aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2007-02-17 15:09:59 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-17 15:09:59 -0500
commit48c871c1f6a7c7044dd76774fb469e65c7e2e4e8 (patch)
treeda3aa535c98cc0957851354ceb0fbff7482d7a9d /drivers/edac
parent1a1689344add3333d28d1b5495d8043a3877d01c (diff)
parent4409d28140d9a6e6e3f4f1fdaf7234c4b965d954 (diff)
Merge branch 'gfar' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc into upstream
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/e752x_edac.c40
-rw-r--r--drivers/edac/edac_mc.c175
-rw-r--r--drivers/edac/edac_mc.h28
3 files changed, 222 insertions, 21 deletions
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c
index c82bc0ed7f14..8bcc887692ab 100644
--- a/drivers/edac/e752x_edac.c
+++ b/drivers/edac/e752x_edac.c
@@ -285,8 +285,9 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
285 if (!pvt->map_type) 285 if (!pvt->map_type)
286 row = 7 - row; 286 row = 7 - row;
287 287
288 edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel, 288 /* e752x mc reads 34:6 of the DRAM linear address */
289 "e752x CE"); 289 edac_mc_handle_ce(mci, page, offset_in_page(sec1_add << 4),
290 sec1_syndrome, row, channel, "e752x CE");
290} 291}
291 292
292static inline void process_ce(struct mem_ctl_info *mci, u16 error_one, 293static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
@@ -319,8 +320,10 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
319 ((block_page >> 1) & 3) : 320 ((block_page >> 1) & 3) :
320 edac_mc_find_csrow_by_page(mci, block_page); 321 edac_mc_find_csrow_by_page(mci, block_page);
321 322
322 edac_mc_handle_ue(mci, block_page, 0, row, 323 /* e752x mc reads 34:6 of the DRAM linear address */
323 "e752x UE from Read"); 324 edac_mc_handle_ue(mci, block_page,
325 offset_in_page(error_2b << 4),
326 row, "e752x UE from Read");
324 } 327 }
325 if (error_one & 0x0404) { 328 if (error_one & 0x0404) {
326 error_2b = scrb_add; 329 error_2b = scrb_add;
@@ -333,8 +336,10 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
333 ((block_page >> 1) & 3) : 336 ((block_page >> 1) & 3) :
334 edac_mc_find_csrow_by_page(mci, block_page); 337 edac_mc_find_csrow_by_page(mci, block_page);
335 338
336 edac_mc_handle_ue(mci, block_page, 0, row, 339 /* e752x mc reads 34:6 of the DRAM linear address */
337 "e752x UE from Scruber"); 340 edac_mc_handle_ue(mci, block_page,
341 offset_in_page(error_2b << 4),
342 row, "e752x UE from Scruber");
338 } 343 }
339} 344}
340 345
@@ -556,17 +561,17 @@ static void e752x_check_sysbus(struct e752x_error_info *info,
556 error32 = (stat32 >> 16) & 0x3ff; 561 error32 = (stat32 >> 16) & 0x3ff;
557 stat32 = stat32 & 0x3ff; 562 stat32 = stat32 & 0x3ff;
558 563
559 if(stat32 & 0x083) 564 if(stat32 & 0x087)
560 sysbus_error(1, stat32 & 0x083, error_found, handle_error); 565 sysbus_error(1, stat32 & 0x087, error_found, handle_error);
561 566
562 if(stat32 & 0x37c) 567 if(stat32 & 0x378)
563 sysbus_error(0, stat32 & 0x37c, error_found, handle_error); 568 sysbus_error(0, stat32 & 0x378, error_found, handle_error);
564 569
565 if(error32 & 0x083) 570 if(error32 & 0x087)
566 sysbus_error(1, error32 & 0x083, error_found, handle_error); 571 sysbus_error(1, error32 & 0x087, error_found, handle_error);
567 572
568 if(error32 & 0x37c) 573 if(error32 & 0x378)
569 sysbus_error(0, error32 & 0x37c, error_found, handle_error); 574 sysbus_error(0, error32 & 0x378, error_found, handle_error);
570} 575}
571 576
572static void e752x_check_membuf (struct e752x_error_info *info, 577static void e752x_check_membuf (struct e752x_error_info *info,
@@ -782,7 +787,12 @@ static void e752x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev,
782 u8 value; 787 u8 value;
783 u32 dra, drc, cumul_size; 788 u32 dra, drc, cumul_size;
784 789
785 pci_read_config_dword(pdev, E752X_DRA, &dra); 790 dra = 0;
791 for (index=0; index < 4; index++) {
792 u8 dra_reg;
793 pci_read_config_byte(pdev, E752X_DRA+index, &dra_reg);
794 dra |= dra_reg << (index * 8);
795 }
786 pci_read_config_dword(pdev, E752X_DRC, &drc); 796 pci_read_config_dword(pdev, E752X_DRC, &drc);
787 drc_chan = dual_channel_active(ddrcsr); 797 drc_chan = dual_channel_active(ddrcsr);
788 drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */ 798 drc_drbg = drc_chan + 1; /* 128 in dual mode, 64 in single */
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 1b4fc9221803..7b622300d0e5 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -927,6 +927,57 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
927 return count; 927 return count;
928} 928}
929 929
930/* memory scrubbing */
931static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
932 const char *data, size_t count)
933{
934 u32 bandwidth = -1;
935
936 if (mci->set_sdram_scrub_rate) {
937
938 memctrl_int_store(&bandwidth, data, count);
939
940 if (!(*mci->set_sdram_scrub_rate)(mci, &bandwidth)) {
941 edac_printk(KERN_DEBUG, EDAC_MC,
942 "Scrub rate set successfully, applied: %d\n",
943 bandwidth);
944 } else {
945 /* FIXME: error codes maybe? */
946 edac_printk(KERN_DEBUG, EDAC_MC,
947 "Scrub rate set FAILED, could not apply: %d\n",
948 bandwidth);
949 }
950 } else {
951 /* FIXME: produce "not implemented" ERROR for user-side. */
952 edac_printk(KERN_WARNING, EDAC_MC,
953 "Memory scrubbing 'set'control is not implemented!\n");
954 }
955 return count;
956}
957
958static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
959{
960 u32 bandwidth = -1;
961
962 if (mci->get_sdram_scrub_rate) {
963 if (!(*mci->get_sdram_scrub_rate)(mci, &bandwidth)) {
964 edac_printk(KERN_DEBUG, EDAC_MC,
965 "Scrub rate successfully, fetched: %d\n",
966 bandwidth);
967 } else {
968 /* FIXME: error codes maybe? */
969 edac_printk(KERN_DEBUG, EDAC_MC,
970 "Scrub rate fetch FAILED, got: %d\n",
971 bandwidth);
972 }
973 } else {
974 /* FIXME: produce "not implemented" ERROR for user-side. */
975 edac_printk(KERN_WARNING, EDAC_MC,
976 "Memory scrubbing 'get' control is not implemented!\n");
977 }
978 return sprintf(data, "%d\n", bandwidth);
979}
980
930/* default attribute files for the MCI object */ 981/* default attribute files for the MCI object */
931static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data) 982static ssize_t mci_ue_count_show(struct mem_ctl_info *mci, char *data)
932{ 983{
@@ -1033,6 +1084,9 @@ MCIDEV_ATTR(ce_noinfo_count,S_IRUGO,mci_ce_noinfo_show,NULL);
1033MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL); 1084MCIDEV_ATTR(ue_count,S_IRUGO,mci_ue_count_show,NULL);
1034MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL); 1085MCIDEV_ATTR(ce_count,S_IRUGO,mci_ce_count_show,NULL);
1035 1086
1087/* memory scrubber attribute file */
1088MCIDEV_ATTR(sdram_scrub_rate,S_IRUGO|S_IWUSR,mci_sdram_scrub_rate_show,mci_sdram_scrub_rate_store);
1089
1036static struct mcidev_attribute *mci_attr[] = { 1090static struct mcidev_attribute *mci_attr[] = {
1037 &mci_attr_reset_counters, 1091 &mci_attr_reset_counters,
1038 &mci_attr_mc_name, 1092 &mci_attr_mc_name,
@@ -1042,6 +1096,7 @@ static struct mcidev_attribute *mci_attr[] = {
1042 &mci_attr_ce_noinfo_count, 1096 &mci_attr_ce_noinfo_count,
1043 &mci_attr_ue_count, 1097 &mci_attr_ue_count,
1044 &mci_attr_ce_count, 1098 &mci_attr_ce_count,
1099 &mci_attr_sdram_scrub_rate,
1045 NULL 1100 NULL
1046}; 1101};
1047 1102
@@ -1442,11 +1497,11 @@ int edac_mc_add_mc(struct mem_ctl_info *mci, int mc_idx)
1442 /* set load time so that error rate can be tracked */ 1497 /* set load time so that error rate can be tracked */
1443 mci->start_time = jiffies; 1498 mci->start_time = jiffies;
1444 1499
1445 if (edac_create_sysfs_mci_device(mci)) { 1500 if (edac_create_sysfs_mci_device(mci)) {
1446 edac_mc_printk(mci, KERN_WARNING, 1501 edac_mc_printk(mci, KERN_WARNING,
1447 "failed to create sysfs device\n"); 1502 "failed to create sysfs device\n");
1448 goto fail1; 1503 goto fail1;
1449 } 1504 }
1450 1505
1451 /* Report action taken */ 1506 /* Report action taken */
1452 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",
@@ -1703,6 +1758,116 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
1703EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); 1758EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info);
1704 1759
1705 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
1706/* 1871/*
1707 * 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
1708 */ 1873 */
@@ -1806,7 +1971,7 @@ static void __exit edac_mc_exit(void)
1806 debugf0("%s()\n", __func__); 1971 debugf0("%s()\n", __func__);
1807 kthread_stop(edac_thread); 1972 kthread_stop(edac_thread);
1808 1973
1809 /* tear down the sysfs device */ 1974 /* tear down the sysfs device */
1810 edac_sysfs_memctrl_teardown(); 1975 edac_sysfs_memctrl_teardown();
1811 edac_sysfs_pci_teardown(); 1976 edac_sysfs_pci_teardown();
1812} 1977}
diff --git a/drivers/edac/edac_mc.h b/drivers/edac/edac_mc.h
index a1cfd4e3c97d..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 {
@@ -315,8 +319,21 @@ struct mem_ctl_info {
315 unsigned long scrub_cap; /* chipset scrub capabilities */ 319 unsigned long scrub_cap; /* chipset scrub capabilities */
316 enum scrub_type scrub_mode; /* current scrub mode */ 320 enum scrub_type scrub_mode; /* current scrub mode */
317 321
322 /* Translates sdram memory scrub rate given in bytes/sec to the
323 internal representation and configures whatever else needs
324 to be configured.
325 */
326 int (*set_sdram_scrub_rate) (struct mem_ctl_info *mci, u32 *bw);
327
328 /* Get the current sdram memory scrub rate from the internal
329 representation and converts it to the closest matching
330 bandwith in bytes/sec.
331 */
332 int (*get_sdram_scrub_rate) (struct mem_ctl_info *mci, u32 *bw);
333
318 /* pointer to edac checking routine */ 334 /* pointer to edac checking routine */
319 void (*edac_check) (struct mem_ctl_info * mci); 335 void (*edac_check) (struct mem_ctl_info * mci);
336
320 /* 337 /*
321 * Remaps memory pages: controller pages to physical pages. 338 * Remaps memory pages: controller pages to physical pages.
322 * For most MC's, this will be NULL. 339 * For most MC's, this will be NULL.
@@ -441,6 +458,15 @@ extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
441 int row, const char *msg); 458 int row, const char *msg);
442extern 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,
443 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);
444 470
445/* 471/*
446 * This kmalloc's and initializes all the structures. 472 * This kmalloc's and initializes all the structures.