Commit b0c13860 authored by Bjørn Mork's avatar Bjørn Mork Committed by Greg Kroah-Hartman

usb: cdc-wdm: adding list lookup indirection

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: default avatarBjørn Mork <bjorn@mork.no>
Acked-by: default avatarOliver Neukum <oneukum@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0dffb486
...@@ -78,6 +78,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); ...@@ -78,6 +78,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_DEFAULT_BUFSIZE 256 #define WDM_DEFAULT_BUFSIZE 256
static DEFINE_MUTEX(wdm_mutex); static DEFINE_MUTEX(wdm_mutex);
static DEFINE_SPINLOCK(wdm_device_list_lock);
static LIST_HEAD(wdm_device_list);
/* --- method tables --- */ /* --- method tables --- */
...@@ -112,10 +114,39 @@ struct wdm_device { ...@@ -112,10 +114,39 @@ struct wdm_device {
struct work_struct rxwork; struct work_struct rxwork;
int werr; int werr;
int rerr; int rerr;
struct list_head device_list;
}; };
static struct usb_driver wdm_driver; 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;
spin_lock(&wdm_device_list_lock);
list_for_each_entry(desc, &wdm_device_list, device_list)
if (desc->intf == intf)
break;
spin_unlock(&wdm_device_list_lock);
return desc;
}
static struct wdm_device *wdm_find_device_by_minor(int minor)
{
struct wdm_device *desc = NULL;
spin_lock(&wdm_device_list_lock);
list_for_each_entry(desc, &wdm_device_list, device_list)
if (desc->intf->minor == minor)
break;
spin_unlock(&wdm_device_list_lock);
return desc;
}
/* --- callbacks --- */ /* --- callbacks --- */
static void wdm_out_callback(struct urb *urb) static void wdm_out_callback(struct urb *urb)
{ {
...@@ -275,6 +306,9 @@ static void free_urbs(struct wdm_device *desc) ...@@ -275,6 +306,9 @@ static void free_urbs(struct wdm_device *desc)
static void cleanup(struct wdm_device *desc) static void cleanup(struct wdm_device *desc)
{ {
spin_lock(&wdm_device_list_lock);
list_del(&desc->device_list);
spin_unlock(&wdm_device_list_lock);
kfree(desc->sbuf); kfree(desc->sbuf);
kfree(desc->inbuf); kfree(desc->inbuf);
kfree(desc->orq); kfree(desc->orq);
...@@ -532,11 +566,11 @@ static int wdm_open(struct inode *inode, struct file *file) ...@@ -532,11 +566,11 @@ static int wdm_open(struct inode *inode, struct file *file)
struct wdm_device *desc; struct wdm_device *desc;
mutex_lock(&wdm_mutex); mutex_lock(&wdm_mutex);
intf = usb_find_interface(&wdm_driver, minor); desc = wdm_find_device_by_minor(minor);
if (!intf) if (!desc)
goto out; goto out;
desc = usb_get_intfdata(intf); intf = desc->intf;
if (test_bit(WDM_DISCONNECTING, &desc->flags)) if (test_bit(WDM_DISCONNECTING, &desc->flags))
goto out; goto out;
file->private_data = desc; file->private_data = desc;
...@@ -639,6 +673,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor ...@@ -639,6 +673,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc) if (!desc)
goto out; goto out;
INIT_LIST_HEAD(&desc->device_list);
mutex_init(&desc->rlock); mutex_init(&desc->rlock);
mutex_init(&desc->wlock); mutex_init(&desc->wlock);
spin_lock_init(&desc->iuspin); spin_lock_init(&desc->iuspin);
...@@ -715,16 +750,17 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor ...@@ -715,16 +750,17 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
desc desc
); );
usb_set_intfdata(intf, desc); spin_lock(&wdm_device_list_lock);
list_add(&desc->device_list, &wdm_device_list);
spin_unlock(&wdm_device_list_lock);
rv = usb_register_dev(intf, &wdm_class); rv = usb_register_dev(intf, &wdm_class);
if (rv < 0) if (rv < 0)
goto err2; goto err;
else else
dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev));
out: out:
return rv; return rv;
err2:
usb_set_intfdata(intf, NULL);
err: err:
cleanup(desc); cleanup(desc);
return rv; return rv;
...@@ -785,8 +821,8 @@ static void wdm_disconnect(struct usb_interface *intf) ...@@ -785,8 +821,8 @@ static void wdm_disconnect(struct usb_interface *intf)
unsigned long flags; unsigned long flags;
usb_deregister_dev(intf, &wdm_class); usb_deregister_dev(intf, &wdm_class);
desc = wdm_find_device(intf);
mutex_lock(&wdm_mutex); mutex_lock(&wdm_mutex);
desc = usb_get_intfdata(intf);
/* the spinlock makes sure no new urbs are generated in the callbacks */ /* the spinlock makes sure no new urbs are generated in the callbacks */
spin_lock_irqsave(&desc->iuspin, flags); spin_lock_irqsave(&desc->iuspin, flags);
...@@ -810,7 +846,7 @@ static void wdm_disconnect(struct usb_interface *intf) ...@@ -810,7 +846,7 @@ static void wdm_disconnect(struct usb_interface *intf)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int wdm_suspend(struct usb_interface *intf, pm_message_t message) 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; int rv = 0;
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
...@@ -860,7 +896,7 @@ static int recover_from_urb_loss(struct wdm_device *desc) ...@@ -860,7 +896,7 @@ static int recover_from_urb_loss(struct wdm_device *desc)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int wdm_resume(struct usb_interface *intf) 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; int rv;
dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
...@@ -874,7 +910,7 @@ static int wdm_resume(struct usb_interface *intf) ...@@ -874,7 +910,7 @@ static int wdm_resume(struct usb_interface *intf)
static int wdm_pre_reset(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);
/* /*
* we notify everybody using poll of * we notify everybody using poll of
...@@ -898,7 +934,7 @@ static int wdm_pre_reset(struct usb_interface *intf) ...@@ -898,7 +934,7 @@ static int wdm_pre_reset(struct usb_interface *intf)
static int wdm_post_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; int rv;
clear_bit(WDM_RESETTING, &desc->flags); clear_bit(WDM_RESETTING, &desc->flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment