aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/edac_mc.c120
-rw-r--r--drivers/edac/edac_mc.h16
2 files changed, 130 insertions, 6 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 1df8c0c5d40a..7b622300d0e5 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -1497,11 +1497,11 @@ int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx)
1497 /* set load time so that error rate can be tracked */ 1497 /* set load time so that error rate can be tracked */
1498 mci->start_time = jiffies; 1498 mci->start_time = jiffies;
1499 1499
1500 if (edac_create_sysfs_mci_device(mci)) { 1500 if (edac_create_sysfs_mci_device(mci)) {
1501 edac_mc_printk(mci, KERN_WARNING, 1501 edac_mc_printk(mci, KERN_WARNING,
1502 "failed to create sysfs device\n"); 1502 "failed to create sysfs device\n");
1503 goto fail1; 1503 goto fail1;
1504 } 1504 }
1505 1505
1506 /* Report action taken */ 1506 /* Report action taken */
1507 edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n", 1507 edac_mc_printk(mci, KERN_INFO, "Giving out device to %s %s: DEV %s\n",
@@ -1758,6 +1758,116 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
1758EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); 1758EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
1759 1759
1760 1760
1761/*************************************************************
1762 * On Fully Buffered DIMM modules, this help function is
1763 * called to process UE events
1764 */
1765void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
1766 unsigned int csrow,
1767 unsigned int channela,
1768 unsigned int channelb,
1769 char *msg)
1770{
1771 int len = EDAC_MC_LABEL_LEN * 4;
1772 char labels[len + 1];
1773 char *pos = labels;
1774 int chars;
1775
1776 if (csrow >= mci->nr_csrows) {
1777 /* something is wrong */
1778 edac_mc_printk(mci, KERN_ERR,
1779 "INTERNAL ERROR: row out of range (%d >= %d)\n",
1780 csrow, mci->nr_csrows);
1781 edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
1782 return;
1783 }
1784
1785 if (channela >= mci->csrows[csrow].nr_channels) {
1786 /* something is wrong */
1787 edac_mc_printk(mci, KERN_ERR,
1788 "INTERNAL ERROR: channel-a out of range "
1789 "(%d >= %d)\n",
1790 channela, mci->csrows[csrow].nr_channels);
1791 edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
1792 return;
1793 }
1794
1795 if (channelb >= mci->csrows[csrow].nr_channels) {
1796 /* something is wrong */
1797 edac_mc_printk(mci, KERN_ERR,
1798 "INTERNAL ERROR: channel-b out of range "
1799 "(%d >= %d)\n",
1800 channelb, mci->csrows[csrow].nr_channels);
1801 edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
1802 return;
1803 }
1804
1805 mci->ue_count++;
1806 mci->csrows[csrow].ue_count++;
1807
1808 /* Generate the DIMM labels from the specified channels */
1809 chars = snprintf(pos, len + 1, "%s",
1810 mci->csrows[csrow].channels[channela].label);
1811 len -= chars; pos += chars;
1812 chars = snprintf(pos, len + 1, "-%s",
1813 mci->csrows[csrow].channels[channelb].label);
1814
1815 if (log_ue)
1816 edac_mc_printk(mci, KERN_EMERG,
1817 "UE row %d, channel-a= %d channel-b= %d "
1818 "labels \"%s\": %s\n", csrow, channela, channelb,
1819 labels, msg);
1820
1821 if (panic_on_ue)
1822 panic("UE row %d, channel-a= %d channel-b= %d "
1823 "labels \"%s\": %s\n", csrow, channela,
1824 channelb, labels, msg);
1825}
1826EXPORT_SYMBOL(edac_mc_handle_fbd_ue);
1827
1828/*************************************************************
1829 * On Fully Buffered DIMM modules, this help function is
1830 * called to process CE events
1831 */
1832void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
1833 unsigned int csrow,
1834 unsigned int channel,
1835 char *msg)
1836{
1837
1838 /* Ensure boundary values */
1839 if (csrow >= mci->nr_csrows) {
1840 /* something is wrong */
1841 edac_mc_printk(mci, KERN_ERR,
1842 "INTERNAL ERROR: row out of range (%d >= %d)\n",
1843 csrow, mci->nr_csrows);
1844 edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
1845 return;
1846 }
1847 if (channel >= mci->csrows[csrow].nr_channels) {
1848 /* something is wrong */
1849 edac_mc_printk(mci, KERN_ERR,
1850 "INTERNAL ERROR: channel out of range (%d >= %d)\n",
1851 channel, mci->csrows[csrow].nr_channels);
1852 edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
1853 return;
1854 }
1855
1856 if (log_ce)
1857 /* FIXME - put in DIMM location */
1858 edac_mc_printk(mci, KERN_WARNING,
1859 "CE row %d, channel %d, label \"%s\": %s\n",
1860 csrow, channel,
1861 mci->csrows[csrow].channels[channel].label,
1862 msg);
1863
1864 mci->ce_count++;
1865 mci->csrows[csrow].ce_count++;
1866 mci->csrows[csrow].channels[channel].ce_count++;
1867}
1868EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
1869
1870
1761/* 1871/*
1762 * Iterate over all MC instances and check for ECC, et al, errors 1872 * Iterate over all MC instances and check for ECC, et al, errors
1763 */ 1873 */
@@ -1861,7 +1971,7 @@ static void __exit edac_mc_exit(void)
1861 debugf0("%s()\n", __func__); 1971 debugf0("%s()\n", __func__);
1862 kthread_stop(edac_thread); 1972 kthread_stop(edac_thread);
1863 1973
1864 /* tear down the sysfs device */ 1974 /* tear down the sysfs device */
1865 edac_sysfs_memctrl_teardown(); 1975 edac_sysfs_memctrl_teardown();
1866 edac_sysfs_pci_teardown(); 1976 edac_sysfs_pci_teardown();
1867} 1977}
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index c41986a9ed5b..713444cc4105 100644
--- a/drivers/edac/edac_mc.h
+++ b/drivers/edac/edac_mc.h
@@ -123,7 +123,9 @@ enum mem_type {
123 MEM_RDR, /* Registered single data rate SDRAM */ 123 MEM_RDR, /* Registered single data rate SDRAM */
124 MEM_DDR, /* Double data rate SDRAM */ 124 MEM_DDR, /* Double data rate SDRAM */
125 MEM_RDDR, /* Registered Double data rate SDRAM */ 125 MEM_RDDR, /* Registered Double data rate SDRAM */
126 MEM_RMBS /* Rambus DRAM */ 126 MEM_RMBS, /* Rambus DRAM */
127 MEM_DDR2, /* DDR2 RAM */
128 MEM_FB_DDR2, /* fully buffered DDR2 */
127}; 129};
128 130
129#define MEM_FLAG_EMPTY BIT(MEM_EMPTY) 131#define MEM_FLAG_EMPTY BIT(MEM_EMPTY)
@@ -137,6 +139,8 @@ enum mem_type {
137#define MEM_FLAG_DDR BIT(MEM_DDR) 139#define MEM_FLAG_DDR BIT(MEM_DDR)
138#define MEM_FLAG_RDDR BIT(MEM_RDDR) 140#define MEM_FLAG_RDDR BIT(MEM_RDDR)
139#define MEM_FLAG_RMBS BIT(MEM_RMBS) 141#define MEM_FLAG_RMBS BIT(MEM_RMBS)
142#define MEM_FLAG_DDR2 BIT(MEM_DDR2)
143#define MEM_FLAG_FB_DDR2 BIT(MEM_FB_DDR2)
140 144
141/* chipset Error Detection and Correction capabilities and mode */ 145/* chipset Error Detection and Correction capabilities and mode */
142enum edac_type { 146enum edac_type {
@@ -329,6 +333,7 @@ struct mem_ctl_info {
329 333
330 /* pointer to edac checking routine */ 334 /* pointer to edac checking routine */
331 void (*edac_check) (struct mem_ctl_info * mci); 335 void (*edac_check) (struct mem_ctl_info * mci);
336
332 /* 337 /*
333 * Remaps memory pages: controller pages to physical pages. 338 * Remaps memory pages: controller pages to physical pages.
334 * For most MC's, this will be NULL. 339 * For most MC's, this will be NULL.
@@ -453,6 +458,15 @@ extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
453 int row, const char *msg); 458 int row, const char *msg);
454extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, 459extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
455 const char *msg); 460 const char *msg);
461extern void edac_mc_handle_fbd_ue(struct mem_ctl_info *mci,
462 unsigned int csrow,
463 unsigned int channel0,
464 unsigned int channel1,
465 char *msg);
466extern void edac_mc_handle_fbd_ce(struct mem_ctl_info *mci,
467 unsigned int csrow,
468 unsigned int channel,
469 char *msg);
456 470
457/* 471/*
458 * This kmalloc's and initializes all the structures. 472 * This kmalloc's and initializes all the structures.