aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/edac_mc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r--drivers/edac/edac_mc.c202
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 */
39static DEFINE_MUTEX(mem_ctls_mutex); 38static DEFINE_MUTEX(mem_ctls_mutex);
40static struct list_head mc_devices = LIST_HEAD_INIT(mc_devices); 39static 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 */
92char * edac_align_ptr(void *ptr, unsigned size) 88char *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 */
135struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows, 131struct 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
191EXPORT_SYMBOL_GPL(edac_mc_alloc); 188EXPORT_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
201EXPORT_SYMBOL_GPL(edac_mc_free); 199EXPORT_SYMBOL_GPL(edac_mc_free);
202 200
203static struct mem_ctl_info *find_mci_by_dev(struct device *dev) 201static 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))
241static void edac_mc_workq_function(struct work_struct *work_req) 239static 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
246static void edac_mc_workq_function(void *ptr) 244static 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 */
323static int add_mc_to_global_list (struct mem_ctl_info *mci) 321static 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
349fail0: 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
355fail1: 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 */
388struct mem_ctl_info * edac_mc_find(int idx) 386struct 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
406EXPORT_SYMBOL(edac_mc_find); 405EXPORT_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
472fail1: 471 fail1:
473 del_mc_from_global_list(mci); 472 del_mc_from_global_list(mci);
474 473
475fail0: 474 fail0:
476 mutex_unlock(&mem_ctls_mutex); 475 mutex_unlock(&mem_ctls_mutex);
477 return 1; 476 return 1;
478} 477}
478
479EXPORT_SYMBOL_GPL(edac_mc_add_mc); 479EXPORT_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 */
488struct mem_ctl_info * edac_mc_del_mc(struct device *dev) 488struct 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
514EXPORT_SYMBOL_GPL(edac_mc_del_mc); 515EXPORT_SYMBOL_GPL(edac_mc_del_mc);
515 516
516static void edac_mc_scrub_block(unsigned long page, unsigned long offset, 517static 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
583EXPORT_SYMBOL_GPL(edac_mc_find_csrow_by_page); 585EXPORT_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/ */
587void edac_mc_handle_ce(struct mem_ctl_info *mci, 589void 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
646EXPORT_SYMBOL_GPL(edac_mc_handle_ce); 650EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
647 651
648void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg) 652void 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
657EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info); 662EXPORT_SYMBOL_GPL(edac_mc_handle_ce_no_info);
658 663
659void edac_mc_handle_ue(struct mem_ctl_info *mci, 664void 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
710EXPORT_SYMBOL_GPL(edac_mc_handle_ue); 716EXPORT_SYMBOL_GPL(edac_mc_handle_ue);
711 717
712void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg) 718void 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}
723EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
724 729
730EXPORT_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 */
730void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci, 736void 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
791EXPORT_SYMBOL(edac_mc_handle_fbd_ue); 798EXPORT_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 */
797void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci, 804void 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}
833EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
834 837
838EXPORT_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