u32 ce_count;
 };
 
-/*
- * An array of these is passed to the alloc() function
- * to specify attributes of the edac_block
- */
-struct edac_attrib_spec {
-       char name[EDAC_DEVICE_NAME_LEN + 1];
+/* forward reference */
+struct edac_device_ctl_info;
+struct edac_device_block;
 
-       int type;
-#define        EDAC_ATTR_INT           0x01
-#define EDAC_ATTR_CHAR         0x02
+/* edac_dev_sysfs_attribute structure
+ *     used for driver sysfs attributes in mem_ctl_info
+ *     for extra controls and attributes:
+ *             like high level error Injection controls
+ */
+struct edac_dev_sysfs_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct edac_device_ctl_info *, char *);
+       ssize_t (*store)(struct edac_device_ctl_info *, const char *, size_t);
 };
 
-/* Attribute control structure
- * In this structure is a pointer to the driver's edac_attrib_spec
- * The life of this pointer is inclusive in the life of the driver's
- * life cycle.
+/* edac_dev_sysfs_block_attribute structure
+ *     used in leaf 'block' nodes for adding controls/attributes
  */
-struct edac_attrib {
-       struct edac_device_block *block;        /* Up Pointer */
-
-       struct edac_attrib_spec *spec;  /* ptr to module spec entry */
-
-       union {                 /* actual value */
-               int edac_attrib_int_value;
-               char edac_attrib_char_value[EDAC_ATTRIB_VALUE_LEN + 1];
-       } edac_attrib_value;
+struct edac_dev_sysfs_block_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct kobject *, struct attribute *, char *);
+       ssize_t (*store)(struct kobject *, struct attribute *,
+                       const char *, size_t);
+       struct edac_device_block *block;
+
+       /* low driver use */
+       void *arg;
+       unsigned int value;
 };
 
 /* device block control structure */
        struct edac_device_counter counters;    /* basic UE and CE counters */
 
        int nr_attribs;         /* how many attributes */
-       struct edac_attrib *attribs;    /* this block's attributes */
+
+       /* this block's attributes, could be NULL */
+       struct edac_dev_sysfs_block_attribute *block_attributes;
 
        /* edac sysfs device control */
        struct kobject kobj;
        struct completion kobj_complete;
 };
 
-/* edac_dev_sysfs_attribute structure
- *     used for driver sysfs attributes and in mem_ctl_info
- *     sysfs top level entries
- */
-struct edac_dev_sysfs_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct edac_device_ctl_info *,char *);
-       ssize_t (*store)(struct edac_device_ctl_info *, const char *,size_t);
-};
 
 /*
  * Abstract edac_device control info structure
  */
 extern struct edac_device_ctl_info *edac_device_alloc_ctl_info(
                unsigned sizeof_private,
-               char *edac_device_name,
-               unsigned nr_instances,
-               char *edac_block_name,
-               unsigned nr_blocks,
+               char *edac_device_name, unsigned nr_instances,
+               char *edac_block_name, unsigned nr_blocks,
                unsigned offset_value,
-               struct edac_attrib_spec *attrib_spec,
+               struct edac_dev_sysfs_block_attribute *block_attributes,
                unsigned nr_attribs);
 
 /* The offset value can be:
 
        char *edac_device_name, unsigned nr_instances,
        char *edac_block_name, unsigned nr_blocks,
        unsigned offset_value,          /* zero, 1, or other based offset */
