From: Duane Grigsby <duane.grig...@cavium.com>

Signed-off-by: Darren Trapp <darren.tr...@cavium.com>
Signed-off-by: Duane Grigsby <duane.grig...@cavium.com>
Signed-off-by: Anil Gurumurthy <anil.gurumur...@cavium.com>
Signed-off-by: Giridhar Malavali <giridhar.malav...@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madh...@cavium.com>
---
 drivers/scsi/qla2xxx/qla_dbg.c    |   9 +-
 drivers/scsi/qla2xxx/qla_def.h    |  31 ++++++-
 drivers/scsi/qla2xxx/qla_fw.h     |  13 ++-
 drivers/scsi/qla2xxx/qla_gbl.h    |   1 +
 drivers/scsi/qla2xxx/qla_init.c   | 168 ++++++++++++++++++++++++++++++++++++--
 drivers/scsi/qla2xxx/qla_iocb.c   |  21 +++++
 drivers/scsi/qla2xxx/qla_mbx.c    |  33 +++++---
 drivers/scsi/qla2xxx/qla_os.c     |   4 +
 drivers/scsi/qla2xxx/qla_target.c |   4 +-
 9 files changed, 257 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index c0c90dcc7c7b..cf4f47603a91 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -15,9 +15,10 @@
  * |                              |                    | 0x015b-0x0160 |
  * |                              |                    | 0x016e                
|
  * | Mailbox commands             |       0x1199       | 0x1193                
|
- * | Device Discovery             |       0x2004       | 0x2016                
|
- * |                              |                    | 0x2011-0x2012, |
- * |                              |                    | 0x2099-0x20a4  |
+ * | Device Discovery             |       0x2131       | 0x210e-0x2116  |
+ * |                             |                    | 0x211a         |
+ * |                              |                    | 0x211c-0x2128  |
+ * |                              |                    | 0x212a-0x2130  |
  * | Queue Command and IO tracing |       0x3074       | 0x300b         |
  * |                              |                    | 0x3027-0x3028  |
  * |                              |                    | 0x303d-0x3041  |
@@ -59,7 +60,7 @@
  * |                              |                    | 0xb13c-0xb140  |
  * |                              |                    | 0xb149                
|
  * | MultiQ                       |       0xc010       |               |
- * | Misc                         |       0xd301       | 0xd031-0xd0ff |
+ * | Misc                         |       0xd302       | 0xd031-0xd0ff |
  * |                              |                    | 0xd101-0xd1fe |
  * |                              |                    | 0xd214-0xd2fe |
  * | Target Mode                 |       0xe081       |                |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index e1af9db3691d..bd1b3fef95a4 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -343,6 +343,7 @@ struct srb_iocb {
 #define SRB_LOGIN_RETRIED      BIT_0
 #define SRB_LOGIN_COND_PLOGI   BIT_1
 #define SRB_LOGIN_SKIP_PRLI    BIT_2
+#define SRB_LOGIN_NVME_PRLI    BIT_3
                        uint16_t data[2];
                        u32 iop[2];
                } logio;
