diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-10-14 07:02:40 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-10 10:49:31 -0400 |
commit | de06eeef5809a69ff4daaae2bd63977e5404553d (patch) | |
tree | 2dab4c58d8837c35946e8f94d04d266607c4b1a3 /drivers/edac | |
parent | fd3826549db7f73d22b9c9abb80e01effb95c2ba (diff) |
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: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/i7core_edac.c | 79 |
1 files changed, 40 insertions, 39 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index bb538dfbdc6c..b6fce2e38e3d 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -202,12 +202,14 @@ struct pci_id_descr { | |||
202 | int dev; | 202 | int dev; |
203 | int func; | 203 | int func; |
204 | int dev_id; | 204 | int dev_id; |
205 | int optional; | ||
205 | }; | 206 | }; |
206 | 207 | ||
207 | struct i7core_dev { | 208 | struct i7core_dev { |
208 | struct list_head list; | 209 | struct list_head list; |
209 | u8 socket; | 210 | u8 socket; |
210 | struct pci_dev **pdev; | 211 | struct pci_dev **pdev; |
212 | int n_devs; | ||
211 | struct mem_ctl_info *mci; | 213 | struct mem_ctl_info *mci; |
212 | }; | 214 | }; |
213 | 215 | ||
@@ -259,11 +261,12 @@ static DEFINE_MUTEX(i7core_edac_lock); | |||
259 | .func = (function), \ | 261 | .func = (function), \ |
260 | .dev_id = (device_id) | 262 | .dev_id = (device_id) |
261 | 263 | ||
262 | struct pci_id_descr pci_dev_descr[] = { | 264 | struct pci_id_descr pci_dev_descr_i7core[] = { |
263 | /* Memory controller */ | 265 | /* Memory controller */ |
264 | { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) }, | 266 | { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) }, |
265 | { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) }, | 267 | { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) }, |
266 | { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM */ | 268 | /* Exists only for RDIMM */ |
269 | { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1 }, | ||
267 | { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) }, | 270 | { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) }, |
268 | 271 | ||
269 | /* Channel 0 */ | 272 | /* Channel 0 */ |
@@ -294,7 +297,6 @@ struct pci_id_descr pci_dev_descr[] = { | |||
294 | { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) }, | 297 | { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) }, |
295 | 298 | ||
296 | }; | 299 | }; |
297 | #define N_DEVS ARRAY_SIZE(pci_dev_descr) | ||
298 | 300 | ||
299 | /* | 301 | /* |
300 | * pci_device_id table for which devices we are looking for | 302 | * 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 | if (!i7core_dev) | 382 | if (!i7core_dev) |
381 | return NULL; | 383 | return NULL; |
382 | 384 | ||
383 | for (i = 0; i < N_DEVS; i++) { | 385 | for (i = 0; i < i7core_dev->n_devs; i++) { |
384 | if (!i7core_dev->pdev[i]) | 386 | if (!i7core_dev->pdev[i]) |
385 | continue; | 387 | continue; |
386 | 388 | ||
@@ -1116,7 +1118,7 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev) | |||
1116 | int i; | 1118 | int i; |
1117 | 1119 | ||
1118 | debugf0(__FILE__ ": %s()\n", __func__); | 1120 | debugf0(__FILE__ ": %s()\n", __func__); |
1119 | for (i = 0; i < N_DEVS; i++) { | 1121 | for (i = 0; i < i7core_dev->n_devs; i++) { |
1120 | struct pci_dev *pdev = i7core_dev->pdev[i]; | 1122 | struct pci_dev *pdev = i7core_dev->pdev[i]; |
1121 | if (!pdev) | 1123 | if (!pdev) |
1122 | continue; | 1124 | continue; |
@@ -1138,7 +1140,7 @@ static void i7core_put_all_devices(void) | |||
1138 | i7core_put_devices(i7core_dev); | 1140 | i7core_put_devices(i7core_dev); |
1139 | } | 1141 | } |
1140 | 1142 | ||
1141 | static void i7core_xeon_pci_fixup(void) | 1143 | static void i7core_xeon_pci_fixup(int dev_id) |
1142 | { | 1144 | { |
1143 | struct pci_dev *pdev = NULL; | 1145 | struct pci_dev *pdev = NULL; |
1144 | int i; | 1146 | int i; |
@@ -1147,8 +1149,7 @@ static void i7core_xeon_pci_fixup(void) | |||
1147 | * aren't announced by acpi. So, we need to use a legacy scan probing | 1149 | * aren't announced by acpi. So, we need to use a legacy scan probing |
1148 | * to detect them | 1150 | * to detect them |
1149 | */ | 1151 | */ |
1150 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1152 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); |
1151 | pci_dev_descr[0].dev_id, NULL); | ||
1152 | if (unlikely(!pdev)) { | 1153 | if (unlikely(!pdev)) { |
1153 | for (i = 0; i < MAX_SOCKET_BUSES; i++) | 1154 | for (i = 0; i < MAX_SOCKET_BUSES; i++) |
1154 | pcibios_scan_specific_bus(255-i); | 1155 | pcibios_scan_specific_bus(255-i); |
@@ -1161,7 +1162,8 @@ static void i7core_xeon_pci_fixup(void) | |||
1161 | * | 1162 | * |
1162 | * Need to 'get' device 16 func 1 and func 2 | 1163 | * Need to 'get' device 16 func 1 and func 2 |
1163 | */ | 1164 | */ |
1164 | int i7core_get_onedevice(struct pci_dev **prev, int devno) | 1165 | int i7core_get_onedevice(struct pci_dev **prev, int devno, |
1166 | struct pci_id_descr *dev_descr, unsigned n_devs) | ||
1165 | { | 1167 | { |
1166 | struct i7core_dev *i7core_dev; | 1168 | struct i7core_dev *i7core_dev; |
1167 | 1169 | ||
@@ -1170,14 +1172,14 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) | |||
1170 | u8 socket = 0; | 1172 | u8 socket = 0; |
1171 | 1173 | ||
1172 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1174 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1173 | pci_dev_descr[devno].dev_id, *prev); | 1175 | dev_descr->dev_id, *prev); |
1174 | 1176 | ||
1175 | /* | 1177 | /* |
1176 | * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs | 1178 | * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs |
1177 | * is at addr 8086:2c40, instead of 8086:2c41. So, we need | 1179 | * is at addr 8086:2c40, instead of 8086:2c41. So, we need |
1178 | * to probe for the alternate address in case of failure | 1180 | * to probe for the alternate address in case of failure |
1179 | */ | 1181 | */ |
1180 | if (pci_dev_descr[devno].dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) | 1182 | if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) |
1181 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 1183 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
1182 | PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); | 1184 | PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); |
1183 | 1185 | ||
@@ -1187,19 +1189,13 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) | |||
1187 | return 0; | 1189 | return 0; |
1188 | } | 1190 | } |
1189 | 1191 | ||
1190 | /* | 1192 | if (dev_descr->optional) |
1191 | * Dev 3 function 2 only exists on chips with RDIMMs | ||
1192 | * so, it is ok to not found it | ||
1193 | */ | ||
1194 | if ((pci_dev_descr[devno].dev == 3) && (pci_dev_descr[devno].func == 2)) { | ||
1195 | *prev = pdev; | ||
1196 | return 0; | 1193 | return 0; |
1197 | } | ||
1198 | 1194 | ||
1199 | i7core_printk(KERN_ERR, | 1195 | i7core_printk(KERN_ERR, |
1200 | "Device not found: dev %02x.%d PCI ID %04x:%04x\n", | 1196 | "Device not found: dev %02x.%d PCI ID %04x:%04x\n", |
1201 | pci_dev_descr[devno].dev, pci_dev_descr[devno].func, | 1197 | dev_descr->dev, dev_descr->func, |
1202 | PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); | 1198 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1203 | 1199 | ||
1204 | /* End of list, leave */ | 1200 | /* End of list, leave */ |
1205 | return -ENODEV; | 1201 | return -ENODEV; |
@@ -1216,11 +1212,12 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) | |||
1216 | i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL); | 1212 | i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL); |
1217 | if (!i7core_dev) | 1213 | if (!i7core_dev) |
1218 | return -ENOMEM; | 1214 | return -ENOMEM; |
1219 | i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * N_DEVS, | 1215 | i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs, |
1220 | GFP_KERNEL); | 1216 | GFP_KERNEL); |
1221 | if (!i7core_dev->pdev) | 1217 | if (!i7core_dev->pdev) |
1222 | return -ENOMEM; | 1218 | return -ENOMEM; |
1223 | i7core_dev->socket = socket; | 1219 | i7core_dev->socket = socket; |
1220 | i7core_dev->n_devs = n_devs; | ||
1224 | list_add_tail(&i7core_dev->list, &i7core_edac_list); | 1221 | list_add_tail(&i7core_dev->list, &i7core_edac_list); |
1225 | } | 1222 | } |
1226 | 1223 | ||
@@ -1228,8 +1225,8 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) | |||
1228 | i7core_printk(KERN_ERR, | 1225 | i7core_printk(KERN_ERR, |
1229 | "Duplicated device for " | 1226 | "Duplicated device for " |
1230 | "dev %02x:%02x.%d PCI ID %04x:%04x\n", | 1227 | "dev %02x:%02x.%d PCI ID %04x:%04x\n", |
1231 | bus, pci_dev_descr[devno].dev, pci_dev_descr[devno].func, | 1228 | bus, dev_descr->dev, dev_descr->func, |
1232 | PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); | 1229 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1233 | pci_dev_put(pdev); | 1230 | pci_dev_put(pdev); |
1234 | return -ENODEV; | 1231 | return -ENODEV; |
1235 | } | 1232 | } |
@@ -1237,14 +1234,14 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) | |||
1237 | i7core_dev->pdev[devno] = pdev; | 1234 | i7core_dev->pdev[devno] = pdev; |
1238 | 1235 | ||
1239 | /* Sanity check */ | 1236 | /* Sanity check */ |
1240 | if (unlikely(PCI_SLOT(pdev->devfn) != pci_dev_descr[devno].dev || | 1237 | if (unlikely(PCI_SLOT(pdev->devfn) != dev_descr->dev || |
1241 | PCI_FUNC(pdev->devfn) != pci_dev_descr[devno].func)) { | 1238 | PCI_FUNC(pdev->devfn) != dev_descr->func)) { |
1242 | i7core_printk(KERN_ERR, | 1239 | i7core_printk(KERN_ERR, |
1243 | "Device PCI ID %04x:%04x " | 1240 | "Device PCI ID %04x:%04x " |
1244 | "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n", | 1241 | "has dev %02x:%02x.%d instead of dev %02x:%02x.%d\n", |
1245 | PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id, | 1242 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id, |
1246 | bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), | 1243 | bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), |
1247 | bus, pci_dev_descr[devno].dev, pci_dev_descr[devno].func); | 1244 | bus, dev_descr->dev, dev_descr->func); |
1248 | return -ENODEV; | 1245 | return -ENODEV; |
1249 | } | 1246 | } |
1250 | 1247 | ||
@@ -1253,30 +1250,32 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) | |||
1253 | i7core_printk(KERN_ERR, | 1250 | i7core_printk(KERN_ERR, |
1254 | "Couldn't enable " | 1251 | "Couldn't enable " |
1255 | "dev %02x:%02x.%d PCI ID %04x:%04x\n", | 1252 | "dev %02x:%02x.%d PCI ID %04x:%04x\n", |
1256 | bus, pci_dev_descr[devno].dev, pci_dev_descr[devno].func, | 1253 | bus, dev_descr->dev, dev_descr->func, |
1257 | PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); | 1254 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1258 | return -ENODEV; | 1255 | return -ENODEV; |
1259 | } | 1256 | } |
1260 | 1257 | ||
1261 | debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", | 1258 | debugf0("Detected socket %d dev %02x:%02x.%d PCI ID %04x:%04x\n", |
1262 | socket, bus, pci_dev_descr[devno].dev, | 1259 | socket, bus, dev_descr->dev, |
1263 | pci_dev_descr[devno].func, | 1260 | dev_descr->func, |
1264 | PCI_VENDOR_ID_INTEL, pci_dev_descr[devno].dev_id); | 1261 | PCI_VENDOR_ID_INTEL, dev_descr->dev_id); |
1265 | 1262 | ||
1266 | *prev = pdev; | 1263 | *prev = pdev; |
1267 | 1264 | ||
1268 | return 0; | 1265 | return 0; |
1269 | } | 1266 | } |
1270 | 1267 | ||
1271 | static int i7core_get_devices(void) | 1268 | static int i7core_get_devices(struct pci_id_descr dev_descr[], unsigned n_devs) |
1272 | { | 1269 | { |
1273 | int i; | 1270 | int i, rc; |
1274 | struct pci_dev *pdev = NULL; | 1271 | struct pci_dev *pdev = NULL; |
1275 | 1272 | ||
1276 | for (i = 0; i < N_DEVS; i++) { | 1273 | for (i = 0; i < n_devs; i++) { |
1277 | pdev = NULL; | 1274 | pdev = NULL; |
1278 | do { | 1275 | do { |
1279 | if (i7core_get_onedevice(&pdev, i) < 0) { | 1276 | rc = i7core_get_onedevice(&pdev, i, &dev_descr[i], |
1277 | n_devs); | ||
1278 | if (rc < 0) { | ||
1280 | i7core_put_all_devices(); | 1279 | i7core_put_all_devices(); |
1281 | return -ENODEV; | 1280 | return -ENODEV; |
1282 | } | 1281 | } |
@@ -1298,7 +1297,7 @@ static int mci_bind_devs(struct mem_ctl_info *mci, | |||
1298 | i7core_dev->mci = mci; | 1297 | i7core_dev->mci = mci; |
1299 | 1298 | ||
1300 | pvt->is_registered = 0; | 1299 | pvt->is_registered = 0; |
1301 | for (i = 0; i < N_DEVS; i++) { | 1300 | for (i = 0; i < i7core_dev->n_devs; i++) { |
1302 | pdev = i7core_dev->pdev[i]; | 1301 | pdev = i7core_dev->pdev[i]; |
1303 | if (!pdev) | 1302 | if (!pdev) |
1304 | continue; | 1303 | continue; |
@@ -1838,7 +1837,9 @@ static int __devinit i7core_probe(struct pci_dev *pdev, | |||
1838 | 1837 | ||
1839 | /* get the pci devices we want to reserve for our use */ | 1838 | /* get the pci devices we want to reserve for our use */ |
1840 | mutex_lock(&i7core_edac_lock); | 1839 | mutex_lock(&i7core_edac_lock); |
1841 | rc = i7core_get_devices(); | 1840 | |
1841 | rc = i7core_get_devices(pci_dev_descr_i7core, | ||
1842 | ARRAY_SIZE(pci_dev_descr_i7core)); | ||
1842 | if (unlikely(rc < 0)) | 1843 | if (unlikely(rc < 0)) |
1843 | goto fail0; | 1844 | goto fail0; |
1844 | 1845 | ||
@@ -1937,7 +1938,7 @@ static int __init i7core_init(void) | |||
1937 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ | 1938 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ |
1938 | opstate_init(); | 1939 | opstate_init(); |
1939 | 1940 | ||
1940 | i7core_xeon_pci_fixup(); | 1941 | i7core_xeon_pci_fixup(pci_dev_descr_i7core[0].dev_id); |
1941 | 1942 | ||
1942 | pci_rc = pci_register_driver(&i7core_driver); | 1943 | pci_rc = pci_register_driver(&i7core_driver); |
1943 | 1944 | ||