diff options
| -rw-r--r-- | drivers/edac/ghes_edac.c | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index d8e54b496e0f..0853f450d2c1 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c | |||
| @@ -27,8 +27,60 @@ static DEFINE_MUTEX(ghes_edac_lock); | |||
| 27 | static int ghes_edac_mc_num; | 27 | static int ghes_edac_mc_num; |
| 28 | 28 | ||
| 29 | void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | 29 | void ghes_edac_report_mem_error(struct ghes *ghes, int sev, |
| 30 | struct cper_sec_mem_err *mem_err) | 30 | struct cper_sec_mem_err *mem_err) |
| 31 | { | 31 | { |
| 32 | enum hw_event_mc_err_type type; | ||
| 33 | struct edac_raw_error_desc *e; | ||
| 34 | struct mem_ctl_info *mci; | ||
| 35 | struct ghes_edac_pvt *pvt = NULL; | ||
| 36 | |||
| 37 | list_for_each_entry(pvt, &ghes_reglist, list) { | ||
| 38 | if (ghes == pvt->ghes) | ||
| 39 | break; | ||
| 40 | } | ||
| 41 | if (!pvt) { | ||
| 42 | pr_err("Internal error: Can't find EDAC structure\n"); | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | mci = pvt->mci; | ||
| 46 | e = &mci->error_desc; | ||
| 47 | |||
| 48 | /* Cleans the error report buffer */ | ||
| 49 | memset(e, 0, sizeof (*e)); | ||
| 50 | e->error_count = 1; | ||
| 51 | e->msg = "APEI"; | ||
| 52 | strcpy(e->label, "unknown"); | ||
| 53 | e->other_detail = ""; | ||
| 54 | |||
| 55 | if (mem_err->validation_bits & CPER_MEM_VALID_PHYSICAL_ADDRESS) { | ||
| 56 | e->page_frame_number = mem_err->physical_addr >> PAGE_SHIFT; | ||
| 57 | e->offset_in_page = mem_err->physical_addr & ~PAGE_MASK; | ||
| 58 | e->grain = ~(mem_err->physical_addr_mask & ~PAGE_MASK); | ||
| 59 | } | ||
| 60 | |||
| 61 | switch (sev) { | ||
| 62 | case GHES_SEV_CORRECTED: | ||
| 63 | type = HW_EVENT_ERR_CORRECTED; | ||
| 64 | break; | ||
| 65 | case GHES_SEV_RECOVERABLE: | ||
| 66 | type = HW_EVENT_ERR_UNCORRECTED; | ||
| 67 | break; | ||
| 68 | case GHES_SEV_PANIC: | ||
| 69 | type = HW_EVENT_ERR_FATAL; | ||
| 70 | break; | ||
| 71 | default: | ||
| 72 | case GHES_SEV_NO: | ||
| 73 | type = HW_EVENT_ERR_INFO; | ||
| 74 | } | ||
| 75 | |||
| 76 | sprintf(e->location, | ||
| 77 | "node:%d card:%d module:%d bank:%d device:%d row: %d column:%d bit_pos:%d", | ||
| 78 | mem_err->node, mem_err->card, mem_err->module, | ||
| 79 | mem_err->bank, mem_err->device, mem_err->row, mem_err->column, | ||
| 80 | mem_err->bit_pos); | ||
| 81 | edac_dbg(3, "error at location %s\n", e->location); | ||
| 82 | |||
| 83 | edac_raw_mc_handle_error(type, mci, e); | ||
| 32 | } | 84 | } |
| 33 | EXPORT_SYMBOL_GPL(ghes_edac_report_mem_error); | 85 | EXPORT_SYMBOL_GPL(ghes_edac_report_mem_error); |
| 34 | 86 | ||
| @@ -60,7 +112,7 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev) | |||
| 60 | 112 | ||
| 61 | pvt = mci->pvt_info; | 113 | pvt = mci->pvt_info; |
| 62 | memset(pvt, 0, sizeof(*pvt)); | 114 | memset(pvt, 0, sizeof(*pvt)); |
| 63 | list_add_tail(&pvt->list, &ghes_reglist); | 115 | list_add_tail(&pvt->list, &ghes_reglist); |
| 64 | pvt->ghes = ghes; | 116 | pvt->ghes = ghes; |
| 65 | pvt->mci = mci; | 117 | pvt->mci = mci; |
| 66 | mci->pdev = dev; | 118 | mci->pdev = dev; |
