diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-17 00:34:31 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-12-17 00:34:31 +0300 |
commit | 60f7c503d971a731ee3c4f884a9f2e80d476730d (patch) | |
tree | 30e23c822306b0e407f6218135feb5b2e847665d /drivers/scsi/ibmvscsi | |
parent | 69f637c33560b02ae7313e0c142d847361cc723a (diff) | |
parent | be1b500212541a70006887bae558ff834d7365d0 (diff) | |
download | linux-60f7c503d971a731ee3c4f884a9f2e80d476730d.tar.xz |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This consists of the usual driver updates (ufs, qla2xxx, smartpqi,
target, zfcp, fnic, mpt3sas, ibmvfc) plus a load of cleanups, a major
power management rework and a load of assorted minor updates.
There are a few core updates (formatting fixes being the big one) but
nothing major this cycle"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (279 commits)
scsi: mpt3sas: Update driver version to 36.100.00.00
scsi: mpt3sas: Handle trigger page after firmware update
scsi: mpt3sas: Add persistent MPI trigger page
scsi: mpt3sas: Add persistent SCSI sense trigger page
scsi: mpt3sas: Add persistent Event trigger page
scsi: mpt3sas: Add persistent Master trigger page
scsi: mpt3sas: Add persistent trigger pages support
scsi: mpt3sas: Sync time periodically between driver and firmware
scsi: qla2xxx: Update version to 10.02.00.104-k
scsi: qla2xxx: Fix device loss on 4G and older HBAs
scsi: qla2xxx: If fcport is undergoing deletion complete I/O with retry
scsi: qla2xxx: Fix the call trace for flush workqueue
scsi: qla2xxx: Fix flash update in 28XX adapters on big endian machines
scsi: qla2xxx: Handle aborts correctly for port undergoing deletion
scsi: qla2xxx: Fix N2N and NVMe connect retry failure
scsi: qla2xxx: Fix FW initialization error on big endian machines
scsi: qla2xxx: Fix crash during driver load on big endian machines
scsi: qla2xxx: Fix compilation issue in PPC systems
scsi: qla2xxx: Don't check for fw_started while posting NVMe command
scsi: qla2xxx: Tear down session if FW say it is down
...
Diffstat (limited to 'drivers/scsi/ibmvscsi')
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.c | 195 | ||||
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvfc.h | 28 |
2 files changed, 154 insertions, 69 deletions
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 070cf516b98f..42e4d35e0d35 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -138,6 +138,31 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *); static const char *unknown_error = "unknown error"; +static int ibmvfc_check_caps(struct ibmvfc_host *vhost, unsigned long cap_flags) +{ + u64 host_caps = be64_to_cpu(vhost->login_buf->resp.capabilities); + + 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 @@ -149,6 +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 = ibmvfc_get_fcp_iu(vhost, vfc_cmd); struct ibmvfc_trace_entry *entry; entry = &vhost->trace[vhost->trace_index++]; @@ -159,11 +185,11 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: - entry->op_code = vfc_cmd->iu.cdb[0]; + entry->op_code = iu->cdb[0]; entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); - entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); - entry->tmf_flags = vfc_cmd->iu.tmf_flags; - entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len); + entry->lun = scsilun_to_int(&iu->lun); + entry->tmf_flags = iu->tmf_flags; + entry->u.start.xfer_len = be32_to_cpu(iu->xfer_len); break; case IBMVFC_MAD_FORMAT: entry->op_code = be32_to_cpu(mad->opcode); @@ -183,6 +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 = 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; @@ -192,15 +220,15 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: - entry->op_code = vfc_cmd->iu.cdb[0]; + entry->op_code = iu->cdb[0]; entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); - entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); - entry->tmf_flags = vfc_cmd->iu.tmf_flags; + entry->lun = scsilun_to_int(&iu->lun); + entry->tmf_flags = iu->tmf_flags; entry->u.end.status = be16_to_cpu(vfc_cmd->status); entry->u.end.error = be16_to_cpu(vfc_cmd->error); - entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags; - entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code; - entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status; + entry->u.end.fcp_rsp_flags = rsp->flags; + entry->u.end.rsp_code = rsp->data.info.rsp_code; + entry->u.end.scsi_status = rsp->scsi_status; break; case IBMVFC_MAD_FORMAT: entry->op_code = be32_to_cpu(mad->opcode); @@ -260,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->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) && @@ -1227,7 +1255,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost) login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED); login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ); - login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE); + login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_SEND_VF_WWPN); login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token); login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs)); strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME); @@ -1378,6 +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 = ibmvfc_get_fcp_iu(evt->vhost, vfc_cmd); if (cls3_error) vfc_cmd->flags |= cpu_to_be16(IBMVFC_CLASS_3_ERR); @@ -1394,10 +1423,10 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, if (scmd->sc_data_direction == DMA_TO_DEVICE) { vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE); - vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA; + iu->add_cdb_len |= IBMVFC_WRDATA; } else { vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ); - vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA; + iu->add_cdb_len |= IBMVFC_RDDATA; } if (sg_mapped == 1) { @@ -1516,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->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)); @@ -1570,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->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); @@ -1584,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); @@ -1646,6 +1675,33 @@ static inline int ibmvfc_host_chkready(struct ibmvfc_host *vhost) return result; } +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; + 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); + vfc_cmd->target_wwpn = cpu_to_be64(rport->port_name); + } 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(*rsp)); + vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + 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, &iu->lun); + + return vfc_cmd; +} + /** * ibmvfc_queuecommand - The queuecommand function of the scsi template * @cmnd: struct scsi_cmnd to be executed @@ -1660,6 +1716,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; @@ -1675,24 +1732,20 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT); evt->cmnd = cmnd; cmnd->scsi_done = done; - vfc_cmd = &evt->iu.cmd; - memset(vfc_cmd, 0, sizeof(*vfc_cmd)); - vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); - vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp)); - vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu)); - vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp)); - vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata); - vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); - vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); - int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun); - memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len); + + vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device); + iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd); + + 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->iu.pri_task_attr = IBMVFC_SIMPLE_TASK; + iu->pri_task_attr = IBMVFC_SIMPLE_TASK; } + vfc_cmd->correlation = cpu_to_be64(evt); + if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev)))) return ibmvfc_send_event(evt, vhost, 0); @@ -2016,7 +2069,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.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; @@ -2025,19 +2079,13 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) if (vhost->state == IBMVFC_ACTIVE) { 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 = &evt->iu.cmd; - memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); - tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); - tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); - tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); - int_to_scsilun(sdev->lun, &tmf->iu.lun); tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); - tmf->iu.tmf_flags = type; + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + tmf->target_wwpn = cpu_to_be64(rport->port_name); + iu->tmf_flags = type; evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -2055,7 +2103,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) @@ -2227,12 +2275,17 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + tmf->common.version = cpu_to_be32(2); + tmf->target_wwpn = cpu_to_be64(rport->port_name); + } else { + tmf->common.version = cpu_to_be32(1); + } tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); tmf->common.length = cpu_to_be16(sizeof(*tmf)); tmf->scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->lun); - if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS)) + if (!ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPRESS_ABTS)) type &= ~IBMVFC_TMF_SUPPRESS_ABTS; if (vhost->state == IBMVFC_ACTIVE) tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID)); @@ -2331,7 +2384,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.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; @@ -2355,21 +2409,17 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) if (vhost->state == IBMVFC_ACTIVE) { 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 = &evt->iu.cmd; - memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); - tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); - tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); - tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); - tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); - tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); - int_to_scsilun(sdev->lun, &tmf->iu.lun); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) + tmf->target_wwpn = cpu_to_be64(rport->port_name); + iu->tmf_flags = IBMVFC_ABORT_TASK_SET; tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); - tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; + tmf->correlation = cpu_to_be64(evt); + init_completion(&evt->comp); rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout); } @@ -2414,7 +2464,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) @@ -3025,7 +3075,7 @@ static ssize_t ibmvfc_show_host_npiv_version(struct device *dev, { struct Scsi_Host *shost = class_to_shost(dev); struct ibmvfc_host *vhost = shost_priv(shost); - return snprintf(buf, PAGE_SIZE, "%d\n", vhost->login_buf->resp.version); + return snprintf(buf, PAGE_SIZE, "%d\n", be32_to_cpu(vhost->login_buf->resp.version)); } static ssize_t ibmvfc_show_host_capabilities(struct device *dev, @@ -3033,7 +3083,7 @@ static ssize_t ibmvfc_show_host_capabilities(struct device *dev, { struct Scsi_Host *shost = class_to_shost(dev); struct ibmvfc_host *vhost = shost_priv(shost); - return snprintf(buf, PAGE_SIZE, "%llx\n", vhost->login_buf->resp.capabilities); + return snprintf(buf, PAGE_SIZE, "%llx\n", be64_to_cpu(vhost->login_buf->resp.capabilities)); } /** @@ -3445,7 +3495,12 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt) evt->tgt = tgt; prli = &evt->iu.prli; memset(prli, 0, sizeof(*prli)); - prli->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + prli->common.version = cpu_to_be32(2); + prli->target_wwpn = cpu_to_be64(tgt->wwpn); + } else { + prli->common.version = cpu_to_be32(1); + } prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN); prli->common.length = cpu_to_be16(sizeof(*prli)); prli->scsi_id = cpu_to_be64(tgt->scsi_id); @@ -3548,7 +3603,12 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt) evt->tgt = tgt; plogi = &evt->iu.plogi; memset(plogi, 0, sizeof(*plogi)); - plogi->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + plogi->common.version = cpu_to_be32(2); + plogi->target_wwpn = cpu_to_be64(tgt->wwpn); + } else { + plogi->common.version = cpu_to_be32(1); + } plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); plogi->common.length = cpu_to_be16(sizeof(*plogi)); plogi->scsi_id = cpu_to_be64(tgt->scsi_id); @@ -3948,7 +4008,12 @@ static void ibmvfc_adisc_timeout(struct timer_list *t) evt->tgt = tgt; tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = cpu_to_be32(1); + if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) { + tmf->common.version = cpu_to_be32(2); + tmf->target_wwpn = cpu_to_be64(tgt->wwpn); + } else { + tmf->common.version = cpu_to_be32(1); + } tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); tmf->common.length = cpu_to_be16(sizeof(*tmf)); tmf->scsi_id = cpu_to_be64(tgt->scsi_id); @@ -4391,7 +4456,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) ibmvfc_dbg(vhost, "Sent NPIV login\n"); else ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); -}; +} /** * ibmvfc_npiv_logout_done - Completion handler for NPIV Logout diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 34debccfb142..9d58cfd774d3 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -54,6 +54,7 @@ #define IBMVFC_MAD_SUCCESS 0x00 #define IBMVFC_MAD_NOT_SUPPORTED 0xF1 +#define IBMVFC_MAD_VERSION_NOT_SUPP 0xF2 #define IBMVFC_MAD_FAILED 0xF7 #define IBMVFC_MAD_DRIVER_FAILED 0xEE #define IBMVFC_MAD_CRQ_ERROR 0xEF @@ -168,6 +169,8 @@ struct ibmvfc_npiv_login { #define IBMVFC_CAN_MIGRATE 0x01 #define IBMVFC_CAN_USE_CHANNELS 0x02 #define IBMVFC_CAN_HANDLE_FPIN 0x04 +#define IBMVFC_CAN_USE_MAD_VERSION 0x08 +#define IBMVFC_CAN_SEND_VF_WWPN 0x10 __be64 node_name; struct srp_direct_buf async; u8 partition_name[IBMVFC_MAX_NAME]; @@ -211,7 +214,9 @@ struct ibmvfc_npiv_login_resp { __be64 capabilities; #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 #define IBMVFC_CAN_SUPPRESS_ABTS 0x10 -#define IBMVFC_CAN_SUPPORT_CHANNELS 0x20 +#define IBMVFC_MAD_VERSION_CAP 0x20 +#define IBMVFC_HANDLE_VF_WWPN 0x40 +#define IBMVFC_CAN_SUPPORT_CHANNELS 0x80 __be32 max_cmds; __be32 scsi_id_sz; __be64 max_dma_len; @@ -293,6 +298,7 @@ struct ibmvfc_port_login { __be32 reserved2; struct ibmvfc_service_parms service_parms; struct ibmvfc_service_parms service_parms_change; + __be64 target_wwpn; __be64 reserved3[2]; } __packed __aligned(8); @@ -344,6 +350,7 @@ struct ibmvfc_process_login { __be16 status; __be16 error; /* also fc_reason */ __be32 reserved2; + __be64 target_wwpn; __be64 reserved3[2]; } __packed __aligned(8); @@ -378,6 +385,8 @@ struct ibmvfc_tmf { __be32 cancel_key; __be32 my_cancel_key; __be32 pad; + __be64 target_wwpn; + __be64 task_tag; __be64 reserved[2]; } __packed __aligned(8); @@ -474,9 +483,19 @@ struct ibmvfc_cmd { __be64 correlation; __be64 tgt_scsi_id; __be64 tag; - __be64 reserved3[2]; - struct ibmvfc_fcp_cmd_iu iu; - struct ibmvfc_fcp_rsp rsp; + __be64 target_wwpn; + __be64 reserved3; + union { + struct { + struct ibmvfc_fcp_cmd_iu iu; + struct ibmvfc_fcp_rsp rsp; + } v1; + struct { + __be64 reserved4; + struct ibmvfc_fcp_cmd_iu iu; + struct ibmvfc_fcp_rsp rsp; + } v2; + }; } __packed __aligned(8); struct ibmvfc_passthru_fc_iu { @@ -503,6 +522,7 @@ struct ibmvfc_passthru_iu { __be64 correlation; __be64 scsi_id; __be64 tag; + __be64 target_wwpn; __be64 reserved2[2]; } __packed __aligned(8); |