📄 nodemgr.c
字号:
&dev_attr_tlabels_free, &dev_attr_tlabels_mask,#endif};fw_attr(ud, struct unit_directory, address, unsigned long long, "0x%016Lx\n")fw_attr(ud, struct unit_directory, length, int, "%d\n")/* These are all dependent on the value being provided */fw_attr(ud, struct unit_directory, vendor_id, unsigned int, "0x%06x\n")fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n")fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n")fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n")fw_attr_td(ud, struct unit_directory, vendor_name_kv)fw_attr_td(ud, struct unit_directory, model_name_kv)static struct device_attribute *const fw_ud_attrs[] = { &dev_attr_ud_address, &dev_attr_ud_length, &dev_attr_ignore_driver,};fw_attr(host, struct hpsb_host, node_count, int, "%d\n")fw_attr(host, struct hpsb_host, selfid_count, int, "%d\n")fw_attr(host, struct hpsb_host, nodes_active, int, "%d\n")fw_attr(host, struct hpsb_host, in_bus_reset, int, "%d\n")fw_attr(host, struct hpsb_host, is_root, int, "%d\n")fw_attr(host, struct hpsb_host, is_cycmst, int, "%d\n")fw_attr(host, struct hpsb_host, is_irm, int, "%d\n")fw_attr(host, struct hpsb_host, is_busmgr, int, "%d\n")static struct device_attribute *const fw_host_attrs[] = { &dev_attr_host_node_count, &dev_attr_host_selfid_count, &dev_attr_host_nodes_active, &dev_attr_host_in_bus_reset, &dev_attr_host_is_root, &dev_attr_host_is_cycmst, &dev_attr_host_is_irm, &dev_attr_host_is_busmgr,};static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf){ struct hpsb_protocol_driver *driver; struct ieee1394_device_id *id; int length = 0; char *scratch = buf; driver = container_of(drv, struct hpsb_protocol_driver, driver); for (id = driver->id_table; id->match_flags != 0; id++) { int need_coma = 0; if (id->match_flags & IEEE1394_MATCH_VENDOR_ID) { length += sprintf(scratch, "vendor_id=0x%06x", id->vendor_id); scratch = buf + length; need_coma++; } if (id->match_flags & IEEE1394_MATCH_MODEL_ID) { length += sprintf(scratch, "%smodel_id=0x%06x", need_coma++ ? "," : "", id->model_id); scratch = buf + length; } if (id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) { length += sprintf(scratch, "%sspecifier_id=0x%06x", need_coma++ ? "," : "", id->specifier_id); scratch = buf + length; } if (id->match_flags & IEEE1394_MATCH_VERSION) { length += sprintf(scratch, "%sversion=0x%06x", need_coma++ ? "," : "", id->version); scratch = buf + length; } if (need_coma) { *scratch++ = '\n'; length++; } } return length;}static DRIVER_ATTR(device_ids,S_IRUGO,fw_show_drv_device_ids,NULL);fw_drv_attr(name, const char *, "%s\n")static struct driver_attribute *const fw_drv_attrs[] = { &driver_attr_drv_name, &driver_attr_device_ids,};static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver){ struct device_driver *drv = &driver->driver; int i; for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) if (driver_create_file(drv, fw_drv_attrs[i])) goto fail; return;fail: HPSB_ERR("Failed to add sysfs attribute for driver %s", driver->name);}static void nodemgr_remove_drv_files(struct hpsb_protocol_driver *driver){ struct device_driver *drv = &driver->driver; int i; for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++) driver_remove_file(drv, fw_drv_attrs[i]);}static void nodemgr_create_ne_dev_files(struct node_entry *ne){ struct device *dev = &ne->device; int i; for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++) if (device_create_file(dev, fw_ne_attrs[i])) goto fail; return;fail: HPSB_ERR("Failed to add sysfs attribute for node %016Lx", (unsigned long long)ne->guid);}static void nodemgr_create_host_dev_files(struct hpsb_host *host){ struct device *dev = &host->device; int i; for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++) if (device_create_file(dev, fw_host_attrs[i])) goto fail; return;fail: HPSB_ERR("Failed to add sysfs attribute for host %d", host->id);}static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid);static void nodemgr_update_host_dev_links(struct hpsb_host *host){ struct device *dev = &host->device; struct node_entry *ne; sysfs_remove_link(&dev->kobj, "irm_id"); sysfs_remove_link(&dev->kobj, "busmgr_id"); sysfs_remove_link(&dev->kobj, "host_id"); if ((ne = find_entry_by_nodeid(host, host->irm_id)) && sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id")) goto fail; if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) && sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id")) goto fail; if ((ne = find_entry_by_nodeid(host, host->node_id)) && sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id")) goto fail; return;fail: HPSB_ERR("Failed to update sysfs attributes for host %d", host->id);}static void nodemgr_create_ud_dev_files(struct unit_directory *ud){ struct device *dev = &ud->device; int i; for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++) if (device_create_file(dev, fw_ud_attrs[i])) goto fail; if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) if (device_create_file(dev, &dev_attr_ud_specifier_id)) goto fail; if (ud->flags & UNIT_DIRECTORY_VERSION) if (device_create_file(dev, &dev_attr_ud_version)) goto fail; if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) { if (device_create_file(dev, &dev_attr_ud_vendor_id)) goto fail; if (ud->vendor_name_kv && device_create_file(dev, &dev_attr_ud_vendor_name_kv)) goto fail; } if (ud->flags & UNIT_DIRECTORY_MODEL_ID) { if (device_create_file(dev, &dev_attr_ud_model_id)) goto fail; if (ud->model_name_kv && device_create_file(dev, &dev_attr_ud_model_name_kv)) goto fail; } return;fail: HPSB_ERR("Failed to add sysfs attributes for unit %s", ud->device.bus_id);}static int nodemgr_bus_match(struct device * dev, struct device_driver * drv){ struct hpsb_protocol_driver *driver; struct unit_directory *ud; struct ieee1394_device_id *id; /* We only match unit directories */ if (dev->platform_data != &nodemgr_ud_platform_data) return 0; ud = container_of(dev, struct unit_directory, device); if (ud->ne->in_limbo || ud->ignore_driver) return 0; /* We only match drivers of type hpsb_protocol_driver */ if (drv == &nodemgr_mid_layer_driver) return 0; driver = container_of(drv, struct hpsb_protocol_driver, driver); for (id = driver->id_table; id->match_flags != 0; id++) { if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) && id->vendor_id != ud->vendor_id) continue; if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) && id->model_id != ud->model_id) continue; if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) && id->specifier_id != ud->specifier_id) continue; if ((id->match_flags & IEEE1394_MATCH_VERSION) && id->version != ud->version) continue; return 1; } return 0;}static DEFINE_MUTEX(nodemgr_serialize_remove_uds);static void nodemgr_remove_uds(struct node_entry *ne){ struct class_device *cdev; struct unit_directory *tmp, *ud; /* Iteration over nodemgr_ud_class.children has to be protected by * nodemgr_ud_class.sem, but class_device_unregister() will eventually * take nodemgr_ud_class.sem too. Therefore pick out one ud at a time, * release the semaphore, and then unregister the ud. Since this code * may be called from other contexts besides the knodemgrds, protect the * gap after release of the semaphore by nodemgr_serialize_remove_uds. */ mutex_lock(&nodemgr_serialize_remove_uds); for (;;) { ud = NULL; down(&nodemgr_ud_class.sem); list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { tmp = container_of(cdev, struct unit_directory, class_dev); if (tmp->ne == ne) { ud = tmp; break; } } up(&nodemgr_ud_class.sem); if (ud == NULL) break; class_device_unregister(&ud->class_dev); device_unregister(&ud->device); } mutex_unlock(&nodemgr_serialize_remove_uds);}static void nodemgr_remove_ne(struct node_entry *ne){ struct device *dev; dev = get_device(&ne->device); if (!dev) return; HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); nodemgr_remove_uds(ne); class_device_unregister(&ne->class_dev); device_unregister(dev); put_device(dev);}static int __nodemgr_remove_host_dev(struct device *dev, void *data){ nodemgr_remove_ne(container_of(dev, struct node_entry, device)); return 0;}static void nodemgr_remove_host_dev(struct device *dev){ WARN_ON(device_for_each_child(dev, NULL, __nodemgr_remove_host_dev)); sysfs_remove_link(&dev->kobj, "irm_id"); sysfs_remove_link(&dev->kobj, "busmgr_id"); sysfs_remove_link(&dev->kobj, "host_id");}static void nodemgr_update_bus_options(struct node_entry *ne){#ifdef CONFIG_IEEE1394_VERBOSEDEBUG static const u16 mr[] = { 4, 64, 1024, 0};#endif quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]); ne->busopt.irmc = (busoptions >> 31) & 1; ne->busopt.cmc = (busoptions >> 30) & 1; ne->busopt.isc = (busoptions >> 29) & 1; ne->busopt.bmc = (busoptions >> 28) & 1; ne->busopt.pmc = (busoptions >> 27) & 1; ne->busopt.cyc_clk_acc = (busoptions >> 16) & 0xff; ne->busopt.max_rec = 1 << (((busoptions >> 12) & 0xf) + 1); ne->busopt.max_rom = (busoptions >> 8) & 0x3; ne->busopt.generation = (busoptions >> 4) & 0xf; ne->busopt.lnkspd = busoptions & 0x7; HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d " "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d", busoptions, ne->busopt.irmc, ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc, ne->busopt.cyc_clk_acc, ne->busopt.max_rec, mr[ne->busopt.max_rom], ne->busopt.generation, ne->busopt.lnkspd);}static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr *csr, struct host_info *hi, nodeid_t nodeid, unsigned int generation){ struct hpsb_host *host = hi->host; struct node_entry *ne; ne = kzalloc(sizeof(*ne), GFP_KERNEL); if (!ne) goto fail_alloc; ne->host = host; ne->nodeid = nodeid; ne->generation = generation; ne->needs_probe = 1; ne->guid = guid; ne->guid_vendor_id = (guid >> 40) & 0xffffff; ne->csr = csr; memcpy(&ne->device, &nodemgr_dev_template_ne, sizeof(ne->device)); ne->device.parent = &host->device; snprintf(ne->device.bus_id, BUS_ID_SIZE, "%016Lx", (unsigned long long)(ne->guid)); ne->class_dev.dev = &ne->device; ne->class_dev.class = &nodemgr_ne_class; snprintf(ne->class_dev.class_id, BUS_ID_SIZE, "%016Lx", (unsigned long long)(ne->guid)); if (device_register(&ne->device)) goto fail_devreg; if (class_device_register(&ne->class_dev)) goto fail_classdevreg; get_device(&ne->device); nodemgr_create_ne_dev_files(ne); nodemgr_update_bus_options(ne); HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", (host->node_id == nodeid) ? "Host" : "Node", NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); return ne;fail_classdevreg: device_unregister(&ne->device);fail_devreg: kfree(ne);fail_alloc: HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid); return NULL;}static struct node_entry *find_entry_by_guid(u64 guid){ struct class_device *cdev; struct node_entry *ne, *ret_ne = NULL; down(&nodemgr_ne_class.sem); list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { ne = container_of(cdev, struct node_entry, class_dev); if (ne->guid == guid) { ret_ne = ne; break; } } up(&nodemgr_ne_class.sem); return ret_ne;}static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid){ struct class_device *cdev; struct node_entry *ne, *ret_ne = NULL; down(&nodemgr_ne_class.sem); list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { ne = container_of(cdev, struct node_entry, class_dev); if (ne->host == host && ne->nodeid == nodeid) { ret_ne = ne; break; } } up(&nodemgr_ne_class.sem); return ret_ne;}static void nodemgr_register_device(struct node_entry *ne, struct unit_directory *ud, struct device *parent){ memcpy(&ud->device, &nodemgr_dev_template_ud, sizeof(ud->device)); ud->device.parent = parent; snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u", ne->device.bus_id, ud->id); ud->class_dev.dev = &ud->device; ud->class_dev.class = &nodemgr_ud_class;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -