static int node_probe(struct device *dev) { struct unit_directory *ud = container_of(dev, struct unit_directory, device); struct firedtv *fdtv; int kv_len, err; void *kv_str; if (ud->model_name_kv) { kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4; kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); } else { kv_len = 0; kv_str = NULL; } fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len); if (!fdtv) return -ENOMEM; /* * Work around a bug in udev's path_id script: Use the fw-host's dev * instead of the unit directory's dev as parent of the input device. */ err = fdtv_register_rc(fdtv, dev->parent->parent); if (err) goto fail_free; spin_lock_irq(&node_list_lock); list_add_tail(&fdtv->list, &node_list); spin_unlock_irq(&node_list_lock); err = avc_identify_subunit(fdtv); if (err) goto fail; err = fdtv_dvb_register(fdtv); if (err) goto fail; avc_register_remote_control(fdtv); return 0; fail: spin_lock_irq(&node_list_lock); list_del(&fdtv->list); spin_unlock_irq(&node_list_lock); fdtv_unregister_rc(fdtv); fail_free: kfree(fdtv); return err; }
static int node_remove(struct device *dev) { struct firedtv *fdtv = dev_get_drvdata(dev); fdtv_dvb_unregister(fdtv); spin_lock_irq(&node_list_lock); list_del(&fdtv->list); spin_unlock_irq(&node_list_lock); fdtv_unregister_rc(fdtv); kfree(fdtv); return 0; }
static int node_remove(struct device *dev) { struct firedtv *fdtv = dev->driver_data; fdtv_dvb_unregister(fdtv); spin_lock_irq(&node_list_lock); list_del(&fdtv->list); spin_unlock_irq(&node_list_lock); cancel_work_sync(&fdtv->remote_ctrl_work); fdtv_unregister_rc(fdtv); kfree(fdtv); return 0; }