Loading drivers/ieee1394/nodemgr.c +176 −138 Original line number Diff line number Diff line Loading @@ -727,33 +727,31 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) static DEFINE_MUTEX(nodemgr_serialize_remove_uds); static int __match_ne(struct device *dev, void *data) { struct unit_directory *ud; struct node_entry *ne = (struct node_entry *)data; ud = container_of(dev, struct unit_directory, unit_dev); return ud->ne == ne; } static void nodemgr_remove_uds(struct node_entry *ne) { struct device *dev; struct unit_directory *tmp, *ud; /* Iteration over nodemgr_ud_class.devices has to be protected by * nodemgr_ud_class.sem, but 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. struct unit_directory *ud; /* Use class_find device to iterate the devices. Since this code * may be called from other contexts besides the knodemgrds, * protect it by nodemgr_serialize_remove_uds. */ mutex_lock(&nodemgr_serialize_remove_uds); for (;;) { ud = NULL; down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { tmp = container_of(dev, struct unit_directory, unit_dev); if (tmp->ne == ne) { ud = tmp; break; } } up(&nodemgr_ud_class.sem); if (ud == NULL) dev = class_find_device(&nodemgr_ud_class, ne, __match_ne); if (!dev) break; ud = container_of(dev, struct unit_directory, unit_dev); put_device(dev); device_unregister(&ud->unit_dev); device_unregister(&ud->device); } Loading Loading @@ -882,45 +880,66 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr return NULL; } static int __match_ne_guid(struct device *dev, void *data) { struct node_entry *ne; u64 *guid = (u64 *)data; ne = container_of(dev, struct node_entry, node_dev); return ne->guid == *guid; } static struct node_entry *find_entry_by_guid(u64 guid) { struct device *dev; struct node_entry *ne, *ret_ne = NULL; struct node_entry *ne; down(&nodemgr_ne_class.sem); list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); put_device(dev); if (ne->guid == guid) { ret_ne = ne; break; } return ne; } up(&nodemgr_ne_class.sem); return ret_ne; } struct match_nodeid_param { struct hpsb_host *host; nodeid_t nodeid; }; static int __match_ne_nodeid(struct device *dev, void *data) { int found = 0; struct node_entry *ne; struct match_nodeid_param *param = (struct match_nodeid_param *)data; if (!dev) goto ret; ne = container_of(dev, struct node_entry, node_dev); if (ne->host == param->host && ne->nodeid == param->nodeid) found = 1; ret: return found; } static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) { struct device *dev; struct node_entry *ne, *ret_ne = NULL; struct node_entry *ne; struct match_nodeid_param param; down(&nodemgr_ne_class.sem); list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { ne = container_of(dev, struct node_entry, node_dev); param.host = host; param.nodeid = nodeid; if (ne->host == host && ne->nodeid == nodeid) { ret_ne = ne; break; } } up(&nodemgr_ne_class.sem); dev = class_find_device(&nodemgr_ne_class, ¶m, __match_ne_nodeid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); put_device(dev); return ret_ne; return ne; } Loading Loading @@ -1370,30 +1389,17 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) } } static void nodemgr_suspend_ne(struct node_entry *ne) static int __nodemgr_driver_suspend(struct device *dev, void *data) { struct device *dev; struct unit_directory *ud; struct device_driver *drv; struct node_entry *ne = (struct node_entry *)data; int error; HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); ne->in_limbo = 1; WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne != ne) continue; if (ud->ne == ne) { drv = get_driver(ud->device.driver); if (!drv) continue; if (drv) { error = 1; /* release if suspend is not implemented */ if (drv->suspend) { down(&ud->device.sem); Loading @@ -1404,29 +1410,21 @@ static void nodemgr_suspend_ne(struct node_entry *ne) device_release_driver(&ud->device); put_driver(drv); } up(&nodemgr_ud_class.sem); } return 0; } static void nodemgr_resume_ne(struct node_entry *ne) static int __nodemgr_driver_resume(struct device *dev, void *data) { struct device *dev; struct unit_directory *ud; struct device_driver *drv; struct node_entry *ne = (struct node_entry *)data; ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne != ne) continue; if (ud->ne == ne) { drv = get_driver(ud->device.driver); if (!drv) continue; if (drv) { if (drv->resume) { down(&ud->device.sem); drv->resume(&ud->device); Loading @@ -1434,33 +1432,49 @@ static void nodemgr_resume_ne(struct node_entry *ne) } put_driver(drv); } up(&nodemgr_ud_class.sem); } return 0; } static void nodemgr_suspend_ne(struct node_entry *ne) { HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); ne->in_limbo = 1; WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend); } static void nodemgr_resume_ne(struct node_entry *ne) { ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume); HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); } static void nodemgr_update_pdrv(struct node_entry *ne) static int __nodemgr_update_pdrv(struct device *dev, void *data) { struct device *dev; struct unit_directory *ud; struct device_driver *drv; struct hpsb_protocol_driver *pdrv; struct node_entry *ne = (struct node_entry *)data; int error; down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne != ne) continue; if (ud->ne == ne) { drv = get_driver(ud->device.driver); if (!drv) continue; if (drv) { error = 0; pdrv = container_of(drv, struct hpsb_protocol_driver, driver); pdrv = container_of(drv, struct hpsb_protocol_driver, driver); if (pdrv->update) { down(&ud->device.sem); error = pdrv->update(ud); Loading @@ -1470,7 +1484,14 @@ static void nodemgr_update_pdrv(struct node_entry *ne) device_release_driver(&ud->device); put_driver(drv); } up(&nodemgr_ud_class.sem); } return 0; } static void nodemgr_update_pdrv(struct node_entry *ne) { class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv); } Loading Loading @@ -1529,13 +1550,31 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge put_device(dev); } struct probe_param { struct host_info *hi; int generation; }; static int __nodemgr_node_probe(struct device *dev, void *data) { struct probe_param *param = (struct probe_param *)data; struct node_entry *ne; ne = container_of(dev, struct node_entry, node_dev); if (!ne->needs_probe) nodemgr_probe_ne(param->hi, ne, param->generation); if (ne->needs_probe) nodemgr_probe_ne(param->hi, ne, param->generation); return 0; } static void nodemgr_node_probe(struct host_info *hi, int generation) { struct hpsb_host *host = hi->host; struct device *dev; struct node_entry *ne; struct probe_param param; param.hi = hi; param.generation = generation; /* Do some processing of the nodes we've probed. This pulls them * into the sysfs layer if needed, and can result in processing of * unit-directories, or just updating the node and it's Loading @@ -1545,19 +1584,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * while probes are time-consuming. (Well, those probes need some * improvement...) */ down(&nodemgr_ne_class.sem); list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { ne = container_of(dev, struct node_entry, node_dev); if (!ne->needs_probe) nodemgr_probe_ne(hi, ne, generation); } list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { ne = container_of(dev, struct node_entry, node_dev); if (ne->needs_probe) nodemgr_probe_ne(hi, ne, generation); } up(&nodemgr_ne_class.sem); class_for_each_device(&nodemgr_ne_class, ¶m, __nodemgr_node_probe); /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we Loading Loading @@ -1757,6 +1784,22 @@ static int nodemgr_host_thread(void *__hi) return 0; } struct host_iter_param { void *data; int (*cb)(struct hpsb_host *, void *); }; static int __nodemgr_for_each_host(struct device *dev, void *data) { struct hpsb_host *host; struct host_iter_param *hip = (struct host_iter_param *)data; int error = 0; host = container_of(dev, struct hpsb_host, host_dev); error = hip->cb(host, hip->data); return error; } /** * nodemgr_for_each_host - call a function for each IEEE 1394 host * @data: an address to supply to the callback Loading @@ -1771,18 +1814,13 @@ static int nodemgr_host_thread(void *__hi) */ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) { struct device *dev; struct hpsb_host *host; int error = 0; down(&hpsb_host_class.sem); list_for_each_entry(dev, &hpsb_host_class.devices, node) { host = container_of(dev, struct hpsb_host, host_dev); struct host_iter_param hip; int error; if ((error = cb(host, data))) break; } up(&hpsb_host_class.sem); hip.cb = cb; hip.data = data; error = class_for_each_device(&hpsb_host_class, &hip, __nodemgr_for_each_host); return error; } Loading Loading
drivers/ieee1394/nodemgr.c +176 −138 Original line number Diff line number Diff line Loading @@ -727,33 +727,31 @@ static int nodemgr_bus_match(struct device * dev, struct device_driver * drv) static DEFINE_MUTEX(nodemgr_serialize_remove_uds); static int __match_ne(struct device *dev, void *data) { struct unit_directory *ud; struct node_entry *ne = (struct node_entry *)data; ud = container_of(dev, struct unit_directory, unit_dev); return ud->ne == ne; } static void nodemgr_remove_uds(struct node_entry *ne) { struct device *dev; struct unit_directory *tmp, *ud; /* Iteration over nodemgr_ud_class.devices has to be protected by * nodemgr_ud_class.sem, but 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. struct unit_directory *ud; /* Use class_find device to iterate the devices. Since this code * may be called from other contexts besides the knodemgrds, * protect it by nodemgr_serialize_remove_uds. */ mutex_lock(&nodemgr_serialize_remove_uds); for (;;) { ud = NULL; down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { tmp = container_of(dev, struct unit_directory, unit_dev); if (tmp->ne == ne) { ud = tmp; break; } } up(&nodemgr_ud_class.sem); if (ud == NULL) dev = class_find_device(&nodemgr_ud_class, ne, __match_ne); if (!dev) break; ud = container_of(dev, struct unit_directory, unit_dev); put_device(dev); device_unregister(&ud->unit_dev); device_unregister(&ud->device); } Loading Loading @@ -882,45 +880,66 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr return NULL; } static int __match_ne_guid(struct device *dev, void *data) { struct node_entry *ne; u64 *guid = (u64 *)data; ne = container_of(dev, struct node_entry, node_dev); return ne->guid == *guid; } static struct node_entry *find_entry_by_guid(u64 guid) { struct device *dev; struct node_entry *ne, *ret_ne = NULL; struct node_entry *ne; down(&nodemgr_ne_class.sem); list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { dev = class_find_device(&nodemgr_ne_class, &guid, __match_ne_guid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); put_device(dev); if (ne->guid == guid) { ret_ne = ne; break; } return ne; } up(&nodemgr_ne_class.sem); return ret_ne; } struct match_nodeid_param { struct hpsb_host *host; nodeid_t nodeid; }; static int __match_ne_nodeid(struct device *dev, void *data) { int found = 0; struct node_entry *ne; struct match_nodeid_param *param = (struct match_nodeid_param *)data; if (!dev) goto ret; ne = container_of(dev, struct node_entry, node_dev); if (ne->host == param->host && ne->nodeid == param->nodeid) found = 1; ret: return found; } static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) { struct device *dev; struct node_entry *ne, *ret_ne = NULL; struct node_entry *ne; struct match_nodeid_param param; down(&nodemgr_ne_class.sem); list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { ne = container_of(dev, struct node_entry, node_dev); param.host = host; param.nodeid = nodeid; if (ne->host == host && ne->nodeid == nodeid) { ret_ne = ne; break; } } up(&nodemgr_ne_class.sem); dev = class_find_device(&nodemgr_ne_class, ¶m, __match_ne_nodeid); if (!dev) return NULL; ne = container_of(dev, struct node_entry, node_dev); put_device(dev); return ret_ne; return ne; } Loading Loading @@ -1370,30 +1389,17 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) } } static void nodemgr_suspend_ne(struct node_entry *ne) static int __nodemgr_driver_suspend(struct device *dev, void *data) { struct device *dev; struct unit_directory *ud; struct device_driver *drv; struct node_entry *ne = (struct node_entry *)data; int error; HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); ne->in_limbo = 1; WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne != ne) continue; if (ud->ne == ne) { drv = get_driver(ud->device.driver); if (!drv) continue; if (drv) { error = 1; /* release if suspend is not implemented */ if (drv->suspend) { down(&ud->device.sem); Loading @@ -1404,29 +1410,21 @@ static void nodemgr_suspend_ne(struct node_entry *ne) device_release_driver(&ud->device); put_driver(drv); } up(&nodemgr_ud_class.sem); } return 0; } static void nodemgr_resume_ne(struct node_entry *ne) static int __nodemgr_driver_resume(struct device *dev, void *data) { struct device *dev; struct unit_directory *ud; struct device_driver *drv; struct node_entry *ne = (struct node_entry *)data; ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne != ne) continue; if (ud->ne == ne) { drv = get_driver(ud->device.driver); if (!drv) continue; if (drv) { if (drv->resume) { down(&ud->device.sem); drv->resume(&ud->device); Loading @@ -1434,33 +1432,49 @@ static void nodemgr_resume_ne(struct node_entry *ne) } put_driver(drv); } up(&nodemgr_ud_class.sem); } return 0; } static void nodemgr_suspend_ne(struct node_entry *ne) { HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); ne->in_limbo = 1; WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_suspend); } static void nodemgr_resume_ne(struct node_entry *ne) { ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_driver_resume); HPSB_DEBUG("Node resumed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid); } static void nodemgr_update_pdrv(struct node_entry *ne) static int __nodemgr_update_pdrv(struct device *dev, void *data) { struct device *dev; struct unit_directory *ud; struct device_driver *drv; struct hpsb_protocol_driver *pdrv; struct node_entry *ne = (struct node_entry *)data; int error; down(&nodemgr_ud_class.sem); list_for_each_entry(dev, &nodemgr_ud_class.devices, node) { ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne != ne) continue; if (ud->ne == ne) { drv = get_driver(ud->device.driver); if (!drv) continue; if (drv) { error = 0; pdrv = container_of(drv, struct hpsb_protocol_driver, driver); pdrv = container_of(drv, struct hpsb_protocol_driver, driver); if (pdrv->update) { down(&ud->device.sem); error = pdrv->update(ud); Loading @@ -1470,7 +1484,14 @@ static void nodemgr_update_pdrv(struct node_entry *ne) device_release_driver(&ud->device); put_driver(drv); } up(&nodemgr_ud_class.sem); } return 0; } static void nodemgr_update_pdrv(struct node_entry *ne) { class_for_each_device(&nodemgr_ud_class, ne, __nodemgr_update_pdrv); } Loading Loading @@ -1529,13 +1550,31 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge put_device(dev); } struct probe_param { struct host_info *hi; int generation; }; static int __nodemgr_node_probe(struct device *dev, void *data) { struct probe_param *param = (struct probe_param *)data; struct node_entry *ne; ne = container_of(dev, struct node_entry, node_dev); if (!ne->needs_probe) nodemgr_probe_ne(param->hi, ne, param->generation); if (ne->needs_probe) nodemgr_probe_ne(param->hi, ne, param->generation); return 0; } static void nodemgr_node_probe(struct host_info *hi, int generation) { struct hpsb_host *host = hi->host; struct device *dev; struct node_entry *ne; struct probe_param param; param.hi = hi; param.generation = generation; /* Do some processing of the nodes we've probed. This pulls them * into the sysfs layer if needed, and can result in processing of * unit-directories, or just updating the node and it's Loading @@ -1545,19 +1584,7 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * while probes are time-consuming. (Well, those probes need some * improvement...) */ down(&nodemgr_ne_class.sem); list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { ne = container_of(dev, struct node_entry, node_dev); if (!ne->needs_probe) nodemgr_probe_ne(hi, ne, generation); } list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { ne = container_of(dev, struct node_entry, node_dev); if (ne->needs_probe) nodemgr_probe_ne(hi, ne, generation); } up(&nodemgr_ne_class.sem); class_for_each_device(&nodemgr_ne_class, ¶m, __nodemgr_node_probe); /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we Loading Loading @@ -1757,6 +1784,22 @@ static int nodemgr_host_thread(void *__hi) return 0; } struct host_iter_param { void *data; int (*cb)(struct hpsb_host *, void *); }; static int __nodemgr_for_each_host(struct device *dev, void *data) { struct hpsb_host *host; struct host_iter_param *hip = (struct host_iter_param *)data; int error = 0; host = container_of(dev, struct hpsb_host, host_dev); error = hip->cb(host, hip->data); return error; } /** * nodemgr_for_each_host - call a function for each IEEE 1394 host * @data: an address to supply to the callback Loading @@ -1771,18 +1814,13 @@ static int nodemgr_host_thread(void *__hi) */ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) { struct device *dev; struct hpsb_host *host; int error = 0; down(&hpsb_host_class.sem); list_for_each_entry(dev, &hpsb_host_class.devices, node) { host = container_of(dev, struct hpsb_host, host_dev); struct host_iter_param hip; int error; if ((error = cb(host, data))) break; } up(&hpsb_host_class.sem); hip.cb = cb; hip.data = data; error = class_for_each_device(&hpsb_host_class, &hip, __nodemgr_for_each_host); return error; } Loading