162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Driver for USB Mass Storage compliant devices 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Current development and maintenance by: 662306a36Sopenharmony_ci * (c) 1999-2003 Matthew Dharm (mdharm-usb@one-eyed-alien.net) 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Developed with the assistance of: 962306a36Sopenharmony_ci * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) 1062306a36Sopenharmony_ci * (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu) 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Initial work by: 1362306a36Sopenharmony_ci * (c) 1999 Michael Gee (michael@linuxspecific.com) 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * usb_device_id support by Adam J. Richter (adam@yggdrasil.com): 1662306a36Sopenharmony_ci * (c) 2000 Yggdrasil Computing, Inc. 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * This driver is based on the 'USB Mass Storage Class' document. This 1962306a36Sopenharmony_ci * describes in detail the protocol used to communicate with such 2062306a36Sopenharmony_ci * devices. Clearly, the designers had SCSI and ATAPI commands in 2162306a36Sopenharmony_ci * mind when they created this document. The commands are all very 2262306a36Sopenharmony_ci * similar to commands in the SCSI-II and ATAPI specifications. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * It is important to note that in a number of cases this class 2562306a36Sopenharmony_ci * exhibits class-specific exemptions from the USB specification. 2662306a36Sopenharmony_ci * Notably the usage of NAK, STALL and ACK differs from the norm, in 2762306a36Sopenharmony_ci * that they are used to communicate wait, failed and OK on commands. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * Also, for certain devices, the interrupt endpoint is used to convey 3062306a36Sopenharmony_ci * status of a command. 3162306a36Sopenharmony_ci */ 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#ifdef CONFIG_USB_STORAGE_DEBUG 3462306a36Sopenharmony_ci#define DEBUG 3562306a36Sopenharmony_ci#endif 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include <linux/sched.h> 3862306a36Sopenharmony_ci#include <linux/errno.h> 3962306a36Sopenharmony_ci#include <linux/module.h> 4062306a36Sopenharmony_ci#include <linux/slab.h> 4162306a36Sopenharmony_ci#include <linux/kthread.h> 4262306a36Sopenharmony_ci#include <linux/mutex.h> 4362306a36Sopenharmony_ci#include <linux/utsname.h> 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include <scsi/scsi.h> 4662306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 4762306a36Sopenharmony_ci#include <scsi/scsi_device.h> 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#include "usb.h" 5062306a36Sopenharmony_ci#include "scsiglue.h" 5162306a36Sopenharmony_ci#include "transport.h" 5262306a36Sopenharmony_ci#include "protocol.h" 5362306a36Sopenharmony_ci#include "debug.h" 5462306a36Sopenharmony_ci#include "initializers.h" 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci#include "sierra_ms.h" 5762306a36Sopenharmony_ci#include "option_ms.h" 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_UAS) 6062306a36Sopenharmony_ci#include "uas-detect.h" 6162306a36Sopenharmony_ci#endif 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define DRV_NAME "usb-storage" 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* Some informational data */ 6662306a36Sopenharmony_ciMODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>"); 6762306a36Sopenharmony_ciMODULE_DESCRIPTION("USB Mass Storage driver for Linux"); 6862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic unsigned int delay_use = 1; 7162306a36Sopenharmony_cimodule_param(delay_use, uint, S_IRUGO | S_IWUSR); 7262306a36Sopenharmony_ciMODULE_PARM_DESC(delay_use, "seconds to delay before using a new device"); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic char quirks[128]; 7562306a36Sopenharmony_cimodule_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR); 7662306a36Sopenharmony_ciMODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci/* 8062306a36Sopenharmony_ci * The entries in this table correspond, line for line, 8162306a36Sopenharmony_ci * with the entries in usb_storage_usb_ids[], defined in usual-tables.c. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* 8562306a36Sopenharmony_ci *The vendor name should be kept at eight characters or less, and 8662306a36Sopenharmony_ci * the product name should be kept at 16 characters or less. If a device 8762306a36Sopenharmony_ci * has the US_FL_FIX_INQUIRY flag, then the vendor and product names 8862306a36Sopenharmony_ci * normally generated by a device through the INQUIRY response will be 8962306a36Sopenharmony_ci * taken from this list, and this is the reason for the above size 9062306a36Sopenharmony_ci * restriction. However, if the flag is not present, then you 9162306a36Sopenharmony_ci * are free to use as many characters as you like. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ 9562306a36Sopenharmony_ci vendor_name, product_name, use_protocol, use_transport, \ 9662306a36Sopenharmony_ci init_function, Flags) \ 9762306a36Sopenharmony_ci{ \ 9862306a36Sopenharmony_ci .vendorName = vendor_name, \ 9962306a36Sopenharmony_ci .productName = product_name, \ 10062306a36Sopenharmony_ci .useProtocol = use_protocol, \ 10162306a36Sopenharmony_ci .useTransport = use_transport, \ 10262306a36Sopenharmony_ci .initFunction = init_function, \ 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci#define COMPLIANT_DEV UNUSUAL_DEV 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#define USUAL_DEV(use_protocol, use_transport) \ 10862306a36Sopenharmony_ci{ \ 10962306a36Sopenharmony_ci .useProtocol = use_protocol, \ 11062306a36Sopenharmony_ci .useTransport = use_transport, \ 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \ 11462306a36Sopenharmony_ci vendor_name, product_name, use_protocol, use_transport, \ 11562306a36Sopenharmony_ci init_function, Flags) \ 11662306a36Sopenharmony_ci{ \ 11762306a36Sopenharmony_ci .vendorName = vendor_name, \ 11862306a36Sopenharmony_ci .productName = product_name, \ 11962306a36Sopenharmony_ci .useProtocol = use_protocol, \ 12062306a36Sopenharmony_ci .useTransport = use_transport, \ 12162306a36Sopenharmony_ci .initFunction = init_function, \ 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic const struct us_unusual_dev us_unusual_dev_list[] = { 12562306a36Sopenharmony_ci# include "unusual_devs.h" 12662306a36Sopenharmony_ci { } /* Terminating entry */ 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic const struct us_unusual_dev for_dynamic_ids = 13062306a36Sopenharmony_ci USUAL_DEV(USB_SC_SCSI, USB_PR_BULK); 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#undef UNUSUAL_DEV 13362306a36Sopenharmony_ci#undef COMPLIANT_DEV 13462306a36Sopenharmony_ci#undef USUAL_DEV 13562306a36Sopenharmony_ci#undef UNUSUAL_VENDOR_INTF 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#ifdef CONFIG_LOCKDEP 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic struct lock_class_key us_interface_key[USB_MAXINTERFACES]; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic void us_set_lock_class(struct mutex *mutex, 14262306a36Sopenharmony_ci struct usb_interface *intf) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(intf); 14562306a36Sopenharmony_ci struct usb_host_config *config = udev->actconfig; 14662306a36Sopenharmony_ci int i; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci for (i = 0; i < config->desc.bNumInterfaces; i++) { 14962306a36Sopenharmony_ci if (config->interface[i] == intf) 15062306a36Sopenharmony_ci break; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci BUG_ON(i == config->desc.bNumInterfaces); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci lockdep_set_class(mutex, &us_interface_key[i]); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#else 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic void us_set_lock_class(struct mutex *mutex, 16162306a36Sopenharmony_ci struct usb_interface *intf) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci#endif 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#ifdef CONFIG_PM /* Minimal support for suspend and resume */ 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ciint usb_stor_suspend(struct usb_interface *iface, pm_message_t message) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* Wait until no command is running */ 17462306a36Sopenharmony_ci mutex_lock(&us->dev_mutex); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci if (us->suspend_resume_hook) 17762306a36Sopenharmony_ci (us->suspend_resume_hook)(us, US_SUSPEND); 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci /* 18062306a36Sopenharmony_ci * When runtime PM is working, we'll set a flag to indicate 18162306a36Sopenharmony_ci * whether we should autoresume when a SCSI request arrives. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci mutex_unlock(&us->dev_mutex); 18562306a36Sopenharmony_ci return 0; 18662306a36Sopenharmony_ci} 18762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_suspend); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciint usb_stor_resume(struct usb_interface *iface) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci mutex_lock(&us->dev_mutex); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (us->suspend_resume_hook) 19662306a36Sopenharmony_ci (us->suspend_resume_hook)(us, US_RESUME); 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci mutex_unlock(&us->dev_mutex); 19962306a36Sopenharmony_ci return 0; 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_resume); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciint usb_stor_reset_resume(struct usb_interface *iface) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* Report the reset to the SCSI core */ 20862306a36Sopenharmony_ci usb_stor_report_bus_reset(us); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* 21162306a36Sopenharmony_ci * If any of the subdrivers implemented a reinitialization scheme, 21262306a36Sopenharmony_ci * this is where the callback would be invoked. 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_ci return 0; 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_reset_resume); 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci#endif /* CONFIG_PM */ 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/* 22162306a36Sopenharmony_ci * The next two routines get called just before and just after 22262306a36Sopenharmony_ci * a USB port reset, whether from this driver or a different one. 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ciint usb_stor_pre_reset(struct usb_interface *iface) 22662306a36Sopenharmony_ci{ 22762306a36Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Make sure no command runs during the reset */ 23062306a36Sopenharmony_ci mutex_lock(&us->dev_mutex); 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_pre_reset); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ciint usb_stor_post_reset(struct usb_interface *iface) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci struct us_data *us = usb_get_intfdata(iface); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci /* Report the reset to the SCSI core */ 24062306a36Sopenharmony_ci usb_stor_report_bus_reset(us); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* 24362306a36Sopenharmony_ci * If any of the subdrivers implemented a reinitialization scheme, 24462306a36Sopenharmony_ci * this is where the callback would be invoked. 24562306a36Sopenharmony_ci */ 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci mutex_unlock(&us->dev_mutex); 24862306a36Sopenharmony_ci return 0; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_post_reset); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/* 25362306a36Sopenharmony_ci * fill_inquiry_response takes an unsigned char array (which must 25462306a36Sopenharmony_ci * be at least 36 characters) and populates the vendor name, 25562306a36Sopenharmony_ci * product name, and revision fields. Then the array is copied 25662306a36Sopenharmony_ci * into the SCSI command's response buffer (oddly enough 25762306a36Sopenharmony_ci * called request_buffer). data_len contains the length of the 25862306a36Sopenharmony_ci * data array, which again must be at least 36. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_civoid fill_inquiry_response(struct us_data *us, unsigned char *data, 26262306a36Sopenharmony_ci unsigned int data_len) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci if (data_len < 36) /* You lose. */ 26562306a36Sopenharmony_ci return; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci memset(data+8, ' ', 28); 26862306a36Sopenharmony_ci if (data[0]&0x20) { /* 26962306a36Sopenharmony_ci * USB device currently not connected. Return 27062306a36Sopenharmony_ci * peripheral qualifier 001b ("...however, the 27162306a36Sopenharmony_ci * physical device is not currently connected 27262306a36Sopenharmony_ci * to this logical unit") and leave vendor and 27362306a36Sopenharmony_ci * product identification empty. ("If the target 27462306a36Sopenharmony_ci * does store some of the INQUIRY data on the 27562306a36Sopenharmony_ci * device, it may return zeros or ASCII spaces 27662306a36Sopenharmony_ci * (20h) in those fields until the data is 27762306a36Sopenharmony_ci * available from the device."). 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci } else { 28062306a36Sopenharmony_ci u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice); 28162306a36Sopenharmony_ci int n; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci n = strlen(us->unusual_dev->vendorName); 28462306a36Sopenharmony_ci memcpy(data+8, us->unusual_dev->vendorName, min(8, n)); 28562306a36Sopenharmony_ci n = strlen(us->unusual_dev->productName); 28662306a36Sopenharmony_ci memcpy(data+16, us->unusual_dev->productName, min(16, n)); 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci data[32] = 0x30 + ((bcdDevice>>12) & 0x0F); 28962306a36Sopenharmony_ci data[33] = 0x30 + ((bcdDevice>>8) & 0x0F); 29062306a36Sopenharmony_ci data[34] = 0x30 + ((bcdDevice>>4) & 0x0F); 29162306a36Sopenharmony_ci data[35] = 0x30 + ((bcdDevice) & 0x0F); 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci usb_stor_set_xfer_buf(data, data_len, us->srb); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(fill_inquiry_response); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cistatic int usb_stor_control_thread(void * __us) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct us_data *us = (struct us_data *)__us; 30162306a36Sopenharmony_ci struct Scsi_Host *host = us_to_host(us); 30262306a36Sopenharmony_ci struct scsi_cmnd *srb; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci for (;;) { 30562306a36Sopenharmony_ci usb_stor_dbg(us, "*** thread sleeping\n"); 30662306a36Sopenharmony_ci if (wait_for_completion_interruptible(&us->cmnd_ready)) 30762306a36Sopenharmony_ci break; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci usb_stor_dbg(us, "*** thread awakened\n"); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* lock the device pointers */ 31262306a36Sopenharmony_ci mutex_lock(&(us->dev_mutex)); 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* lock access to the state */ 31562306a36Sopenharmony_ci scsi_lock(host); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* When we are called with no command pending, we're done */ 31862306a36Sopenharmony_ci srb = us->srb; 31962306a36Sopenharmony_ci if (srb == NULL) { 32062306a36Sopenharmony_ci scsi_unlock(host); 32162306a36Sopenharmony_ci mutex_unlock(&us->dev_mutex); 32262306a36Sopenharmony_ci usb_stor_dbg(us, "-- exiting\n"); 32362306a36Sopenharmony_ci break; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci /* has the command timed out *already* ? */ 32762306a36Sopenharmony_ci if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { 32862306a36Sopenharmony_ci srb->result = DID_ABORT << 16; 32962306a36Sopenharmony_ci goto SkipForAbort; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci scsi_unlock(host); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci /* 33562306a36Sopenharmony_ci * reject the command if the direction indicator 33662306a36Sopenharmony_ci * is UNKNOWN 33762306a36Sopenharmony_ci */ 33862306a36Sopenharmony_ci if (srb->sc_data_direction == DMA_BIDIRECTIONAL) { 33962306a36Sopenharmony_ci usb_stor_dbg(us, "UNKNOWN data direction\n"); 34062306a36Sopenharmony_ci srb->result = DID_ERROR << 16; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci /* 34462306a36Sopenharmony_ci * reject if target != 0 or if LUN is higher than 34562306a36Sopenharmony_ci * the maximum known LUN 34662306a36Sopenharmony_ci */ 34762306a36Sopenharmony_ci else if (srb->device->id && 34862306a36Sopenharmony_ci !(us->fflags & US_FL_SCM_MULT_TARG)) { 34962306a36Sopenharmony_ci usb_stor_dbg(us, "Bad target number (%d:%llu)\n", 35062306a36Sopenharmony_ci srb->device->id, 35162306a36Sopenharmony_ci srb->device->lun); 35262306a36Sopenharmony_ci srb->result = DID_BAD_TARGET << 16; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci else if (srb->device->lun > us->max_lun) { 35662306a36Sopenharmony_ci usb_stor_dbg(us, "Bad LUN (%d:%llu)\n", 35762306a36Sopenharmony_ci srb->device->id, 35862306a36Sopenharmony_ci srb->device->lun); 35962306a36Sopenharmony_ci srb->result = DID_BAD_TARGET << 16; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci /* 36362306a36Sopenharmony_ci * Handle those devices which need us to fake 36462306a36Sopenharmony_ci * their inquiry data 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_ci else if ((srb->cmnd[0] == INQUIRY) && 36762306a36Sopenharmony_ci (us->fflags & US_FL_FIX_INQUIRY)) { 36862306a36Sopenharmony_ci unsigned char data_ptr[36] = { 36962306a36Sopenharmony_ci 0x00, 0x80, 0x02, 0x02, 37062306a36Sopenharmony_ci 0x1F, 0x00, 0x00, 0x00}; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci usb_stor_dbg(us, "Faking INQUIRY command\n"); 37362306a36Sopenharmony_ci fill_inquiry_response(us, data_ptr, 36); 37462306a36Sopenharmony_ci srb->result = SAM_STAT_GOOD; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* we've got a command, let's do it! */ 37862306a36Sopenharmony_ci else { 37962306a36Sopenharmony_ci US_DEBUG(usb_stor_show_command(us, srb)); 38062306a36Sopenharmony_ci us->proto_handler(srb, us); 38162306a36Sopenharmony_ci usb_mark_last_busy(us->pusb_dev); 38262306a36Sopenharmony_ci } 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci /* lock access to the state */ 38562306a36Sopenharmony_ci scsi_lock(host); 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* was the command aborted? */ 38862306a36Sopenharmony_ci if (srb->result == DID_ABORT << 16) { 38962306a36Sopenharmony_ciSkipForAbort: 39062306a36Sopenharmony_ci usb_stor_dbg(us, "scsi command aborted\n"); 39162306a36Sopenharmony_ci srb = NULL; /* Don't call scsi_done() */ 39262306a36Sopenharmony_ci } 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* 39562306a36Sopenharmony_ci * If an abort request was received we need to signal that 39662306a36Sopenharmony_ci * the abort has finished. The proper test for this is 39762306a36Sopenharmony_ci * the TIMED_OUT flag, not srb->result == DID_ABORT, because 39862306a36Sopenharmony_ci * the timeout might have occurred after the command had 39962306a36Sopenharmony_ci * already completed with a different result code. 40062306a36Sopenharmony_ci */ 40162306a36Sopenharmony_ci if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) { 40262306a36Sopenharmony_ci complete(&(us->notify)); 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* Allow USB transfers to resume */ 40562306a36Sopenharmony_ci clear_bit(US_FLIDX_ABORTING, &us->dflags); 40662306a36Sopenharmony_ci clear_bit(US_FLIDX_TIMED_OUT, &us->dflags); 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci /* finished working on this command */ 41062306a36Sopenharmony_ci us->srb = NULL; 41162306a36Sopenharmony_ci scsi_unlock(host); 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci /* unlock the device pointers */ 41462306a36Sopenharmony_ci mutex_unlock(&us->dev_mutex); 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci /* now that the locks are released, notify the SCSI core */ 41762306a36Sopenharmony_ci if (srb) { 41862306a36Sopenharmony_ci usb_stor_dbg(us, "scsi cmd done, result=0x%x\n", 41962306a36Sopenharmony_ci srb->result); 42062306a36Sopenharmony_ci scsi_done_direct(srb); 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci } /* for (;;) */ 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* Wait until we are told to stop */ 42562306a36Sopenharmony_ci for (;;) { 42662306a36Sopenharmony_ci set_current_state(TASK_INTERRUPTIBLE); 42762306a36Sopenharmony_ci if (kthread_should_stop()) 42862306a36Sopenharmony_ci break; 42962306a36Sopenharmony_ci schedule(); 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci __set_current_state(TASK_RUNNING); 43262306a36Sopenharmony_ci return 0; 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci/*********************************************************************** 43662306a36Sopenharmony_ci * Device probing and disconnecting 43762306a36Sopenharmony_ci ***********************************************************************/ 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/* Associate our private data with the USB device */ 44062306a36Sopenharmony_cistatic int associate_dev(struct us_data *us, struct usb_interface *intf) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci /* Fill in the device-related fields */ 44362306a36Sopenharmony_ci us->pusb_dev = interface_to_usbdev(intf); 44462306a36Sopenharmony_ci us->pusb_intf = intf; 44562306a36Sopenharmony_ci us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 44662306a36Sopenharmony_ci usb_stor_dbg(us, "Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n", 44762306a36Sopenharmony_ci le16_to_cpu(us->pusb_dev->descriptor.idVendor), 44862306a36Sopenharmony_ci le16_to_cpu(us->pusb_dev->descriptor.idProduct), 44962306a36Sopenharmony_ci le16_to_cpu(us->pusb_dev->descriptor.bcdDevice)); 45062306a36Sopenharmony_ci usb_stor_dbg(us, "Interface Subclass: 0x%02x, Protocol: 0x%02x\n", 45162306a36Sopenharmony_ci intf->cur_altsetting->desc.bInterfaceSubClass, 45262306a36Sopenharmony_ci intf->cur_altsetting->desc.bInterfaceProtocol); 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci /* Store our private data in the interface */ 45562306a36Sopenharmony_ci usb_set_intfdata(intf, us); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci /* Allocate the control/setup and DMA-mapped buffers */ 45862306a36Sopenharmony_ci us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL); 45962306a36Sopenharmony_ci if (!us->cr) 46062306a36Sopenharmony_ci return -ENOMEM; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE, 46362306a36Sopenharmony_ci GFP_KERNEL, &us->iobuf_dma); 46462306a36Sopenharmony_ci if (!us->iobuf) { 46562306a36Sopenharmony_ci usb_stor_dbg(us, "I/O buffer allocation failed\n"); 46662306a36Sopenharmony_ci return -ENOMEM; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci return 0; 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci/* Works only for digits and letters, but small and fast */ 47262306a36Sopenharmony_ci#define TOLOWER(x) ((x) | 0x20) 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci/* Adjust device flags based on the "quirks=" module parameter */ 47562306a36Sopenharmony_civoid usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci char *p; 47862306a36Sopenharmony_ci u16 vid = le16_to_cpu(udev->descriptor.idVendor); 47962306a36Sopenharmony_ci u16 pid = le16_to_cpu(udev->descriptor.idProduct); 48062306a36Sopenharmony_ci unsigned f = 0; 48162306a36Sopenharmony_ci unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE | 48262306a36Sopenharmony_ci US_FL_FIX_CAPACITY | US_FL_IGNORE_UAS | 48362306a36Sopenharmony_ci US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE | 48462306a36Sopenharmony_ci US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 | 48562306a36Sopenharmony_ci US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE | 48662306a36Sopenharmony_ci US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT | 48762306a36Sopenharmony_ci US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 | 48862306a36Sopenharmony_ci US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE | 48962306a36Sopenharmony_ci US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES | 49062306a36Sopenharmony_ci US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS | 49162306a36Sopenharmony_ci US_FL_ALWAYS_SYNC); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci p = quirks; 49462306a36Sopenharmony_ci while (*p) { 49562306a36Sopenharmony_ci /* Each entry consists of VID:PID:flags */ 49662306a36Sopenharmony_ci if (vid == simple_strtoul(p, &p, 16) && 49762306a36Sopenharmony_ci *p == ':' && 49862306a36Sopenharmony_ci pid == simple_strtoul(p+1, &p, 16) && 49962306a36Sopenharmony_ci *p == ':') 50062306a36Sopenharmony_ci break; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* Move forward to the next entry */ 50362306a36Sopenharmony_ci while (*p) { 50462306a36Sopenharmony_ci if (*p++ == ',') 50562306a36Sopenharmony_ci break; 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci if (!*p) /* No match */ 50962306a36Sopenharmony_ci return; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci /* Collect the flags */ 51262306a36Sopenharmony_ci while (*++p && *p != ',') { 51362306a36Sopenharmony_ci switch (TOLOWER(*p)) { 51462306a36Sopenharmony_ci case 'a': 51562306a36Sopenharmony_ci f |= US_FL_SANE_SENSE; 51662306a36Sopenharmony_ci break; 51762306a36Sopenharmony_ci case 'b': 51862306a36Sopenharmony_ci f |= US_FL_BAD_SENSE; 51962306a36Sopenharmony_ci break; 52062306a36Sopenharmony_ci case 'c': 52162306a36Sopenharmony_ci f |= US_FL_FIX_CAPACITY; 52262306a36Sopenharmony_ci break; 52362306a36Sopenharmony_ci case 'd': 52462306a36Sopenharmony_ci f |= US_FL_NO_READ_DISC_INFO; 52562306a36Sopenharmony_ci break; 52662306a36Sopenharmony_ci case 'e': 52762306a36Sopenharmony_ci f |= US_FL_NO_READ_CAPACITY_16; 52862306a36Sopenharmony_ci break; 52962306a36Sopenharmony_ci case 'f': 53062306a36Sopenharmony_ci f |= US_FL_NO_REPORT_OPCODES; 53162306a36Sopenharmony_ci break; 53262306a36Sopenharmony_ci case 'g': 53362306a36Sopenharmony_ci f |= US_FL_MAX_SECTORS_240; 53462306a36Sopenharmony_ci break; 53562306a36Sopenharmony_ci case 'h': 53662306a36Sopenharmony_ci f |= US_FL_CAPACITY_HEURISTICS; 53762306a36Sopenharmony_ci break; 53862306a36Sopenharmony_ci case 'i': 53962306a36Sopenharmony_ci f |= US_FL_IGNORE_DEVICE; 54062306a36Sopenharmony_ci break; 54162306a36Sopenharmony_ci case 'j': 54262306a36Sopenharmony_ci f |= US_FL_NO_REPORT_LUNS; 54362306a36Sopenharmony_ci break; 54462306a36Sopenharmony_ci case 'k': 54562306a36Sopenharmony_ci f |= US_FL_NO_SAME; 54662306a36Sopenharmony_ci break; 54762306a36Sopenharmony_ci case 'l': 54862306a36Sopenharmony_ci f |= US_FL_NOT_LOCKABLE; 54962306a36Sopenharmony_ci break; 55062306a36Sopenharmony_ci case 'm': 55162306a36Sopenharmony_ci f |= US_FL_MAX_SECTORS_64; 55262306a36Sopenharmony_ci break; 55362306a36Sopenharmony_ci case 'n': 55462306a36Sopenharmony_ci f |= US_FL_INITIAL_READ10; 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci case 'o': 55762306a36Sopenharmony_ci f |= US_FL_CAPACITY_OK; 55862306a36Sopenharmony_ci break; 55962306a36Sopenharmony_ci case 'p': 56062306a36Sopenharmony_ci f |= US_FL_WRITE_CACHE; 56162306a36Sopenharmony_ci break; 56262306a36Sopenharmony_ci case 'r': 56362306a36Sopenharmony_ci f |= US_FL_IGNORE_RESIDUE; 56462306a36Sopenharmony_ci break; 56562306a36Sopenharmony_ci case 's': 56662306a36Sopenharmony_ci f |= US_FL_SINGLE_LUN; 56762306a36Sopenharmony_ci break; 56862306a36Sopenharmony_ci case 't': 56962306a36Sopenharmony_ci f |= US_FL_NO_ATA_1X; 57062306a36Sopenharmony_ci break; 57162306a36Sopenharmony_ci case 'u': 57262306a36Sopenharmony_ci f |= US_FL_IGNORE_UAS; 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci case 'w': 57562306a36Sopenharmony_ci f |= US_FL_NO_WP_DETECT; 57662306a36Sopenharmony_ci break; 57762306a36Sopenharmony_ci case 'y': 57862306a36Sopenharmony_ci f |= US_FL_ALWAYS_SYNC; 57962306a36Sopenharmony_ci break; 58062306a36Sopenharmony_ci /* Ignore unrecognized flag characters */ 58162306a36Sopenharmony_ci } 58262306a36Sopenharmony_ci } 58362306a36Sopenharmony_ci *fflags = (*fflags & ~mask) | f; 58462306a36Sopenharmony_ci} 58562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_adjust_quirks); 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci/* Get the unusual_devs entries and the string descriptors */ 58862306a36Sopenharmony_cistatic int get_device_info(struct us_data *us, const struct usb_device_id *id, 58962306a36Sopenharmony_ci const struct us_unusual_dev *unusual_dev) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci struct usb_device *dev = us->pusb_dev; 59262306a36Sopenharmony_ci struct usb_interface_descriptor *idesc = 59362306a36Sopenharmony_ci &us->pusb_intf->cur_altsetting->desc; 59462306a36Sopenharmony_ci struct device *pdev = &us->pusb_intf->dev; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci /* Store the entries */ 59762306a36Sopenharmony_ci us->unusual_dev = unusual_dev; 59862306a36Sopenharmony_ci us->subclass = (unusual_dev->useProtocol == USB_SC_DEVICE) ? 59962306a36Sopenharmony_ci idesc->bInterfaceSubClass : 60062306a36Sopenharmony_ci unusual_dev->useProtocol; 60162306a36Sopenharmony_ci us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ? 60262306a36Sopenharmony_ci idesc->bInterfaceProtocol : 60362306a36Sopenharmony_ci unusual_dev->useTransport; 60462306a36Sopenharmony_ci us->fflags = id->driver_info; 60562306a36Sopenharmony_ci usb_stor_adjust_quirks(us->pusb_dev, &us->fflags); 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if (us->fflags & US_FL_IGNORE_DEVICE) { 60862306a36Sopenharmony_ci dev_info(pdev, "device ignored\n"); 60962306a36Sopenharmony_ci return -ENODEV; 61062306a36Sopenharmony_ci } 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci /* 61362306a36Sopenharmony_ci * This flag is only needed when we're in high-speed, so let's 61462306a36Sopenharmony_ci * disable it if we're in full-speed 61562306a36Sopenharmony_ci */ 61662306a36Sopenharmony_ci if (dev->speed != USB_SPEED_HIGH) 61762306a36Sopenharmony_ci us->fflags &= ~US_FL_GO_SLOW; 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci if (us->fflags) 62062306a36Sopenharmony_ci dev_info(pdev, "Quirks match for vid %04x pid %04x: %lx\n", 62162306a36Sopenharmony_ci le16_to_cpu(dev->descriptor.idVendor), 62262306a36Sopenharmony_ci le16_to_cpu(dev->descriptor.idProduct), 62362306a36Sopenharmony_ci us->fflags); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci /* 62662306a36Sopenharmony_ci * Log a message if a non-generic unusual_dev entry contains an 62762306a36Sopenharmony_ci * unnecessary subclass or protocol override. This may stimulate 62862306a36Sopenharmony_ci * reports from users that will help us remove unneeded entries 62962306a36Sopenharmony_ci * from the unusual_devs.h table. 63062306a36Sopenharmony_ci */ 63162306a36Sopenharmony_ci if (id->idVendor || id->idProduct) { 63262306a36Sopenharmony_ci static const char *msgs[3] = { 63362306a36Sopenharmony_ci "an unneeded SubClass entry", 63462306a36Sopenharmony_ci "an unneeded Protocol entry", 63562306a36Sopenharmony_ci "unneeded SubClass and Protocol entries"}; 63662306a36Sopenharmony_ci struct usb_device_descriptor *ddesc = &dev->descriptor; 63762306a36Sopenharmony_ci int msg = -1; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci if (unusual_dev->useProtocol != USB_SC_DEVICE && 64062306a36Sopenharmony_ci us->subclass == idesc->bInterfaceSubClass) 64162306a36Sopenharmony_ci msg += 1; 64262306a36Sopenharmony_ci if (unusual_dev->useTransport != USB_PR_DEVICE && 64362306a36Sopenharmony_ci us->protocol == idesc->bInterfaceProtocol) 64462306a36Sopenharmony_ci msg += 2; 64562306a36Sopenharmony_ci if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE)) 64662306a36Sopenharmony_ci dev_notice(pdev, "This device " 64762306a36Sopenharmony_ci "(%04x,%04x,%04x S %02x P %02x)" 64862306a36Sopenharmony_ci " has %s in unusual_devs.h (kernel" 64962306a36Sopenharmony_ci " %s)\n" 65062306a36Sopenharmony_ci " Please send a copy of this message to " 65162306a36Sopenharmony_ci "<linux-usb@vger.kernel.org> and " 65262306a36Sopenharmony_ci "<usb-storage@lists.one-eyed-alien.net>\n", 65362306a36Sopenharmony_ci le16_to_cpu(ddesc->idVendor), 65462306a36Sopenharmony_ci le16_to_cpu(ddesc->idProduct), 65562306a36Sopenharmony_ci le16_to_cpu(ddesc->bcdDevice), 65662306a36Sopenharmony_ci idesc->bInterfaceSubClass, 65762306a36Sopenharmony_ci idesc->bInterfaceProtocol, 65862306a36Sopenharmony_ci msgs[msg], 65962306a36Sopenharmony_ci utsname()->release); 66062306a36Sopenharmony_ci } 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci return 0; 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci/* Get the transport settings */ 66662306a36Sopenharmony_cistatic void get_transport(struct us_data *us) 66762306a36Sopenharmony_ci{ 66862306a36Sopenharmony_ci switch (us->protocol) { 66962306a36Sopenharmony_ci case USB_PR_CB: 67062306a36Sopenharmony_ci us->transport_name = "Control/Bulk"; 67162306a36Sopenharmony_ci us->transport = usb_stor_CB_transport; 67262306a36Sopenharmony_ci us->transport_reset = usb_stor_CB_reset; 67362306a36Sopenharmony_ci us->max_lun = 7; 67462306a36Sopenharmony_ci break; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci case USB_PR_CBI: 67762306a36Sopenharmony_ci us->transport_name = "Control/Bulk/Interrupt"; 67862306a36Sopenharmony_ci us->transport = usb_stor_CB_transport; 67962306a36Sopenharmony_ci us->transport_reset = usb_stor_CB_reset; 68062306a36Sopenharmony_ci us->max_lun = 7; 68162306a36Sopenharmony_ci break; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci case USB_PR_BULK: 68462306a36Sopenharmony_ci us->transport_name = "Bulk"; 68562306a36Sopenharmony_ci us->transport = usb_stor_Bulk_transport; 68662306a36Sopenharmony_ci us->transport_reset = usb_stor_Bulk_reset; 68762306a36Sopenharmony_ci break; 68862306a36Sopenharmony_ci } 68962306a36Sopenharmony_ci} 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci/* Get the protocol settings */ 69262306a36Sopenharmony_cistatic void get_protocol(struct us_data *us) 69362306a36Sopenharmony_ci{ 69462306a36Sopenharmony_ci switch (us->subclass) { 69562306a36Sopenharmony_ci case USB_SC_RBC: 69662306a36Sopenharmony_ci us->protocol_name = "Reduced Block Commands (RBC)"; 69762306a36Sopenharmony_ci us->proto_handler = usb_stor_transparent_scsi_command; 69862306a36Sopenharmony_ci break; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci case USB_SC_8020: 70162306a36Sopenharmony_ci us->protocol_name = "8020i"; 70262306a36Sopenharmony_ci us->proto_handler = usb_stor_pad12_command; 70362306a36Sopenharmony_ci us->max_lun = 0; 70462306a36Sopenharmony_ci break; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci case USB_SC_QIC: 70762306a36Sopenharmony_ci us->protocol_name = "QIC-157"; 70862306a36Sopenharmony_ci us->proto_handler = usb_stor_pad12_command; 70962306a36Sopenharmony_ci us->max_lun = 0; 71062306a36Sopenharmony_ci break; 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci case USB_SC_8070: 71362306a36Sopenharmony_ci us->protocol_name = "8070i"; 71462306a36Sopenharmony_ci us->proto_handler = usb_stor_pad12_command; 71562306a36Sopenharmony_ci us->max_lun = 0; 71662306a36Sopenharmony_ci break; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci case USB_SC_SCSI: 71962306a36Sopenharmony_ci us->protocol_name = "Transparent SCSI"; 72062306a36Sopenharmony_ci us->proto_handler = usb_stor_transparent_scsi_command; 72162306a36Sopenharmony_ci break; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci case USB_SC_UFI: 72462306a36Sopenharmony_ci us->protocol_name = "Uniform Floppy Interface (UFI)"; 72562306a36Sopenharmony_ci us->proto_handler = usb_stor_ufi_command; 72662306a36Sopenharmony_ci break; 72762306a36Sopenharmony_ci } 72862306a36Sopenharmony_ci} 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci/* Get the pipe settings */ 73162306a36Sopenharmony_cistatic int get_pipes(struct us_data *us) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct usb_host_interface *alt = us->pusb_intf->cur_altsetting; 73462306a36Sopenharmony_ci struct usb_endpoint_descriptor *ep_in; 73562306a36Sopenharmony_ci struct usb_endpoint_descriptor *ep_out; 73662306a36Sopenharmony_ci struct usb_endpoint_descriptor *ep_int; 73762306a36Sopenharmony_ci int res; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci /* 74062306a36Sopenharmony_ci * Find the first endpoint of each type we need. 74162306a36Sopenharmony_ci * We are expecting a minimum of 2 endpoints - in and out (bulk). 74262306a36Sopenharmony_ci * An optional interrupt-in is OK (necessary for CBI protocol). 74362306a36Sopenharmony_ci * We will ignore any others. 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci res = usb_find_common_endpoints(alt, &ep_in, &ep_out, NULL, NULL); 74662306a36Sopenharmony_ci if (res) { 74762306a36Sopenharmony_ci usb_stor_dbg(us, "bulk endpoints not found\n"); 74862306a36Sopenharmony_ci return res; 74962306a36Sopenharmony_ci } 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci res = usb_find_int_in_endpoint(alt, &ep_int); 75262306a36Sopenharmony_ci if (res && us->protocol == USB_PR_CBI) { 75362306a36Sopenharmony_ci usb_stor_dbg(us, "interrupt endpoint not found\n"); 75462306a36Sopenharmony_ci return res; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci /* Calculate and store the pipe values */ 75862306a36Sopenharmony_ci us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0); 75962306a36Sopenharmony_ci us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0); 76062306a36Sopenharmony_ci us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev, 76162306a36Sopenharmony_ci usb_endpoint_num(ep_out)); 76262306a36Sopenharmony_ci us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, 76362306a36Sopenharmony_ci usb_endpoint_num(ep_in)); 76462306a36Sopenharmony_ci if (ep_int) { 76562306a36Sopenharmony_ci us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev, 76662306a36Sopenharmony_ci usb_endpoint_num(ep_int)); 76762306a36Sopenharmony_ci us->ep_bInterval = ep_int->bInterval; 76862306a36Sopenharmony_ci } 76962306a36Sopenharmony_ci return 0; 77062306a36Sopenharmony_ci} 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci/* Initialize all the dynamic resources we need */ 77362306a36Sopenharmony_cistatic int usb_stor_acquire_resources(struct us_data *us) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci int p; 77662306a36Sopenharmony_ci struct task_struct *th; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci us->current_urb = usb_alloc_urb(0, GFP_KERNEL); 77962306a36Sopenharmony_ci if (!us->current_urb) 78062306a36Sopenharmony_ci return -ENOMEM; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci /* 78362306a36Sopenharmony_ci * Just before we start our control thread, initialize 78462306a36Sopenharmony_ci * the device if it needs initialization 78562306a36Sopenharmony_ci */ 78662306a36Sopenharmony_ci if (us->unusual_dev->initFunction) { 78762306a36Sopenharmony_ci p = us->unusual_dev->initFunction(us); 78862306a36Sopenharmony_ci if (p) 78962306a36Sopenharmony_ci return p; 79062306a36Sopenharmony_ci } 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci /* Start up our control thread */ 79362306a36Sopenharmony_ci th = kthread_run(usb_stor_control_thread, us, "usb-storage"); 79462306a36Sopenharmony_ci if (IS_ERR(th)) { 79562306a36Sopenharmony_ci dev_warn(&us->pusb_intf->dev, 79662306a36Sopenharmony_ci "Unable to start control thread\n"); 79762306a36Sopenharmony_ci return PTR_ERR(th); 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci us->ctl_thread = th; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci return 0; 80262306a36Sopenharmony_ci} 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci/* Release all our dynamic resources */ 80562306a36Sopenharmony_cistatic void usb_stor_release_resources(struct us_data *us) 80662306a36Sopenharmony_ci{ 80762306a36Sopenharmony_ci /* 80862306a36Sopenharmony_ci * Tell the control thread to exit. The SCSI host must 80962306a36Sopenharmony_ci * already have been removed and the DISCONNECTING flag set 81062306a36Sopenharmony_ci * so that we won't accept any more commands. 81162306a36Sopenharmony_ci */ 81262306a36Sopenharmony_ci usb_stor_dbg(us, "-- sending exit command to thread\n"); 81362306a36Sopenharmony_ci complete(&us->cmnd_ready); 81462306a36Sopenharmony_ci if (us->ctl_thread) 81562306a36Sopenharmony_ci kthread_stop(us->ctl_thread); 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci /* Call the destructor routine, if it exists */ 81862306a36Sopenharmony_ci if (us->extra_destructor) { 81962306a36Sopenharmony_ci usb_stor_dbg(us, "-- calling extra_destructor()\n"); 82062306a36Sopenharmony_ci us->extra_destructor(us->extra); 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* Free the extra data and the URB */ 82462306a36Sopenharmony_ci kfree(us->extra); 82562306a36Sopenharmony_ci usb_free_urb(us->current_urb); 82662306a36Sopenharmony_ci} 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci/* Dissociate from the USB device */ 82962306a36Sopenharmony_cistatic void dissociate_dev(struct us_data *us) 83062306a36Sopenharmony_ci{ 83162306a36Sopenharmony_ci /* Free the buffers */ 83262306a36Sopenharmony_ci kfree(us->cr); 83362306a36Sopenharmony_ci usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* Remove our private data from the interface */ 83662306a36Sopenharmony_ci usb_set_intfdata(us->pusb_intf, NULL); 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci/* 84062306a36Sopenharmony_ci * First stage of disconnect processing: stop SCSI scanning, 84162306a36Sopenharmony_ci * remove the host, and stop accepting new commands 84262306a36Sopenharmony_ci */ 84362306a36Sopenharmony_cistatic void quiesce_and_remove_host(struct us_data *us) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci struct Scsi_Host *host = us_to_host(us); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci /* If the device is really gone, cut short reset delays */ 84862306a36Sopenharmony_ci if (us->pusb_dev->state == USB_STATE_NOTATTACHED) { 84962306a36Sopenharmony_ci set_bit(US_FLIDX_DISCONNECTING, &us->dflags); 85062306a36Sopenharmony_ci wake_up(&us->delay_wait); 85162306a36Sopenharmony_ci } 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_ci /* 85462306a36Sopenharmony_ci * Prevent SCSI scanning (if it hasn't started yet) 85562306a36Sopenharmony_ci * or wait for the SCSI-scanning routine to stop. 85662306a36Sopenharmony_ci */ 85762306a36Sopenharmony_ci cancel_delayed_work_sync(&us->scan_dwork); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci /* Balance autopm calls if scanning was cancelled */ 86062306a36Sopenharmony_ci if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags)) 86162306a36Sopenharmony_ci usb_autopm_put_interface_no_suspend(us->pusb_intf); 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci /* 86462306a36Sopenharmony_ci * Removing the host will perform an orderly shutdown: caches 86562306a36Sopenharmony_ci * synchronized, disks spun down, etc. 86662306a36Sopenharmony_ci */ 86762306a36Sopenharmony_ci scsi_remove_host(host); 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* 87062306a36Sopenharmony_ci * Prevent any new commands from being accepted and cut short 87162306a36Sopenharmony_ci * reset delays. 87262306a36Sopenharmony_ci */ 87362306a36Sopenharmony_ci scsi_lock(host); 87462306a36Sopenharmony_ci set_bit(US_FLIDX_DISCONNECTING, &us->dflags); 87562306a36Sopenharmony_ci scsi_unlock(host); 87662306a36Sopenharmony_ci wake_up(&us->delay_wait); 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci/* Second stage of disconnect processing: deallocate all resources */ 88062306a36Sopenharmony_cistatic void release_everything(struct us_data *us) 88162306a36Sopenharmony_ci{ 88262306a36Sopenharmony_ci usb_stor_release_resources(us); 88362306a36Sopenharmony_ci dissociate_dev(us); 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci /* 88662306a36Sopenharmony_ci * Drop our reference to the host; the SCSI core will free it 88762306a36Sopenharmony_ci * (and "us" along with it) when the refcount becomes 0. 88862306a36Sopenharmony_ci */ 88962306a36Sopenharmony_ci scsi_host_put(us_to_host(us)); 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci/* Delayed-work routine to carry out SCSI-device scanning */ 89362306a36Sopenharmony_cistatic void usb_stor_scan_dwork(struct work_struct *work) 89462306a36Sopenharmony_ci{ 89562306a36Sopenharmony_ci struct us_data *us = container_of(work, struct us_data, 89662306a36Sopenharmony_ci scan_dwork.work); 89762306a36Sopenharmony_ci struct device *dev = &us->pusb_intf->dev; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci dev_dbg(dev, "starting scan\n"); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci /* For bulk-only devices, determine the max LUN value */ 90262306a36Sopenharmony_ci if (us->protocol == USB_PR_BULK && 90362306a36Sopenharmony_ci !(us->fflags & US_FL_SINGLE_LUN) && 90462306a36Sopenharmony_ci !(us->fflags & US_FL_SCM_MULT_TARG)) { 90562306a36Sopenharmony_ci mutex_lock(&us->dev_mutex); 90662306a36Sopenharmony_ci us->max_lun = usb_stor_Bulk_max_lun(us); 90762306a36Sopenharmony_ci /* 90862306a36Sopenharmony_ci * Allow proper scanning of devices that present more than 8 LUNs 90962306a36Sopenharmony_ci * While not affecting other devices that may need the previous 91062306a36Sopenharmony_ci * behavior 91162306a36Sopenharmony_ci */ 91262306a36Sopenharmony_ci if (us->max_lun >= 8) 91362306a36Sopenharmony_ci us_to_host(us)->max_lun = us->max_lun+1; 91462306a36Sopenharmony_ci mutex_unlock(&us->dev_mutex); 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci scsi_scan_host(us_to_host(us)); 91762306a36Sopenharmony_ci dev_dbg(dev, "scan complete\n"); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci /* Should we unbind if no devices were detected? */ 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci usb_autopm_put_interface(us->pusb_intf); 92262306a36Sopenharmony_ci clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags); 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_cistatic unsigned int usb_stor_sg_tablesize(struct usb_interface *intf) 92662306a36Sopenharmony_ci{ 92762306a36Sopenharmony_ci struct usb_device *usb_dev = interface_to_usbdev(intf); 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci if (usb_dev->bus->sg_tablesize) { 93062306a36Sopenharmony_ci return usb_dev->bus->sg_tablesize; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci return SG_ALL; 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci/* First part of general USB mass-storage probing */ 93662306a36Sopenharmony_ciint usb_stor_probe1(struct us_data **pus, 93762306a36Sopenharmony_ci struct usb_interface *intf, 93862306a36Sopenharmony_ci const struct usb_device_id *id, 93962306a36Sopenharmony_ci const struct us_unusual_dev *unusual_dev, 94062306a36Sopenharmony_ci const struct scsi_host_template *sht) 94162306a36Sopenharmony_ci{ 94262306a36Sopenharmony_ci struct Scsi_Host *host; 94362306a36Sopenharmony_ci struct us_data *us; 94462306a36Sopenharmony_ci int result; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci dev_info(&intf->dev, "USB Mass Storage device detected\n"); 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci /* 94962306a36Sopenharmony_ci * Ask the SCSI layer to allocate a host structure, with extra 95062306a36Sopenharmony_ci * space at the end for our private us_data structure. 95162306a36Sopenharmony_ci */ 95262306a36Sopenharmony_ci host = scsi_host_alloc(sht, sizeof(*us)); 95362306a36Sopenharmony_ci if (!host) { 95462306a36Sopenharmony_ci dev_warn(&intf->dev, "Unable to allocate the scsi host\n"); 95562306a36Sopenharmony_ci return -ENOMEM; 95662306a36Sopenharmony_ci } 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci /* 95962306a36Sopenharmony_ci * Allow 16-byte CDBs and thus > 2TB 96062306a36Sopenharmony_ci */ 96162306a36Sopenharmony_ci host->max_cmd_len = 16; 96262306a36Sopenharmony_ci host->sg_tablesize = usb_stor_sg_tablesize(intf); 96362306a36Sopenharmony_ci *pus = us = host_to_us(host); 96462306a36Sopenharmony_ci mutex_init(&(us->dev_mutex)); 96562306a36Sopenharmony_ci us_set_lock_class(&us->dev_mutex, intf); 96662306a36Sopenharmony_ci init_completion(&us->cmnd_ready); 96762306a36Sopenharmony_ci init_completion(&(us->notify)); 96862306a36Sopenharmony_ci init_waitqueue_head(&us->delay_wait); 96962306a36Sopenharmony_ci INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci /* Associate the us_data structure with the USB device */ 97262306a36Sopenharmony_ci result = associate_dev(us, intf); 97362306a36Sopenharmony_ci if (result) 97462306a36Sopenharmony_ci goto BadDevice; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci /* Get the unusual_devs entries and the descriptors */ 97762306a36Sopenharmony_ci result = get_device_info(us, id, unusual_dev); 97862306a36Sopenharmony_ci if (result) 97962306a36Sopenharmony_ci goto BadDevice; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci /* Get standard transport and protocol settings */ 98262306a36Sopenharmony_ci get_transport(us); 98362306a36Sopenharmony_ci get_protocol(us); 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_ci /* 98662306a36Sopenharmony_ci * Give the caller a chance to fill in specialized transport 98762306a36Sopenharmony_ci * or protocol settings. 98862306a36Sopenharmony_ci */ 98962306a36Sopenharmony_ci return 0; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ciBadDevice: 99262306a36Sopenharmony_ci usb_stor_dbg(us, "storage_probe() failed\n"); 99362306a36Sopenharmony_ci release_everything(us); 99462306a36Sopenharmony_ci return result; 99562306a36Sopenharmony_ci} 99662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_probe1); 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci/* Second part of general USB mass-storage probing */ 99962306a36Sopenharmony_ciint usb_stor_probe2(struct us_data *us) 100062306a36Sopenharmony_ci{ 100162306a36Sopenharmony_ci int result; 100262306a36Sopenharmony_ci struct device *dev = &us->pusb_intf->dev; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* Make sure the transport and protocol have both been set */ 100562306a36Sopenharmony_ci if (!us->transport || !us->proto_handler) { 100662306a36Sopenharmony_ci result = -ENXIO; 100762306a36Sopenharmony_ci goto BadDevice; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci usb_stor_dbg(us, "Transport: %s\n", us->transport_name); 101062306a36Sopenharmony_ci usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci if (us->fflags & US_FL_SCM_MULT_TARG) { 101362306a36Sopenharmony_ci /* 101462306a36Sopenharmony_ci * SCM eUSCSI bridge devices can have different numbers 101562306a36Sopenharmony_ci * of LUNs on different targets; allow all to be probed. 101662306a36Sopenharmony_ci */ 101762306a36Sopenharmony_ci us->max_lun = 7; 101862306a36Sopenharmony_ci /* The eUSCSI itself has ID 7, so avoid scanning that */ 101962306a36Sopenharmony_ci us_to_host(us)->this_id = 7; 102062306a36Sopenharmony_ci /* max_id is 8 initially, so no need to set it here */ 102162306a36Sopenharmony_ci } else { 102262306a36Sopenharmony_ci /* In the normal case there is only a single target */ 102362306a36Sopenharmony_ci us_to_host(us)->max_id = 1; 102462306a36Sopenharmony_ci /* 102562306a36Sopenharmony_ci * Like Windows, we won't store the LUN bits in CDB[1] for 102662306a36Sopenharmony_ci * SCSI-2 devices using the Bulk-Only transport (even though 102762306a36Sopenharmony_ci * this violates the SCSI spec). 102862306a36Sopenharmony_ci */ 102962306a36Sopenharmony_ci if (us->transport == usb_stor_Bulk_transport) 103062306a36Sopenharmony_ci us_to_host(us)->no_scsi2_lun_in_cdb = 1; 103162306a36Sopenharmony_ci } 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* fix for single-lun devices */ 103462306a36Sopenharmony_ci if (us->fflags & US_FL_SINGLE_LUN) 103562306a36Sopenharmony_ci us->max_lun = 0; 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci /* Find the endpoints and calculate pipe values */ 103862306a36Sopenharmony_ci result = get_pipes(us); 103962306a36Sopenharmony_ci if (result) 104062306a36Sopenharmony_ci goto BadDevice; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci /* 104362306a36Sopenharmony_ci * If the device returns invalid data for the first READ(10) 104462306a36Sopenharmony_ci * command, indicate the command should be retried. 104562306a36Sopenharmony_ci */ 104662306a36Sopenharmony_ci if (us->fflags & US_FL_INITIAL_READ10) 104762306a36Sopenharmony_ci set_bit(US_FLIDX_REDO_READ10, &us->dflags); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci /* Acquire all the other resources and add the host */ 105062306a36Sopenharmony_ci result = usb_stor_acquire_resources(us); 105162306a36Sopenharmony_ci if (result) 105262306a36Sopenharmony_ci goto BadDevice; 105362306a36Sopenharmony_ci usb_autopm_get_interface_no_resume(us->pusb_intf); 105462306a36Sopenharmony_ci snprintf(us->scsi_name, sizeof(us->scsi_name), "usb-storage %s", 105562306a36Sopenharmony_ci dev_name(&us->pusb_intf->dev)); 105662306a36Sopenharmony_ci result = scsi_add_host(us_to_host(us), dev); 105762306a36Sopenharmony_ci if (result) { 105862306a36Sopenharmony_ci dev_warn(dev, 105962306a36Sopenharmony_ci "Unable to add the scsi host\n"); 106062306a36Sopenharmony_ci goto HostAddErr; 106162306a36Sopenharmony_ci } 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci /* Submit the delayed_work for SCSI-device scanning */ 106462306a36Sopenharmony_ci set_bit(US_FLIDX_SCAN_PENDING, &us->dflags); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (delay_use > 0) 106762306a36Sopenharmony_ci dev_dbg(dev, "waiting for device to settle before scanning\n"); 106862306a36Sopenharmony_ci queue_delayed_work(system_freezable_wq, &us->scan_dwork, 106962306a36Sopenharmony_ci delay_use * HZ); 107062306a36Sopenharmony_ci return 0; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci /* We come here if there are any problems */ 107362306a36Sopenharmony_ciHostAddErr: 107462306a36Sopenharmony_ci usb_autopm_put_interface_no_suspend(us->pusb_intf); 107562306a36Sopenharmony_ciBadDevice: 107662306a36Sopenharmony_ci usb_stor_dbg(us, "storage_probe() failed\n"); 107762306a36Sopenharmony_ci release_everything(us); 107862306a36Sopenharmony_ci return result; 107962306a36Sopenharmony_ci} 108062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_probe2); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci/* Handle a USB mass-storage disconnect */ 108362306a36Sopenharmony_civoid usb_stor_disconnect(struct usb_interface *intf) 108462306a36Sopenharmony_ci{ 108562306a36Sopenharmony_ci struct us_data *us = usb_get_intfdata(intf); 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci quiesce_and_remove_host(us); 108862306a36Sopenharmony_ci release_everything(us); 108962306a36Sopenharmony_ci} 109062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_disconnect); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_cistatic struct scsi_host_template usb_stor_host_template; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci/* The main probe routine for standard devices */ 109562306a36Sopenharmony_cistatic int storage_probe(struct usb_interface *intf, 109662306a36Sopenharmony_ci const struct usb_device_id *id) 109762306a36Sopenharmony_ci{ 109862306a36Sopenharmony_ci const struct us_unusual_dev *unusual_dev; 109962306a36Sopenharmony_ci struct us_data *us; 110062306a36Sopenharmony_ci int result; 110162306a36Sopenharmony_ci int size; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci /* If uas is enabled and this device can do uas then ignore it. */ 110462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_UAS) 110562306a36Sopenharmony_ci if (uas_use_uas_driver(intf, id, NULL)) 110662306a36Sopenharmony_ci return -ENXIO; 110762306a36Sopenharmony_ci#endif 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_ci /* 111062306a36Sopenharmony_ci * If the device isn't standard (is handled by a subdriver 111162306a36Sopenharmony_ci * module) then don't accept it. 111262306a36Sopenharmony_ci */ 111362306a36Sopenharmony_ci if (usb_usual_ignore_device(intf)) 111462306a36Sopenharmony_ci return -ENXIO; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci /* 111762306a36Sopenharmony_ci * Call the general probe procedures. 111862306a36Sopenharmony_ci * 111962306a36Sopenharmony_ci * The unusual_dev_list array is parallel to the usb_storage_usb_ids 112062306a36Sopenharmony_ci * table, so we use the index of the id entry to find the 112162306a36Sopenharmony_ci * corresponding unusual_devs entry. 112262306a36Sopenharmony_ci */ 112362306a36Sopenharmony_ci 112462306a36Sopenharmony_ci size = ARRAY_SIZE(us_unusual_dev_list); 112562306a36Sopenharmony_ci if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) { 112662306a36Sopenharmony_ci unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list; 112762306a36Sopenharmony_ci } else { 112862306a36Sopenharmony_ci unusual_dev = &for_dynamic_ids; 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci dev_dbg(&intf->dev, "Use Bulk-Only transport with the Transparent SCSI protocol for dynamic id: 0x%04x 0x%04x\n", 113162306a36Sopenharmony_ci id->idVendor, id->idProduct); 113262306a36Sopenharmony_ci } 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci result = usb_stor_probe1(&us, intf, id, unusual_dev, 113562306a36Sopenharmony_ci &usb_stor_host_template); 113662306a36Sopenharmony_ci if (result) 113762306a36Sopenharmony_ci return result; 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci /* No special transport or protocol settings in the main module */ 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci result = usb_stor_probe2(us); 114262306a36Sopenharmony_ci return result; 114362306a36Sopenharmony_ci} 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_cistatic struct usb_driver usb_storage_driver = { 114662306a36Sopenharmony_ci .name = DRV_NAME, 114762306a36Sopenharmony_ci .probe = storage_probe, 114862306a36Sopenharmony_ci .disconnect = usb_stor_disconnect, 114962306a36Sopenharmony_ci .suspend = usb_stor_suspend, 115062306a36Sopenharmony_ci .resume = usb_stor_resume, 115162306a36Sopenharmony_ci .reset_resume = usb_stor_reset_resume, 115262306a36Sopenharmony_ci .pre_reset = usb_stor_pre_reset, 115362306a36Sopenharmony_ci .post_reset = usb_stor_post_reset, 115462306a36Sopenharmony_ci .id_table = usb_storage_usb_ids, 115562306a36Sopenharmony_ci .supports_autosuspend = 1, 115662306a36Sopenharmony_ci .soft_unbind = 1, 115762306a36Sopenharmony_ci}; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_cimodule_usb_stor_driver(usb_storage_driver, usb_stor_host_template, DRV_NAME); 1160