edac_device_sysfs.c
来自「linux 内核源代码」· C语言 代码 · 共 897 行 · 第 1/2 页
C
897 行
block = to_block(kobj); /* map from 'block kobj' to 'block->instance->controller->main_kobj' * now 'release' the block kobject */ kobject_put(&block->instance->ctl->kobj);}/* Function to 'show' fields from the edac_dev 'block' structure */static ssize_t edac_dev_block_show(struct kobject *kobj, struct attribute *attr, char *buffer){ struct edac_dev_sysfs_block_attribute *block_attr = to_block_attr(attr); if (block_attr->show) return block_attr->show(kobj, attr, buffer); return -EIO;}/* Function to 'store' fields into the edac_dev 'block' structure */static ssize_t edac_dev_block_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count){ struct edac_dev_sysfs_block_attribute *block_attr; block_attr = to_block_attr(attr); if (block_attr->store) return block_attr->store(kobj, attr, buffer, count); return -EIO;}/* edac_dev file operations for a 'block' */static struct sysfs_ops device_block_ops = { .show = edac_dev_block_show, .store = edac_dev_block_store};#define BLOCK_ATTR(_name,_mode,_show,_store) \static struct edac_dev_sysfs_block_attribute attr_block_##_name = { \ .attr = {.name = __stringify(_name), .mode = _mode }, \ .show = _show, \ .store = _store, \};BLOCK_ATTR(ce_count, S_IRUGO, block_ce_count_show, NULL);BLOCK_ATTR(ue_count, S_IRUGO, block_ue_count_show, NULL);/* list of edac_dev 'block' attributes */static struct edac_dev_sysfs_block_attribute *device_block_attr[] = { &attr_block_ce_count, &attr_block_ue_count, NULL,};/* The 'ktype' for each edac_dev 'block' */static struct kobj_type ktype_block_ctrl = { .release = edac_device_ctrl_block_release, .sysfs_ops = &device_block_ops, .default_attrs = (struct attribute **)device_block_attr,};/* block ctor/dtor code *//* * edac_device_create_block */static int edac_device_create_block(struct edac_device_ctl_info *edac_dev, struct edac_device_instance *instance, struct edac_device_block *block){ int i; int err; struct edac_dev_sysfs_block_attribute *sysfs_attrib; struct kobject *main_kobj; debugf4("%s() Instance '%s' inst_p=%p block '%s' block_p=%p\n", __func__, instance->name, instance, block->name, block); debugf4("%s() block kobj=%p block kobj->parent=%p\n", __func__, &block->kobj, &block->kobj.parent); /* init this block's kobject */ memset(&block->kobj, 0, sizeof(struct kobject)); block->kobj.parent = &instance->kobj; block->kobj.ktype = &ktype_block_ctrl; err = kobject_set_name(&block->kobj, "%s", block->name); if (err) return err; /* bump the main kobject's reference count for this controller * and this instance is dependant on the main */ main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { err = -ENODEV; goto err_out; } /* Add this block's kobject */ err = kobject_register(&block->kobj); if (err) { debugf1("%s() Failed to register instance '%s'\n", __func__, block->name); kobject_put(main_kobj); err = -ENODEV; goto err_out; } /* If there are driver level block attributes, then added them * to the block kobject */ sysfs_attrib = block->block_attributes; if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { debugf4("%s() creating block attrib='%s' " "attrib->%p to kobj=%p\n", __func__, sysfs_attrib->attr.name, sysfs_attrib, &block->kobj); /* Create each block_attribute file */ err = sysfs_create_file(&block->kobj, &sysfs_attrib->attr); if (err) goto err_on_attrib; } } return 0; /* Error unwind stack */err_on_attrib: kobject_unregister(&block->kobj);err_out: return err;}/* * edac_device_delete_block(edac_dev,block); */static void edac_device_delete_block(struct edac_device_ctl_info *edac_dev, struct edac_device_block *block){ struct edac_dev_sysfs_block_attribute *sysfs_attrib; int i; /* if this block has 'attributes' then we need to iterate over the list * and 'remove' the attributes on this block */ sysfs_attrib = block->block_attributes; if (sysfs_attrib && block->nr_attribs) { for (i = 0; i < block->nr_attribs; i++, sysfs_attrib++) { /* remove each block_attrib file */ sysfs_remove_file(&block->kobj, (struct attribute *) sysfs_attrib); } } /* unregister this block's kobject, SEE: * edac_device_ctrl_block_release() callback operation */ kobject_unregister(&block->kobj);}/* instance ctor/dtor code *//* * edac_device_create_instance * create just one instance of an edac_device 'instance' */static int edac_device_create_instance(struct edac_device_ctl_info *edac_dev, int idx){ int i, j; int err; struct edac_device_instance *instance; struct kobject *main_kobj; instance = &edac_dev->instances[idx]; /* Init the instance's kobject */ memset(&instance->kobj, 0, sizeof(struct kobject)); /* set this new device under the edac_device main kobject */ instance->kobj.parent = &edac_dev->kobj; instance->kobj.ktype = &ktype_instance_ctrl; instance->ctl = edac_dev; err = kobject_set_name(&instance->kobj, "%s", instance->name); if (err) goto err_out; /* bump the main kobject's reference count for this controller * and this instance is dependant on the main */ main_kobj = kobject_get(&edac_dev->kobj); if (!main_kobj) { err = -ENODEV; goto err_out; } /* Formally register this instance's kobject */ err = kobject_register(&instance->kobj); if (err != 0) { debugf2("%s() Failed to register instance '%s'\n", __func__, instance->name); kobject_put(main_kobj); goto err_out; } debugf4("%s() now register '%d' blocks for instance %d\n", __func__, instance->nr_blocks, idx); /* register all blocks of this instance */ for (i = 0; i < instance->nr_blocks; i++) { err = edac_device_create_block(edac_dev, instance, &instance->blocks[i]); if (err) { /* If any fail, remove all previous ones */ for (j = 0; j < i; j++) edac_device_delete_block(edac_dev, &instance->blocks[j]); goto err_release_instance_kobj; } } debugf4("%s() Registered instance %d '%s' kobject\n", __func__, idx, instance->name); return 0; /* error unwind stack */err_release_instance_kobj: kobject_unregister(&instance->kobj);err_out: return err;}/* * edac_device_remove_instance * remove an edac_device instance */static void edac_device_delete_instance(struct edac_device_ctl_info *edac_dev, int idx){ struct edac_device_instance *instance; int i; instance = &edac_dev->instances[idx]; /* unregister all blocks in this instance */ for (i = 0; i < instance->nr_blocks; i++) edac_device_delete_block(edac_dev, &instance->blocks[i]); /* unregister this instance's kobject, SEE: * edac_device_ctrl_instance_release() for callback operation */ kobject_unregister(&instance->kobj);}/* * edac_device_create_instances * create the first level of 'instances' for this device * (ie 'cache' might have 'cache0', 'cache1', 'cache2', etc */static int edac_device_create_instances(struct edac_device_ctl_info *edac_dev){ int i, j; int err; debugf0("%s()\n", __func__); /* iterate over creation of the instances */ for (i = 0; i < edac_dev->nr_instances; i++) { err = edac_device_create_instance(edac_dev, i); if (err) { /* unwind previous instances on error */ for (j = 0; j < i; j++) edac_device_delete_instance(edac_dev, j); return err; } } return 0;}/* * edac_device_delete_instances(edac_dev); * unregister all the kobjects of the instances */static void edac_device_delete_instances(struct edac_device_ctl_info *edac_dev){ int i; /* iterate over creation of the instances */ for (i = 0; i < edac_dev->nr_instances; i++) edac_device_delete_instance(edac_dev, i);}/* edac_dev sysfs ctor/dtor code *//* * edac_device_add_main_sysfs_attributes * add some attributes to this instance's main kobject */static int edac_device_add_main_sysfs_attributes( struct edac_device_ctl_info *edac_dev){ struct edac_dev_sysfs_attribute *sysfs_attrib; int err = 0; sysfs_attrib = edac_dev->sysfs_attributes; if (sysfs_attrib) { /* iterate over the array and create an attribute for each * entry in the list */ while (sysfs_attrib->attr.name != NULL) { err = sysfs_create_file(&edac_dev->kobj, (struct attribute*) sysfs_attrib); if (err) goto err_out; sysfs_attrib++; } }err_out: return err;}/* * edac_device_remove_main_sysfs_attributes * remove any attributes to this instance's main kobject */static void edac_device_remove_main_sysfs_attributes( struct edac_device_ctl_info *edac_dev){ struct edac_dev_sysfs_attribute *sysfs_attrib; /* if there are main attributes, defined, remove them. First, * point to the start of the array and iterate over it * removing each attribute listed from this device's instance's kobject */ sysfs_attrib = edac_dev->sysfs_attributes; if (sysfs_attrib) { while (sysfs_attrib->attr.name != NULL) { sysfs_remove_file(&edac_dev->kobj, (struct attribute *) sysfs_attrib); sysfs_attrib++; } }}/* * edac_device_create_sysfs() Constructor * * accept a created edac_device control structure * and 'export' it to sysfs. The 'main' kobj should already have been * created. 'instance' and 'block' kobjects should be registered * along with any 'block' attributes from the low driver. In addition, * the main attributes (if any) are connected to the main kobject of * the control structure. * * Return: * 0 Success * !0 Failure */int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev){ int err; struct kobject *edac_kobj = &edac_dev->kobj; debugf0("%s() idx=%d\n", __func__, edac_dev->dev_idx); /* go create any main attributes callers wants */ err = edac_device_add_main_sysfs_attributes(edac_dev); if (err) { debugf0("%s() failed to add sysfs attribs\n", __func__); goto err_out; } /* create a symlink from the edac device * to the platform 'device' being used for this */ err = sysfs_create_link(edac_kobj, &edac_dev->dev->kobj, EDAC_DEVICE_SYMLINK); if (err) { debugf0("%s() sysfs_create_link() returned err= %d\n", __func__, err); goto err_remove_main_attribs; } /* Create the first level instance directories * In turn, the nested blocks beneath the instances will * be registered as well */ err = edac_device_create_instances(edac_dev); if (err) { debugf0("%s() edac_device_create_instances() " "returned err= %d\n", __func__, err); goto err_remove_link; } debugf4("%s() create-instances done, idx=%d\n", __func__, edac_dev->dev_idx); return 0; /* Error unwind stack */err_remove_link: /* remove the sym link */ sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK);err_remove_main_attribs: edac_device_remove_main_sysfs_attributes(edac_dev);err_out: return err;}/* * edac_device_remove_sysfs() destructor * * given an edac_device struct, tear down the kobject resources */void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev){ debugf0("%s()\n", __func__); /* remove any main attributes for this device */ edac_device_remove_main_sysfs_attributes(edac_dev); /* remove the device sym link */ sysfs_remove_link(&edac_dev->kobj, EDAC_DEVICE_SYMLINK); /* walk the instance/block kobject tree, deconstructing it */ edac_device_delete_instances(edac_dev);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?