Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i7300_edac: Fix memory detection in single mode

When the machine is on single mode, only branch 0 channel 0
is valid. However, the code is not honouring it:

[ 1952.639341] EDAC DEBUG: i7300_get_mc_regs: Memory controller operating on single mode
...
[ 1952.639351] EDAC DEBUG: i7300_init_csrows: AMB-present CH0 = 0x1:
[ 1952.639353] EDAC DEBUG: i7300_init_csrows: AMB-present CH1 = 0x0:
[ 1952.639355] EDAC DEBUG: i7300_init_csrows: AMB-present CH2 = 0x0:
[ 1952.639358] EDAC DEBUG: i7300_init_csrows: AMB-present CH3 = 0x0:
...
[ 1952.639360] EDAC DEBUG: decode_mtr: MTR0 CH0: DIMMs are Present (mtr)
[ 1952.639362] EDAC DEBUG: decode_mtr: WIDTH: x8
[ 1952.639363] EDAC DEBUG: decode_mtr: ELECTRICAL THROTTLING is enabled
[ 1952.639364] EDAC DEBUG: decode_mtr: NUMBANK: 4 bank(s)
[ 1952.639366] EDAC DEBUG: decode_mtr: NUMRANK: single
[ 1952.639367] EDAC DEBUG: decode_mtr: NUMROW: 16,384 - 14 rows
[ 1952.639368] EDAC DEBUG: decode_mtr: NUMCOL: 1,024 - 10 columns
[ 1952.639370] EDAC DEBUG: decode_mtr: SIZE: 512 MB
[ 1952.639371] EDAC DEBUG: decode_mtr: ECC code is 8-byte-over-32-byte SECDED+ code
[ 1952.639373] EDAC DEBUG: decode_mtr: Scrub algorithm for x8 is on enhanced mode
[ 1952.639374] EDAC DEBUG: decode_mtr: MTR0 CH1: DIMMs are Present (mtr)
[ 1952.639376] EDAC DEBUG: decode_mtr: WIDTH: x8
[ 1952.639377] EDAC DEBUG: decode_mtr: ELECTRICAL THROTTLING is enabled
[ 1952.639379] EDAC DEBUG: decode_mtr: NUMBANK: 4 bank(s)
[ 1952.639380] EDAC DEBUG: decode_mtr: NUMRANK: single
[ 1952.639381] EDAC DEBUG: decode_mtr: NUMROW: 16,384 - 14 rows
[ 1952.639383] EDAC DEBUG: decode_mtr: NUMCOL: 1,024 - 10 columns
[ 1952.639384] EDAC DEBUG: decode_mtr: SIZE: 512 MB
[ 1952.639385] EDAC DEBUG: decode_mtr: ECC code is 8-byte-over-32-byte SECDED+ code
[ 1952.639387] EDAC DEBUG: decode_mtr: Scrub algorithm for x8 is on enhanced mode
...
[ 1952.639449] EDAC DEBUG: print_dimm_size: channel 0 | channel 1 | channel 2 | channel 3 |
[ 1952.639451] EDAC DEBUG: print_dimm_size: -------------------------------------------------------------
[ 1952.639453] EDAC DEBUG: print_dimm_size: csrow/SLOT 0 512 MB | 512 MB | 0 MB | 0 MB |
[ 1952.639456] EDAC DEBUG: print_dimm_size: csrow/SLOT 1 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639458] EDAC DEBUG: print_dimm_size: csrow/SLOT 2 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639460] EDAC DEBUG: print_dimm_size: csrow/SLOT 3 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639462] EDAC DEBUG: print_dimm_size: csrow/SLOT 4 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639464] EDAC DEBUG: print_dimm_size: csrow/SLOT 5 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639466] EDAC DEBUG: print_dimm_size: csrow/SLOT 6 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639468] EDAC DEBUG: print_dimm_size: csrow/SLOT 7 0 MB | 0 MB | 0 MB | 0 MB |
[ 1952.639470] EDAC DEBUG: print_dimm_size: -------------------------------------------------------------

Instead of detecting a single memory at channel 0, it is showing
twice the memory.

Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

+15 -4
+15 -4
drivers/edac/i7300_edac.c
··· 750 750 struct i7300_dimm_info *dinfo; 751 751 int rc = -ENODEV; 752 752 int mtr; 753 - int ch, branch, slot, channel; 753 + int ch, branch, slot, channel, max_channel, max_branch; 754 754 struct dimm_info *dimm; 755 755 756 756 pvt = mci->pvt_info; 757 757 758 758 edac_dbg(2, "Memory Technology Registers:\n"); 759 759 760 + if (IS_SINGLE_MODE(pvt->mc_settings_a)) { 761 + max_branch = 1; 762 + max_channel = 1; 763 + } else { 764 + max_branch = MAX_BRANCHES; 765 + max_channel = MAX_CH_PER_BRANCH; 766 + } 767 + 760 768 /* Get the AMB present registers for the four channels */ 761 - for (branch = 0; branch < MAX_BRANCHES; branch++) { 769 + for (branch = 0; branch < max_branch; branch++) { 762 770 /* Read and dump branch 0's MTRs */ 763 771 channel = to_channel(0, branch); 764 772 pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], ··· 774 766 &pvt->ambpresent[channel]); 775 767 edac_dbg(2, "\t\tAMB-present CH%d = 0x%x:\n", 776 768 channel, pvt->ambpresent[channel]); 769 + 770 + if (max_channel == 1) 771 + continue; 777 772 778 773 channel = to_channel(1, branch); 779 774 pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], ··· 789 778 /* Get the set of MTR[0-7] regs by each branch */ 790 779 for (slot = 0; slot < MAX_SLOTS; slot++) { 791 780 int where = mtr_regs[slot]; 792 - for (branch = 0; branch < MAX_BRANCHES; branch++) { 781 + for (branch = 0; branch < max_branch; branch++) { 793 782 pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], 794 783 where, 795 784 &pvt->mtr[slot][branch]); 796 - for (ch = 0; ch < MAX_CH_PER_BRANCH; ch++) { 785 + for (ch = 0; ch < max_channel; ch++) { 797 786 int channel = to_channel(ch, branch); 798 787 799 788 dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms,