Commit de3910eb79ac8c0f29a11224661c0ebaaf813039
1 parent
e39f4ea9b0
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
edac: change the mem allocation scheme to make Documentation/kobject.txt happy
Kernel kobjects have rigid rules: each container object should be dynamically allocated, and can't be allocated into a single kmalloc. EDAC never obeyed this rule: it has a single malloc function that allocates all needed data into a single kzalloc. As this is not accepted anymore, change the allocation schema of the EDAC *_info structs to enforce this Kernel standard. Acked-by: Chris Metcalf <cmetcalf@tilera.com> Cc: Aristeu Rozanski <arozansk@redhat.com> Cc: Doug Thompson <norsk5@yahoo.com> Cc: Greg K H <gregkh@linuxfoundation.org> Cc: Borislav Petkov <borislav.petkov@amd.com> Cc: Mark Gross <mark.gross@intel.com> Cc: Tim Small <tim@buttersideup.com> Cc: Ranganathan Desikan <ravi@jetztechnologies.com> Cc: "Arvind R." <arvino55@gmail.com> Cc: Olof Johansson <olof@lixom.net> Cc: Egor Martovetsky <egor@pasemi.com> Cc: Michal Marek <mmarek@suse.cz> Cc: Jiri Kosina <jkosina@suse.cz> Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Hitoshi Mitake <h.mitake@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Shaohui Xie <Shaohui.Xie@freescale.com> Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Showing 22 changed files with 242 additions and 164 deletions Side-by-side Diff
- drivers/edac/amd64_edac.c
- drivers/edac/amd76x_edac.c
- drivers/edac/cell_edac.c
- drivers/edac/cpc925_edac.c
- drivers/edac/e752x_edac.c
- drivers/edac/e7xxx_edac.c
- drivers/edac/edac_mc.c
- drivers/edac/edac_mc_sysfs.c
- drivers/edac/i3000_edac.c
- drivers/edac/i3200_edac.c
- drivers/edac/i5400_edac.c
- drivers/edac/i82443bxgx_edac.c
- drivers/edac/i82860_edac.c
- drivers/edac/i82875p_edac.c
- drivers/edac/i82975x_edac.c
- drivers/edac/mpc85xx_edac.c
- drivers/edac/mv64x60_edac.c
- drivers/edac/pasemi_edac.c
- drivers/edac/r82600_edac.c
- drivers/edac/tile_edac.c
- drivers/edac/x38_edac.c
- include/linux/edac.h
drivers/edac/amd64_edac.c
... | ... | @@ -2205,6 +2205,7 @@ |
2205 | 2205 | static int init_csrows(struct mem_ctl_info *mci) |
2206 | 2206 | { |
2207 | 2207 | struct csrow_info *csrow; |
2208 | + struct dimm_info *dimm; | |
2208 | 2209 | struct amd64_pvt *pvt = mci->pvt_info; |
2209 | 2210 | u64 base, mask; |
2210 | 2211 | u32 val; |
... | ... | @@ -2222,7 +2223,7 @@ |
2222 | 2223 | !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); |
2223 | 2224 | |
2224 | 2225 | for_each_chip_select(i, 0, pvt) { |
2225 | - csrow = &mci->csrows[i]; | |
2226 | + csrow = mci->csrows[i]; | |
2226 | 2227 | |
2227 | 2228 | if (!csrow_enabled(i, 0, pvt) && !csrow_enabled(i, 1, pvt)) { |
2228 | 2229 | debugf1("----CSROW %d EMPTY for node %d\n", i, |
... | ... | @@ -2257,9 +2258,10 @@ |
2257 | 2258 | edac_mode = EDAC_NONE; |
2258 | 2259 | |
2259 | 2260 | for (j = 0; j < pvt->channel_count; j++) { |
2260 | - csrow->channels[j].dimm->mtype = mtype; | |
2261 | - csrow->channels[j].dimm->edac_mode = edac_mode; | |
2262 | - csrow->channels[j].dimm->nr_pages = nr_pages; | |
2261 | + dimm = csrow->channels[j]->dimm; | |
2262 | + dimm->mtype = mtype; | |
2263 | + dimm->edac_mode = edac_mode; | |
2264 | + dimm->nr_pages = nr_pages; | |
2263 | 2265 | } |
2264 | 2266 | } |
2265 | 2267 |
drivers/edac/amd76x_edac.c
... | ... | @@ -146,7 +146,7 @@ |
146 | 146 | if (handle_errors) { |
147 | 147 | row = (info->ecc_mode_status >> 4) & 0xf; |
148 | 148 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, |
149 | - mci->csrows[row].first_page, 0, 0, | |
149 | + mci->csrows[row]->first_page, 0, 0, | |
150 | 150 | row, 0, -1, |
151 | 151 | mci->ctl_name, "", NULL); |
152 | 152 | } |
... | ... | @@ -161,7 +161,7 @@ |
161 | 161 | if (handle_errors) { |
162 | 162 | row = info->ecc_mode_status & 0xf; |
163 | 163 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, |
164 | - mci->csrows[row].first_page, 0, 0, | |
164 | + mci->csrows[row]->first_page, 0, 0, | |
165 | 165 | row, 0, -1, |
166 | 166 | mci->ctl_name, "", NULL); |
167 | 167 | } |
... | ... | @@ -194,8 +194,8 @@ |
194 | 194 | int index; |
195 | 195 | |
196 | 196 | for (index = 0; index < mci->nr_csrows; index++) { |
197 | - csrow = &mci->csrows[index]; | |
198 | - dimm = csrow->channels[0].dimm; | |
197 | + csrow = mci->csrows[index]; | |
198 | + dimm = csrow->channels[0]->dimm; | |
199 | 199 | |
200 | 200 | /* find the DRAM Chip Select Base address and mask */ |
201 | 201 | pci_read_config_dword(pdev, |
drivers/edac/cell_edac.c
... | ... | @@ -33,7 +33,7 @@ |
33 | 33 | static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar) |
34 | 34 | { |
35 | 35 | struct cell_edac_priv *priv = mci->pvt_info; |
36 | - struct csrow_info *csrow = &mci->csrows[0]; | |
36 | + struct csrow_info *csrow = mci->csrows[0]; | |
37 | 37 | unsigned long address, pfn, offset, syndrome; |
38 | 38 | |
39 | 39 | dev_dbg(mci->pdev, "ECC CE err on node %d, channel %d, ar = 0x%016llx\n", |
... | ... | @@ -56,7 +56,7 @@ |
56 | 56 | static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar) |
57 | 57 | { |
58 | 58 | struct cell_edac_priv *priv = mci->pvt_info; |
59 | - struct csrow_info *csrow = &mci->csrows[0]; | |
59 | + struct csrow_info *csrow = mci->csrows[0]; | |
60 | 60 | unsigned long address, pfn, offset; |
61 | 61 | |
62 | 62 | dev_dbg(mci->pdev, "ECC UE err on node %d, channel %d, ar = 0x%016llx\n", |
... | ... | @@ -126,7 +126,7 @@ |
126 | 126 | |
127 | 127 | static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci) |
128 | 128 | { |
129 | - struct csrow_info *csrow = &mci->csrows[0]; | |
129 | + struct csrow_info *csrow = mci->csrows[0]; | |
130 | 130 | struct dimm_info *dimm; |
131 | 131 | struct cell_edac_priv *priv = mci->pvt_info; |
132 | 132 | struct device_node *np; |
... | ... | @@ -150,7 +150,7 @@ |
150 | 150 | csrow->last_page = csrow->first_page + nr_pages - 1; |
151 | 151 | |
152 | 152 | for (j = 0; j < csrow->nr_channels; j++) { |
153 | - dimm = csrow->channels[j].dimm; | |
153 | + dimm = csrow->channels[j]->dimm; | |
154 | 154 | dimm->mtype = MEM_XDR; |
155 | 155 | dimm->edac_mode = EDAC_SECDED; |
156 | 156 | dimm->nr_pages = nr_pages / csrow->nr_channels; |
drivers/edac/cpc925_edac.c
... | ... | @@ -348,7 +348,7 @@ |
348 | 348 | if (bba == 0) |
349 | 349 | continue; /* not populated */ |
350 | 350 | |
351 | - csrow = &mci->csrows[index]; | |
351 | + csrow = mci->csrows[index]; | |
352 | 352 | |
353 | 353 | row_size = bba * (1UL << 28); /* 256M */ |
354 | 354 | csrow->first_page = last_nr_pages; |
... | ... | @@ -380,7 +380,7 @@ |
380 | 380 | break; |
381 | 381 | } |
382 | 382 | for (j = 0; j < csrow->nr_channels; j++) { |
383 | - dimm = csrow->channels[j].dimm; | |
383 | + dimm = csrow->channels[j]->dimm; | |
384 | 384 | dimm->nr_pages = nr_pages / csrow->nr_channels; |
385 | 385 | dimm->mtype = MEM_RDDR; |
386 | 386 | dimm->edac_mode = EDAC_SECDED; |
... | ... | @@ -463,7 +463,7 @@ |
463 | 463 | *csrow = rank; |
464 | 464 | |
465 | 465 | #ifdef CONFIG_EDAC_DEBUG |
466 | - if (mci->csrows[rank].first_page == 0) { | |
466 | + if (mci->csrows[rank]->first_page == 0) { | |
467 | 467 | cpc925_mc_printk(mci, KERN_ERR, "ECC occurs in a " |
468 | 468 | "non-populated csrow, broken hardware?\n"); |
469 | 469 | return; |
... | ... | @@ -471,7 +471,7 @@ |
471 | 471 | #endif |
472 | 472 | |
473 | 473 | /* Revert csrow number */ |
474 | - pa = mci->csrows[rank].first_page << PAGE_SHIFT; | |
474 | + pa = mci->csrows[rank]->first_page << PAGE_SHIFT; | |
475 | 475 | |
476 | 476 | /* Revert column address */ |
477 | 477 | col += bcnt; |
drivers/edac/e752x_edac.c
... | ... | @@ -1096,7 +1096,7 @@ |
1096 | 1096 | for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) { |
1097 | 1097 | /* mem_dev 0=x8, 1=x4 */ |
1098 | 1098 | mem_dev = (dra >> (index * 4 + 2)) & 0x3; |
1099 | - csrow = &mci->csrows[remap_csrow_index(mci, index)]; | |
1099 | + csrow = mci->csrows[remap_csrow_index(mci, index)]; | |
1100 | 1100 | |
1101 | 1101 | mem_dev = (mem_dev == 2); |
1102 | 1102 | pci_read_config_byte(pdev, E752X_DRB + index, &value); |
... | ... | @@ -1127,7 +1127,7 @@ |
1127 | 1127 | } else |
1128 | 1128 | edac_mode = EDAC_NONE; |
1129 | 1129 | for (i = 0; i < csrow->nr_channels; i++) { |
1130 | - struct dimm_info *dimm = csrow->channels[i].dimm; | |
1130 | + struct dimm_info *dimm = csrow->channels[i]->dimm; | |
1131 | 1131 | |
1132 | 1132 | debugf3("Initializing rank at (%i,%i)\n", index, i); |
1133 | 1133 | dimm->nr_pages = nr_pages / csrow->nr_channels; |
drivers/edac/e7xxx_edac.c
... | ... | @@ -378,7 +378,7 @@ |
378 | 378 | for (index = 0; index < mci->nr_csrows; index++) { |
379 | 379 | /* mem_dev 0=x8, 1=x4 */ |
380 | 380 | mem_dev = (dra >> (index * 4 + 3)) & 0x1; |
381 | - csrow = &mci->csrows[index]; | |
381 | + csrow = mci->csrows[index]; | |
382 | 382 | |
383 | 383 | pci_read_config_byte(pdev, E7XXX_DRB + index, &value); |
384 | 384 | /* convert a 64 or 32 MiB DRB to a page size. */ |
... | ... | @@ -409,7 +409,7 @@ |
409 | 409 | edac_mode = EDAC_NONE; |
410 | 410 | |
411 | 411 | for (j = 0; j < drc_chan + 1; j++) { |
412 | - dimm = csrow->channels[j].dimm; | |
412 | + dimm = csrow->channels[j]->dimm; | |
413 | 413 | |
414 | 414 | dimm->nr_pages = nr_pages / (drc_chan + 1); |
415 | 415 | dimm->grain = 1 << 12; /* 4KiB - resolution of CELOG */ |
drivers/edac/edac_mc.c
... | ... | @@ -210,15 +210,15 @@ |
210 | 210 | { |
211 | 211 | struct mem_ctl_info *mci; |
212 | 212 | struct edac_mc_layer *layer; |
213 | - struct csrow_info *csi, *csr; | |
214 | - struct rank_info *chi, *chp, *chan; | |
213 | + struct csrow_info *csr; | |
214 | + struct rank_info *chan; | |
215 | 215 | struct dimm_info *dimm; |
216 | 216 | u32 *ce_per_layer[EDAC_MAX_LAYERS], *ue_per_layer[EDAC_MAX_LAYERS]; |
217 | 217 | unsigned pos[EDAC_MAX_LAYERS]; |
218 | 218 | unsigned size, tot_dimms = 1, count = 1; |
219 | 219 | unsigned tot_csrows = 1, tot_channels = 1, tot_errcount = 0; |
220 | 220 | void *pvt, *p, *ptr = NULL; |
221 | - int i, j, row, chn, n, len; | |
221 | + int i, j, row, chn, n, len, off; | |
222 | 222 | bool per_rank = false; |
223 | 223 | |
224 | 224 | BUG_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0); |
... | ... | @@ -244,9 +244,6 @@ |
244 | 244 | */ |
245 | 245 | mci = edac_align_ptr(&ptr, sizeof(*mci), 1); |
246 | 246 | layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers); |
247 | - csi = edac_align_ptr(&ptr, sizeof(*csi), tot_csrows); | |
248 | - chi = edac_align_ptr(&ptr, sizeof(*chi), tot_csrows * tot_channels); | |
249 | - dimm = edac_align_ptr(&ptr, sizeof(*dimm), tot_dimms); | |
250 | 247 | for (i = 0; i < n_layers; i++) { |
251 | 248 | count *= layers[i].size; |
252 | 249 | debugf4("%s: errcount layer %d size %d\n", __func__, i, count); |
... | ... | @@ -264,6 +261,7 @@ |
264 | 261 | tot_dimms, |
265 | 262 | per_rank ? "ranks" : "dimms", |
266 | 263 | tot_csrows * tot_channels); |
264 | + | |
267 | 265 | mci = kzalloc(size, GFP_KERNEL); |
268 | 266 | if (mci == NULL) |
269 | 267 | return NULL; |
... | ... | @@ -272,9 +270,6 @@ |
272 | 270 | * rather than an imaginary chunk of memory located at address 0. |
273 | 271 | */ |
274 | 272 | layer = (struct edac_mc_layer *)(((char *)mci) + ((unsigned long)layer)); |
275 | - csi = (struct csrow_info *)(((char *)mci) + ((unsigned long)csi)); | |
276 | - chi = (struct rank_info *)(((char *)mci) + ((unsigned long)chi)); | |
277 | - dimm = (struct dimm_info *)(((char *)mci) + ((unsigned long)dimm)); | |
278 | 273 | for (i = 0; i < n_layers; i++) { |
279 | 274 | mci->ce_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ce_per_layer[i])); |
280 | 275 | mci->ue_per_layer[i] = (u32 *)((char *)mci + ((unsigned long)ue_per_layer[i])); |
... | ... | @@ -283,8 +278,6 @@ |
283 | 278 | |
284 | 279 | /* setup index and various internal pointers */ |
285 | 280 | mci->mc_idx = mc_num; |
286 | - mci->csrows = csi; | |
287 | - mci->dimms = dimm; | |
288 | 281 | mci->tot_dimms = tot_dimms; |
289 | 282 | mci->pvt_info = pvt; |
290 | 283 | mci->n_layers = n_layers; |
291 | 284 | |
292 | 285 | |
293 | 286 | |
294 | 287 | |
295 | 288 | |
296 | 289 | |
297 | 290 | |
298 | 291 | |
... | ... | @@ -295,39 +288,60 @@ |
295 | 288 | mci->mem_is_per_rank = per_rank; |
296 | 289 | |
297 | 290 | /* |
298 | - * Fill the csrow struct | |
291 | + * Alocate and fill the csrow/channels structs | |
299 | 292 | */ |
293 | + mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL); | |
294 | + if (!mci->csrows) | |
295 | + goto error; | |
300 | 296 | for (row = 0; row < tot_csrows; row++) { |
301 | - csr = &csi[row]; | |
297 | + csr = kzalloc(sizeof(**mci->csrows), GFP_KERNEL); | |
298 | + if (!csr) | |
299 | + goto error; | |
300 | + mci->csrows[row] = csr; | |
302 | 301 | csr->csrow_idx = row; |
303 | 302 | csr->mci = mci; |
304 | 303 | csr->nr_channels = tot_channels; |
305 | - chp = &chi[row * tot_channels]; | |
306 | - csr->channels = chp; | |
304 | + csr->channels = kcalloc(sizeof(*csr->channels), tot_channels, | |
305 | + GFP_KERNEL); | |
306 | + if (!csr->channels) | |
307 | + goto error; | |
307 | 308 | |
308 | 309 | for (chn = 0; chn < tot_channels; chn++) { |
309 | - chan = &chp[chn]; | |
310 | + chan = kzalloc(sizeof(**csr->channels), GFP_KERNEL); | |
311 | + if (!chan) | |
312 | + goto error; | |
313 | + csr->channels[chn] = chan; | |
310 | 314 | chan->chan_idx = chn; |
311 | 315 | chan->csrow = csr; |
312 | 316 | } |
313 | 317 | } |
314 | 318 | |
315 | 319 | /* |
316 | - * Fill the dimm struct | |
320 | + * Allocate and fill the dimm structs | |
317 | 321 | */ |
322 | + mci->dimms = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL); | |
323 | + if (!mci->dimms) | |
324 | + goto error; | |
325 | + | |
318 | 326 | memset(&pos, 0, sizeof(pos)); |
319 | 327 | row = 0; |
320 | 328 | chn = 0; |
321 | 329 | debugf4("%s: initializing %d %s\n", __func__, tot_dimms, |
322 | 330 | per_rank ? "ranks" : "dimms"); |
323 | 331 | for (i = 0; i < tot_dimms; i++) { |
324 | - chan = &csi[row].channels[chn]; | |
325 | - dimm = EDAC_DIMM_PTR(layer, mci->dimms, n_layers, | |
326 | - pos[0], pos[1], pos[2]); | |
332 | + chan = mci->csrows[row]->channels[chn]; | |
333 | + off = EDAC_DIMM_OFF(layer, n_layers, pos[0], pos[1], pos[2]); | |
334 | + if (off < 0 || off >= tot_dimms) { | |
335 | + edac_mc_printk(mci, KERN_ERR, "EDAC core bug: EDAC_DIMM_OFF is trying to do an illegal data access\n"); | |
336 | + goto error; | |
337 | + } | |
338 | + | |
339 | + dimm = kzalloc(sizeof(**mci->dimms), GFP_KERNEL); | |
340 | + mci->dimms[off] = dimm; | |
327 | 341 | dimm->mci = mci; |
328 | 342 | |
329 | - debugf2("%s: %d: %s%zd (%d:%d:%d): row %d, chan %d\n", __func__, | |
330 | - i, per_rank ? "rank" : "dimm", (dimm - mci->dimms), | |
343 | + debugf2("%s: %d: %s%i (%d:%d:%d): row %d, chan %d\n", __func__, | |
344 | + i, per_rank ? "rank" : "dimm", off, | |
331 | 345 | pos[0], pos[1], pos[2], row, chn); |
332 | 346 | |
333 | 347 | /* |
... | ... | @@ -381,6 +395,28 @@ |
381 | 395 | */ |
382 | 396 | |
383 | 397 | return mci; |
398 | + | |
399 | +error: | |
400 | + if (mci->dimms) { | |
401 | + for (i = 0; i < tot_dimms; i++) | |
402 | + kfree(mci->dimms[i]); | |
403 | + kfree(mci->dimms); | |
404 | + } | |
405 | + if (mci->csrows) { | |
406 | + for (chn = 0; chn < tot_channels; chn++) { | |
407 | + csr = mci->csrows[chn]; | |
408 | + if (csr) { | |
409 | + for (chn = 0; chn < tot_channels; chn++) | |
410 | + kfree(csr->channels[chn]); | |
411 | + kfree(csr); | |
412 | + } | |
413 | + kfree(mci->csrows[i]); | |
414 | + } | |
415 | + kfree(mci->csrows); | |
416 | + } | |
417 | + kfree(mci); | |
418 | + | |
419 | + return NULL; | |
384 | 420 | } |
385 | 421 | EXPORT_SYMBOL_GPL(edac_mc_alloc); |
386 | 422 | |
387 | 423 | |
... | ... | @@ -393,10 +429,8 @@ |
393 | 429 | { |
394 | 430 | debugf1("%s()\n", __func__); |
395 | 431 | |
432 | + /* the mci instance is freed here, when the sysfs object is dropped */ | |
396 | 433 | edac_unregister_sysfs(mci); |
397 | - | |
398 | - /* free the mci instance memory here */ | |
399 | - kfree(mci); | |
400 | 434 | } |
401 | 435 | EXPORT_SYMBOL_GPL(edac_mc_free); |
402 | 436 | |
403 | 437 | |
... | ... | @@ -668,13 +702,12 @@ |
668 | 702 | for (i = 0; i < mci->nr_csrows; i++) { |
669 | 703 | int j; |
670 | 704 | |
671 | - edac_mc_dump_csrow(&mci->csrows[i]); | |
672 | - for (j = 0; j < mci->csrows[i].nr_channels; j++) | |
673 | - edac_mc_dump_channel(&mci->csrows[i]. | |
674 | - channels[j]); | |
705 | + edac_mc_dump_csrow(mci->csrows[i]); | |
706 | + for (j = 0; j < mci->csrows[i]->nr_channels; j++) | |
707 | + edac_mc_dump_channel(mci->csrows[i]->channels[j]); | |
675 | 708 | } |
676 | 709 | for (i = 0; i < mci->tot_dimms; i++) |
677 | - edac_mc_dump_dimm(&mci->dimms[i]); | |
710 | + edac_mc_dump_dimm(mci->dimms[i]); | |
678 | 711 | } |
679 | 712 | #endif |
680 | 713 | mutex_lock(&mem_ctls_mutex); |
681 | 714 | |
682 | 715 | |
... | ... | @@ -793,17 +826,17 @@ |
793 | 826 | /* FIXME - should return -1 */ |
794 | 827 | int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page) |
795 | 828 | { |
796 | - struct csrow_info *csrows = mci->csrows; | |
829 | + struct csrow_info **csrows = mci->csrows; | |
797 | 830 | int row, i, j, n; |
798 | 831 | |
799 | 832 | debugf1("MC%d: %s(): 0x%lx\n", mci->mc_idx, __func__, page); |
800 | 833 | row = -1; |
801 | 834 | |
802 | 835 | for (i = 0; i < mci->nr_csrows; i++) { |
803 | - struct csrow_info *csrow = &csrows[i]; | |
836 | + struct csrow_info *csrow = csrows[i]; | |
804 | 837 | n = 0; |
805 | 838 | for (j = 0; j < csrow->nr_channels; j++) { |
806 | - struct dimm_info *dimm = csrow->channels[j].dimm; | |
839 | + struct dimm_info *dimm = csrow->channels[j]->dimm; | |
807 | 840 | n += dimm->nr_pages; |
808 | 841 | } |
809 | 842 | if (n == 0) |
... | ... | @@ -1062,7 +1095,7 @@ |
1062 | 1095 | p = label; |
1063 | 1096 | *p = '\0'; |
1064 | 1097 | for (i = 0; i < mci->tot_dimms; i++) { |
1065 | - struct dimm_info *dimm = &mci->dimms[i]; | |
1098 | + struct dimm_info *dimm = mci->dimms[i]; | |
1066 | 1099 | |
1067 | 1100 | if (top_layer >= 0 && top_layer != dimm->location[0]) |
1068 | 1101 | continue; |
1069 | 1102 | |
1070 | 1103 | |
... | ... | @@ -1120,13 +1153,13 @@ |
1120 | 1153 | strcpy(label, "unknown memory"); |
1121 | 1154 | if (type == HW_EVENT_ERR_CORRECTED) { |
1122 | 1155 | if (row >= 0) { |
1123 | - mci->csrows[row].ce_count++; | |
1156 | + mci->csrows[row]->ce_count++; | |
1124 | 1157 | if (chan >= 0) |
1125 | - mci->csrows[row].channels[chan].ce_count++; | |
1158 | + mci->csrows[row]->channels[chan]->ce_count++; | |
1126 | 1159 | } |
1127 | 1160 | } else |
1128 | 1161 | if (row >= 0) |
1129 | - mci->csrows[row].ue_count++; | |
1162 | + mci->csrows[row]->ue_count++; | |
1130 | 1163 | } |
1131 | 1164 | |
1132 | 1165 | /* Fill the RAM location data */ |
drivers/edac/edac_mc_sysfs.c
... | ... | @@ -82,7 +82,7 @@ |
82 | 82 | &edac_mc_poll_msec, 0644); |
83 | 83 | MODULE_PARM_DESC(edac_mc_poll_msec, "Polling period in milliseconds"); |
84 | 84 | |
85 | -static struct device mci_pdev; | |
85 | +static struct device *mci_pdev; | |
86 | 86 | |
87 | 87 | /* |
88 | 88 | * various constants for Memory Controllers |
... | ... | @@ -181,7 +181,7 @@ |
181 | 181 | u32 nr_pages = 0; |
182 | 182 | |
183 | 183 | for (i = 0; i < csrow->nr_channels; i++) |
184 | - nr_pages += csrow->channels[i].dimm->nr_pages; | |
184 | + nr_pages += csrow->channels[i]->dimm->nr_pages; | |
185 | 185 | return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); |
186 | 186 | } |
187 | 187 | |
... | ... | @@ -190,7 +190,7 @@ |
190 | 190 | { |
191 | 191 | struct csrow_info *csrow = to_csrow(dev); |
192 | 192 | |
193 | - return sprintf(data, "%s\n", mem_types[csrow->channels[0].dimm->mtype]); | |
193 | + return sprintf(data, "%s\n", mem_types[csrow->channels[0]->dimm->mtype]); | |
194 | 194 | } |
195 | 195 | |
196 | 196 | static ssize_t csrow_dev_type_show(struct device *dev, |
... | ... | @@ -198,7 +198,7 @@ |
198 | 198 | { |
199 | 199 | struct csrow_info *csrow = to_csrow(dev); |
200 | 200 | |
201 | - return sprintf(data, "%s\n", dev_types[csrow->channels[0].dimm->dtype]); | |
201 | + return sprintf(data, "%s\n", dev_types[csrow->channels[0]->dimm->dtype]); | |
202 | 202 | } |
203 | 203 | |
204 | 204 | static ssize_t csrow_edac_mode_show(struct device *dev, |
... | ... | @@ -207,7 +207,7 @@ |
207 | 207 | { |
208 | 208 | struct csrow_info *csrow = to_csrow(dev); |
209 | 209 | |
210 | - return sprintf(data, "%s\n", edac_caps[csrow->channels[0].dimm->edac_mode]); | |
210 | + return sprintf(data, "%s\n", edac_caps[csrow->channels[0]->dimm->edac_mode]); | |
211 | 211 | } |
212 | 212 | |
213 | 213 | /* show/store functions for DIMM Label attributes */ |
... | ... | @@ -217,7 +217,7 @@ |
217 | 217 | { |
218 | 218 | struct csrow_info *csrow = to_csrow(dev); |
219 | 219 | unsigned chan = to_channel(mattr); |
220 | - struct rank_info *rank = &csrow->channels[chan]; | |
220 | + struct rank_info *rank = csrow->channels[chan]; | |
221 | 221 | |
222 | 222 | /* if field has not been initialized, there is nothing to send */ |
223 | 223 | if (!rank->dimm->label[0]) |
... | ... | @@ -233,7 +233,7 @@ |
233 | 233 | { |
234 | 234 | struct csrow_info *csrow = to_csrow(dev); |
235 | 235 | unsigned chan = to_channel(mattr); |
236 | - struct rank_info *rank = &csrow->channels[chan]; | |
236 | + struct rank_info *rank = csrow->channels[chan]; | |
237 | 237 | |
238 | 238 | ssize_t max_size = 0; |
239 | 239 | |
... | ... | @@ -250,7 +250,7 @@ |
250 | 250 | { |
251 | 251 | struct csrow_info *csrow = to_csrow(dev); |
252 | 252 | unsigned chan = to_channel(mattr); |
253 | - struct rank_info *rank = &csrow->channels[chan]; | |
253 | + struct rank_info *rank = csrow->channels[chan]; | |
254 | 254 | |
255 | 255 | return sprintf(data, "%u\n", rank->ce_count); |
256 | 256 | } |
257 | 257 | |
... | ... | @@ -283,9 +283,12 @@ |
283 | 283 | NULL |
284 | 284 | }; |
285 | 285 | |
286 | -static void csrow_attr_release(struct device *device) | |
286 | +static void csrow_attr_release(struct device *dev) | |
287 | 287 | { |
288 | - debugf1("Releasing csrow device %s\n", dev_name(device)); | |
288 | + struct csrow_info *csrow = container_of(dev, struct csrow_info, dev); | |
289 | + | |
290 | + debugf1("Releasing csrow device %s\n", dev_name(dev)); | |
291 | + kfree(csrow); | |
289 | 292 | } |
290 | 293 | |
291 | 294 | static struct device_type csrow_attr_type = { |
... | ... | @@ -352,7 +355,7 @@ |
352 | 355 | int chan, nr_pages = 0; |
353 | 356 | |
354 | 357 | for (chan = 0; chan < csrow->nr_channels; chan++) |
355 | - nr_pages += csrow->channels[chan].dimm->nr_pages; | |
358 | + nr_pages += csrow->channels[chan]->dimm->nr_pages; | |
356 | 359 | |
357 | 360 | return nr_pages; |
358 | 361 | } |
... | ... | @@ -382,7 +385,7 @@ |
382 | 385 | |
383 | 386 | for (chan = 0; chan < csrow->nr_channels; chan++) { |
384 | 387 | /* Only expose populated DIMMs */ |
385 | - if (!csrow->channels[chan].dimm->nr_pages) | |
388 | + if (!csrow->channels[chan]->dimm->nr_pages) | |
386 | 389 | continue; |
387 | 390 | err = device_create_file(&csrow->dev, |
388 | 391 | dynamic_csrow_dimm_attr[chan]); |
389 | 392 | |
... | ... | @@ -418,10 +421,10 @@ |
418 | 421 | struct csrow_info *csrow; |
419 | 422 | |
420 | 423 | for (i = 0; i < mci->nr_csrows; i++) { |
421 | - csrow = &mci->csrows[i]; | |
424 | + csrow = mci->csrows[i]; | |
422 | 425 | if (!nr_pages_per_csrow(csrow)) |
423 | 426 | continue; |
424 | - err = edac_create_csrow_object(mci, &mci->csrows[i], i); | |
427 | + err = edac_create_csrow_object(mci, mci->csrows[i], i); | |
425 | 428 | if (err < 0) |
426 | 429 | goto error; |
427 | 430 | } |
428 | 431 | |
429 | 432 | |
... | ... | @@ -429,18 +432,18 @@ |
429 | 432 | |
430 | 433 | error: |
431 | 434 | for (--i; i >= 0; i--) { |
432 | - csrow = &mci->csrows[i]; | |
435 | + csrow = mci->csrows[i]; | |
433 | 436 | if (!nr_pages_per_csrow(csrow)) |
434 | 437 | continue; |
435 | 438 | for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { |
436 | - if (!csrow->channels[chan].dimm->nr_pages) | |
439 | + if (!csrow->channels[chan]->dimm->nr_pages) | |
437 | 440 | continue; |
438 | 441 | device_remove_file(&csrow->dev, |
439 | 442 | dynamic_csrow_dimm_attr[chan]); |
440 | 443 | device_remove_file(&csrow->dev, |
441 | 444 | dynamic_csrow_ce_count_attr[chan]); |
442 | 445 | } |
443 | - put_device(&mci->csrows[i].dev); | |
446 | + put_device(&mci->csrows[i]->dev); | |
444 | 447 | } |
445 | 448 | |
446 | 449 | return err; |
447 | 450 | |
... | ... | @@ -452,11 +455,11 @@ |
452 | 455 | struct csrow_info *csrow; |
453 | 456 | |
454 | 457 | for (i = mci->nr_csrows - 1; i >= 0; i--) { |
455 | - csrow = &mci->csrows[i]; | |
458 | + csrow = mci->csrows[i]; | |
456 | 459 | if (!nr_pages_per_csrow(csrow)) |
457 | 460 | continue; |
458 | 461 | for (chan = csrow->nr_channels - 1; chan >= 0; chan--) { |
459 | - if (!csrow->channels[chan].dimm->nr_pages) | |
462 | + if (!csrow->channels[chan]->dimm->nr_pages) | |
460 | 463 | continue; |
461 | 464 | debugf1("Removing csrow %d channel %d sysfs nodes\n", |
462 | 465 | i, chan); |
... | ... | @@ -465,8 +468,8 @@ |
465 | 468 | device_remove_file(&csrow->dev, |
466 | 469 | dynamic_csrow_ce_count_attr[chan]); |
467 | 470 | } |
468 | - put_device(&mci->csrows[i].dev); | |
469 | - device_del(&mci->csrows[i].dev); | |
471 | + put_device(&mci->csrows[i]->dev); | |
472 | + device_del(&mci->csrows[i]->dev); | |
470 | 473 | } |
471 | 474 | } |
472 | 475 | #endif |
473 | 476 | |
... | ... | @@ -585,9 +588,12 @@ |
585 | 588 | NULL |
586 | 589 | }; |
587 | 590 | |
588 | -static void dimm_attr_release(struct device *device) | |
591 | +static void dimm_attr_release(struct device *dev) | |
589 | 592 | { |
590 | - debugf1("Releasing dimm device %s\n", dev_name(device)); | |
593 | + struct dimm_info *dimm = container_of(dev, struct dimm_info, dev); | |
594 | + | |
595 | + debugf1("Releasing dimm device %s\n", dev_name(dev)); | |
596 | + kfree(dimm); | |
591 | 597 | } |
592 | 598 | |
593 | 599 | static struct device_type dimm_attr_type = { |
594 | 600 | |
... | ... | @@ -641,13 +647,13 @@ |
641 | 647 | mci->ce_noinfo_count = 0; |
642 | 648 | |
643 | 649 | for (row = 0; row < mci->nr_csrows; row++) { |
644 | - struct csrow_info *ri = &mci->csrows[row]; | |
650 | + struct csrow_info *ri = mci->csrows[row]; | |
645 | 651 | |
646 | 652 | ri->ue_count = 0; |
647 | 653 | ri->ce_count = 0; |
648 | 654 | |
649 | 655 | for (chan = 0; chan < ri->nr_channels; chan++) |
650 | - ri->channels[chan].ce_count = 0; | |
656 | + ri->channels[chan]->ce_count = 0; | |
651 | 657 | } |
652 | 658 | |
653 | 659 | cnt = 1; |
654 | 660 | |
... | ... | @@ -779,10 +785,10 @@ |
779 | 785 | int total_pages = 0, csrow_idx, j; |
780 | 786 | |
781 | 787 | for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { |
782 | - struct csrow_info *csrow = &mci->csrows[csrow_idx]; | |
788 | + struct csrow_info *csrow = mci->csrows[csrow_idx]; | |
783 | 789 | |
784 | 790 | for (j = 0; j < csrow->nr_channels; j++) { |
785 | - struct dimm_info *dimm = csrow->channels[j].dimm; | |
791 | + struct dimm_info *dimm = csrow->channels[j]->dimm; | |
786 | 792 | |
787 | 793 | total_pages += dimm->nr_pages; |
788 | 794 | } |
789 | 795 | |
... | ... | @@ -889,9 +895,12 @@ |
889 | 895 | NULL |
890 | 896 | }; |
891 | 897 | |
892 | -static void mci_attr_release(struct device *device) | |
898 | +static void mci_attr_release(struct device *dev) | |
893 | 899 | { |
894 | - debugf1("Releasing mci device %s\n", dev_name(device)); | |
900 | + struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev); | |
901 | + | |
902 | + debugf1("Releasing csrow device %s\n", dev_name(dev)); | |
903 | + kfree(mci); | |
895 | 904 | } |
896 | 905 | |
897 | 906 | static struct device_type mci_attr_type = { |
898 | 907 | |
899 | 908 | |
900 | 909 | |
... | ... | @@ -950,29 +959,28 @@ |
950 | 959 | { |
951 | 960 | int i, err; |
952 | 961 | |
953 | - debugf0("%s() idx=%d\n", __func__, mci->mc_idx); | |
962 | + /* | |
963 | + * The memory controller needs its own bus, in order to avoid | |
964 | + * namespace conflicts at /sys/bus/edac. | |
965 | + */ | |
966 | + mci->bus.name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx); | |
967 | + if (!mci->bus.name) | |
968 | + return -ENOMEM; | |
969 | + debugf0("creating bus %s\n",mci->bus.name); | |
970 | + err = bus_register(&mci->bus); | |
971 | + if (err < 0) | |
972 | + return err; | |
954 | 973 | |
955 | 974 | /* get the /sys/devices/system/edac subsys reference */ |
956 | - | |
957 | 975 | mci->dev.type = &mci_attr_type; |
958 | 976 | device_initialize(&mci->dev); |
959 | 977 | |
960 | - mci->dev.parent = &mci_pdev; | |
978 | + mci->dev.parent = mci_pdev; | |
961 | 979 | mci->dev.bus = &mci->bus; |
962 | 980 | dev_set_name(&mci->dev, "mc%d", mci->mc_idx); |
963 | 981 | dev_set_drvdata(&mci->dev, mci); |
964 | 982 | pm_runtime_forbid(&mci->dev); |
965 | 983 | |
966 | - /* | |
967 | - * The memory controller needs its own bus, in order to avoid | |
968 | - * namespace conflicts at /sys/bus/edac. | |
969 | - */ | |
970 | - debugf0("creating bus %s\n",mci->bus.name); | |
971 | - mci->bus.name = kstrdup(dev_name(&mci->dev), GFP_KERNEL); | |
972 | - err = bus_register(&mci->bus); | |
973 | - if (err < 0) | |
974 | - return err; | |
975 | - | |
976 | 984 | debugf0("%s(): creating device %s\n", __func__, |
977 | 985 | dev_name(&mci->dev)); |
978 | 986 | err = device_add(&mci->dev); |
... | ... | @@ -986,7 +994,7 @@ |
986 | 994 | * Create the dimm/rank devices |
987 | 995 | */ |
988 | 996 | for (i = 0; i < mci->tot_dimms; i++) { |
989 | - struct dimm_info *dimm = &mci->dimms[i]; | |
997 | + struct dimm_info *dimm = mci->dimms[i]; | |
990 | 998 | /* Only expose populated DIMMs */ |
991 | 999 | if (dimm->nr_pages == 0) |
992 | 1000 | continue; |
... | ... | @@ -1023,7 +1031,7 @@ |
1023 | 1031 | |
1024 | 1032 | fail: |
1025 | 1033 | for (i--; i >= 0; i--) { |
1026 | - struct dimm_info *dimm = &mci->dimms[i]; | |
1034 | + struct dimm_info *dimm = mci->dimms[i]; | |
1027 | 1035 | if (dimm->nr_pages == 0) |
1028 | 1036 | continue; |
1029 | 1037 | put_device(&dimm->dev); |
... | ... | @@ -1053,7 +1061,7 @@ |
1053 | 1061 | #endif |
1054 | 1062 | |
1055 | 1063 | for (i = 0; i < mci->tot_dimms; i++) { |
1056 | - struct dimm_info *dimm = &mci->dimms[i]; | |
1064 | + struct dimm_info *dimm = mci->dimms[i]; | |
1057 | 1065 | if (dimm->nr_pages == 0) |
1058 | 1066 | continue; |
1059 | 1067 | debugf0("%s(): removing device %s\n", __func__, |
1060 | 1068 | |
... | ... | @@ -1072,9 +1080,15 @@ |
1072 | 1080 | kfree(mci->bus.name); |
1073 | 1081 | } |
1074 | 1082 | |
1075 | -static void mc_attr_release(struct device *device) | |
1083 | +static void mc_attr_release(struct device *dev) | |
1076 | 1084 | { |
1077 | - debugf1("Releasing device %s\n", dev_name(device)); | |
1085 | + /* | |
1086 | + * There's no container structure here, as this is just the mci | |
1087 | + * parent device, used to create the /sys/devices/mc sysfs node. | |
1088 | + * So, there are no attributes on it. | |
1089 | + */ | |
1090 | + debugf1("Releasing device %s\n", dev_name(dev)); | |
1091 | + kfree(dev); | |
1078 | 1092 | } |
1079 | 1093 | |
1080 | 1094 | static struct device_type mc_attr_type = { |
1081 | 1095 | |
1082 | 1096 | |
1083 | 1097 | |
... | ... | @@ -1095,22 +1109,26 @@ |
1095 | 1109 | return -EINVAL; |
1096 | 1110 | } |
1097 | 1111 | |
1098 | - mci_pdev.bus = edac_subsys; | |
1099 | - mci_pdev.type = &mc_attr_type; | |
1100 | - device_initialize(&mci_pdev); | |
1101 | - dev_set_name(&mci_pdev, "mc"); | |
1112 | + mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL); | |
1102 | 1113 | |
1103 | - err = device_add(&mci_pdev); | |
1114 | + mci_pdev->bus = edac_subsys; | |
1115 | + mci_pdev->type = &mc_attr_type; | |
1116 | + device_initialize(mci_pdev); | |
1117 | + dev_set_name(mci_pdev, "mc"); | |
1118 | + | |
1119 | + err = device_add(mci_pdev); | |
1104 | 1120 | if (err < 0) |
1105 | 1121 | return err; |
1106 | 1122 | |
1123 | + debugf0("device %s created\n", dev_name(mci_pdev)); | |
1124 | + | |
1107 | 1125 | return 0; |
1108 | 1126 | } |
1109 | 1127 | |
1110 | 1128 | void __exit edac_mc_sysfs_exit(void) |
1111 | 1129 | { |
1112 | - put_device(&mci_pdev); | |
1113 | - device_del(&mci_pdev); | |
1130 | + put_device(mci_pdev); | |
1131 | + device_del(mci_pdev); | |
1114 | 1132 | edac_put_sysfs_subsys(); |
1115 | 1133 | } |
drivers/edac/i3000_edac.c
... | ... | @@ -236,7 +236,7 @@ |
236 | 236 | int row, multi_chan, channel; |
237 | 237 | unsigned long pfn, offset; |
238 | 238 | |
239 | - multi_chan = mci->csrows[0].nr_channels - 1; | |
239 | + multi_chan = mci->csrows[0]->nr_channels - 1; | |
240 | 240 | |
241 | 241 | if (!(info->errsts & I3000_ERRSTS_BITS)) |
242 | 242 | return 0; |
... | ... | @@ -393,7 +393,7 @@ |
393 | 393 | for (last_cumul_size = i = 0; i < mci->nr_csrows; i++) { |
394 | 394 | u8 value; |
395 | 395 | u32 cumul_size; |
396 | - struct csrow_info *csrow = &mci->csrows[i]; | |
396 | + struct csrow_info *csrow = mci->csrows[i]; | |
397 | 397 | |
398 | 398 | value = drb[i]; |
399 | 399 | cumul_size = value << (I3000_DRB_SHIFT - PAGE_SHIFT); |
... | ... | @@ -410,7 +410,7 @@ |
410 | 410 | last_cumul_size = cumul_size; |
411 | 411 | |
412 | 412 | for (j = 0; j < nr_channels; j++) { |
413 | - struct dimm_info *dimm = csrow->channels[j].dimm; | |
413 | + struct dimm_info *dimm = csrow->channels[j]->dimm; | |
414 | 414 | |
415 | 415 | dimm->nr_pages = nr_pages / nr_channels; |
416 | 416 | dimm->grain = I3000_DEAP_GRAIN; |
drivers/edac/i3200_edac.c
... | ... | @@ -379,7 +379,7 @@ |
379 | 379 | */ |
380 | 380 | for (i = 0; i < mci->nr_csrows; i++) { |
381 | 381 | unsigned long nr_pages; |
382 | - struct csrow_info *csrow = &mci->csrows[i]; | |
382 | + struct csrow_info *csrow = mci->csrows[i]; | |
383 | 383 | |
384 | 384 | nr_pages = drb_to_nr_pages(drbs, stacked, |
385 | 385 | i / I3200_RANKS_PER_CHANNEL, |
... | ... | @@ -389,7 +389,7 @@ |
389 | 389 | continue; |
390 | 390 | |
391 | 391 | for (j = 0; j < nr_channels; j++) { |
392 | - struct dimm_info *dimm = csrow->channels[j].dimm; | |
392 | + struct dimm_info *dimm = csrow->channels[j]->dimm; | |
393 | 393 | |
394 | 394 | dimm->nr_pages = nr_pages / nr_channels; |
395 | 395 | dimm->grain = nr_pages << PAGE_SHIFT; |
drivers/edac/i5400_edac.c
... | ... | @@ -1203,8 +1203,8 @@ |
1203 | 1203 | |
1204 | 1204 | size_mb = pvt->dimm_info[slot][channel].megabytes; |
1205 | 1205 | |
1206 | - debugf2("%s: dimm%zd (branch %d channel %d slot %d): %d.%03d GB\n", | |
1207 | - __func__, dimm - mci->dimms, | |
1206 | + debugf2("%s: dimm (branch %d channel %d slot %d): %d.%03d GB\n", | |
1207 | + __func__, | |
1208 | 1208 | channel / 2, channel % 2, slot, |
1209 | 1209 | size_mb / 1000, size_mb % 1000); |
1210 | 1210 | |
... | ... | @@ -1227,7 +1227,7 @@ |
1227 | 1227 | * With such single-DIMM mode, the SDCC algorithm degrades to SECDEC+. |
1228 | 1228 | */ |
1229 | 1229 | if (ndimms == 1) |
1230 | - mci->dimms[0].edac_mode = EDAC_SECDED; | |
1230 | + mci->dimms[0]->edac_mode = EDAC_SECDED; | |
1231 | 1231 | |
1232 | 1232 | return (ndimms == 0); |
1233 | 1233 | } |
drivers/edac/i82443bxgx_edac.c
... | ... | @@ -197,8 +197,8 @@ |
197 | 197 | pci_read_config_byte(pdev, I82443BXGX_DRAMC, &dramc); |
198 | 198 | row_high_limit_last = 0; |
199 | 199 | for (index = 0; index < mci->nr_csrows; index++) { |
200 | - csrow = &mci->csrows[index]; | |
201 | - dimm = csrow->channels[0].dimm; | |
200 | + csrow = mci->csrows[index]; | |
201 | + dimm = csrow->channels[0]->dimm; | |
202 | 202 | |
203 | 203 | pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); |
204 | 204 | debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", |
drivers/edac/i82860_edac.c
... | ... | @@ -116,7 +116,7 @@ |
116 | 116 | |
117 | 117 | info->eap >>= PAGE_SHIFT; |
118 | 118 | row = edac_mc_find_csrow_by_page(mci, info->eap); |
119 | - dimm = mci->csrows[row].channels[0].dimm; | |
119 | + dimm = mci->csrows[row]->channels[0]->dimm; | |
120 | 120 | |
121 | 121 | if (info->errsts & 0x0002) |
122 | 122 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, |
... | ... | @@ -161,8 +161,8 @@ |
161 | 161 | * in all eight rows. |
162 | 162 | */ |
163 | 163 | for (index = 0; index < mci->nr_csrows; index++) { |
164 | - csrow = &mci->csrows[index]; | |
165 | - dimm = csrow->channels[0].dimm; | |
164 | + csrow = mci->csrows[index]; | |
165 | + dimm = csrow->channels[0]->dimm; | |
166 | 166 | |
167 | 167 | pci_read_config_word(pdev, I82860_GBA + index * 2, &value); |
168 | 168 | cumul_size = (value & I82860_GBA_MASK) << |
drivers/edac/i82875p_edac.c
... | ... | @@ -227,7 +227,7 @@ |
227 | 227 | { |
228 | 228 | int row, multi_chan; |
229 | 229 | |
230 | - multi_chan = mci->csrows[0].nr_channels - 1; | |
230 | + multi_chan = mci->csrows[0]->nr_channels - 1; | |
231 | 231 | |
232 | 232 | if (!(info->errsts & 0x0081)) |
233 | 233 | return 0; |
... | ... | @@ -367,7 +367,7 @@ |
367 | 367 | */ |
368 | 368 | |
369 | 369 | for (index = 0; index < mci->nr_csrows; index++) { |
370 | - csrow = &mci->csrows[index]; | |
370 | + csrow = mci->csrows[index]; | |
371 | 371 | |
372 | 372 | value = readb(ovrfl_window + I82875P_DRB + index); |
373 | 373 | cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT); |
... | ... | @@ -382,7 +382,7 @@ |
382 | 382 | last_cumul_size = cumul_size; |
383 | 383 | |
384 | 384 | for (j = 0; j < nr_chans; j++) { |
385 | - dimm = csrow->channels[j].dimm; | |
385 | + dimm = csrow->channels[j]->dimm; | |
386 | 386 | |
387 | 387 | dimm->nr_pages = nr_pages / nr_chans; |
388 | 388 | dimm->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */ |
drivers/edac/i82975x_edac.c
... | ... | @@ -308,10 +308,10 @@ |
308 | 308 | (info->xeap & 1) ? 1 : 0, info->eap, (unsigned int) page); |
309 | 309 | return 0; |
310 | 310 | } |
311 | - chan = (mci->csrows[row].nr_channels == 1) ? 0 : info->eap & 1; | |
311 | + chan = (mci->csrows[row]->nr_channels == 1) ? 0 : info->eap & 1; | |
312 | 312 | offst = info->eap |
313 | 313 | & ((1 << PAGE_SHIFT) - |
314 | - (1 << mci->csrows[row].channels[chan].dimm->grain)); | |
314 | + (1 << mci->csrows[row]->channels[chan]->dimm->grain)); | |
315 | 315 | |
316 | 316 | if (info->errsts & 0x0002) |
317 | 317 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, |
... | ... | @@ -394,7 +394,7 @@ |
394 | 394 | */ |
395 | 395 | |
396 | 396 | for (index = 0; index < mci->nr_csrows; index++) { |
397 | - csrow = &mci->csrows[index]; | |
397 | + csrow = mci->csrows[index]; | |
398 | 398 | |
399 | 399 | value = readb(mch_window + I82975X_DRB + index + |
400 | 400 | ((index >= 4) ? 0x80 : 0)); |
401 | 401 | |
... | ... | @@ -421,10 +421,10 @@ |
421 | 421 | */ |
422 | 422 | dtype = i82975x_dram_type(mch_window, index); |
423 | 423 | for (chan = 0; chan < csrow->nr_channels; chan++) { |
424 | - dimm = mci->csrows[index].channels[chan].dimm; | |
424 | + dimm = mci->csrows[index]->channels[chan]->dimm; | |
425 | 425 | |
426 | 426 | dimm->nr_pages = nr_pages / csrow->nr_channels; |
427 | - strncpy(csrow->channels[chan].dimm->label, | |
427 | + strncpy(csrow->channels[chan]->dimm->label, | |
428 | 428 | labels[(index >> 1) + (chan * 2)], |
429 | 429 | EDAC_MC_LABEL_LEN); |
430 | 430 | dimm->grain = 1 << 7; /* 128Byte cache-line resolution */ |
drivers/edac/mpc85xx_edac.c
... | ... | @@ -825,7 +825,7 @@ |
825 | 825 | pfn = err_addr >> PAGE_SHIFT; |
826 | 826 | |
827 | 827 | for (row_index = 0; row_index < mci->nr_csrows; row_index++) { |
828 | - csrow = &mci->csrows[row_index]; | |
828 | + csrow = mci->csrows[row_index]; | |
829 | 829 | if ((pfn >= csrow->first_page) && (pfn <= csrow->last_page)) |
830 | 830 | break; |
831 | 831 | } |
... | ... | @@ -945,8 +945,8 @@ |
945 | 945 | u32 start; |
946 | 946 | u32 end; |
947 | 947 | |
948 | - csrow = &mci->csrows[index]; | |
949 | - dimm = csrow->channels[0].dimm; | |
948 | + csrow = mci->csrows[index]; | |
949 | + dimm = csrow->channels[0]->dimm; | |
950 | 950 | |
951 | 951 | cs_bnds = in_be32(pdata->mc_vbase + MPC85XX_MC_CS_BNDS_0 + |
952 | 952 | (index * MPC85XX_MC_CS_BNDS_OFS)); |
drivers/edac/mv64x60_edac.c
... | ... | @@ -670,8 +670,8 @@ |
670 | 670 | |
671 | 671 | ctl = in_le32(pdata->mc_vbase + MV64X60_SDRAM_CONFIG); |
672 | 672 | |
673 | - csrow = &mci->csrows[0]; | |
674 | - dimm = csrow->channels[0].dimm; | |
673 | + csrow = mci->csrows[0]; | |
674 | + dimm = csrow->channels[0]->dimm; | |
675 | 675 | |
676 | 676 | dimm->nr_pages = pdata->total_mem >> PAGE_SHIFT; |
677 | 677 | dimm->grain = 8; |
drivers/edac/pasemi_edac.c
... | ... | @@ -111,14 +111,14 @@ |
111 | 111 | if (errsta & (MCDEBUG_ERRSTA_MBE_STATUS | |
112 | 112 | MCDEBUG_ERRSTA_RFL_STATUS)) { |
113 | 113 | edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, |
114 | - mci->csrows[cs].first_page, 0, 0, | |
114 | + mci->csrows[cs]->first_page, 0, 0, | |
115 | 115 | cs, 0, -1, mci->ctl_name, "", NULL); |
116 | 116 | } |
117 | 117 | |
118 | 118 | /* correctable/single-bit errors */ |
119 | 119 | if (errsta & MCDEBUG_ERRSTA_SBE_STATUS) |
120 | 120 | edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, |
121 | - mci->csrows[cs].first_page, 0, 0, | |
121 | + mci->csrows[cs]->first_page, 0, 0, | |
122 | 122 | cs, 0, -1, mci->ctl_name, "", NULL); |
123 | 123 | } |
124 | 124 | |
... | ... | @@ -141,8 +141,8 @@ |
141 | 141 | int index; |
142 | 142 | |
143 | 143 | for (index = 0; index < mci->nr_csrows; index++) { |
144 | - csrow = &mci->csrows[index]; | |
145 | - dimm = csrow->channels[0].dimm; | |
144 | + csrow = mci->csrows[index]; | |
145 | + dimm = csrow->channels[0]->dimm; | |
146 | 146 | |
147 | 147 | pci_read_config_dword(pdev, |
148 | 148 | MCDRAM_RANKCFG + (index * 12), |
drivers/edac/r82600_edac.c
... | ... | @@ -230,8 +230,8 @@ |
230 | 230 | row_high_limit_last = 0; |
231 | 231 | |
232 | 232 | for (index = 0; index < mci->nr_csrows; index++) { |
233 | - csrow = &mci->csrows[index]; | |
234 | - dimm = csrow->channels[0].dimm; | |
233 | + csrow = mci->csrows[index]; | |
234 | + dimm = csrow->channels[0]->dimm; | |
235 | 235 | |
236 | 236 | /* find the DRAM Chip Select Base address and mask */ |
237 | 237 | pci_read_config_byte(pdev, R82600_DRBA + index, &drbar); |
drivers/edac/tile_edac.c
... | ... | @@ -84,10 +84,10 @@ |
84 | 84 | */ |
85 | 85 | static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci) |
86 | 86 | { |
87 | - struct csrow_info *csrow = &mci->csrows[0]; | |
87 | + struct csrow_info *csrow = mci->csrows[0]; | |
88 | 88 | struct tile_edac_priv *priv = mci->pvt_info; |
89 | 89 | struct mshim_mem_info mem_info; |
90 | - struct dimm_info *dimm = csrow->channels[0].dimm; | |
90 | + struct dimm_info *dimm = csrow->channels[0]->dimm; | |
91 | 91 | |
92 | 92 | if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info, |
93 | 93 | sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) != |
drivers/edac/x38_edac.c
... | ... | @@ -378,7 +378,7 @@ |
378 | 378 | */ |
379 | 379 | for (i = 0; i < mci->nr_csrows; i++) { |
380 | 380 | unsigned long nr_pages; |
381 | - struct csrow_info *csrow = &mci->csrows[i]; | |
381 | + struct csrow_info *csrow = mci->csrows[i]; | |
382 | 382 | |
383 | 383 | nr_pages = drb_to_nr_pages(drbs, stacked, |
384 | 384 | i / X38_RANKS_PER_CHANNEL, |
... | ... | @@ -388,7 +388,7 @@ |
388 | 388 | continue; |
389 | 389 | |
390 | 390 | for (j = 0; j < x38_channel_num; j++) { |
391 | - struct dimm_info *dimm = csrow->channels[j].dimm; | |
391 | + struct dimm_info *dimm = csrow->channels[j]->dimm; | |
392 | 392 | |
393 | 393 | dimm->nr_pages = nr_pages / x38_channel_num; |
394 | 394 | dimm->grain = nr_pages << PAGE_SHIFT; |
include/linux/edac.h
... | ... | @@ -412,23 +412,21 @@ |
412 | 412 | #define EDAC_MAX_LAYERS 3 |
413 | 413 | |
414 | 414 | /** |
415 | - * EDAC_DIMM_PTR - Macro responsible to find a pointer inside a pointer array | |
415 | + * EDAC_DIMM_OFF - Macro responsible to get a pointer offset inside a pointer array | |
416 | 416 | * for the element given by [layer0,layer1,layer2] position |
417 | 417 | * |
418 | 418 | * @layers: a struct edac_mc_layer array, describing how many elements |
419 | 419 | * were allocated for each layer |
420 | - * @var: name of the var where we want to get the pointer | |
421 | - * (like mci->dimms) | |
422 | 420 | * @n_layers: Number of layers at the @layers array |
423 | 421 | * @layer0: layer0 position |
424 | 422 | * @layer1: layer1 position. Unused if n_layers < 2 |
425 | 423 | * @layer2: layer2 position. Unused if n_layers < 3 |
426 | 424 | * |
427 | - * For 1 layer, this macro returns &var[layer0] | |
425 | + * For 1 layer, this macro returns &var[layer0] - &var | |
428 | 426 | * For 2 layers, this macro is similar to allocate a bi-dimensional array |
429 | - * and to return "&var[layer0][layer1]" | |
427 | + * and to return "&var[layer0][layer1] - &var" | |
430 | 428 | * For 3 layers, this macro is similar to allocate a tri-dimensional array |
431 | - * and to return "&var[layer0][layer1][layer2]" | |
429 | + * and to return "&var[layer0][layer1][layer2] - &var" | |
432 | 430 | * |
433 | 431 | * A loop could be used here to make it more generic, but, as we only have |
434 | 432 | * 3 layers, this is a little faster. |
435 | 433 | |
436 | 434 | |
437 | 435 | |
438 | 436 | |
439 | 437 | |
... | ... | @@ -436,17 +434,46 @@ |
436 | 434 | * a NULL is returned, causing an OOPS during the memory allocation routine, |
437 | 435 | * with would point to the developer that he's doing something wrong. |
438 | 436 | */ |
439 | -#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ | |
440 | - typeof(var) __p; \ | |
437 | +#define EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2) ({ \ | |
438 | + int __i; \ | |
441 | 439 | if ((nlayers) == 1) \ |
442 | - __p = &var[layer0]; \ | |
440 | + __i = layer0; \ | |
443 | 441 | else if ((nlayers) == 2) \ |
444 | - __p = &var[(layer1) + ((layers[1]).size * (layer0))]; \ | |
442 | + __i = (layer1) + ((layers[1]).size * (layer0)); \ | |
445 | 443 | else if ((nlayers) == 3) \ |
446 | - __p = &var[(layer2) + ((layers[2]).size * ((layer1) + \ | |
447 | - ((layers[1]).size * (layer0))))]; \ | |
444 | + __i = (layer2) + ((layers[2]).size * ((layer1) + \ | |
445 | + ((layers[1]).size * (layer0)))); \ | |
448 | 446 | else \ |
447 | + __i = -EINVAL; \ | |
448 | + __i; \ | |
449 | +}) | |
450 | + | |
451 | +/** | |
452 | + * EDAC_DIMM_PTR - Macro responsible to get a pointer inside a pointer array | |
453 | + * for the element given by [layer0,layer1,layer2] position | |
454 | + * | |
455 | + * @layers: a struct edac_mc_layer array, describing how many elements | |
456 | + * were allocated for each layer | |
457 | + * @var: name of the var where we want to get the pointer | |
458 | + * (like mci->dimms) | |
459 | + * @n_layers: Number of layers at the @layers array | |
460 | + * @layer0: layer0 position | |
461 | + * @layer1: layer1 position. Unused if n_layers < 2 | |
462 | + * @layer2: layer2 position. Unused if n_layers < 3 | |
463 | + * | |
464 | + * For 1 layer, this macro returns &var[layer0] | |
465 | + * For 2 layers, this macro is similar to allocate a bi-dimensional array | |
466 | + * and to return "&var[layer0][layer1]" | |
467 | + * For 3 layers, this macro is similar to allocate a tri-dimensional array | |
468 | + * and to return "&var[layer0][layer1][layer2]" | |
469 | + */ | |
470 | +#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \ | |
471 | + typeof(*var) __p; \ | |
472 | + int ___i = EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2); \ | |
473 | + if (___i < 0) \ | |
449 | 474 | __p = NULL; \ |
475 | + else \ | |
476 | + __p = (var)[___i]; \ | |
450 | 477 | __p; \ |
451 | 478 | }) |
452 | 479 | |
... | ... | @@ -486,8 +513,6 @@ |
486 | 513 | * patches in this series will fix this issue. |
487 | 514 | */ |
488 | 515 | struct rank_info { |
489 | - struct device dev; | |
490 | - | |
491 | 516 | int chan_idx; |
492 | 517 | struct csrow_info *csrow; |
493 | 518 | struct dimm_info *dimm; |
... | ... | @@ -513,7 +538,7 @@ |
513 | 538 | |
514 | 539 | /* channel information for this csrow */ |
515 | 540 | u32 nr_channels; |
516 | - struct rank_info *channels; | |
541 | + struct rank_info **channels; | |
517 | 542 | }; |
518 | 543 | |
519 | 544 | /* |
... | ... | @@ -572,7 +597,7 @@ |
572 | 597 | unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci, |
573 | 598 | unsigned long page); |
574 | 599 | int mc_idx; |
575 | - struct csrow_info *csrows; | |
600 | + struct csrow_info **csrows; | |
576 | 601 | unsigned nr_csrows, num_cschannel; |
577 | 602 | |
578 | 603 | /* |
... | ... | @@ -592,7 +617,7 @@ |
592 | 617 | * DIMM info. Will eventually remove the entire csrows_info some day |
593 | 618 | */ |
594 | 619 | unsigned tot_dimms; |
595 | - struct dimm_info *dimms; | |
620 | + struct dimm_info **dimms; | |
596 | 621 | |
597 | 622 | /* |
598 | 623 | * FIXME - what about controllers on other busses? - IDs must be |