aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/include/linux/edac.h
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-04-24 15:05:43 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-06-11 13:23:45 -0300
commitde3910eb79ac8c0f29a11224661c0ebaaf813039 (patch)
tree44584d6691588b2c18823260be0e44f0c9872d02 /include/linux/edac.h
parentedac: Only expose csrows/channels on legacy API if they're populated (diff)
downloadwireguard-linux-de3910eb79ac8c0f29a11224661c0ebaaf813039.tar.xz
wireguard-linux-de3910eb79ac8c0f29a11224661c0ebaaf813039.zip
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>
Diffstat (limited to 'include/linux/edac.h')
-rw-r--r--include/linux/edac.h59
1 files changed, 42 insertions, 17 deletions
diff --git a/include/linux/edac.h b/include/linux/edac.h
index 64ae0c5cf62e..6677af853e30 100644
--- a/include/linux/edac.h
+++ b/include/linux/edac.h
@@ -412,23 +412,21 @@ struct edac_mc_layer {
#define EDAC_MAX_LAYERS 3
/**
- * EDAC_DIMM_PTR - Macro responsible to find a pointer inside a pointer array
+ * EDAC_DIMM_OFF - Macro responsible to get a pointer offset inside a pointer array
* for the element given by [layer0,layer1,layer2] position
*
* @layers: a struct edac_mc_layer array, describing how many elements
* were allocated for each layer
- * @var: name of the var where we want to get the pointer
- * (like mci->dimms)
* @n_layers: Number of layers at the @layers array
* @layer0: layer0 position
* @layer1: layer1 position. Unused if n_layers < 2
* @layer2: layer2 position. Unused if n_layers < 3
*
- * For 1 layer, this macro returns &var[layer0]
+ * For 1 layer, this macro returns &var[layer0] - &var
* For 2 layers, this macro is similar to allocate a bi-dimensional array
- * and to return "&var[layer0][layer1]"
+ * and to return "&var[layer0][layer1] - &var"
* For 3 layers, this macro is similar to allocate a tri-dimensional array
- * and to return "&var[layer0][layer1][layer2]"
+ * and to return "&var[layer0][layer1][layer2] - &var"
*
* A loop could be used here to make it more generic, but, as we only have
* 3 layers, this is a little faster.
@@ -436,17 +434,46 @@ struct edac_mc_layer {
* a NULL is returned, causing an OOPS during the memory allocation routine,
* with would point to the developer that he's doing something wrong.
*/
-#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \
- typeof(var) __p; \
+#define EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2) ({ \
+ int __i; \
if ((nlayers) == 1) \
- __p = &var[layer0]; \
+ __i = layer0; \
else if ((nlayers) == 2) \
- __p = &var[(layer1) + ((layers[1]).size * (layer0))]; \
+ __i = (layer1) + ((layers[1]).size * (layer0)); \
else if ((nlayers) == 3) \
- __p = &var[(layer2) + ((layers[2]).size * ((layer1) + \
- ((layers[1]).size * (layer0))))]; \
+ __i = (layer2) + ((layers[2]).size * ((layer1) + \
+ ((layers[1]).size * (layer0)))); \
else \
+ __i = -EINVAL; \
+ __i; \
+})
+
+/**
+ * EDAC_DIMM_PTR - Macro responsible to get a pointer inside a pointer array
+ * for the element given by [layer0,layer1,layer2] position
+ *
+ * @layers: a struct edac_mc_layer array, describing how many elements
+ * were allocated for each layer
+ * @var: name of the var where we want to get the pointer
+ * (like mci->dimms)
+ * @n_layers: Number of layers at the @layers array
+ * @layer0: layer0 position
+ * @layer1: layer1 position. Unused if n_layers < 2
+ * @layer2: layer2 position. Unused if n_layers < 3
+ *
+ * For 1 layer, this macro returns &var[layer0]
+ * For 2 layers, this macro is similar to allocate a bi-dimensional array
+ * and to return "&var[layer0][layer1]"
+ * For 3 layers, this macro is similar to allocate a tri-dimensional array
+ * and to return "&var[layer0][layer1][layer2]"
+ */
+#define EDAC_DIMM_PTR(layers, var, nlayers, layer0, layer1, layer2) ({ \
+ typeof(*var) __p; \
+ int ___i = EDAC_DIMM_OFF(layers, nlayers, layer0, layer1, layer2); \
+ if (___i < 0) \
__p = NULL; \
+ else \
+ __p = (var)[___i]; \
__p; \
})
@@ -486,8 +513,6 @@ struct dimm_info {
* patches in this series will fix this issue.
*/
struct rank_info {
- struct device dev;
-
int chan_idx;
struct csrow_info *csrow;
struct dimm_info *dimm;
@@ -513,7 +538,7 @@ struct csrow_info {
/* channel information for this csrow */
u32 nr_channels;
- struct rank_info *channels;
+ struct rank_info **channels;
};
/*
@@ -572,7 +597,7 @@ struct mem_ctl_info {
unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
unsigned long page);
int mc_idx;
- struct csrow_info *csrows;
+ struct csrow_info **csrows;
unsigned nr_csrows, num_cschannel;
/*
@@ -592,7 +617,7 @@ struct mem_ctl_info {
* DIMM info. Will eventually remove the entire csrows_info some day
*/
unsigned tot_dimms;
- struct dimm_info *dimms;
+ struct dimm_info **dimms;
/*
* FIXME - what about controllers on other busses? - IDs must be