summaryrefslogtreecommitdiff
path: root/drivers/usb/storage/uas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/storage/uas.c')
-rw-r--r--drivers/usb/storage/uas.c200
1 files changed, 115 insertions, 85 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index d592071119ba..73b1981cb1d5 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -21,6 +21,7 @@
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_devinfo.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
@@ -37,7 +38,7 @@ struct uas_dev_info {
struct usb_anchor cmd_urbs;
struct usb_anchor sense_urbs;
struct usb_anchor data_urbs;
- unsigned long flags;
+ u64 flags;
int qdepth, resetting;
unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
unsigned use_streams:1;
@@ -113,7 +114,7 @@ static void uas_do_work(struct work_struct *work)
continue;
cmnd = devinfo->cmnd[i];
- cmdinfo = (void *)&cmnd->SCp;
+ cmdinfo = scsi_cmd_priv(cmnd);
if (!(cmdinfo->state & IS_IN_WORK_LIST))
continue;
@@ -139,10 +140,9 @@ static void uas_scan_work(struct work_struct *work)
dev_dbg(&devinfo->intf->dev, "scan complete\n");
}
-static void uas_add_work(struct uas_cmd_info *cmdinfo)
+static void uas_add_work(struct scsi_cmnd *cmnd)
{
- struct scsi_pointer *scp = (void *)cmdinfo;
- struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct uas_dev_info *devinfo = cmnd->device->hostdata;
lockdep_assert_held(&devinfo->lock);
@@ -163,7 +163,7 @@ static void uas_zap_pending(struct uas_dev_info *devinfo, int result)
continue;
cmnd = devinfo->cmnd[i];
- cmdinfo = (void *)&cmnd->SCp;
+ cmdinfo = scsi_cmd_priv(cmnd);
uas_log_cmd_state(cmnd, __func__, 0);
/* Sense urbs were killed, clear COMMAND_INFLIGHT manually */
cmdinfo->state &= ~COMMAND_INFLIGHT;
@@ -200,15 +200,14 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
int status)
{
- struct uas_cmd_info *ci = (void *)&cmnd->SCp;
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *ci = scsi_cmd_priv(cmnd);
if (status == -ENODEV) /* too late */
return;
scmd_printk(KERN_INFO, cmnd,
"%s %d uas-tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
- prefix, status, cmdinfo->uas_tag,
+ prefix, status, ci->uas_tag,
(ci->state & SUBMIT_STATUS_URB) ? " s-st" : "",
(ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "",
(ci->state & SUBMIT_DATA_IN_URB) ? " s-in" : "",
@@ -231,7 +230,7 @@ static void uas_free_unsubmitted_urbs(struct scsi_cmnd *cmnd)
if (!cmnd)
return;
- cmdinfo = (void *)&cmnd->SCp;
+ cmdinfo = scsi_cmd_priv(cmnd);
if (cmdinfo->state & SUBMIT_CMD_URB)
usb_free_urb(cmdinfo->cmd_urb);
@@ -245,7 +244,7 @@ static void uas_free_unsubmitted_urbs(struct scsi_cmnd *cmnd)
static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
{
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
lockdep_assert_held(&devinfo->lock);
@@ -256,20 +255,20 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
return -EBUSY;
devinfo->cmnd[cmdinfo->uas_tag - 1] = NULL;
uas_free_unsubmitted_urbs(cmnd);
- cmnd->scsi_done(cmnd);
+ scsi_done(cmnd);
return 0;
}
static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
unsigned direction)
{
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
int err;
cmdinfo->state |= direction | SUBMIT_STATUS_URB;
err = uas_submit_urbs(cmnd, cmnd->device->hostdata);
if (err) {
- uas_add_work(cmdinfo);
+ uas_add_work(cmnd);
}
}
@@ -279,17 +278,17 @@ static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd *
switch (response_code) {
case RC_INCORRECT_LUN:
- cmnd->result = DID_BAD_TARGET << 16;
+ set_host_byte(cmnd, DID_BAD_TARGET);
break;
case RC_TMF_SUCCEEDED:
- cmnd->result = DID_OK << 16;
+ set_host_byte(cmnd, DID_OK);
break;
case RC_TMF_NOT_SUPPORTED:
- cmnd->result = DID_TARGET_FAILURE << 16;
+ set_host_byte(cmnd, DID_BAD_TARGET);
break;
default:
uas_log_cmd_state(cmnd, "response iu", response_code);
- cmnd->result = DID_ERROR << 16;
+ set_host_byte(cmnd, DID_ERROR);
break;
}
@@ -310,18 +309,18 @@ static void uas_stat_cmplt(struct urb *urb)
int status = urb->status;
bool success;
- spin_lock_irqsave(&devinfo->lock, flags);
-
- if (devinfo->resetting)
- goto out;
-
if (status) {
if (status != -ENOENT && status != -ECONNRESET && status != -ESHUTDOWN)
dev_err(&urb->dev->dev, "stat urb: status %d\n", status);
- goto out;
+ goto bail;
}
idx = be16_to_cpup(&iu->tag) - 1;
+
+ spin_lock_irqsave(&devinfo->lock, flags);
+
+ if (devinfo->resetting)
+ goto out;
if (idx >= MAX_CMNDS || !devinfo->cmnd[idx]) {
dev_err(&urb->dev->dev,
"stat urb: no pending cmd for uas-tag %d\n", idx + 1);
@@ -329,7 +328,7 @@ static void uas_stat_cmplt(struct urb *urb)
}
cmnd = devinfo->cmnd[idx];
- cmdinfo = (void *)&cmnd->SCp;
+ cmdinfo = scsi_cmd_priv(cmnd);
if (!(cmdinfo->state & COMMAND_INFLIGHT)) {
uas_log_cmd_state(cmnd, "unexpected status cmplt", 0);
@@ -376,9 +375,8 @@ static void uas_stat_cmplt(struct urb *urb)
default:
uas_log_cmd_state(cmnd, "bogus IU", iu->iu_id);
}
-out:
- usb_free_urb(urb);
spin_unlock_irqrestore(&devinfo->lock, flags);
+ usb_free_urb(urb);
/* Unlinking of data urbs must be done without holding the lock */
if (data_in_urb) {
@@ -389,12 +387,18 @@ out:
usb_unlink_urb(data_out_urb);
usb_put_urb(data_out_urb);
}
+ return;
+
+out:
+ spin_unlock_irqrestore(&devinfo->lock, flags);
+bail:
+ usb_free_urb(urb);
}
static void uas_data_cmplt(struct urb *urb)
{
struct scsi_cmnd *cmnd = urb->context;
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
struct scsi_data_buffer *sdb = &cmnd->sdb;
unsigned long flags;
@@ -424,13 +428,14 @@ static void uas_data_cmplt(struct urb *urb)
uas_log_cmd_state(cmnd, "data cmplt err", status);
/* error: no data transfered */
scsi_set_resid(cmnd, sdb->length);
+ set_host_byte(cmnd, DID_ERROR);
} else {
scsi_set_resid(cmnd, sdb->length - urb->actual_length);
}
uas_try_complete(cmnd, __func__);
out:
- usb_free_urb(urb);
spin_unlock_irqrestore(&devinfo->lock, flags);
+ usb_free_urb(urb);
}
static void uas_cmd_cmplt(struct urb *urb)
@@ -446,7 +451,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
enum dma_data_direction dir)
{
struct usb_device *udev = devinfo->udev;
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct urb *urb = usb_alloc_urb(0, gfp);
struct scsi_data_buffer *sdb = &cmnd->sdb;
unsigned int pipe = (dir == DMA_FROM_DEVICE)
@@ -468,7 +473,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
struct scsi_cmnd *cmnd)
{
struct usb_device *udev = devinfo->udev;
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct urb *urb = usb_alloc_urb(0, gfp);
struct sense_iu *iu;
@@ -496,7 +501,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
{
struct usb_device *udev = devinfo->udev;
struct scsi_device *sdev = cmnd->device;
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct urb *urb = usb_alloc_urb(0, gfp);
struct command_iu *iu;
int len;
@@ -535,7 +540,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
* daft to me.
*/
-static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
+static int uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
{
struct uas_dev_info *devinfo = cmnd->device->hostdata;
struct urb *urb;
@@ -543,30 +548,28 @@ static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
urb = uas_alloc_sense_urb(devinfo, gfp, cmnd);
if (!urb)
- return NULL;
+ return -ENOMEM;
usb_anchor_urb(urb, &devinfo->sense_urbs);
err = usb_submit_urb(urb, gfp);
if (err) {
usb_unanchor_urb(urb);
uas_log_cmd_state(cmnd, "sense submit err", err);
usb_free_urb(urb);
- return NULL;
}
- return urb;
+ return err;
}
static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo)
{
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
- struct urb *urb;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
int err;
lockdep_assert_held(&devinfo->lock);
if (cmdinfo->state & SUBMIT_STATUS_URB) {
- urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
- if (!urb)
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ err = uas_submit_sense_urb(cmnd, GFP_ATOMIC);
+ if (err)
+ return err;
cmdinfo->state &= ~SUBMIT_STATUS_URB;
}
@@ -574,7 +577,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
cmnd, DMA_FROM_DEVICE);
if (!cmdinfo->data_in_urb)
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ return -ENOMEM;
cmdinfo->state &= ~ALLOC_DATA_IN_URB;
}
@@ -584,7 +587,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
if (err) {
usb_unanchor_urb(cmdinfo->data_in_urb);
uas_log_cmd_state(cmnd, "data in submit err", err);
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ return err;
}
cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
cmdinfo->state |= DATA_IN_URB_INFLIGHT;
@@ -594,7 +597,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, GFP_ATOMIC,
cmnd, DMA_TO_DEVICE);
if (!cmdinfo->data_out_urb)
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ return -ENOMEM;
cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
}
@@ -604,7 +607,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
if (err) {
usb_unanchor_urb(cmdinfo->data_out_urb);
uas_log_cmd_state(cmnd, "data out submit err", err);
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ return err;
}
cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
@@ -613,7 +616,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
if (cmdinfo->state & ALLOC_CMD_URB) {
cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, GFP_ATOMIC, cmnd);
if (!cmdinfo->cmd_urb)
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ return -ENOMEM;
cmdinfo->state &= ~ALLOC_CMD_URB;
}
@@ -623,7 +626,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
if (err) {
usb_unanchor_urb(cmdinfo->cmd_urb);
uas_log_cmd_state(cmnd, "cmd submit err", err);
- return SCSI_MLQUEUE_DEVICE_BUSY;
+ return err;
}
cmdinfo->cmd_urb = NULL;
cmdinfo->state &= ~SUBMIT_CMD_URB;
@@ -633,17 +636,14 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
return 0;
}
-static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
- void (*done)(struct scsi_cmnd *))
+static int uas_queuecommand_lck(struct scsi_cmnd *cmnd)
{
struct scsi_device *sdev = cmnd->device;
struct uas_dev_info *devinfo = sdev->hostdata;
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
unsigned long flags;
int idx, err;
- BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
-
/* Re-check scsi_block_requests now that we've the host-lock */
if (cmnd->device->host->host_self_blocked)
return SCSI_MLQUEUE_DEVICE_BUSY;
@@ -653,17 +653,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
memcpy(cmnd->sense_buffer, usb_stor_sense_invalidCDB,
sizeof(usb_stor_sense_invalidCDB));
cmnd->result = SAM_STAT_CHECK_CONDITION;
- cmnd->scsi_done(cmnd);
+ scsi_done(cmnd);
return 0;
}
spin_lock_irqsave(&devinfo->lock, flags);
if (devinfo->resetting) {
- cmnd->result = DID_ERROR << 16;
- cmnd->scsi_done(cmnd);
- spin_unlock_irqrestore(&devinfo->lock, flags);
- return 0;
+ set_host_byte(cmnd, DID_ERROR);
+ scsi_done(cmnd);
+ goto zombie;
}
/* Find a free uas-tag */
@@ -676,8 +675,6 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
return SCSI_MLQUEUE_DEVICE_BUSY;
}
- cmnd->scsi_done = done;
-
memset(cmdinfo, 0, sizeof(*cmdinfo));
cmdinfo->uas_tag = idx + 1; /* uas-tag == usb-stream-id, so 1 based */
cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB;
@@ -688,9 +685,10 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
break;
case DMA_BIDIRECTIONAL:
cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB;
- /* fall through */
+ fallthrough;
case DMA_TO_DEVICE:
cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB;
+ break;
case DMA_NONE:
break;
}
@@ -699,16 +697,32 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
err = uas_submit_urbs(cmnd, devinfo);
+ /*
+ * in case of fatal errors the SCSI layer is peculiar
+ * a command that has finished is a success for the purpose
+ * of queueing, no matter how fatal the error
+ */
+ if (err == -ENODEV) {
+ if (cmdinfo->state & (COMMAND_INFLIGHT | DATA_IN_URB_INFLIGHT |
+ DATA_OUT_URB_INFLIGHT))
+ goto out;
+
+ set_host_byte(cmnd, DID_NO_CONNECT);
+ scsi_done(cmnd);
+ goto zombie;
+ }
if (err) {
/* If we did nothing, give up now */
if (cmdinfo->state & SUBMIT_STATUS_URB) {
spin_unlock_irqrestore(&devinfo->lock, flags);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
- uas_add_work(cmdinfo);
+ uas_add_work(cmnd);
}
+out:
devinfo->cmnd[idx] = cmnd;
+zombie:
spin_unlock_irqrestore(&devinfo->lock, flags);
return 0;
}
@@ -722,7 +736,7 @@ static DEF_SCSI_QCMD(uas_queuecommand)
*/
static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
{
- struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
+ struct uas_cmd_info *cmdinfo = scsi_cmd_priv(cmnd);
struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
struct urb *data_in_urb = NULL;
struct urb *data_out_urb = NULL;
@@ -813,32 +827,31 @@ static int uas_target_alloc(struct scsi_target *starget)
return 0;
}
-static int uas_slave_alloc(struct scsi_device *sdev)
+static int uas_sdev_init(struct scsi_device *sdev)
{
struct uas_dev_info *devinfo =
(struct uas_dev_info *)sdev->host->hostdata;
- sdev->hostdata = devinfo;
-
/*
- * The protocol has no requirements on alignment in the strict sense.
- * Controllers may or may not have alignment restrictions.
- * As this is not exported, we use an extremely conservative guess.
+ * Some USB storage devices reset if the IO advice hints grouping mode
+ * page is queried. Hence skip that mode page.
*/
- blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
-
- if (devinfo->flags & US_FL_MAX_SECTORS_64)
- blk_queue_max_hw_sectors(sdev->request_queue, 64);
- else if (devinfo->flags & US_FL_MAX_SECTORS_240)
- blk_queue_max_hw_sectors(sdev->request_queue, 240);
+ sdev->sdev_bflags |= BLIST_SKIP_IO_HINTS;
+ sdev->hostdata = devinfo;
return 0;
}
-static int uas_slave_configure(struct scsi_device *sdev)
+static int uas_sdev_configure(struct scsi_device *sdev,
+ struct queue_limits *lim)
{
struct uas_dev_info *devinfo = sdev->hostdata;
+ if (devinfo->flags & US_FL_MAX_SECTORS_64)
+ lim->max_hw_sectors = 64;
+ else if (devinfo->flags & US_FL_MAX_SECTORS_240)
+ lim->max_hw_sectors = 240;
+
if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
sdev->no_report_opcodes = 1;
@@ -857,6 +870,9 @@ static int uas_slave_configure(struct scsi_device *sdev)
if (devinfo->flags & US_FL_NO_READ_CAPACITY_16)
sdev->no_read_capacity_16 = 1;
+ /* Some disks cannot handle WRITE_SAME */
+ if (devinfo->flags & US_FL_NO_SAME)
+ sdev->no_write_same = 1;
/*
* Some disks return the total number of blocks in response
* to READ CAPACITY rather than the highest block number.
@@ -872,6 +888,13 @@ static int uas_slave_configure(struct scsi_device *sdev)
sdev->guess_capacity = 1;
/*
+ * Some devices report generic values until the media has been
+ * accessed. Force a READ(10) prior to querying device
+ * characteristics.
+ */
+ sdev->read_before_ms = 1;
+
+ /*
* Some devices don't like MODE SENSE with page=0x3f,
* which is the command used for checking if a device
* is write-protected. Now that we tell the sd driver
@@ -887,18 +910,25 @@ static int uas_slave_configure(struct scsi_device *sdev)
return 0;
}
-static struct scsi_host_template uas_host_template = {
+static const struct scsi_host_template uas_host_template = {
.module = THIS_MODULE,
.name = "uas",
.queuecommand = uas_queuecommand,
.target_alloc = uas_target_alloc,
- .slave_alloc = uas_slave_alloc,
- .slave_configure = uas_slave_configure,
+ .sdev_init = uas_sdev_init,
+ .sdev_configure = uas_sdev_configure,
.eh_abort_handler = uas_eh_abort_handler,
.eh_device_reset_handler = uas_eh_device_reset_handler,
.this_id = -1,
.skip_settle_delay = 1,
+ /*
+ * The protocol has no requirements on alignment in the strict sense.
+ * Controllers may or may not have alignment restrictions.
+ * As this is not exported, we use an extremely conservative guess.
+ */
+ .dma_alignment = 511,
.dma_boundary = PAGE_SIZE - 1,
+ .cmd_size = sizeof(struct uas_cmd_info),
};
#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
@@ -907,7 +937,7 @@ static struct scsi_host_template uas_host_template = {
{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
.driver_info = (flags) }
-static struct usb_device_id uas_usb_ids[] = {
+static const struct usb_device_id uas_usb_ids[] = {
# include "unusual_uas.h"
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) },
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
@@ -980,7 +1010,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct Scsi_Host *shost = NULL;
struct uas_dev_info *devinfo;
struct usb_device *udev = interface_to_usbdev(intf);
- unsigned long dev_flags;
+ u64 dev_flags;
if (!uas_use_uas_driver(intf, id, &dev_flags))
return -ENODEV;
@@ -1213,9 +1243,8 @@ static void uas_disconnect(struct usb_interface *intf)
* hang on reboot when the device is still in uas mode. Note the reset is
* necessary as some devices won't revert to usb-storage mode without it.
*/
-static void uas_shutdown(struct device *dev)
+static void uas_shutdown(struct usb_interface *intf)
{
- struct usb_interface *intf = to_usb_interface(dev);
struct usb_device *udev = interface_to_usbdev(intf);
struct Scsi_Host *shost = usb_get_intfdata(intf);
struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
@@ -1238,7 +1267,7 @@ static struct usb_driver uas_driver = {
.suspend = uas_suspend,
.resume = uas_resume,
.reset_resume = uas_reset_resume,
- .drvwrap.driver.shutdown = uas_shutdown,
+ .shutdown = uas_shutdown,
.id_table = uas_usb_ids,
};
@@ -1246,7 +1275,7 @@ static int __init uas_init(void)
{
int rv;
- workqueue = alloc_workqueue("uas", WQ_MEM_RECLAIM, 0);
+ workqueue = alloc_workqueue("uas", WQ_MEM_RECLAIM | WQ_PERCPU, 0);
if (!workqueue)
return -ENOMEM;
@@ -1268,7 +1297,8 @@ static void __exit uas_exit(void)
module_init(uas_init);
module_exit(uas_exit);
+MODULE_DESCRIPTION("USB Attached SCSI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
MODULE_AUTHOR(
"Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp");