diff options
author | Bjørn Mork <bjorn@mork.no> | 2012-03-06 11:29:21 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-03-08 16:06:48 -0500 |
commit | b0c13860808a528cd580fdca61aef9f73352a331 (patch) | |
tree | 8b2bc79cf10452c499741a5bb1a0a7c22ab4df94 /drivers/usb/class | |
parent | 0dffb4862a5f109dc9b72e3a4e0ecc85a87ce397 (diff) |
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: Bjørn Mork <bjorn@mork.no>
Acked-by: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/class')
-rw-r--r-- | drivers/usb/class/cdc-wdm.c | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 451793036d37..46827373ecf9 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -78,6 +78,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
78 | #define WDM_DEFAULT_BUFSIZE 256 | 78 | #define WDM_DEFAULT_BUFSIZE 256 |
79 | 79 | ||
80 | static DEFINE_MUTEX(wdm_mutex); | 80 | static DEFINE_MUTEX(wdm_mutex); |
81 | static DEFINE_SPINLOCK(wdm_device_list_lock); | ||
82 | static LIST_HEAD(wdm_device_list); | ||
81 | 83 | ||
82 | /* --- method tables --- */ | 84 | /* --- method tables --- */ |
83 | 85 | ||
@@ -112,10 +114,39 @@ struct wdm_device { | |||
112 | struct work_struct rxwork; | 114 | struct work_struct rxwork; |
113 | int werr; | 115 | int werr; |
114 | int rerr; | 116 | int rerr; |
117 | |||
118 | struct list_head device_list; | ||
115 | }; | 119 | }; |
116 | 120 | ||
117 | static struct usb_driver wdm_driver; | 121 | static struct usb_driver wdm_driver; |
118 | 122 | ||
123 | /* return intfdata if we own the interface, else look up intf in the list */ | ||
124 | static struct wdm_device *wdm_find_device(struct usb_interface *intf) | ||
125 | { | ||
126 | struct wdm_device *desc = NULL; | ||
127 | |||
128 | spin_lock(&wdm_device_list_lock); | ||
129 | list_for_each_entry(desc, &wdm_device_list, device_list) | ||
130 | if (desc->intf == intf) | ||
131 | break; | ||
132 | spin_unlock(&wdm_device_list_lock); | ||
133 | |||
134 | return desc; | ||
135 | } | ||
136 | |||
137 | static struct wdm_device *wdm_find_device_by_minor(int minor) | ||
138 | { | ||
139 | struct wdm_device *desc = NULL; | ||
140 | |||
141 | spin_lock(&wdm_device_list_lock); | ||
142 | list_for_each_entry(desc, &wdm_device_list, device_list) | ||
143 | if (desc->intf->minor == minor) | ||
144 | break; | ||
145 | spin_unlock(&wdm_device_list_lock); | ||
146 | |||
147 | return desc; | ||
148 | } | ||
149 | |||
119 | /* --- callbacks --- */ | 150 | /* --- callbacks --- */ |
120 | static void wdm_out_callback(struct urb *urb) | 151 | static void wdm_out_callback(struct urb *urb) |
121 | { | 152 | { |
@@ -275,6 +306,9 @@ static void free_urbs(struct wdm_device *desc) | |||
275 | 306 | ||
276 | static void cleanup(struct wdm_device *desc) | 307 | static void cleanup(struct wdm_device *desc) |
277 | { | 308 | { |
309 | spin_lock(&wdm_device_list_lock); | ||
310 | list_del(&desc->device_list); | ||
311 | spin_unlock(&wdm_device_list_lock); | ||
278 | kfree(desc->sbuf); | 312 | kfree(desc->sbuf); |
279 | kfree(desc->inbuf); | 313 | kfree(desc->inbuf); |
280 | kfree(desc->orq); | 314 | kfree(desc->orq); |
@@ -532,11 +566,11 @@ static int wdm_open(struct inode *inode, struct file *file) | |||
532 | struct wdm_device *desc; | 566 | struct wdm_device *desc; |
533 | 567 | ||
534 | mutex_lock(&wdm_mutex); | 568 | mutex_lock(&wdm_mutex); |
535 | intf = usb_find_interface(&wdm_driver, minor); | 569 | desc = wdm_find_device_by_minor(minor); |
536 | if (!intf) | 570 | if (!desc) |
537 | goto out; | 571 | goto out; |
538 | 572 | ||
539 | desc = usb_get_intfdata(intf); | 573 | intf = desc->intf; |
540 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) | 574 | if (test_bit(WDM_DISCONNECTING, &desc->flags)) |
541 | goto out; | 575 | goto out; |
542 | file->private_data = desc; | 576 | file->private_data = desc; |
@@ -639,6 +673,7 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor | |||
639 | desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); | 673 | desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL); |
640 | if (!desc) | 674 | if (!desc) |
641 | goto out; | 675 | goto out; |
676 | INIT_LIST_HEAD(&desc->device_list); | ||
642 | mutex_init(&desc->rlock); | 677 | mutex_init(&desc->rlock); |
643 | mutex_init(&desc->wlock); | 678 | mutex_init(&desc->wlock); |
644 | spin_lock_init(&desc->iuspin); | 679 | spin_lock_init(&desc->iuspin); |
@@ -715,16 +750,17 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor | |||
715 | desc | 750 | desc |
716 | ); | 751 | ); |
717 | 752 | ||
718 | usb_set_intfdata(intf, desc); | 753 | spin_lock(&wdm_device_list_lock); |
754 | list_add(&desc->device_list, &wdm_device_list); | ||
755 | spin_unlock(&wdm_device_list_lock); | ||
756 | |||
719 | rv = usb_register_dev(intf, &wdm_class); | 757 | rv = usb_register_dev(intf, &wdm_class); |
720 | if (rv < 0) | 758 | if (rv < 0) |
721 | goto err2; | 759 | goto err; |
722 | else | 760 | else |
723 | dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); | 761 | dev_info(&intf->dev, "%s: USB WDM device\n", dev_name(intf->usb_dev)); |
724 | out: | 762 | out: |
725 | return rv; | 763 | return rv; |
726 | err2: | ||
727 | usb_set_intfdata(intf, NULL); | ||
728 | err: | 764 | err: |
729 | cleanup(desc); | 765 | cleanup(desc); |
730 | return rv; | 766 | return rv; |
@@ -785,8 +821,8 @@ static void wdm_disconnect(struct usb_interface *intf) | |||
785 | unsigned long flags; | 821 | unsigned long flags; |
786 | 822 | ||
787 | usb_deregister_dev(intf, &wdm_class); | 823 | usb_deregister_dev(intf, &wdm_class); |
824 | desc = wdm_find_device(intf); | ||
788 | mutex_lock(&wdm_mutex); | 825 | mutex_lock(&wdm_mutex); |
789 | desc = usb_get_intfdata(intf); | ||
790 | 826 | ||
791 | /* the spinlock makes sure no new urbs are generated in the callbacks */ | 827 | /* the spinlock makes sure no new urbs are generated in the callbacks */ |
792 | spin_lock_irqsave(&desc->iuspin, flags); | 828 | spin_lock_irqsave(&desc->iuspin, flags); |
@@ -810,7 +846,7 @@ static void wdm_disconnect(struct usb_interface *intf) | |||
810 | #ifdef CONFIG_PM | 846 | #ifdef CONFIG_PM |
811 | static int wdm_suspend(struct usb_interface *intf, pm_message_t message) | 847 | static int wdm_suspend(struct usb_interface *intf, pm_message_t message) |
812 | { | 848 | { |
813 | struct wdm_device *desc = usb_get_intfdata(intf); | 849 | struct wdm_device *desc = wdm_find_device(intf); |
814 | int rv = 0; | 850 | int rv = 0; |
815 | 851 | ||
816 | dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor); | 852 | 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 | #ifdef CONFIG_PM | 896 | #ifdef CONFIG_PM |
861 | static int wdm_resume(struct usb_interface *intf) | 897 | static int wdm_resume(struct usb_interface *intf) |
862 | { | 898 | { |
863 | struct wdm_device *desc = usb_get_intfdata(intf); | 899 | struct wdm_device *desc = wdm_find_device(intf); |
864 | int rv; | 900 | int rv; |
865 | 901 | ||
866 | dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); | 902 | dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor); |
@@ -874,7 +910,7 @@ static int wdm_resume(struct usb_interface *intf) | |||
874 | 910 | ||
875 | static int wdm_pre_reset(struct usb_interface *intf) | 911 | static int wdm_pre_reset(struct usb_interface *intf) |
876 | { | 912 | { |
877 | struct wdm_device *desc = usb_get_intfdata(intf); | 913 | struct wdm_device *desc = wdm_find_device(intf); |
878 | 914 | ||
879 | /* | 915 | /* |
880 | * we notify everybody using poll of | 916 | * we notify everybody using poll of |
@@ -898,7 +934,7 @@ static int wdm_pre_reset(struct usb_interface *intf) | |||
898 | 934 | ||
899 | static int wdm_post_reset(struct usb_interface *intf) | 935 | static int wdm_post_reset(struct usb_interface *intf) |
900 | { | 936 | { |
901 | struct wdm_device *desc = usb_get_intfdata(intf); | 937 | struct wdm_device *desc = wdm_find_device(intf); |
902 | int rv; | 938 | int rv; |
903 | 939 | ||
904 | clear_bit(WDM_RESETTING, &desc->flags); | 940 | clear_bit(WDM_RESETTING, &desc->flags); |