aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/devio.c39
-rw-r--r--drivers/usb/core/inode.c16
-rw-r--r--drivers/usb/core/usb.h17
3 files changed, 41 insertions, 31 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index e09935acae80..bbd029f68faa 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -59,6 +59,22 @@
59/* Mutual exclusion for removal, open, and release */ 59/* Mutual exclusion for removal, open, and release */
60DEFINE_MUTEX(usbfs_mutex); 60DEFINE_MUTEX(usbfs_mutex);
61 61
62struct dev_state {
63 struct list_head list; /* state list */
64 struct usb_device *dev;
65 struct file *file;
66 spinlock_t lock; /* protects the async urb lists */
67 struct list_head async_pending;
68 struct list_head async_completed;
69 wait_queue_head_t wait; /* wake up if a request completed */
70 unsigned int discsignr;
71 struct pid *disc_pid;
72 uid_t disc_uid, disc_euid;
73 void __user *disccontext;
74 unsigned long ifclaimed;
75 u32 secid;
76};
77
62struct async { 78struct async {
63 struct list_head asynclist; 79 struct list_head asynclist;
64 struct dev_state *ps; 80 struct dev_state *ps;
@@ -1680,6 +1696,28 @@ const struct file_operations usbdev_file_operations = {
1680 .release = usbdev_release, 1696 .release = usbdev_release,
1681}; 1697};
1682 1698
1699void usb_fs_classdev_common_remove(struct usb_device *udev)
1700{
1701 struct dev_state *ps;
1702 struct siginfo sinfo;
1703
1704 while (!list_empty(&udev->filelist)) {
1705 ps = list_entry(udev->filelist.next, struct dev_state, list);
1706 destroy_all_async(ps);
1707 wake_up_all(&ps->wait);
1708 list_del_init(&ps->list);
1709 if (ps->discsignr) {
1710 sinfo.si_signo = ps->discsignr;
1711 sinfo.si_errno = EPIPE;
1712 sinfo.si_code = SI_ASYNCIO;
1713 sinfo.si_addr = ps->disccontext;
1714 kill_pid_info_as_uid(ps->discsignr, &sinfo,
1715 ps->disc_pid, ps->disc_uid,
1716 ps->disc_euid, ps->secid);
1717 }
1718 }
1719}
1720
1683#ifdef CONFIG_USB_DEVICE_CLASS 1721#ifdef CONFIG_USB_DEVICE_CLASS
1684static struct class *usb_classdev_class; 1722static struct class *usb_classdev_class;
1685 1723
@@ -1699,6 +1737,7 @@ static int usb_classdev_add(struct usb_device *dev)
1699static void usb_classdev_remove(struct usb_device *dev) 1737static void usb_classdev_remove(struct usb_device *dev)
1700{ 1738{
1701 device_unregister(dev->usb_classdev); 1739 device_unregister(dev->usb_classdev);
1740 usb_fs_classdev_common_remove(dev);
1702} 1741}
1703 1742
1704static int usb_classdev_notify(struct notifier_block *self, 1743static int usb_classdev_notify(struct notifier_block *self,
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index 1d253dd4ea81..db410e92c80d 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -712,25 +712,11 @@ static void usbfs_add_device(struct usb_device *dev)
712 712
713static void usbfs_remove_device(struct usb_device *dev) 713static void usbfs_remove_device(struct usb_device *dev)
714{ 714{
715 struct dev_state *ds;
716 struct siginfo sinfo;
717
718 if (dev->usbfs_dentry) { 715 if (dev->usbfs_dentry) {
719 fs_remove_file (dev->usbfs_dentry); 716 fs_remove_file (dev->usbfs_dentry);
720 dev->usbfs_dentry = NULL; 717 dev->usbfs_dentry = NULL;
721 } 718 }
722 while (!list_empty(&dev->filelist)) { 719 usb_fs_classdev_common_remove(dev);
723 ds = list_entry(dev->filelist.next, struct dev_state, list);
724 wake_up_all(&ds->wait);
725 list_del_init(&ds->list);
726 if (ds->discsignr) {
727 sinfo.si_signo = ds->discsignr;
728 sinfo.si_errno = EPIPE;
729 sinfo.si_code = SI_ASYNCIO;
730 sinfo.si_addr = ds->disccontext;
731 kill_pid_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid, ds->secid);
732 }
733 }
734} 720}
735 721
736static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) 722static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index d3eb0a29bca1..d9a6e16dbf84 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -142,26 +142,11 @@ extern struct usb_driver usbfs_driver;
142extern const struct file_operations usbfs_devices_fops; 142extern const struct file_operations usbfs_devices_fops;
143extern const struct file_operations usbdev_file_operations; 143extern const struct file_operations usbdev_file_operations;
144extern void usbfs_conn_disc_event(void); 144extern void usbfs_conn_disc_event(void);
145extern void usb_fs_classdev_common_remove(struct usb_device *udev);
145 146
146extern int usb_devio_init(void); 147extern int usb_devio_init(void);
147extern void usb_devio_cleanup(void); 148extern void usb_devio_cleanup(void);
148 149
149struct dev_state {
150 struct list_head list; /* state list */
151 struct usb_device *dev;
152 struct file *file;
153 spinlock_t lock; /* protects the async urb lists */
154 struct list_head async_pending;
155 struct list_head async_completed;
156 wait_queue_head_t wait; /* wake up if a request completed */
157 unsigned int discsignr;
158 struct pid *disc_pid;
159 uid_t disc_uid, disc_euid;
160 void __user *disccontext;
161 unsigned long ifclaimed;
162 u32 secid;
163};
164
165/* internal notify stuff */ 150/* internal notify stuff */
166extern void usb_notify_add_device(struct usb_device *udev); 151extern void usb_notify_add_device(struct usb_device *udev);
167extern void usb_notify_remove_device(struct usb_device *udev); 152extern void usb_notify_remove_device(struct usb_device *udev);