edac_dbg(4, "    channel->dimm = %p\n", chan->dimm);
 }
 
-static void edac_mc_dump_dimm(struct dimm_info *dimm, int number)
+static void edac_mc_dump_dimm(struct dimm_info *dimm)
 {
        char location[80];
 
+       if (!dimm->nr_pages)
+               return;
+
        edac_dimm_info_location(dimm, location, sizeof(location));
 
        edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n",
                 dimm->mci->csbased ? "rank" : "dimm",
-                number, location, dimm->csrow, dimm->cschannel);
+                dimm->idx, location, dimm->csrow, dimm->cschannel);
        edac_dbg(4, "  dimm = %p\n", dimm);
        edac_dbg(4, "  dimm->label = '%s'\n", dimm->label);
        edac_dbg(4, "  dimm->nr_pages = 0x%x\n", dimm->nr_pages);
                edac_mc_dump_mci(mci);
 
        if (edac_debug_level >= 4) {
+               struct dimm_info *dimm;
                int i;
 
                for (i = 0; i < mci->nr_csrows; i++) {
                                if (csrow->channels[j]->dimm->nr_pages)
                                        edac_mc_dump_channel(csrow->channels[j]);
                }
-               for (i = 0; i < mci->tot_dimms; i++)
-                       if (mci->dimms[i]->nr_pages)
-                               edac_mc_dump_dimm(mci->dimms[i], i);
+
+               mci_for_each_dimm(mci, dimm)
+                       edac_mc_dump_dimm(dimm);
        }
 #endif
        mutex_lock(&mem_ctls_mutex);
                          const char *msg,
                          const char *other_detail)
 {
+       struct dimm_info *dimm;
        char *p;
        int row = -1, chan = -1;
        int pos[EDAC_MAX_LAYERS] = { top_layer, mid_layer, low_layer };
        p = e->label;
        *p = '\0';
 
-       for (i = 0; i < mci->tot_dimms; i++) {
-               struct dimm_info *dimm = mci->dimms[i];
-
+       mci_for_each_dimm(mci, dimm) {
                if (top_layer >= 0 && top_layer != dimm->location[0])
                        continue;
                if (mid_layer >= 0 && mid_layer != dimm->location[1])
 
 
 /* Create a DIMM object under specifed memory controller device */
 static int edac_create_dimm_object(struct mem_ctl_info *mci,
-                                  struct dimm_info *dimm,
-                                  int index)
+                                  struct dimm_info *dimm)
 {
        int err;
        dimm->mci = mci;
 
        dimm->dev.parent = &mci->dev;
        if (mci->csbased)
-               dev_set_name(&dimm->dev, "rank%d", index);
+               dev_set_name(&dimm->dev, "rank%d", dimm->idx);
        else
-               dev_set_name(&dimm->dev, "dimm%d", index);
+               dev_set_name(&dimm->dev, "dimm%d", dimm->idx);
        dev_set_drvdata(&dimm->dev, dimm);
        pm_runtime_forbid(&mci->dev);
 
 int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
                                 const struct attribute_group **groups)
 {
-       int i, err;
+       struct dimm_info *dimm;
+       int err;
 
        /* get the /sys/devices/system/edac subsys reference */
        mci->dev.type = &mci_attr_type;
        /*
         * Create the dimm/rank devices
         */
-       for (i = 0; i < mci->tot_dimms; i++) {
-               struct dimm_info *dimm = mci->dimms[i];
+       mci_for_each_dimm(mci, dimm) {
                /* Only expose populated DIMMs */
                if (!dimm->nr_pages)
                        continue;
 
-               err = edac_create_dimm_object(mci, dimm, i);
+               err = edac_create_dimm_object(mci, dimm);
                if (err)
                        goto fail_unregister_dimm;
        }
        return 0;
 
 fail_unregister_dimm:
-       for (i--; i >= 0; i--) {
-               struct dimm_info *dimm = mci->dimms[i];
-               if (!dimm->nr_pages)
-                       continue;
-
-               device_unregister(&dimm->dev);
+       mci_for_each_dimm(mci, dimm) {
+               if (device_is_registered(&dimm->dev))
+                       device_unregister(&dimm->dev);
        }
        device_unregister(&mci->dev);
 
  */
 void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
 {
-       int i;
+       struct dimm_info *dimm;
 
        edac_dbg(0, "\n");
 
        edac_delete_csrow_objects(mci);
 #endif
 
-       for (i = 0; i < mci->tot_dimms; i++) {
-               struct dimm_info *dimm = mci->dimms[i];
+       mci_for_each_dimm(mci, dimm) {
                if (dimm->nr_pages == 0)
                        continue;
                edac_dbg(1, "unregistering device %s\n", dev_name(&dimm->dev));
 
 
 static int get_dimm_smbios_index(struct mem_ctl_info *mci, u16 handle)
 {
-       int i;
+       struct dimm_info *dimm;
 
-       for (i = 0; i < mci->tot_dimms; i++) {
-               if (mci->dimms[i]->smbios_handle == handle)
-                       return i;
+       mci_for_each_dimm(mci, dimm) {
+               if (dimm->smbios_handle == handle)
+                       return dimm->idx;
        }
+
        return -1;
 }
 
 
 
 static void i5100_init_csrows(struct mem_ctl_info *mci)
 {
-       int i;
        struct i5100_priv *priv = mci->pvt_info;
+       struct dimm_info *dimm;
 
-       for (i = 0; i < mci->tot_dimms; i++) {
-               struct dimm_info *dimm;
-               const unsigned long npages = i5100_npages(mci, i);
-               const unsigned int chan = i5100_csrow_to_chan(mci, i);
-               const unsigned int rank = i5100_csrow_to_rank(mci, i);
+       mci_for_each_dimm(mci, dimm) {
+               const unsigned long npages = i5100_npages(mci, dimm->idx);
+               const unsigned int chan = i5100_csrow_to_chan(mci, dimm->idx);
+               const unsigned int rank = i5100_csrow_to_rank(mci, dimm->idx);
 
                if (!npages)
                        continue;
 
-               dimm = edac_get_dimm(mci, chan, rank, 0);
-
                dimm->nr_pages = npages;
                dimm->grain = 32;
                dimm->dtype = (priv->mtr[chan][rank].width == 4) ?
 
        u16 fake_inject_count;
 };
 
+#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