diff options
| -rw-r--r-- | drivers/usb/core/devio.c | 39 | ||||
| -rw-r--r-- | drivers/usb/core/inode.c | 16 | ||||
| -rw-r--r-- | drivers/usb/core/usb.h | 17 |
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 */ |
| 60 | DEFINE_MUTEX(usbfs_mutex); | 60 | DEFINE_MUTEX(usbfs_mutex); |
| 61 | 61 | ||
| 62 | struct 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 | |||
| 62 | struct async { | 78 | struct 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 | ||
| 1699 | void 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 |
| 1684 | static struct class *usb_classdev_class; | 1722 | static struct class *usb_classdev_class; |
| 1685 | 1723 | ||
| @@ -1699,6 +1737,7 @@ static int usb_classdev_add(struct usb_device *dev) | |||
| 1699 | static void usb_classdev_remove(struct usb_device *dev) | 1737 | static 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 | ||
| 1704 | static int usb_classdev_notify(struct notifier_block *self, | 1743 | static 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 | ||
| 713 | static void usbfs_remove_device(struct usb_device *dev) | 713 | static 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 | ||
| 736 | static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev) | 722 | static 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; | |||
| 142 | extern const struct file_operations usbfs_devices_fops; | 142 | extern const struct file_operations usbfs_devices_fops; |
| 143 | extern const struct file_operations usbdev_file_operations; | 143 | extern const struct file_operations usbdev_file_operations; |
| 144 | extern void usbfs_conn_disc_event(void); | 144 | extern void usbfs_conn_disc_event(void); |
| 145 | extern void usb_fs_classdev_common_remove(struct usb_device *udev); | ||
| 145 | 146 | ||
| 146 | extern int usb_devio_init(void); | 147 | extern int usb_devio_init(void); |
| 147 | extern void usb_devio_cleanup(void); | 148 | extern void usb_devio_cleanup(void); |
| 148 | 149 | ||
| 149 | struct 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 */ |
| 166 | extern void usb_notify_add_device(struct usb_device *udev); | 151 | extern void usb_notify_add_device(struct usb_device *udev); |
| 167 | extern void usb_notify_remove_device(struct usb_device *udev); | 152 | extern void usb_notify_remove_device(struct usb_device *udev); |
