diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2009-01-13 11:33:42 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@kvm.kroah.org> | 2009-01-27 19:15:32 -0500 |
commit | 501950d846218ed80a776d2aae5aed9c8b92e778 (patch) | |
tree | ace5472aed14811e8914b7d22b1c4dba27d296f8 | |
parent | a15d95a003fae154121733f049dd25e9c13dbef3 (diff) |
USB: fix char-device disconnect handling
This patch (as1198) fixes a conceptual bug: Somewhere along the line
we managed to confuse USB class devices with USB char devices. As a
result, the code to send a disconnect signal to userspace would not be
built if both CONFIG_USB_DEVICE_CLASS and CONFIG_USB_DEVICEFS were
disabled.
The usb_fs_classdev_common_remove() routine has been renamed to
usbdev_remove() and it is now called whenever any USB device is
removed, not just when a class device is unregistered. The notifier
registration and unregistration calls are no longer conditionally
compiled. And since the common removal code will always be called as
part of the char device interface, there's no need to call it again as
part of the usbfs interface; thus the invocation of
usb_fs_classdev_common_remove() has been taken out of
usbfs_remove_device().
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Alon Bar-Lev <alon.barlev@gmail.com>
Tested-by: Alon Bar-Lev <alon.barlev@gmail.com>
Cc: stable <stable@kernel.org>
-rw-r--r-- | drivers/usb/core/devio.c | 20 | ||||
-rw-r--r-- | drivers/usb/core/inode.c | 1 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 |
3 files changed, 12 insertions, 10 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 26fece124e0e..7513bb083c15 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -1700,7 +1700,7 @@ const struct file_operations usbdev_file_operations = { | |||
1700 | .release = usbdev_release, | 1700 | .release = usbdev_release, |
1701 | }; | 1701 | }; |
1702 | 1702 | ||
1703 | void usb_fs_classdev_common_remove(struct usb_device *udev) | 1703 | static void usbdev_remove(struct usb_device *udev) |
1704 | { | 1704 | { |
1705 | struct dev_state *ps; | 1705 | struct dev_state *ps; |
1706 | struct siginfo sinfo; | 1706 | struct siginfo sinfo; |
@@ -1742,10 +1742,15 @@ static void usb_classdev_remove(struct usb_device *dev) | |||
1742 | { | 1742 | { |
1743 | if (dev->usb_classdev) | 1743 | if (dev->usb_classdev) |
1744 | device_unregister(dev->usb_classdev); | 1744 | device_unregister(dev->usb_classdev); |
1745 | usb_fs_classdev_common_remove(dev); | ||
1746 | } | 1745 | } |
1747 | 1746 | ||
1748 | static int usb_classdev_notify(struct notifier_block *self, | 1747 | #else |
1748 | #define usb_classdev_add(dev) 0 | ||
1749 | #define usb_classdev_remove(dev) do {} while (0) | ||
1750 | |||
1751 | #endif | ||
1752 | |||
1753 | static int usbdev_notify(struct notifier_block *self, | ||
1749 | unsigned long action, void *dev) | 1754 | unsigned long action, void *dev) |
1750 | { | 1755 | { |
1751 | switch (action) { | 1756 | switch (action) { |
@@ -1755,15 +1760,15 @@ static int usb_classdev_notify(struct notifier_block *self, | |||
1755 | break; | 1760 | break; |
1756 | case USB_DEVICE_REMOVE: | 1761 | case USB_DEVICE_REMOVE: |
1757 | usb_classdev_remove(dev); | 1762 | usb_classdev_remove(dev); |
1763 | usbdev_remove(dev); | ||
1758 | break; | 1764 | break; |
1759 | } | 1765 | } |
1760 | return NOTIFY_OK; | 1766 | return NOTIFY_OK; |
1761 | } | 1767 | } |
1762 | 1768 | ||
1763 | static struct notifier_block usbdev_nb = { | 1769 | static struct notifier_block usbdev_nb = { |
1764 | .notifier_call = usb_classdev_notify, | 1770 | .notifier_call = usbdev_notify, |
1765 | }; | 1771 | }; |
1766 | #endif | ||
1767 | 1772 | ||
1768 | static struct cdev usb_device_cdev; | 1773 | static struct cdev usb_device_cdev; |
1769 | 1774 | ||
@@ -1798,9 +1803,8 @@ int __init usb_devio_init(void) | |||
1798 | * to /sys/dev | 1803 | * to /sys/dev |
1799 | */ | 1804 | */ |
1800 | usb_classdev_class->dev_kobj = NULL; | 1805 | usb_classdev_class->dev_kobj = NULL; |
1801 | |||
1802 | usb_register_notify(&usbdev_nb); | ||
1803 | #endif | 1806 | #endif |
1807 | usb_register_notify(&usbdev_nb); | ||
1804 | out: | 1808 | out: |
1805 | return retval; | 1809 | return retval; |
1806 | 1810 | ||
@@ -1811,8 +1815,8 @@ error_cdev: | |||
1811 | 1815 | ||
1812 | void usb_devio_cleanup(void) | 1816 | void usb_devio_cleanup(void) |
1813 | { | 1817 | { |
1814 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
1815 | usb_unregister_notify(&usbdev_nb); | 1818 | usb_unregister_notify(&usbdev_nb); |
1819 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
1816 | class_destroy(usb_classdev_class); | 1820 | class_destroy(usb_classdev_class); |
1817 | #endif | 1821 | #endif |
1818 | cdev_del(&usb_device_cdev); | 1822 | cdev_del(&usb_device_cdev); |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 2a129cb7bb56..dff5760a37f6 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
@@ -717,7 +717,6 @@ static void usbfs_remove_device(struct usb_device *dev) | |||
717 | fs_remove_file (dev->usbfs_dentry); | 717 | fs_remove_file (dev->usbfs_dentry); |
718 | dev->usbfs_dentry = NULL; | 718 | dev->usbfs_dentry = NULL; |
719 | } | 719 | } |
720 | usb_fs_classdev_common_remove(dev); | ||
721 | } | 720 | } |
722 | 721 | ||
723 | 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 9d0f33fe8719..79d8a9ea559b 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -152,7 +152,6 @@ extern struct usb_driver usbfs_driver; | |||
152 | extern const struct file_operations usbfs_devices_fops; | 152 | extern const struct file_operations usbfs_devices_fops; |
153 | extern const struct file_operations usbdev_file_operations; | 153 | extern const struct file_operations usbdev_file_operations; |
154 | extern void usbfs_conn_disc_event(void); | 154 | extern void usbfs_conn_disc_event(void); |
155 | extern void usb_fs_classdev_common_remove(struct usb_device *udev); | ||
156 | 155 | ||
157 | extern int usb_devio_init(void); | 156 | extern int usb_devio_init(void); |
158 | extern void usb_devio_cleanup(void); | 157 | extern void usb_devio_cleanup(void); |