Messages in this thread Patch in this message | | | From | Greg Kroah-Hartman <> | Subject | [ 09/37] edac: Fix the dimm filling for csrows-based layouts | Date | Fri, 14 Dec 2012 15:00:46 -0800 |
| |
3.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mauro Carvalho Chehab <mchehab@redhat.com>
commit 24bef66e74d647aebd34e0bef7693512b7912029 upstream.
The driver is currently filling data in a wrong way, on drivers for csrows-based memory controller, when the first layer is a csrow.
This is not easily to notice, as, in general, memories are filed in dual, interleaved, symetric mode, as very few memory controllers support asymetric modes.
While digging into a bug for i82795_edac driver, the asymetric mode there is now working, allowing us to fill the machine with 4x1GB ranks at channel 0, and 2x512GB at channel 1:
Channel 0 ranks: EDAC DEBUG: i82975x_init_csrows: DIMM A0: from page 0x00000000 to 0x0003ffff (size: 0x00040000 pages) EDAC DEBUG: i82975x_init_csrows: DIMM A1: from page 0x00040000 to 0x0007ffff (size: 0x00040000 pages) EDAC DEBUG: i82975x_init_csrows: DIMM A2: from page 0x00080000 to 0x000bffff (size: 0x00040000 pages) EDAC DEBUG: i82975x_init_csrows: DIMM A3: from page 0x000c0000 to 0x000fffff (size: 0x00040000 pages)
Channel 1 ranks: EDAC DEBUG: i82975x_init_csrows: DIMM B0: from page 0x00100000 to 0x0011ffff (size: 0x00020000 pages) EDAC DEBUG: i82975x_init_csrows: DIMM B1: from page 0x00120000 to 0x0013ffff (size: 0x00020000 pages)
Instead of properly showing the memories as such, before this patch, it shows the memory layout as:
+-----------------------------------+ | mc0 | | csrow0 | csrow1 | csrow2 | ----------+-----------------------------------+ channel1: | 1024 MB | 1024 MB | 512 MB | channel0: | 1024 MB | 1024 MB | 512 MB | ----------+-----------------------------------+
as if both channels were symetric, grouping the DIMMs on a wrong layout.
After this patch, the memory is correctly represented. So, for csrows at layers[0], it shows:
+-----------------------------------------------+ | mc0 | | csrow0 | csrow1 | csrow2 | csrow3 | ----------+-----------------------------------------------+ channel1: | 512 MB | 512 MB | 0 MB | 0 MB | channel0: | 1024 MB | 1024 MB | 1024 MB | 1024 MB | ----------+-----------------------------------------------+
For csrows at layers[1], it shows:
+-----------------------+ | mc0 | | channel0 | channel1 | --------+-----------------------+ csrow3: | 1024 MB | 0 MB | csrow2: | 1024 MB | 0 MB | --------+-----------------------+ csrow1: | 1024 MB | 512 MB | csrow0: | 1024 MB | 512 MB | --------+-----------------------+
So, no matter of what comes first, the information between channel and csrow will be properly represented.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com> Signed-off-by: CAI Qian <caiqian@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
--- drivers/edac/edac_mc.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
--- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c @@ -416,10 +416,18 @@ struct mem_ctl_info *edac_mc_alloc(unsig dimm->cschannel = chn; /* Increment csrow location */ - row++; - if (row == tot_csrows) { - row = 0; + if (layers[0].is_virt_csrow) { chn++; + if (chn == tot_channels) { + chn = 0; + row++; + } + } else { + row++; + if (row == tot_csrows) { + row = 0; + chn++; + } } /* Increment dimm location */
| |