Commit 5a9d16f7 authored by Tyrel Datwyler's avatar Tyrel Datwyler Committed by Martin K. Petersen
Browse files

scsi: ibmvfc: Add FC payload retrieval routines for versioned vfcFrames

The FC iu and response payloads are located at different offsets depending
on the ibmvfc_cmd version. This is a result of the version 2 vfcFrame
definition adding an extra 64bytes of reserved space to the structure prior
to the payloads.

Add helper routines to determine the current vfcFrame version and return a
pointer to the proper iu or response structure within that ibmvfc_cmd.

Link: https://lore.kernel.org/r/20201118011104.296999-5-tyreld@linux.ibm.com


Acked-by: default avatarBrian King <brking@linux.vnet.ibm.com>
Signed-off-by: default avatarTyrel Datwyler <tyreld@linux.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a318c2b7
Loading
Loading
Loading
Loading
+54 −23
Original line number Diff line number Diff line
@@ -145,6 +145,24 @@ static int ibmvfc_check_caps(struct ibmvfc_host *vhost, unsigned long cap_flags)
	return (host_caps & cap_flags) ? 1 : 0;
}

static struct ibmvfc_fcp_cmd_iu *ibmvfc_get_fcp_iu(struct ibmvfc_host *vhost,
						   struct ibmvfc_cmd *vfc_cmd)
{
	if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN))
		return &vfc_cmd->v2.iu;
	else
		return &vfc_cmd->v1.iu;
}

static struct ibmvfc_fcp_rsp *ibmvfc_get_fcp_rsp(struct ibmvfc_host *vhost,
						 struct ibmvfc_cmd *vfc_cmd)
{
	if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN))
		return &vfc_cmd->v2.rsp;
	else
		return &vfc_cmd->v1.rsp;
}

#ifdef CONFIG_SCSI_IBMVFC_TRACE
/**
 * ibmvfc_trc_start - Log a start trace entry
@@ -156,7 +174,7 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)
	struct ibmvfc_host *vhost = evt->vhost;
	struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd;
	struct ibmvfc_mad_common *mad = &evt->iu.mad_common;
	struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu;
	struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);
	struct ibmvfc_trace_entry *entry;

	entry = &vhost->trace[vhost->trace_index++];
@@ -191,8 +209,8 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)
	struct ibmvfc_host *vhost = evt->vhost;
	struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
	struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common;
	struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu;
	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp;
	struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);
	struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd);
	struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++];

	entry->evt = evt;
@@ -270,10 +288,10 @@ static const char *ibmvfc_get_cmd_error(u16 status, u16 error)
 * Return value:
 *	SCSI result value to return for completed command
 **/
static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd)
static int ibmvfc_get_err_result(struct ibmvfc_host *vhost, struct ibmvfc_cmd *vfc_cmd)
{
	int err;
	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp;
	struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd);
	int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len);

	if ((rsp->flags & FCP_RSP_LEN_VALID) &&
@@ -1388,7 +1406,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
	int sg_mapped;
	struct srp_direct_buf *data = &vfc_cmd->ioba;
	struct ibmvfc_host *vhost = dev_get_drvdata(dev);
	struct ibmvfc_fcp_cmd_iu *iu = &vfc_cmd->v1.iu;
	struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(evt->vhost, vfc_cmd);

	if (cls3_error)
		vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR);
@@ -1527,7 +1545,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
{
	struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
	struct ibmvfc_host *vhost = evt->vhost;
	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp;
	struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd);
	struct scsi_cmnd *cmnd = evt->cmnd;
	const char *err = unknown_error;
	int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error));