@@ -436,6 +437,7 @@ struct srb_iocb {
 #define SRB_NACK_PLOGI 16
 #define SRB_NACK_PRLI  17
 #define SRB_NACK_LOGO  18
+#define SRB_PRLI_CMD   21
 
 enum {
        TYPE_SRB,
@@ -1088,6 +1090,7 @@ struct mbx_cmd_32 {
 #define        MBX_1           BIT_1
 #define        MBX_0           BIT_0
 
+#define RNID_TYPE_PORT_LOGIN   0x7
 #define RNID_TYPE_SET_VERSION  0x9
 #define RNID_TYPE_ASIC_TEMP    0xC
 
@@ -2152,10 +2155,12 @@ typedef struct {
        uint8_t fabric_port_name[WWN_SIZE];
        uint16_t fp_speed;
        uint8_t fc4_type;
+       uint8_t fc4f_nvme;      /* nvme fc4 feature bits */
 } sw_info_t;
 
 /* FCP-4 types */
 #define FC4_TYPE_FCP_SCSI      0x08
+#define FC4_TYPE_NVME          0x28
 #define FC4_TYPE_OTHER         0x0
 #define FC4_TYPE_UNKNOWN       0xff
 
@@ -2180,7 +2185,8 @@ typedef enum {
        FCT_SWITCH,
        FCT_BROADCAST,
        FCT_INITIATOR,
-       FCT_TARGET
+       FCT_TARGET,
+       FCT_NVME
 } fc_port_type_t;
 
 enum qla_sess_deletion {
@@ -2237,10 +2243,12 @@ enum fcport_mgt_event {
        FCME_RSCN,
        FCME_GIDPN_DONE,
        FCME_PLOGI_DONE,        /* Initiator side sent LLIOCB */
+       FCME_PRLI_DONE,
        FCME_GNL_DONE,
        FCME_GPSC_DONE,
        FCME_GPDB_DONE,
        FCME_GPNID_DONE,
+       FCME_GFFID_DONE,
        FCME_DELETE_DONE,
 };
 
@@ -2274,6 +2282,16 @@ typedef struct fc_port {
        unsigned int login_pause:1;
        unsigned int login_succ:1;
 
+       struct work_struct nvme_del_work;
+       atomic_t nvme_ref_count;
+       uint32_t nvme_prli_service_param;
+#define NVME_PRLI_SP_CONF       BIT_7
+#define NVME_PRLI_SP_INITIATOR  BIT_5
+#define NVME_PRLI_SP_TARGET     BIT_4
+#define NVME_PRLI_SP_DISCOVERY  BIT_3
+       uint8_t nvme_flag;
+#define NVME_FLAG_REGISTERED 4
+
        struct fc_port *conflict;
        unsigned char logout_completed;
        int generation;
@@ -2306,6 +2324,7 @@ typedef struct fc_port {
        u32 supported_classes;
 
        uint8_t fc4_type;
+       uint8_t fc4f_nvme;
        uint8_t scan_state;
 
        unsigned long last_queue_full;
@@ -2313,6 +2332,8 @@ typedef struct fc_port {
 
        uint16_t port_id;
 
+       struct nvme_fc_remote_port *nvme_remote_port;
+
        unsigned long retry_delay_timestamp;
        struct qla_tgt_sess *tgt_session;
        struct ct_sns_desc ct_desc;
@@ -2745,7 +2766,7 @@ struct ct_sns_req {
 
                struct {
                        uint8_t reserved;
-                       uint8_t port_name[3];
+                       uint8_t port_id[3];
                } gff_id;
 
                struct {
@@ -3052,6 +3073,7 @@ enum qla_work_type {
        QLA_EVT_GPNID_DONE,
        QLA_EVT_NEW_SESS,
        QLA_EVT_GPDB,
+       QLA_EVT_PRLI,
        QLA_EVT_GPSC,
        QLA_EVT_UPD_FCPORT,
        QLA_EVT_GNL,
@@ -4007,6 +4029,7 @@ typedef struct scsi_qla_host {
                uint32_t        qpairs_available:1;
                uint32_t        qpairs_req_created:1;
                uint32_t        qpairs_rsp_created:1;
+               uint32_t        nvme_enabled:1;
        } flags;
 
        atomic_t        loop_state;
@@ -4085,6 +4108,10 @@ typedef struct scsi_qla_host {
        uint8_t         port_name[WWN_SIZE];
        uint8_t         fabric_node_name[WWN_SIZE];
 
+       struct          nvme_fc_local_port *nvme_local_port;
+       atomic_t        nvme_ref_count;
+       struct list_head nvme_rport_list;
+
        uint16_t        fcoe_vlan_id;
        uint16_t        fcoe_fcf_idx;
        uint8_t         fcoe_vn_port_mac[6];
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 1f808928763b..dcae62d4cbeb 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -37,6 +37,12 @@ struct port_database_24xx {
 #define PDF_CLASS_2            BIT_4
 #define PDF_HARD_ADDR          BIT_1
 
+       /*
+        * for NVMe, the login_state field has been
+        * split into nibbles.
+        * The lower nibble is for FCP.
+        * The upper nibble is for NVMe.
+        */
        uint8_t current_login_state;
        uint8_t last_login_state;
 #define PDS_PLOGI_PENDING      0x03
@@ -69,7 +75,11 @@ struct port_database_24xx {
        uint8_t port_name[WWN_SIZE];
        uint8_t node_name[WWN_SIZE];
 
-       uint8_t reserved_3[24];
+       uint8_t reserved_3[4];
+       uint16_t prli_nvme_svc_param_word_0;    /* Bits 15-0 of word 0 */
+       uint16_t prli_nvme_svc_param_word_3;    /* Bits 15-0 of word 3 */
+       uint16_t nvme_first_burst_size;
+       uint8_t reserved_4[14];
 };
 
 /*
@@ -819,6 +829,7 @@ struct logio_entry_24xx {
 #define LCF_CLASS_2            BIT_8   /* Enable class 2 during PLOGI. */
 #define LCF_FREE_NPORT         BIT_7   /* Release NPORT handle after LOGO. */
 #define LCF_EXPL_LOGO          BIT_6   /* Perform an explicit LOGO. */
+#define LCF_NVME_PRLI          BIT_6   /* Perform NVME FC4 PRLI */
 #define LCF_SKIP_PRLI          BIT_5   /* Skip PRLI after PLOGI. */
 #define LCF_IMPL_LOGO_ALL      BIT_5   /* Implicit LOGO to all ports. */
 #define LCF_COND_PLOGI         BIT_4   /* PLOGI only if not logged-in. */
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index beebf96c23d4..6fbee11c1a18 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -99,6 +99,7 @@ extern struct qla_qpair *qla2xxx_create_qpair(struct 
scsi_qla_host *,
 extern int qla2xxx_delete_qpair(struct scsi_qla_host *, struct qla_qpair *);
 void qla2x00_fcport_event_handler(scsi_qla_host_t *, struct event_arg *);
 int qla24xx_async_gpdb(struct scsi_qla_host *, fc_port_t *, u8);
+int qla24xx_async_prli(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_notify_ack(scsi_qla_host_t *, fc_port_t *,
        struct imm_ntfy_from_isp *, int);
 int qla24xx_post_newsess_work(struct scsi_qla_host *, port_id_t *, u8 *,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 48c0a58330d4..8a2586a04961 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -37,8 +37,11 @@ static struct qla_chip_state_84xx *qla84xx_get_chip(struct 
scsi_qla_host *);
 static int qla84xx_init_chip(scsi_qla_host_t *);
 static int qla25xx_init_queues(struct qla_hw_data *);
 static int qla24xx_post_gpdb_work(struct scsi_qla_host *, fc_port_t *, u8);
+static int qla24xx_post_prli_work(struct scsi_qla_host*, fc_port_t *);
 static void qla24xx_handle_plogi_done_event(struct scsi_qla_host *,
     struct event_arg *);
+static void qla24xx_handle_prli_done_event(struct scsi_qla_host *,
+    struct event_arg *);
 
 /* SRB Extensions ---------------------------------------------------------- */
 
@@ -191,6 +194,10 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t 
*fcport,
        lio->timeout = qla2x00_async_iocb_timeout;
        sp->done = qla2x00_async_login_sp_done;
        lio->u.logio.flags |= SRB_LOGIN_COND_PLOGI;
+
+       if (fcport->fc4f_nvme)
+               lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
+
        if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
                lio->u.logio.flags |= SRB_LOGIN_RETRIED;
        rval = qla2x00_start_sp(sp);
@@ -327,7 +334,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t 
*vha,
        u16 i, n, found = 0, loop_id;
        port_id_t id;
        u64 wwn;
-       u8 opt = 0;
+       u8 opt = 0, current_login_state;
 
        fcport = ea->fcport;
 
@@ -414,7 +421,12 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t 
*vha,
                        fcport->login_pause = 1;
                }
 
-               switch (e->current_login_state) {
+               if  (fcport->fc4f_nvme)
+                       current_login_state = e->current_login_state >> 4;
+               else
+                       current_login_state = e->current_login_state & 0xf;
+
+               switch (current_login_state) {
                case DSC_LS_PRLI_COMP:
                        ql_dbg(ql_dbg_disc, vha, 0x20e4,
                            "%s %d %8phC post gpdb\n",
@@ -422,7 +434,6 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t 
*vha,
                        opt = PDO_FORCE_ADISC;
                        qla24xx_post_gpdb_work(vha, fcport, opt);
                        break;
-
                case DSC_LS_PORT_UNAVAIL:
                default:
                        if (fcport->loop_id == FC_NO_LOOP_ID) {
@@ -665,6 +676,104 @@ void qla24xx_async_gpdb_sp_done(void *s, int res)
        sp->free(sp);
 }
 
+static int qla24xx_post_prli_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+       struct qla_work_evt *e;
+
+       e = qla2x00_alloc_work(vha, QLA_EVT_PRLI);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+
+       e->u.fcport.fcport = fcport;
+
+       return qla2x00_post_work(vha, e);
+}
+
+static void
+qla2x00_async_prli_sp_done(void *ptr, int res)
+{
+       srb_t *sp = ptr;
+       struct scsi_qla_host *vha = sp->vha;
+       struct srb_iocb *lio = &sp->u.iocb_cmd;
+       struct event_arg ea;
+
+       ql_dbg(ql_dbg_disc, vha, 0x2129,
+           "%s %8phC res %d \n", __func__,
+           sp->fcport->port_name, res);
+
+       sp->fcport->flags &= ~FCF_ASYNC_SENT;
+
+       if (!test_bit(UNLOADING, &vha->dpc_flags)) {
+               memset(&ea, 0, sizeof(ea));
+               ea.event = FCME_PRLI_DONE;
+               ea.fcport = sp->fcport;
+               ea.data[0] = lio->u.logio.data[0];
+               ea.data[1] = lio->u.logio.data[1];
+               ea.iop[0] = lio->u.logio.iop[0];
+               ea.iop[1] = lio->u.logio.iop[1];
+               ea.sp = sp;
+
+               qla2x00_fcport_event_handler(vha, &ea);
+       }
+
+       sp->free(sp);
+}
+
+int
+qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+       srb_t *sp;
+       struct srb_iocb *lio;
+       int rval = QLA_FUNCTION_FAILED;
+
+       if (!vha->flags.online)
+               return rval;
+
+       if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+           (fcport->fw_login_state == DSC_LS_PLOGI_COMP) ||
+           (fcport->fw_login_state == DSC_LS_PRLI_PEND))
+               return rval;
+
+       sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
+       if (!sp)
+               return rval;
+
+       fcport->flags |= FCF_ASYNC_SENT;
+       fcport->logout_completed = 0;
+
+       sp->type = SRB_PRLI_CMD;
+       sp->name = "prli";
+       qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
+
+       lio = &sp->u.iocb_cmd;
+       lio->timeout = qla2x00_async_iocb_timeout;
+       sp->done = qla2x00_async_prli_sp_done;
+       lio->u.logio.flags = 0;
+
+       if  (fcport->fc4f_nvme)
+               lio->u.logio.flags |= SRB_LOGIN_NVME_PRLI;
+
+       rval = qla2x00_start_sp(sp);
+       if (rval != QLA_SUCCESS) {
+               fcport->flags &= ~FCF_ASYNC_SENT;
+               fcport->flags |= FCF_LOGIN_NEEDED;
+               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+               goto done_free_sp;
+       }
+
+       ql_dbg(ql_dbg_disc, vha, 0x211b,
+           "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d.\n",
+           fcport->port_name, sp->handle, fcport->loop_id,
+           fcport->d_id.b24, fcport->login_retry);
+
+       return rval;
+
+done_free_sp:
+       sp->free(sp);
+       fcport->flags &= ~FCF_ASYNC_SENT;
+       return rval;
+}
+
 static int qla24xx_post_gpdb_work(struct scsi_qla_host *vha, fc_port_t *fcport,
     u8 opt)
 {
@@ -1126,6 +1235,9 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, 
struct event_arg *ea)
        case FCME_PLOGI_DONE:   /* Initiator side sent LLIOCB */
                qla24xx_handle_plogi_done_event(vha, ea);
                break;
+       case FCME_PRLI_DONE:
+               qla24xx_handle_prli_done_event(vha, ea);
+               break;
        case FCME_GPDB_DONE:
                qla24xx_handle_gpdb_event(vha, ea);
                break;
@@ -1308,6 +1420,27 @@ qla24xx_async_abort_command(srb_t *sp)
 }
 
 static void
+qla24xx_handle_prli_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
+{
+       switch (ea->data[0]) {
+       case MBS_COMMAND_COMPLETE:
+               ql_dbg(ql_dbg_disc, vha, 0x2118,
+                   "%s %d %8phC post gpdb\n",
+                   __func__, __LINE__, ea->fcport->port_name);
+
+               ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
+               ea->fcport->logout_on_delete = 1;
+               qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+               break;
+       default:
+               ql_dbg(ql_dbg_disc, vha, 0x2119,
+                   "%s %d %8phC unhandle event of %x\n",
+                   __func__, __LINE__, ea->fcport->port_name, ea->data[0]);
+               break;
+       }
+}
+
+static void
 qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg 
*ea)
 {
        port_id_t cid;  /* conflict Nport id */
@@ -1319,12 +1452,19 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host 
*vha, struct event_arg *ea)
                 * force a relogin attempt via implicit LOGO, PLOGI, and PRLI
                 * requests.
                 */
-               ql_dbg(ql_dbg_disc, vha, 0x20ea,
-                   "%s %d %8phC post gpdb\n",
-                   __func__, __LINE__, ea->fcport->port_name);
-               ea->fcport->chip_reset = vha->hw->base_qpair->chip_reset;
-               ea->fcport->logout_on_delete = 1;
-               qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+               if (ea->fcport->fc4f_nvme) {
+                       ql_dbg(ql_dbg_disc, vha, 0x2117,
+                               "%s %d %8phC post prli\n",
+                               __func__, __LINE__, ea->fcport->port_name);
+                       qla24xx_post_prli_work(vha, ea->fcport);
+               } else {
+                       ql_dbg(ql_dbg_disc, vha, 0x20ea,
+                               "%s %d %8phC post gpdb\n",
+                               __func__, __LINE__, ea->fcport->port_name);
+                       ea->fcport->chip_reset = 
vha->hw->base_qpair->chip_reset;
+                       ea->fcport->logout_on_delete = 1;
+                       qla24xx_post_gpdb_work(vha, ea->fcport, 0);
+               }
                break;
        case MBS_COMMAND_ERROR:
                ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %d %8phC cmd error %x\n",
@@ -4639,6 +4779,16 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha)
                                new_fcport->fp_speed = swl[swl_idx].fp_speed;
                                new_fcport->fc4_type = swl[swl_idx].fc4_type;
 
+                               new_fcport->nvme_flag = 0;
+                               if (vha->flags.nvme_enabled &&
+                                   swl[swl_idx].fc4f_nvme) {
+                                       new_fcport->fc4f_nvme =
+                                           swl[swl_idx].fc4f_nvme;
+                                       ql_log(ql_log_info, vha, 0x2131,
+                                           "FOUND: NVME port %8phC as FC Type 
28h\n",
+                                           new_fcport->port_name);
+                               }
+
                                if (swl[swl_idx].d_id.b.rsvd_1 != 0) {
                                        last_dev = 1;
                                }
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index ac49febbac76..daa53235a28a 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2211,12 +2211,30 @@ qla2x00_alloc_iocbs(struct scsi_qla_host *vha, srb_t 
*sp)
 }
 
 static void
+qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
+{
+       struct srb_iocb *lio = &sp->u.iocb_cmd;
+
+       logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
+       logio->control_flags = cpu_to_le16(LCF_COMMAND_PRLI);
+       if (lio->u.logio.flags & SRB_LOGIN_NVME_PRLI)
+               logio->control_flags |= LCF_NVME_PRLI;
+
+       logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
+       logio->port_id[0] = sp->fcport->d_id.b.al_pa;
+       logio->port_id[1] = sp->fcport->d_id.b.area;
+       logio->port_id[2] = sp->fcport->d_id.b.domain;
+       logio->vp_index = sp->vha->vp_idx;
+}
+
+static void
 qla24xx_login_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 {
        struct srb_iocb *lio = &sp->u.iocb_cmd;
 
        logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
        logio->control_flags = cpu_to_le16(LCF_COMMAND_PLOGI);
+
        if (lio->u.logio.flags & SRB_LOGIN_COND_PLOGI)
                logio->control_flags |= cpu_to_le16(LCF_COND_PLOGI);
        if (lio->u.logio.flags & SRB_LOGIN_SKIP_PRLI)
@@ -3162,6 +3180,9 @@ qla2x00_start_sp(srb_t *sp)
                    qla24xx_login_iocb(sp, pkt) :
                    qla2x00_login_iocb(sp, pkt);
                break;
+       case SRB_PRLI_CMD:
+               qla24xx_prli_iocb(sp, pkt);
+               break;
        case SRB_LOGOUT_CMD:
                IS_FWI2_CAPABLE(ha) ?
                    qla24xx_logout_iocb(sp, pkt) :
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f02a2baffb5b..1eac67e8fdfd 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -5968,14 +5968,22 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, 
fc_port_t *fcport,
 {
        int rval = QLA_SUCCESS;
        uint64_t zero = 0;
+       u8 current_login_state, last_login_state;
+
+       if (fcport->fc4f_nvme) {
+               current_login_state = pd->current_login_state >> 4;
+               last_login_state = pd->last_login_state >> 4;
+       } else {
+               current_login_state = pd->current_login_state & 0xf;
+               last_login_state = pd->last_login_state & 0xf;
+       }
 
        /* Check for logged in state. */
-       if (pd->current_login_state != PDS_PRLI_COMPLETE &&
-               pd->last_login_state != PDS_PRLI_COMPLETE) {
+       if (current_login_state != PDS_PRLI_COMPLETE &&
+           last_login_state != PDS_PRLI_COMPLETE) {
                ql_dbg(ql_dbg_mbx, vha, 0x119a,
                    "Unable to verify login-state (%x/%x) for loop_id %x.\n",
-                   pd->current_login_state, pd->last_login_state,
-                   fcport->loop_id);
+                   current_login_state, last_login_state, fcport->loop_id);
                rval = QLA_FUNCTION_FAILED;
                goto gpd_error_out;
        }
@@ -5998,12 +6006,17 @@ int __qla24xx_parse_gpdb(struct scsi_qla_host *vha, 
fc_port_t *fcport,
        fcport->d_id.b.al_pa = pd->port_id[2];
        fcport->d_id.b.rsvd_1 = 0;
 
-       /* If not target must be initiator or unknown type. */
-       if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
-               fcport->port_type = FCT_INITIATOR;
-       else
-               fcport->port_type = FCT_TARGET;
-
+       if (fcport->fc4f_nvme) {
+               fcport->nvme_prli_service_param =
+                   pd->prli_nvme_svc_param_word_3;
+               fcport->port_type = FCT_NVME;
+       } else {
+               /* If not target must be initiator or unknown type. */
+               if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
+                       fcport->port_type = FCT_INITIATOR;
+               else
+                       fcport->port_type = FCT_TARGET;
+       }
        /* Passback COS information. */
        fcport->supported_classes = (pd->flags & PDF_CLASS_2) ?
                FC_COS_CLASS2 : FC_COS_CLASS3;
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 88e115fcea60..b2474952f858 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4431,6 +4431,7 @@ struct scsi_qla_host *qla2x00_create_host(struct 
scsi_host_template *sht,
        INIT_LIST_HEAD(&vha->plogi_ack_list);
        INIT_LIST_HEAD(&vha->qp_list);
        INIT_LIST_HEAD(&vha->gnl.fcports);
+       INIT_LIST_HEAD(&vha->nvme_rport_list);
 
        spin_lock_init(&vha->work_lock);
        spin_lock_init(&vha->cmd_list_lock);
@@ -4720,6 +4721,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
                        qla24xx_async_gpdb(vha, e->u.fcport.fcport,
                            e->u.fcport.opt);
                        break;
+               case QLA_EVT_PRLI:
+                       qla24xx_async_prli(vha, e->u.fcport.fcport);
+                       break;
                case QLA_EVT_GPSC:
                        qla24xx_async_gpsc(vha, e->u.fcport.fcport);
                        break;
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 8f75d27daae2..a2b310de429b 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -963,7 +963,6 @@ static void qlt_free_session_done(struct work_struct *work)
                sess->logout_on_delete, sess->keep_nport_handle,
                sess->send_els_logo);
 
-
        if (!IS_SW_RESV_ADDR(sess->d_id)) {
                if (sess->send_els_logo) {
                        qlt_port_logo_t logo;
@@ -1118,6 +1117,9 @@ void qlt_unreg_sess(struct fc_port *sess)
        sess->last_rscn_gen = sess->rscn_gen;
        sess->last_login_gen = sess->login_gen;
 
+       if (sess->nvme_flag & NVME_FLAG_REGISTERED)
+               schedule_work(&sess->nvme_del_work);
+
        INIT_WORK(&sess->free_work, qlt_free_session_done);
        schedule_work(&sess->free_work);
 }
-- 
2.12.0

Reply via email to