uas: Reduce number of function arguments for uas_alloc_foo functions
[firefly-linux-kernel-4.4.55.git] / drivers / usb / storage / uas.c
index c69b9c5bb26538136e0268dffe53f258cdcb353d..d1dbe8833b4aca445db23a5d43a69d7c96030a51 100644 (file)
 
 #define MAX_CMNDS 256
 
-/*
- * The r00-r01c specs define this version of the SENSE IU data structure.
- * It's still in use by several different firmware releases.
- */
-struct sense_iu_old {
-       __u8 iu_id;
-       __u8 rsvd1;
-       __be16 tag;
-       __be16 len;
-       __u8 status;
-       __u8 service_response;
-       __u8 sense[SCSI_SENSE_BUFFERSIZE];
-};
-
 struct uas_dev_info {
        struct usb_interface *intf;
        struct usb_device *udev;
@@ -56,7 +42,6 @@ struct uas_dev_info {
        int qdepth, resetting;
        unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
        unsigned use_streams:1;
-       unsigned uas_sense_old:1;
        unsigned shutdown:1;
        struct scsi_cmnd *cmnd[MAX_CMNDS];
        spinlock_t lock;
@@ -74,9 +59,8 @@ enum {
        COMMAND_INFLIGHT        = (1 << 8),
        DATA_IN_URB_INFLIGHT    = (1 << 9),
        DATA_OUT_URB_INFLIGHT   = (1 << 10),
-       COMMAND_COMPLETED       = (1 << 11),
-       COMMAND_ABORTED         = (1 << 12),
-       IS_IN_WORK_LIST         = (1 << 13),
+       COMMAND_ABORTED         = (1 << 11),
+       IS_IN_WORK_LIST         = (1 << 12),
 };
 
 /* Overrides scsi_pointer */
@@ -94,7 +78,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 static void uas_do_work(struct work_struct *work);
 static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
 static void uas_free_streams(struct uas_dev_info *devinfo);
-static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller);
+static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
+                               int status);
 
 static void uas_do_work(struct work_struct *work)
 {
@@ -155,7 +140,7 @@ static void uas_zap_pending(struct uas_dev_info *devinfo, int result)
 
                cmnd = devinfo->cmnd[i];
                cmdinfo = (void *)&cmnd->SCp;
-               uas_log_cmd_state(cmnd, __func__);
+               uas_log_cmd_state(cmnd, __func__, 0);
                /* Sense urbs were killed, clear COMMAND_INFLIGHT manually */
                cmdinfo->state &= ~COMMAND_INFLIGHT;
                cmnd->result = result << 16;
@@ -188,29 +173,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
        cmnd->result = sense_iu->status;
 }
 
