[SPARC64]: Restrict PCI bus scanning on SUN4V.
On the PBM's first bus number, only allow device 0, function 0, to be
poked at with PCI config space accesses.
For some reason, this single device responds to all device numbers.
Also, reduce the verbiage of the debugging log printk's for PCI cfg
space accesses in the SUN4V PCI controller driver, so that it doesn't
overwhelm the slow SUN4V hypervisor console.
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index ac311d3..ea51ade4 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -517,8 +517,14 @@
/* SUN4V PCI configuration space accessors. */
-static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus)
+static inline int pci_sun4v_out_of_range(struct pci_pbm_info *pbm, unsigned int bus, unsigned int device, unsigned int func)
{
+ if (bus == pbm->pci_first_busno) {
+ if (device == 0 && func == 0)
+ return 0;
+ return 1;
+ }
+
if (bus < pbm->pci_first_busno ||
bus > pbm->pci_last_busno)
return 1;
@@ -535,15 +541,14 @@
unsigned int func = PCI_FUNC(devfn);
unsigned long ret;
- if (pci_sun4v_out_of_range(pbm, bus)) {
+ if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
ret = ~0UL;
} else {
ret = pci_sun4v_config_get(devhandle,
HV_PCI_DEVICE_BUILD(bus, device, func),
where, size);
#if 0
- printk("read_pci_cfg: devh[%x] device[%08x] where[%x] sz[%d] "
- "== [%016lx]\n",
+ printk("rcfg: [%x:%x:%x:%d]=[%lx]\n",
devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
where, size, ret);
#endif
@@ -574,15 +579,14 @@
unsigned int func = PCI_FUNC(devfn);
unsigned long ret;
- if (pci_sun4v_out_of_range(pbm, bus)) {
+ if (pci_sun4v_out_of_range(pbm, bus, device, func)) {
/* Do nothing. */
} else {
ret = pci_sun4v_config_put(devhandle,
HV_PCI_DEVICE_BUILD(bus, device, func),
where, size, value);
#if 0
- printk("write_pci_cfg: devh[%x] device[%08x] where[%x] sz[%d] "
- "val[%08x] == [%016lx]\n",
+ printk("wcfg: [%x:%x:%x:%d] v[%x] == [%lx]\n",
devhandle, HV_PCI_DEVICE_BUILD(bus, device, func),
where, size, value, ret);
#endif
@@ -610,16 +614,13 @@
memset(cookie, 0, sizeof(*cookie));
cookie->pbm = pbm;
- pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
- p->pci_ops,
- pbm);
+ pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno, p->pci_ops, pbm);
#if 0
pci_fixup_host_bridge_self(pbm->pci_bus);
pbm->pci_bus->self->sysdata = cookie;
#endif
-
pci_fill_in_pbm_cookies(pbm->pci_bus, pbm,
- prom_getchild(pbm->prom_node));
+ pbm->prom_node);
pci_record_assignments(pbm, pbm->pci_bus);
pci_assign_unassigned(pbm, pbm->pci_bus);
pci_fixup_irq(pbm, pbm->pci_bus);
@@ -884,19 +885,12 @@
probe_existing_entries(pbm, iommu);
}
-/* Don't get this from the root nexus, get it from the "pci@0" node below. */
static void pci_sun4v_get_bus_range(struct pci_pbm_info *pbm)
{
unsigned int busrange[2];
int prom_node = pbm->prom_node;
int err;
- prom_node = prom_getchild(prom_node);
- if (prom_node == 0) {
- prom_printf("%s: Fatal error, no child OBP node.\n", pbm->name);
- prom_halt();
- }
-
err = prom_getproperty(prom_node, "bus-range",
(char *)&busrange[0],
sizeof(busrange));
@@ -929,7 +923,9 @@
sprintf(pbm->name, "SUN4V-PCI%d PBM%c",
p->index, (pbm == &p->pbm_A ? 'A' : 'B'));
- printk("%s: devhandle[%x]\n", pbm->name, pbm->devhandle);
+ printk("%s: devhandle[%x] prom_node[%x:%x]\n",
+ pbm->name, pbm->devhandle,
+ pbm->prom_node, prom_getchild(pbm->prom_node));
prom_getstring(prom_node, "name",
pbm->prom_name, sizeof(pbm->prom_name));