diff options
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r-- | drivers/edac/edac_mc.c | 202 |
1 files changed, 103 insertions, 99 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 2e8c198749a1..835319126bb6 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "edac_core.h" | 34 | #include "edac_core.h" |
35 | #include "edac_module.h" | 35 | #include "edac_module.h" |
36 | 36 | ||
37 | |||
38 | /* lock to memory controller's control array */ | 37 | /* lock to memory controller's control array */ |
39 | static DEFINE_MUTEX(mem_ctls_mutex); | 38 | static DEFINE_MUTEX(mem_ctls_mutex); |
40 | static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); | 39 | static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); |
@@ -54,13 +53,11 @@ static void edac_mc_dump_csrow(struct csrow_info *csrow) | |||
54 | { | 53 | { |
55 | debugf4("\tcsrow = %p\n", csrow); | 54 | debugf4("\tcsrow = %p\n", csrow); |
56 | debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); | 55 | debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx); |
57 | debugf4("\tcsrow->first_page = 0x%lx\n", | 56 | debugf4("\tcsrow->first_page = 0x%lx\n", csrow->first_page); |
58 | csrow->first_page); | ||
59 | debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page); | 57 | debugf4("\tcsrow->last_page = 0x%lx\n", csrow->last_page); |
60 | debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); | 58 | debugf4("\tcsrow->page_mask = 0x%lx\n", csrow->page_mask); |
61 | debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages); | 59 | debugf4("\tcsrow->nr_pages = 0x%x\n", csrow->nr_pages); |
62 | debugf4("\tcsrow->nr_channels = %d\n", | 60 | debugf4("\tcsrow->nr_channels = %d\n", csrow->nr_channels); |
63 | csrow->nr_channels); | ||
64 | debugf4("\tcsrow->channels = %p\n", csrow->channels); | 61 | debugf4("\tcsrow->channels = %p\n", csrow->channels); |
65 | debugf4("\tcsrow->mci = %p\n\n", csrow->mci); | 62 | debugf4("\tcsrow->mci = %p\n\n", csrow->mci); |
66 | } | 63 | } |
@@ -75,12 +72,11 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
75 | debugf3("\tmci->nr_csrows = %d, csrows = %p\n", | 72 | debugf3("\tmci->nr_csrows = %d, csrows = %p\n", |
76 | mci->nr_csrows, mci->csrows); | 73 | mci->nr_csrows, mci->csrows); |
77 | debugf3("\tdev = %p\n", mci->dev); | 74 | debugf3("\tdev = %p\n", mci->dev); |
78 | debugf3("\tmod_name:ctl_name = %s:%s\n", | 75 | debugf3("\tmod_name:ctl_name = %s:%s\n", mci->mod_name, mci->ctl_name); |
79 | mci->mod_name, mci->ctl_name); | ||
80 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); | 76 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); |
81 | } | 77 | } |
82 | 78 | ||
83 | #endif /* CONFIG_EDAC_DEBUG */ | 79 | #endif /* CONFIG_EDAC_DEBUG */ |
84 | 80 | ||
85 | /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. | 81 | /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. |
86 | * Adjust 'ptr' so that its alignment is at least as stringent as what the | 82 | * Adjust 'ptr' so that its alignment is at least as stringent as what the |
@@ -89,7 +85,7 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
89 | * If 'size' is a constant, the compiler will optimize this whole function | 85 | * If 'size' is a constant, the compiler will optimize this whole function |
90 | * down to either a no-op or the addition of a constant to the value of 'ptr'. | 86 | * down to either a no-op or the addition of a constant to the value of 'ptr'. |
91 | */ | 87 | */ |
92 | char * edac_align_ptr(void *ptr, unsigned size) | 88 | char *edac_align_ptr(void *ptr, unsigned size) |
93 | { | 89 | { |
94 | unsigned align, r; | 90 | unsigned align, r; |
95 | 91 | ||
@@ -106,14 +102,14 @@ char * edac_align_ptr(void *ptr, unsigned size) | |||
106 | else if (size > sizeof(char)) | 102 | else if (size > sizeof(char)) |
107 | align = sizeof(short); | 103 | align = sizeof(short); |
108 | else | 104 | else |
109 | return (char *) ptr; | 105 | return (char *)ptr; |
110 | 106 | ||
111 | r = size % align; | 107 | r = size % align; |
112 | 108 | ||
113 | if (r == 0) | 109 | if (r == 0) |
114 | return (char *) ptr; | 110 | return (char *)ptr; |
115 | 111 | ||
116 | return (char *) (((unsigned long) ptr) + align - r); | 112 | return (char *)(((unsigned long)ptr) + align - r); |
117 | } | 113 | } |
118 | 114 | ||
119 | /** | 115 | /** |
@@ -133,7 +129,7 @@ char * edac_align_ptr(void *ptr, unsigned size) | |||
133 | * struct mem_ctl_info pointer | 129 | * struct mem_ctl_info pointer |
134 | */ | 130 | */ |
135 | struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, | 131 | struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, |
136 | unsigned nr_chans) | 132 | unsigned nr_chans) |
137 | { | 133 | { |
138 | struct mem_ctl_info *mci; | 134 | struct mem_ctl_info *mci; |
139 | struct csrow_info *csi, *csrow; | 135 | struct csrow_info *csi, *csrow; |
@@ -147,12 +143,12 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, | |||
147 | * stringent as what the compiler would provide if we could simply | 143 | * stringent as what the compiler would provide if we could simply |
148 | * hardcode everything into a single struct. | 144 | * hardcode everything into a single struct. |
149 | */ | 145 | */ |
150 | mci = (struct mem_ctl_info *) 0; | 146 | mci = (struct mem_ctl_info *)0; |
151 | csi = (struct csrow_info *)edac_align_ptr(&mci[1], sizeof(*csi)); | 147 | csi = (struct csrow_info *)edac_align_ptr(&mci[1], sizeof(*csi)); |
152 | chi = (struct channel_info *) | 148 | chi = (struct channel_info *) |
153 | edac_align_ptr(&csi[nr_csrows], sizeof(*chi)); | 149 | edac_align_ptr(&csi[nr_csrows], sizeof(*chi)); |
154 | pvt = edac_align_ptr(&chi[nr_chans * nr_csrows], sz_pvt); | 150 | pvt = edac_align_ptr(&chi[nr_chans * nr_csrows], sz_pvt); |
155 | size = ((unsigned long) pvt) + sz_pvt; | 151 | size = ((unsigned long)pvt) + sz_pvt; |
156 | 152 | ||
157 | if ((mci = kmalloc(size, GFP_KERNEL)) == NULL) | 153 | if ((mci = kmalloc(size, GFP_KERNEL)) == NULL) |
158 | return NULL; | 154 | return NULL; |
@@ -160,11 +156,11 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, | |||
160 | /* Adjust pointers so they point within the memory we just allocated | 156 | /* Adjust pointers so they point within the memory we just allocated |
161 | * rather than an imaginary chunk of memory located at address 0. | 157 | * rather than an imaginary chunk of memory located at address 0. |
162 | */ | 158 | */ |
163 | csi = (struct csrow_info *) (((char *) mci) + ((unsigned long) csi)); | 159 | csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi)); |
164 | chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi)); | 160 | chi = (struct channel_info *)(((char *)mci) + ((unsigned long)chi)); |
165 | pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL; | 161 | pvt = sz_pvt ? (((char *)mci) + ((unsigned long)pvt)) : NULL; |
166 | 162 | ||
167 | memset(mci, 0, size); /* clear all fields */ | 163 | memset(mci, 0, size); /* clear all fields */ |
168 | mci->csrows = csi; | 164 | mci->csrows = csi; |
169 | mci->pvt_info = pvt; | 165 | mci->pvt_info = pvt; |
170 | mci->nr_csrows = nr_csrows; | 166 | mci->nr_csrows = nr_csrows; |
@@ -188,6 +184,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, | |||
188 | 184 | ||
189 | return mci; | 185 | return mci; |
190 | } | 186 | } |
187 | |||
191 | EXPORT_SYMBOL_GPL(edac_mc_alloc); | 188 | EXPORT_SYMBOL_GPL(edac_mc_alloc); |
192 | 189 | ||
193 | /** | 190 | /** |
@@ -198,6 +195,7 @@ void edac_mc_free(struct mem_ctl_info *mci) | |||
198 | { | 195 | { |
199 | kfree(mci); | 196 | kfree(mci); |
200 | } | 197 | } |
198 | |||
201 | EXPORT_SYMBOL_GPL(edac_mc_free); | 199 | EXPORT_SYMBOL_GPL(edac_mc_free); |
202 | 200 | ||
203 | static struct mem_ctl_info *find_mci_by_dev(struct device *dev) | 201 | static struct mem_ctl_info *find_mci_by_dev(struct device *dev) |
@@ -224,7 +222,7 @@ static int edac_mc_assert_error_check_and_clear(void) | |||
224 | { | 222 | { |
225 | int old_state; | 223 | int old_state; |
226 | 224 | ||
227 | if(edac_op_state == EDAC_OPSTATE_POLL) | 225 | if (edac_op_state == EDAC_OPSTATE_POLL) |
228 | return 1; | 226 | return 1; |
229 | 227 | ||
230 | old_state = edac_err_assert; | 228 | old_state = edac_err_assert; |
@@ -240,12 +238,12 @@ static int edac_mc_assert_error_check_and_clear(void) | |||
240 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) | 238 | #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) |
241 | static void edac_mc_workq_function(struct work_struct *work_req) | 239 | static void edac_mc_workq_function(struct work_struct *work_req) |
242 | { | 240 | { |
243 | struct delayed_work *d_work = (struct delayed_work*) work_req; | 241 | struct delayed_work *d_work = (struct delayed_work *)work_req; |
244 | struct mem_ctl_info *mci = to_edac_mem_ctl_work(d_work); | 242 | struct mem_ctl_info *mci = to_edac_mem_ctl_work(d_work); |
245 | #else | 243 | #else |
246 | static void edac_mc_workq_function(void *ptr) | 244 | static void edac_mc_workq_function(void *ptr) |
247 | { | 245 | { |
248 | struct mem_ctl_info *mci = (struct mem_ctl_info *) ptr; | 246 | struct mem_ctl_info *mci = (struct mem_ctl_info *)ptr; |
249 | #endif | 247 | #endif |
250 | 248 | ||
251 | mutex_lock(&mem_ctls_mutex); | 249 | mutex_lock(&mem_ctls_mutex); |
@@ -264,7 +262,7 @@ static void edac_mc_workq_function(void *ptr) | |||
264 | 262 | ||
265 | /* Reschedule */ | 263 | /* Reschedule */ |
266 | queue_delayed_work(edac_workqueue, &mci->work, | 264 | queue_delayed_work(edac_workqueue, &mci->work, |
267 | msecs_to_jiffies(edac_mc_get_poll_msec())); | 265 | msecs_to_jiffies(edac_mc_get_poll_msec())); |
268 | } | 266 | } |
269 | 267 | ||
270 | /* | 268 | /* |
@@ -320,7 +318,7 @@ void edac_reset_delay_period(struct mem_ctl_info *mci, unsigned long value) | |||
320 | * Before calling this function, caller must | 318 | * Before calling this function, caller must |
321 | * assign a unique value to mci->mc_idx. | 319 | * assign a unique value to mci->mc_idx. |
322 | */ | 320 | */ |
323 | static int add_mc_to_global_list (struct mem_ctl_info *mci) | 321 | static int add_mc_to_global_list(struct mem_ctl_info *mci) |
324 | { | 322 | { |
325 | struct list_head *item, *insert_before; | 323 | struct list_head *item, *insert_before; |
326 | struct mem_ctl_info *p; | 324 | struct mem_ctl_info *p; |
@@ -346,13 +344,13 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci) | |||
346 | atomic_inc(&edac_handlers); | 344 | atomic_inc(&edac_handlers); |
347 | return 0; | 345 | return 0; |
348 | 346 | ||
349 | fail0: | 347 | fail0: |
350 | edac_printk(KERN_WARNING, EDAC_MC, | 348 | edac_printk(KERN_WARNING, EDAC_MC, |
351 | "%s (%s) %s %s already assigned %d\n", p->dev->bus_id, | 349 | "%s (%s) %s %s already assigned %d\n", p->dev->bus_id, |
352 | dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx); | 350 | dev_name(mci), p->mod_name, p->ctl_name, p->mc_idx); |
353 | return 1; | 351 | return 1; |
354 | 352 | ||
355 | fail1: | 353 | fail1: |
356 | edac_printk(KERN_WARNING, EDAC_MC, | 354 | edac_printk(KERN_WARNING, EDAC_MC, |
357 | "bug in low-level driver: attempt to assign\n" | 355 | "bug in low-level driver: attempt to assign\n" |
358 | " duplicate mc_idx %d in %s()\n", p->mc_idx, __func__); | 356 | " duplicate mc_idx %d in %s()\n", p->mc_idx, __func__); |
@@ -385,7 +383,7 @@ static void del_mc_from_global_list(struct mem_ctl_info *mci) | |||
385 | * | 383 | * |
386 | * Caller must hold mem_ctls_mutex. | 384 | * Caller must hold mem_ctls_mutex. |
387 | */ | 385 | */ |
388 | struct mem_ctl_info * edac_mc_find(int idx) | 386 | struct mem_ctl_info *edac_mc_find(int idx) |
389 | { | 387 | { |
390 | struct list_head *item; | 388 | struct list_head *item; |
391 | struct mem_ctl_info *mci; | 389 | struct mem_ctl_info *mci; |
@@ -403,6 +401,7 @@ struct mem_ctl_info * edac_mc_find(int idx) | |||
403 | 401 | ||
404 | return NULL; | 402 | return NULL; |
405 | } | 403 | } |
404 | |||
406 | EXPORT_SYMBOL(edac_mc_find); | 405 | EXPORT_SYMBOL(edac_mc_find); |
407 | 406 | ||
408 | /** | 407 | /** |
@@ -433,8 +432,8 @@ int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx) | |||
433 | 432 | ||
434 | edac_mc_dump_csrow(&mci->csrows[i]); | 433 | edac_mc_dump_csrow(&mci->csrows[i]); |
435 | for (j = 0; j < mci->csrows[i].nr_channels; j++) | 434 | for (j = 0; j < mci->csrows[i].nr_channels; j++) |
436 | edac_mc_dump_channel( | 435 | edac_mc_dump_channel(&mci->csrows[i]. |
437 | &mci->csrows[i].channels[j]); | 436 | channels[j]); |
438 | } | 437 | } |
439 | } | 438 | } |
440 | #endif | 439 | #endif |
@@ -448,7 +447,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx) | |||
448 | 447 | ||
449 | if (edac_create_sysfs_mci_device(mci)) { | 448 | if (edac_create_sysfs_mci_device(mci)) { |
450 | edac_mc_printk(mci, KERN_WARNING, | 449 | edac_mc_printk(mci, KERN_WARNING, |
451 | "failed to create sysfs device\n"); | 450 | "failed to create sysfs device\n"); |
452 | goto fail1; | 451 | goto fail1; |
453 | } | 452 | } |
454 | 453 | ||
@@ -464,18 +463,19 @@ int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx) | |||
464 | 463 | ||
465 | /* Report action taken */ | 464 | /* Report action taken */ |
466 | edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n", | 465 | edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n", |
467 | mci->mod_name, mci->ctl_name, dev_name(mci)); | 466 | mci->mod_name, mci->ctl_name, dev_name(mci)); |
468 | 467 | ||
469 | mutex_unlock(&mem_ctls_mutex); | 468 | mutex_unlock(&mem_ctls_mutex); |
470 | return 0; | 469 | return 0; |
471 | 470 | ||
472 | fail1: | 471 | fail1: |
473 | del_mc_from_global_list(mci); | 472 | del_mc_from_global_list(mci); |
474 | 473 | ||
475 | fail0: | 474 | fail0: |
476 | mutex_unlock(&mem_ctls_mutex); | 475 | mutex_unlock(&mem_ctls_mutex); |
477 | return 1; | 476 | return 1; |
478 | } | 477 | } |
478 | |||
479 | EXPORT_SYMBOL_GPL(edac_mc_add_mc); | 479 | EXPORT_SYMBOL_GPL(edac_mc_add_mc); |
480 | 480 | ||
481 | /** | 481 | /** |
@@ -485,7 +485,7 @@ EXPORT_SYMBOL_GPL(edac_mc_add_mc); | |||
485 | * | 485 | * |
486 | * Return pointer to removed mci structure, or NULL if device not found. | 486 | * Return pointer to removed mci structure, or NULL if device not found. |
487 | */ | 487 | */ |
488 | struct mem_ctl_info * edac_mc_del_mc(struct device *dev) | 488 | struct mem_ctl_info *edac_mc_del_mc(struct device *dev) |
489 | { | 489 | { |
490 | struct mem_ctl_info *mci; | 490 | struct mem_ctl_info *mci; |
491 | 491 | ||
@@ -507,10 +507,11 @@ struct mem_ctl_info * edac_mc_del_mc(struct device *dev) | |||
507 | del_mc_from_global_list(mci); | 507 | del_mc_from_global_list(mci); |
508 | mutex_unlock(&mem_ctls_mutex); | 508 | mutex_unlock(&mem_ctls_mutex); |
509 | edac_printk(KERN_INFO, EDAC_MC, | 509 | edac_printk(KERN_INFO, EDAC_MC, |
510 | "Removed device %d for %s %s: DEV %s\n", mci->mc_idx, | 510 | "Removed device %d for %s %s: DEV %s\n", mci->mc_idx, |
511 | mci->mod_name, mci->ctl_name, dev_name(mci)); | 511 | mci->mod_name, mci->ctl_name, dev_name(mci)); |
512 | return mci; | 512 | return mci; |
513 | } | 513 | } |
514 | |||
514 | EXPORT_SYMBOL_GPL(edac_mc_del_mc); | 515 | EXPORT_SYMBOL_GPL(edac_mc_del_mc); |
515 | 516 | ||
516 | static void edac_mc_scrub_block(unsigned long page, unsigned long offset, | 517 | static void edac_mc_scrub_block(unsigned long page, unsigned long offset, |
@@ -523,7 +524,7 @@ static void edac_mc_scrub_block(unsigned long page, unsigned long offset, | |||
523 | debugf3("%s()\n", __func__); | 524 | debugf3("%s()\n", __func__); |
524 | 525 | ||
525 | /* ECC error page was not in our memory. Ignore it. */ | 526 | /* ECC error page was not in our memory. Ignore it. */ |
526 | if(!pfn_valid(page)) | 527 | if (!pfn_valid(page)) |
527 | return; | 528 | return; |
528 | 529 | ||
529 | /* Find the actual page structure then map it and fix */ | 530 | /* Find the actual page structure then map it and fix */ |
@@ -575,18 +576,20 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) | |||
575 | 576 | ||
576 | if (row == -1) | 577 | if (row == -1) |
577 | edac_mc_printk(mci, KERN_ERR, | 578 | edac_mc_printk(mci, KERN_ERR, |
578 | "could not look up page error address %lx\n", | 579 | "could not look up page error address %lx\n", |
579 | (unsigned long) page); | 580 | (unsigned long)page); |
580 | 581 | ||
581 | return row; | 582 | return row; |
582 | } | 583 | } |
584 | |||
583 | EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page); | 585 | EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page); |
584 | 586 | ||
585 | /* FIXME - setable log (warning/emerg) levels */ | 587 | /* FIXME - setable log (warning/emerg) levels */ |
586 | /* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ | 588 | /* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */ |
587 | void edac_mc_handle_ce(struct mem_ctl_info *mci, | 589 | void edac_mc_handle_ce(struct mem_ctl_info *mci, |
588 | unsigned long page_frame_number, unsigned long offset_in_page, | 590 | unsigned long page_frame_number, |
589 | unsigned long syndrome, int row, int channel, const char *msg) | 591 | unsigned long offset_in_page, unsigned long syndrome, |
592 | int row, int channel, const char *msg) | ||
590 | { | 593 | { |
591 | unsigned long remapped_page; | 594 | unsigned long remapped_page; |
592 | 595 | ||
@@ -596,8 +599,8 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, | |||
596 | if (row >= mci->nr_csrows || row < 0) { | 599 | if (row >= mci->nr_csrows || row < 0) { |
597 | /* something is wrong */ | 600 | /* something is wrong */ |
598 | edac_mc_printk(mci, KERN_ERR, | 601 | edac_mc_printk(mci, KERN_ERR, |
599 | "INTERNAL ERROR: row out of range " | 602 | "INTERNAL ERROR: row out of range " |
600 | "(%d >= %d)\n", row, mci->nr_csrows); | 603 | "(%d >= %d)\n", row, mci->nr_csrows); |
601 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); | 604 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); |
602 | return; | 605 | return; |
603 | } | 606 | } |
@@ -605,9 +608,9 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, | |||
605 | if (channel >= mci->csrows[row].nr_channels || channel < 0) { | 608 | if (channel >= mci->csrows[row].nr_channels || channel < 0) { |
606 | /* something is wrong */ | 609 | /* something is wrong */ |
607 | edac_mc_printk(mci, KERN_ERR, | 610 | edac_mc_printk(mci, KERN_ERR, |
608 | "INTERNAL ERROR: channel out of range " | 611 | "INTERNAL ERROR: channel out of range " |
609 | "(%d >= %d)\n", channel, | 612 | "(%d >= %d)\n", channel, |
610 | mci->csrows[row].nr_channels); | 613 | mci->csrows[row].nr_channels); |
611 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); | 614 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); |
612 | return; | 615 | return; |
613 | } | 616 | } |
@@ -615,11 +618,11 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, | |||
615 | if (edac_mc_get_log_ce()) | 618 | if (edac_mc_get_log_ce()) |
616 | /* FIXME - put in DIMM location */ | 619 | /* FIXME - put in DIMM location */ |
617 | edac_mc_printk(mci, KERN_WARNING, | 620 | edac_mc_printk(mci, KERN_WARNING, |
618 | "CE page 0x%lx, offset 0x%lx, grain %d, syndrome " | 621 | "CE page 0x%lx, offset 0x%lx, grain %d, syndrome " |
619 | "0x%lx, row %d, channel %d, label \"%s\": %s\n", | 622 | "0x%lx, row %d, channel %d, label \"%s\": %s\n", |
620 | page_frame_number, offset_in_page, | 623 | page_frame_number, offset_in_page, |
621 | mci->csrows[row].grain, syndrome, row, channel, | 624 | mci->csrows[row].grain, syndrome, row, channel, |
622 | mci->csrows[row].channels[channel].label, msg); | 625 | mci->csrows[row].channels[channel].label, msg); |
623 | 626 | ||
624 | mci->ce_count++; | 627 | mci->ce_count++; |
625 | mci->csrows[row].ce_count++; | 628 | mci->csrows[row].ce_count++; |
@@ -640,25 +643,27 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci, | |||
640 | page_frame_number; | 643 | page_frame_number; |
641 | 644 | ||
642 | edac_mc_scrub_block(remapped_page, offset_in_page, | 645 | edac_mc_scrub_block(remapped_page, offset_in_page, |
643 | mci->csrows[row].grain); | 646 | mci->csrows[row].grain); |
644 | } | 647 | } |
645 | } | 648 | } |
649 | |||
646 | EXPORT_SYMBOL_GPL(edac_mc_handle_ce); | 650 | EXPORT_SYMBOL_GPL(edac_mc_handle_ce); |
647 | 651 | ||
648 | void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) | 652 | void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) |
649 | { | 653 | { |
650 | if (edac_mc_get_log_ce()) | 654 | if (edac_mc_get_log_ce()) |
651 | edac_mc_printk(mci, KERN_WARNING, | 655 | edac_mc_printk(mci, KERN_WARNING, |
652 | "CE - no information available: %s\n", msg); | 656 | "CE - no information available: %s\n", msg); |
653 | 657 | ||
654 | mci->ce_noinfo_count++; | 658 | mci->ce_noinfo_count++; |
655 | mci->ce_count++; | 659 | mci->ce_count++; |
656 | } | 660 | } |
661 | |||
657 | EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info); | 662 | EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info); |
658 | 663 | ||
659 | void edac_mc_handle_ue(struct mem_ctl_info *mci, | 664 | void edac_mc_handle_ue(struct mem_ctl_info *mci, |
660 | unsigned long page_frame_number, unsigned long offset_in_page, | 665 | unsigned long page_frame_number, |
661 | int row, const char *msg) | 666 | unsigned long offset_in_page, int row, const char *msg) |
662 | { | 667 | { |
663 | int len = EDAC_MC_LABEL_LEN * 4; | 668 | int len = EDAC_MC_LABEL_LEN * 4; |
664 | char labels[len + 1]; | 669 | char labels[len + 1]; |
@@ -672,41 +677,42 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci, | |||
672 | if (row >= mci->nr_csrows || row < 0) { | 677 | if (row >= mci->nr_csrows || row < 0) { |
673 | /* something is wrong */ | 678 | /* something is wrong */ |
674 | edac_mc_printk(mci, KERN_ERR, | 679 | edac_mc_printk(mci, KERN_ERR, |
675 | "INTERNAL ERROR: row out of range " | 680 | "INTERNAL ERROR: row out of range " |
676 | "(%d >= %d)\n", row, mci->nr_csrows); | 681 | "(%d >= %d)\n", row, mci->nr_csrows); |
677 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); | 682 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); |
678 | return; | 683 | return; |
679 | } | 684 | } |
680 | 685 | ||
681 | chars = snprintf(pos, len + 1, "%s", | 686 | chars = snprintf(pos, len + 1, "%s", |
682 | mci->csrows[row].channels[0].label); | 687 | mci->csrows[row].channels[0].label); |
683 | len -= chars; | 688 | len -= chars; |
684 | pos += chars; | 689 | pos += chars; |
685 | 690 | ||
686 | for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0); | 691 | for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0); |
687 | chan++) { | 692 | chan++) { |
688 | chars = snprintf(pos, len + 1, ":%s", | 693 | chars = snprintf(pos, len + 1, ":%s", |
689 | mci->csrows[row].channels[chan].label); | 694 | mci->csrows[row].channels[chan].label); |
690 | len -= chars; | 695 | len -= chars; |
691 | pos += chars; | 696 | pos += chars; |
692 | } | 697 | } |
693 | 698 | ||
694 | if (edac_mc_get_log_ue()) | 699 | if (edac_mc_get_log_ue()) |
695 | edac_mc_printk(mci, KERN_EMERG, | 700 | edac_mc_printk(mci, KERN_EMERG, |
696 | "UE page 0x%lx, offset 0x%lx, grain %d, row %d, " | 701 | "UE page 0x%lx, offset 0x%lx, grain %d, row %d, " |
697 | "labels \"%s\": %s\n", page_frame_number, | 702 | "labels \"%s\": %s\n", page_frame_number, |
698 | offset_in_page, mci->csrows[row].grain, row, labels, | 703 | offset_in_page, mci->csrows[row].grain, row, |
699 | msg); | 704 | labels, msg); |
700 | 705 | ||
701 | if (edac_mc_get_panic_on_ue()) | 706 | if (edac_mc_get_panic_on_ue()) |
702 | panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, " | 707 | panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, " |
703 | "row %d, labels \"%s\": %s\n", mci->mc_idx, | 708 | "row %d, labels \"%s\": %s\n", mci->mc_idx, |
704 | page_frame_number, offset_in_page, | 709 | page_frame_number, offset_in_page, |
705 | mci->csrows[row].grain, row, labels, msg); | 710 | mci->csrows[row].grain, row, labels, msg); |
706 | 711 | ||
707 | mci->ue_count++; | 712 | mci->ue_count++; |
708 | mci->csrows[row].ue_count++; | 713 | mci->csrows[row].ue_count++; |
709 | } | 714 | } |
715 | |||
710 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue); | 716 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue); |
711 | 717 | ||
712 | void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) | 718 | void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) |
@@ -716,22 +722,21 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) | |||
716 | 722 | ||
717 | if (edac_mc_get_log_ue()) | 723 | if (edac_mc_get_log_ue()) |
718 | edac_mc_printk(mci, KERN_WARNING, | 724 | edac_mc_printk(mci, KERN_WARNING, |
719 | "UE - no information available: %s\n", msg); | 725 | "UE - no information available: %s\n", msg); |
720 | mci->ue_noinfo_count++; | 726 | mci->ue_noinfo_count++; |
721 | mci->ue_count++; | 727 | mci->ue_count++; |
722 | } | 728 | } |
723 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); | ||
724 | 729 | ||
730 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); | ||
725 | 731 | ||
726 | /************************************************************* | 732 | /************************************************************* |
727 | * On Fully Buffered DIMM modules, this help function is | 733 | * On Fully Buffered DIMM modules, this help function is |
728 | * called to process UE events | 734 | * called to process UE events |
729 | */ | 735 | */ |
730 | void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, | 736 | void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, |
731 | unsigned int csrow, | 737 | unsigned int csrow, |
732 | unsigned int channela, | 738 | unsigned int channela, |
733 | unsigned int channelb, | 739 | unsigned int channelb, char *msg) |
734 | char *msg) | ||
735 | { | 740 | { |
736 | int len = EDAC_MC_LABEL_LEN * 4; | 741 | int len = EDAC_MC_LABEL_LEN * 4; |
737 | char labels[len + 1]; | 742 | char labels[len + 1]; |
@@ -741,8 +746,8 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, | |||
741 | if (csrow >= mci->nr_csrows) { | 746 | if (csrow >= mci->nr_csrows) { |
742 | /* something is wrong */ | 747 | /* something is wrong */ |
743 | edac_mc_printk(mci, KERN_ERR, | 748 | edac_mc_printk(mci, KERN_ERR, |
744 | "INTERNAL ERROR: row out of range (%d >= %d)\n", | 749 | "INTERNAL ERROR: row out of range (%d >= %d)\n", |
745 | csrow, mci->nr_csrows); | 750 | csrow, mci->nr_csrows); |
746 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); | 751 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); |
747 | return; | 752 | return; |
748 | } | 753 | } |
@@ -750,9 +755,9 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, | |||
750 | if (channela >= mci->csrows[csrow].nr_channels) { | 755 | if (channela >= mci->csrows[csrow].nr_channels) { |
751 | /* something is wrong */ | 756 | /* something is wrong */ |
752 | edac_mc_printk(mci, KERN_ERR, | 757 | edac_mc_printk(mci, KERN_ERR, |
753 | "INTERNAL ERROR: channel-a out of range " | 758 | "INTERNAL ERROR: channel-a out of range " |
754 | "(%d >= %d)\n", | 759 | "(%d >= %d)\n", |
755 | channela, mci->csrows[csrow].nr_channels); | 760 | channela, mci->csrows[csrow].nr_channels); |
756 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); | 761 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); |
757 | return; | 762 | return; |
758 | } | 763 | } |
@@ -760,9 +765,9 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, | |||
760 | if (channelb >= mci->csrows[csrow].nr_channels) { | 765 | if (channelb >= mci->csrows[csrow].nr_channels) { |
761 | /* something is wrong */ | 766 | /* something is wrong */ |
762 | edac_mc_printk(mci, KERN_ERR, | 767 | edac_mc_printk(mci, KERN_ERR, |
763 | "INTERNAL ERROR: channel-b out of range " | 768 | "INTERNAL ERROR: channel-b out of range " |
764 | "(%d >= %d)\n", | 769 | "(%d >= %d)\n", |
765 | channelb, mci->csrows[csrow].nr_channels); | 770 | channelb, mci->csrows[csrow].nr_channels); |
766 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); | 771 | edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR"); |
767 | return; | 772 | return; |
768 | } | 773 | } |
@@ -773,21 +778,23 @@ void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, | |||
773 | /* Generate the DIMM labels from the specified channels */ | 778 | /* Generate the DIMM labels from the specified channels */ |
774 | chars = snprintf(pos, len + 1, "%s", | 779 | chars = snprintf(pos, len + 1, "%s", |
775 | mci->csrows[csrow].channels[channela].label); | 780 | mci->csrows[csrow].channels[channela].label); |
776 | len -= chars; pos += chars; | 781 | len -= chars; |
782 | pos += chars; | ||
777 | chars = snprintf(pos, len + 1, "-%s", | 783 | chars = snprintf(pos, len + 1, "-%s", |
778 | mci->csrows[csrow].channels[channelb].label); | 784 | mci->csrows[csrow].channels[channelb].label); |
779 | 785 | ||
780 | if (edac_mc_get_log_ue()) | 786 | if (edac_mc_get_log_ue()) |
781 | edac_mc_printk(mci, KERN_EMERG, | 787 | edac_mc_printk(mci, KERN_EMERG, |
782 | "UE row %d, channel-a= %d channel-b= %d " | 788 | "UE row %d, channel-a= %d channel-b= %d " |
783 | "labels \"%s\": %s\n", csrow, channela, channelb, | 789 | "labels \"%s\": %s\n", csrow, channela, channelb, |
784 | labels, msg); | 790 | labels, msg); |
785 | 791 | ||
786 | if (edac_mc_get_panic_on_ue()) | 792 | if (edac_mc_get_panic_on_ue()) |
787 | panic("UE row %d, channel-a= %d channel-b= %d " | 793 | panic("UE row %d, channel-a= %d channel-b= %d " |
788 | "labels \"%s\": %s\n", csrow, channela, | 794 | "labels \"%s\": %s\n", csrow, channela, |
789 | channelb, labels, msg); | 795 | channelb, labels, msg); |
790 | } | 796 | } |
797 | |||
791 | EXPORT_SYMBOL(edac_mc_handle_fbd_ue); | 798 | EXPORT_SYMBOL(edac_mc_handle_fbd_ue); |
792 | 799 | ||
793 | /************************************************************* | 800 | /************************************************************* |
@@ -795,25 +802,23 @@ EXPORT_SYMBOL(edac_mc_handle_fbd_ue); | |||
795 | * called to process CE events | 802 | * called to process CE events |
796 | */ | 803 | */ |
797 | void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci, | 804 | void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci, |
798 | unsigned int csrow, | 805 | unsigned int csrow, unsigned int channel, char *msg) |
799 | unsigned int channel, | ||
800 | char *msg) | ||
801 | { | 806 | { |
802 | 807 | ||
803 | /* Ensure boundary values */ | 808 | /* Ensure boundary values */ |
804 | if (csrow >= mci->nr_csrows) { | 809 | if (csrow >= mci->nr_csrows) { |
805 | /* something is wrong */ | 810 | /* something is wrong */ |
806 | edac_mc_printk(mci, KERN_ERR, | 811 | edac_mc_printk(mci, KERN_ERR, |
807 | "INTERNAL ERROR: row out of range (%d >= %d)\n", | 812 | "INTERNAL ERROR: row out of range (%d >= %d)\n", |
808 | csrow, mci->nr_csrows); | 813 | csrow, mci->nr_csrows); |
809 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); | 814 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); |
810 | return; | 815 | return; |
811 | } | 816 | } |
812 | if (channel >= mci->csrows[csrow].nr_channels) { | 817 | if (channel >= mci->csrows[csrow].nr_channels) { |
813 | /* something is wrong */ | 818 | /* something is wrong */ |
814 | edac_mc_printk(mci, KERN_ERR, | 819 | edac_mc_printk(mci, KERN_ERR, |
815 | "INTERNAL ERROR: channel out of range (%d >= %d)\n", | 820 | "INTERNAL ERROR: channel out of range (%d >= %d)\n", |
816 | channel, mci->csrows[csrow].nr_channels); | 821 | channel, mci->csrows[csrow].nr_channels); |
817 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); | 822 | edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR"); |
818 | return; | 823 | return; |
819 | } | 824 | } |
@@ -821,17 +826,16 @@ void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci, | |||
821 | if (edac_mc_get_log_ce()) | 826 | if (edac_mc_get_log_ce()) |
822 | /* FIXME - put in DIMM location */ | 827 | /* FIXME - put in DIMM location */ |
823 | edac_mc_printk(mci, KERN_WARNING, | 828 | edac_mc_printk(mci, KERN_WARNING, |
824 | "CE row %d, channel %d, label \"%s\": %s\n", | 829 | "CE row %d, channel %d, label \"%s\": %s\n", |
825 | csrow, channel, | 830 | csrow, channel, |
826 | mci->csrows[csrow].channels[channel].label, | 831 | mci->csrows[csrow].channels[channel].label, msg); |
827 | msg); | ||
828 | 832 | ||
829 | mci->ce_count++; | 833 | mci->ce_count++; |
830 | mci->csrows[csrow].ce_count++; | 834 | mci->csrows[csrow].ce_count++; |
831 | mci->csrows[csrow].channels[channel].ce_count++; | 835 | mci->csrows[csrow].channels[channel].ce_count++; |
832 | } | 836 | } |
833 | EXPORT_SYMBOL(edac_mc_handle_fbd_ce); | ||
834 | 837 | ||
838 | EXPORT_SYMBOL(edac_mc_handle_fbd_ce); | ||
835 | 839 | ||
836 | /* | 840 | /* |
837 | * Iterate over all MC instances and check for ECC, et al, errors | 841 | * Iterate over all MC instances and check for ECC, et al, errors |