18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Driver for USB Mass Storage compliant devices
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Current development and maintenance by:
68c2ecf20Sopenharmony_ci *   (c) 1999-2003 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Developed with the assistance of:
98c2ecf20Sopenharmony_ci *   (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
108c2ecf20Sopenharmony_ci *   (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu)
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Initial work by:
138c2ecf20Sopenharmony_ci *   (c) 1999 Michael Gee (michael@linuxspecific.com)
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * usb_device_id support by Adam J. Richter (adam@yggdrasil.com):
168c2ecf20Sopenharmony_ci *   (c) 2000 Yggdrasil Computing, Inc.
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * This driver is based on the 'USB Mass Storage Class' document. This
198c2ecf20Sopenharmony_ci * describes in detail the protocol used to communicate with such
208c2ecf20Sopenharmony_ci * devices.  Clearly, the designers had SCSI and ATAPI commands in
218c2ecf20Sopenharmony_ci * mind when they created this document.  The commands are all very
228c2ecf20Sopenharmony_ci * similar to commands in the SCSI-II and ATAPI specifications.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * It is important to note that in a number of cases this class
258c2ecf20Sopenharmony_ci * exhibits class-specific exemptions from the USB specification.
268c2ecf20Sopenharmony_ci * Notably the usage of NAK, STALL and ACK differs from the norm, in
278c2ecf20Sopenharmony_ci * that they are used to communicate wait, failed and OK on commands.
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * Also, for certain devices, the interrupt endpoint is used to convey
308c2ecf20Sopenharmony_ci * status of a command.
318c2ecf20Sopenharmony_ci */
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_STORAGE_DEBUG
348c2ecf20Sopenharmony_ci#define DEBUG
358c2ecf20Sopenharmony_ci#endif
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include <linux/sched.h>
388c2ecf20Sopenharmony_ci#include <linux/errno.h>
398c2ecf20Sopenharmony_ci#include <linux/module.h>
408c2ecf20Sopenharmony_ci#include <linux/slab.h>
418c2ecf20Sopenharmony_ci#include <linux/kthread.h>
428c2ecf20Sopenharmony_ci#include <linux/mutex.h>
438c2ecf20Sopenharmony_ci#include <linux/utsname.h>
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include <scsi/scsi.h>
468c2ecf20Sopenharmony_ci#include <scsi/scsi_cmnd.h>
478c2ecf20Sopenharmony_ci#include <scsi/scsi_device.h>
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci#include "usb.h"
508c2ecf20Sopenharmony_ci#include "scsiglue.h"
518c2ecf20Sopenharmony_ci#include "transport.h"
528c2ecf20Sopenharmony_ci#include "protocol.h"
538c2ecf20Sopenharmony_ci#include "debug.h"
548c2ecf20Sopenharmony_ci#include "initializers.h"
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#include "sierra_ms.h"
578c2ecf20Sopenharmony_ci#include "option_ms.h"
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_UAS)
608c2ecf20Sopenharmony_ci#include "uas-detect.h"
618c2ecf20Sopenharmony_ci#endif
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci#define DRV_NAME "usb-storage"
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* Some informational data */
668c2ecf20Sopenharmony_ciMODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
678c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("USB Mass Storage driver for Linux");
688c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic unsigned int delay_use = 1;
718c2ecf20Sopenharmony_cimodule_param(delay_use, uint, S_IRUGO | S_IWUSR);
728c2ecf20Sopenharmony_ciMODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistatic char quirks[128];
758c2ecf20Sopenharmony_cimodule_param_string(quirks, quirks, sizeof(quirks), S_IRUGO | S_IWUSR);
768c2ecf20Sopenharmony_ciMODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks");
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/*
808c2ecf20Sopenharmony_ci * The entries in this table correspond, line for line,
818c2ecf20Sopenharmony_ci * with the entries in usb_storage_usb_ids[], defined in usual-tables.c.
828c2ecf20Sopenharmony_ci */
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/*
858c2ecf20Sopenharmony_ci *The vendor name should be kept at eight characters or less, and
868c2ecf20Sopenharmony_ci * the product name should be kept at 16 characters or less. If a device
878c2ecf20Sopenharmony_ci * has the US_FL_FIX_INQUIRY flag, then the vendor and product names
888c2ecf20Sopenharmony_ci * normally generated by a device through the INQUIRY response will be
898c2ecf20Sopenharmony_ci * taken from this list, and this is the reason for the above size
908c2ecf20Sopenharmony_ci * restriction. However, if the flag is not present, then you
918c2ecf20Sopenharmony_ci * are free to use as many characters as you like.
928c2ecf20Sopenharmony_ci */
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
958c2ecf20Sopenharmony_ci		    vendor_name, product_name, use_protocol, use_transport, \
968c2ecf20Sopenharmony_ci		    init_function, Flags) \
978c2ecf20Sopenharmony_ci{ \
988c2ecf20Sopenharmony_ci	.vendorName = vendor_name,	\
998c2ecf20Sopenharmony_ci	.productName = product_name,	\
1008c2ecf20Sopenharmony_ci	.useProtocol = use_protocol,	\
1018c2ecf20Sopenharmony_ci	.useTransport = use_transport,	\
1028c2ecf20Sopenharmony_ci	.initFunction = init_function,	\
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#define COMPLIANT_DEV	UNUSUAL_DEV
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci#define USUAL_DEV(use_protocol, use_transport) \
1088c2ecf20Sopenharmony_ci{ \
1098c2ecf20Sopenharmony_ci	.useProtocol = use_protocol,	\
1108c2ecf20Sopenharmony_ci	.useTransport = use_transport,	\
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \
1148c2ecf20Sopenharmony_ci		vendor_name, product_name, use_protocol, use_transport, \
1158c2ecf20Sopenharmony_ci		init_function, Flags) \
1168c2ecf20Sopenharmony_ci{ \
1178c2ecf20Sopenharmony_ci	.vendorName = vendor_name,	\
1188c2ecf20Sopenharmony_ci	.productName = product_name,	\
1198c2ecf20Sopenharmony_ci	.useProtocol = use_protocol,	\
1208c2ecf20Sopenharmony_ci	.useTransport = use_transport,	\
1218c2ecf20Sopenharmony_ci	.initFunction = init_function,	\
1228c2ecf20Sopenharmony_ci}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic const struct us_unusual_dev us_unusual_dev_list[] = {
1258c2ecf20Sopenharmony_ci#	include "unusual_devs.h"
1268c2ecf20Sopenharmony_ci	{ }		/* Terminating entry */
1278c2ecf20Sopenharmony_ci};
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_cistatic const struct us_unusual_dev for_dynamic_ids =
1308c2ecf20Sopenharmony_ci		USUAL_DEV(USB_SC_SCSI, USB_PR_BULK);
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci#undef UNUSUAL_DEV
1338c2ecf20Sopenharmony_ci#undef COMPLIANT_DEV
1348c2ecf20Sopenharmony_ci#undef USUAL_DEV
1358c2ecf20Sopenharmony_ci#undef UNUSUAL_VENDOR_INTF
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci#ifdef CONFIG_LOCKDEP
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_cistatic struct lock_class_key us_interface_key[USB_MAXINTERFACES];
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic void us_set_lock_class(struct mutex *mutex,
1428c2ecf20Sopenharmony_ci		struct usb_interface *intf)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	struct usb_device *udev = interface_to_usbdev(intf);
1458c2ecf20Sopenharmony_ci	struct usb_host_config *config = udev->actconfig;
1468c2ecf20Sopenharmony_ci	int i;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	for (i = 0; i < config->desc.bNumInterfaces; i++) {
1498c2ecf20Sopenharmony_ci		if (config->interface[i] == intf)
1508c2ecf20Sopenharmony_ci			break;
1518c2ecf20Sopenharmony_ci	}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	BUG_ON(i == config->desc.bNumInterfaces);
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	lockdep_set_class(mutex, &us_interface_key[i]);
1568c2ecf20Sopenharmony_ci}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci#else
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic void us_set_lock_class(struct mutex *mutex,
1618c2ecf20Sopenharmony_ci		struct usb_interface *intf)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci#endif
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci#ifdef CONFIG_PM	/* Minimal support for suspend and resume */
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ciint usb_stor_suspend(struct usb_interface *iface, pm_message_t message)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	struct us_data *us = usb_get_intfdata(iface);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	/* Wait until no command is running */
1748c2ecf20Sopenharmony_ci	mutex_lock(&us->dev_mutex);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (us->suspend_resume_hook)
1778c2ecf20Sopenharmony_ci		(us->suspend_resume_hook)(us, US_SUSPEND);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	/*
1808c2ecf20Sopenharmony_ci	 * When runtime PM is working, we'll set a flag to indicate
1818c2ecf20Sopenharmony_ci	 * whether we should autoresume when a SCSI request arrives.
1828c2ecf20Sopenharmony_ci	 */
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	mutex_unlock(&us->dev_mutex);
1858c2ecf20Sopenharmony_ci	return 0;
1868c2ecf20Sopenharmony_ci}
1878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_suspend);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ciint usb_stor_resume(struct usb_interface *iface)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci	struct us_data *us = usb_get_intfdata(iface);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	mutex_lock(&us->dev_mutex);
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	if (us->suspend_resume_hook)
1968c2ecf20Sopenharmony_ci		(us->suspend_resume_hook)(us, US_RESUME);
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	mutex_unlock(&us->dev_mutex);
1998c2ecf20Sopenharmony_ci	return 0;
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_resume);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ciint usb_stor_reset_resume(struct usb_interface *iface)
2048c2ecf20Sopenharmony_ci{
2058c2ecf20Sopenharmony_ci	struct us_data *us = usb_get_intfdata(iface);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	/* Report the reset to the SCSI core */
2088c2ecf20Sopenharmony_ci	usb_stor_report_bus_reset(us);
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	/*
2118c2ecf20Sopenharmony_ci	 * If any of the subdrivers implemented a reinitialization scheme,
2128c2ecf20Sopenharmony_ci	 * this is where the callback would be invoked.
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci	return 0;
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_reset_resume);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci/*
2218c2ecf20Sopenharmony_ci * The next two routines get called just before and just after
2228c2ecf20Sopenharmony_ci * a USB port reset, whether from this driver or a different one.
2238c2ecf20Sopenharmony_ci */
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ciint usb_stor_pre_reset(struct usb_interface *iface)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct us_data *us = usb_get_intfdata(iface);
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/* Make sure no command runs during the reset */
2308c2ecf20Sopenharmony_ci	mutex_lock(&us->dev_mutex);
2318c2ecf20Sopenharmony_ci	return 0;
2328c2ecf20Sopenharmony_ci}
2338c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_pre_reset);
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ciint usb_stor_post_reset(struct usb_interface *iface)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	struct us_data *us = usb_get_intfdata(iface);
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	/* Report the reset to the SCSI core */
2408c2ecf20Sopenharmony_ci	usb_stor_report_bus_reset(us);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/*
2438c2ecf20Sopenharmony_ci	 * If any of the subdrivers implemented a reinitialization scheme,
2448c2ecf20Sopenharmony_ci	 * this is where the callback would be invoked.
2458c2ecf20Sopenharmony_ci	 */
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	mutex_unlock(&us->dev_mutex);
2488c2ecf20Sopenharmony_ci	return 0;
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_post_reset);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci/*
2538c2ecf20Sopenharmony_ci * fill_inquiry_response takes an unsigned char array (which must
2548c2ecf20Sopenharmony_ci * be at least 36 characters) and populates the vendor name,
2558c2ecf20Sopenharmony_ci * product name, and revision fields. Then the array is copied
2568c2ecf20Sopenharmony_ci * into the SCSI command's response buffer (oddly enough
2578c2ecf20Sopenharmony_ci * called request_buffer). data_len contains the length of the
2588c2ecf20Sopenharmony_ci * data array, which again must be at least 36.
2598c2ecf20Sopenharmony_ci */
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_civoid fill_inquiry_response(struct us_data *us, unsigned char *data,
2628c2ecf20Sopenharmony_ci		unsigned int data_len)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	if (data_len < 36) /* You lose. */
2658c2ecf20Sopenharmony_ci		return;
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci	memset(data+8, ' ', 28);
2688c2ecf20Sopenharmony_ci	if (data[0]&0x20) { /*
2698c2ecf20Sopenharmony_ci			     * USB device currently not connected. Return
2708c2ecf20Sopenharmony_ci			     * peripheral qualifier 001b ("...however, the
2718c2ecf20Sopenharmony_ci			     * physical device is not currently connected
2728c2ecf20Sopenharmony_ci			     * to this logical unit") and leave vendor and
2738c2ecf20Sopenharmony_ci			     * product identification empty. ("If the target
2748c2ecf20Sopenharmony_ci			     * does store some of the INQUIRY data on the
2758c2ecf20Sopenharmony_ci			     * device, it may return zeros or ASCII spaces
2768c2ecf20Sopenharmony_ci			     * (20h) in those fields until the data is
2778c2ecf20Sopenharmony_ci			     * available from the device.").
2788c2ecf20Sopenharmony_ci			     */
2798c2ecf20Sopenharmony_ci	} else {
2808c2ecf20Sopenharmony_ci		u16 bcdDevice = le16_to_cpu(us->pusb_dev->descriptor.bcdDevice);
2818c2ecf20Sopenharmony_ci		int n;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci		n = strlen(us->unusual_dev->vendorName);
2848c2ecf20Sopenharmony_ci		memcpy(data+8, us->unusual_dev->vendorName, min(8, n));
2858c2ecf20Sopenharmony_ci		n = strlen(us->unusual_dev->productName);
2868c2ecf20Sopenharmony_ci		memcpy(data+16, us->unusual_dev->productName, min(16, n));
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		data[32] = 0x30 + ((bcdDevice>>12) & 0x0F);
2898c2ecf20Sopenharmony_ci		data[33] = 0x30 + ((bcdDevice>>8) & 0x0F);
2908c2ecf20Sopenharmony_ci		data[34] = 0x30 + ((bcdDevice>>4) & 0x0F);
2918c2ecf20Sopenharmony_ci		data[35] = 0x30 + ((bcdDevice) & 0x0F);
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	usb_stor_set_xfer_buf(data, data_len, us->srb);
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fill_inquiry_response);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic int usb_stor_control_thread(void * __us)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	struct us_data *us = (struct us_data *)__us;
3018c2ecf20Sopenharmony_ci	struct Scsi_Host *host = us_to_host(us);
3028c2ecf20Sopenharmony_ci	struct scsi_cmnd *srb;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	for (;;) {
3058c2ecf20Sopenharmony_ci		usb_stor_dbg(us, "*** thread sleeping\n");
3068c2ecf20Sopenharmony_ci		if (wait_for_completion_interruptible(&us->cmnd_ready))
3078c2ecf20Sopenharmony_ci			break;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci		usb_stor_dbg(us, "*** thread awakened\n");
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci		/* lock the device pointers */
3128c2ecf20Sopenharmony_ci		mutex_lock(&(us->dev_mutex));
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci		/* lock access to the state */
3158c2ecf20Sopenharmony_ci		scsi_lock(host);
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci		/* When we are called with no command pending, we're done */
3188c2ecf20Sopenharmony_ci		srb = us->srb;
3198c2ecf20Sopenharmony_ci		if (srb == NULL) {
3208c2ecf20Sopenharmony_ci			scsi_unlock(host);
3218c2ecf20Sopenharmony_ci			mutex_unlock(&us->dev_mutex);
3228c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "-- exiting\n");
3238c2ecf20Sopenharmony_ci			break;
3248c2ecf20Sopenharmony_ci		}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci		/* has the command timed out *already* ? */
3278c2ecf20Sopenharmony_ci		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
3288c2ecf20Sopenharmony_ci			srb->result = DID_ABORT << 16;
3298c2ecf20Sopenharmony_ci			goto SkipForAbort;
3308c2ecf20Sopenharmony_ci		}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci		scsi_unlock(host);
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci		/*
3358c2ecf20Sopenharmony_ci		 * reject the command if the direction indicator
3368c2ecf20Sopenharmony_ci		 * is UNKNOWN
3378c2ecf20Sopenharmony_ci		 */
3388c2ecf20Sopenharmony_ci		if (srb->sc_data_direction == DMA_BIDIRECTIONAL) {
3398c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "UNKNOWN data direction\n");
3408c2ecf20Sopenharmony_ci			srb->result = DID_ERROR << 16;
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		/*
3448c2ecf20Sopenharmony_ci		 * reject if target != 0 or if LUN is higher than
3458c2ecf20Sopenharmony_ci		 * the maximum known LUN
3468c2ecf20Sopenharmony_ci		 */
3478c2ecf20Sopenharmony_ci		else if (srb->device->id &&
3488c2ecf20Sopenharmony_ci				!(us->fflags & US_FL_SCM_MULT_TARG)) {
3498c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "Bad target number (%d:%llu)\n",
3508c2ecf20Sopenharmony_ci				     srb->device->id,
3518c2ecf20Sopenharmony_ci				     srb->device->lun);
3528c2ecf20Sopenharmony_ci			srb->result = DID_BAD_TARGET << 16;
3538c2ecf20Sopenharmony_ci		}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci		else if (srb->device->lun > us->max_lun) {
3568c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "Bad LUN (%d:%llu)\n",
3578c2ecf20Sopenharmony_ci				     srb->device->id,
3588c2ecf20Sopenharmony_ci				     srb->device->lun);
3598c2ecf20Sopenharmony_ci			srb->result = DID_BAD_TARGET << 16;
3608c2ecf20Sopenharmony_ci		}
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci		/*
3638c2ecf20Sopenharmony_ci		 * Handle those devices which need us to fake
3648c2ecf20Sopenharmony_ci		 * their inquiry data
3658c2ecf20Sopenharmony_ci		 */
3668c2ecf20Sopenharmony_ci		else if ((srb->cmnd[0] == INQUIRY) &&
3678c2ecf20Sopenharmony_ci			    (us->fflags & US_FL_FIX_INQUIRY)) {
3688c2ecf20Sopenharmony_ci			unsigned char data_ptr[36] = {
3698c2ecf20Sopenharmony_ci			    0x00, 0x80, 0x02, 0x02,
3708c2ecf20Sopenharmony_ci			    0x1F, 0x00, 0x00, 0x00};
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "Faking INQUIRY command\n");
3738c2ecf20Sopenharmony_ci			fill_inquiry_response(us, data_ptr, 36);
3748c2ecf20Sopenharmony_ci			srb->result = SAM_STAT_GOOD;
3758c2ecf20Sopenharmony_ci		}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci		/* we've got a command, let's do it! */
3788c2ecf20Sopenharmony_ci		else {
3798c2ecf20Sopenharmony_ci			US_DEBUG(usb_stor_show_command(us, srb));
3808c2ecf20Sopenharmony_ci			us->proto_handler(srb, us);
3818c2ecf20Sopenharmony_ci			usb_mark_last_busy(us->pusb_dev);
3828c2ecf20Sopenharmony_ci		}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci		/* lock access to the state */
3858c2ecf20Sopenharmony_ci		scsi_lock(host);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci		/* was the command aborted? */
3888c2ecf20Sopenharmony_ci		if (srb->result == DID_ABORT << 16) {
3898c2ecf20Sopenharmony_ciSkipForAbort:
3908c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "scsi command aborted\n");
3918c2ecf20Sopenharmony_ci			srb = NULL;	/* Don't call srb->scsi_done() */
3928c2ecf20Sopenharmony_ci		}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci		/*
3958c2ecf20Sopenharmony_ci		 * If an abort request was received we need to signal that
3968c2ecf20Sopenharmony_ci		 * the abort has finished.  The proper test for this is
3978c2ecf20Sopenharmony_ci		 * the TIMED_OUT flag, not srb->result == DID_ABORT, because
3988c2ecf20Sopenharmony_ci		 * the timeout might have occurred after the command had
3998c2ecf20Sopenharmony_ci		 * already completed with a different result code.
4008c2ecf20Sopenharmony_ci		 */
4018c2ecf20Sopenharmony_ci		if (test_bit(US_FLIDX_TIMED_OUT, &us->dflags)) {
4028c2ecf20Sopenharmony_ci			complete(&(us->notify));
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci			/* Allow USB transfers to resume */
4058c2ecf20Sopenharmony_ci			clear_bit(US_FLIDX_ABORTING, &us->dflags);
4068c2ecf20Sopenharmony_ci			clear_bit(US_FLIDX_TIMED_OUT, &us->dflags);
4078c2ecf20Sopenharmony_ci		}
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci		/* finished working on this command */
4108c2ecf20Sopenharmony_ci		us->srb = NULL;
4118c2ecf20Sopenharmony_ci		scsi_unlock(host);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci		/* unlock the device pointers */
4148c2ecf20Sopenharmony_ci		mutex_unlock(&us->dev_mutex);
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci		/* now that the locks are released, notify the SCSI core */
4178c2ecf20Sopenharmony_ci		if (srb) {
4188c2ecf20Sopenharmony_ci			usb_stor_dbg(us, "scsi cmd done, result=0x%x\n",
4198c2ecf20Sopenharmony_ci					srb->result);
4208c2ecf20Sopenharmony_ci			srb->scsi_done(srb);
4218c2ecf20Sopenharmony_ci		}
4228c2ecf20Sopenharmony_ci	} /* for (;;) */
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/* Wait until we are told to stop */
4258c2ecf20Sopenharmony_ci	for (;;) {
4268c2ecf20Sopenharmony_ci		set_current_state(TASK_INTERRUPTIBLE);
4278c2ecf20Sopenharmony_ci		if (kthread_should_stop())
4288c2ecf20Sopenharmony_ci			break;
4298c2ecf20Sopenharmony_ci		schedule();
4308c2ecf20Sopenharmony_ci	}
4318c2ecf20Sopenharmony_ci	__set_current_state(TASK_RUNNING);
4328c2ecf20Sopenharmony_ci	return 0;
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci/***********************************************************************
4368c2ecf20Sopenharmony_ci * Device probing and disconnecting
4378c2ecf20Sopenharmony_ci ***********************************************************************/
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci/* Associate our private data with the USB device */
4408c2ecf20Sopenharmony_cistatic int associate_dev(struct us_data *us, struct usb_interface *intf)
4418c2ecf20Sopenharmony_ci{
4428c2ecf20Sopenharmony_ci	/* Fill in the device-related fields */
4438c2ecf20Sopenharmony_ci	us->pusb_dev = interface_to_usbdev(intf);
4448c2ecf20Sopenharmony_ci	us->pusb_intf = intf;
4458c2ecf20Sopenharmony_ci	us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
4468c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "Vendor: 0x%04x, Product: 0x%04x, Revision: 0x%04x\n",
4478c2ecf20Sopenharmony_ci		     le16_to_cpu(us->pusb_dev->descriptor.idVendor),
4488c2ecf20Sopenharmony_ci		     le16_to_cpu(us->pusb_dev->descriptor.idProduct),
4498c2ecf20Sopenharmony_ci		     le16_to_cpu(us->pusb_dev->descriptor.bcdDevice));
4508c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "Interface Subclass: 0x%02x, Protocol: 0x%02x\n",
4518c2ecf20Sopenharmony_ci		     intf->cur_altsetting->desc.bInterfaceSubClass,
4528c2ecf20Sopenharmony_ci		     intf->cur_altsetting->desc.bInterfaceProtocol);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci	/* Store our private data in the interface */
4558c2ecf20Sopenharmony_ci	usb_set_intfdata(intf, us);
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/* Allocate the control/setup and DMA-mapped buffers */
4588c2ecf20Sopenharmony_ci	us->cr = kmalloc(sizeof(*us->cr), GFP_KERNEL);
4598c2ecf20Sopenharmony_ci	if (!us->cr)
4608c2ecf20Sopenharmony_ci		return -ENOMEM;
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	us->iobuf = usb_alloc_coherent(us->pusb_dev, US_IOBUF_SIZE,
4638c2ecf20Sopenharmony_ci			GFP_KERNEL, &us->iobuf_dma);
4648c2ecf20Sopenharmony_ci	if (!us->iobuf) {
4658c2ecf20Sopenharmony_ci		usb_stor_dbg(us, "I/O buffer allocation failed\n");
4668c2ecf20Sopenharmony_ci		return -ENOMEM;
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci	return 0;
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci/* Works only for digits and letters, but small and fast */
4728c2ecf20Sopenharmony_ci#define TOLOWER(x) ((x) | 0x20)
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci/* Adjust device flags based on the "quirks=" module parameter */
4758c2ecf20Sopenharmony_civoid usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	char *p;
4788c2ecf20Sopenharmony_ci	u16 vid = le16_to_cpu(udev->descriptor.idVendor);
4798c2ecf20Sopenharmony_ci	u16 pid = le16_to_cpu(udev->descriptor.idProduct);
4808c2ecf20Sopenharmony_ci	unsigned f = 0;
4818c2ecf20Sopenharmony_ci	unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
4828c2ecf20Sopenharmony_ci			US_FL_FIX_CAPACITY | US_FL_IGNORE_UAS |
4838c2ecf20Sopenharmony_ci			US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
4848c2ecf20Sopenharmony_ci			US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
4858c2ecf20Sopenharmony_ci			US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
4868c2ecf20Sopenharmony_ci			US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
4878c2ecf20Sopenharmony_ci			US_FL_NO_READ_DISC_INFO | US_FL_NO_READ_CAPACITY_16 |
4888c2ecf20Sopenharmony_ci			US_FL_INITIAL_READ10 | US_FL_WRITE_CACHE |
4898c2ecf20Sopenharmony_ci			US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES |
4908c2ecf20Sopenharmony_ci			US_FL_MAX_SECTORS_240 | US_FL_NO_REPORT_LUNS |
4918c2ecf20Sopenharmony_ci			US_FL_ALWAYS_SYNC);
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	p = quirks;
4948c2ecf20Sopenharmony_ci	while (*p) {
4958c2ecf20Sopenharmony_ci		/* Each entry consists of VID:PID:flags */
4968c2ecf20Sopenharmony_ci		if (vid == simple_strtoul(p, &p, 16) &&
4978c2ecf20Sopenharmony_ci				*p == ':' &&
4988c2ecf20Sopenharmony_ci				pid == simple_strtoul(p+1, &p, 16) &&
4998c2ecf20Sopenharmony_ci				*p == ':')
5008c2ecf20Sopenharmony_ci			break;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci		/* Move forward to the next entry */
5038c2ecf20Sopenharmony_ci		while (*p) {
5048c2ecf20Sopenharmony_ci			if (*p++ == ',')
5058c2ecf20Sopenharmony_ci				break;
5068c2ecf20Sopenharmony_ci		}
5078c2ecf20Sopenharmony_ci	}
5088c2ecf20Sopenharmony_ci	if (!*p)	/* No match */
5098c2ecf20Sopenharmony_ci		return;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	/* Collect the flags */
5128c2ecf20Sopenharmony_ci	while (*++p && *p != ',') {
5138c2ecf20Sopenharmony_ci		switch (TOLOWER(*p)) {
5148c2ecf20Sopenharmony_ci		case 'a':
5158c2ecf20Sopenharmony_ci			f |= US_FL_SANE_SENSE;
5168c2ecf20Sopenharmony_ci			break;
5178c2ecf20Sopenharmony_ci		case 'b':
5188c2ecf20Sopenharmony_ci			f |= US_FL_BAD_SENSE;
5198c2ecf20Sopenharmony_ci			break;
5208c2ecf20Sopenharmony_ci		case 'c':
5218c2ecf20Sopenharmony_ci			f |= US_FL_FIX_CAPACITY;
5228c2ecf20Sopenharmony_ci			break;
5238c2ecf20Sopenharmony_ci		case 'd':
5248c2ecf20Sopenharmony_ci			f |= US_FL_NO_READ_DISC_INFO;
5258c2ecf20Sopenharmony_ci			break;
5268c2ecf20Sopenharmony_ci		case 'e':
5278c2ecf20Sopenharmony_ci			f |= US_FL_NO_READ_CAPACITY_16;
5288c2ecf20Sopenharmony_ci			break;
5298c2ecf20Sopenharmony_ci		case 'f':
5308c2ecf20Sopenharmony_ci			f |= US_FL_NO_REPORT_OPCODES;
5318c2ecf20Sopenharmony_ci			break;
5328c2ecf20Sopenharmony_ci		case 'g':
5338c2ecf20Sopenharmony_ci			f |= US_FL_MAX_SECTORS_240;
5348c2ecf20Sopenharmony_ci			break;
5358c2ecf20Sopenharmony_ci		case 'h':
5368c2ecf20Sopenharmony_ci			f |= US_FL_CAPACITY_HEURISTICS;
5378c2ecf20Sopenharmony_ci			break;
5388c2ecf20Sopenharmony_ci		case 'i':
5398c2ecf20Sopenharmony_ci			f |= US_FL_IGNORE_DEVICE;
5408c2ecf20Sopenharmony_ci			break;
5418c2ecf20Sopenharmony_ci		case 'j':
5428c2ecf20Sopenharmony_ci			f |= US_FL_NO_REPORT_LUNS;
5438c2ecf20Sopenharmony_ci			break;
5448c2ecf20Sopenharmony_ci		case 'k':
5458c2ecf20Sopenharmony_ci			f |= US_FL_NO_SAME;
5468c2ecf20Sopenharmony_ci			break;
5478c2ecf20Sopenharmony_ci		case 'l':
5488c2ecf20Sopenharmony_ci			f |= US_FL_NOT_LOCKABLE;
5498c2ecf20Sopenharmony_ci			break;
5508c2ecf20Sopenharmony_ci		case 'm':
5518c2ecf20Sopenharmony_ci			f |= US_FL_MAX_SECTORS_64;
5528c2ecf20Sopenharmony_ci			break;
5538c2ecf20Sopenharmony_ci		case 'n':
5548c2ecf20Sopenharmony_ci			f |= US_FL_INITIAL_READ10;
5558c2ecf20Sopenharmony_ci			break;
5568c2ecf20Sopenharmony_ci		case 'o':
5578c2ecf20Sopenharmony_ci			f |= US_FL_CAPACITY_OK;
5588c2ecf20Sopenharmony_ci			break;
5598c2ecf20Sopenharmony_ci		case 'p':
5608c2ecf20Sopenharmony_ci			f |= US_FL_WRITE_CACHE;
5618c2ecf20Sopenharmony_ci			break;
5628c2ecf20Sopenharmony_ci		case 'r':
5638c2ecf20Sopenharmony_ci			f |= US_FL_IGNORE_RESIDUE;
5648c2ecf20Sopenharmony_ci			break;
5658c2ecf20Sopenharmony_ci		case 's':
5668c2ecf20Sopenharmony_ci			f |= US_FL_SINGLE_LUN;
5678c2ecf20Sopenharmony_ci			break;
5688c2ecf20Sopenharmony_ci		case 't':
5698c2ecf20Sopenharmony_ci			f |= US_FL_NO_ATA_1X;
5708c2ecf20Sopenharmony_ci			break;
5718c2ecf20Sopenharmony_ci		case 'u':
5728c2ecf20Sopenharmony_ci			f |= US_FL_IGNORE_UAS;
5738c2ecf20Sopenharmony_ci			break;
5748c2ecf20Sopenharmony_ci		case 'w':
5758c2ecf20Sopenharmony_ci			f |= US_FL_NO_WP_DETECT;
5768c2ecf20Sopenharmony_ci			break;
5778c2ecf20Sopenharmony_ci		case 'y':
5788c2ecf20Sopenharmony_ci			f |= US_FL_ALWAYS_SYNC;
5798c2ecf20Sopenharmony_ci			break;
5808c2ecf20Sopenharmony_ci		/* Ignore unrecognized flag characters */
5818c2ecf20Sopenharmony_ci		}
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci	*fflags = (*fflags & ~mask) | f;
5848c2ecf20Sopenharmony_ci}
5858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_adjust_quirks);
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_ci/* Get the unusual_devs entries and the string descriptors */
5888c2ecf20Sopenharmony_cistatic int get_device_info(struct us_data *us, const struct usb_device_id *id,
5898c2ecf20Sopenharmony_ci		const struct us_unusual_dev *unusual_dev)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	struct usb_device *dev = us->pusb_dev;
5928c2ecf20Sopenharmony_ci	struct usb_interface_descriptor *idesc =
5938c2ecf20Sopenharmony_ci		&us->pusb_intf->cur_altsetting->desc;
5948c2ecf20Sopenharmony_ci	struct device *pdev = &us->pusb_intf->dev;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	/* Store the entries */
5978c2ecf20Sopenharmony_ci	us->unusual_dev = unusual_dev;
5988c2ecf20Sopenharmony_ci	us->subclass = (unusual_dev->useProtocol == USB_SC_DEVICE) ?
5998c2ecf20Sopenharmony_ci			idesc->bInterfaceSubClass :
6008c2ecf20Sopenharmony_ci			unusual_dev->useProtocol;
6018c2ecf20Sopenharmony_ci	us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ?
6028c2ecf20Sopenharmony_ci			idesc->bInterfaceProtocol :
6038c2ecf20Sopenharmony_ci			unusual_dev->useTransport;
6048c2ecf20Sopenharmony_ci	us->fflags = id->driver_info;
6058c2ecf20Sopenharmony_ci	usb_stor_adjust_quirks(us->pusb_dev, &us->fflags);
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	if (us->fflags & US_FL_IGNORE_DEVICE) {
6088c2ecf20Sopenharmony_ci		dev_info(pdev, "device ignored\n");
6098c2ecf20Sopenharmony_ci		return -ENODEV;
6108c2ecf20Sopenharmony_ci	}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	/*
6138c2ecf20Sopenharmony_ci	 * This flag is only needed when we're in high-speed, so let's
6148c2ecf20Sopenharmony_ci	 * disable it if we're in full-speed
6158c2ecf20Sopenharmony_ci	 */
6168c2ecf20Sopenharmony_ci	if (dev->speed != USB_SPEED_HIGH)
6178c2ecf20Sopenharmony_ci		us->fflags &= ~US_FL_GO_SLOW;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	if (us->fflags)
6208c2ecf20Sopenharmony_ci		dev_info(pdev, "Quirks match for vid %04x pid %04x: %lx\n",
6218c2ecf20Sopenharmony_ci				le16_to_cpu(dev->descriptor.idVendor),
6228c2ecf20Sopenharmony_ci				le16_to_cpu(dev->descriptor.idProduct),
6238c2ecf20Sopenharmony_ci				us->fflags);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	/*
6268c2ecf20Sopenharmony_ci	 * Log a message if a non-generic unusual_dev entry contains an
6278c2ecf20Sopenharmony_ci	 * unnecessary subclass or protocol override.  This may stimulate
6288c2ecf20Sopenharmony_ci	 * reports from users that will help us remove unneeded entries
6298c2ecf20Sopenharmony_ci	 * from the unusual_devs.h table.
6308c2ecf20Sopenharmony_ci	 */
6318c2ecf20Sopenharmony_ci	if (id->idVendor || id->idProduct) {
6328c2ecf20Sopenharmony_ci		static const char *msgs[3] = {
6338c2ecf20Sopenharmony_ci			"an unneeded SubClass entry",
6348c2ecf20Sopenharmony_ci			"an unneeded Protocol entry",
6358c2ecf20Sopenharmony_ci			"unneeded SubClass and Protocol entries"};
6368c2ecf20Sopenharmony_ci		struct usb_device_descriptor *ddesc = &dev->descriptor;
6378c2ecf20Sopenharmony_ci		int msg = -1;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci		if (unusual_dev->useProtocol != USB_SC_DEVICE &&
6408c2ecf20Sopenharmony_ci			us->subclass == idesc->bInterfaceSubClass)
6418c2ecf20Sopenharmony_ci			msg += 1;
6428c2ecf20Sopenharmony_ci		if (unusual_dev->useTransport != USB_PR_DEVICE &&
6438c2ecf20Sopenharmony_ci			us->protocol == idesc->bInterfaceProtocol)
6448c2ecf20Sopenharmony_ci			msg += 2;
6458c2ecf20Sopenharmony_ci		if (msg >= 0 && !(us->fflags & US_FL_NEED_OVERRIDE))
6468c2ecf20Sopenharmony_ci			dev_notice(pdev, "This device "
6478c2ecf20Sopenharmony_ci					"(%04x,%04x,%04x S %02x P %02x)"
6488c2ecf20Sopenharmony_ci					" has %s in unusual_devs.h (kernel"
6498c2ecf20Sopenharmony_ci					" %s)\n"
6508c2ecf20Sopenharmony_ci					"   Please send a copy of this message to "
6518c2ecf20Sopenharmony_ci					"<linux-usb@vger.kernel.org> and "
6528c2ecf20Sopenharmony_ci					"<usb-storage@lists.one-eyed-alien.net>\n",
6538c2ecf20Sopenharmony_ci					le16_to_cpu(ddesc->idVendor),
6548c2ecf20Sopenharmony_ci					le16_to_cpu(ddesc->idProduct),
6558c2ecf20Sopenharmony_ci					le16_to_cpu(ddesc->bcdDevice),
6568c2ecf20Sopenharmony_ci					idesc->bInterfaceSubClass,
6578c2ecf20Sopenharmony_ci					idesc->bInterfaceProtocol,
6588c2ecf20Sopenharmony_ci					msgs[msg],
6598c2ecf20Sopenharmony_ci					utsname()->release);
6608c2ecf20Sopenharmony_ci	}
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	return 0;
6638c2ecf20Sopenharmony_ci}
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci/* Get the transport settings */
6668c2ecf20Sopenharmony_cistatic void get_transport(struct us_data *us)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	switch (us->protocol) {
6698c2ecf20Sopenharmony_ci	case USB_PR_CB:
6708c2ecf20Sopenharmony_ci		us->transport_name = "Control/Bulk";
6718c2ecf20Sopenharmony_ci		us->transport = usb_stor_CB_transport;
6728c2ecf20Sopenharmony_ci		us->transport_reset = usb_stor_CB_reset;
6738c2ecf20Sopenharmony_ci		us->max_lun = 7;
6748c2ecf20Sopenharmony_ci		break;
6758c2ecf20Sopenharmony_ci
6768c2ecf20Sopenharmony_ci	case USB_PR_CBI:
6778c2ecf20Sopenharmony_ci		us->transport_name = "Control/Bulk/Interrupt";
6788c2ecf20Sopenharmony_ci		us->transport = usb_stor_CB_transport;
6798c2ecf20Sopenharmony_ci		us->transport_reset = usb_stor_CB_reset;
6808c2ecf20Sopenharmony_ci		us->max_lun = 7;
6818c2ecf20Sopenharmony_ci		break;
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	case USB_PR_BULK:
6848c2ecf20Sopenharmony_ci		us->transport_name = "Bulk";
6858c2ecf20Sopenharmony_ci		us->transport = usb_stor_Bulk_transport;
6868c2ecf20Sopenharmony_ci		us->transport_reset = usb_stor_Bulk_reset;
6878c2ecf20Sopenharmony_ci		break;
6888c2ecf20Sopenharmony_ci	}
6898c2ecf20Sopenharmony_ci}
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci/* Get the protocol settings */
6928c2ecf20Sopenharmony_cistatic void get_protocol(struct us_data *us)
6938c2ecf20Sopenharmony_ci{
6948c2ecf20Sopenharmony_ci	switch (us->subclass) {
6958c2ecf20Sopenharmony_ci	case USB_SC_RBC:
6968c2ecf20Sopenharmony_ci		us->protocol_name = "Reduced Block Commands (RBC)";
6978c2ecf20Sopenharmony_ci		us->proto_handler = usb_stor_transparent_scsi_command;
6988c2ecf20Sopenharmony_ci		break;
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	case USB_SC_8020:
7018c2ecf20Sopenharmony_ci		us->protocol_name = "8020i";
7028c2ecf20Sopenharmony_ci		us->proto_handler = usb_stor_pad12_command;
7038c2ecf20Sopenharmony_ci		us->max_lun = 0;
7048c2ecf20Sopenharmony_ci		break;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	case USB_SC_QIC:
7078c2ecf20Sopenharmony_ci		us->protocol_name = "QIC-157";
7088c2ecf20Sopenharmony_ci		us->proto_handler = usb_stor_pad12_command;
7098c2ecf20Sopenharmony_ci		us->max_lun = 0;
7108c2ecf20Sopenharmony_ci		break;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	case USB_SC_8070:
7138c2ecf20Sopenharmony_ci		us->protocol_name = "8070i";
7148c2ecf20Sopenharmony_ci		us->proto_handler = usb_stor_pad12_command;
7158c2ecf20Sopenharmony_ci		us->max_lun = 0;
7168c2ecf20Sopenharmony_ci		break;
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci	case USB_SC_SCSI:
7198c2ecf20Sopenharmony_ci		us->protocol_name = "Transparent SCSI";
7208c2ecf20Sopenharmony_ci		us->proto_handler = usb_stor_transparent_scsi_command;
7218c2ecf20Sopenharmony_ci		break;
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	case USB_SC_UFI:
7248c2ecf20Sopenharmony_ci		us->protocol_name = "Uniform Floppy Interface (UFI)";
7258c2ecf20Sopenharmony_ci		us->proto_handler = usb_stor_ufi_command;
7268c2ecf20Sopenharmony_ci		break;
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_ci/* Get the pipe settings */
7318c2ecf20Sopenharmony_cistatic int get_pipes(struct us_data *us)
7328c2ecf20Sopenharmony_ci{
7338c2ecf20Sopenharmony_ci	struct usb_host_interface *alt = us->pusb_intf->cur_altsetting;
7348c2ecf20Sopenharmony_ci	struct usb_endpoint_descriptor *ep_in;
7358c2ecf20Sopenharmony_ci	struct usb_endpoint_descriptor *ep_out;
7368c2ecf20Sopenharmony_ci	struct usb_endpoint_descriptor *ep_int;
7378c2ecf20Sopenharmony_ci	int res;
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	/*
7408c2ecf20Sopenharmony_ci	 * Find the first endpoint of each type we need.
7418c2ecf20Sopenharmony_ci	 * We are expecting a minimum of 2 endpoints - in and out (bulk).
7428c2ecf20Sopenharmony_ci	 * An optional interrupt-in is OK (necessary for CBI protocol).
7438c2ecf20Sopenharmony_ci	 * We will ignore any others.
7448c2ecf20Sopenharmony_ci	 */
7458c2ecf20Sopenharmony_ci	res = usb_find_common_endpoints(alt, &ep_in, &ep_out, NULL, NULL);
7468c2ecf20Sopenharmony_ci	if (res) {
7478c2ecf20Sopenharmony_ci		usb_stor_dbg(us, "bulk endpoints not found\n");
7488c2ecf20Sopenharmony_ci		return res;
7498c2ecf20Sopenharmony_ci	}
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	res = usb_find_int_in_endpoint(alt, &ep_int);
7528c2ecf20Sopenharmony_ci	if (res && us->protocol == USB_PR_CBI) {
7538c2ecf20Sopenharmony_ci		usb_stor_dbg(us, "interrupt endpoint not found\n");
7548c2ecf20Sopenharmony_ci		return res;
7558c2ecf20Sopenharmony_ci	}
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	/* Calculate and store the pipe values */
7588c2ecf20Sopenharmony_ci	us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0);
7598c2ecf20Sopenharmony_ci	us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
7608c2ecf20Sopenharmony_ci	us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev,
7618c2ecf20Sopenharmony_ci		usb_endpoint_num(ep_out));
7628c2ecf20Sopenharmony_ci	us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev,
7638c2ecf20Sopenharmony_ci		usb_endpoint_num(ep_in));
7648c2ecf20Sopenharmony_ci	if (ep_int) {
7658c2ecf20Sopenharmony_ci		us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev,
7668c2ecf20Sopenharmony_ci			usb_endpoint_num(ep_int));
7678c2ecf20Sopenharmony_ci		us->ep_bInterval = ep_int->bInterval;
7688c2ecf20Sopenharmony_ci	}
7698c2ecf20Sopenharmony_ci	return 0;
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci/* Initialize all the dynamic resources we need */
7738c2ecf20Sopenharmony_cistatic int usb_stor_acquire_resources(struct us_data *us)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	int p;
7768c2ecf20Sopenharmony_ci	struct task_struct *th;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	us->current_urb = usb_alloc_urb(0, GFP_KERNEL);
7798c2ecf20Sopenharmony_ci	if (!us->current_urb)
7808c2ecf20Sopenharmony_ci		return -ENOMEM;
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_ci	/*
7838c2ecf20Sopenharmony_ci	 * Just before we start our control thread, initialize
7848c2ecf20Sopenharmony_ci	 * the device if it needs initialization
7858c2ecf20Sopenharmony_ci	 */
7868c2ecf20Sopenharmony_ci	if (us->unusual_dev->initFunction) {
7878c2ecf20Sopenharmony_ci		p = us->unusual_dev->initFunction(us);
7888c2ecf20Sopenharmony_ci		if (p)
7898c2ecf20Sopenharmony_ci			return p;
7908c2ecf20Sopenharmony_ci	}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	/* Start up our control thread */
7938c2ecf20Sopenharmony_ci	th = kthread_run(usb_stor_control_thread, us, "usb-storage");
7948c2ecf20Sopenharmony_ci	if (IS_ERR(th)) {
7958c2ecf20Sopenharmony_ci		dev_warn(&us->pusb_intf->dev,
7968c2ecf20Sopenharmony_ci				"Unable to start control thread\n");
7978c2ecf20Sopenharmony_ci		return PTR_ERR(th);
7988c2ecf20Sopenharmony_ci	}
7998c2ecf20Sopenharmony_ci	us->ctl_thread = th;
8008c2ecf20Sopenharmony_ci
8018c2ecf20Sopenharmony_ci	return 0;
8028c2ecf20Sopenharmony_ci}
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci/* Release all our dynamic resources */
8058c2ecf20Sopenharmony_cistatic void usb_stor_release_resources(struct us_data *us)
8068c2ecf20Sopenharmony_ci{
8078c2ecf20Sopenharmony_ci	/*
8088c2ecf20Sopenharmony_ci	 * Tell the control thread to exit.  The SCSI host must
8098c2ecf20Sopenharmony_ci	 * already have been removed and the DISCONNECTING flag set
8108c2ecf20Sopenharmony_ci	 * so that we won't accept any more commands.
8118c2ecf20Sopenharmony_ci	 */
8128c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "-- sending exit command to thread\n");
8138c2ecf20Sopenharmony_ci	complete(&us->cmnd_ready);
8148c2ecf20Sopenharmony_ci	if (us->ctl_thread)
8158c2ecf20Sopenharmony_ci		kthread_stop(us->ctl_thread);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	/* Call the destructor routine, if it exists */
8188c2ecf20Sopenharmony_ci	if (us->extra_destructor) {
8198c2ecf20Sopenharmony_ci		usb_stor_dbg(us, "-- calling extra_destructor()\n");
8208c2ecf20Sopenharmony_ci		us->extra_destructor(us->extra);
8218c2ecf20Sopenharmony_ci	}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	/* Free the extra data and the URB */
8248c2ecf20Sopenharmony_ci	kfree(us->extra);
8258c2ecf20Sopenharmony_ci	usb_free_urb(us->current_urb);
8268c2ecf20Sopenharmony_ci}
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci/* Dissociate from the USB device */
8298c2ecf20Sopenharmony_cistatic void dissociate_dev(struct us_data *us)
8308c2ecf20Sopenharmony_ci{
8318c2ecf20Sopenharmony_ci	/* Free the buffers */
8328c2ecf20Sopenharmony_ci	kfree(us->cr);
8338c2ecf20Sopenharmony_ci	usb_free_coherent(us->pusb_dev, US_IOBUF_SIZE, us->iobuf, us->iobuf_dma);
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	/* Remove our private data from the interface */
8368c2ecf20Sopenharmony_ci	usb_set_intfdata(us->pusb_intf, NULL);
8378c2ecf20Sopenharmony_ci}
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci/*
8408c2ecf20Sopenharmony_ci * First stage of disconnect processing: stop SCSI scanning,
8418c2ecf20Sopenharmony_ci * remove the host, and stop accepting new commands
8428c2ecf20Sopenharmony_ci */
8438c2ecf20Sopenharmony_cistatic void quiesce_and_remove_host(struct us_data *us)
8448c2ecf20Sopenharmony_ci{
8458c2ecf20Sopenharmony_ci	struct Scsi_Host *host = us_to_host(us);
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	/* If the device is really gone, cut short reset delays */
8488c2ecf20Sopenharmony_ci	if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
8498c2ecf20Sopenharmony_ci		set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
8508c2ecf20Sopenharmony_ci		wake_up(&us->delay_wait);
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	/*
8548c2ecf20Sopenharmony_ci	 * Prevent SCSI scanning (if it hasn't started yet)
8558c2ecf20Sopenharmony_ci	 * or wait for the SCSI-scanning routine to stop.
8568c2ecf20Sopenharmony_ci	 */
8578c2ecf20Sopenharmony_ci	cancel_delayed_work_sync(&us->scan_dwork);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	/* Balance autopm calls if scanning was cancelled */
8608c2ecf20Sopenharmony_ci	if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
8618c2ecf20Sopenharmony_ci		usb_autopm_put_interface_no_suspend(us->pusb_intf);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	/*
8648c2ecf20Sopenharmony_ci	 * Removing the host will perform an orderly shutdown: caches
8658c2ecf20Sopenharmony_ci	 * synchronized, disks spun down, etc.
8668c2ecf20Sopenharmony_ci	 */
8678c2ecf20Sopenharmony_ci	scsi_remove_host(host);
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	/*
8708c2ecf20Sopenharmony_ci	 * Prevent any new commands from being accepted and cut short
8718c2ecf20Sopenharmony_ci	 * reset delays.
8728c2ecf20Sopenharmony_ci	 */
8738c2ecf20Sopenharmony_ci	scsi_lock(host);
8748c2ecf20Sopenharmony_ci	set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
8758c2ecf20Sopenharmony_ci	scsi_unlock(host);
8768c2ecf20Sopenharmony_ci	wake_up(&us->delay_wait);
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci/* Second stage of disconnect processing: deallocate all resources */
8808c2ecf20Sopenharmony_cistatic void release_everything(struct us_data *us)
8818c2ecf20Sopenharmony_ci{
8828c2ecf20Sopenharmony_ci	usb_stor_release_resources(us);
8838c2ecf20Sopenharmony_ci	dissociate_dev(us);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	/*
8868c2ecf20Sopenharmony_ci	 * Drop our reference to the host; the SCSI core will free it
8878c2ecf20Sopenharmony_ci	 * (and "us" along with it) when the refcount becomes 0.
8888c2ecf20Sopenharmony_ci	 */
8898c2ecf20Sopenharmony_ci	scsi_host_put(us_to_host(us));
8908c2ecf20Sopenharmony_ci}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci/* Delayed-work routine to carry out SCSI-device scanning */
8938c2ecf20Sopenharmony_cistatic void usb_stor_scan_dwork(struct work_struct *work)
8948c2ecf20Sopenharmony_ci{
8958c2ecf20Sopenharmony_ci	struct us_data *us = container_of(work, struct us_data,
8968c2ecf20Sopenharmony_ci			scan_dwork.work);
8978c2ecf20Sopenharmony_ci	struct device *dev = &us->pusb_intf->dev;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	dev_dbg(dev, "starting scan\n");
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	/* For bulk-only devices, determine the max LUN value */
9028c2ecf20Sopenharmony_ci	if (us->protocol == USB_PR_BULK &&
9038c2ecf20Sopenharmony_ci	    !(us->fflags & US_FL_SINGLE_LUN) &&
9048c2ecf20Sopenharmony_ci	    !(us->fflags & US_FL_SCM_MULT_TARG)) {
9058c2ecf20Sopenharmony_ci		mutex_lock(&us->dev_mutex);
9068c2ecf20Sopenharmony_ci		us->max_lun = usb_stor_Bulk_max_lun(us);
9078c2ecf20Sopenharmony_ci		/*
9088c2ecf20Sopenharmony_ci		 * Allow proper scanning of devices that present more than 8 LUNs
9098c2ecf20Sopenharmony_ci		 * While not affecting other devices that may need the previous
9108c2ecf20Sopenharmony_ci		 * behavior
9118c2ecf20Sopenharmony_ci		 */
9128c2ecf20Sopenharmony_ci		if (us->max_lun >= 8)
9138c2ecf20Sopenharmony_ci			us_to_host(us)->max_lun = us->max_lun+1;
9148c2ecf20Sopenharmony_ci		mutex_unlock(&us->dev_mutex);
9158c2ecf20Sopenharmony_ci	}
9168c2ecf20Sopenharmony_ci	scsi_scan_host(us_to_host(us));
9178c2ecf20Sopenharmony_ci	dev_dbg(dev, "scan complete\n");
9188c2ecf20Sopenharmony_ci
9198c2ecf20Sopenharmony_ci	/* Should we unbind if no devices were detected? */
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	usb_autopm_put_interface(us->pusb_intf);
9228c2ecf20Sopenharmony_ci	clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
9268c2ecf20Sopenharmony_ci{
9278c2ecf20Sopenharmony_ci	struct usb_device *usb_dev = interface_to_usbdev(intf);
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	if (usb_dev->bus->sg_tablesize) {
9308c2ecf20Sopenharmony_ci		return usb_dev->bus->sg_tablesize;
9318c2ecf20Sopenharmony_ci	}
9328c2ecf20Sopenharmony_ci	return SG_ALL;
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci/* First part of general USB mass-storage probing */
9368c2ecf20Sopenharmony_ciint usb_stor_probe1(struct us_data **pus,
9378c2ecf20Sopenharmony_ci		struct usb_interface *intf,
9388c2ecf20Sopenharmony_ci		const struct usb_device_id *id,
9398c2ecf20Sopenharmony_ci		const struct us_unusual_dev *unusual_dev,
9408c2ecf20Sopenharmony_ci		struct scsi_host_template *sht)
9418c2ecf20Sopenharmony_ci{
9428c2ecf20Sopenharmony_ci	struct Scsi_Host *host;
9438c2ecf20Sopenharmony_ci	struct us_data *us;
9448c2ecf20Sopenharmony_ci	int result;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	dev_info(&intf->dev, "USB Mass Storage device detected\n");
9478c2ecf20Sopenharmony_ci
9488c2ecf20Sopenharmony_ci	/*
9498c2ecf20Sopenharmony_ci	 * Ask the SCSI layer to allocate a host structure, with extra
9508c2ecf20Sopenharmony_ci	 * space at the end for our private us_data structure.
9518c2ecf20Sopenharmony_ci	 */
9528c2ecf20Sopenharmony_ci	host = scsi_host_alloc(sht, sizeof(*us));
9538c2ecf20Sopenharmony_ci	if (!host) {
9548c2ecf20Sopenharmony_ci		dev_warn(&intf->dev, "Unable to allocate the scsi host\n");
9558c2ecf20Sopenharmony_ci		return -ENOMEM;
9568c2ecf20Sopenharmony_ci	}
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	/*
9598c2ecf20Sopenharmony_ci	 * Allow 16-byte CDBs and thus > 2TB
9608c2ecf20Sopenharmony_ci	 */
9618c2ecf20Sopenharmony_ci	host->max_cmd_len = 16;
9628c2ecf20Sopenharmony_ci	host->sg_tablesize = usb_stor_sg_tablesize(intf);
9638c2ecf20Sopenharmony_ci	*pus = us = host_to_us(host);
9648c2ecf20Sopenharmony_ci	mutex_init(&(us->dev_mutex));
9658c2ecf20Sopenharmony_ci	us_set_lock_class(&us->dev_mutex, intf);
9668c2ecf20Sopenharmony_ci	init_completion(&us->cmnd_ready);
9678c2ecf20Sopenharmony_ci	init_completion(&(us->notify));
9688c2ecf20Sopenharmony_ci	init_waitqueue_head(&us->delay_wait);
9698c2ecf20Sopenharmony_ci	INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci	/* Associate the us_data structure with the USB device */
9728c2ecf20Sopenharmony_ci	result = associate_dev(us, intf);
9738c2ecf20Sopenharmony_ci	if (result)
9748c2ecf20Sopenharmony_ci		goto BadDevice;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	/* Get the unusual_devs entries and the descriptors */
9778c2ecf20Sopenharmony_ci	result = get_device_info(us, id, unusual_dev);
9788c2ecf20Sopenharmony_ci	if (result)
9798c2ecf20Sopenharmony_ci		goto BadDevice;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	/* Get standard transport and protocol settings */
9828c2ecf20Sopenharmony_ci	get_transport(us);
9838c2ecf20Sopenharmony_ci	get_protocol(us);
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	/*
9868c2ecf20Sopenharmony_ci	 * Give the caller a chance to fill in specialized transport
9878c2ecf20Sopenharmony_ci	 * or protocol settings.
9888c2ecf20Sopenharmony_ci	 */
9898c2ecf20Sopenharmony_ci	return 0;
9908c2ecf20Sopenharmony_ci
9918c2ecf20Sopenharmony_ciBadDevice:
9928c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "storage_probe() failed\n");
9938c2ecf20Sopenharmony_ci	release_everything(us);
9948c2ecf20Sopenharmony_ci	return result;
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_probe1);
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci/* Second part of general USB mass-storage probing */
9998c2ecf20Sopenharmony_ciint usb_stor_probe2(struct us_data *us)
10008c2ecf20Sopenharmony_ci{
10018c2ecf20Sopenharmony_ci	int result;
10028c2ecf20Sopenharmony_ci	struct device *dev = &us->pusb_intf->dev;
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci	/* Make sure the transport and protocol have both been set */
10058c2ecf20Sopenharmony_ci	if (!us->transport || !us->proto_handler) {
10068c2ecf20Sopenharmony_ci		result = -ENXIO;
10078c2ecf20Sopenharmony_ci		goto BadDevice;
10088c2ecf20Sopenharmony_ci	}
10098c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "Transport: %s\n", us->transport_name);
10108c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "Protocol: %s\n", us->protocol_name);
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	if (us->fflags & US_FL_SCM_MULT_TARG) {
10138c2ecf20Sopenharmony_ci		/*
10148c2ecf20Sopenharmony_ci		 * SCM eUSCSI bridge devices can have different numbers
10158c2ecf20Sopenharmony_ci		 * of LUNs on different targets; allow all to be probed.
10168c2ecf20Sopenharmony_ci		 */
10178c2ecf20Sopenharmony_ci		us->max_lun = 7;
10188c2ecf20Sopenharmony_ci		/* The eUSCSI itself has ID 7, so avoid scanning that */
10198c2ecf20Sopenharmony_ci		us_to_host(us)->this_id = 7;
10208c2ecf20Sopenharmony_ci		/* max_id is 8 initially, so no need to set it here */
10218c2ecf20Sopenharmony_ci	} else {
10228c2ecf20Sopenharmony_ci		/* In the normal case there is only a single target */
10238c2ecf20Sopenharmony_ci		us_to_host(us)->max_id = 1;
10248c2ecf20Sopenharmony_ci		/*
10258c2ecf20Sopenharmony_ci		 * Like Windows, we won't store the LUN bits in CDB[1] for
10268c2ecf20Sopenharmony_ci		 * SCSI-2 devices using the Bulk-Only transport (even though
10278c2ecf20Sopenharmony_ci		 * this violates the SCSI spec).
10288c2ecf20Sopenharmony_ci		 */
10298c2ecf20Sopenharmony_ci		if (us->transport == usb_stor_Bulk_transport)
10308c2ecf20Sopenharmony_ci			us_to_host(us)->no_scsi2_lun_in_cdb = 1;
10318c2ecf20Sopenharmony_ci	}
10328c2ecf20Sopenharmony_ci
10338c2ecf20Sopenharmony_ci	/* fix for single-lun devices */
10348c2ecf20Sopenharmony_ci	if (us->fflags & US_FL_SINGLE_LUN)
10358c2ecf20Sopenharmony_ci		us->max_lun = 0;
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	/* Find the endpoints and calculate pipe values */
10388c2ecf20Sopenharmony_ci	result = get_pipes(us);
10398c2ecf20Sopenharmony_ci	if (result)
10408c2ecf20Sopenharmony_ci		goto BadDevice;
10418c2ecf20Sopenharmony_ci
10428c2ecf20Sopenharmony_ci	/*
10438c2ecf20Sopenharmony_ci	 * If the device returns invalid data for the first READ(10)
10448c2ecf20Sopenharmony_ci	 * command, indicate the command should be retried.
10458c2ecf20Sopenharmony_ci	 */
10468c2ecf20Sopenharmony_ci	if (us->fflags & US_FL_INITIAL_READ10)
10478c2ecf20Sopenharmony_ci		set_bit(US_FLIDX_REDO_READ10, &us->dflags);
10488c2ecf20Sopenharmony_ci
10498c2ecf20Sopenharmony_ci	/* Acquire all the other resources and add the host */
10508c2ecf20Sopenharmony_ci	result = usb_stor_acquire_resources(us);
10518c2ecf20Sopenharmony_ci	if (result)
10528c2ecf20Sopenharmony_ci		goto BadDevice;
10538c2ecf20Sopenharmony_ci	usb_autopm_get_interface_no_resume(us->pusb_intf);
10548c2ecf20Sopenharmony_ci	snprintf(us->scsi_name, sizeof(us->scsi_name), "usb-storage %s",
10558c2ecf20Sopenharmony_ci					dev_name(&us->pusb_intf->dev));
10568c2ecf20Sopenharmony_ci	result = scsi_add_host(us_to_host(us), dev);
10578c2ecf20Sopenharmony_ci	if (result) {
10588c2ecf20Sopenharmony_ci		dev_warn(dev,
10598c2ecf20Sopenharmony_ci				"Unable to add the scsi host\n");
10608c2ecf20Sopenharmony_ci		goto HostAddErr;
10618c2ecf20Sopenharmony_ci	}
10628c2ecf20Sopenharmony_ci
10638c2ecf20Sopenharmony_ci	/* Submit the delayed_work for SCSI-device scanning */
10648c2ecf20Sopenharmony_ci	set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	if (delay_use > 0)
10678c2ecf20Sopenharmony_ci		dev_dbg(dev, "waiting for device to settle before scanning\n");
10688c2ecf20Sopenharmony_ci	queue_delayed_work(system_freezable_wq, &us->scan_dwork,
10698c2ecf20Sopenharmony_ci			delay_use * HZ);
10708c2ecf20Sopenharmony_ci	return 0;
10718c2ecf20Sopenharmony_ci
10728c2ecf20Sopenharmony_ci	/* We come here if there are any problems */
10738c2ecf20Sopenharmony_ciHostAddErr:
10748c2ecf20Sopenharmony_ci	usb_autopm_put_interface_no_suspend(us->pusb_intf);
10758c2ecf20Sopenharmony_ciBadDevice:
10768c2ecf20Sopenharmony_ci	usb_stor_dbg(us, "storage_probe() failed\n");
10778c2ecf20Sopenharmony_ci	release_everything(us);
10788c2ecf20Sopenharmony_ci	return result;
10798c2ecf20Sopenharmony_ci}
10808c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_probe2);
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci/* Handle a USB mass-storage disconnect */
10838c2ecf20Sopenharmony_civoid usb_stor_disconnect(struct usb_interface *intf)
10848c2ecf20Sopenharmony_ci{
10858c2ecf20Sopenharmony_ci	struct us_data *us = usb_get_intfdata(intf);
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	quiesce_and_remove_host(us);
10888c2ecf20Sopenharmony_ci	release_everything(us);
10898c2ecf20Sopenharmony_ci}
10908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(usb_stor_disconnect);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_cistatic struct scsi_host_template usb_stor_host_template;
10938c2ecf20Sopenharmony_ci
10948c2ecf20Sopenharmony_ci/* The main probe routine for standard devices */
10958c2ecf20Sopenharmony_cistatic int storage_probe(struct usb_interface *intf,
10968c2ecf20Sopenharmony_ci			 const struct usb_device_id *id)
10978c2ecf20Sopenharmony_ci{
10988c2ecf20Sopenharmony_ci	const struct us_unusual_dev *unusual_dev;
10998c2ecf20Sopenharmony_ci	struct us_data *us;
11008c2ecf20Sopenharmony_ci	int result;
11018c2ecf20Sopenharmony_ci	int size;
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci	/* If uas is enabled and this device can do uas then ignore it. */
11048c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_USB_UAS)
11058c2ecf20Sopenharmony_ci	if (uas_use_uas_driver(intf, id, NULL))
11068c2ecf20Sopenharmony_ci		return -ENXIO;
11078c2ecf20Sopenharmony_ci#endif
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	/*
11108c2ecf20Sopenharmony_ci	 * If the device isn't standard (is handled by a subdriver
11118c2ecf20Sopenharmony_ci	 * module) then don't accept it.
11128c2ecf20Sopenharmony_ci	 */
11138c2ecf20Sopenharmony_ci	if (usb_usual_ignore_device(intf))
11148c2ecf20Sopenharmony_ci		return -ENXIO;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	/*
11178c2ecf20Sopenharmony_ci	 * Call the general probe procedures.
11188c2ecf20Sopenharmony_ci	 *
11198c2ecf20Sopenharmony_ci	 * The unusual_dev_list array is parallel to the usb_storage_usb_ids
11208c2ecf20Sopenharmony_ci	 * table, so we use the index of the id entry to find the
11218c2ecf20Sopenharmony_ci	 * corresponding unusual_devs entry.
11228c2ecf20Sopenharmony_ci	 */
11238c2ecf20Sopenharmony_ci
11248c2ecf20Sopenharmony_ci	size = ARRAY_SIZE(us_unusual_dev_list);
11258c2ecf20Sopenharmony_ci	if (id >= usb_storage_usb_ids && id < usb_storage_usb_ids + size) {
11268c2ecf20Sopenharmony_ci		unusual_dev = (id - usb_storage_usb_ids) + us_unusual_dev_list;
11278c2ecf20Sopenharmony_ci	} else {
11288c2ecf20Sopenharmony_ci		unusual_dev = &for_dynamic_ids;
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ci		dev_dbg(&intf->dev, "Use Bulk-Only transport with the Transparent SCSI protocol for dynamic id: 0x%04x 0x%04x\n",
11318c2ecf20Sopenharmony_ci			id->idVendor, id->idProduct);
11328c2ecf20Sopenharmony_ci	}
11338c2ecf20Sopenharmony_ci
11348c2ecf20Sopenharmony_ci	result = usb_stor_probe1(&us, intf, id, unusual_dev,
11358c2ecf20Sopenharmony_ci				 &usb_stor_host_template);
11368c2ecf20Sopenharmony_ci	if (result)
11378c2ecf20Sopenharmony_ci		return result;
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci	/* No special transport or protocol settings in the main module */
11408c2ecf20Sopenharmony_ci
11418c2ecf20Sopenharmony_ci	result = usb_stor_probe2(us);
11428c2ecf20Sopenharmony_ci	return result;
11438c2ecf20Sopenharmony_ci}
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_cistatic struct usb_driver usb_storage_driver = {
11468c2ecf20Sopenharmony_ci	.name =		DRV_NAME,
11478c2ecf20Sopenharmony_ci	.probe =	storage_probe,
11488c2ecf20Sopenharmony_ci	.disconnect =	usb_stor_disconnect,
11498c2ecf20Sopenharmony_ci	.suspend =	usb_stor_suspend,
11508c2ecf20Sopenharmony_ci	.resume =	usb_stor_resume,
11518c2ecf20Sopenharmony_ci	.reset_resume =	usb_stor_reset_resume,
11528c2ecf20Sopenharmony_ci	.pre_reset =	usb_stor_pre_reset,
11538c2ecf20Sopenharmony_ci	.post_reset =	usb_stor_post_reset,
11548c2ecf20Sopenharmony_ci	.id_table =	usb_storage_usb_ids,
11558c2ecf20Sopenharmony_ci	.supports_autosuspend = 1,
11568c2ecf20Sopenharmony_ci	.soft_unbind =	1,
11578c2ecf20Sopenharmony_ci};
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_cimodule_usb_stor_driver(usb_storage_driver, usb_stor_host_template, DRV_NAME);
1160