@@ -1581,7 +1599,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev)
static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
{
	struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
	struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->v1.rsp;
	struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(evt->vhost, vfc_cmd);
	struct scsi_cmnd *cmnd = evt->cmnd;
	u32 rsp_len = 0;
	u32 sense_len = be32_to_cpu(rsp->fcp_sense_len);
@@ -1595,7 +1613,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
			scsi_set_resid(cmnd, 0);

		if (vfc_cmd->status) {
			cmnd->result = ibmvfc_get_err_result(vfc_cmd);
			cmnd->result = ibmvfc_get_err_result(evt->vhost, vfc_cmd);

			if (rsp->flags & FCP_RSP_LEN_VALID)
				rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
@@ -1660,18 +1678,25 @@ static inline int ibmvfc_host_chkready(struct ibmvfc_host *vhost)
static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct scsi_device *sdev)
{
	struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
	struct ibmvfc_host *vhost = evt->vhost;
	struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd;
	size_t offset = offsetof(struct ibmvfc_cmd, v1.rsp);
	struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);
	struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd);
	size_t offset;

	memset(vfc_cmd, 0, sizeof(*vfc_cmd));
	if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN))
		offset = offsetof(struct ibmvfc_cmd, v2.rsp);
	else
		offset = offsetof(struct ibmvfc_cmd, v1.rsp);
	vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offset);
	vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp));
	vfc_cmd->resp.len = cpu_to_be32(sizeof(*rsp));
	vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
	vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->v1.iu));
	vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp));
	vfc_cmd->payload_len = cpu_to_be32(sizeof(*iu));
	vfc_cmd->resp_len = cpu_to_be32(sizeof(*rsp));
	vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
	vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id);
	int_to_scsilun(sdev->lun, &vfc_cmd->v1.iu.lun);
	int_to_scsilun(sdev->lun, &iu->lun);

	return vfc_cmd;
}
@@ -1690,6 +1715,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
	struct ibmvfc_host *vhost = shost_priv(cmnd->device->host);
	struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
	struct ibmvfc_cmd *vfc_cmd;
	struct ibmvfc_fcp_cmd_iu *iu;
	struct ibmvfc_event *evt;
	int rc;

@@ -1707,13 +1733,14 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
	cmnd->scsi_done = done;

	vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device);
	iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);

	vfc_cmd->v1.iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd));
	memcpy(vfc_cmd->v1.iu.cdb, cmnd->cmnd, cmnd->cmd_len);
	iu->xfer_len = cpu_to_be32(scsi_bufflen(cmnd));
	memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);

	if (cmnd->flags & SCMD_TAGGED) {
		vfc_cmd->task_tag = cpu_to_be64(cmnd->tag);
		vfc_cmd->v1.iu.pri_task_attr = IBMVFC_SIMPLE_TASK;
		iu->pri_task_attr = IBMVFC_SIMPLE_TASK;
	}

	vfc_cmd->correlation = cpu_to_be64(evt);
@@ -2040,7 +2067,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
	struct ibmvfc_cmd *tmf;
	struct ibmvfc_event *evt = NULL;
	union ibmvfc_iu rsp_iu;
	struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.v1.rsp;
	struct ibmvfc_fcp_cmd_iu *iu;
	struct ibmvfc_fcp_rsp *fc_rsp = ibmvfc_get_fcp_rsp(vhost, &rsp_iu.cmd);
	int rsp_rc = -EBUSY;
	unsigned long flags;
	int rsp_code = 0;
@@ -2050,9 +2078,10 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
		evt = ibmvfc_get_event(vhost);
		ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
		tmf = ibmvfc_init_vfc_cmd(evt, sdev);
		iu = ibmvfc_get_fcp_iu(vhost, tmf);

		tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
		tmf->v1.iu.tmf_flags = type;
		iu->tmf_flags = type;
		evt->sync_iu = &rsp_iu;

		init_completion(&evt->comp);
@@ -2070,7 +2099,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
	wait_for_completion(&evt->comp);

	if (rsp_iu.cmd.status)
		rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd);
		rsp_code = ibmvfc_get_err_result(vhost, &rsp_iu.cmd);

	if (rsp_code) {
		if (fc_rsp->flags & FCP_RSP_LEN_VALID)
@@ -2345,7 +2374,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
	struct ibmvfc_cmd *tmf;
	struct ibmvfc_event *evt, *found_evt;
	union ibmvfc_iu rsp_iu;
	struct ibmvfc_fcp_rsp *fc_rsp = &rsp_iu.cmd.v1.rsp;
	struct ibmvfc_fcp_cmd_iu *iu;
	struct ibmvfc_fcp_rsp *fc_rsp = ibmvfc_get_fcp_rsp(vhost, &rsp_iu.cmd);
	int rc, rsp_rc = -EBUSY;
	unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT;
	int rsp_code = 0;
@@ -2370,9 +2400,10 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
		evt = ibmvfc_get_event(vhost);
		ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
		tmf = ibmvfc_init_vfc_cmd(evt, sdev);
		iu = ibmvfc_get_fcp_iu(vhost, tmf);

		iu->tmf_flags = IBMVFC_ABORT_TASK_SET;
		tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
		tmf->v1.iu.tmf_flags = IBMVFC_ABORT_TASK_SET;
		evt->sync_iu = &rsp_iu;

		tmf->correlation = cpu_to_be64(evt);
@@ -2421,7 +2452,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
	}

	if (rsp_iu.cmd.status)
		rsp_code = ibmvfc_get_err_result(&rsp_iu.cmd);
		rsp_code = ibmvfc_get_err_result(vhost, &rsp_iu.cmd);

	if (rsp_code) {
		if (fc_rsp->flags & FCP_RSP_LEN_VALID)