Merge branches 'edac-misc' and 'edac-alloc-cleanup' into edac-updates-for-v5.19
Combine all collected EDAC changes for submission into v5.19: * edac-misc: EDAC/xgene: Fix typo processsors -> processors EDAC/i5100: Remove unused inline function i5100_nrecmema_dm_buf_id() EDAC/ghes: Change ghes_hw from global to static EDAC/armada_xp: Use devm_platform_ioremap_resource() EDAC/synopsys: Add a SPDX identifier EDAC/synopsys: Add driver support for i.MX platforms EDAC/dmc520: Don't print an error for each unconfigured interrupt line efi/cper: Reformat CPER memory error location to more readable EDAC/ghes: Unify CPER memory error location reporting efi/cper: Add a cper_mem_err_status_str() to decode error description powerpc/85xx: Remove fsl,85... bindings * edac-alloc-cleanup: EDAC: Use kcalloc() EDAC/mc: Get rid of edac_align_ptr() EDAC/device: Sanitize edac_device_alloc_ctl_info() definition EDAC/device: Get rid of the silly one-shot memory allocation in edac_device_alloc_ctl_info() EDAC/pci: Get rid of the silly one-shot memory allocation in edac_pci_alloc_ctl_info() EDAC/mc: Get rid of silly one-shot struct allocation in edac_mc_alloc() Signed-off-by: Borislav Petkov <bp@suse.de>
This commit is contained in:
commit
be80a1ca51
|
@ -47,99 +47,67 @@ static void edac_device_dump_device(struct edac_device_ctl_info *edac_dev)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_EDAC_DEBUG */
|
#endif /* CONFIG_EDAC_DEBUG */
|
||||||
|
|
||||||
struct edac_device_ctl_info *edac_device_alloc_ctl_info(
|
/*
|
||||||
unsigned sz_private,
|
* @off_val: zero, 1, or other based offset
|
||||||
char *edac_device_name, unsigned nr_instances,
|
*/
|
||||||
char *edac_block_name, unsigned nr_blocks,
|
struct edac_device_ctl_info *
|
||||||
unsigned offset_value, /* zero, 1, or other based offset */
|
edac_device_alloc_ctl_info(unsigned pvt_sz, char *dev_name, unsigned nr_instances,
|
||||||
struct edac_dev_sysfs_block_attribute *attrib_spec, unsigned nr_attrib,
|
char *blk_name, unsigned nr_blocks, unsigned off_val,
|
||||||
int device_index)
|
struct edac_dev_sysfs_block_attribute *attrib_spec,
|
||||||
|
unsigned nr_attrib, int device_index)
|
||||||
{
|
{
|
||||||
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_dev_sysfs_block_attribute *dev_attrib, *attrib_p, *attrib;
|
struct edac_dev_sysfs_block_attribute *dev_attrib, *attrib_p, *attrib;
|
||||||
unsigned total_size;
|
struct edac_device_block *dev_blk, *blk_p, *blk;
|
||||||
unsigned count;
|
struct edac_device_instance *dev_inst, *inst;
|
||||||
|
struct edac_device_ctl_info *dev_ctl;
|
||||||
unsigned instance, block, attr;
|
unsigned instance, block, attr;
|
||||||
void *pvt, *p;
|
void *pvt;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks);
|
edac_dbg(4, "instances=%d blocks=%d\n", nr_instances, nr_blocks);
|
||||||
|
|
||||||
/* Calculate the size of memory we need to allocate AND
|
dev_ctl = kzalloc(sizeof(struct edac_device_ctl_info), GFP_KERNEL);
|
||||||
* determine the offsets of the various item arrays
|
if (!dev_ctl)
|
||||||
* (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.
|
|
||||||
*/
|
|
||||||
p = NULL;
|
|
||||||
dev_ctl = edac_align_ptr(&p, sizeof(*dev_ctl), 1);
|
|
||||||
|
|
||||||
/* 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(&p, sizeof(*dev_inst), nr_instances);
|
|
||||||
|
|
||||||
/* Calc the 'end' offset past the instance array within the ctl_info
|
|
||||||
* which will become the start of the block array
|
|
||||||
*/
|
|
||||||
count = nr_instances * nr_blocks;
|
|
||||||
dev_blk = edac_align_ptr(&p, sizeof(*dev_blk), count);
|
|
||||||
|
|
||||||
/* Calc the 'end' offset past the dev_blk array
|
|
||||||
* which will become the start of the attrib array, if any.
|
|
||||||
*/
|
|
||||||
/* calc how many nr_attrib we need */
|
|
||||||
if (nr_attrib > 0)
|
|
||||||
count *= nr_attrib;
|
|
||||||
dev_attrib = edac_align_ptr(&p, sizeof(*dev_attrib), count);
|
|
||||||
|
|
||||||
/* Calc the 'end' offset past the attributes array */
|
|
||||||
pvt = edac_align_ptr(&p, sz_private, 1);
|
|
||||||
|
|
||||||
/* '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 */
|
|
||||||
dev_ctl = kzalloc(total_size, GFP_KERNEL);
|
|
||||||
if (dev_ctl == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Adjust pointers so they point within the actual memory we
|
dev_inst = kcalloc(nr_instances, sizeof(struct edac_device_instance), GFP_KERNEL);
|
||||||
* just allocated rather than an imaginary chunk of memory
|
if (!dev_inst)
|
||||||
* located at address 0.
|
goto free;
|
||||||
* '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_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->dev_idx = device_index;
|
|
||||||
dev_ctl->nr_instances = nr_instances;
|
|
||||||
dev_ctl->instances = dev_inst;
|
dev_ctl->instances = dev_inst;
|
||||||
dev_ctl->pvt_info = pvt;
|
|
||||||
|
dev_blk = kcalloc(nr_instances * nr_blocks, sizeof(struct edac_device_block), GFP_KERNEL);
|
||||||
|
if (!dev_blk)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
dev_ctl->blocks = dev_blk;
|
||||||
|
|
||||||
|
if (nr_attrib) {
|
||||||
|
dev_attrib = kcalloc(nr_attrib, sizeof(struct edac_dev_sysfs_block_attribute),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!dev_attrib)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
dev_ctl->attribs = dev_attrib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pvt_sz) {
|
||||||
|
pvt = kzalloc(pvt_sz, GFP_KERNEL);
|
||||||
|
if (!pvt)
|
||||||
|
goto free;
|
||||||
|
|
||||||
|
dev_ctl->pvt_info = pvt;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_ctl->dev_idx = device_index;
|
||||||
|
dev_ctl->nr_instances = nr_instances;
|
||||||
|
|
||||||
/* Default logging of CEs and UEs */
|
/* Default logging of CEs and UEs */
|
||||||
dev_ctl->log_ce = 1;
|
dev_ctl->log_ce = 1;
|
||||||
dev_ctl->log_ue = 1;
|
dev_ctl->log_ue = 1;
|
||||||
|
|
||||||
/* Name of this edac device */
|
/* Name of this edac device */
|
||||||
snprintf(dev_ctl->name,sizeof(dev_ctl->name),"%s",edac_device_name);
|
snprintf(dev_ctl->name, sizeof(dev_ctl->name),"%s", dev_name);
|
||||||
|
|
||||||
edac_dbg(4, "edac_dev=%p next after end=%p\n",
|
|
||||||
dev_ctl, pvt + sz_private);
|
|
||||||
|
|
||||||
/* Initialize every Instance */
|
/* Initialize every Instance */
|
||||||
for (instance = 0; instance < nr_instances; instance++) {
|
for (instance = 0; instance < nr_instances; instance++) {
|
||||||
|
@ -150,15 +118,14 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
|
||||||
inst->blocks = blk_p;
|
inst->blocks = blk_p;
|
||||||
|
|
||||||
/* name of this instance */
|
/* name of this instance */
|
||||||
snprintf(inst->name, sizeof(inst->name),
|
snprintf(inst->name, sizeof(inst->name), "%s%u", dev_name, instance);
|
||||||
"%s%u", edac_device_name, instance);
|
|
||||||
|
|
||||||
/* Initialize every block in each instance */
|
/* Initialize every block in each instance */
|
||||||
for (block = 0; block < nr_blocks; block++) {
|
for (block = 0; block < nr_blocks; block++) {
|
||||||
blk = &blk_p[block];
|
blk = &blk_p[block];
|
||||||
blk->instance = inst;
|
blk->instance = inst;
|
||||||
snprintf(blk->name, sizeof(blk->name),
|
snprintf(blk->name, sizeof(blk->name),
|
||||||
"%s%d", edac_block_name, block+offset_value);
|
"%s%d", blk_name, block + off_val);
|
||||||
|
|
||||||
edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n",
|
edac_dbg(4, "instance=%d inst_p=%p block=#%d block_p=%p name='%s'\n",
|
||||||
instance, inst, block, blk, blk->name);
|
instance, inst, block, blk, blk->name);
|
||||||
|
@ -210,10 +177,8 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
|
||||||
* Initialize the 'root' kobj for the edac_device controller
|
* Initialize the 'root' kobj for the edac_device controller
|
||||||
*/
|
*/
|
||||||
err = edac_device_register_sysfs_main_kobj(dev_ctl);
|
err = edac_device_register_sysfs_main_kobj(dev_ctl);
|
||||||
if (err) {
|
if (err)
|
||||||
kfree(dev_ctl);
|
goto free;
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* at this point, the root kobj is valid, and in order to
|
/* at this point, the root kobj is valid, and in order to
|
||||||
* 'free' the object, then the function:
|
* 'free' the object, then the function:
|
||||||
|
@ -223,6 +188,11 @@ struct edac_device_ctl_info *edac_device_alloc_ctl_info(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return dev_ctl;
|
return dev_ctl;
|
||||||
|
|
||||||
|
free:
|
||||||
|
__edac_device_free_ctl_info(dev_ctl);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(edac_device_alloc_ctl_info);
|
EXPORT_SYMBOL_GPL(edac_device_alloc_ctl_info);
|
||||||
|
|
||||||
|
|
|
@ -216,6 +216,8 @@ struct edac_device_ctl_info {
|
||||||
*/
|
*/
|
||||||
u32 nr_instances;
|
u32 nr_instances;
|
||||||
struct edac_device_instance *instances;
|
struct edac_device_instance *instances;
|
||||||
|
struct edac_device_block *blocks;
|
||||||
|
struct edac_dev_sysfs_block_attribute *attribs;
|
||||||
|
|
||||||
/* Event counters for the this whole EDAC Device */
|
/* Event counters for the this whole EDAC Device */
|
||||||
struct edac_device_counter counters;
|
struct edac_device_counter counters;
|
||||||
|
@ -348,4 +350,16 @@ edac_device_handle_ue(struct edac_device_ctl_info *edac_dev, int inst_nr,
|
||||||
*/
|
*/
|
||||||
extern int edac_device_alloc_index(void);
|
extern int edac_device_alloc_index(void);
|
||||||
extern const char *edac_layer_name[];
|
extern const char *edac_layer_name[];
|
||||||
|
|
||||||
|
/* Free the actual struct */
|
||||||
|
static inline void __edac_device_free_ctl_info(struct edac_device_ctl_info *ci)
|
||||||
|
{
|
||||||
|
if (ci) {
|
||||||
|
kfree(ci->pvt_info);
|
||||||
|
kfree(ci->attribs);
|
||||||
|
kfree(ci->blocks);
|
||||||
|
kfree(ci->instances);
|
||||||
|
kfree(ci);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -208,10 +208,7 @@ static void edac_device_ctrl_master_release(struct kobject *kobj)
|
||||||
/* decrement the EDAC CORE module ref count */
|
/* decrement the EDAC CORE module ref count */
|
||||||
module_put(edac_dev->owner);
|
module_put(edac_dev->owner);
|
||||||
|
|
||||||
/* free the control struct containing the 'main' kobj
|
__edac_device_free_ctl_info(edac_dev);
|
||||||
* passed in to this routine
|
|
||||||
*/
|
|
||||||
kfree(edac_dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ktype for the main (master) kobject */
|
/* ktype for the main (master) kobject */
|
||||||
|
|
|
@ -170,61 +170,6 @@ const char * const edac_mem_types[] = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(edac_mem_types);
|
EXPORT_SYMBOL_GPL(edac_mem_types);
|
||||||
|
|
||||||
/**
|
|
||||||
* edac_align_ptr - Prepares the pointer offsets for a single-shot allocation
|
|
||||||
* @p: pointer to a pointer with the memory offset to be used. At
|
|
||||||
* return, this will be incremented to point to the next offset
|
|
||||||
* @size: Size of the data structure to be reserved
|
|
||||||
* @n_elems: Number of elements that should be reserved
|
|
||||||
*
|
|
||||||
* If 'size' is a constant, the compiler will optimize this whole function
|
|
||||||
* down to either a no-op or the addition of a constant to the value of '*p'.
|
|
||||||
*
|
|
||||||
* The 'p' pointer is absolutely needed to keep the proper advancing
|
|
||||||
* further in memory to the proper offsets when allocating the struct along
|
|
||||||
* with its embedded structs, as edac_device_alloc_ctl_info() does it
|
|
||||||
* above, for example.
|
|
||||||
*
|
|
||||||
* At return, the pointer 'p' will be incremented to be used on a next call
|
|
||||||
* to this function.
|
|
||||||
*/
|
|
||||||
void *edac_align_ptr(void **p, unsigned int size, int n_elems)
|
|
||||||
{
|
|
||||||
unsigned int align, r;
|
|
||||||
void *ptr = *p;
|
|
||||||
|
|
||||||
*p += size * n_elems;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 'p' can possibly be an unaligned item X such that sizeof(X) is
|
|
||||||
* 'size'. Adjust 'p' so that its alignment is at least as
|
|
||||||
* stringent as what the compiler would provide for X and return
|
|
||||||
* the aligned result.
|
|
||||||
* Here we assume that the alignment of a "long long" is the most
|
|
||||||
* stringent alignment that the compiler will ever provide by default.
|
|
||||||
* As far as I know, this is a reasonable assumption.
|
|
||||||
*/
|
|
||||||
if (size > sizeof(long))
|
|
||||||
align = sizeof(long long);
|
|
||||||
else if (size > sizeof(int))
|
|
||||||
align = sizeof(long);
|
|
||||||
else if (size > sizeof(short))
|
|
||||||
align = sizeof(int);
|
|
||||||
else if (size > sizeof(char))
|
|
||||||
align = sizeof(short);
|
|
||||||
else
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
r = (unsigned long)ptr % align;
|
|
||||||
|
|
||||||
if (r == 0)
|
|
||||||
return ptr;
|
|
||||||
|
|
||||||
*p += align - r;
|
|
||||||
|
|
||||||
return (void *)(((unsigned long)ptr) + align - r);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _edac_mc_free(struct mem_ctl_info *mci)
|
static void _edac_mc_free(struct mem_ctl_info *mci)
|
||||||
{
|
{
|
||||||
put_device(&mci->dev);
|
put_device(&mci->dev);
|
||||||
|
@ -257,6 +202,8 @@ static void mci_release(struct device *dev)
|
||||||
}
|
}
|
||||||
kfree(mci->csrows);
|
kfree(mci->csrows);
|
||||||
}
|
}
|
||||||
|
kfree(mci->pvt_info);
|
||||||
|
kfree(mci->layers);
|
||||||
kfree(mci);
|
kfree(mci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,9 +339,8 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
|
||||||
{
|
{
|
||||||
struct mem_ctl_info *mci;
|
struct mem_ctl_info *mci;
|
||||||
struct edac_mc_layer *layer;
|
struct edac_mc_layer *layer;
|
||||||
unsigned int idx, size, tot_dimms = 1;
|
unsigned int idx, tot_dimms = 1;
|
||||||
unsigned int tot_csrows = 1, tot_channels = 1;
|
unsigned int tot_csrows = 1, tot_channels = 1;
|
||||||
void *pvt, *ptr = NULL;
|
|
||||||
bool per_rank = false;
|
bool per_rank = false;
|
||||||
|
|
||||||
if (WARN_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0))
|
if (WARN_ON(n_layers > EDAC_MAX_LAYERS || n_layers == 0))
|
||||||
|
@ -416,41 +362,25 @@ struct mem_ctl_info *edac_mc_alloc(unsigned int mc_num,
|
||||||
per_rank = true;
|
per_rank = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Figure out the offsets of the various items from the start of an mc
|
mci = kzalloc(sizeof(struct mem_ctl_info), GFP_KERNEL);
|
||||||
* structure. We want the alignment of each item to be at least as
|
if (!mci)
|
||||||
* stringent as what the compiler would provide if we could simply
|
|
||||||
* hardcode everything into a single struct.
|
|
||||||
*/
|
|
||||||
mci = edac_align_ptr(&ptr, sizeof(*mci), 1);
|
|
||||||
layer = edac_align_ptr(&ptr, sizeof(*layer), n_layers);
|
|
||||||
pvt = edac_align_ptr(&ptr, sz_pvt, 1);
|
|
||||||
size = ((unsigned long)pvt) + sz_pvt;
|
|
||||||
|
|
||||||
edac_dbg(1, "allocating %u bytes for mci data (%d %s, %d csrows/channels)\n",
|
|
||||||
size,
|
|
||||||
tot_dimms,
|
|
||||||
per_rank ? "ranks" : "dimms",
|
|
||||||
tot_csrows * tot_channels);
|
|
||||||
|
|
||||||
mci = kzalloc(size, GFP_KERNEL);
|
|
||||||
if (mci == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
mci->layers = kcalloc(n_layers, sizeof(struct edac_mc_layer), GFP_KERNEL);
|
||||||
|
if (!mci->layers)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
mci->pvt_info = kzalloc(sz_pvt, GFP_KERNEL);
|
||||||
|
if (!mci->pvt_info)
|
||||||
|
goto error;
|
||||||
|
|
||||||
mci->dev.release = mci_release;
|
mci->dev.release = mci_release;
|
||||||
device_initialize(&mci->dev);
|
device_initialize(&mci->dev);
|
||||||
|
|
||||||
/* Adjust pointers so they point within the memory we just allocated
|
|
||||||
* rather than an imaginary chunk of memory located at address 0.
|
|
||||||
*/
|
|
||||||
layer = (struct edac_mc_layer *)(((char *)mci) + ((unsigned long)layer));
|
|
||||||
pvt = sz_pvt ? (((char *)mci) + ((unsigned long)pvt)) : NULL;
|
|
||||||
|
|
||||||
/* setup index and various internal pointers */
|
/* setup index and various internal pointers */
|
||||||
mci->mc_idx = mc_num;
|
mci->mc_idx = mc_num;
|
||||||
mci->tot_dimms = tot_dimms;
|
mci->tot_dimms = tot_dimms;
|
||||||
mci->pvt_info = pvt;
|
|
||||||
mci->n_layers = n_layers;
|
mci->n_layers = n_layers;
|
||||||
mci->layers = layer;
|
|
||||||
memcpy(mci->layers, layers, sizeof(*layer) * n_layers);
|
memcpy(mci->layers, layers, sizeof(*layer) * n_layers);
|
||||||
mci->nr_csrows = tot_csrows;
|
mci->nr_csrows = tot_csrows;
|
||||||
mci->num_cschannel = tot_channels;
|
mci->num_cschannel = tot_channels;
|
||||||
|
|
|
@ -59,8 +59,6 @@ extern void edac_device_reset_delay_period(struct edac_device_ctl_info
|
||||||
*edac_dev, unsigned long value);
|
*edac_dev, unsigned long value);
|
||||||
extern void edac_mc_reset_delay_period(unsigned long value);
|
extern void edac_mc_reset_delay_period(unsigned long value);
|
||||||
|
|
||||||
extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EDAC debugfs functions
|
* EDAC debugfs functions
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -29,32 +29,31 @@ static LIST_HEAD(edac_pci_list);
|
||||||
static atomic_t pci_indexes = ATOMIC_INIT(0);
|
static atomic_t pci_indexes = ATOMIC_INIT(0);
|
||||||
|
|
||||||
struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
|
struct edac_pci_ctl_info *edac_pci_alloc_ctl_info(unsigned int sz_pvt,
|
||||||
const char *edac_pci_name)
|
const char *edac_pci_name)
|
||||||
{
|
{
|
||||||
struct edac_pci_ctl_info *pci;
|
struct edac_pci_ctl_info *pci;
|
||||||
void *p = NULL, *pvt;
|
|
||||||
unsigned int size;
|
|
||||||
|
|
||||||
edac_dbg(1, "\n");
|
edac_dbg(1, "\n");
|
||||||
|
|
||||||
pci = edac_align_ptr(&p, sizeof(*pci), 1);
|
pci = kzalloc(sizeof(struct edac_pci_ctl_info), GFP_KERNEL);
|
||||||
pvt = edac_align_ptr(&p, 1, sz_pvt);
|
if (!pci)
|
||||||
size = ((unsigned long)pvt) + sz_pvt;
|
|
||||||
|
|
||||||
/* Alloc the needed control struct memory */
|
|
||||||
pci = kzalloc(size, GFP_KERNEL);
|
|
||||||
if (pci == NULL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Now much private space */
|
if (sz_pvt) {
|
||||||
pvt = sz_pvt ? ((char *)pci) + ((unsigned long)pvt) : NULL;
|
pci->pvt_info = kzalloc(sz_pvt, GFP_KERNEL);
|
||||||
|
if (!pci->pvt_info)
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
|
||||||
pci->pvt_info = pvt;
|
|
||||||
pci->op_state = OP_ALLOC;
|
pci->op_state = OP_ALLOC;
|
||||||
|
|
||||||
snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name);
|
snprintf(pci->name, strlen(edac_pci_name) + 1, "%s", edac_pci_name);
|
||||||
|
|
||||||
return pci;
|
return pci;
|
||||||
|
|
||||||
|
free:
|
||||||
|
kfree(pci);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
|
EXPORT_SYMBOL_GPL(edac_pci_alloc_ctl_info);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue