clk: rockchip: rk3328: add pclk for acodec
[firefly-linux-kernel-4.4.55.git] / drivers / scsi / storvsc_drv.c
index 3fba42ad9fb8aee55d5015167a9cb9ad601fb1a7..cd5c1c060481711812d10d1ce70a59376fb4ff80 100644 (file)
@@ -135,6 +135,8 @@ struct hv_fc_wwn_packet {
 #define SRB_FLAGS_PORT_DRIVER_RESERVED         0x0F000000
 #define SRB_FLAGS_CLASS_DRIVER_RESERVED                0xF0000000
 
+#define SP_UNTAGGED                    ((unsigned char) ~0)
+#define SRB_SIMPLE_TAG_REQUEST         0x20
 
 /*
  * Platform neutral description of a scsi request -
@@ -354,6 +356,7 @@ enum storvsc_request_type {
 #define SRB_STATUS_SUCCESS     0x01
 #define SRB_STATUS_ABORTED     0x02
 #define SRB_STATUS_ERROR       0x04
+#define SRB_STATUS_DATA_OVERRUN        0x12
 
 #define SRB_STATUS(status) \
        (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
@@ -863,6 +866,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
 
        switch (SRB_STATUS(vm_srb->srb_status)) {
        case SRB_STATUS_ERROR:
+               /*
+                * Let upper layer deal with error when
+                * sense message is present.
+                */
+
+               if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID)
+                       break;
                /*
                 * If there is an error; offline the device since all
                 * error recovery strategies would have already been
@@ -889,8 +899,9 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
                do_work = true;
                process_err_fn = storvsc_remove_lun;
                break;
-       case (SRB_STATUS_ABORTED | SRB_STATUS_AUTOSENSE_VALID):
-               if ((asc == 0x2a) && (ascq == 0x9)) {
+       case SRB_STATUS_ABORTED:
+               if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID &&
+                   (asc == 0x2a) && (ascq == 0x9)) {
                        do_work = true;
                        process_err_fn = storvsc_device_scan;
                        /*
@@ -926,6 +937,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
        struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
        struct scsi_sense_hdr sense_hdr;
        struct vmscsi_request *vm_srb;
+       u32 data_transfer_length;
        struct Scsi_Host *host;
        struct storvsc_device *stor_dev;
        struct hv_device *dev = host_dev->dev;
@@ -936,6 +948,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
        host = stor_dev->host;
 
        vm_srb = &cmd_request->vstor_packet.vm_srb;
+       data_transfer_length = vm_srb->data_transfer_length;
 
        scmnd->result = vm_srb->scsi_status;
 
@@ -946,13 +959,20 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
                                             &sense_hdr);
        }
 
-       if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
+       if (vm_srb->srb_status != SRB_STATUS_SUCCESS) {
                storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc,
                                         sense_hdr.ascq);
+               /*
+                * The Windows driver set data_transfer_length on
+                * SRB_STATUS_DATA_OVERRUN. On other errors, this value
+                * is untouched.  In these cases we set it to 0.
+                */
+               if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN)
+                       data_transfer_length = 0;
+       }
 
        scsi_set_resid(scmnd,
-               cmd_request->payload->range.len -
-               vm_srb->data_transfer_length);
+               cmd_request->payload->range.len - data_transfer_length);
 
        scmnd->scsi_done(scmnd);
 
@@ -1408,6 +1428,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
        vm_srb->win8_extension.srb_flags |=
                SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
 
+       if (scmnd->device->tagged_supported) {
+               vm_srb->win8_extension.srb_flags |=
+               (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE);
+               vm_srb->win8_extension.queue_tag = SP_UNTAGGED;
+               vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST;
+       }
+
        /* Build the SRB */
        switch (scmnd->sc_data_direction) {
        case DMA_TO_DEVICE: