diff options
Diffstat (limited to 'drivers/scsi/storvsc_drv.c')
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 32 |
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 0f636cc4c809..cd5c1c060481 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c | |||
@@ -135,6 +135,8 @@ struct hv_fc_wwn_packet { | |||
135 | #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000 | 135 | #define SRB_FLAGS_PORT_DRIVER_RESERVED 0x0F000000 |
136 | #define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000 | 136 | #define SRB_FLAGS_CLASS_DRIVER_RESERVED 0xF0000000 |
137 | 137 | ||
138 | #define SP_UNTAGGED ((unsigned char) ~0) | ||
139 | #define SRB_SIMPLE_TAG_REQUEST 0x20 | ||
138 | 140 | ||
139 | /* | 141 | /* |
140 | * Platform neutral description of a scsi request - | 142 | * Platform neutral description of a scsi request - |
@@ -354,6 +356,7 @@ enum storvsc_request_type { | |||
354 | #define SRB_STATUS_SUCCESS 0x01 | 356 | #define SRB_STATUS_SUCCESS 0x01 |
355 | #define SRB_STATUS_ABORTED 0x02 | 357 | #define SRB_STATUS_ABORTED 0x02 |
356 | #define SRB_STATUS_ERROR 0x04 | 358 | #define SRB_STATUS_ERROR 0x04 |
359 | #define SRB_STATUS_DATA_OVERRUN 0x12 | ||
357 | 360 | ||
358 | #define SRB_STATUS(status) \ | 361 | #define SRB_STATUS(status) \ |
359 | (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) | 362 | (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN)) |
@@ -864,6 +867,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, | |||
864 | switch (SRB_STATUS(vm_srb->srb_status)) { | 867 | switch (SRB_STATUS(vm_srb->srb_status)) { |
865 | case SRB_STATUS_ERROR: | 868 | case SRB_STATUS_ERROR: |
866 | /* | 869 | /* |
870 | * Let upper layer deal with error when | ||
871 | * sense message is present. | ||
872 | */ | ||
873 | |||
874 | if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) | ||
875 | break; | ||
876 | /* | ||
867 | * If there is an error; offline the device since all | 877 | * If there is an error; offline the device since all |
868 | * error recovery strategies would have already been | 878 | * error recovery strategies would have already been |
869 | * deployed on the host side. However, if the command | 879 | * deployed on the host side. However, if the command |
@@ -927,6 +937,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
927 | struct hv_host_device *host_dev = shost_priv(scmnd->device->host); | 937 | struct hv_host_device *host_dev = shost_priv(scmnd->device->host); |
928 | struct scsi_sense_hdr sense_hdr; | 938 | struct scsi_sense_hdr sense_hdr; |
929 | struct vmscsi_request *vm_srb; | 939 | struct vmscsi_request *vm_srb; |
940 | u32 data_transfer_length; | ||
930 | struct Scsi_Host *host; | 941 | struct Scsi_Host *host; |
931 | struct storvsc_device *stor_dev; | 942 | struct storvsc_device *stor_dev; |
932 | struct hv_device *dev = host_dev->dev; | 943 | struct hv_device *dev = host_dev->dev; |
@@ -937,6 +948,7 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
937 | host = stor_dev->host; | 948 | host = stor_dev->host; |
938 | 949 | ||
939 | vm_srb = &cmd_request->vstor_packet.vm_srb; | 950 | vm_srb = &cmd_request->vstor_packet.vm_srb; |
951 | data_transfer_length = vm_srb->data_transfer_length; | ||
940 | 952 | ||
941 | scmnd->result = vm_srb->scsi_status; | 953 | scmnd->result = vm_srb->scsi_status; |
942 | 954 | ||
@@ -947,13 +959,20 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
947 | &sense_hdr); | 959 | &sense_hdr); |
948 | } | 960 | } |
949 | 961 | ||
950 | if (vm_srb->srb_status != SRB_STATUS_SUCCESS) | 962 | if (vm_srb->srb_status != SRB_STATUS_SUCCESS) { |
951 | storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc, | 963 | storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc, |
952 | sense_hdr.ascq); | 964 | sense_hdr.ascq); |
965 | /* | ||
966 | * The Windows driver set data_transfer_length on | ||
967 | * SRB_STATUS_DATA_OVERRUN. On other errors, this value | ||
968 | * is untouched. In these cases we set it to 0. | ||
969 | */ | ||
970 | if (vm_srb->srb_status != SRB_STATUS_DATA_OVERRUN) | ||
971 | data_transfer_length = 0; | ||
972 | } | ||
953 | 973 | ||
954 | scsi_set_resid(scmnd, | 974 | scsi_set_resid(scmnd, |
955 | cmd_request->payload->range.len - | 975 | cmd_request->payload->range.len - data_transfer_length); |
956 | vm_srb->data_transfer_length); | ||
957 | 976 | ||
958 | scmnd->scsi_done(scmnd); | 977 | scmnd->scsi_done(scmnd); |
959 | 978 | ||
@@ -1409,6 +1428,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) | |||
1409 | vm_srb->win8_extension.srb_flags |= | 1428 | vm_srb->win8_extension.srb_flags |= |
1410 | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; | 1429 | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; |
1411 | 1430 | ||
1431 | if (scmnd->device->tagged_supported) { | ||
1432 | vm_srb->win8_extension.srb_flags |= | ||
1433 | (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); | ||
1434 | vm_srb->win8_extension.queue_tag = SP_UNTAGGED; | ||
1435 | vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST; | ||
1436 | } | ||
1437 | |||
1412 | /* Build the SRB */ | 1438 | /* Build the SRB */ |
1413 | switch (scmnd->sc_data_direction) { | 1439 | switch (scmnd->sc_data_direction) { |
1414 | case DMA_TO_DEVICE: | 1440 | case DMA_TO_DEVICE: |