X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fieee1394%2Fnodemgr.c;h=90dc75be3418c91f0baab414181577f62ded696f;hb=172acf60f39046987d3ff7b955f2bcc45de7ddd3;hp=835937e385292d648ba3d2b131e906d66bbb5f09;hpb=57a44415beee38d1afcd8e1b5fad66f3414d2dac;p=linux-2.6-omap-h63xx.git diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 835937e3852..90dc75be341 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "csr.h" #include "highlevel.h" @@ -145,8 +146,6 @@ static struct csr1212_bus_ops nodemgr_csr_ops = { * but now we are much simpler because of the LDM. */ -static DEFINE_MUTEX(nodemgr_serialize); - struct host_info { struct hpsb_host *host; struct list_head list; @@ -154,8 +153,7 @@ struct host_info { }; static int nodemgr_bus_match(struct device * dev, struct device_driver * drv); -static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, - char *buffer, int buffer_size); +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env); static void nodemgr_resume_ne(struct node_entry *ne); static void nodemgr_remove_ne(struct node_entry *ne); static struct node_entry *find_entry_by_guid(u64 guid); @@ -165,37 +163,38 @@ struct bus_type ieee1394_bus_type = { .match = nodemgr_bus_match, }; -static void host_cls_release(struct class_device *class_dev) +static void host_cls_release(struct device *dev) { - put_device(&container_of((class_dev), struct hpsb_host, class_dev)->device); + put_device(&container_of((dev), struct hpsb_host, host_dev)->device); } struct class hpsb_host_class = { .name = "ieee1394_host", - .release = host_cls_release, + .dev_release = host_cls_release, }; -static void ne_cls_release(struct class_device *class_dev) +static void ne_cls_release(struct device *dev) { - put_device(&container_of((class_dev), struct node_entry, class_dev)->device); + put_device(&container_of((dev), struct node_entry, node_dev)->device); } static struct class nodemgr_ne_class = { .name = "ieee1394_node", - .release = ne_cls_release, + .dev_release = ne_cls_release, }; -static void ud_cls_release(struct class_device *class_dev) +static void ud_cls_release(struct device *dev) { - put_device(&container_of((class_dev), struct unit_directory, class_dev)->device); + put_device(&container_of((dev), struct unit_directory, unit_dev)->device); } /* The name here is only so that unit directory hotplug works with old - * style hotplug, which only ever did unit directories anyway. */ + * style hotplug, which only ever did unit directories anyway. + */ static struct class nodemgr_ud_class = { .name = "ieee1394", - .release = ud_cls_release, - .uevent = nodemgr_uevent, + .dev_release = ud_cls_release, + .dev_uevent = nodemgr_uevent, }; static struct hpsb_highlevel nodemgr_highlevel; @@ -283,7 +282,7 @@ static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attr memcpy(buf, \ CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv), \ len); \ - while ((buf + len - 1) == '\0') \ + while (buf[len - 1] == '\0') \ len--; \ buf[len++] = '\n'; \ buf[len] = '\0'; \ @@ -730,11 +729,11 @@ static DEFINE_MUTEX(nodemgr_serialize_remove_uds); static void nodemgr_remove_uds(struct node_entry *ne) { - struct class_device *cdev; + struct device *dev; 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 + /* 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 @@ -744,9 +743,9 @@ static void nodemgr_remove_uds(struct node_entry *ne) 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); + 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; @@ -755,7 +754,7 @@ static void nodemgr_remove_uds(struct node_entry *ne) up(&nodemgr_ud_class.sem); if (ud == NULL) break; - class_device_unregister(&ud->class_dev); + device_unregister(&ud->unit_dev); device_unregister(&ud->device); } mutex_unlock(&nodemgr_serialize_remove_uds); @@ -772,10 +771,9 @@ static void nodemgr_remove_ne(struct node_entry *ne) 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(&ne->node_dev); device_unregister(dev); put_device(dev); @@ -783,7 +781,9 @@ static void nodemgr_remove_ne(struct node_entry *ne) static int __nodemgr_remove_host_dev(struct device *dev, void *data) { - nodemgr_remove_ne(container_of(dev, struct node_entry, device)); + if (dev->bus == &ieee1394_bus_type) + nodemgr_remove_ne(container_of(dev, struct node_entry, + device)); return 0; } @@ -850,14 +850,14 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr 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)); + ne->node_dev.parent = &ne->device; + ne->node_dev.class = &nodemgr_ne_class; + snprintf(ne->node_dev.bus_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)) + if (device_register(&ne->node_dev)) goto fail_classdevreg; get_device(&ne->device); @@ -885,12 +885,12 @@ fail_alloc: static struct node_entry *find_entry_by_guid(u64 guid) { - struct class_device *cdev; + struct device *dev; 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); + list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { + ne = container_of(dev, struct node_entry, node_dev); if (ne->guid == guid) { ret_ne = ne; @@ -906,12 +906,12 @@ static struct node_entry *find_entry_by_guid(u64 guid) static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host, nodeid_t nodeid) { - struct class_device *cdev; + struct device *dev; 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); + list_for_each_entry(dev, &nodemgr_ne_class.devices, node) { + ne = container_of(dev, struct node_entry, node_dev); if (ne->host == host && ne->nodeid == nodeid) { ret_ne = ne; @@ -935,14 +935,14 @@ static void nodemgr_register_device(struct node_entry *ne, 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; - snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u", + ud->unit_dev.parent = &ud->device; + ud->unit_dev.class = &nodemgr_ud_class; + snprintf(ud->unit_dev.bus_id, BUS_ID_SIZE, "%s-%u", ne->device.bus_id, ud->id); if (device_register(&ud->device)) goto fail_devreg; - if (class_device_register(&ud->class_dev)) + if (device_register(&ud->unit_dev)) goto fail_classdevreg; get_device(&ud->device); @@ -976,7 +976,8 @@ static struct unit_directory *nodemgr_process_unit_directory ud->ne = ne; ud->ignore_driver = ignore_drivers; - ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE; + ud->address = ud_kv->offset + CSR1212_REGISTER_SPACE_BASE; + ud->directory_id = ud->address & 0xffffff; ud->ud_kv = ud_kv; ud->id = (*id)++; @@ -1013,13 +1014,13 @@ static struct unit_directory *nodemgr_process_unit_directory CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { switch (last_key_id) { case CSR1212_KV_ID_VENDOR: - ud->vendor_name_kv = kv; csr1212_keep_keyval(kv); + ud->vendor_name_kv = kv; break; case CSR1212_KV_ID_MODEL: - ud->model_name_kv = kv; csr1212_keep_keyval(kv); + ud->model_name_kv = kv; break; } @@ -1085,6 +1086,10 @@ static struct unit_directory *nodemgr_process_unit_directory break; + case CSR1212_KV_ID_DIRECTORY_ID: + ud->directory_id = kv->value.immediate; + break; + default: break; } @@ -1107,7 +1112,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent { unsigned int ud_id = 0; struct csr1212_dentry *dentry; - struct csr1212_keyval *kv; + struct csr1212_keyval *kv, *vendor_name_kv = NULL; u8 last_key_id = 0; ne->needs_probe = 0; @@ -1134,8 +1139,8 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 && CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 && CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) { - ne->vendor_name_kv = kv; csr1212_keep_keyval(kv); + vendor_name_kv = kv; } } break; @@ -1144,39 +1149,37 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent } if (ne->vendor_name_kv) { - int error = device_create_file(&ne->device, - &dev_attr_ne_vendor_name_kv); - - if (error && error != -EEXIST) + kv = ne->vendor_name_kv; + ne->vendor_name_kv = vendor_name_kv; + csr1212_release_keyval(kv); + } else if (vendor_name_kv) { + ne->vendor_name_kv = vendor_name_kv; + if (device_create_file(&ne->device, + &dev_attr_ne_vendor_name_kv) != 0) HPSB_ERR("Failed to add sysfs attribute"); } } #ifdef CONFIG_HOTPLUG -static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) { struct unit_directory *ud; - int i = 0; - int length = 0; int retval = 0; /* ieee1394:venNmoNspNverN */ char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1]; - if (!cdev) + if (!dev) return -ENODEV; - ud = container_of(cdev, struct unit_directory, class_dev); + ud = container_of(dev, struct unit_directory, unit_dev); if (ud->ne->in_limbo || ud->ignore_driver) return -ENODEV; #define PUT_ENVP(fmt,val) \ do { \ - retval = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &length, \ - fmt, val); \ + retval = add_uevent_var(env, fmt, val); \ if (retval) \ return retval; \ } while (0) @@ -1195,15 +1198,12 @@ do { \ #undef PUT_ENVP - envp[i] = NULL; - return 0; } #else -static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp, - char *buffer, int buffer_size) +static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; } @@ -1373,8 +1373,10 @@ static void nodemgr_node_scan(struct host_info *hi, int generation) static void nodemgr_suspend_ne(struct node_entry *ne) { - struct class_device *cdev; + struct device *dev; struct unit_directory *ud; + struct device_driver *drv; + 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); @@ -1383,15 +1385,24 @@ static void nodemgr_suspend_ne(struct node_entry *ne) WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo)); down(&nodemgr_ud_class.sem); - list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { - ud = container_of(cdev, struct unit_directory, class_dev); + 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->device.driver && - (!ud->device.driver->suspend || - ud->device.driver->suspend(&ud->device, PMSG_SUSPEND))) + drv = get_driver(ud->device.driver); + if (!drv) + continue; + + error = 1; /* release if suspend is not implemented */ + if (drv->suspend) { + down(&ud->device.sem); + error = drv->suspend(&ud->device, PMSG_SUSPEND); + up(&ud->device.sem); + } + if (error) device_release_driver(&ud->device); + put_driver(drv); } up(&nodemgr_ud_class.sem); } @@ -1399,20 +1410,29 @@ static void nodemgr_suspend_ne(struct node_entry *ne) static void nodemgr_resume_ne(struct node_entry *ne) { - struct class_device *cdev; + struct device *dev; struct unit_directory *ud; + struct device_driver *drv; ne->in_limbo = 0; device_remove_file(&ne->device, &dev_attr_ne_in_limbo); down(&nodemgr_ud_class.sem); - list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { - ud = container_of(cdev, struct unit_directory, class_dev); + 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->device.driver && ud->device.driver->resume) - ud->device.driver->resume(&ud->device); + drv = get_driver(ud->device.driver); + if (!drv) + continue; + + if (drv->resume) { + down(&ud->device.sem); + drv->resume(&ud->device); + up(&ud->device.sem); + } + put_driver(drv); } up(&nodemgr_ud_class.sem); @@ -1423,23 +1443,32 @@ static void nodemgr_resume_ne(struct node_entry *ne) static void nodemgr_update_pdrv(struct node_entry *ne) { + struct device *dev; struct unit_directory *ud; + struct device_driver *drv; struct hpsb_protocol_driver *pdrv; - struct class_device *cdev; + int error; down(&nodemgr_ud_class.sem); - list_for_each_entry(cdev, &nodemgr_ud_class.children, node) { - ud = container_of(cdev, struct unit_directory, class_dev); + 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->device.driver) { - pdrv = container_of(ud->device.driver, - struct hpsb_protocol_driver, - driver); - if (pdrv->update && pdrv->update(ud)) - device_release_driver(&ud->device); + drv = get_driver(ud->device.driver); + if (!drv) + continue; + + error = 0; + pdrv = container_of(drv, struct hpsb_protocol_driver, driver); + if (pdrv->update) { + down(&ud->device.sem); + error = pdrv->update(ud); + up(&ud->device.sem); } + if (error) + device_release_driver(&ud->device); + put_driver(drv); } up(&nodemgr_ud_class.sem); } @@ -1504,7 +1533,7 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge static void nodemgr_node_probe(struct host_info *hi, int generation) { struct hpsb_host *host = hi->host; - struct class_device *cdev; + struct device *dev; struct node_entry *ne; /* Do some processing of the nodes we've probed. This pulls them @@ -1517,13 +1546,13 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * improvement...) */ down(&nodemgr_ne_class.sem); - list_for_each_entry(cdev, &nodemgr_ne_class.children, node) { - ne = container_of(cdev, struct node_entry, class_dev); + 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(cdev, &nodemgr_ne_class.children, node) { - ne = container_of(cdev, struct node_entry, class_dev); + 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); } @@ -1664,6 +1693,7 @@ static int nodemgr_host_thread(void *__hi) unsigned int g, generation = 0; int i, reset_cycles = 0; + set_freezable(); /* Setup our device-model entries */ nodemgr_create_host_dev_files(host); @@ -1681,18 +1711,13 @@ static int nodemgr_host_thread(void *__hi) if (kthread_should_stop()) goto exit; - if (mutex_lock_interruptible(&nodemgr_serialize)) { - if (try_to_freeze()) - continue; - goto exit; - } - /* Pause for 1/4 second in 1/16 second intervals, * to make sure things settle down. */ g = get_hpsb_generation(host); for (i = 0; i < 4 ; i++) { - if (msleep_interruptible(63) || kthread_should_stop()) - goto unlock_exit; + msleep_interruptible(63); + if (kthread_should_stop()) + goto exit; /* Now get the generation in which the node ID's we collect * are valid. During the bus scan we will use this generation @@ -1710,7 +1735,6 @@ static int nodemgr_host_thread(void *__hi) if (!nodemgr_check_irm_capability(host, reset_cycles) || !nodemgr_do_irm_duties(host, reset_cycles)) { reset_cycles++; - mutex_unlock(&nodemgr_serialize); continue; } reset_cycles = 0; @@ -1727,11 +1751,7 @@ static int nodemgr_host_thread(void *__hi) /* Update some of our sysfs symlinks */ nodemgr_update_host_dev_links(host); - - mutex_unlock(&nodemgr_serialize); } -unlock_exit: - mutex_unlock(&nodemgr_serialize); exit: HPSB_VERBOSE("NodeMgr: Exiting thread"); return 0; @@ -1751,13 +1771,13 @@ exit: */ int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *)) { - struct class_device *cdev; + struct device *dev; struct hpsb_host *host; int error = 0; down(&hpsb_host_class.sem); - list_for_each_entry(cdev, &hpsb_host_class.children, node) { - host = container_of(cdev, struct hpsb_host, class_dev); + list_for_each_entry(dev, &hpsb_host_class.devices, node) { + host = container_of(dev, struct hpsb_host, host_dev); if ((error = cb(host, data))) break;