📄 sysfs.c
字号:
&port_pma_attr_symbol_error.attr.attr, &port_pma_attr_link_error_recovery.attr.attr, &port_pma_attr_link_downed.attr.attr, &port_pma_attr_port_rcv_errors.attr.attr, &port_pma_attr_port_rcv_remote_physical_errors.attr.attr, &port_pma_attr_port_rcv_switch_relay_errors.attr.attr, &port_pma_attr_port_xmit_discards.attr.attr, &port_pma_attr_port_xmit_constraint_errors.attr.attr, &port_pma_attr_port_rcv_constraint_errors.attr.attr, &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_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 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)) 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); 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.node_guid)[0]), be16_to_cpu(((__be16 *) &attr.node_guid)[1]), be16_to_cpu(((__be16 *) &attr.node_guid)[2]), be16_to_cpu(((__be16 *) &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 + -