sysfs.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 778 行 · 第 1/2 页

C
778
字号
	&port_pma_attr_local_link_integrity_errors.attr.attr,	&port_pma_attr_excessive_buffer_overrun_errors.attr.attr,	&port_pma_attr_VL15_dropped.attr.attr,	&port_pma_attr_port_xmit_data.attr.attr,	&port_pma_attr_port_rcv_data.attr.attr,	&port_pma_attr_port_xmit_packets.attr.attr,	&port_pma_attr_port_rcv_packets.attr.attr,	NULL};static struct attribute_group pma_group = {	.name  = "counters",	.attrs  = pma_attrs};static void ib_port_release(struct kobject *kobj){	struct ib_port *p = container_of(kobj, struct ib_port, kobj);	struct attribute *a;	int i;	for (i = 0; (a = p->gid_group.attrs[i]); ++i)		kfree(a);	kfree(p->gid_group.attrs);	for (i = 0; (a = p->pkey_group.attrs[i]); ++i)		kfree(a);	kfree(p->pkey_group.attrs);	kfree(p);}static struct kobj_type port_type = {	.release       = ib_port_release,	.sysfs_ops     = &port_sysfs_ops,	.default_attrs = port_default_attrs};static void ib_device_release(struct class_device *cdev){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	kfree(dev);}static int ib_device_uevent(struct class_device *cdev, char **envp,			    int num_envp, char *buf, int size){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	int i = 0, len = 0;	if (add_uevent_var(envp, num_envp, &i, buf, size, &len,			   "NAME=%s", dev->name))		return -ENOMEM;	/*	 * It would be nice to pass the node GUID with the event...	 */	envp[i] = NULL;	return 0;}static struct attribute **alloc_group_attrs(ssize_t (*show)(struct ib_port *,				  struct port_attribute *, char *buf),		  int len){	struct attribute **tab_attr;	struct port_table_attribute *element;	int i;	tab_attr = kcalloc(1 + len, sizeof(struct attribute *), GFP_KERNEL);	if (!tab_attr)		return NULL;	for (i = 0; i < len; i++) {		element = kzalloc(sizeof(struct port_table_attribute),				  GFP_KERNEL);		if (!element)			goto err;		if (snprintf(element->name, sizeof(element->name),			     "%d", i) >= sizeof(element->name)) {			kfree(element);			goto err;		}		element->attr.attr.name  = element->name;		element->attr.attr.mode  = S_IRUGO;		element->attr.attr.owner = THIS_MODULE;		element->attr.show       = show;		element->index		 = i;		tab_attr[i] = &element->attr.attr;	}	return tab_attr;err:	while (--i >= 0)		kfree(tab_attr[i]);	kfree(tab_attr);	return NULL;}static int add_port(struct ib_device *device, int port_num){	struct ib_port *p;	struct ib_port_attr attr;	int i;	int ret;	ret = ib_query_port(device, port_num, &attr);	if (ret)		return ret;	p = kzalloc(sizeof *p, GFP_KERNEL);	if (!p)		return -ENOMEM;	p->ibdev      = device;	p->port_num   = port_num;	p->kobj.ktype = &port_type;	p->kobj.parent = kobject_get(&device->ports_parent);	if (!p->kobj.parent) {		ret = -EBUSY;		goto err;	}	ret = kobject_set_name(&p->kobj, "%d", port_num);	if (ret)		goto err_put;	ret = kobject_register(&p->kobj);	if (ret)		goto err_put;	ret = sysfs_create_group(&p->kobj, &pma_group);	if (ret)		goto err_put;	p->gid_group.name  = "gids";	p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len);	if (!p->gid_group.attrs)		goto err_remove_pma;	ret = sysfs_create_group(&p->kobj, &p->gid_group);	if (ret)		goto err_free_gid;	p->pkey_group.name  = "pkeys";	p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,						attr.pkey_tbl_len);	if (!p->pkey_group.attrs)		goto err_remove_gid;	ret = sysfs_create_group(&p->kobj, &p->pkey_group);	if (ret)		goto err_free_pkey;	list_add_tail(&p->kobj.entry, &device->port_list);	return 0;err_free_pkey:	for (i = 0; i < attr.pkey_tbl_len; ++i)		kfree(p->pkey_group.attrs[i]);	kfree(p->pkey_group.attrs);err_remove_gid:	sysfs_remove_group(&p->kobj, &p->gid_group);err_free_gid:	for (i = 0; i < attr.gid_tbl_len; ++i)		kfree(p->gid_group.attrs[i]);	kfree(p->gid_group.attrs);err_remove_pma:	sysfs_remove_group(&p->kobj, &pma_group);err_put:	kobject_put(&device->ports_parent);err:	kfree(p);	return ret;}static ssize_t show_node_type(struct class_device *cdev, char *buf){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	if (!ibdev_is_alive(dev))		return -ENODEV;	switch (dev->node_type) {	case IB_NODE_CA:     return sprintf(buf, "%d: CA\n", dev->node_type);	case IB_NODE_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);	case IB_NODE_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type);	default:             return sprintf(buf, "%d: <unknown>\n", dev->node_type);	}}static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	struct ib_device_attr attr;	ssize_t ret;	if (!ibdev_is_alive(dev))		return -ENODEV;	ret = ib_query_device(dev, &attr);	if (ret)		return ret;	return sprintf(buf, "%04x:%04x:%04x:%04x\n",		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[0]),		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[1]),		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[2]),		       be16_to_cpu(((__be16 *) &attr.sys_image_guid)[3]));}static ssize_t show_node_guid(struct class_device *cdev, char *buf){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	if (!ibdev_is_alive(dev))		return -ENODEV;	return sprintf(buf, "%04x:%04x:%04x:%04x\n",		       be16_to_cpu(((__be16 *) &dev->node_guid)[0]),		       be16_to_cpu(((__be16 *) &dev->node_guid)[1]),		       be16_to_cpu(((__be16 *) &dev->node_guid)[2]),		       be16_to_cpu(((__be16 *) &dev->node_guid)[3]));}static ssize_t show_node_desc(struct class_device *cdev, char *buf){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	return sprintf(buf, "%.64s\n", dev->node_desc);}static ssize_t set_node_desc(struct class_device *cdev, const char *buf,			      size_t count){	struct ib_device *dev = container_of(cdev, struct ib_device, class_dev);	struct ib_device_modify desc = {};	int ret;	if (!dev->modify_device)		return -EIO;	memcpy(desc.node_desc, buf, min_t(int, count, 64));	ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc);	if (ret)		return ret;	return count;}static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);static CLASS_DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);static CLASS_DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);static CLASS_DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc,			 set_node_desc);static struct class_device_attribute *ib_class_attributes[] = {	&class_device_attr_node_type,	&class_device_attr_sys_image_guid,	&class_device_attr_node_guid,	&class_device_attr_node_desc};static struct class ib_class = {	.name    = "infiniband",	.release = ib_device_release,	.uevent = ib_device_uevent,};int ib_device_register_sysfs(struct ib_device *device){	struct class_device *class_dev = &device->class_dev;	int ret;	int i;	class_dev->class      = &ib_class;	class_dev->class_data = device;	strlcpy(class_dev->class_id, device->name, BUS_ID_SIZE);	INIT_LIST_HEAD(&device->port_list);	ret = class_device_register(class_dev);	if (ret)		goto err;	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {		ret = class_device_create_file(class_dev, ib_class_attributes[i]);		if (ret)			goto err_unregister;	}	device->ports_parent.parent = kobject_get(&class_dev->kobj);	if (!device->ports_parent.parent) {		ret = -EBUSY;		goto err_unregister;	}	ret = kobject_set_name(&device->ports_parent, "ports");	if (ret)		goto err_put;	ret = kobject_register(&device->ports_parent);	if (ret)		goto err_put;	if (device->node_type == IB_NODE_SWITCH) {		ret = add_port(device, 0);		if (ret)			goto err_put;	} else {		int i;		for (i = 1; i <= device->phys_port_cnt; ++i) {			ret = add_port(device, i);			if (ret)				goto err_put;		}	}	return 0;err_put:	{		struct kobject *p, *t;		struct ib_port *port;		list_for_each_entry_safe(p, t, &device->port_list, entry) {			list_del(&p->entry);			port = container_of(p, struct ib_port, kobj);			sysfs_remove_group(p, &pma_group);			sysfs_remove_group(p, &port->pkey_group);			sysfs_remove_group(p, &port->gid_group);			kobject_unregister(p);		}	}	kobject_put(&class_dev->kobj);err_unregister:	class_device_unregister(class_dev);err:	return ret;}void ib_device_unregister_sysfs(struct ib_device *device){	struct kobject *p, *t;	struct ib_port *port;	list_for_each_entry_safe(p, t, &device->port_list, entry) {		list_del(&p->entry);		port = container_of(p, struct ib_port, kobj);		sysfs_remove_group(p, &pma_group);		sysfs_remove_group(p, &port->pkey_group);		sysfs_remove_group(p, &port->gid_group);		kobject_unregister(p);	}	kobject_unregister(&device->ports_parent);	class_device_unregister(&device->class_dev);}int ib_sysfs_setup(void){	return class_register(&ib_class);}void ib_sysfs_cleanup(void){	class_unregister(&ib_class);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?