Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+59 −42
Original line number Diff line number Diff line
@@ -761,37 +761,23 @@ static int storvsc_channel_init(struct hv_device *device)
	return ret;
}


static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
static void storvsc_handle_error(struct vmscsi_request *vm_srb,
				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 stor_mem_pools *memp = scmnd->device->hostdata;

	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);
	}
	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.
		 */
	scmnd->result = vm_srb->scsi_status;

	if (vm_srb->srb_status == SRB_STATUS_ERROR) {
		switch (scmnd->cmnd[0]) {
		case ATA_16:
		case ATA_12:
@@ -800,38 +786,69 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request)
		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;

	/*
	 * 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 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);
		}
	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);
	}

	scmnd->result = vm_srb->scsi_status;

	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);