aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/storvsc_drv.c101
1 files changed, 59 insertions, 42 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 82873e775fc3..95c759fe071a 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -761,6 +761,55 @@ cleanup:
761 return ret; 761 return ret;
762} 762}
763 763
764static void storvsc_handle_error(struct vmscsi_request *vm_srb,
765 struct scsi_cmnd *scmnd,
766 struct Scsi_Host *host,
767 u8 asc, u8 ascq)
768{
769 struct storvsc_scan_work *wrk;
770 void (*process_err_fn)(struct work_struct *work);
771 bool do_work = false;
772
773 switch (vm_srb->srb_status) {
774 case SRB_STATUS_ERROR:
775 /*
776 * If there is an error; offline the device since all
777 * error recovery strategies would have already been
778 * deployed on the host side. However, if the command
779 * were a pass-through command deal with it appropriately.
780 */
781 switch (scmnd->cmnd[0]) {
782 case ATA_16:
783 case ATA_12:
784 set_host_byte(scmnd, DID_PASSTHROUGH);
785 break;
786 default:
787 set_host_byte(scmnd, DID_TARGET_FAILURE);
788 }
789 break;
790 case SRB_STATUS_INVALID_LUN:
791 do_work = true;
792 process_err_fn = storvsc_remove_lun;
793 break;
794 }
795 if (!do_work)
796 return;
797
798 /*
799 * We need to schedule work to process this error; schedule it.
800 */
801 wrk = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC);
802 if (!wrk) {
803 set_host_byte(scmnd, DID_TARGET_FAILURE);
804 return;
805 }
806
807 wrk->host = host;
808 wrk->lun = vm_srb->lun;
809 INIT_WORK(&wrk->work, process_err_fn);
810 schedule_work(&wrk->work);
811}
812
764 813
765static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) 814static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
766{ 815{
@@ -769,8 +818,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
769 void (*scsi_done_fn)(struct scsi_cmnd *); 818 void (*scsi_done_fn)(struct scsi_cmnd *);
770 struct scsi_sense_hdr sense_hdr; 819 struct scsi_sense_hdr sense_hdr;
771 struct vmscsi_request *vm_srb; 820 struct vmscsi_request *vm_srb;
772 struct storvsc_scan_work *wrk;
773 struct stor_mem_pools *memp = scmnd->device->hostdata; 821 struct stor_mem_pools *memp = scmnd->device->hostdata;
822 struct Scsi_Host *host;
823 struct storvsc_device *stor_dev;
824 struct hv_device *dev = host_dev->dev;
825
826 stor_dev = get_in_stor_device(dev);
827 host = stor_dev->host;
774 828
775 vm_srb = &cmd_request->vstor_packet.vm_srb; 829 vm_srb = &cmd_request->vstor_packet.vm_srb;
776 if (cmd_request->bounce_sgl_count) { 830 if (cmd_request->bounce_sgl_count) {
@@ -783,55 +837,18 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
783 cmd_request->bounce_sgl_count); 837 cmd_request->bounce_sgl_count);
784 } 838 }
785 839
786 /*
787 * If there is an error; offline the device since all
788 * error recovery strategies would have already been
789 * deployed on the host side. However, if the command
790 * were a pass-through command deal with it appropriately.
791 */
792 scmnd->result = vm_srb->scsi_status; 840 scmnd->result = vm_srb->scsi_status;
793 841
794 if (vm_srb->srb_status == SRB_STATUS_ERROR) {
795 switch (scmnd->cmnd[0]) {
796 case ATA_16:
797 case ATA_12:
798 set_host_byte(scmnd, DID_PASSTHROUGH);
799 break;
800 default:
801 set_host_byte(scmnd, DID_TARGET_FAILURE);
802 }
803 }
804
805
806 /*
807 * If the LUN is invalid; remove the device.
808 */
809 if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
810 struct storvsc_device *stor_dev;
811 struct hv_device *dev = host_dev->dev;
812 struct Scsi_Host *host;
813
814 stor_dev = get_in_stor_device(dev);
815 host = stor_dev->host;
816
817 wrk = kmalloc(sizeof(struct storvsc_scan_work),
818 GFP_ATOMIC);
819 if (!wrk) {
820 scmnd->result = DID_TARGET_FAILURE << 16;
821 } else {
822 wrk->host = host;
823 wrk->lun = vm_srb->lun;
824 INIT_WORK(&wrk->work, storvsc_remove_lun);
825 schedule_work(&wrk->work);
826 }
827 }
828
829 if (scmnd->result) { 842 if (scmnd->result) {
830 if (scsi_normalize_sense(scmnd->sense_buffer, 843 if (scsi_normalize_sense(scmnd->sense_buffer,
831 SCSI_SENSE_BUFFERSIZE, &sense_hdr)) 844 SCSI_SENSE_BUFFERSIZE, &sense_hdr))
832 scsi_print_sense_hdr("storvsc", &sense_hdr); 845 scsi_print_sense_hdr("storvsc", &sense_hdr);
833 } 846 }
834 847
848 if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
849 storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc,
850 sense_hdr.ascq);
851
835 scsi_set_resid(scmnd, 852 scsi_set_resid(scmnd,
836 cmd_request->data_buffer.len - 853 cmd_request->data_buffer.len -
837 vm_srb->data_transfer_length); 854 vm_srb->data_transfer_length);