aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-07-04 03:18:02 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-06 13:53:19 -0400
commit19181bc50e1b8e92a7a3b3d78637c6dc5c0b5a1b (patch)
tree347b45182dd50d1237f24579628232ca3a04de97 /drivers/usb
parent2102e06a5f2e414694921f23591f072a5ba7db9f (diff)
usbdevfs: Add a USBDEVFS_GET_CAPABILITIES ioctl
There are a few (new) usbdevfs capabilities which an application cannot discover in any other way then checking the kernel version. There are 3 problems with this: 1) It is just not very pretty. 2) Given the tendency of enterprise distros to backport stuff it is not reliable. 3) As discussed in length on the mailinglist, USBDEVFS_URB_BULK_CONTINUATION does not work as it should when combined with USBDEVFS_URB_SHORT_NOT_OK (which is its intended use) on devices attached to an XHCI controller. So the availability of these features can be host controller dependent, making depending on them based on the kernel version not a good idea. This patch besides adding the new ioctl also adds flags for the following existing capabilities: USBDEVFS_CAP_ZERO_PACKET, available since 2.6.31 USBDEVFS_CAP_BULK_CONTINUATION, available since 2.6.32, except for XHCI USBDEVFS_CAP_NO_PACKET_SIZE_LIM, available since 3.3 Note that this patch only does not advertise the USBDEVFS_URB_BULK_CONTINUATION cap for XHCI controllers, bulk transfers with this flag set will still be accepted when submitted to XHCI controllers. Returning -EINVAL for them would break existing apps, and in most cases the troublesome scenario wrt USBDEVFS_URB_SHORT_NOT_OK urbs on XHCI controllers will never get hit, so this would break working use cases. The disadvantage of not returning -EINVAL is that cases were it is causing real trouble may go undetected / the cause of the trouble may be unclear, but this is the best we can do. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/core/devio.c17
-rw-r--r--drivers/usb/host/xhci.c2
2 files changed, 19 insertions, 0 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 62679bc031fb..0b387c1a8b7e 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1824,6 +1824,20 @@ static int proc_release_port(struct dev_state *ps, void __user *arg)
1824 return usb_hub_release_port(ps->dev, portnum, ps); 1824 return usb_hub_release_port(ps->dev, portnum, ps);
1825} 1825}
1826 1826
1827static int proc_get_capabilities(struct dev_state *ps, void __user *arg)
1828{
1829 __u32 caps;
1830
1831 caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM;
1832 if (!ps->dev->bus->no_stop_on_short)
1833 caps |= USBDEVFS_CAP_BULK_CONTINUATION;
1834
1835 if (put_user(caps, (__u32 __user *)arg))
1836 return -EFAULT;
1837
1838 return 0;
1839}
1840
1827/* 1841/*
1828 * NOTE: All requests here that have interface numbers as parameters 1842 * NOTE: All requests here that have interface numbers as parameters
1829 * are assuming that somehow the configuration has been prevented from 1843 * are assuming that somehow the configuration has been prevented from
@@ -1994,6 +2008,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd,
1994 snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__); 2008 snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__);
1995 ret = proc_release_port(ps, p); 2009 ret = proc_release_port(ps, p);
1996 break; 2010 break;
2011 case USBDEVFS_GET_CAPABILITIES:
2012 ret = proc_get_capabilities(ps, p);
2013 break;
1997 } 2014 }
1998 usb_unlock_device(dev); 2015 usb_unlock_device(dev);
1999 if (ret >= 0) 2016 if (ret >= 0)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index a979cd0dbe0f..7648b2d4b268 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4450,6 +4450,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
4450 4450
4451 /* Accept arbitrarily long scatter-gather lists */ 4451 /* Accept arbitrarily long scatter-gather lists */
4452 hcd->self.sg_tablesize = ~0; 4452 hcd->self.sg_tablesize = ~0;
4453 /* XHCI controllers don't stop the ep queue on short packets :| */
4454 hcd->self.no_stop_on_short = 1;
4453 4455
4454 if (usb_hcd_is_primary_hcd(hcd)) { 4456 if (usb_hcd_is_primary_hcd(hcd)) {
4455 xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL); 4457 xhci = kzalloc(sizeof(struct xhci_hcd), GFP_KERNEL);