| From 24bef66e74d647aebd34e0bef7693512b7912029 Mon Sep 17 00:00:00 2001 |
| From: Mauro Carvalho Chehab <mchehab@redhat.com> |
| Date: Wed, 24 Oct 2012 10:30:01 -0200 |
| Subject: edac: Fix the dimm filling for csrows-based layouts |
| |
| 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 */ |