📄 sysfs.c
字号:
&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_attr[i]); ++i) { kfree(a->name); kfree(a); } for (i = 0; (a = p->pkey_attr[i]); ++i) { kfree(a->name); kfree(a); } kfree(p->gid_attr); 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_hotplug(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_hotplug_env_var(envp, num_envp, &i, buf, size, &len, "NAME=%s", dev->name)) return -ENOMEM; /* * It might be nice to pass the node GUID to hotplug, but * right now the only way to get it is to query the device * provider, and this can crash during device removal because * we are will be running after driver removal has started. * We could add a node_guid field to struct ib_device, or we * could just let the hotplug script read the node GUID from * sysfs when devices are added. */ envp[i] = NULL; return 0;}static int alloc_group(struct attribute ***attr, ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf), int len){ struct port_table_attribute ***tab_attr = (struct port_table_attribute ***) attr; int i; int ret; *tab_attr = kmalloc((1 + len) * sizeof *tab_attr, GFP_KERNEL); if (!*tab_attr) return -ENOMEM; memset(*tab_attr, 0, (1 + len) * sizeof *tab_attr); for (i = 0; i < len; ++i) { (*tab_attr)[i] = kmalloc(sizeof *(*tab_attr)[i], GFP_KERNEL); if (!(*tab_attr)[i]) { ret = -ENOMEM; goto err; } memset((*tab_attr)[i], 0, sizeof *(*tab_attr)[i]); (*tab_attr)[i]->attr.attr.name = kmalloc(8, GFP_KERNEL); if (!(*tab_attr)[i]->attr.attr.name) { ret = -ENOMEM; goto err; } if (snprintf((*tab_attr)[i]->attr.attr.name, 8, "%d", i) >= 8) { ret = -ENOMEM; goto err; } (*tab_attr)[i]->attr.attr.mode = S_IRUGO; (*tab_attr)[i]->attr.attr.owner = THIS_MODULE; (*tab_attr)[i]->attr.show = show; (*tab_attr)[i]->index = i; } return 0;err: for (i = 0; i < len; ++i) { if ((*tab_attr)[i]) kfree((*tab_attr)[i]->attr.attr.name); kfree((*tab_attr)[i]); } kfree(*tab_attr); return ret;}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 = kmalloc(sizeof *p, GFP_KERNEL); if (!p) return -ENOMEM; memset(p, 0, sizeof *p); 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; ret = alloc_group(&p->gid_attr, show_port_gid, attr.gid_tbl_len); if (ret) goto err_remove_pma; p->gid_group.name = "gids"; p->gid_group.attrs = p->gid_attr; ret = sysfs_create_group(&p->kobj, &p->gid_group); if (ret) goto err_free_gid; ret = alloc_group(&p->pkey_attr, show_port_pkey, attr.pkey_tbl_len); if (ret) goto err_remove_gid; p->pkey_group.name = "pkeys"; p->pkey_group.attrs = p->pkey_attr; 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_attr[i]->name); kfree(p->pkey_attr[i]); } kfree(p->pkey_attr);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_attr[i]->name); kfree(p->gid_attr[i]); } kfree(p->gid_attr);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); 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; ret = ib_query_device(dev, &attr); if (ret) return ret; return sprintf(buf, "%04x:%04x:%04x:%04x\n", be16_to_cpu(((u16 *) &attr.sys_image_guid)[0]), be16_to_cpu(((u16 *) &attr.sys_image_guid)[1]), be16_to_cpu(((u16 *) &attr.sys_image_guid)[2]), be16_to_cpu(((u16 *) &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); struct ib_device_attr attr; ssize_t ret; ret = ib_query_device(dev, &attr); if (ret) return ret; return sprintf(buf, "%04x:%04x:%04x:%04x\n", be16_to_cpu(((u16 *) &attr.node_guid)[0]), be16_to_cpu(((u16 *) &attr.node_guid)[1]), be16_to_cpu(((u16 *) &attr.node_guid)[2]), be16_to_cpu(((u16 *) &attr.node_guid)[3]));}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 struct class_device_attribute *ib_class_attributes[] = { &class_device_attr_node_type, &class_device_attr_sys_image_guid, &class_device_attr_node_guid};static struct class ib_class = { .name = "infiniband", .release = ib_device_release, .hotplug = ib_device_hotplug,};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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -