scsi: ibmvfc: add NVMe/FC Process Login support

Extend PRLI handling code to support NVMe/FC targets.

When the target protocol is NVMe/FC, issue the NVMe process login MAD,
set the NVMe FC-4 type, and populate NVMe-specific service parameters.
On completion, decode the returned PRLI service parameters and derive
the appropriate remote-port roles for NVMe initiator, target, and
discovery ports.

Keep the existing SCSI PRLI flow unchanged while allowing the common
target state machine to complete login for NVMe/FC targets.

Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Link: https://patch.msgid.link/20260723000149.969416-19-tyreld@linux.ibm.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Tyrel Datwyler
2026-07-22 17:01:34 -07:00
committed by Martin K. Petersen
parent 4bc896bf09
commit d11c05ddc2
2 changed files with 45 additions and 16 deletions

View File

@@ -4090,11 +4090,12 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
switch (status) {
case IBMVFC_MAD_SUCCESS:
tgt_dbg(tgt, "Process Login succeeded: %X %02X %04X\n",
parms->type, parms->flags, parms->service_parms);
tgt_dbg(tgt, "%s Process Login succeeded: %X %02X %04X\n",
proto_type[tgt->protocol], parms->type, parms->flags,
parms->service_parms);
index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags));
if (parms->type == IBMVFC_SCSI_FCP_TYPE) {
index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags));
if (prli_rsp[index].logged_in) {
if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) {
tgt->need_login = 0;
@@ -4110,6 +4111,22 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
else
ibmvfc_del_tgt(tgt);
} else if (parms->type == IBMVFC_NVME_FCP_TYPE) {
if (prli_rsp[index].logged_in) {
/* For FC-NVMe PRLI the Image Pair field is always set to zero (see 6.3.3) */
tgt->need_login = 0;
tgt->ids.roles = 0;
if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_NVME_TARGET)
tgt->ids.roles |= FC_PORT_ROLE_NVME_TARGET;
if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_NVME_INITIATOR)
tgt->ids.roles |= FC_PORT_ROLE_NVME_INITIATOR;
if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_NVME_DISCOVERY)
tgt->ids.roles |= FC_PORT_ROLE_NVME_DISCOVERY;
tgt->add_rport = 1;
} else if (prli_rsp[index].retry)
ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
else
ibmvfc_del_tgt(tgt);
} else
ibmvfc_del_tgt(tgt);
break;
@@ -4130,9 +4147,10 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
else
ibmvfc_del_tgt(tgt);
tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n",
ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)),
be16_to_cpu(rsp->status), be16_to_cpu(rsp->error), status);
tgt_log(tgt, level, "%s Process Login failed: %s (%x:%x) rc=0x%02X\n",
proto_type[tgt->protocol], ibmvfc_get_cmd_error(be16_to_cpu(rsp->status),
be16_to_cpu(rsp->error)), be16_to_cpu(rsp->status),
be16_to_cpu(rsp->error), status);
break;
}
@@ -4174,25 +4192,30 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
} else {
prli->common.version = cpu_to_be32(1);
}
prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN);
if (tgt->protocol == IBMVFC_PROTO_SCSI) {
prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN);
prli->parms.type = IBMVFC_SCSI_FCP_TYPE;
prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR);
prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC);
prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED);
if (cls3_error)
prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_RETRY);
} else {
prli->common.opcode = cpu_to_be32(IBMVFC_NVMF_PROCESS_LOGIN);
prli->parms.type = IBMVFC_NVME_FCP_TYPE;
prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_NVME_INITIATOR);
}
prli->common.length = cpu_to_be16(sizeof(*prli));
prli->scsi_id = cpu_to_be64(tgt->scsi_id);
prli->parms.type = IBMVFC_SCSI_FCP_TYPE;
prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR);
prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC);
prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED);
if (cls3_error)
prli->parms.service_parms |= cpu_to_be32(IBMVFC_PRLI_RETRY);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
if (ibmvfc_send_event(evt, vhost, default_timeout)) {
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
kref_put(&tgt->kref, ibmvfc_release_tgt);
} else
tgt_dbg(tgt, "Sent process login\n");
tgt_dbg(tgt, "%s Sent process login\n", proto_type[tgt->protocol]);
}
/**

View File

@@ -381,6 +381,7 @@ struct ibmvfc_move_login {
struct ibmvfc_prli_svc_parms {
u8 type;
#define IBMVFC_SCSI_FCP_TYPE 0x08
#define IBMVFC_NVME_FCP_TYPE 0x28
u8 type_ext;
__be16 flags;
#define IBMVFC_PRLI_ORIG_PA_VALID 0x8000
@@ -396,6 +397,11 @@ struct ibmvfc_prli_svc_parms {
#define IBMVFC_PRLI_TARGET_FUNC 0x00000010
#define IBMVFC_PRLI_READ_FCP_XFER_RDY_DISABLED 0x00000002
#define IBMVFC_PRLI_WR_FCP_XFER_RDY_DISABLED 0x00000001
#define IBMVFC_PRLI_NVME_PI_CTRL 0x00000200
#define IBMVFC_PRLI_NVME_SLER 0x00000100
#define IBMVFC_PRLI_NVME_INITIATOR 0x00000020
#define IBMVFC_PRLI_NVME_TARGET 0x00000010
#define IBMVFC_PRLI_NVME_DISCOVERY 0x00000008
} __packed __aligned(4);
struct ibmvfc_process_login {