Commit c50bd448 authored by K. Y. Srinivasan's avatar K. Y. Srinivasan Committed by James Bottomley

[SCSI] storvsc: Restructure error handling code on command completion

In preparation for handling additional sense codes, restructure and cleanup
the error handling code in the command completion code path.
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 3e8f4f40
...@@ -761,37 +761,23 @@ static int storvsc_channel_init(struct hv_device *device) ...@@ -761,37 +761,23 @@ static int storvsc_channel_init(struct hv_device *device)
return ret; return ret;
} }
static void storvsc_handle_error(struct vmscsi_request *vm_srb,
static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) struct scsi_cmnd *scmnd,
struct Scsi_Host *host,
u8 asc, u8 ascq)
{ {
struct scsi_cmnd *scmnd = cmd_request->cmd;
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
void (*scsi_done_fn)(struct scsi_cmnd *);
struct scsi_sense_hdr sense_hdr;
struct vmscsi_request *vm_srb;
struct storvsc_scan_work *wrk; struct storvsc_scan_work *wrk;
struct stor_mem_pools *memp = scmnd->device->hostdata; void (*process_err_fn)(struct work_struct *work);
bool do_work = false;
vm_srb = &cmd_request->vstor_packet.vm_srb;
if (cmd_request->bounce_sgl_count) {
if (vm_srb->data_in == READ_TYPE)
copy_from_bounce_buffer(scsi_sglist(scmnd),
cmd_request->bounce_sgl,
scsi_sg_count(scmnd),
cmd_request->bounce_sgl_count);
destroy_bounce_buffer(cmd_request->bounce_sgl,
cmd_request->bounce_sgl_count);
}
switch (vm_srb->srb_status) {
case SRB_STATUS_ERROR:
/* /*
* If there is an error; offline the device since all * If there is an error; offline the device since all
* error recovery strategies would have already been * error recovery strategies would have already been
* deployed on the host side. However, if the command * deployed on the host side. However, if the command
* were a pass-through command deal with it appropriately. * 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]) { switch (scmnd->cmnd[0]) {
case ATA_16: case ATA_16:
case ATA_12: case ATA_12:
...@@ -800,38 +786,69 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) ...@@ -800,38 +786,69 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
default: default:
set_host_byte(scmnd, DID_TARGET_FAILURE); 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;
/* /*
* If the LUN is invalid; remove the device. * We need to schedule work to process this error; schedule it.
*/ */
if (vm_srb->srb_status == SRB_STATUS_INVALID_LUN) { 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)
{
struct scsi_cmnd *scmnd = cmd_request->cmd;
struct hv_host_device *host_dev = shost_priv(scmnd->device->host);
void (*scsi_done_fn)(struct scsi_cmnd *);
struct scsi_sense_hdr sense_hdr;
struct vmscsi_request *vm_srb;
struct stor_mem_pools *memp = scmnd->device->hostdata;
struct Scsi_Host *host;
struct storvsc_device *stor_dev; struct storvsc_device *stor_dev;
struct hv_device *dev = host_dev->dev; struct hv_device *dev = host_dev->dev;
struct Scsi_Host *host;
stor_dev = get_in_stor_device(dev); stor_dev = get_in_stor_device(dev);
host = stor_dev->host; host = stor_dev->host;
wrk = kmalloc(sizeof(struct storvsc_scan_work), vm_srb = &cmd_request->vstor_packet.vm_srb;
GFP_ATOMIC); if (cmd_request->bounce_sgl_count) {
if (!wrk) { if (vm_srb->data_in == READ_TYPE)
scmnd->result = DID_TARGET_FAILURE << 16; copy_from_bounce_buffer(scsi_sglist(scmnd),
} else { cmd_request->bounce_sgl,
wrk->host = host; scsi_sg_count(scmnd),
wrk->lun = vm_srb->lun; cmd_request->bounce_sgl_count);
INIT_WORK(&wrk->work, storvsc_remove_lun); destroy_bounce_buffer(cmd_request->bounce_sgl,
schedule_work(&wrk->work); cmd_request->bounce_sgl_count);
}
} }
scmnd->result = vm_srb->scsi_status;
if (scmnd->result) { if (scmnd->result) {
if (scsi_normalize_sense(scmnd->sense_buffer, if (scsi_normalize_sense(scmnd->sense_buffer,
SCSI_SENSE_BUFFERSIZE, &sense_hdr)) SCSI_SENSE_BUFFERSIZE, &sense_hdr))
scsi_print_sense_hdr("storvsc", &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, scsi_set_resid(scmnd,
cmd_request->data_buffer.len - cmd_request->data_buffer.len -
vm_srb->data_transfer_length); vm_srb->data_transfer_length);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment