diff options
Diffstat (limited to 'drivers/edac/edac_device.c')
-rw-r--r-- | drivers/edac/edac_device.c | 94 |
1 files changed, 63 insertions, 31 deletions
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index b53e8d51d9a..8264e3728c7 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -67,12 +67,12 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( 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; @@ -81,29 +81,47 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( 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 */ @@ -111,17 +129,22 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( 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; @@ -145,28 +168,37 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info( 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++; } } } |