/* Mutual exclusion for removal, open, and release */
DEFINE_MUTEX(usbfs_mutex);
+struct dev_state {
+ struct list_head list; /* state list */
+ struct usb_device *dev;
+ struct file *file;
+ spinlock_t lock; /* protects the async urb lists */
+ struct list_head async_pending;
+ struct list_head async_completed;
+ wait_queue_head_t wait; /* wake up if a request completed */
+ unsigned int discsignr;
+ struct pid *disc_pid;
+ uid_t disc_uid, disc_euid;
+ void __user *disccontext;
+ unsigned long ifclaimed;
+ u32 secid;
+};
+
struct async {
struct list_head asynclist;
struct dev_state *ps;
.release = usbdev_release,
};
+void usb_fs_classdev_common_remove(struct usb_device *udev)
+{
+ struct dev_state *ps;
+ struct siginfo sinfo;
+
+ while (!list_empty(&udev->filelist)) {
+ ps = list_entry(udev->filelist.next, struct dev_state, list);
+ destroy_all_async(ps);
+ wake_up_all(&ps->wait);
+ list_del_init(&ps->list);
+ if (ps->discsignr) {
+ sinfo.si_signo = ps->discsignr;
+ sinfo.si_errno = EPIPE;
+ sinfo.si_code = SI_ASYNCIO;
+ sinfo.si_addr = ps->disccontext;
+ kill_pid_info_as_uid(ps->discsignr, &sinfo,
+ ps->disc_pid, ps->disc_uid,
+ ps->disc_euid, ps->secid);
+ }
+ }
+}
+
#ifdef CONFIG_USB_DEVICE_CLASS
static struct class *usb_classdev_class;
static void usb_classdev_remove(struct usb_device *dev)
{
device_unregister(dev->usb_classdev);
+ usb_fs_classdev_common_remove(dev);
}
static int usb_classdev_notify(struct notifier_block *self,
static void usbfs_remove_device(struct usb_device *dev)
{
- struct dev_state *ds;
- struct siginfo sinfo;
-
if (dev->usbfs_dentry) {
fs_remove_file (dev->usbfs_dentry);
dev->usbfs_dentry = NULL;
}
- while (!list_empty(&dev->filelist)) {
- ds = list_entry(dev->filelist.next, struct dev_state, list);
- wake_up_all(&ds->wait);
- list_del_init(&ds->list);
- if (ds->discsignr) {
- sinfo.si_signo = ds->discsignr;
- sinfo.si_errno = EPIPE;
- sinfo.si_code = SI_ASYNCIO;
- sinfo.si_addr = ds->disccontext;
- kill_pid_info_as_uid(ds->discsignr, &sinfo, ds->disc_pid, ds->disc_uid, ds->disc_euid, ds->secid);
- }
- }
+ usb_fs_classdev_common_remove(dev);
}
static int usbfs_notify(struct notifier_block *self, unsigned long action, void *dev)
extern const struct file_operations usbfs_devices_fops;
extern const struct file_operations usbdev_file_operations;
extern void usbfs_conn_disc_event(void);
+extern void usb_fs_classdev_common_remove(struct usb_device *udev);
extern int usb_devio_init(void);
extern void usb_devio_cleanup(void);
-struct dev_state {
- struct list_head list; /* state list */
- struct usb_device *dev;
- struct file *file;
- spinlock_t lock; /* protects the async urb lists */
- struct list_head async_pending;
- struct list_head async_completed;
- wait_queue_head_t wait; /* wake up if a request completed */
- unsigned int discsignr;
- struct pid *disc_pid;
- uid_t disc_uid, disc_euid;
- void __user *disccontext;
- unsigned long ifclaimed;
- u32 secid;
-};
-
/* internal notify stuff */
extern void usb_notify_add_device(struct usb_device *udev);
extern void usb_notify_remove_device(struct usb_device *udev);