i7core: fix get_devices routine for Xeon55xx
i7core_get_devices() were preparet to get just the first found device of each type.
Due to that, on Xeon 55xx, only socket 1 were retrived.
Rework i7core_get_devices() to clean it and to properly support Xeon 55xx.
While here, fix a small typo.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 9f39d3d..79636b5 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -410,7 +410,7 @@
}
}
- debugf0("Number of active channels on socked %d: %d\n",
+ debugf0("Number of active channels on socket %d: %d\n",
socket, *channels);
return 0;
@@ -1126,107 +1126,137 @@
*
* Need to 'get' device 16 func 1 and func 2
*/
-static int i7core_get_devices(void)
+int i7core_get_onedevice(struct pci_dev **prev, int devno)
{
- int rc, i;
struct pci_dev *pdev = NULL;
u8 bus = 0;
u8 socket = 0;
- for (i = 0; i < N_DEVS; i++) {
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ pci_devs[devno].dev_id, *prev);
+
+ /*
+ * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
+ * aren't announced by acpi. So, we need to use a legacy scan probing
+ * to detect them
+ */
+ if (unlikely(!pdev && !devno && !prev)) {
+ pcibios_scan_specific_bus(254);
+ pcibios_scan_specific_bus(255);
+
pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
- pci_devs[i].dev_id, NULL);
+ pci_devs[devno].dev_id, *prev);
+ }
- if (!pdev && !i) {
- pcibios_scan_specific_bus(254);
- pcibios_scan_specific_bus(255);
+ /*
+ * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
+ * is at addr 8086:2c40, instead of 8086:2c41. So, we need
+ * to probe for the alternate address in case of failure
+ */
+ if (pci_devs[devno].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE && !pdev)
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
+ PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, *prev);
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
- pci_devs[i].dev_id, NULL);
+ if (!pdev) {
+ if (*prev) {
+ *prev = pdev;
+ return 0;
}
/*
- * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
- * is at addr 8086:2c40, instead of 8086:2c41. So, we need
- * to probe for the alternate address in case of failure
+ * Dev 3 function 2 only exists on chips with RDIMMs
+ * so, it is ok to not found it
*/
- if (pci_devs[i].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE
- && !pdev)
- pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, NULL);
-
- if (likely(pdev)) {
- bus = pdev->bus->number;
-
- if (bus == 0x3f)
- socket = 0;
- else
- socket = 255 - bus;
-
- if (socket >= NUM_SOCKETS) {
- i7core_printk(KERN_ERR,
- "Found unexpected socket for "
- "dev %02x:%02x.%d PCI ID %04x:%04x\n",
- bus, pci_devs[i].dev, pci_devs[i].func,
- PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
-
- rc = -ENODEV;
- goto error;
- }
-
- pci_devs[i].pdev[socket] = pdev;
- } else {
- i7core_printk(KERN_ERR,
- "Device not found: "
- "dev %02x:%02x.%d PCI ID %04x:%04x\n",
- bus, pci_devs[i].dev, pci_devs[i].func,
- PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
-
- /* Dev 3 function 2 only exists on chips with RDIMMs */
- if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
- continue;
-
- /* End of list, leave */
- rc = -ENODEV;
- goto error;
+ if ((pci_devs[devno].dev == 3) && (pci_devs[devno].func == 2)) {
+ *prev = pdev;
+ return 0;
}
- /* Sanity check */
- if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[i].dev ||
- PCI_FUNC(pdev->devfn) != pci_devs[i].func)) {
- i7core_printk(KERN_ERR,
- "Device PCI ID %04x:%04x "
- "has fn %d.%d instead of fn %d.%d\n",
- PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
- pci_devs[i].dev, pci_devs[i].func);
- rc = -EINVAL;
- goto error;
- }
+ i7core_printk(KERN_ERR,
+ "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
+ pci_devs[devno].dev, pci_devs[devno].func,
+ PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
- /* Be sure that the device is enabled */
- rc = pci_enable_device(pdev);
- if (unlikely(rc < 0)) {
- i7core_printk(KERN_ERR,
- "Couldn't enable PCI ID %04x:%04x "
- "fn %d.%d\n",
- PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
- goto error;
- }
+ /* End of list, leave */
+ return -ENODEV;
+ }
+ bus = pdev->bus->number;
- i7core_printk(KERN_INFO,
- "Registered socket %d "
- "dev %02x:%02x.%d PCI ID %04x:%04x\n",
- socket, bus, pci_devs[i].dev, pci_devs[i].func,
- PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id);
+ if (bus == 0x3f)
+ socket = 0;
+ else
+ socket = 255 - bus;
+
+ if (socket >= NUM_SOCKETS) {
+ i7core_printk(KERN_ERR,
+ "Unexpected socket for "
+ "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ bus, pci_devs[devno].dev, pci_devs[devno].func,
+ PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+ pci_dev_put(pdev);
+ return -ENODEV;
}
- return 0;
+ if (pci_devs[devno].pdev[socket]) {
+ i7core_printk(KERN_ERR,
+ "Duplicated device for "
+ "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ bus, pci_devs[devno].dev, pci_devs[devno].func,
+ PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+ pci_dev_put(pdev);
+ return -ENODEV;
+ }
-error:
- i7core_put_devices();
- return -EINVAL;
+ pci_devs[devno].pdev[socket] = pdev;
+
+ /* Sanity check */
+ if (unlikely(PCI_SLOT(pdev->devfn) != pci_devs[devno].dev ||
+ PCI_FUNC(pdev->devfn) != pci_devs[devno].func)) {
+ i7core_printk(KERN_ERR,
+ "Device PCI ID %04x:%04x "
+ "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n",
+ PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id,
+ bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
+ bus, pci_devs[devno].dev, pci_devs[devno].func);
+ return -ENODEV;
+ }
+
+ /* Be sure that the device is enabled */
+ if (unlikely(pci_enable_device(pdev) < 0)) {
+ i7core_printk(KERN_ERR,
+ "Couldn't enable "
+ "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ bus, pci_devs[devno].dev, pci_devs[devno].func,
+ PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+ return -ENODEV;
+ }
+
+ i7core_printk(KERN_INFO,
+ "Registered socket %d "
+ "dev %02x:%02x.%d PCI ID %04x:%04x\n",
+ socket, bus, pci_devs[devno].dev, pci_devs[devno].func,
+ PCI_VENDOR_ID_INTEL, pci_devs[devno].dev_id);
+
+ *prev = pdev;
+
+ return 0;
+}
+
+static int i7core_get_devices(void)
+{
+ int i;
+ struct pci_dev *pdev = NULL;
+
+ for (i = 0; i < N_DEVS; i++) {
+ pdev = NULL;
+ do {
+ if (i7core_get_onedevice(&pdev, i) < 0) {
+ i7core_put_devices();
+ return -ENODEV;
+ }
+ } while (pdev);
+ }
+ return 0;
}
static int mci_bind_devs(struct mem_ctl_info *mci)