diff options
Diffstat (limited to 'drivers/usb/storage')
-rw-r--r-- | drivers/usb/storage/Kconfig | 14 | ||||
-rw-r--r-- | drivers/usb/storage/Makefile | 9 | ||||
-rw-r--r-- | drivers/usb/storage/alauda.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/cypress_atacb.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/datafab.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/ene_ub6250.c | 30 | ||||
-rw-r--r-- | drivers/usb/storage/freecom.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/isd200.c | 5 | ||||
-rw-r--r-- | drivers/usb/storage/jumpshot.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/karma.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/libusual.c | 243 | ||||
-rw-r--r-- | drivers/usb/storage/onetouch.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/realtek_cr.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/sddr09.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/sddr55.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/shuttle_usbat.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/sierra_ms.c | 3 | ||||
-rw-r--r-- | drivers/usb/storage/transport.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/uas.c | 107 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_devs.h | 36 | ||||
-rw-r--r-- | drivers/usb/storage/usb.c | 17 | ||||
-rw-r--r-- | drivers/usb/storage/usual-tables.c | 18 |
22 files changed, 138 insertions, 368 deletions
diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7691c866637b..0ae7bb64b5ea 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -213,17 +213,3 @@ config USB_UAS say 'Y' or 'M' here and the kernel will use the right driver. If you compile this driver as a module, it will be named uas. - -config USB_LIBUSUAL - bool "The shared table of common (or usual) storage devices" - depends on USB - help - This module contains a table of common (or usual) devices - for usb-storage and ub drivers, and allows to switch binding - of these devices without rebuilding modules. - - Typical syntax of /etc/modprobe.d/*conf is: - - options libusual bias="ub" - - If unsure, say N. diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 82e6416a2d47..4cd55481b309 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -12,16 +12,9 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-y := scsiglue.o protocol.o transport.o usb.o usb-storage-y += initializers.o sierra_ms.o option_ms.o - +usb-storage-y += usual-tables.o usb-storage-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -ifeq ($(CONFIG_USB_LIBUSUAL),) - usb-storage-y += usual-tables.o -else - obj-$(CONFIG_USB) += usb-libusual.o - usb-libusual-y := libusual.o usual-tables.o -endif - obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index bab8c8fe8290..be5564cc8e01 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -137,7 +137,7 @@ static int init_alauda(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id alauda_usb_ids[] = { # include "unusual_alauda.h" diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 5fe451d16e68..070b5c0ebbf9 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -41,7 +41,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id cypress_usb_ids[] = { # include "unusual_cypress.h" diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 35e9c51e6696..494fee5af41d 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -86,7 +86,7 @@ static int datafab_determine_lun(struct us_data *us, vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id datafab_usb_ids[] = { # include "unusual_datafab.h" diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index b28f2ad127d4..118b134a1dad 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -29,9 +29,21 @@ #include "protocol.h" #include "debug.h" +#define SD_INIT1_FIRMWARE "ene-ub6250/sd_init1.bin" +#define SD_INIT2_FIRMWARE "ene-ub6250/sd_init2.bin" +#define SD_RW_FIRMWARE "ene-ub6250/sd_rdwr.bin" +#define MS_INIT_FIRMWARE "ene-ub6250/ms_init.bin" +#define MSP_RW_FIRMWARE "ene-ub6250/msp_rdwr.bin" +#define MS_RW_FIRMWARE "ene-ub6250/ms_rdwr.bin" + MODULE_DESCRIPTION("Driver for ENE UB6250 reader"); MODULE_LICENSE("GPL"); - +MODULE_FIRMWARE(SD_INIT1_FIRMWARE); +MODULE_FIRMWARE(SD_INIT2_FIRMWARE); +MODULE_FIRMWARE(SD_RW_FIRMWARE); +MODULE_FIRMWARE(MS_INIT_FIRMWARE); +MODULE_FIRMWARE(MSP_RW_FIRMWARE); +MODULE_FIRMWARE(MS_RW_FIRMWARE); /* * The table of devices @@ -40,7 +52,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags)} static struct usb_device_id ene_ub6250_usb_ids[] = { # include "unusual_ene_ub6250.h" @@ -1883,28 +1895,28 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag) /* For SD */ case SD_INIT1_PATTERN: US_DEBUGP("SD_INIT1_PATTERN\n"); - fw_name = "ene-ub6250/sd_init1.bin"; + fw_name = SD_INIT1_FIRMWARE; break; case SD_INIT2_PATTERN: US_DEBUGP("SD_INIT2_PATTERN\n"); - fw_name = "ene-ub6250/sd_init2.bin"; + fw_name = SD_INIT2_FIRMWARE; break; case SD_RW_PATTERN: - US_DEBUGP("SD_RDWR_PATTERN\n"); - fw_name = "ene-ub6250/sd_rdwr.bin"; + US_DEBUGP("SD_RW_PATTERN\n"); + fw_name = SD_RW_FIRMWARE; break; /* For MS */ case MS_INIT_PATTERN: US_DEBUGP("MS_INIT_PATTERN\n"); - fw_name = "ene-ub6250/ms_init.bin"; + fw_name = MS_INIT_FIRMWARE; break; case MSP_RW_PATTERN: US_DEBUGP("MSP_RW_PATTERN\n"); - fw_name = "ene-ub6250/msp_rdwr.bin"; + fw_name = MSP_RW_FIRMWARE; break; case MS_RW_PATTERN: US_DEBUGP("MS_RW_PATTERN\n"); - fw_name = "ene-ub6250/ms_rdwr.bin"; + fw_name = MS_RW_FIRMWARE; break; default: US_DEBUGP("----------- Unknown PATTERN ----------\n"); diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 042cf9ef3153..e6df087dca9d 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -117,7 +117,7 @@ static int init_freecom(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id freecom_usb_ids[] = { # include "unusual_freecom.h" diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 31fa24e7e68a..ecea47877364 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -74,7 +74,7 @@ static int isd200_Initialization(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id isd200_usb_ids[] = { # include "unusual_isd200.h" @@ -83,7 +83,6 @@ static struct usb_device_id isd200_usb_ids[] = { MODULE_DEVICE_TABLE(usb, isd200_usb_ids); #undef UNUSUAL_DEV -#undef USUAL_DEV /* * The flags table @@ -105,8 +104,6 @@ static struct us_unusual_dev isd200_unusual_dev_list[] = { }; #undef UNUSUAL_DEV -#undef USUAL_DEV - /* Timeout defines (in Seconds) */ diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index e3b97383186a..ddc78780b1ad 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -69,7 +69,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id jumpshot_usb_ids[] = { # include "unusual_jumpshot.h" diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index a8708eae9788..f085ffb606c8 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -57,7 +57,7 @@ static int rio_karma_init(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id karma_usb_ids[] = { # include "unusual_karma.h" diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c deleted file mode 100644 index fe3ffe1459b2..000000000000 --- a/drivers/usb/storage/libusual.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * libusual - * - * The libusual contains the table of devices common for ub and usb-storage. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/usb.h> -#include <linux/usb_usual.h> -#include <linux/vmalloc.h> -#include <linux/kthread.h> -#include <linux/mutex.h> - -/* - */ -#define USU_MOD_FL_THREAD 1 /* Thread is running */ -#define USU_MOD_FL_PRESENT 2 /* The module is loaded */ - -struct mod_status { - unsigned long fls; -}; - -static struct mod_status stat[3]; -static DEFINE_SPINLOCK(usu_lock); - -/* - */ -#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR -static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS); - -#define BIAS_NAME_SIZE (sizeof("usb-storage")) -static const char *bias_names[3] = { "none", "usb-storage", "ub" }; - -static DEFINE_MUTEX(usu_probe_mutex); -static DECLARE_COMPLETION(usu_end_notify); -static atomic_t total_threads = ATOMIC_INIT(0); - -static int usu_probe_thread(void *arg); - -/* - * @type: the module type as an integer - */ -void usb_usual_set_present(int type) -{ - struct mod_status *st; - unsigned long flags; - - if (type <= 0 || type >= 3) - return; - st = &stat[type]; - spin_lock_irqsave(&usu_lock, flags); - st->fls |= USU_MOD_FL_PRESENT; - spin_unlock_irqrestore(&usu_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_usual_set_present); - -void usb_usual_clear_present(int type) -{ - struct mod_status *st; - unsigned long flags; - - if (type <= 0 || type >= 3) - return; - st = &stat[type]; - spin_lock_irqsave(&usu_lock, flags); - st->fls &= ~USU_MOD_FL_PRESENT; - spin_unlock_irqrestore(&usu_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_usual_clear_present); - -/* - * Match the calling driver type against the table. - * Returns: 0 if the device matches. - */ -int usb_usual_check_type(const struct usb_device_id *id, int caller_type) -{ - int id_type = USB_US_TYPE(id->driver_info); - - if (caller_type <= 0 || caller_type >= 3) - return -EINVAL; - - /* Drivers grab fixed assignment devices */ - if (id_type == caller_type) - return 0; - /* Drivers grab devices biased to them */ - if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias)) - return 0; - return -ENODEV; -} -EXPORT_SYMBOL_GPL(usb_usual_check_type); - -/* - */ -static int usu_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int rc; - unsigned long type; - struct task_struct* task; - unsigned long flags; - - type = USB_US_TYPE(id->driver_info); - if (type == 0) - type = atomic_read(&usu_bias); - - spin_lock_irqsave(&usu_lock, flags); - if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { - spin_unlock_irqrestore(&usu_lock, flags); - return -ENXIO; - } - stat[type].fls |= USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - - task = kthread_run(usu_probe_thread, (void*)type, "libusual_%ld", type); - if (IS_ERR(task)) { - rc = PTR_ERR(task); - printk(KERN_WARNING "libusual: " - "Unable to start the thread for %s: %d\n", - bias_names[type], rc); - spin_lock_irqsave(&usu_lock, flags); - stat[type].fls &= ~USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - return rc; /* Not being -ENXIO causes a message printed */ - } - atomic_inc(&total_threads); - - return -ENXIO; -} - -static void usu_disconnect(struct usb_interface *intf) -{ - ; /* We should not be here. */ -} - -static struct usb_driver usu_driver = { - .name = "libusual", - .probe = usu_probe, - .disconnect = usu_disconnect, - .id_table = usb_storage_usb_ids, -}; - -/* - * A whole new thread for a purpose of request_module seems quite stupid. - * The request_module forks once inside again. However, if we attempt - * to load a storage module from our own modprobe thread, that module - * references our symbols, which cannot be resolved until our module is - * initialized. I wish there was a way to wait for the end of initialization. - * The module notifier reports MODULE_STATE_COMING only. - * So, we wait until module->init ends as the next best thing. - */ -static int usu_probe_thread(void *arg) -{ - int type = (unsigned long) arg; - struct mod_status *st = &stat[type]; - int rc; - unsigned long flags; - - mutex_lock(&usu_probe_mutex); - rc = request_module(bias_names[type]); - spin_lock_irqsave(&usu_lock, flags); - if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) { - /* - * This should not happen, but let us keep tabs on it. - */ - printk(KERN_NOTICE "libusual: " - "modprobe for %s succeeded, but module is not present\n", - bias_names[type]); - } - st->fls &= ~USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - mutex_unlock(&usu_probe_mutex); - - complete_and_exit(&usu_end_notify, 0); -} - -/* - */ -static int __init usb_usual_init(void) -{ - int rc; - - mutex_lock(&usu_probe_mutex); - rc = usb_register(&usu_driver); - mutex_unlock(&usu_probe_mutex); - return rc; -} - -static void __exit usb_usual_exit(void) -{ - /* - * We do not check for any drivers present, because - * they keep us pinned with symbol references. - */ - - usb_deregister(&usu_driver); - - while (atomic_read(&total_threads) > 0) { - wait_for_completion(&usu_end_notify); - atomic_dec(&total_threads); - } -} - -/* - * Validate and accept the bias parameter. - */ -static int usu_set_bias(const char *bias_s, struct kernel_param *kp) -{ - int i; - int len; - int bias_n = 0; - - len = strlen(bias_s); - if (len == 0) - return -EDOM; - if (bias_s[len-1] == '\n') - --len; - - for (i = 1; i < 3; i++) { - if (strncmp(bias_s, bias_names[i], len) == 0) { - bias_n = i; - break; - } - } - if (bias_n == 0) - return -EINVAL; - - atomic_set(&usu_bias, bias_n); - return 0; -} - -static int usu_get_bias(char *buffer, struct kernel_param *kp) -{ - return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)])); -} - -module_init(usb_usual_init); -module_exit(usb_usual_exit); - -module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR); -__MODULE_PARM_TYPE(bias, "string"); -MODULE_PARM_DESC(bias, "Bias to usb-storage or ub"); - -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 886567a3806d..cb79de61f4c8 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -67,7 +67,7 @@ struct usb_onetouch { vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id onetouch_usb_ids[] = { # include "unusual_onetouch.h" diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 63cf2822e299..d36446dd7ae8 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -172,7 +172,7 @@ static int init_realtek_cr(struct us_data *us); initFunction, flags) \ {\ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24)\ + .driver_info = (flags) \ } static const struct usb_device_id realtek_cr_ids[] = { diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 3252a62b31bc..7bd54e0d5120 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -69,7 +69,7 @@ static int usb_stor_sddr09_init(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id sddr09_usb_ids[] = { # include "unusual_sddr09.h" diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index c144078065a7..d278c5a99b7a 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id sddr55_usb_ids[] = { # include "unusual_sddr55.h" diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index fa1ceebc465c..daf2fc58ae02 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -168,7 +168,7 @@ static int init_usbat_flash(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id usbat_usb_ids[] = { # include "unusual_usbat.h" diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 37539c89e3ba..17e36952bced 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -130,14 +130,13 @@ int sierra_ms_init(struct us_data *us) struct swoc_info *swocInfo; struct usb_device *udev; struct Scsi_Host *sh; - struct scsi_device *sd; retries = 3; result = 0; udev = us->pusb_dev; sh = us_to_host(us); - sd = scsi_get_host_dev(sh); + scsi_get_host_dev(sh); US_DEBUGP("SWIMS: sierra_ms_init called\n"); diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c70109e5d60b..c0543c83923e 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1331,7 +1331,7 @@ int usb_stor_port_reset(struct us_data *us) int result; /*for these devices we must use the class specific method */ - if (us->pusb_dev->quirks & USB_QUIRK_RESET_MORPHS) + if (us->pusb_dev->quirks & USB_QUIRK_RESET) return -EPERM; result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 638cd64f9610..98b98eef7527 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -41,6 +41,7 @@ struct sense_iu_old { struct uas_dev_info { struct usb_interface *intf; struct usb_device *udev; + struct usb_anchor cmd_urbs; struct usb_anchor sense_urbs; struct usb_anchor data_urbs; int qdepth, resetting; @@ -49,6 +50,7 @@ struct uas_dev_info { unsigned use_streams:1; unsigned uas_sense_old:1; struct scsi_cmnd *cmnd; + spinlock_t lock; }; enum { @@ -63,13 +65,13 @@ enum { DATA_IN_URB_INFLIGHT = (1 << 9), DATA_OUT_URB_INFLIGHT = (1 << 10), COMMAND_COMPLETED = (1 << 11), + COMMAND_ABORTED = (1 << 12), }; /* Overrides scsi_pointer */ struct uas_cmd_info { unsigned int state; unsigned int stream; - unsigned int aborted; struct urb *cmd_urb; struct urb *data_in_urb; struct urb *data_out_urb; @@ -90,6 +92,7 @@ static void uas_do_work(struct work_struct *work) struct uas_cmd_info *cmdinfo; struct uas_cmd_info *temp; struct list_head list; + unsigned long flags; int err; spin_lock_irq(&uas_work_lock); @@ -100,7 +103,10 @@ static void uas_do_work(struct work_struct *work) struct scsi_pointer *scp = (void *)cmdinfo; struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); - err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; + spin_lock_irqsave(&devinfo->lock, flags); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); + spin_unlock_irqrestore(&devinfo->lock, flags); if (err) { list_del(&cmdinfo->list); spin_lock_irq(&uas_work_lock); @@ -162,7 +168,7 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) struct uas_cmd_info *ci = (void *)&cmnd->SCp; scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:" - "%s%s%s%s%s%s%s%s%s%s%s\n", + "%s%s%s%s%s%s%s%s%s%s%s%s\n", caller, cmnd, cmnd->request->tag, (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "", @@ -174,13 +180,16 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) (ci->state & COMMAND_INFLIGHT) ? " CMD" : "", (ci->state & DATA_IN_URB_INFLIGHT) ? " IN" : "", (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT" : "", - (ci->state & COMMAND_COMPLETED) ? " done" : ""); + (ci->state & COMMAND_COMPLETED) ? " done" : "", + (ci->state & COMMAND_ABORTED) ? " abort" : ""); } static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) { struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; + WARN_ON(!spin_is_locked(&devinfo->lock)); if (cmdinfo->state & (COMMAND_INFLIGHT | DATA_IN_URB_INFLIGHT | DATA_OUT_URB_INFLIGHT)) @@ -189,6 +198,10 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) cmdinfo->state |= COMMAND_COMPLETED; usb_free_urb(cmdinfo->data_in_urb); usb_free_urb(cmdinfo->data_out_urb); + if (cmdinfo->state & COMMAND_ABORTED) { + scmd_printk(KERN_INFO, cmnd, "abort completed\n"); + cmnd->result = DID_ABORT << 16; + } cmnd->scsi_done(cmnd); return 0; } @@ -216,6 +229,7 @@ static void uas_stat_cmplt(struct urb *urb) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; struct uas_cmd_info *cmdinfo; + unsigned long flags; u16 tag; if (urb->status) { @@ -229,20 +243,24 @@ static void uas_stat_cmplt(struct urb *urb) return; } + spin_lock_irqsave(&devinfo->lock, flags); tag = be16_to_cpup(&iu->tag) - 1; if (tag == 0) cmnd = devinfo->cmnd; else cmnd = scsi_host_find_tag(shost, tag - 1); + if (!cmnd) { - if (iu->iu_id != IU_ID_RESPONSE) { - usb_free_urb(urb); - return; + if (iu->iu_id == IU_ID_RESPONSE) { + /* store results for uas_eh_task_mgmt() */ + memcpy(&devinfo->response, iu, sizeof(devinfo->response)); } - } else { - cmdinfo = (void *)&cmnd->SCp; + usb_free_urb(urb); + spin_unlock_irqrestore(&devinfo->lock, flags); + return; } + cmdinfo = (void *)&cmnd->SCp; switch (iu->iu_id) { case IU_ID_STATUS: if (devinfo->cmnd == cmnd) @@ -256,10 +274,16 @@ static void uas_stat_cmplt(struct urb *urb) uas_sense(urb, cmnd); if (cmnd->result != 0) { /* cancel data transfers on error */ - if (cmdinfo->state & DATA_IN_URB_INFLIGHT) + if (cmdinfo->state & DATA_IN_URB_INFLIGHT) { + spin_unlock_irqrestore(&devinfo->lock, flags); usb_unlink_urb(cmdinfo->data_in_urb); - if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) + spin_lock_irqsave(&devinfo->lock, flags); + } + if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) { + spin_unlock_irqrestore(&devinfo->lock, flags); usb_unlink_urb(cmdinfo->data_out_urb); + spin_lock_irqsave(&devinfo->lock, flags); + } } cmdinfo->state &= ~COMMAND_INFLIGHT; uas_try_complete(cmnd, __func__); @@ -270,23 +294,23 @@ static void uas_stat_cmplt(struct urb *urb) case IU_ID_WRITE_READY: uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); break; - case IU_ID_RESPONSE: - /* store results for uas_eh_task_mgmt() */ - memcpy(&devinfo->response, iu, sizeof(devinfo->response)); - break; default: scmd_printk(KERN_ERR, cmnd, "Bogus IU (%d) received on status pipe\n", iu->iu_id); } usb_free_urb(urb); + spin_unlock_irqrestore(&devinfo->lock, flags); } static void uas_data_cmplt(struct urb *urb) { struct scsi_cmnd *cmnd = urb->context; struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; struct scsi_data_buffer *sdb = NULL; + unsigned long flags; + spin_lock_irqsave(&devinfo->lock, flags); if (cmdinfo->data_in_urb == urb) { sdb = scsi_in(cmnd); cmdinfo->state &= ~DATA_IN_URB_INFLIGHT; @@ -301,10 +325,8 @@ static void uas_data_cmplt(struct urb *urb) } else { sdb->resid = sdb->length - urb->actual_length; } - if (cmdinfo->aborted) { - return; - } uas_try_complete(cmnd, __func__); + spin_unlock_irqrestore(&devinfo->lock, flags); } static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, @@ -431,6 +453,7 @@ static int uas_submit_task_urb(struct scsi_cmnd *cmnd, gfp_t gfp, err = usb_submit_urb(urb, gfp); if (err) goto err; + usb_anchor_urb(urb, &devinfo->cmd_urbs); return 0; @@ -470,6 +493,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; int err; + WARN_ON(!spin_is_locked(&devinfo->lock)); if (cmdinfo->state & SUBMIT_STATUS_URB) { err = uas_submit_sense_urb(cmnd->device->host, gfp, cmdinfo->stream); @@ -521,18 +545,22 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_CMD_URB) { cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd, - cmdinfo->stream); + cmdinfo->stream); if (!cmdinfo->cmd_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_CMD_URB; } if (cmdinfo->state & SUBMIT_CMD_URB) { + usb_get_urb(cmdinfo->cmd_urb); if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) { scmd_printk(KERN_INFO, cmnd, "cmd urb submission failure\n"); return SCSI_MLQUEUE_DEVICE_BUSY; } + usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs); + usb_put_urb(cmdinfo->cmd_urb); + cmdinfo->cmd_urb = NULL; cmdinfo->state &= ~SUBMIT_CMD_URB; cmdinfo->state |= COMMAND_INFLIGHT; } @@ -546,12 +574,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, struct scsi_device *sdev = cmnd->device; struct uas_dev_info *devinfo = sdev->hostdata; struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + unsigned long flags; int err; BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); - if (devinfo->cmnd) + spin_lock_irqsave(&devinfo->lock, flags); + if (devinfo->cmnd) { + spin_unlock_irqrestore(&devinfo->lock, flags); return SCSI_MLQUEUE_DEVICE_BUSY; + } if (blk_rq_tagged(cmnd->request)) { cmdinfo->stream = cmnd->request->tag + 2; @@ -564,7 +596,6 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB; - cmdinfo->aborted = 0; switch (cmnd->sc_data_direction) { case DMA_FROM_DEVICE: @@ -587,6 +618,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, if (err) { /* If we did nothing, give up now */ if (cmdinfo->state & SUBMIT_STATUS_URB) { + spin_unlock_irqrestore(&devinfo->lock, flags); return SCSI_MLQUEUE_DEVICE_BUSY; } spin_lock(&uas_work_lock); @@ -595,6 +627,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, schedule_work(&uas_work); } + spin_unlock_irqrestore(&devinfo->lock, flags); return 0; } @@ -605,22 +638,28 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, { struct Scsi_Host *shost = cmnd->device->host; struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; - u16 tag = 9999; /* FIXME */ + u16 tag = devinfo->qdepth - 1; + unsigned long flags; + spin_lock_irqsave(&devinfo->lock, flags); memset(&devinfo->response, 0, sizeof(devinfo->response)); - if (uas_submit_sense_urb(shost, GFP_NOIO, tag)) { + if (uas_submit_sense_urb(shost, GFP_ATOMIC, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit sense urb failed\n", __func__, fname); + spin_unlock_irqrestore(&devinfo->lock, flags); return FAILED; } - if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) { + if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit task mgmt urb failed\n", __func__, fname); + spin_unlock_irqrestore(&devinfo->lock, flags); return FAILED; } - if (0 == usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000)) { + spin_unlock_irqrestore(&devinfo->lock, flags); + + if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) { shost_printk(KERN_INFO, shost, "%s: %s timed out\n", __func__, fname); return FAILED; @@ -643,15 +682,15 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) { struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; + unsigned long flags; int ret; uas_log_cmd_state(cmnd, __func__); - cmdinfo->aborted = 1; + spin_lock_irqsave(&devinfo->lock, flags); + cmdinfo->state |= COMMAND_ABORTED; + spin_unlock_irqrestore(&devinfo->lock, flags); ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK); - if (cmdinfo->state & DATA_IN_URB_INFLIGHT) - usb_kill_urb(cmdinfo->data_in_urb); - if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) - usb_kill_urb(cmdinfo->data_out_urb); return ret; } @@ -670,6 +709,7 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) int err; devinfo->resetting = 1; + usb_kill_anchored_urbs(&devinfo->cmd_urbs); usb_kill_anchored_urbs(&devinfo->sense_urbs); usb_kill_anchored_urbs(&devinfo->data_urbs); err = usb_reset_device(udev); @@ -694,7 +734,7 @@ static int uas_slave_configure(struct scsi_device *sdev) { struct uas_dev_info *devinfo = sdev->hostdata; scsi_set_tag_type(sdev, MSG_ORDERED_TAG); - scsi_activate_tcq(sdev, devinfo->qdepth - 2); + scsi_activate_tcq(sdev, devinfo->qdepth - 3); return 0; } @@ -868,11 +908,13 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->intf = intf; devinfo->udev = udev; devinfo->resetting = 0; + init_usb_anchor(&devinfo->cmd_urbs); init_usb_anchor(&devinfo->sense_urbs); init_usb_anchor(&devinfo->data_urbs); + spin_lock_init(&devinfo->lock); uas_configure_endpoints(devinfo); - result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 3); if (result) goto free; @@ -913,6 +955,7 @@ static void uas_disconnect(struct usb_interface *intf) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); + usb_kill_anchored_urbs(&devinfo->cmd_urbs); usb_kill_anchored_urbs(&devinfo->sense_urbs); usb_kill_anchored_urbs(&devinfo->data_urbs); uas_free_streams(devinfo); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 62a31bea0634..779cd954abcb 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2038,25 +2038,25 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Control/Bulk transport for all SubClass values */ -USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_QIC, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_UFI, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8070, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_SCSI, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_RBC, USB_PR_CB), +USUAL_DEV(USB_SC_8020, USB_PR_CB), +USUAL_DEV(USB_SC_QIC, USB_PR_CB), +USUAL_DEV(USB_SC_UFI, USB_PR_CB), +USUAL_DEV(USB_SC_8070, USB_PR_CB), +USUAL_DEV(USB_SC_SCSI, USB_PR_CB), /* Control/Bulk/Interrupt transport for all SubClass values */ -USUAL_DEV(USB_SC_RBC, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8020, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_QIC, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_UFI, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8070, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_SCSI, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_RBC, USB_PR_CBI), +USUAL_DEV(USB_SC_8020, USB_PR_CBI), +USUAL_DEV(USB_SC_QIC, USB_PR_CBI), +USUAL_DEV(USB_SC_UFI, USB_PR_CBI), +USUAL_DEV(USB_SC_8070, USB_PR_CBI), +USUAL_DEV(USB_SC_SCSI, USB_PR_CBI), /* Bulk-only transport for all SubClass values */ -USUAL_DEV(USB_SC_RBC, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8020, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_QIC, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_UFI, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8070, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0), +USUAL_DEV(USB_SC_RBC, USB_PR_BULK), +USUAL_DEV(USB_SC_8020, USB_PR_BULK), +USUAL_DEV(USB_SC_QIC, USB_PR_BULK), +USUAL_DEV(USB_SC_UFI, USB_PR_BULK), +USUAL_DEV(USB_SC_8070, USB_PR_BULK), +USUAL_DEV(USB_SC_SCSI, USB_PR_BULK), diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index d012fe4329e7..12aa72630aed 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -114,7 +114,7 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); #define COMPLIANT_DEV UNUSUAL_DEV -#define USUAL_DEV(use_protocol, use_transport, use_type) \ +#define USUAL_DEV(use_protocol, use_transport) \ { \ .useProtocol = use_protocol, \ .useTransport = use_transport, \ @@ -126,7 +126,7 @@ static struct us_unusual_dev us_unusual_dev_list[] = { }; static struct us_unusual_dev for_dynamic_ids = - USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0); + USUAL_DEV(USB_SC_SCSI, USB_PR_BULK); #undef UNUSUAL_DEV #undef COMPLIANT_DEV @@ -564,7 +564,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id, us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; - us->fflags = USB_US_ORIG_FLAGS(id->driver_info); + us->fflags = id->driver_info; adjust_quirks(us); if (us->fflags & US_FL_IGNORE_DEVICE) { @@ -1041,13 +1041,10 @@ static int storage_probe(struct usb_interface *intf, int size; /* - * If libusual is configured, let it decide whether a standard - * device should be handled by usb-storage or by ub. * If the device isn't standard (is handled by a subdriver * module) then don't accept it. */ - if (usb_usual_check_type(id, USB_US_TYPE_STOR) || - usb_usual_ignore_device(intf)) + if (usb_usual_ignore_device(intf)) return -ENXIO; /* @@ -1105,10 +1102,8 @@ static int __init usb_stor_init(void) /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); - if (retval == 0) { + if (retval == 0) pr_info("USB Mass Storage support registered.\n"); - usb_usual_set_present(USB_US_TYPE_STOR); - } return retval; } @@ -1122,8 +1117,6 @@ static void __exit usb_stor_exit(void) */ US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; - - usb_usual_clear_present(USB_US_TYPE_STOR); } module_init(usb_stor_init); diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index b96927914f89..b78a526910fb 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -34,31 +34,23 @@ vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName, useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ .driver_info = (flags) } -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = ((useType)<<24) } +#define COMPLIANT_DEV UNUSUAL_DEV + +#define USUAL_DEV(useProto, useTrans) \ +{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) } struct usb_device_id usb_storage_usb_ids[] = { # include "unusual_devs.h" { } /* Terminating entry */ }; -EXPORT_SYMBOL_GPL(usb_storage_usb_ids); - MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); #undef UNUSUAL_DEV #undef COMPLIANT_DEV #undef USUAL_DEV - /* * The table of devices to ignore */ @@ -95,7 +87,6 @@ static struct ignore_entry ignore_ids[] = { #undef UNUSUAL_DEV - /* Return an error if a device is in the ignore_ids list */ int usb_usual_ignore_device(struct usb_interface *intf) { @@ -115,4 +106,3 @@ int usb_usual_ignore_device(struct usb_interface *intf) } return 0; } -EXPORT_SYMBOL_GPL(usb_usual_ignore_device); |