Register all interfaces handled by this driver in a list, getting rid of the dependency on usb_set_intfdata. This allows further generalization and simplification of the probe/create functions. This is needed to decouple wdm_open from the driver owning the interface, and it also allows us to share all the code in wdm_create with drivers unable to do usb_set_intfdata. Signed-off-by: Bjørn Mork <bjorn@xxxxxxx> --- drivers/usb/class/cdc-wdm.c | 56 +++++++++++++++++++++++++++++++++--------- 1 files changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 89c2c46..c86f8e5 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -77,6 +77,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_DEFAULT_BUFSIZE 256 static DEFINE_MUTEX(wdm_mutex); +static LIST_HEAD(wdm_device_list); /* --- method tables --- */ @@ -111,10 +112,38 @@ struct wdm_device { struct work_struct rxwork; int werr; int rerr; + + struct list_head device_list; }; static struct usb_driver wdm_driver; +/* return intfdata if we own the interface, else look up intf in the list */ +static struct wdm_device *wdm_find_device(struct usb_interface *intf) +{ + struct wdm_device *desc = NULL; + + mutex_lock(&wdm_mutex); + list_for_each_entry(desc, &wdm_device_list, device_list) + if (desc->intf == intf) + break; + mutex_unlock(&wdm_mutex); + + return desc; +} + +/* caller holds wdm_mutex */ +static struct wdm_device *wdm_find_device_by_minor(int minor) +{ + struct wdm_device *desc = NULL; + + list_for_each_entry(desc, &wdm_device_list, device_list) + if (desc->intf->minor == minor) + break; + + return desc; +} + /* --- callbacks --- */ static void wdm_out_callback(struct urb *urb) { @@ -274,6 +303,7 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { + list_del(&desc->device_list); kfree(desc->sbuf); kfree(desc->inbuf); kfree(desc->orq); @@ -518,11 +548,11 @@ static int wdm_open(struct inode *inode, struct file *file) struct wdm_device *desc; mutex_lock(&wdm_mutex); - intf = usb_find_interface(&wdm_driver, minor); - if (!intf) + desc = wdm_find_device_by_minor(minor); + if (!desc) goto out; - desc = usb_get_intfdata(intf); + intf = desc->intf; if (test_bit(WDM_DISCONNECTING, &desc->flags)) goto out; file->private_data = desc; @@ -625,6 +655,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); if (!desc) goto out; + INIT_LIST_HEAD(&desc->device_list); mutex_init(&desc->rlock); mutex_init(&desc->wlock); spin_lock_init(&desc->iuspin); @@ -701,16 +732,17 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor desc ); - usb_set_intfdata(intf, desc); + mutex_lock(&wdm_mutex); + list_add(&desc->device_list, &wdm_device_list); + mutex_unlock(&wdm_mutex); + rv = usb_register_dev(intf, &wdm_class); if (rv < 0) - goto err2; + goto err; else dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); out: return rv; -err2: - usb_set_intfdata(intf, NULL); err: cleanup(desc); return rv; @@ -771,8 +803,8 @@ static void wdm_disconnect(struct usb_interface *intf) unsigned long flags; usb_deregister_dev(intf, &wdm_class); + desc = wdm_find_device(intf); mutex_lock(&wdm_mutex); - desc = usb_get_intfdata(intf); /* the spinlock makes sure no new urbs are generated in the callbacks */ spin_lock_irqsave(&desc->iuspin, flags); @@ -796,7 +828,7 @@ static void wdm_disconnect(struct usb_interface *intf) #ifdef CONFIG_PM static int wdm_suspend(struct usb_interface *intf, pm_message_t message) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); int rv = 0; dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); @@ -846,7 +878,7 @@ static int recover_from_urb_loss(struct wdm_device *desc) #ifdef CONFIG_PM static int wdm_resume(struct usb_interface *intf) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); int rv; dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); @@ -860,7 +892,7 @@ static int wdm_resume(struct usb_interface *intf) static int wdm_pre_reset(struct usb_interface *intf) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); mutex_lock(&desc->rlock); mutex_lock(&desc->wlock); @@ -881,7 +913,7 @@ static int wdm_pre_reset(struct usb_interface *intf) static int wdm_post_reset(struct usb_interface *intf) { - struct wdm_device *desc = usb_get_intfdata(intf); + struct wdm_device *desc = wdm_find_device(intf); int rv; rv = recover_from_urb_loss(desc); -- 1.7.8.3 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html