diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-06-22 21:48:29 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-10 10:44:45 -0400 |
commit | 0b2b7b7ec06ce615acd11374bf9a512e166dabb0 (patch) | |
tree | bd57e9162b2880aa52271d067ba36a409428c781 /drivers/edac | |
parent | 194a40feabb7cab38911a357c86e968e98024281 (diff) |
i7core_edac: Add more status functions to EDAC driver
This patch were co-authored with Aristeu Rozanski.
Signed-off-by: Aristeu Sergio <arozansk@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/i7core_edac.c | 114 |
1 files changed, 95 insertions, 19 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index b590f8468693..da40730bf9c9 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c | |||
@@ -62,6 +62,15 @@ | |||
62 | 62 | ||
63 | /* OFFSETS for Devices 4,5 and 6 Function 0 */ | 63 | /* OFFSETS for Devices 4,5 and 6 Function 0 */ |
64 | 64 | ||
65 | #define MC_CHANNEL_DIMM_INIT_PARAMS 0x58 | ||
66 | #define THREE_DIMMS_PRESENT (1 << 24) | ||
67 | #define SINGLE_QUAD_RANK_PRESENT (1 << 23) | ||
68 | #define QUAD_RANK_PRESENT (1 << 22) | ||
69 | #define REGISTERED_DIMM (1 << 15) | ||
70 | |||
71 | #define MC_CHANNEL_RANK_PRESENT 0x7c | ||
72 | #define RANK_PRESENT_MASK 0xffff | ||
73 | |||
65 | #define MC_CHANNEL_ADDR_MATCH 0xf0 | 74 | #define MC_CHANNEL_ADDR_MATCH 0xf0 |
66 | #define MC_CHANNEL_ERROR_MASK 0xf8 | 75 | #define MC_CHANNEL_ERROR_MASK 0xf8 |
67 | #define MC_CHANNEL_ERROR_INJECT 0xfc | 76 | #define MC_CHANNEL_ERROR_INJECT 0xfc |
@@ -74,6 +83,46 @@ | |||
74 | #define NO_MASK_CACHELINE 0x00 | 83 | #define NO_MASK_CACHELINE 0x00 |
75 | #define REPEAT_EN 0x01 | 84 | #define REPEAT_EN 0x01 |
76 | 85 | ||
86 | /* OFFSETS for Devices 4,5 and 6 Function 1 */ | ||
87 | #define MC_DOD_CH_DIMM0 0x48 | ||
88 | #define MC_DOD_CH_DIMM1 0x4c | ||
89 | #define MC_DOD_CH_DIMM2 0x50 | ||
90 | #define RANKOFFSET_MASK ((1 << 12) | (1 << 11) | (1 << 10)) | ||
91 | #define RANKOFFSET(x) ((x & RANKOFFSET_MASK) >> 10) | ||
92 | #define DIMM_PRESENT_MASK (1 << 9) | ||
93 | #define DIMM_PRESENT(x) (((x) & DIMM_PRESENT_MASK) >> 9) | ||
94 | #define NUMBANK_MASK ((1 << 8) | (1 << 7)) | ||
95 | #define NUMBANK(x) (((x) & NUMBANK_MASK) >> 7) | ||
96 | #define NUMRANK_MASK ((1 << 6) | (1 << 5)) | ||
97 | #define NUMRANK(x) (((x) & NUMRANK_MASK) >> 5) | ||
98 | #define NUMROW_MASK ((1 << 4) | (1 << 3)) | ||
99 | #define NUMROW(x) (((x) & NUMROW_MASK) >> 3) | ||
100 | #define NUMCOL_MASK 3 | ||
101 | #define NUMCOL(x) ((x) & NUMCOL_MASK) | ||
102 | |||
103 | #define MC_SAG_CH_0 0x80 | ||
104 | #define MC_SAG_CH_1 0x84 | ||
105 | #define MC_SAG_CH_2 0x88 | ||
106 | #define MC_SAG_CH_3 0x8c | ||
107 | #define MC_SAG_CH_4 0x90 | ||
108 | #define MC_SAG_CH_5 0x94 | ||
109 | #define MC_SAG_CH_6 0x98 | ||
110 | #define MC_SAG_CH_7 0x9c | ||
111 | |||
112 | #define MC_RIR_LIMIT_CH_0 0x40 | ||
113 | #define MC_RIR_LIMIT_CH_1 0x44 | ||
114 | #define MC_RIR_LIMIT_CH_2 0x48 | ||
115 | #define MC_RIR_LIMIT_CH_3 0x4C | ||
116 | #define MC_RIR_LIMIT_CH_4 0x50 | ||
117 | #define MC_RIR_LIMIT_CH_5 0x54 | ||
118 | #define MC_RIR_LIMIT_CH_6 0x58 | ||
119 | #define MC_RIR_LIMIT_CH_7 0x5C | ||
120 | #define MC_RIR_LIMIT_MASK ((1 << 10) - 1) | ||
121 | |||
122 | #define MC_RIR_WAY_CH 0x80 | ||
123 | #define MC_RIR_WAY_OFFSET_MASK (((1 << 14) - 1) & ~0x7) | ||
124 | #define MC_RIR_WAY_RANK_MASK 0x7 | ||
125 | |||
77 | /* | 126 | /* |
78 | * i7core structs | 127 | * i7core structs |
79 | */ | 128 | */ |
@@ -99,11 +148,17 @@ struct i7core_inject { | |||
99 | int channel, dimm, rank, bank, page, col; | 148 | int channel, dimm, rank, bank, page, col; |
100 | }; | 149 | }; |
101 | 150 | ||
151 | struct i7core_channel { | ||
152 | u32 ranks; | ||
153 | u32 dimms; | ||
154 | }; | ||
155 | |||
102 | struct i7core_pvt { | 156 | struct i7core_pvt { |
103 | struct pci_dev *pci_mcr; /* Dev 3:0 */ | 157 | struct pci_dev *pci_mcr; /* Dev 3:0 */ |
104 | struct pci_dev *pci_ch[NUM_CHANS][NUM_FUNCS]; | 158 | struct pci_dev *pci_ch[NUM_CHANS][NUM_FUNCS]; |
105 | struct i7core_info info; | 159 | struct i7core_info info; |
106 | struct i7core_inject inject; | 160 | struct i7core_inject inject; |
161 | struct i7core_channel channel[NUM_CHANS]; | ||
107 | }; | 162 | }; |
108 | 163 | ||
109 | /* Device name and register DID (Device ID) */ | 164 | /* Device name and register DID (Device ID) */ |
@@ -133,16 +188,12 @@ static struct edac_pci_ctl_info *i7core_pci; | |||
133 | ****************************************************************************/ | 188 | ****************************************************************************/ |
134 | 189 | ||
135 | /* MC_CONTROL bits */ | 190 | /* MC_CONTROL bits */ |
136 | #define CH2_ACTIVE(pvt) ((pvt)->info.mc_control & 1 << 10) | 191 | #define CH_ACTIVE(pvt, ch) ((pvt)->info.mc_control & 1 << (8 + ch)) |
137 | #define CH1_ACTIVE(pvt) ((pvt)->info.mc_control & 1 << 9) | ||
138 | #define CH0_ACTIVE(pvt) ((pvt)->info.mc_control & 1 << 8) | ||
139 | #define ECCx8(pvt) ((pvt)->info.mc_control & 1 << 1) | 192 | #define ECCx8(pvt) ((pvt)->info.mc_control & 1 << 1) |
140 | 193 | ||
141 | /* MC_STATUS bits */ | 194 | /* MC_STATUS bits */ |
142 | #define ECC_ENABLED(pvt) ((pvt)->info.mc_status & 1 << 3) | 195 | #define ECC_ENABLED(pvt) ((pvt)->info.mc_status & 1 << 3) |
143 | #define CH2_DISABLED(pvt) ((pvt)->info.mc_status & 1 << 2) | 196 | #define CH_DISABLED(pvt, ch) ((pvt)->info.mc_status & 1 << ch) |
144 | #define CH1_DISABLED(pvt) ((pvt)->info.mc_status & 1 << 1) | ||
145 | #define CH0_DISABLED(pvt) ((pvt)->info.mc_status & 1 << 0) | ||
146 | 197 | ||
147 | /* MC_MAX_DOD read functions */ | 198 | /* MC_MAX_DOD read functions */ |
148 | static inline int maxnumdimms(struct i7core_pvt *pvt) | 199 | static inline int maxnumdimms(struct i7core_pvt *pvt) |
@@ -189,19 +240,12 @@ static inline int maxnumcol(struct i7core_pvt *pvt) | |||
189 | static int get_dimm_config(struct mem_ctl_info *mci) | 240 | static int get_dimm_config(struct mem_ctl_info *mci) |
190 | { | 241 | { |
191 | struct i7core_pvt *pvt = mci->pvt_info; | 242 | struct i7core_pvt *pvt = mci->pvt_info; |
243 | int i; | ||
192 | 244 | ||
193 | pci_read_config_dword(pvt->pci_mcr, MC_CONTROL, &pvt->info.mc_control); | 245 | pci_read_config_dword(pvt->pci_mcr, MC_CONTROL, &pvt->info.mc_control); |
194 | pci_read_config_dword(pvt->pci_mcr, MC_STATUS, &pvt->info.mc_status); | 246 | pci_read_config_dword(pvt->pci_mcr, MC_STATUS, &pvt->info.mc_status); |
195 | pci_read_config_dword(pvt->pci_mcr, MC_MAX_DOD, &pvt->info.max_dod); | 247 | pci_read_config_dword(pvt->pci_mcr, MC_MAX_DOD, &pvt->info.max_dod); |
196 | 248 | ||
197 | debugf0("Channels active [%c][%c][%c] - enabled [%c][%c][%c]\n", | ||
198 | CH0_ACTIVE(pvt)?'0':'-', | ||
199 | CH1_ACTIVE(pvt)?'1':'-', | ||
200 | CH2_ACTIVE(pvt)?'2':'-', | ||
201 | CH0_DISABLED(pvt)?'-':'0', | ||
202 | CH1_DISABLED(pvt)?'-':'1', | ||
203 | CH2_DISABLED(pvt)?'-':'2'); | ||
204 | |||
205 | if (ECC_ENABLED(pvt)) | 249 | if (ECC_ENABLED(pvt)) |
206 | debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4); | 250 | debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4); |
207 | else | 251 | else |
@@ -213,6 +257,38 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
213 | debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n", | 257 | debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n", |
214 | maxnumrow(pvt), maxnumcol(pvt)); | 258 | maxnumrow(pvt), maxnumcol(pvt)); |
215 | 259 | ||
260 | debugf0("Memory channel configuration:\n"); | ||
261 | |||
262 | for (i = 0; i < NUM_CHANS; i++) { | ||
263 | u32 data; | ||
264 | |||
265 | if (!CH_ACTIVE(pvt, i)) { | ||
266 | debugf0("Channel %i is not active\n", i); | ||
267 | continue; | ||
268 | } | ||
269 | if (CH_DISABLED(pvt, i)) { | ||
270 | debugf0("Channel %i is disabled\n", i); | ||
271 | continue; | ||
272 | } | ||
273 | |||
274 | pci_read_config_dword(pvt->pci_ch[i][0], | ||
275 | MC_CHANNEL_DIMM_INIT_PARAMS, &data); | ||
276 | |||
277 | pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2; | ||
278 | |||
279 | if (data & THREE_DIMMS_PRESENT) | ||
280 | pvt->channel[i].dimms = 3; | ||
281 | else if (data & SINGLE_QUAD_RANK_PRESENT) | ||
282 | pvt->channel[i].dimms = 1; | ||
283 | else | ||
284 | pvt->channel[i].dimms = 2; | ||
285 | |||
286 | debugf0("Channel %d (0x%08x): %d ranks, %d dimms " | ||
287 | "(%sregistered)\n", i, data, | ||
288 | pvt->channel[i].ranks, pvt->channel[i].dimms, | ||
289 | (data & REGISTERED_DIMM)? "" : "un" ); | ||
290 | } | ||
291 | |||
216 | return 0; | 292 | return 0; |
217 | } | 293 | } |
218 | 294 | ||
@@ -489,7 +565,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, | |||
489 | if (pvt->inject.dimm < 0) | 565 | if (pvt->inject.dimm < 0) |
490 | mask |= 1l << 41; | 566 | mask |= 1l << 41; |
491 | else { | 567 | else { |
492 | if (maxnumdimms(pvt) > 2) | 568 | if (pvt->channel[pvt->inject.channel].dimms > 2) |
493 | mask |= (pvt->inject.dimm & 0x3l) << 35; | 569 | mask |= (pvt->inject.dimm & 0x3l) << 35; |
494 | else | 570 | else |
495 | mask |= (pvt->inject.dimm & 0x1l) << 36; | 571 | mask |= (pvt->inject.dimm & 0x1l) << 36; |
@@ -499,7 +575,7 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, | |||
499 | if (pvt->inject.rank < 0) | 575 | if (pvt->inject.rank < 0) |
500 | mask |= 1l << 40; | 576 | mask |= 1l << 40; |
501 | else { | 577 | else { |
502 | if (maxnumdimms(pvt) > 2) | 578 | if (pvt->channel[pvt->inject.channel].dimms > 2) |
503 | mask |= (pvt->inject.rank & 0x1l) << 34; | 579 | mask |= (pvt->inject.rank & 0x1l) << 34; |
504 | else | 580 | else |
505 | mask |= (pvt->inject.rank & 0x3l) << 34; | 581 | mask |= (pvt->inject.rank & 0x3l) << 34; |
@@ -646,9 +722,6 @@ static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx) | |||
646 | } | 722 | } |
647 | pvt->pci_mcr=pdev; | 723 | pvt->pci_mcr=pdev; |
648 | 724 | ||
649 | /* Get dimm basic config */ | ||
650 | get_dimm_config(mci); | ||
651 | |||
652 | /* Retrieve all needed functions at MTR channel controllers */ | 725 | /* Retrieve all needed functions at MTR channel controllers */ |
653 | for (i = 0; i < NUM_CHANS; i++) { | 726 | for (i = 0; i < NUM_CHANS; i++) { |
654 | pdev = NULL; | 727 | pdev = NULL; |
@@ -672,6 +745,9 @@ static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx) | |||
672 | } | 745 | } |
673 | i7core_printk(KERN_INFO, "Driver loaded.\n"); | 746 | i7core_printk(KERN_INFO, "Driver loaded.\n"); |
674 | 747 | ||
748 | /* Get dimm basic config */ | ||
749 | get_dimm_config(mci); | ||
750 | |||
675 | return 0; | 751 | return 0; |
676 | } | 752 | } |
677 | 753 | ||