-static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd)
-{
-       struct sense_iu_old *sense_iu = urb->transfer_buffer;
-       struct scsi_device *sdev = cmnd->device;
-
-       if (urb->actual_length > 8) {
-               unsigned len = be16_to_cpup(&sense_iu->len) - 2;
-               if (len + 8 != urb->actual_length) {
-                       int newlen = min(len + 8, urb->actual_length) - 8;
-                       if (newlen < 0)
-                               newlen = 0;
-                       sdev_printk(KERN_INFO, sdev, "%s: urb length %d "
-                               "disagrees with IU sense data length %d, "
-                               "using %d bytes of sense data\n", __func__,
-                                       urb->actual_length, len, newlen);
-                       len = newlen;
-               }
-               memcpy(cmnd->sense_buffer, sense_iu->sense, len);
-       }
-
-       cmnd->result = sense_iu->status;
-}
-
 /*
  * scsi-tags go from 0 - (nr_tags - 1), uas tags need to match stream-ids,
  * which go from 1 - nr_streams. And we use 1 for untagged commands.
@@ -227,13 +189,14 @@ static int uas_get_tag(struct scsi_cmnd *cmnd)
        return tag;
 }
 
-static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller)
+static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *prefix,
+                             int status)
 {
        struct uas_cmd_info *ci = (void *)&cmnd->SCp;
 
        scmd_printk(KERN_INFO, cmnd,
-                   "%s %p tag %d, inflight:%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
-                   caller, cmnd, uas_get_tag(cmnd),
+                   "%s %d tag %d inflight:%s%s%s%s%s%s%s%s%s%s%s%s ",
+                   prefix, status, uas_get_tag(cmnd),
                    (ci->state & SUBMIT_STATUS_URB)     ? " s-st"  : "",
                    (ci->state & ALLOC_DATA_IN_URB)     ? " a-in"  : "",
                    (ci->state & SUBMIT_DATA_IN_URB)    ? " s-in"  : "",
@@ -244,9 +207,9 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller)
                    (ci->state & COMMAND_INFLIGHT)      ? " CMD"   : "",
                    (ci->state & DATA_IN_URB_INFLIGHT)  ? " IN"    : "",
                    (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT"   : "",
-                   (ci->state & COMMAND_COMPLETED)     ? " done"  : "",
                    (ci->state & COMMAND_ABORTED)       ? " abort" : "",
                    (ci->state & IS_IN_WORK_LIST)       ? " work"  : "");
+       scsi_print_command(cmnd);
 }
 
 static void uas_free_unsubmitted_urbs(struct scsi_cmnd *cmnd)
@@ -279,8 +242,6 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller)
                              DATA_OUT_URB_INFLIGHT |
                              COMMAND_ABORTED))
                return -EBUSY;
-       WARN_ON_ONCE(cmdinfo->state & COMMAND_COMPLETED);
-       cmdinfo->state |= COMMAND_COMPLETED;
        devinfo->cmnd[uas_get_tag(cmnd) - 1] = NULL;
        uas_free_unsubmitted_urbs(cmnd);
        cmnd->scsi_done(cmnd);
@@ -318,10 +279,7 @@ static void uas_stat_cmplt(struct urb *urb)
                goto out;
 
        if (urb->status) {
-               if (urb->status == -ENOENT) {
-                       dev_err(&urb->dev->dev, "stat urb: killed, stream %d\n",
-                               urb->stream_id);
-               } else {
+               if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
                        dev_err(&urb->dev->dev, "stat urb: status %d\n",
                                urb->status);
                }
@@ -339,18 +297,13 @@ static void uas_stat_cmplt(struct urb *urb)
        cmdinfo = (void *)&cmnd->SCp;
 
        if (!(cmdinfo->state & COMMAND_INFLIGHT)) {
-               scmd_printk(KERN_ERR, cmnd, "unexpected status cmplt\n");
+               uas_log_cmd_state(cmnd, "unexpected status cmplt", 0);
                goto out;
        }
 
        switch (iu->iu_id) {
        case IU_ID_STATUS:
-               if (urb->actual_length < 16)
-                       devinfo->uas_sense_old = 1;
-               if (devinfo->uas_sense_old)
-                       uas_sense_old(urb, cmnd);
-               else
-                       uas_sense(urb, cmnd);
+               uas_sense(urb, cmnd);
                if (cmnd->result != 0) {
                        /* cancel data transfers on error */
                        data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
@@ -362,7 +315,7 @@ static void uas_stat_cmplt(struct urb *urb)
        case IU_ID_READ_READY:
                if (!cmdinfo->data_in_urb ||
                                (cmdinfo->state & DATA_IN_URB_INFLIGHT)) {
-                       scmd_printk(KERN_ERR, cmnd, "unexpected read rdy\n");
+                       uas_log_cmd_state(cmnd, "unexpected read rdy", 0);
                        break;
                }
                uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
@@ -370,14 +323,23 @@ static void uas_stat_cmplt(struct urb *urb)
        case IU_ID_WRITE_READY:
                if (!cmdinfo->data_out_urb ||
                                (cmdinfo->state & DATA_OUT_URB_INFLIGHT)) {
-                       scmd_printk(KERN_ERR, cmnd, "unexpected write rdy\n");
+                       uas_log_cmd_state(cmnd, "unexpected write rdy", 0);
                        break;
                }
                uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
                break;
+       case IU_ID_RESPONSE:
+               uas_log_cmd_state(cmnd, "unexpected response iu",
+                                 ((struct response_iu *)iu)->response_code);
+               /* Error, cancel data transfers */
+               data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
+               data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
+               cmdinfo->state &= ~COMMAND_INFLIGHT;
+               cmnd->result = DID_ERROR << 16;
+               uas_try_complete(cmnd, __func__);
+               break;
        default:
-               scmd_printk(KERN_ERR, cmnd,
-                       "Bogus IU (%d) received on status pipe\n", iu->iu_id);
+               uas_log_cmd_state(cmnd, "bogus IU", iu->iu_id);
        }
 out:
        usb_free_urb(urb);
