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 <[email protected]>
---
 drivers/scsi/ibmvscsi/ibmvfc-core.c | 55 ++++++++++++++++++++---------
 drivers/scsi/ibmvscsi/ibmvfc.h      |  6 ++++
 2 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c 
b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index 2c54d0b9add4..b45cd0183fb5 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -4088,11 +4088,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;
@@ -4108,6 +4109,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;
@@ -4128,9 +4145,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;
        }
 
@@ -4172,25 +4190,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]);
 }
 
 /**
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 67f546ff092e..66025e6ffeed 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -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 {
-- 
2.54.0


Reply via email to