Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73c59afc authored by Muli Ben-Yehuda's avatar Muli Ben-Yehuda Committed by Linus Torvalds
Browse files

finish i386 and x86-64 sysdata conversion



This patch finishes the i386 and x86-64 ->sysdata conversion and hopefully
also fixes Riku's and Andy's observed bugs.  It is based on Yinghai Lu's
and Andy Whitcroft's patches (thanks!) with some changes:

- introduce pci_scan_bus_with_sysdata() and use it instead of
  pci_scan_bus() where appropriate. pci_scan_bus_with_sysdata() will
  allocate the sysdata structure and then call pci_scan_bus().
- always allocate pci_sysdata dynamically. The whole point of this
  sysdata work is to make it easy to do root-bus specific things
  (e.g., support PCI domains and IOMMU's). I dislike using a default
  struct pci_sysdata in some places and a dynamically allocated
  pci_sysdata elsewhere - the potential for someone indavertantly
  changing the default structure is too high.
- this patch only makes the minimal changes necessary, i.e., the NUMA node is
  always initialized to -1. Patches to do the right thing with regards
  to the NUMA node can build on top of this (either add a 'node'
  parameter to pci_scan_bus_with_sysdata() or just update the node
  when it becomes known).

The patch was compile tested with various configurations (e.g., NUMAQ,
VISWS) and run-time tested on i386 and x86-64.  Unfortunately none of my
machines exhibited the bugs so caveat emptor.

Andy, could you please see if this fixes the NUMA issues you've seen?
Riku, does this fix "pci=noacpi" on your laptop?

Signed-off-by: default avatarMuli Ben-Yehuda <muli@il.ibm.com>
Cc: Yinghai Lu <yhlu.kernel@gmail.com>
Cc: Andi Kleen <ak@suse.de>
Cc: Chuck Ebbert <cebbert@redhat.com>
Cc: <riku.seppala@kymp.net>
Cc: Andy Whitcroft <apw@shadowen.org>
Cc: Jeff Garzik <jeff@garzik.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f0b85c0c
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -455,3 +455,26 @@ void pcibios_disable_device (struct pci_dev *dev)
	if (!dev->msi_enabled && pcibios_disable_irq)
		pcibios_disable_irq(dev);
}

struct pci_bus *pci_scan_bus_with_sysdata(int busno)
{
	struct pci_bus *bus = NULL;
	struct pci_sysdata *sd;

	/*
	 * Allocate per-root-bus (not per bus) arch-specific data.
	 * TODO: leak; this memory is never freed.
	 * It's arguable whether it's worth the trouble to care.
	 */
	sd = kzalloc(sizeof(*sd), GFP_KERNEL);
	if (!sd) {
		printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno);
		return NULL;
	}
	sd->node = -1;
	bus = pci_scan_bus(busno, &pci_root_ops, sd);
	if (!bus)
		kfree(sd);

	return bus;
}
+3 −3
Original line number Diff line number Diff line
@@ -25,9 +25,9 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
		pci_read_config_byte(d, reg++, &subb);
		DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
		if (busno)
			pci_scan_bus(busno, &pci_root_ops, NULL);	/* Bus A */
			pci_scan_bus_with_sysdata(busno);	/* Bus A */
		if (suba < subb)
			pci_scan_bus(suba+1, &pci_root_ops, NULL);	/* Bus B */
			pci_scan_bus_with_sysdata(suba+1);	/* Bus B */
	}
	pcibios_last_bus = -1;
}
@@ -42,7 +42,7 @@ static void __devinit pci_fixup_i450gx(struct pci_dev *d)
	u8 busno;
	pci_read_config_byte(d, 0x4a, &busno);
	printk(KERN_INFO "PCI: i440KX/GX host bridge %s: secondary bus %02x\n", pci_name(d), busno);
	pci_scan_bus(busno, &pci_root_ops, NULL);
	pci_scan_bus_with_sysdata(busno);
	pcibios_last_bus = -1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx);
+3 −2
Original line number Diff line number Diff line
@@ -138,8 +138,9 @@ static void __init pirq_peer_trick(void)
	for(i = 1; i < 256; i++) {
		if (!busmap[i] || pci_find_bus(0, i))
			continue;
		if (pci_scan_bus(i, &pci_root_ops, NULL))
			printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i);
		if (pci_scan_bus_with_sysdata(i))
			printk(KERN_INFO "PCI: Discovered primary peer "
			       "bus %02x [IRQ]\n", i);
	}
	pcibios_last_bus = -1;
}
+1 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ static void __devinit pcibios_fixup_peer_bridges(void)
			    l != 0x0000 && l != 0xffff) {
				DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l);
				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
				pci_scan_bus(n, &pci_root_ops, NULL);
				pci_scan_bus_with_sysdata(n);
				break;
			}
		}
+9 −6
Original line number Diff line number Diff line
@@ -96,10 +96,14 @@ static void __devinit pci_fixup_i450nx(struct pci_dev *d)
		pci_read_config_byte(d, reg++, &suba);
		pci_read_config_byte(d, reg++, &subb);
		DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb);
		if (busno)
			pci_scan_bus(QUADLOCAL2BUS(quad,busno), &pci_root_ops, NULL);	/* Bus A */
		if (suba < subb)
			pci_scan_bus(QUADLOCAL2BUS(quad,suba+1), &pci_root_ops, NULL);	/* Bus B */
		if (busno) {
			/* Bus A */
			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, busno));
		}
		if (suba < subb) {
			/* Bus B */
			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, suba+1));
		}
	}
	pcibios_last_bus = -1;
}
@@ -123,8 +127,7 @@ static int __init pci_numa_init(void)
				continue;
			printk("Scanning PCI bus %d for quad %d\n", 
				QUADLOCAL2BUS(quad,0), quad);
			pci_scan_bus(QUADLOCAL2BUS(quad,0), 
				&pci_root_ops, NULL);
			pci_scan_bus_with_sysdata(QUADLOCAL2BUS(quad, 0));
		}
	return 0;
}
Loading