@@ -423,17 +385,13 @@ static void uas_data_cmplt(struct urb *urb)
 
        /* Data urbs should not complete before the cmd urb is submitted */
        if (cmdinfo->state & SUBMIT_CMD_URB) {
-               scmd_printk(KERN_ERR, cmnd, "unexpected data cmplt\n");
+               uas_log_cmd_state(cmnd, "unexpected data cmplt", 0);
                goto out;
        }
 
        if (urb->status) {
-               if (urb->status != -ECONNRESET) {
-                       uas_log_cmd_state(cmnd, __func__);
-                       scmd_printk(KERN_ERR, cmnd,
-                               "data cmplt err %d stream %d\n",
-                               urb->status, urb->stream_id);
-               }
+               if (urb->status != -ENOENT && urb->status != -ECONNRESET)
+                       uas_log_cmd_state(cmnd, "data cmplt err", urb->status);
                /* error: no data transfered */
                sdb->resid = sdb->length;
        } else {
@@ -454,20 +412,22 @@ static void uas_cmd_cmplt(struct urb *urb)
 }
 
 static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-                                     unsigned int pipe, u16 stream_id,
                                      struct scsi_cmnd *cmnd,
                                      enum dma_data_direction dir)
 {
        struct usb_device *udev = devinfo->udev;
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
        struct urb *urb = usb_alloc_urb(0, gfp);
        struct scsi_data_buffer *sdb = (dir == DMA_FROM_DEVICE)
                ? scsi_in(cmnd) : scsi_out(cmnd);
+       unsigned int pipe = (dir == DMA_FROM_DEVICE)
+               ? devinfo->data_in_pipe : devinfo->data_out_pipe;
 
        if (!urb)
                goto out;
        usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
                          uas_data_cmplt, cmnd);
-       urb->stream_id = stream_id;
+       urb->stream_id = cmdinfo->stream;
        urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
        urb->sg = sdb->table.sgl;
  out:
@@ -475,9 +435,10 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
 }
 
 static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-                                      struct Scsi_Host *shost, u16 stream_id)
+                                      struct scsi_cmnd *cmnd)
 {
        struct usb_device *udev = devinfo->udev;
+       struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
        struct urb *urb = usb_alloc_urb(0, gfp);
        struct sense_iu *iu;
 
@@ -489,8 +450,8 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp,
                goto free;
 
        usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu),
-                                               uas_stat_cmplt, shost);
-       urb->stream_id = stream_id;
+                         uas_stat_cmplt, cmnd->device->host);
+       urb->stream_id = cmdinfo->stream;
        urb->transfer_flags |= URB_FREE_BUFFER;
  out:
        return urb;
@@ -542,25 +503,20 @@ 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, unsigned int stream)
+static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd, gfp_t gfp)
 {
-       struct Scsi_Host *shost = cmnd->device->host;
-       struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
+       struct uas_dev_info *devinfo = cmnd->device->hostdata;
        struct urb *urb;
        int err;
 
-       urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
+       urb = uas_alloc_sense_urb(devinfo, gfp, cmnd);
        if (!urb)
                return NULL;
        usb_anchor_urb(urb, &devinfo->sense_urbs);
        err = usb_submit_urb(urb, gfp);
        if (err) {
                usb_unanchor_urb(urb);
-               uas_log_cmd_state(cmnd, __func__);
-               shost_printk(KERN_INFO, shost,
-                            "sense urb submission error %d stream %d\n",
-                            err, stream);
+               uas_log_cmd_state(cmnd, "sense submit err", err);
                usb_free_urb(urb);
                return NULL;
        }
@@ -576,7 +532,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 
        lockdep_assert_held(&devinfo->lock);
        if (cmdinfo->state & SUBMIT_STATUS_URB) {
-               urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
+               urb = uas_submit_sense_urb(cmnd, gfp);
                if (!urb)
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                cmdinfo->state &= ~SUBMIT_STATUS_URB;
@@ -584,8 +540,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 
        if (cmdinfo->state & ALLOC_DATA_IN_URB) {
                cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp,
-                                       devinfo->data_in_pipe, cmdinfo->stream,
-                                       cmnd, DMA_FROM_DEVICE);
+                                                       cmnd, DMA_FROM_DEVICE);
                if (!cmdinfo->data_in_urb)
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                cmdinfo->state &= ~ALLOC_DATA_IN_URB;
@@ -596,10 +551,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
                err = usb_submit_urb(cmdinfo->data_in_urb, gfp);
                if (err) {
                        usb_unanchor_urb(cmdinfo->data_in_urb);
-                       uas_log_cmd_state(cmnd, __func__);
-                       scmd_printk(KERN_INFO, cmnd,
-                               "data in urb submission error %d stream %d\n",
-                               err, cmdinfo->data_in_urb->stream_id);
+                       uas_log_cmd_state(cmnd, "data in submit err", err);
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                }
                cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
@@ -608,8 +560,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 
        if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
                cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp,
-                                       devinfo->data_out_pipe, cmdinfo->stream,
-                                       cmnd, DMA_TO_DEVICE);
+                                                       cmnd, DMA_TO_DEVICE);
                if (!cmdinfo->data_out_urb)
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                cmdinfo->state &= ~ALLOC_DATA_OUT_URB;
@@ -620,10 +571,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
                err = usb_submit_urb(cmdinfo->data_out_urb, gfp);
                if (err) {
                        usb_unanchor_urb(cmdinfo->data_out_urb);
-                       uas_log_cmd_state(cmnd, __func__);
-                       scmd_printk(KERN_INFO, cmnd,
-                               "data out urb submission error %d stream %d\n",
-                               err, cmdinfo->data_out_urb->stream_id);
+                       uas_log_cmd_state(cmnd, "data out submit err", err);
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                }
                cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
