diff options
-rw-r--r-- | drivers/usb/storage/uas-detect.h | 11 | ||||
-rw-r--r-- | drivers/usb/storage/uas.c | 17 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_uas.h | 52 | ||||
-rw-r--r-- | include/linux/usb_usual.h | 6 |
4 files changed, 80 insertions, 6 deletions
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h index 28101c7e6a9f..02bf5ec957f5 100644 --- a/drivers/usb/storage/uas-detect.h +++ b/drivers/usb/storage/uas-detect.h | |||
@@ -38,3 +38,14 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf) | |||
38 | 38 | ||
39 | return -ENODEV; | 39 | return -ENODEV; |
40 | } | 40 | } |
41 | |||
42 | static int uas_use_uas_driver(struct usb_interface *intf, | ||
43 | const struct usb_device_id *id) | ||
44 | { | ||
45 | unsigned long flags = id->driver_info; | ||
46 | |||
47 | if (flags & US_FL_IGNORE_UAS) | ||
48 | return 0; | ||
49 | |||
50 | return uas_find_uas_alt_setting(intf) >= 0; | ||
51 | } | ||
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 6ea892f32f74..e817e72d8673 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/usb.h> | 15 | #include <linux/usb.h> |
16 | #include <linux/usb_usual.h> | ||
16 | #include <linux/usb/hcd.h> | 17 | #include <linux/usb/hcd.h> |
17 | #include <linux/usb/storage.h> | 18 | #include <linux/usb/storage.h> |
18 | #include <linux/usb/uas.h> | 19 | #include <linux/usb/uas.h> |
@@ -866,7 +867,14 @@ static struct scsi_host_template uas_host_template = { | |||
866 | .ordered_tag = 1, | 867 | .ordered_tag = 1, |
867 | }; | 868 | }; |
868 | 869 | ||
870 | #define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ | ||
871 | vendorName, productName, useProtocol, useTransport, \ | ||
872 | initFunction, flags) \ | ||
873 | { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ | ||
874 | .driver_info = (flags) } | ||
875 | |||
869 | static struct usb_device_id uas_usb_ids[] = { | 876 | static struct usb_device_id uas_usb_ids[] = { |
877 | # include "unusual_uas.h" | ||
870 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) }, | 878 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) }, |
871 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) }, | 879 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) }, |
872 | /* 0xaa is a prototype device I happen to have access to */ | 880 | /* 0xaa is a prototype device I happen to have access to */ |
@@ -875,6 +883,8 @@ static struct usb_device_id uas_usb_ids[] = { | |||
875 | }; | 883 | }; |
876 | MODULE_DEVICE_TABLE(usb, uas_usb_ids); | 884 | MODULE_DEVICE_TABLE(usb, uas_usb_ids); |
877 | 885 | ||
886 | #undef UNUSUAL_DEV | ||
887 | |||
878 | static int uas_switch_interface(struct usb_device *udev, | 888 | static int uas_switch_interface(struct usb_device *udev, |
879 | struct usb_interface *intf) | 889 | struct usb_interface *intf) |
880 | { | 890 | { |
@@ -973,6 +983,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) | |||
973 | struct uas_dev_info *devinfo; | 983 | struct uas_dev_info *devinfo; |
974 | struct usb_device *udev = interface_to_usbdev(intf); | 984 | struct usb_device *udev = interface_to_usbdev(intf); |
975 | 985 | ||
986 | if (!uas_use_uas_driver(intf, id)) | ||
987 | return -ENODEV; | ||
988 | |||
976 | if (uas_switch_interface(udev, intf)) | 989 | if (uas_switch_interface(udev, intf)) |
977 | return -ENODEV; | 990 | return -ENODEV; |
978 | 991 | ||
@@ -1083,10 +1096,6 @@ static void uas_disconnect(struct usb_interface *intf) | |||
1083 | kfree(devinfo); | 1096 | kfree(devinfo); |
1084 | } | 1097 | } |
1085 | 1098 | ||
1086 | /* | ||
1087 | * XXX: Should this plug into libusual so we can auto-upgrade devices from | ||
1088 | * Bulk-Only to UAS? | ||
1089 | */ | ||
1090 | static struct usb_driver uas_driver = { | 1099 | static struct usb_driver uas_driver = { |
1091 | .name = "uas", | 1100 | .name = "uas", |
1092 | .probe = uas_probe, | 1101 | .probe = uas_probe, |
diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h new file mode 100644 index 000000000000..7244444df8ee --- /dev/null +++ b/drivers/usb/storage/unusual_uas.h | |||
@@ -0,0 +1,52 @@ | |||
1 | /* Driver for USB Attached SCSI devices - Unusual Devices File | ||
2 | * | ||
3 | * (c) 2013 Hans de Goede <hdegoede@redhat.com> | ||
4 | * | ||
5 | * Based on the same file for the usb-storage driver, which is: | ||
6 | * (c) 2000-2002 Matthew Dharm (mdharm-usb@one-eyed-alien.net) | ||
7 | * (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2, or (at your option) any | ||
12 | * later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * IMPORTANT NOTE: This file must be included in another file which defines | ||
26 | * a UNUSUAL_DEV macro before this file is included. | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * If you edit this file, please try to keep it sorted first by VendorID, | ||
31 | * then by ProductID. | ||
32 | * | ||
33 | * If you want to add an entry for this file, be sure to include the | ||
34 | * following information: | ||
35 | * - a patch that adds the entry for your device, including your | ||
36 | * email address right above the entry (plus maybe a brief | ||
37 | * explanation of the reason for the entry), | ||
38 | * - lsusb -v output for the device | ||
39 | * Send your submission to Hans de Goede <hdegoede@redhat.com> | ||
40 | * and don't forget to CC: the USB development list <linux-usb@vger.kernel.org> | ||
41 | */ | ||
42 | |||
43 | /* | ||
44 | * This is an example entry for the US_FL_IGNORE_UAS flag. Once we have an | ||
45 | * actual entry using US_FL_IGNORE_UAS this entry should be removed. | ||
46 | * | ||
47 | * UNUSUAL_DEV( 0xabcd, 0x1234, 0x0100, 0x0100, | ||
48 | * "Example", | ||
49 | * "Storage with broken UAS", | ||
50 | * USB_SC_DEVICE, USB_PR_DEVICE, NULL, | ||
51 | * US_FL_IGNORE_UAS), | ||
52 | */ | ||
diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index 630356866030..1a64b26046ed 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h | |||
@@ -67,8 +67,10 @@ | |||
67 | /* Initial READ(10) (and others) must be retried */ \ | 67 | /* Initial READ(10) (and others) must be retried */ \ |
68 | US_FLAG(WRITE_CACHE, 0x00200000) \ | 68 | US_FLAG(WRITE_CACHE, 0x00200000) \ |
69 | /* Write Cache status is not available */ \ | 69 | /* Write Cache status is not available */ \ |
70 | US_FLAG(NEEDS_CAP16, 0x00400000) | 70 | US_FLAG(NEEDS_CAP16, 0x00400000) \ |
71 | /* cannot handle READ_CAPACITY_10 */ | 71 | /* cannot handle READ_CAPACITY_10 */ \ |
72 | US_FLAG(IGNORE_UAS, 0x00800000) \ | ||
73 | /* Device advertises UAS but it is broken */ | ||
72 | 74 | ||
73 | #define US_FLAG(name, value) US_FL_##name = value , | 75 | #define US_FLAG(name, value) US_FL_##name = value , |
74 | enum { US_DO_ALL_FLAGS }; | 76 | enum { US_DO_ALL_FLAGS }; |