diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/edac/x38_edac.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/edac/x38_edac.c')
-rw-r--r-- | drivers/edac/x38_edac.c | 95 |
1 files changed, 43 insertions, 52 deletions
diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index c9db24d95ca..b6f47de152f 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c | |||
@@ -103,10 +103,10 @@ static int how_many_channel(struct pci_dev *pdev) | |||
103 | 103 | ||
104 | pci_read_config_byte(pdev, X38_CAPID0 + 8, &capid0_8b); | 104 | pci_read_config_byte(pdev, X38_CAPID0 + 8, &capid0_8b); |
105 | if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ | 105 | if (capid0_8b & 0x20) { /* check DCD: Dual Channel Disable */ |
106 | edac_dbg(0, "In single channel mode\n"); | 106 | debugf0("In single channel mode.\n"); |
107 | x38_channel_num = 1; | 107 | x38_channel_num = 1; |
108 | } else { | 108 | } else { |
109 | edac_dbg(0, "In dual channel mode\n"); | 109 | debugf0("In dual channel mode.\n"); |
110 | x38_channel_num = 2; | 110 | x38_channel_num = 2; |
111 | } | 111 | } |
112 | 112 | ||
@@ -151,7 +151,7 @@ static void x38_clear_error_info(struct mem_ctl_info *mci) | |||
151 | { | 151 | { |
152 | struct pci_dev *pdev; | 152 | struct pci_dev *pdev; |
153 | 153 | ||
154 | pdev = to_pci_dev(mci->pdev); | 154 | pdev = to_pci_dev(mci->dev); |
155 | 155 | ||
156 | /* | 156 | /* |
157 | * Clear any error bits. | 157 | * Clear any error bits. |
@@ -172,7 +172,7 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, | |||
172 | struct pci_dev *pdev; | 172 | struct pci_dev *pdev; |
173 | void __iomem *window = mci->pvt_info; | 173 | void __iomem *window = mci->pvt_info; |
174 | 174 | ||
175 | pdev = to_pci_dev(mci->pdev); | 175 | pdev = to_pci_dev(mci->dev); |
176 | 176 | ||
177 | /* | 177 | /* |
178 | * This is a mess because there is no atomic way to read all the | 178 | * This is a mess because there is no atomic way to read all the |
@@ -215,26 +215,19 @@ static void x38_process_error_info(struct mem_ctl_info *mci, | |||
215 | return; | 215 | return; |
216 | 216 | ||
217 | if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { | 217 | if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { |
218 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, 0, 0, 0, | 218 | edac_mc_handle_ce_no_info(mci, "UE overwrote CE"); |
219 | -1, -1, -1, | ||
220 | "UE overwrote CE", ""); | ||
221 | info->errsts = info->errsts2; | 219 | info->errsts = info->errsts2; |
222 | } | 220 | } |
223 | 221 | ||
224 | for (channel = 0; channel < x38_channel_num; channel++) { | 222 | for (channel = 0; channel < x38_channel_num; channel++) { |
225 | log = info->eccerrlog[channel]; | 223 | log = info->eccerrlog[channel]; |
226 | if (log & X38_ECCERRLOG_UE) { | 224 | if (log & X38_ECCERRLOG_UE) { |
227 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, | 225 | edac_mc_handle_ue(mci, 0, 0, |
228 | 0, 0, 0, | 226 | eccerrlog_row(channel, log), "x38 UE"); |
229 | eccerrlog_row(channel, log), | ||
230 | -1, -1, | ||
231 | "x38 UE", ""); | ||
232 | } else if (log & X38_ECCERRLOG_CE) { | 227 | } else if (log & X38_ECCERRLOG_CE) { |
233 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, | 228 | edac_mc_handle_ce(mci, 0, 0, |
234 | 0, 0, eccerrlog_syndrome(log), | 229 | eccerrlog_syndrome(log), |
235 | eccerrlog_row(channel, log), | 230 | eccerrlog_row(channel, log), 0, "x38 CE"); |
236 | -1, -1, | ||
237 | "x38 CE", ""); | ||
238 | } | 231 | } |
239 | } | 232 | } |
240 | } | 233 | } |
@@ -243,7 +236,7 @@ static void x38_check(struct mem_ctl_info *mci) | |||
243 | { | 236 | { |
244 | struct x38_error_info info; | 237 | struct x38_error_info info; |
245 | 238 | ||
246 | edac_dbg(1, "MC%d\n", mci->mc_idx); | 239 | debugf1("MC%d: %s()\n", mci->mc_idx, __func__); |
247 | x38_get_and_clear_error_info(mci, &info); | 240 | x38_get_and_clear_error_info(mci, &info); |
248 | x38_process_error_info(mci, &info); | 241 | x38_process_error_info(mci, &info); |
249 | } | 242 | } |
@@ -324,14 +317,14 @@ static unsigned long drb_to_nr_pages( | |||
324 | static int x38_probe1(struct pci_dev *pdev, int dev_idx) | 317 | static int x38_probe1(struct pci_dev *pdev, int dev_idx) |
325 | { | 318 | { |
326 | int rc; | 319 | int rc; |
327 | int i, j; | 320 | int i; |
328 | struct mem_ctl_info *mci = NULL; | 321 | struct mem_ctl_info *mci = NULL; |
329 | struct edac_mc_layer layers[2]; | 322 | unsigned long last_page; |
330 | u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]; | 323 | u16 drbs[X38_CHANNELS][X38_RANKS_PER_CHANNEL]; |
331 | bool stacked; | 324 | bool stacked; |
332 | void __iomem *window; | 325 | void __iomem *window; |
333 | 326 | ||
334 | edac_dbg(0, "MC:\n"); | 327 | debugf0("MC: %s()\n", __func__); |
335 | 328 | ||
336 | window = x38_map_mchbar(pdev); | 329 | window = x38_map_mchbar(pdev); |
337 | if (!window) | 330 | if (!window) |
@@ -342,19 +335,13 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) | |||
342 | how_many_channel(pdev); | 335 | how_many_channel(pdev); |
343 | 336 | ||
344 | /* FIXME: unconventional pvt_info usage */ | 337 | /* FIXME: unconventional pvt_info usage */ |
345 | layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; | 338 | mci = edac_mc_alloc(0, X38_RANKS, x38_channel_num, 0); |
346 | layers[0].size = X38_RANKS; | ||
347 | layers[0].is_virt_csrow = true; | ||
348 | layers[1].type = EDAC_MC_LAYER_CHANNEL; | ||
349 | layers[1].size = x38_channel_num; | ||
350 | layers[1].is_virt_csrow = false; | ||
351 | mci = edac_mc_alloc(0, ARRAY_SIZE(layers), layers, 0); | ||
352 | if (!mci) | 339 | if (!mci) |
353 | return -ENOMEM; | 340 | return -ENOMEM; |
354 | 341 | ||
355 | edac_dbg(3, "MC: init mci\n"); | 342 | debugf3("MC: %s(): init mci\n", __func__); |
356 | 343 | ||
357 | mci->pdev = &pdev->dev; | 344 | mci->dev = &pdev->dev; |
358 | mci->mtype_cap = MEM_FLAG_DDR2; | 345 | mci->mtype_cap = MEM_FLAG_DDR2; |
359 | 346 | ||
360 | mci->edac_ctl_cap = EDAC_FLAG_SECDED; | 347 | mci->edac_ctl_cap = EDAC_FLAG_SECDED; |
@@ -376,38 +363,41 @@ static int x38_probe1(struct pci_dev *pdev, int dev_idx) | |||
376 | * cumulative; the last one will contain the total memory | 363 | * cumulative; the last one will contain the total memory |
377 | * contained in all ranks. | 364 | * contained in all ranks. |
378 | */ | 365 | */ |
366 | last_page = -1UL; | ||
379 | for (i = 0; i < mci->nr_csrows; i++) { | 367 | for (i = 0; i < mci->nr_csrows; i++) { |
380 | unsigned long nr_pages; | 368 | unsigned long nr_pages; |
381 | struct csrow_info *csrow = mci->csrows[i]; | 369 | struct csrow_info *csrow = &mci->csrows[i]; |
382 | 370 | ||
383 | nr_pages = drb_to_nr_pages(drbs, stacked, | 371 | nr_pages = drb_to_nr_pages(drbs, stacked, |
384 | i / X38_RANKS_PER_CHANNEL, | 372 | i / X38_RANKS_PER_CHANNEL, |
385 | i % X38_RANKS_PER_CHANNEL); | 373 | i % X38_RANKS_PER_CHANNEL); |
386 | 374 | ||
387 | if (nr_pages == 0) | 375 | if (nr_pages == 0) { |
376 | csrow->mtype = MEM_EMPTY; | ||
388 | continue; | 377 | continue; |
378 | } | ||
389 | 379 | ||
390 | for (j = 0; j < x38_channel_num; j++) { | 380 | csrow->first_page = last_page + 1; |
391 | struct dimm_info *dimm = csrow->channels[j]->dimm; | 381 | last_page += nr_pages; |
382 | csrow->last_page = last_page; | ||
383 | csrow->nr_pages = nr_pages; | ||
392 | 384 | ||
393 | dimm->nr_pages = nr_pages / x38_channel_num; | 385 | csrow->grain = nr_pages << PAGE_SHIFT; |
394 | dimm->grain = nr_pages << PAGE_SHIFT; | 386 | csrow->mtype = MEM_DDR2; |
395 | dimm->mtype = MEM_DDR2; | 387 | csrow->dtype = DEV_UNKNOWN; |
396 | dimm->dtype = DEV_UNKNOWN; | 388 | csrow->edac_mode = EDAC_UNKNOWN; |
397 | dimm->edac_mode = EDAC_UNKNOWN; | ||
398 | } | ||
399 | } | 389 | } |
400 | 390 | ||
401 | x38_clear_error_info(mci); | 391 | x38_clear_error_info(mci); |
402 | 392 | ||
403 | rc = -ENODEV; | 393 | rc = -ENODEV; |
404 | if (edac_mc_add_mc(mci)) { | 394 | if (edac_mc_add_mc(mci)) { |
405 | edac_dbg(3, "MC: failed edac_mc_add_mc()\n"); | 395 | debugf3("MC: %s(): failed edac_mc_add_mc()\n", __func__); |
406 | goto fail; | 396 | goto fail; |
407 | } | 397 | } |
408 | 398 | ||
409 | /* get this far and it's successful */ | 399 | /* get this far and it's successful */ |
410 | edac_dbg(3, "MC: success\n"); | 400 | debugf3("MC: %s(): success\n", __func__); |
411 | return 0; | 401 | return 0; |
412 | 402 | ||
413 | fail: | 403 | fail: |
@@ -418,11 +408,12 @@ fail: | |||
418 | return rc; | 408 | return rc; |
419 | } | 409 | } |
420 | 410 | ||
421 | static int x38_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 411 | static int __devinit x38_init_one(struct pci_dev *pdev, |
412 | const struct pci_device_id *ent) | ||
422 | { | 413 | { |
423 | int rc; | 414 | int rc; |
424 | 415 | ||
425 | edac_dbg(0, "MC:\n"); | 416 | debugf0("MC: %s()\n", __func__); |
426 | 417 | ||
427 | if (pci_enable_device(pdev) < 0) | 418 | if (pci_enable_device(pdev) < 0) |
428 | return -EIO; | 419 | return -EIO; |
@@ -434,11 +425,11 @@ static int x38_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
434 | return rc; | 425 | return rc; |
435 | } | 426 | } |
436 | 427 | ||
437 | static void x38_remove_one(struct pci_dev *pdev) | 428 | static void __devexit x38_remove_one(struct pci_dev *pdev) |
438 | { | 429 | { |
439 | struct mem_ctl_info *mci; | 430 | struct mem_ctl_info *mci; |
440 | 431 | ||
441 | edac_dbg(0, "\n"); | 432 | debugf0("%s()\n", __func__); |
442 | 433 | ||
443 | mci = edac_mc_del_mc(&pdev->dev); | 434 | mci = edac_mc_del_mc(&pdev->dev); |
444 | if (!mci) | 435 | if (!mci) |
@@ -449,7 +440,7 @@ static void x38_remove_one(struct pci_dev *pdev) | |||
449 | edac_mc_free(mci); | 440 | edac_mc_free(mci); |
450 | } | 441 | } |
451 | 442 | ||
452 | static DEFINE_PCI_DEVICE_TABLE(x38_pci_tbl) = { | 443 | static const struct pci_device_id x38_pci_tbl[] __devinitdata = { |
453 | { | 444 | { |
454 | PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 445 | PCI_VEND_DEV(INTEL, X38_HB), PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
455 | X38}, | 446 | X38}, |
@@ -463,7 +454,7 @@ MODULE_DEVICE_TABLE(pci, x38_pci_tbl); | |||
463 | static struct pci_driver x38_driver = { | 454 | static struct pci_driver x38_driver = { |
464 | .name = EDAC_MOD_STR, | 455 | .name = EDAC_MOD_STR, |
465 | .probe = x38_init_one, | 456 | .probe = x38_init_one, |
466 | .remove = x38_remove_one, | 457 | .remove = __devexit_p(x38_remove_one), |
467 | .id_table = x38_pci_tbl, | 458 | .id_table = x38_pci_tbl, |
468 | }; | 459 | }; |
469 | 460 | ||
@@ -471,7 +462,7 @@ static int __init x38_init(void) | |||
471 | { | 462 | { |
472 | int pci_rc; | 463 | int pci_rc; |
473 | 464 | ||
474 | edac_dbg(3, "MC:\n"); | 465 | debugf3("MC: %s()\n", __func__); |
475 | 466 | ||
476 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ | 467 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ |
477 | opstate_init(); | 468 | opstate_init(); |
@@ -485,14 +476,14 @@ static int __init x38_init(void) | |||
485 | mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, | 476 | mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, |
486 | PCI_DEVICE_ID_INTEL_X38_HB, NULL); | 477 | PCI_DEVICE_ID_INTEL_X38_HB, NULL); |
487 | if (!mci_pdev) { | 478 | if (!mci_pdev) { |
488 | edac_dbg(0, "x38 pci_get_device fail\n"); | 479 | debugf0("x38 pci_get_device fail\n"); |
489 | pci_rc = -ENODEV; | 480 | pci_rc = -ENODEV; |
490 | goto fail1; | 481 | goto fail1; |
491 | } | 482 | } |
492 | 483 | ||
493 | pci_rc = x38_init_one(mci_pdev, x38_pci_tbl); | 484 | pci_rc = x38_init_one(mci_pdev, x38_pci_tbl); |
494 | if (pci_rc < 0) { | 485 | if (pci_rc < 0) { |
495 | edac_dbg(0, "x38 init fail\n"); | 486 | debugf0("x38 init fail\n"); |
496 | pci_rc = -ENODEV; | 487 | pci_rc = -ENODEV; |
497 | goto fail1; | 488 | goto fail1; |
498 | } | 489 | } |
@@ -512,7 +503,7 @@ fail0: | |||
512 | 503 | ||
513 | static void __exit x38_exit(void) | 504 | static void __exit x38_exit(void) |
514 | { | 505 | { |
515 | edac_dbg(3, "MC:\n"); | 506 | debugf3("MC: %s()\n", __func__); |
516 | 507 | ||
517 | pci_unregister_driver(&x38_driver); | 508 | pci_unregister_driver(&x38_driver); |
518 | if (!x38_registered) { | 509 | if (!x38_registered) { |