@@ -642,9 +590,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
                err = usb_submit_urb(cmdinfo->cmd_urb, gfp);
                if (err) {
                        usb_unanchor_urb(cmdinfo->cmd_urb);
-                       uas_log_cmd_state(cmnd, __func__);
-                       scmd_printk(KERN_INFO, cmnd,
-                                   "cmd urb submission error %d\n", err);
+                       uas_log_cmd_state(cmnd, "cmd submit err", err);
                        return SCSI_MLQUEUE_DEVICE_BUSY;
                }
                cmdinfo->cmd_urb = NULL;
@@ -750,7 +696,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
 
        spin_lock_irqsave(&devinfo->lock, flags);
 
-       uas_log_cmd_state(cmnd, __func__);
+       uas_log_cmd_state(cmnd, __func__, 0);
 
        /* Ensure that try_complete does not call scsi_done */
        cmdinfo->state |= COMMAND_ABORTED;
@@ -813,7 +759,8 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
        usb_unlock_device(udev);
 
        if (err) {
-               shost_printk(KERN_INFO, sdev->host, "%s FAILED\n", __func__);
+               shost_printk(KERN_INFO, sdev->host, "%s FAILED err %d\n",
+                            __func__, err);
                return FAILED;
        }
 
@@ -883,8 +830,6 @@ static 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) },
-       /* 0xaa is a prototype device I happen to have access to */
-       { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, 0xaa) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, uas_usb_ids);
@@ -910,8 +855,6 @@ static int uas_configure_endpoints(struct uas_dev_info *devinfo)
        struct usb_device *udev = devinfo->udev;
        int r;
 
-       devinfo->uas_sense_old = 0;
-
        r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps);
        if (r)
                return r;
@@ -1091,13 +1034,16 @@ static int uas_post_reset(struct usb_interface *intf)
        struct Scsi_Host *shost = usb_get_intfdata(intf);
        struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
        unsigned long flags;
+       int err;
 
        if (devinfo->shutdown)
                return 0;
 
-       if (uas_configure_endpoints(devinfo) != 0) {
+       err = uas_configure_endpoints(devinfo);
+       if (err) {
                shost_printk(KERN_ERR, shost,
-                            "%s: alloc streams error after reset", __func__);
+                            "%s: alloc streams error %d after reset",
+                            __func__, err);
                return 1;
        }
 
@@ -1133,10 +1079,13 @@ static int uas_reset_resume(struct usb_interface *intf)
        struct Scsi_Host *shost = usb_get_intfdata(intf);
        struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
        unsigned long flags;
+       int err;
 
-       if (uas_configure_endpoints(devinfo) != 0) {
+       err = uas_configure_endpoints(devinfo);
+       if (err) {
                shost_printk(KERN_ERR, shost,
-                            "%s: alloc streams error after reset", __func__);
+                            "%s: alloc streams error %d after reset",
+                            __func__, err);
                return -EIO;
        }