[SCSI] storvsc: Restructure error handling code on command completion
authorK. Y. Srinivasan <kys@microsoft.com>
Thu, 21 Feb 2013 20:04:52 +0000 (12:04 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Sun, 24 Feb 2013 09:40:32 +0000 (09:40 +0000)
In preparation for handling additional sense codes, restructure and cleanup
the error handling code in the command completion code path.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/storvsc_drv.c

index 82873e7..95c759f 100644 (file)
@@ -761,6 +761,55 @@ cleanup:
        return ret;
 }
 
+static void storvsc_handle_error(struct vmscsi_request *vm_srb,
+                               struct scsi_cmnd *scmnd,
+                               struct Scsi_Host *host,
+                               u8 asc, u8 ascq)
+{
+       struct storvsc_scan_work *wrk;
+       void (*process_err_fn)(struct work_struct *work);
+       bool do_work = false;
+
+       switch (vm_srb->srb_status) {
+       case SRB_STATUS_ERROR:
+               /*
+                * If there is an error; offline the device since all
+                * error recovery strategies would have already been
+                * deployed on the host side. However, if the command
+                * were a pass-through command deal with it appropriately.
+                */
+               switch (scmnd->cmnd[0]) {
+               case ATA_16:
+               case ATA_12:
+                       set_host_byte(scmnd, DID_PASSTHROUGH);
+                       break;
+               default:
+                       set_host_byte(scmnd, DID_TARGET_FAILURE);
+               }
+               break;
+       case SRB_STATUS_INVALID_LUN:
+               do_work = true;
+               process_err_fn = storvsc_remove_lun;
+               break;
+       }
+       if (!do_work)
+               return;
+
+       /*
+        * We need to schedule work to process this error; schedule it.
+        */
+       wrk = kmalloc(sizeof(struct storvsc_scan_work), GFP_ATOMIC);
+       if (!wrk) {
+               set_host_byte(scmnd, DID_TARGET_FAILURE);
+               return;
+       }
+
+       wrk->host = host;
+       wrk->lun = vm_srb->lun;
+       INIT_WORK(&wrk->work, process_err_fn);
+       schedule_work(&wrk->work);
+}
+
 
 static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
 {
@@ -769,8 +818,13 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
        void (*scsi_done_fn)(struct scsi_cmnd *);
        struct scsi_sense_hdr sense_hdr;
        struct vmscsi_request *vm_srb;
-       struct storvsc_scan_work *wrk;
        struct stor_mem_pools *memp = scmnd->device->hostdata;
+       struct Scsi_Host *host;
+       struct storvsc_device *stor_dev;
+       struct hv_device *dev = host_dev->dev;
+
+       stor_dev = get_in_stor_device(dev);
+       host = stor_dev->host;
 
        vm_srb = &cmd_request->vstor_packet.vm_srb;
        if (cmd_request->bounce_sgl_count) {
@@ -783,55 +837,18 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
                                        cmd_request->bounce_sgl_count);
        }
 
-       /*
-        * If there is an error; offline the device since all
-        * error recovery strategies would have already been
-        * deployed on the host side. However, if the command
-        * were a pass-through command deal with it appropriately.
-        */
        scmnd->result = vm_srb->scsi_status;
 
-       if (vm_srb->srb_status == SRB_STATUS_ERROR) {
-               switch (scmnd->cmnd[0]) {
-               case ATA_16:
-               case ATA_12:
-                       set_host_byte(scmnd, DID_PASSTHROUGH);
-                       break;
-               default:
-                       set_host_byte(scmnd, DID_TARGET_FAILURE);
-               }
-       }
-
-
-       /*
-        * If the LUN is invalid; remove the device.
-        */
-       if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) {
-               struct storvsc_device *stor_dev;
-               struct hv_device *dev = host_dev->dev;
-               struct Scsi_Host *host;
-
-               stor_dev = get_in_stor_device(dev);
-               host = stor_dev->host;
-
-               wrk = kmalloc(sizeof(struct storvsc_scan_work),
-                               GFP_ATOMIC);
-               if (!wrk) {
-                       scmnd->result = DID_TARGET_FAILURE << 16;
-               } else {
-                       wrk->host = host;
-                       wrk->lun = vm_srb->lun;
-                       INIT_WORK(&wrk->work, storvsc_remove_lun);
-                       schedule_work(&wrk->work);
-               }
-       }
-
        if (scmnd->result) {
                if (scsi_normalize_sense(scmnd->sense_buffer,
                                SCSI_SENSE_BUFFERSIZE, &sense_hdr))
                        scsi_print_sense_hdr("storvsc", &sense_hdr);
        }
 
+       if (vm_srb->srb_status != SRB_STATUS_SUCCESS)
+               storvsc_handle_error(vm_srb, scmnd, host, sense_hdr.asc,
+                                        sense_hdr.ascq);
+
        scsi_set_resid(scmnd,
                cmd_request->data_buffer.len -
                vm_srb->data_transfer_length);