diff options
Diffstat (limited to 'drivers/edac/e7xxx_edac.c')
-rw-r--r-- | drivers/edac/e7xxx_edac.c | 132 |
1 files changed, 59 insertions, 73 deletions
diff --git a/drivers/edac/e7xxx_edac.c b/drivers/edac/e7xxx_edac.c index 5202bbf2e0cd..2b20610991c0 100644 --- a/drivers/edac/e7xxx_edac.c +++ b/drivers/edac/e7xxx_edac.c | |||
@@ -146,21 +146,17 @@ struct e7xxx_error_info { | |||
146 | 146 | ||
147 | static const struct e7xxx_dev_info e7xxx_devs[] = { | 147 | static const struct e7xxx_dev_info e7xxx_devs[] = { |
148 | [E7500] = { | 148 | [E7500] = { |
149 | .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, | 149 | .err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR, |
150 | .ctl_name = "E7500" | 150 | .ctl_name = "E7500"}, |
151 | }, | ||
152 | [E7501] = { | 151 | [E7501] = { |
153 | .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, | 152 | .err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR, |
154 | .ctl_name = "E7501" | 153 | .ctl_name = "E7501"}, |
155 | }, | ||
156 | [E7505] = { | 154 | [E7505] = { |
157 | .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, | 155 | .err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR, |
158 | .ctl_name = "E7505" | 156 | .ctl_name = "E7505"}, |
159 | }, | ||
160 | [E7205] = { | 157 | [E7205] = { |
161 | .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, | 158 | .err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR, |
162 | .ctl_name = "E7205" | 159 | .ctl_name = "E7205"}, |
163 | }, | ||
164 | }; | 160 | }; |
165 | 161 | ||
166 | /* FIXME - is this valid for both SECDED and S4ECD4ED? */ | 162 | /* FIXME - is this valid for both SECDED and S4ECD4ED? */ |
@@ -181,15 +177,15 @@ static inline int e7xxx_find_channel(u16 syndrome) | |||
181 | } | 177 | } |
182 | 178 | ||
183 | static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, | 179 | static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, |
184 | unsigned long page) | 180 | unsigned long page) |
185 | { | 181 | { |
186 | u32 remap; | 182 | u32 remap; |
187 | struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info; | 183 | struct e7xxx_pvt *pvt = (struct e7xxx_pvt *)mci->pvt_info; |
188 | 184 | ||
189 | debugf3("%s()\n", __func__); | 185 | debugf3("%s()\n", __func__); |
190 | 186 | ||
191 | if ((page < pvt->tolm) || | 187 | if ((page < pvt->tolm) || |
192 | ((page >= 0x100000) && (page < pvt->remapbase))) | 188 | ((page >= 0x100000) && (page < pvt->remapbase))) |
193 | return page; | 189 | return page; |
194 | 190 | ||
195 | remap = (page - pvt->tolm) + pvt->remapbase; | 191 | remap = (page - pvt->tolm) + pvt->remapbase; |
@@ -201,8 +197,7 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci, | |||
201 | return pvt->tolm - 1; | 197 | return pvt->tolm - 1; |
202 | } | 198 | } |
203 | 199 | ||
204 | static void process_ce(struct mem_ctl_info *mci, | 200 | static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info) |
205 | struct e7xxx_error_info *info) | ||
206 | { | 201 | { |
207 | u32 error_1b, page; | 202 | u32 error_1b, page; |
208 | u16 syndrome; | 203 | u16 syndrome; |
@@ -213,7 +208,7 @@ static void process_ce(struct mem_ctl_info *mci, | |||
213 | /* read the error address */ | 208 | /* read the error address */ |
214 | error_1b = info->dram_celog_add; | 209 | error_1b = info->dram_celog_add; |
215 | /* FIXME - should use PAGE_SHIFT */ | 210 | /* FIXME - should use PAGE_SHIFT */ |
216 | page = error_1b >> 6; /* convert the address to 4k page */ | 211 | page = error_1b >> 6; /* convert the address to 4k page */ |
217 | /* read the syndrome */ | 212 | /* read the syndrome */ |
218 | syndrome = info->dram_celog_syndrome; | 213 | syndrome = info->dram_celog_syndrome; |
219 | /* FIXME - check for -1 */ | 214 | /* FIXME - check for -1 */ |
@@ -229,8 +224,7 @@ static void process_ce_no_info(struct mem_ctl_info *mci) | |||
229 | edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow"); | 224 | edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow"); |
230 | } | 225 | } |
231 | 226 | ||
232 | static void process_ue(struct mem_ctl_info *mci, | 227 | static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info) |
233 | struct e7xxx_error_info *info) | ||
234 | { | 228 | { |
235 | u32 error_2b, block_page; | 229 | u32 error_2b, block_page; |
236 | int row; | 230 | int row; |
@@ -239,7 +233,7 @@ static void process_ue(struct mem_ctl_info *mci, | |||
239 | /* read the error address */ | 233 | /* read the error address */ |
240 | error_2b = info->dram_uelog_add; | 234 | error_2b = info->dram_uelog_add; |
241 | /* FIXME - should use PAGE_SHIFT */ | 235 | /* FIXME - should use PAGE_SHIFT */ |
242 | block_page = error_2b >> 6; /* convert to 4k address */ | 236 | block_page = error_2b >> 6; /* convert to 4k address */ |
243 | row = edac_mc_find_csrow_by_page(mci, block_page); | 237 | row = edac_mc_find_csrow_by_page(mci, block_page); |
244 | edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE"); | 238 | edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE"); |
245 | } | 239 | } |
@@ -250,28 +244,26 @@ static void process_ue_no_info(struct mem_ctl_info *mci) | |||
250 | edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow"); | 244 | edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow"); |
251 | } | 245 | } |
252 | 246 | ||
253 | static void e7xxx_get_error_info (struct mem_ctl_info *mci, | 247 | static void e7xxx_get_error_info(struct mem_ctl_info *mci, |
254 | struct e7xxx_error_info *info) | 248 | struct e7xxx_error_info *info) |
255 | { | 249 | { |
256 | struct e7xxx_pvt *pvt; | 250 | struct e7xxx_pvt *pvt; |
257 | 251 | ||
258 | pvt = (struct e7xxx_pvt *) mci->pvt_info; | 252 | pvt = (struct e7xxx_pvt *)mci->pvt_info; |
259 | pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR, | 253 | pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR, &info->dram_ferr); |
260 | &info->dram_ferr); | 254 | pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR, &info->dram_nerr); |
261 | pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR, | ||
262 | &info->dram_nerr); | ||
263 | 255 | ||
264 | if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) { | 256 | if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) { |
265 | pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD, | 257 | pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD, |
266 | &info->dram_celog_add); | 258 | &info->dram_celog_add); |
267 | pci_read_config_word(pvt->bridge_ck, | 259 | pci_read_config_word(pvt->bridge_ck, |
268 | E7XXX_DRAM_CELOG_SYNDROME, | 260 | E7XXX_DRAM_CELOG_SYNDROME, |
269 | &info->dram_celog_syndrome); | 261 | &info->dram_celog_syndrome); |
270 | } | 262 | } |
271 | 263 | ||
272 | if ((info->dram_ferr & 2) || (info->dram_nerr & 2)) | 264 | if ((info->dram_ferr & 2) || (info->dram_nerr & 2)) |
273 | pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD, | 265 | pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD, |
274 | &info->dram_uelog_add); | 266 | &info->dram_uelog_add); |
275 | 267 | ||
276 | if (info->dram_ferr & 3) | 268 | if (info->dram_ferr & 3) |
277 | pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); | 269 | pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03); |
@@ -280,8 +272,9 @@ static void e7xxx_get_error_info (struct mem_ctl_info *mci, | |||
280 | pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); | 272 | pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03); |
281 | } | 273 | } |
282 | 274 | ||
283 | static int e7xxx_process_error_info (struct mem_ctl_info *mci, | 275 | static int e7xxx_process_error_info(struct mem_ctl_info *mci, |
284 | struct e7xxx_error_info *info, int handle_errors) | 276 | struct e7xxx_error_info *info, |
277 | int handle_errors) | ||
285 | { | 278 | { |
286 | int error_found; | 279 | int error_found; |
287 | 280 | ||
@@ -342,7 +335,6 @@ static inline int dual_channel_active(u32 drc, int dev_idx) | |||
342 | return (dev_idx == E7501) ? ((drc >> 22) & 0x1) : 1; | 335 | return (dev_idx == E7501) ? ((drc >> 22) & 0x1) : 1; |
343 | } | 336 | } |
344 | 337 | ||
345 | |||
346 | /* Return DRB granularity (0=32mb, 1=64mb). */ | 338 | /* Return DRB granularity (0=32mb, 1=64mb). */ |
347 | static inline int drb_granularity(u32 drc, int dev_idx) | 339 | static inline int drb_granularity(u32 drc, int dev_idx) |
348 | { | 340 | { |
@@ -350,9 +342,8 @@ static inline int drb_granularity(u32 drc, int dev_idx) | |||
350 | return (dev_idx == E7501) ? ((drc >> 18) & 0x3) : 1; | 342 | return (dev_idx == E7501) ? ((drc >> 18) & 0x3) : 1; |
351 | } | 343 | } |
352 | 344 | ||
353 | |||
354 | static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, | 345 | static void e7xxx_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, |
355 | int dev_idx, u32 drc) | 346 | int dev_idx, u32 drc) |
356 | { | 347 | { |
357 | unsigned long last_cumul_size; | 348 | unsigned long last_cumul_size; |
358 | int index; | 349 | int index; |
@@ -422,13 +413,13 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
422 | debugf0("%s(): mci\n", __func__); | 413 | debugf0("%s(): mci\n", __func__); |
423 | 414 | ||
424 | /* make sure error reporting method is sane */ | 415 | /* make sure error reporting method is sane */ |
425 | switch(edac_op_state) { | 416 | switch (edac_op_state) { |
426 | case EDAC_OPSTATE_POLL: | 417 | case EDAC_OPSTATE_POLL: |
427 | case EDAC_OPSTATE_NMI: | 418 | case EDAC_OPSTATE_NMI: |
428 | break; | 419 | break; |
429 | default: | 420 | default: |
430 | edac_op_state = EDAC_OPSTATE_POLL; | 421 | edac_op_state = EDAC_OPSTATE_POLL; |
431 | break; | 422 | break; |
432 | } | 423 | } |
433 | 424 | ||
434 | pci_read_config_dword(pdev, E7XXX_DRC, &drc); | 425 | pci_read_config_dword(pdev, E7XXX_DRC, &drc); |
@@ -442,22 +433,21 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
442 | debugf3("%s(): init mci\n", __func__); | 433 | debugf3("%s(): init mci\n", __func__); |
443 | mci->mtype_cap = MEM_FLAG_RDDR; | 434 | mci->mtype_cap = MEM_FLAG_RDDR; |
444 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | | 435 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED | |
445 | EDAC_FLAG_S4ECD4ED; | 436 | EDAC_FLAG_S4ECD4ED; |
446 | /* FIXME - what if different memory types are in different csrows? */ | 437 | /* FIXME - what if different memory types are in different csrows? */ |
447 | mci->mod_name = EDAC_MOD_STR; | 438 | mci->mod_name = EDAC_MOD_STR; |
448 | mci->mod_ver = E7XXX_REVISION; | 439 | mci->mod_ver = E7XXX_REVISION; |
449 | mci->dev = &pdev->dev; | 440 | mci->dev = &pdev->dev; |
450 | debugf3("%s(): init pvt\n", __func__); | 441 | debugf3("%s(): init pvt\n", __func__); |
451 | pvt = (struct e7xxx_pvt *) mci->pvt_info; | 442 | pvt = (struct e7xxx_pvt *)mci->pvt_info; |
452 | pvt->dev_info = &e7xxx_devs[dev_idx]; | 443 | pvt->dev_info = &e7xxx_devs[dev_idx]; |
453 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, | 444 | pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL, |
454 | pvt->dev_info->err_dev, | 445 | pvt->dev_info->err_dev, pvt->bridge_ck); |
455 | pvt->bridge_ck); | ||
456 | 446 | ||
457 | if (!pvt->bridge_ck) { | 447 | if (!pvt->bridge_ck) { |
458 | e7xxx_printk(KERN_ERR, "error reporting device not found:" | 448 | e7xxx_printk(KERN_ERR, "error reporting device not found:" |
459 | "vendor %x device 0x%x (broken BIOS?)\n", | 449 | "vendor %x device 0x%x (broken BIOS?)\n", |
460 | PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); | 450 | PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev); |
461 | goto fail0; | 451 | goto fail0; |
462 | } | 452 | } |
463 | 453 | ||
@@ -477,8 +467,8 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
477 | pci_read_config_word(pdev, E7XXX_REMAPLIMIT, &pci_data); | 467 | pci_read_config_word(pdev, E7XXX_REMAPLIMIT, &pci_data); |
478 | pvt->remaplimit = ((u32) pci_data) << 14; | 468 | pvt->remaplimit = ((u32) pci_data) << 14; |
479 | e7xxx_printk(KERN_INFO, | 469 | e7xxx_printk(KERN_INFO, |
480 | "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, | 470 | "tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm, |
481 | pvt->remapbase, pvt->remaplimit); | 471 | pvt->remapbase, pvt->remaplimit); |
482 | 472 | ||
483 | /* clear any pending errors, or initial state bits */ | 473 | /* clear any pending errors, or initial state bits */ |
484 | e7xxx_get_error_info(mci, &discard); | 474 | e7xxx_get_error_info(mci, &discard); |
@@ -486,7 +476,7 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
486 | /* Here we assume that we will never see multiple instances of this | 476 | /* Here we assume that we will never see multiple instances of this |
487 | * type of memory controller. The ID is therefore hardcoded to 0. | 477 | * type of memory controller. The ID is therefore hardcoded to 0. |
488 | */ | 478 | */ |
489 | if (edac_mc_add_mc(mci,0)) { | 479 | if (edac_mc_add_mc(mci, 0)) { |
490 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 480 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
491 | goto fail1; | 481 | goto fail1; |
492 | } | 482 | } |
@@ -495,10 +485,10 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx) | |||
495 | debugf3("%s(): success\n", __func__); | 485 | debugf3("%s(): success\n", __func__); |
496 | return 0; | 486 | return 0; |
497 | 487 | ||
498 | fail1: | 488 | fail1: |
499 | pci_dev_put(pvt->bridge_ck); | 489 | pci_dev_put(pvt->bridge_ck); |
500 | 490 | ||
501 | fail0: | 491 | fail0: |
502 | edac_mc_free(mci); | 492 | edac_mc_free(mci); |
503 | 493 | ||
504 | return -ENODEV; | 494 | return -ENODEV; |
@@ -506,13 +496,13 @@ fail0: | |||
506 | 496 | ||
507 | /* returns count (>= 0), or negative on error */ | 497 | /* returns count (>= 0), or negative on error */ |
508 | static int __devinit e7xxx_init_one(struct pci_dev *pdev, | 498 | static int __devinit e7xxx_init_one(struct pci_dev *pdev, |
509 | const struct pci_device_id *ent) | 499 | const struct pci_device_id *ent) |
510 | { | 500 | { |
511 | debugf0("%s()\n", __func__); | 501 | debugf0("%s()\n", __func__); |
512 | 502 | ||
513 | /* wake up and enable device */ | 503 | /* wake up and enable device */ |
514 | return pci_enable_device(pdev) ? | 504 | return pci_enable_device(pdev) ? |
515 | -EIO : e7xxx_probe1(pdev, ent->driver_data); | 505 | -EIO : e7xxx_probe1(pdev, ent->driver_data); |
516 | } | 506 | } |
517 | 507 | ||
518 | static void __devexit e7xxx_remove_one(struct pci_dev *pdev) | 508 | static void __devexit e7xxx_remove_one(struct pci_dev *pdev) |
@@ -525,31 +515,27 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev) | |||
525 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) | 515 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
526 | return; | 516 | return; |
527 | 517 | ||
528 | pvt = (struct e7xxx_pvt *) mci->pvt_info; | 518 | pvt = (struct e7xxx_pvt *)mci->pvt_info; |
529 | pci_dev_put(pvt->bridge_ck); | 519 | pci_dev_put(pvt->bridge_ck); |
530 | edac_mc_free(mci); | 520 | edac_mc_free(mci); |
531 | } | 521 | } |
532 | 522 | ||
533 | static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = { | 523 | static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = { |
534 | { | 524 | { |
535 | PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 525 | PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
536 | E7205 | 526 | E7205}, |
537 | }, | ||
538 | { | 527 | { |
539 | PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 528 | PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
540 | E7500 | 529 | E7500}, |
541 | }, | ||
542 | { | 530 | { |
543 | PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 531 | PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
544 | E7501 | 532 | E7501}, |
545 | }, | ||
546 | { | 533 | { |
547 | PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 534 | PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
548 | E7505 | 535 | E7505}, |
549 | }, | ||
550 | { | 536 | { |
551 | 0, | 537 | 0, |
552 | } /* 0 terminated list. */ | 538 | } /* 0 terminated list. */ |
553 | }; | 539 | }; |
554 | 540 | ||
555 | MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); | 541 | MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl); |
@@ -576,7 +562,7 @@ module_exit(e7xxx_exit); | |||
576 | 562 | ||
577 | MODULE_LICENSE("GPL"); | 563 | MODULE_LICENSE("GPL"); |
578 | MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" | 564 | MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n" |
579 | "Based on.work by Dan Hollis et al"); | 565 | "Based on.work by Dan Hollis et al"); |
580 | MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers"); | 566 | MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers"); |
581 | module_param(edac_op_state, int, 0444); | 567 | module_param(edac_op_state, int, 0444); |
582 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | 568 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); |