]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - include/linux/edac.h
mm: clean up and clarify lruvec lookup procedure
[linux.git] / include / linux / edac.h
index c19483b900794cd8a478f265a6873bea054ac712..cc31b974268424f926726b2528e8e03126e95b1d 100644 (file)
@@ -362,78 +362,6 @@ struct edac_mc_layer {
  */
 #define EDAC_MAX_LAYERS                3
 
-/**
- * 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
- * @nlayers:   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] - var";
- *
- * For 2 layers, this macro is similar to allocate a bi-dimensional array
- * 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] - var".
- *
- * A loop could be used here to make it more generic, but, as we only have
- * 3 layers, this is a little faster.
- *
- * By design, layers can never be 0 or more than 3. If that ever happens,
- * 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_OFF(layers, nlayers, layer0, layer1, layer2) ({              \
-       int __i;                                                        \
-       if ((nlayers) == 1)                                             \
-               __i = layer0;                                           \
-       else if ((nlayers) == 2)                                        \
-               __i = (layer1) + ((layers[1]).size * (layer0));         \
-       else if ((nlayers) == 3)                                        \
-               __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)
- * @nlayers:   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;                                                            \
-})
-
 struct dimm_info {
        struct device dev;
 
@@ -443,6 +371,7 @@ struct dimm_info {
        unsigned int location[EDAC_MAX_LAYERS];
 
        struct mem_ctl_info *mci;       /* the parent */
+       unsigned int idx;               /* index within the parent dimm array */
 
        u32 grain;              /* granularity of reported error in bytes */
        enum dev_type dtype;    /* memory device type */
@@ -528,15 +457,10 @@ struct errcount_attribute_data {
  *                             (typically, a memory controller error)
  */
 struct edac_raw_error_desc {
-       /*
-        * NOTE: everything before grain won't be cleaned by
-        * edac_raw_error_desc_clean()
-        */
        char location[LOCATION_SIZE];
        char label[(EDAC_MC_LABEL_LEN + 1 + sizeof(OTHER_LABEL)) * EDAC_MAX_LABELS];
        long grain;
 
-       /* the vars below and grain will be cleaned on every new error report */
        u16 error_count;
        int top_layer;
        int mid_layer;
@@ -669,4 +593,70 @@ struct mem_ctl_info {
        bool fake_inject_ue;
        u16 fake_inject_count;
 };
-#endif
+
+#define mci_for_each_dimm(mci, dimm)                           \
+       for ((dimm) = (mci)->dimms[0];                          \
+            (dimm);                                            \
+            (dimm) = (dimm)->idx + 1 < (mci)->tot_dimms        \
+                    ? (mci)->dimms[(dimm)->idx + 1]            \
+                    : NULL)
+
+/**
+ * edac_get_dimm_by_index - Get DIMM info at @index from a memory
+ *                         controller
+ *
+ * @mci:       MC descriptor struct mem_ctl_info
+ * @index:     index in the memory controller's DIMM array
+ *
+ * Returns a struct dimm_info * or NULL on failure.
+ */
+static inline struct dimm_info *
+edac_get_dimm_by_index(struct mem_ctl_info *mci, int index)
+{
+       if (index < 0 || index >= mci->tot_dimms)
+               return NULL;
+
+       if (WARN_ON_ONCE(mci->dimms[index]->idx != index))
+               return NULL;
+
+       return mci->dimms[index];
+}
+
+/**
+ * edac_get_dimm - Get DIMM info from a memory controller given by
+ *                 [layer0,layer1,layer2] position
+ *
+ * @mci:       MC descriptor struct mem_ctl_info
+ * @layer0:    layer0 position
+ * @layer1:    layer1 position. Unused if n_layers < 2
+ * @layer2:    layer2 position. Unused if n_layers < 3
+ *
+ * For 1 layer, this function returns "dimms[layer0]";
+ *
+ * For 2 layers, this function is similar to allocating a two-dimensional
+ * array and returning "dimms[layer0][layer1]";
+ *
+ * For 3 layers, this function is similar to allocating a tri-dimensional
+ * array and returning "dimms[layer0][layer1][layer2]";
+ */
+static inline struct dimm_info *edac_get_dimm(struct mem_ctl_info *mci,
+       int layer0, int layer1, int layer2)
+{
+       int index;
+
+       if (layer0 < 0
+           || (mci->n_layers > 1 && layer1 < 0)
+           || (mci->n_layers > 2 && layer2 < 0))
+               return NULL;
+
+       index = layer0;
+
+       if (mci->n_layers > 1)
+               index = index * mci->layers[1].size + layer1;
+
+       if (mci->n_layers > 2)
+               index = index * mci->layers[2].size + layer2;
+
+       return edac_get_dimm_by_index(mci, index);
+}
+#endif /* _LINUX_EDAC_H_ */