提交 de06eeef 编写于 作者: M Mauro Carvalho Chehab

i7core_edac: Use a more generic approach for probing PCI devices

Currently, only one PCI set of tables is allowed. This prevents using
the driver for other devices like Lynnfield, with have a different
set of PCI ID's.
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 fd382654
...@@ -202,12 +202,14 @@ struct pci_id_descr { ...@@ -202,12 +202,14 @@ struct pci_id_descr {
int dev; int dev;
int func; int func;
int dev_id; int dev_id;
int optional;
}; };
struct i7core_dev { struct i7core_dev {
struct list_head list; struct list_head list;
u8 socket; u8 socket;
struct pci_dev **pdev; struct pci_dev **pdev;
int n_devs;
struct mem_ctl_info *mci; struct mem_ctl_info *mci;
}; };
...@@ -259,11 +261,12 @@ static DEFINE_MUTEX(i7core_edac_lock); ...@@ -259,11 +261,12 @@ static DEFINE_MUTEX(i7core_edac_lock);
.func = (function), \ .func = (function), \
.dev_id = (device_id) .dev_id = (device_id)
struct pci_id_descr pci_dev_descr[] = { struct pci_id_descr pci_dev_descr_i7core[] = {
/* Memory controller */ /* Memory controller */
{ PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) }, { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
{ PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) }, { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
{ PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM */ /* Exists only for RDIMM */
{ PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1 },
{ PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) }, { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
/* Channel 0 */ /* Channel 0 */
...@@ -294,7 +297,6 @@ struct pci_id_descr pci_dev_descr[] = { ...@@ -294,7 +297,6 @@ struct pci_id_descr pci_dev_descr[] = {
{ PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) }, { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) },
}; };
#define N_DEVS ARRAY_SIZE(pci_dev_descr)
/* /*
* pci_device_id table for which devices we are looking for * pci_device_id table for which devices we are looking for
...@@ -380,7 +382,7 @@ static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot, ...@@ -380,7 +382,7 @@ static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
if (!i7core_dev) if (!i7core_dev)
return NULL; return NULL;
for (i = 0; i < N_DEVS; i++) { for (i = 0; i < i7core_dev->n_devs; i++) {
if (!i7core_dev->pdev[i]) if (!i7core_dev->pdev[i])
continue; continue;
...@@ -1116,7 +1118,7 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev) ...@@ -1116,7 +1118,7 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev)
int i; int i;
debugf0(__FILE__ ": %s()\n", __func__); debugf0(__FILE__ ": %s()\n", __func__);
for (i = 0; i < N_DEVS; i++) { for (i = 0; i < i7core_dev->n_devs; i++) {
struct pci_dev *pdev = i7core_dev->pdev[i]; struct pci_dev *pdev = i7core_dev->pdev[i];
if (!pdev) if (!pdev)
continue; continue;
...@@ -1138,7 +1140,7 @@ static void i7core_put_all_devices(void) ...@@ -1138,7 +1140,7 @@ static void i7core_put_all_devices(void)
i7core_put_devices(i7core_dev); i7core_put_devices(i7core_dev);
} }
static void i7core_xeon_pci_fixup(void) static void i7core_xeon_pci_fixup(int dev_id)
{ {
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
int i; int i;
...@@ -1147,8 +1149,7 @@ static void i7core_xeon_pci_fixup(void) ...@@ -1147,8 +1149,7 @@ static void i7core_xeon_pci_fixup(void)
* aren't announced by acpi. So, we need to use a legacy scan probing * aren't announced by acpi. So, we need to use a legacy scan probing
* to detect them * to detect them
*/ */
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, pdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL);
pci_dev_descr[0].dev_id, NULL);
if (unlikely(!pdev)) { if (unlikely(!pdev)) {
for (i = 0; i < MAX_SOCKET_BUSES; i++) for (i = 0; i < MAX_SOCKET_BUSES; i++)
pcibios_scan_specific_bus(255-i); pcibios_scan_specific_bus(255-i);
...@@ -1161,7 +1162,8 @@ static void i7core_xeon_pci_fixup(void) ...@@ -1161,7 +1162,8 @@ static void i7core_xeon_pci_fixup(void)
* *
* Need to 'get' device 16 func 1 and func 2 * Need to 'get' device 16 func 1 and func 2
*/ */
int i7core_get_onedevice(struct pci_dev **prev, int devno) int i7core_get_onedevice(struct pci_dev **prev, int devno,
struct pci_id_descr *dev_descr, unsigned n_devs)
{ {
struct i7core_dev *i7core_dev; struct i7core_dev *i7core_dev;
...@@ -1170,14 +1172,14 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) ...@@ -1170,14 +1172,14 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
u8 socket = 0; u8 socket = 0;
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
pci_dev_descr[devno].dev_id, *prev); dev_descr->dev_id, *prev);
/* /*
* On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
* is at addr 8086:2c40, instead of 8086:2c41. So, we need * is at addr 8086:2c40, instead of 8086:2c41. So, we need
* to probe for the alternate address in case of failure * to probe for the alternate address in case of failure
*/ */
if (pci_dev_descr[devno].dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
pdev = pci_get_device(PCI_VENDOR_ID_INTEL, pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
...@@ -1187,19 +1189,13 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) ...@@ -1187,19 +1189,13 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
return 0; return 0;
} }
/* if (dev_descr->optional)
* Dev 3 function 2 only exists on chips with RDIMMs
* so, it is ok to not found it
*/
if ((pci_dev_descr[devno].dev == 3) && (pci_dev_descr[devno].func == 2)) {
*prev = pdev;
return 0; return 0;
}
i7core_printk(KERN_ERR, i7core_printk(KERN_ERR,
"Device not found: dev %02x.%d PCI ID %04x:%04x\n", "Device not found: dev %02x.%d PCI ID %04x:%04x\n",
pci_dev_descr[devno].dev, pci_dev_descr[devno].func, dev_descr->dev, dev_descr->func,
PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
/* End of list, leave */ /* End of list, leave */
return -ENODEV; return -ENODEV;
...@@ -1216,11 +1212,12 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) ...@@ -1216,11 +1212,12 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL); i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
if (!i7core_dev) if (!i7core_dev)
return -ENOMEM; return -ENOMEM;
i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * N_DEVS, i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs,
GFP_KERNEL); GFP_KERNEL);
if (!i7core_dev->pdev) if (!i7core_dev->pdev)
return -ENOMEM; return -ENOMEM;
i7core_dev->socket = socket; i7core_dev->socket = socket;
i7core_dev->n_devs = n_devs;
list_add_tail(&i7core_dev->list, &i7core_edac_list); list_add_tail(&i7core_dev->list, &i7core_edac_list);
} }
...@@ -1228,8 +1225,8 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) ...@@ -1228,8 +1225,8 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
i7core_printk(KERN_ERR, i7core_printk(KERN_ERR,
"Duplicated device for " "Duplicated device for "
"dev %02x:%02x.%d PCI ID %04x:%04x\n", "dev %02x:%02x.%d PCI ID %04x:%04x\n",
bus, pci_dev_descr[devno].dev, pci_dev_descr[devno].func, bus, dev_descr->dev, dev_descr->func,
PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
pci_dev_put(pdev); pci_dev_put(pdev);
return -ENODEV; return -ENODEV;
} }
...@@ -1237,14 +1234,14 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) ...@@ -1237,14 +1234,14 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
i7core_dev->pdev[devno] = pdev; i7core_dev->pdev[devno] = pdev;
/* Sanity check */ /* Sanity check */
if (unlikely(PCI_SLOT(pdev->devfn) != pci_dev_descr[devno].dev || if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev ||
PCI_FUNC(pdev->devfn) != pci_dev_descr[devno].func)) { PCI_FUNC(pdev->devfn) != dev_descr->func)) {
i7core_printk(KERN_ERR, i7core_printk(KERN_ERR,
"Device PCI ID %04x:%04x " "Device PCI ID %04x:%04x "
"has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n", "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n",
PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id, PCI_VENDOR_ID_INTEL, dev_descr->dev_id,
bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
bus, pci_dev_descr[devno].dev, pci_dev_descr[devno].func); bus, dev_descr->dev, dev_descr->func);
return -ENODEV; return -ENODEV;
} }
...@@ -1253,30 +1250,32 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) ...@@ -1253,30 +1250,32 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno)
i7core_printk(KERN_ERR, i7core_printk(KERN_ERR,
"Couldn't enable " "Couldn't enable "
"dev %02x:%02x.%d PCI ID %04x:%04x\n", "dev %02x:%02x.%d PCI ID %04x:%04x\n",
bus, pci_dev_descr[devno].dev, pci_dev_descr[devno].func, bus, dev_descr->dev, dev_descr->func,
PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
return -ENODEV; return -ENODEV;
} }
debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n",
socket, bus, pci_dev_descr[devno].dev, socket, bus, dev_descr->dev,
pci_dev_descr[devno].func, dev_descr->func,
PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
*prev = pdev; *prev = pdev;
return 0; return 0;
} }
static int i7core_get_devices(void) static int i7core_get_devices(struct pci_id_descr dev_descr[], unsigned n_devs)
{ {
int i; int i, rc;
struct pci_dev *pdev = NULL; struct pci_dev *pdev = NULL;
for (i = 0; i < N_DEVS; i++) { for (i = 0; i < n_devs; i++) {
pdev = NULL; pdev = NULL;
do { do {
if (i7core_get_onedevice(&pdev, i) < 0) { rc = i7core_get_onedevice(&pdev, i, &dev_descr[i],
n_devs);
if (rc < 0) {
i7core_put_all_devices(); i7core_put_all_devices();
return -ENODEV; return -ENODEV;
} }
...@@ -1298,7 +1297,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci, ...@@ -1298,7 +1297,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
i7core_dev->mci = mci; i7core_dev->mci = mci;
pvt->is_registered = 0; pvt->is_registered = 0;
for (i = 0; i < N_DEVS; i++) { for (i = 0; i < i7core_dev->n_devs; i++) {
pdev = i7core_dev->pdev[i]; pdev = i7core_dev->pdev[i];
if (!pdev) if (!pdev)
continue; continue;
...@@ -1838,7 +1837,9 @@ static int __devinit i7core_probe(struct pci_dev *pdev, ...@@ -1838,7 +1837,9 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
/* get the pci devices we want to reserve for our use */ /* get the pci devices we want to reserve for our use */
mutex_lock(&i7core_edac_lock); mutex_lock(&i7core_edac_lock);
rc = i7core_get_devices();
rc = i7core_get_devices(pci_dev_descr_i7core,
ARRAY_SIZE(pci_dev_descr_i7core));
if (unlikely(rc < 0)) if (unlikely(rc < 0))
goto fail0; goto fail0;
...@@ -1937,7 +1938,7 @@ static int __init i7core_init(void) ...@@ -1937,7 +1938,7 @@ static int __init i7core_init(void)
/* Ensure that the OPSTATE is set correctly for POLL or NMI */ /* Ensure that the OPSTATE is set correctly for POLL or NMI */
opstate_init(); opstate_init();
i7core_xeon_pci_fixup(); i7core_xeon_pci_fixup(pci_dev_descr_i7core[0].dev_id);
pci_rc = pci_register_driver(&i7core_driver); pci_rc = pci_register_driver(&i7core_driver);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册