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 + -
显示快捷键?