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) ...@@ -145,6 +145,24 @@ static int ibmvfc_check_caps(struct ibmvfc_host *vhost, unsigned long cap_flags)
return (host_caps & cap_flags) ? 1 : 0; 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 #ifdef CONFIG_SCSI_IBMVFC_TRACE
/** /**
* ibmvfc_trc_start - Log a start trace entry * ibmvfc_trc_start - Log a start trace entry
...@@ -156,7 +174,7 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) ...@@ -156,7 +174,7 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)
struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd;
struct ibmvfc_mad_common *mad = &evt->iu.mad_common; 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; struct ibmvfc_trace_entry *entry;
entry = &vhost->trace[vhost->trace_index++]; entry = &vhost->trace[vhost->trace_index++];
...@@ -191,8 +209,8 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) ...@@ -191,8 +209,8 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)
struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common; struct ibmvfc_mad_common *mad = &evt->xfer_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_fcp_rsp *rsp = &vfc_cmd->v1.rsp; struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd);
struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++]; struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++];
entry->evt = evt; entry->evt = evt;
...@@ -270,10 +288,10 @@ static const char *ibmvfc_get_cmd_error(u16 status, u16 error) ...@@ -270,10 +288,10 @@ static const char *ibmvfc_get_cmd_error(u16 status, u16 error)
* Return value: * Return value:
* SCSI result value to return for completed command * 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; 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); int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
if ((rsp->flags & FCP_RSP_LEN_VALID) && if ((rsp->flags & FCP_RSP_LEN_VALID) &&
...@@ -1388,7 +1406,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, ...@@ -1388,7 +1406,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd,
int sg_mapped; int sg_mapped;
struct srp_direct_buf *data = &vfc_cmd->ioba; struct srp_direct_buf *data = &vfc_cmd->ioba;
struct ibmvfc_host *vhost = dev_get_drvdata(dev); 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) if (cls3_error)
vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR); vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR);
...@@ -1527,7 +1545,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) ...@@ -1527,7 +1545,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt)
{ {
struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd;
struct ibmvfc_host *vhost = evt->vhost; 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; struct scsi_cmnd *cmnd = evt->cmnd;
const char *err = unknown_error; const char *err = unknown_error;
int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->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) ...@@ -1581,7 +1599,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev)
static void ibmvfc_scsi_done(struct ibmvfc_event *evt) static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
{ {
struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; 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; struct scsi_cmnd *cmnd = evt->cmnd;
u32 rsp_len = 0; u32 rsp_len = 0;
u32 sense_len = be32_to_cpu(rsp->fcp_sense_len); u32 sense_len = be32_to_cpu(rsp->fcp_sense_len);
...@@ -1595,7 +1613,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) ...@@ -1595,7 +1613,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
scsi_set_resid(cmnd, 0); scsi_set_resid(cmnd, 0);
if (vfc_cmd->status) { 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) if (rsp->flags & FCP_RSP_LEN_VALID)
rsp_len = be32_to_cpu(rsp->fcp_rsp_len); rsp_len = be32_to_cpu(rsp->fcp_rsp_len);
...@@ -1660,18 +1678,25 @@ static inline int ibmvfc_host_chkready(struct ibmvfc_host *vhost) ...@@ -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) 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 fc_rport *rport = starget_to_rport(scsi_target(sdev));
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_cmd *vfc_cmd = &evt->iu.cmd; 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)); 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.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->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE);
vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->v1.iu)); vfc_cmd->payload_len = cpu_to_be32(sizeof(*iu));
vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->v1.rsp)); vfc_cmd->resp_len = cpu_to_be32(sizeof(*rsp));
vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); vfc_cmd->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); 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; return vfc_cmd;
} }
...@@ -1690,6 +1715,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, ...@@ -1690,6 +1715,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
struct ibmvfc_host *vhost = shost_priv(cmnd->device->host); struct ibmvfc_host *vhost = shost_priv(cmnd->device->host);
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
struct ibmvfc_cmd *vfc_cmd; struct ibmvfc_cmd *vfc_cmd;
struct ibmvfc_fcp_cmd_iu *iu;
struct ibmvfc_event *evt; struct ibmvfc_event *evt;
int rc; int rc;
...@@ -1707,13 +1733,14 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, ...@@ -1707,13 +1733,14 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
cmnd->scsi_done = done; cmnd->scsi_done = done;
vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device); 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)); iu->xfer_len = cpu_to_be32(scsi_bufflen(cmnd));
memcpy(vfc_cmd->v1.iu.cdb, cmnd->cmnd, cmnd->cmd_len); memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
if (cmnd->flags & SCMD_TAGGED) { if (cmnd->flags & SCMD_TAGGED) {
vfc_cmd->task_tag = cpu_to_be64(cmnd->tag); 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); vfc_cmd->correlation = cpu_to_be64(evt);
...@@ -2040,7 +2067,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) ...@@ -2040,7 +2067,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
struct ibmvfc_cmd *tmf; struct ibmvfc_cmd *tmf;
struct ibmvfc_event *evt = NULL; struct ibmvfc_event *evt = NULL;
union ibmvfc_iu rsp_iu; 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; int rsp_rc = -EBUSY;
unsigned long flags; unsigned long flags;
int rsp_code = 0; int rsp_code = 0;
...@@ -2050,9 +2078,10 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) ...@@ -2050,9 +2078,10 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
evt = ibmvfc_get_event(vhost); evt = ibmvfc_get_event(vhost);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
tmf = ibmvfc_init_vfc_cmd(evt, sdev); 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->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; evt->sync_iu = &rsp_iu;
init_completion(&evt->comp); init_completion(&evt->comp);
...@@ -2070,7 +2099,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) ...@@ -2070,7 +2099,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
wait_for_completion(&evt->comp); wait_for_completion(&evt->comp);
if (rsp_iu.cmd.status) 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 (rsp_code) {
if (fc_rsp->flags & FCP_RSP_LEN_VALID) if (fc_rsp->flags & FCP_RSP_LEN_VALID)
...@@ -2345,7 +2374,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) ...@@ -2345,7 +2374,8 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
struct ibmvfc_cmd *tmf; struct ibmvfc_cmd *tmf;
struct ibmvfc_event *evt, *found_evt; struct ibmvfc_event *evt, *found_evt;
union ibmvfc_iu rsp_iu; 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; int rc, rsp_rc = -EBUSY;
unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT; unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT;
int rsp_code = 0; int rsp_code = 0;
...@@ -2370,9 +2400,10 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) ...@@ -2370,9 +2400,10 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
evt = ibmvfc_get_event(vhost); evt = ibmvfc_get_event(vhost);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT); ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
tmf = ibmvfc_init_vfc_cmd(evt, sdev); 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->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF));
tmf->v1.iu.tmf_flags = IBMVFC_ABORT_TASK_SET;
evt->sync_iu = &rsp_iu; evt->sync_iu = &rsp_iu;
tmf->correlation = cpu_to_be64(evt); tmf->correlation = cpu_to_be64(evt);
...@@ -2421,7 +2452,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) ...@@ -2421,7 +2452,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
} }
if (rsp_iu.cmd.status) 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 (rsp_code) {
if (fc_rsp->flags & FCP_RSP_LEN_VALID) 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