Patch "USB: usbfs: allow URBs to be reaped after disconnection" has been added to the 3.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
USB: usbfs: allow URBs to be reaped after disconnection
to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
usb-usbfs-allow-urbs-to-be-reaped-after-disconnection.patch
and it can be found in the queue-3.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
3f2cee73b650921b2e214bf487b2061a1c266504Mon Sep 17 00:00:00 2001
From: Alan Stern <[email protected]>
Date: Thu, 29 Jan 2015 11:29:13 -0500
Subject: USB: usbfs: allow URBs to be reaped after disconnection
From: Alan Stern <[email protected]>
commit 3f2cee73b650921b2e214bf487b2061a1c266504 upstream.
The usbfs API has a peculiar hole: Users are not allowed to reap their URBs after the device has been disconnected. There doesn't seem to be any good reason for this; it is an ad-hoc inconsistency.
The patch allows users to issue the USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY ioctls (together with their 32-bit counterparts on 64-bit systems) even after the device is gone. If no URBs are pending for a disconnected device then the ioctls will return -ENODEV rather than -EAGAIN, because obviously no new URBs will ever be able to complete.
The patch also adds a new capability flag for USBDEVFS_GET_CAPABILITIES to indicate that the reap-after-disconnect feature is supported.
--- drivers/usb/core/devio.c | 63 ++++++++++++++++++++++---------------- include/uapi/linux/usbdevice_fs.h | 3 + 2 files changed, 39 insertions(+), 27 deletions(-)
drivers/usb/core/devio.c +37 -26
@@ -1593,7 +1593,7 @@ static struct async *reap_as(struct dev_for (;;) {__set_current_state (TASK_INTERRUPTIBLE ); as =async_getcompleted (ps); -if (as) +if (as || !connected (ps))break ;if (signal_pending (current))break ;
@@ -1616,7 +1616,7 @@ static int proc_reapurb(struct dev_state }if (signal_pending (current))return -EINTR ; -return -EIO ; +return -ENODEV ; }static int proc_reapurbnonblock (struct dev_state *ps,void __user *arg)
@@ -1625,10 +1625,11 @@ static int proc_reapurbnonblock(struct dstruct async *as; as =async_getcompleted (ps); - retval = -EAGAIN ;if (as) { retval =processcompl (as, (void __user *__user *)arg);free_async (as); + }else { + retval = (connected (ps) ? -EAGAIN : -ENODEV ); }return retval; }
@@ -1758,7 +1759,7 @@ static int proc_reapurb_compat(struct de }if (signal_pending (current))return -EINTR ; -return -EIO ; +return -ENODEV ; }static int proc_reapurbnonblock_compat (struct dev_state *ps,void __user *arg)
@@ -1766,11 +1767,12 @@ static int proc_reapurbnonblock_compat(sint retval;struct async *as; - retval = -EAGAIN ; as =async_getcompleted (ps);if (as) { retval =processcompl_compat (as, (void __user *__user *)arg);free_async (as); + }else { + retval = (connected (ps) ? -EAGAIN : -ENODEV ); }return retval; }
@@ -1941,7 +1943,8 @@ static int proc_get_capabilities(struct {__u32 caps; - caps =USBDEVFS_CAP_ZERO_PACKET |USBDEVFS_CAP_NO_PACKET_SIZE_LIM ; + caps =USBDEVFS_CAP_ZERO_PACKET |USBDEVFS_CAP_NO_PACKET_SIZE_LIM | +USBDEVFS_CAP_REAP_AFTER_DISCONNECT ;if (!ps->dev->bus->no_stop_on_short) caps |=USBDEVFS_CAP_BULK_CONTINUATION ;if (ps->dev->bus->sg_tablesize)
@@ -2002,6 +2005,32 @@ static long usbdev_do_ioctl(struct filereturn -EPERM ;usb_lock_device (dev); + +/* Reap operations are allowed even after disconnection */ +switch (cmd) { +case USBDEVFS_REAPURB : +snoop (&dev->dev,"%s: REAPURB\n" , __func__); + ret =proc_reapurb (ps, p); + goto done; + +case USBDEVFS_REAPURBNDELAY : +snoop (&dev->dev,"%s: REAPURBNDELAY\n" , __func__); + ret =proc_reapurbnonblock (ps, p); + goto done; + +#ifdef CONFIG_COMPAT +case USBDEVFS_REAPURB32 : +snoop (&dev->dev,"%s: REAPURB32\n" , __func__); + ret =proc_reapurb_compat (ps, p); + goto done; + +case USBDEVFS_REAPURBNDELAY32 : +snoop (&dev->dev,"%s: REAPURBNDELAY32\n" , __func__); + ret =proc_reapurbnonblock_compat (ps, p); + goto done; +#endif + } +if (!connected (ps)) {usb_unlock_device (dev);return -ENODEV ;
@@ -2095,16 +2124,6 @@ static long usbdev_do_ioctl(struct file inode->i_mtime =CURRENT_TIME ;break ; -case USBDEVFS_REAPURB32 : -snoop (&dev->dev,"%s: REAPURB32\n" , __func__); - ret =proc_reapurb_compat (ps, p); -break ; - -case USBDEVFS_REAPURBNDELAY32 : -snoop (&dev->dev,"%s: REAPURBNDELAY32\n" , __func__); - ret =proc_reapurbnonblock_compat (ps, p); -break ; -case USBDEVFS_IOCTL32 :snoop (&dev->dev,"%s: IOCTL32\n" , __func__); ret =proc_ioctl_compat (ps,ptr_to_compat (p));
@@ -2116,16 +2135,6 @@ static long usbdev_do_ioctl(struct file ret =proc_unlinkurb (ps, p);break ; -case USBDEVFS_REAPURB : -snoop (&dev->dev,"%s: REAPURB\n" , __func__); - ret =proc_reapurb (ps, p); -break ; - -case USBDEVFS_REAPURBNDELAY : -snoop (&dev->dev,"%s: REAPURBNDELAY\n" , __func__); - ret =proc_reapurbnonblock (ps, p); -break ; -case USBDEVFS_DISCSIGNAL :snoop (&dev->dev,"%s: DISCSIGNAL\n" , __func__); ret =proc_disconnectsignal (ps, p);
@@ -2162,6 +2171,8 @@ static long usbdev_do_ioctl(struct file ret =proc_disconnect_claim (ps, p);break ; } + + done:usb_unlock_device (dev);if (ret >=0 ) inode->i_atime =CURRENT_TIME ;
include/uapi/linux/usbdevice_fs.h +2 -1
@@ -125,11 +125,12 @@ struct usbdevfs_hub_portinfo {char port [127 ];/* e.g. port 3 connects to device 27 */ }; -/* Device capability flags */ +/* System and bus capability flags */ #define USBDEVFS_CAP_ZERO_PACKET 0x01#define USBDEVFS_CAP_BULK_CONTINUATION 0x02#define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04#define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08 +#define USBDEVFS_CAP_REAP_AFTER_DISCONNECT 0x10/* USBDEVFS_DISCONNECT_CLAIM flags & struct */
Patches currently in stable-queue which might be from [email protected] are
queue-3.10/usb-usbfs-allow-urbs-to-be-reaped-after-disconnection.patch queue-3.10/usb-devio-fix-a-condition-in-async_completed.patch