Skip to content

Commit

Permalink
usb/uas: only bind if the hcd supports SG
Browse files Browse the repository at this point in the history
The UAS driver requires SG support by the HCD operating the device. This
patch stops UAS from operating on a HCD without sg support and prints a
message to let him know.

The spec says:
|For [USB2] backward compatibility, the device shall present [BOT] as
|alternate interface zero (primary) and [UAS] as alternate interface one
|(secondary). A device which does not need backward compatibility with
|[BOT] shall present [UAS] as alternate interface zero. In [USB2]
|systems, the [BOT] driver or an associated filter driver may need to
|issue a SET INTERFACE request for alternate interface one and then allow
|the [UAS] driver to load.

If the user used usb_modeswitch to switch to UAS then he can go back to
BOT or use a different HCD. In case UAS is the only interface then there
is currently no way out.
In future usb_sg_wait() should be extended to provide a non-blocking
interface so it can work with the UAS driver.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
  • Loading branch information
Sebastian Andrzej Siewior authored and Sarah Sharp committed Feb 2, 2012
1 parent b603669 commit c898add
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions drivers/usb/storage/uas.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/types.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/usb/storage.h>

#include <scsi/scsi.h>
Expand Down Expand Up @@ -621,22 +622,34 @@ static int uas_is_interface(struct usb_host_interface *intf)
intf->desc.bInterfaceProtocol == USB_PR_UAS);
}

static int uas_isnt_supported(struct usb_device *udev)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);

dev_warn(&udev->dev, "The driver for the USB controller %s does not "
"support scatter-gather which is\n",
hcd->driver->description);
dev_warn(&udev->dev, "required by the UAS driver. Please try an"
"alternative USB controller if you wish to use UAS.\n");
return -ENODEV;
}

static int uas_switch_interface(struct usb_device *udev,
struct usb_interface *intf)
{
int i;

if (uas_is_interface(intf->cur_altsetting))
return 0;
int sg_supported = udev->bus->sg_tablesize != 0;

for (i = 0; i < intf->num_altsetting; i++) {
struct usb_host_interface *alt = &intf->altsetting[i];
if (alt == intf->cur_altsetting)
continue;
if (uas_is_interface(alt))

if (uas_is_interface(alt)) {
if (!sg_supported)
return uas_isnt_supported(udev);
return usb_set_interface(udev,
alt->desc.bInterfaceNumber,
alt->desc.bAlternateSetting);
}
}

return -ENODEV;
Expand Down

0 comments on commit c898add

Please sign in to comment.