edac_mc.c (a7d7d2e1a07e3811dc49af2962c940fd8bbb6c8f) edac_mc.c (084a4fccef39ac7abb039511f32380f28d0b67e6)
1/*
2 * edac_mc kernel module
3 * (C) 2005, 2006 Linux Networx (http://lnxi.com)
4 * This file may be distributed under the terms of the
5 * GNU General Public License.
6 *
7 * Written by Thayne Harbaugh
8 * Based on work by Dan Hollis <goemon at anime dot net> and others.

--- 29 unchanged lines hidden (view full) ---

38static LIST_HEAD(mc_devices);
39
40#ifdef CONFIG_EDAC_DEBUG
41
42static void edac_mc_dump_channel(struct rank_info *chan)
43{
44 debugf4("\tchannel = %p\n", chan);
45 debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
1/*
2 * edac_mc kernel module
3 * (C) 2005, 2006 Linux Networx (http://lnxi.com)
4 * This file may be distributed under the terms of the
5 * GNU General Public License.
6 *
7 * Written by Thayne Harbaugh
8 * Based on work by Dan Hollis <goemon at anime dot net> and others.

--- 29 unchanged lines hidden (view full) ---

38static LIST_HEAD(mc_devices);
39
40#ifdef CONFIG_EDAC_DEBUG
41
42static void edac_mc_dump_channel(struct rank_info *chan)
43{
44 debugf4("\tchannel = %p\n", chan);
45 debugf4("\tchannel->chan_idx = %d\n", chan->chan_idx);
46 debugf4("\tchannel->ce_count = %d\n", chan->ce_count);
46 debugf4("\tchannel->ce_count = %d\n", chan->dimm->ce_count);
47 debugf4("\tchannel->label = '%s'\n", chan->dimm->label);
48 debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
49}
50
51static void edac_mc_dump_csrow(struct csrow_info *csrow)
52{
53 debugf4("\tcsrow = %p\n", csrow);
54 debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);

--- 635 unchanged lines hidden (view full) ---

690/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
691void edac_mc_handle_ce(struct mem_ctl_info *mci,
692 unsigned long page_frame_number,
693 unsigned long offset_in_page, unsigned long syndrome,
694 int row, int channel, const char *msg)
695{
696 unsigned long remapped_page;
697 char *label = NULL;
47 debugf4("\tchannel->label = '%s'\n", chan->dimm->label);
48 debugf4("\tchannel->csrow = %p\n\n", chan->csrow);
49}
50
51static void edac_mc_dump_csrow(struct csrow_info *csrow)
52{
53 debugf4("\tcsrow = %p\n", csrow);
54 debugf4("\tcsrow->csrow_idx = %d\n", csrow->csrow_idx);

--- 635 unchanged lines hidden (view full) ---

690/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
691void edac_mc_handle_ce(struct mem_ctl_info *mci,
692 unsigned long page_frame_number,
693 unsigned long offset_in_page, unsigned long syndrome,
694 int row, int channel, const char *msg)
695{
696 unsigned long remapped_page;
697 char *label = NULL;
698 u32 grain;
698
699 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
700
701 /* FIXME - maybe make panic on INTERNAL ERROR an option */
702 if (row >= mci->nr_csrows || row < 0) {
703 /* something is wrong */
704 edac_mc_printk(mci, KERN_ERR,
705 "INTERNAL ERROR: row out of range "

--- 8 unchanged lines hidden (view full) ---

714 "INTERNAL ERROR: channel out of range "
715 "(%d >= %d)\n", channel,
716 mci->csrows[row].nr_channels);
717 edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
718 return;
719 }
720
721 label = mci->csrows[row].channels[channel].dimm->label;
699
700 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
701
702 /* FIXME - maybe make panic on INTERNAL ERROR an option */
703 if (row >= mci->nr_csrows || row < 0) {
704 /* something is wrong */
705 edac_mc_printk(mci, KERN_ERR,
706 "INTERNAL ERROR: row out of range "

--- 8 unchanged lines hidden (view full) ---

715 "INTERNAL ERROR: channel out of range "
716 "(%d >= %d)\n", channel,
717 mci->csrows[row].nr_channels);
718 edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
719 return;
720 }
721
722 label = mci->csrows[row].channels[channel].dimm->label;
723 grain = mci->csrows[row].channels[channel].dimm->grain;
722
723 if (edac_mc_get_log_ce())
724 /* FIXME - put in DIMM location */
725 edac_mc_printk(mci, KERN_WARNING,
726 "CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
727 "0x%lx, row %d, channel %d, label \"%s\": %s\n",
728 page_frame_number, offset_in_page,
724
725 if (edac_mc_get_log_ce())
726 /* FIXME - put in DIMM location */
727 edac_mc_printk(mci, KERN_WARNING,
728 "CE page 0x%lx, offset 0x%lx, grain %d, syndrome "
729 "0x%lx, row %d, channel %d, label \"%s\": %s\n",
730 page_frame_number, offset_in_page,
729 mci->csrows[row].grain, syndrome, row, channel,
731 grain, syndrome, row, channel,
730 label, msg);
731
732 mci->ce_count++;
733 mci->csrows[row].ce_count++;
732 label, msg);
733
734 mci->ce_count++;
735 mci->csrows[row].ce_count++;
736 mci->csrows[row].channels[channel].dimm->ce_count++;
734 mci->csrows[row].channels[channel].ce_count++;
735
736 if (mci->scrub_mode & SCRUB_SW_SRC) {
737 /*
738 * Some MC's can remap memory so that it is still available
739 * at a different address when PCI devices map into memory.
740 * MC's that can't do this lose the memory where PCI devices
741 * are mapped. This mapping is MC dependent and so we call
742 * back into the MC driver for it to map the MC page to
743 * a physical (CPU) page which can then be mapped to a virtual
744 * page - which can then be scrubbed.
745 */
746 remapped_page = mci->ctl_page_to_phys ?
747 mci->ctl_page_to_phys(mci, page_frame_number) :
748 page_frame_number;
749
737 mci->csrows[row].channels[channel].ce_count++;
738
739 if (mci->scrub_mode & SCRUB_SW_SRC) {
740 /*
741 * Some MC's can remap memory so that it is still available
742 * at a different address when PCI devices map into memory.
743 * MC's that can't do this lose the memory where PCI devices
744 * are mapped. This mapping is MC dependent and so we call
745 * back into the MC driver for it to map the MC page to
746 * a physical (CPU) page which can then be mapped to a virtual
747 * page - which can then be scrubbed.
748 */
749 remapped_page = mci->ctl_page_to_phys ?
750 mci->ctl_page_to_phys(mci, page_frame_number) :
751 page_frame_number;
752
750 edac_mc_scrub_block(remapped_page, offset_in_page,
751 mci->csrows[row].grain);
753 edac_mc_scrub_block(remapped_page, offset_in_page, grain);
752 }
753}
754EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
755
756void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
757{
758 if (edac_mc_get_log_ce())
759 edac_mc_printk(mci, KERN_WARNING,

--- 9 unchanged lines hidden (view full) ---

769 unsigned long offset_in_page, int row, const char *msg)
770{
771 int len = EDAC_MC_LABEL_LEN * 4;
772 char labels[len + 1];
773 char *pos = labels;
774 int chan;
775 int chars;
776 char *label = NULL;
754 }
755}
756EXPORT_SYMBOL_GPL(edac_mc_handle_ce);
757
758void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
759{
760 if (edac_mc_get_log_ce())
761 edac_mc_printk(mci, KERN_WARNING,

--- 9 unchanged lines hidden (view full) ---

771 unsigned long offset_in_page, int row, const char *msg)
772{
773 int len = EDAC_MC_LABEL_LEN * 4;
774 char labels[len + 1];
775 char *pos = labels;
776 int chan;
777 int chars;
778 char *label = NULL;
779 u32 grain;
777
778 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
779
780 /* FIXME - maybe make panic on INTERNAL ERROR an option */
781 if (row >= mci->nr_csrows || row < 0) {
782 /* something is wrong */
783 edac_mc_printk(mci, KERN_ERR,
784 "INTERNAL ERROR: row out of range "
785 "(%d >= %d)\n", row, mci->nr_csrows);
786 edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
787 return;
788 }
789
780
781 debugf3("MC%d: %s()\n", mci->mc_idx, __func__);
782
783 /* FIXME - maybe make panic on INTERNAL ERROR an option */
784 if (row >= mci->nr_csrows || row < 0) {
785 /* something is wrong */
786 edac_mc_printk(mci, KERN_ERR,
787 "INTERNAL ERROR: row out of range "
788 "(%d >= %d)\n", row, mci->nr_csrows);
789 edac_mc_handle_ue_no_info(mci, "INTERNAL ERROR");
790 return;
791 }
792
793 grain = mci->csrows[row].channels[0].dimm->grain;
790 label = mci->csrows[row].channels[0].dimm->label;
791 chars = snprintf(pos, len + 1, "%s", label);
792 len -= chars;
793 pos += chars;
794
795 for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
796 chan++) {
797 label = mci->csrows[row].channels[chan].dimm->label;
798 chars = snprintf(pos, len + 1, ":%s", label);
799 len -= chars;
800 pos += chars;
801 }
802
803 if (edac_mc_get_log_ue())
804 edac_mc_printk(mci, KERN_EMERG,
805 "UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
806 "labels \"%s\": %s\n", page_frame_number,
794 label = mci->csrows[row].channels[0].dimm->label;
795 chars = snprintf(pos, len + 1, "%s", label);
796 len -= chars;
797 pos += chars;
798
799 for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
800 chan++) {
801 label = mci->csrows[row].channels[chan].dimm->label;
802 chars = snprintf(pos, len + 1, ":%s", label);
803 len -= chars;
804 pos += chars;
805 }
806
807 if (edac_mc_get_log_ue())
808 edac_mc_printk(mci, KERN_EMERG,
809 "UE page 0x%lx, offset 0x%lx, grain %d, row %d, "
810 "labels \"%s\": %s\n", page_frame_number,
807 offset_in_page, mci->csrows[row].grain, row,
808 labels, msg);
811 offset_in_page, grain, row, labels, msg);
809
810 if (edac_mc_get_panic_on_ue())
811 panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
812 "row %d, labels \"%s\": %s\n", mci->mc_idx,
813 page_frame_number, offset_in_page,
812
813 if (edac_mc_get_panic_on_ue())
814 panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
815 "row %d, labels \"%s\": %s\n", mci->mc_idx,
816 page_frame_number, offset_in_page,
814 mci->csrows[row].grain, row, labels, msg);
817 grain, row, labels, msg);
815
816 mci->ue_count++;
817 mci->csrows[row].ue_count++;
818}
819EXPORT_SYMBOL_GPL(edac_mc_handle_ue);
820
821void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
822{

--- 55 unchanged lines hidden (view full) ---

878 mci->ue_count++;
879 mci->csrows[csrow].ue_count++;
880
881 /* Generate the DIMM labels from the specified channels */
882 label = mci->csrows[csrow].channels[channela].dimm->label;
883 chars = snprintf(pos, len + 1, "%s", label);
884 len -= chars;
885 pos += chars;
818
819 mci->ue_count++;
820 mci->csrows[row].ue_count++;
821}
822EXPORT_SYMBOL_GPL(edac_mc_handle_ue);
823
824void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
825{

--- 55 unchanged lines hidden (view full) ---

881 mci->ue_count++;
882 mci->csrows[csrow].ue_count++;
883
884 /* Generate the DIMM labels from the specified channels */
885 label = mci->csrows[csrow].channels[channela].dimm->label;
886 chars = snprintf(pos, len + 1, "%s", label);
887 len -= chars;
888 pos += chars;
889
886 chars = snprintf(pos, len + 1, "-%s",
887 mci->csrows[csrow].channels[channelb].dimm->label);
888
889 if (edac_mc_get_log_ue())
890 edac_mc_printk(mci, KERN_EMERG,
891 "UE row %d, channel-a= %d channel-b= %d "
892 "labels \"%s\": %s\n", csrow, channela, channelb,
893 labels, msg);

--- 37 unchanged lines hidden (view full) ---

931 if (edac_mc_get_log_ce())
932 /* FIXME - put in DIMM location */
933 edac_mc_printk(mci, KERN_WARNING,
934 "CE row %d, channel %d, label \"%s\": %s\n",
935 csrow, channel, label, msg);
936
937 mci->ce_count++;
938 mci->csrows[csrow].ce_count++;
890 chars = snprintf(pos, len + 1, "-%s",
891 mci->csrows[csrow].channels[channelb].dimm->label);
892
893 if (edac_mc_get_log_ue())
894 edac_mc_printk(mci, KERN_EMERG,
895 "UE row %d, channel-a= %d channel-b= %d "
896 "labels \"%s\": %s\n", csrow, channela, channelb,
897 labels, msg);

--- 37 unchanged lines hidden (view full) ---

935 if (edac_mc_get_log_ce())
936 /* FIXME - put in DIMM location */
937 edac_mc_printk(mci, KERN_WARNING,
938 "CE row %d, channel %d, label \"%s\": %s\n",
939 csrow, channel, label, msg);
940
941 mci->ce_count++;
942 mci->csrows[csrow].ce_count++;
943 mci->csrows[csrow].channels[channel].dimm->ce_count++;
939 mci->csrows[csrow].channels[channel].ce_count++;
940}
941EXPORT_SYMBOL(edac_mc_handle_fbd_ce);
944 mci->csrows[csrow].channels[channel].ce_count++;
945}
946EXPORT_SYMBOL(edac_mc_handle_fbd_ce);