-       struct edac_attrib_spec *attrib_spec, unsigned nr_attribs)
+       struct edac_dev_sysfs_block_attribute *attrib_spec, unsigned nr_attrib)
 {
        struct edac_device_ctl_info *dev_ctl;
        struct edac_device_instance *dev_inst, *inst;
        struct edac_device_block *dev_blk, *blk_p, *blk;
-       struct edac_attrib *dev_attrib, *attrib_p, *attrib;
+       struct edac_dev_sysfs_block_attribute *dev_attrib, *attrib_p, *attrib;
        unsigned total_size;
        unsigned count;
        unsigned instance, block, attr;
        debugf1("%s() instances=%d blocks=%d\n",
                __func__, nr_instances, nr_blocks);
 
-       /* Figure out the offsets of the various items from the start of an
-        * ctl_info structure.  We want the alignment of each item
+       /* Calculate the size of memory we need to allocate AND
+        * determine the offsets of the various item arrays
+        * (instance,block,attrib) from the start of an  allocated structure.
+        * We want the alignment of each item  (instance,block,attrib)
         * to be at least as stringent as what the compiler would
         * provide if we could simply hardcode everything into a single struct.
         */
        dev_ctl = (struct edac_device_ctl_info *)NULL;
 
-       /* Calc the 'end' offset past the ctl_info structure */
+       /* Calc the 'end' offset past end of ONE ctl_info structure
+        * which will become the start of the 'instance' array
+        */
        dev_inst = edac_align_ptr(&dev_ctl[1], sizeof(*dev_inst));
 
-       /* Calc the 'end' offset past the instance array */
+       /* Calc the 'end' offset past the instance array within the ctl_info
+        * which will become the start of the block array
+        */
        dev_blk = edac_align_ptr(&dev_inst[nr_instances], sizeof(*dev_blk));
 
-       /* Calc the 'end' offset past the dev_blk array */
+       /* Calc the 'end' offset past the dev_blk array
+        * which will become the start of the attrib array, if any.
+        */
        count = nr_instances * nr_blocks;
        dev_attrib = edac_align_ptr(&dev_blk[count], sizeof(*dev_attrib));
 
-       /* Check for case of NO attributes specified */
-       if (nr_attribs > 0)
-               count *= nr_attribs;
+       /* Check for case of when an attribute array is specified */
+       if (nr_attrib > 0) {
+               /* calc how many nr_attrib we need */
+               count *= nr_attrib;
 
-       /* Calc the 'end' offset past the attributes array */
-       pvt = edac_align_ptr(&dev_attrib[count], sz_private);
+               /* Calc the 'end' offset past the attributes array */
+               pvt = edac_align_ptr(&dev_attrib[count], sz_private);
+       } else {
+               /* no attribute array specificed */
+               pvt = edac_align_ptr(dev_attrib, sz_private);
+       }
+
+       /* 'pvt' now points to where the private data area is.
+        * At this point 'pvt' (like dev_inst,dev_blk and dev_attrib)
+        * is baselined at ZERO
+        */
        total_size = ((unsigned long)pvt) + sz_private;
 
        /* Allocate the amount of memory for the set of control structures */
        if (dev_ctl == NULL)
                return NULL;
 
-       /* Adjust pointers so they point within the memory we just allocated
-        * rather than an imaginary chunk of memory located at address 0.
+       /* Adjust pointers so they point within the actual memory we
+        * just allocated rather than an imaginary chunk of memory
+        * located at address 0.
+        * 'dev_ctl' points to REAL memory, while the others are
+        * ZERO based and thus need to be adjusted to point within
+        * the allocated memory.
         */
        dev_inst = (struct edac_device_instance *)
                (((char *)dev_ctl) + ((unsigned long)dev_inst));
        dev_blk = (struct edac_device_block *)
                (((char *)dev_ctl) + ((unsigned long)dev_blk));
-       dev_attrib = (struct edac_attrib *)
+       dev_attrib = (struct edac_dev_sysfs_block_attribute *)
                (((char *)dev_ctl) + ((unsigned long)dev_attrib));
        pvt = sz_private ? (((char *)dev_ctl) + ((unsigned long)pvt)) : NULL;
 
+       /* Begin storing the information into the control info structure */
        dev_ctl->nr_instances = nr_instances;
        dev_ctl->instances = dev_inst;
        dev_ctl->pvt_info = pvt;
                for (block = 0; block < nr_blocks; block++) {
                        blk = &blk_p[block];
                        blk->instance = inst;
-                       blk->nr_attribs = nr_attribs;
-                       attrib_p = &dev_attrib[block * nr_attribs];
-                       blk->attribs = attrib_p;
                        snprintf(blk->name, sizeof(blk->name),
                                 "%s%d", edac_block_name, block+offset_value);
 
                        debugf1("%s() instance=%d block=%d name=%s\n",
                                __func__, instance, block, blk->name);
 
-                       if (attrib_spec != NULL) {
-                               /* when there is an attrib_spec passed int then
-                                * Initialize every attrib of each block
-                                */
-                               for (attr = 0; attr < nr_attribs; attr++) {
-                                       attrib = &attrib_p[attr];
-                                       attrib->block = blk;
-
-                                       /* Link each attribute to the caller's
-                                        * spec entry, for name and type
-                                        */
-                                       attrib->spec = &attrib_spec[attr];
-                               }
+                       /* if there are NO attributes OR no attribute pointer
+                        * then continue on to next block iteration
+                        */
+                       if ((nr_attrib == 0) || (attrib_spec == NULL))
+                               continue;
+
+                       /* setup the attribute array for this block */
+                       blk->nr_attribs = nr_attrib;
+                       attrib_p = &dev_attrib[block*nr_instances*nr_attrib];
+                       blk->block_attributes = attrib_p;
+
+                       /* Initialize every user specified attribute in this
+                        * block with the data the caller passed in
+                        */
+                       for (attr = 0; attr < nr_attrib; attr++) {
+                               attrib = &attrib_p[attr];
+                               attrib->attr = attrib_spec->attr;
+                               attrib->show = attrib_spec->show;
+                               attrib->store = attrib_spec->store;
+
+                               /* up reference this block */
+                               attrib->block = blk;
+
+                               /* bump the attrib_spec */
+                               attrib_spec++;
                        }
                }
        }