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

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.comAcked-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
......@@ -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)
......
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