diff options
author | eric wollesen <ericw@xmtp.net> | 2007-02-12 03:53:08 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-12 12:48:32 -0500 |
commit | 9794f33ddedd878dd92fcf8b4834391840366919 (patch) | |
tree | b64ed2488fe95a1217d14704422cc467193f34a3 /drivers/edac/edac_mc.c | |
parent | 4f423ddf56e5ecb1fb2eac83b8e228e3d0aae0f6 (diff) |
[PATCH] EDAC: Add Fully-Buffered DIMM APIs to core
Eric Wollesen ported the Bluesmoke Memory Controller driver for the Intel
5000X/V/P (Blackford/Greencreek) chipset to the in kernel EDAC model.
This patch incorporates those required changes to the edac_mc.c and edac_mc.h
core files by added new Fully Buffered DIMM interface to the EDAC Core module.
Signed-off-by: eric wollesen <ericw@xmtp.net>
Signed-off-by: doug thompson <norsk5@xmission.com>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r-- | drivers/edac/edac_mc.c | 120 |
1 files changed, 115 insertions, 5 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) | |||
1758 | EXPORT_SYMBOL_GPL(edac_mc_handle_ue_no_info); | 1758 | EXPORT_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 | */ | ||
1765 | void 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 | } | ||
1826 | EXPORT_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 | */ | ||
1832 | void 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 | } | ||
1868 | EXPORT_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 | } |