]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
scsi: qla2xxx: Migrate NVME N2N handling into state machine
authorQuinn Tran <quinn.tran@cavium.com>
Thu, 2 Aug 2018 20:16:57 +0000 (13:16 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 2 Aug 2018 20:56:18 +0000 (16:56 -0400)
This patch fixes regression introduced for the N2N support for FC-NVMe. For
FC-NVMe with N2N connection, instead of FW initiating the Login, Driver
starts Login process.  This patch migrates that new process from a
standalone path into existing session management state machine. With this
state change now driver will not wait for pull NPort ID from FW.

Fixes: edd05de197592 ("scsi: qla2xxx: Changes to support N2N logins")
Signed-off-by: Quinn Tran <quinn.tran@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
12 files changed:
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_inline.h
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/qla2xxx/qla_nvme.h
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c

index d1ff1b8f1ae5a1ec52d1641621ad616883de8861..a03e12797f309b9b6bc97e68eacc595bc465361e 100644 (file)
@@ -398,6 +398,8 @@ struct srb_iocb {
                        struct completion comp;
                        struct els_plogi_payload *els_plogi_pyld;
                        struct els_plogi_payload *els_resp_pyld;
+                       u32 tx_size;
+                       u32 rx_size;
                        dma_addr_t els_plogi_pyld_dma;
                        dma_addr_t els_resp_pyld_dma;
                        uint32_t        fw_status[3];
@@ -2312,6 +2314,7 @@ enum fcport_mgt_event {
        FCME_ADISC_DONE,
        FCME_GNNID_DONE,
        FCME_GFPNID_DONE,
+       FCME_ELS_PLOGI_DONE,
 };
 
 enum rscn_addr_format {
@@ -2408,6 +2411,7 @@ typedef struct fc_port {
        struct ct_sns_desc ct_desc;
        enum discovery_state disc_state;
        enum login_state fw_login_state;
+       unsigned long dm_login_expire;
        unsigned long plogi_nack_done_deadline;
 
        u32 login_gen, last_login_gen;
@@ -2418,7 +2422,8 @@ typedef struct fc_port {
        u8 iocb[IOCB_SIZE];
        u8 current_login_state;
        u8 last_login_state;
-       struct completion n2n_done;
+       u16 n2n_link_reset_cnt;
+       u16 n2n_chip_reset;
 } fc_port_t;
 
 #define QLA_FCPORT_SCAN                1
@@ -3228,6 +3233,7 @@ enum qla_work_type {
        QLA_EVT_GFPNID,
        QLA_EVT_SP_RETRY,
        QLA_EVT_IIDMA,
+       QLA_EVT_ELS_PLOGI,
 };
 
 
@@ -3600,6 +3606,7 @@ struct qla_hw_data {
                uint32_t        using_lr_setting:1;
                uint32_t        rida_fmt2:1;
                uint32_t        purge_mbox:1;
+               uint32_t        n2n_bigger:1;
        } flags;
 
        uint16_t max_exchg;
@@ -3908,6 +3915,9 @@ struct qla_hw_data {
        int             exchoffld_size;
        int             exchoffld_count;
 
+       /* n2n */
+       struct els_plogi_payload plogi_els_payld;
+
        void            *swl;
 
        /* These are used by mailbox operations. */
index 5d8688e5bc7c9cefd0904d75b49ff7539af69d1f..50c1e6c62e31f06c42a63a2602b6b7ca22d0735d 100644 (file)
@@ -1366,6 +1366,11 @@ struct vp_rpt_id_entry_24xx {
                        /* format 1 fabric */
                        uint8_t vpstat1_subcode; /* vp_status=1 subcode */
                        uint8_t flags;
+#define TOPO_MASK  0xE
+#define TOPO_FL    0x2
+#define TOPO_N2N   0x4
+#define TOPO_F     0x6
+
                        uint16_t fip_flags;
                        uint8_t rsv2[12];
 
index 6f2a37220a5581ce0d2c81a6c9b3f515d5f40cdc..035ab18bd534574ee15951b7c01098af7273e57c 100644 (file)
@@ -45,8 +45,7 @@ extern int qla2x00_fabric_login(scsi_qla_host_t *, fc_port_t *, uint16_t *);
 extern int qla2x00_local_device_login(scsi_qla_host_t *, fc_port_t *);
 
 extern int qla24xx_els_dcmd_iocb(scsi_qla_host_t *, int, port_id_t);
-extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *,
-                                 port_id_t);
+extern int qla24xx_els_dcmd2_iocb(scsi_qla_host_t *, int, fc_port_t *, bool);
 
 extern void qla2x00_update_fcports(scsi_qla_host_t *);
 
index cf70c59c252311c1a3894bf67600fb0befea0dac..407eb705f1be347eb48ca15cf028862213f2ffb4 100644 (file)
@@ -3383,19 +3383,40 @@ int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
 
 void qla24xx_sp_unmap(scsi_qla_host_t *vha, srb_t *sp)
 {
-       if (sp->u.iocb_cmd.u.ctarg.req) {
-               dma_free_coherent(&vha->hw->pdev->dev,
-                       sizeof(struct ct_sns_pkt),
-                       sp->u.iocb_cmd.u.ctarg.req,
-                       sp->u.iocb_cmd.u.ctarg.req_dma);
-               sp->u.iocb_cmd.u.ctarg.req = NULL;
-       }
-       if (sp->u.iocb_cmd.u.ctarg.rsp) {
-               dma_free_coherent(&vha->hw->pdev->dev,
-                       sizeof(struct ct_sns_pkt),
-                       sp->u.iocb_cmd.u.ctarg.rsp,
-                       sp->u.iocb_cmd.u.ctarg.rsp_dma);
-               sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+       struct srb_iocb *c = &sp->u.iocb_cmd;
+
+       switch (sp->type) {
+       case SRB_ELS_DCMD:
+               if (c->u.els_plogi.els_plogi_pyld)
+                       dma_free_coherent(&vha->hw->pdev->dev,
+                           c->u.els_plogi.tx_size,
+                           c->u.els_plogi.els_plogi_pyld,
+                           c->u.els_plogi.els_plogi_pyld_dma);
+
+               if (c->u.els_plogi.els_resp_pyld)
+                       dma_free_coherent(&vha->hw->pdev->dev,
+                           c->u.els_plogi.rx_size,
+                           c->u.els_plogi.els_resp_pyld,
+                           c->u.els_plogi.els_resp_pyld_dma);
+               break;
+       case SRB_CT_PTHRU_CMD:
+       default:
+               if (sp->u.iocb_cmd.u.ctarg.req) {
+                       dma_free_coherent(&vha->hw->pdev->dev,
+                           sizeof(struct ct_sns_pkt),
+                           sp->u.iocb_cmd.u.ctarg.req,
+                           sp->u.iocb_cmd.u.ctarg.req_dma);
+                       sp->u.iocb_cmd.u.ctarg.req = NULL;
+               }
+
+               if (sp->u.iocb_cmd.u.ctarg.rsp) {
+                       dma_free_coherent(&vha->hw->pdev->dev,
+                           sizeof(struct ct_sns_pkt),
+                           sp->u.iocb_cmd.u.ctarg.rsp,
+                           sp->u.iocb_cmd.u.ctarg.rsp_dma);
+                       sp->u.iocb_cmd.u.ctarg.rsp = NULL;
+               }
+               break;
        }
 
        sp->free(sp);
index 471322c29db684caf1518bedb0b84ccf31bc48f1..f52c68b4da444d84a64bbae0dfebe5308c9dbc30 100644 (file)
@@ -419,6 +419,19 @@ void qla24xx_handle_adisc_event(scsi_qla_host_t *vha, struct event_arg *ea)
        __qla24xx_handle_gpdb_event(vha, ea);
 }
 
+int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+       struct qla_work_evt *e;
+
+       e = qla2x00_alloc_work(vha, QLA_EVT_ELS_PLOGI);
+       if (!e)
+               return QLA_FUNCTION_FAILED;
+
+       e->u.fcport.fcport = fcport;
+       fcport->flags |= FCF_ASYNC_ACTIVE;
+       return qla2x00_post_work(vha, e);
+}
+
 static void
 qla2x00_async_adisc_sp_done(void *ptr, int res)
 {
@@ -467,6 +480,8 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t *fcport,
 
        lio = &sp->u.iocb_cmd;
        lio->timeout = qla2x00_async_iocb_timeout;
+       sp->gen1 = fcport->rscn_gen;
+       sp->gen2 = fcport->login_gen;
        qla2x00_init_timer(sp, qla2x00_get_async_timeout(vha) + 2);
 
        sp->done = qla2x00_async_adisc_sp_done;
@@ -560,12 +575,17 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
 
                loop_id = le16_to_cpu(e->nport_handle);
                loop_id = (loop_id & 0x7fff);
+               if  (fcport->fc4f_nvme)
+                       current_login_state = e->current_login_state >> 4;
+               else
+                       current_login_state = e->current_login_state & 0xf;
+
 
                ql_dbg(ql_dbg_disc, vha, 0x20e2,
-                   "%s found %8phC CLS [%d|%d] ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
+                   "%s found %8phC CLS [%x|%x] nvme %d ID[%02x%02x%02x|%02x%02x%02x] lid[%d|%d]\n",
                    __func__, fcport->port_name,
                    e->current_login_state, fcport->fw_login_state,
-                   id.b.domain, id.b.area, id.b.al_pa,
+                   fcport->fc4f_nvme, id.b.domain, id.b.area, id.b.al_pa,
                    fcport->d_id.b.domain, fcport->d_id.b.area,
                    fcport->d_id.b.al_pa, loop_id, fcport->loop_id);
 
@@ -574,9 +594,13 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
                case DSC_DELETED:
                        break;
                default:
-                       if ((id.b24 != fcport->d_id.b24) ||
-                           ((fcport->loop_id != FC_NO_LOOP_ID) &&
-                               (fcport->loop_id != loop_id))) {
+                       if ((id.b24 != fcport->d_id.b24 &&
+                           fcport->d_id.b24) ||
+                           (fcport->loop_id != FC_NO_LOOP_ID &&
+                               fcport->loop_id != loop_id)) {
+                               ql_dbg(ql_dbg_disc, vha, 0x20e3,
+                                   "%s %d %8phC post del sess\n",
+                                   __func__, __LINE__, fcport->port_name);
                                qlt_schedule_sess_for_deletion(fcport);
                                return;
                        }
@@ -599,11 +623,6 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
                        fcport->login_pause = 1;
                }
 
-               if (fcport->fc4f_nvme)
-                       current_login_state = e->current_login_state >> 4;
-               else
-                       current_login_state = e->current_login_state & 0xf;
-
                switch (vha->hw->current_topology) {
                default:
                        switch (current_login_state) {
@@ -632,6 +651,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
                        }
                        break;
                case ISP_CFG_N:
+                       fcport->fw_login_state = current_login_state;
+                       fcport->d_id = id;
                        switch (current_login_state) {
                        case DSC_LS_PRLI_COMP:
                                if ((e->prli_svc_param_word_3[0] & BIT_4) == 0)
@@ -705,12 +726,39 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
                        qla24xx_fcport_handle_login(vha, fcport);
                        break;
                case ISP_CFG_N:
-                       /*
-                        * FW handles the initial login for n2n.
-                        * Do link reinit to trigger this auto login.
-                        */
-                       set_bit(N2N_LINK_RESET, &vha->dpc_flags);
-                       qla2xxx_wake_dpc(vha);
+                       fcport->disc_state = DSC_DELETED;
+                       if (time_after_eq(jiffies, fcport->dm_login_expire)) {
+                               if (fcport->n2n_link_reset_cnt < 2) {
+                                       fcport->n2n_link_reset_cnt++;
+                                       /*
+                                        * remote port is not sending PLOGI.
+                                        * Reset link to kick start his state
+                                        * machine
+                                        */
+                                       set_bit(N2N_LINK_RESET,
+                                           &vha->dpc_flags);
+                               } else {
+                                       if (fcport->n2n_chip_reset < 1) {
+                                               ql_log(ql_log_info, vha, 0x705d,
+                                                   "Chip reset to bring laser down");
+                                               set_bit(ISP_ABORT_NEEDED,
+                                                   &vha->dpc_flags);
+                                               fcport->n2n_chip_reset++;
+                                       } else {
+                                               ql_log(ql_log_info, vha, 0x705d,
+                                                   "Remote port %8ph is not coming back\n",
+                                                   fcport->port_name);
+                                               fcport->scan_state = 0;
+                                       }
+                               }
+                               qla2xxx_wake_dpc(vha);
+                       } else {
+                               /*
+                                * report port suppose to do PLOGI. Give him
+                                * more time. FW will catch it.
+                                */
+                               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+                       }
                        break;
                default:
                        break;
@@ -1020,9 +1068,9 @@ qla24xx_async_prli(struct scsi_qla_host *vha, fc_port_t *fcport)
        }
 
        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);
+           "Async-prli - %8phC hdl=%x, loopid=%x portid=%06x retries=%d %s.\n",
+           fcport->port_name, sp->handle, fcport->loop_id, fcport->d_id.b24,
+           fcport->login_retry, fcport->fc4f_nvme ? "nvme" : "fc");
 
        return rval;
 
@@ -1164,8 +1212,9 @@ void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
        fcport->flags &= ~FCF_ASYNC_SENT;
 
        ql_dbg(ql_dbg_disc, vha, 0x20d2,
-           "%s %8phC DS %d LS %d rc %d\n", __func__, fcport->port_name,
-           fcport->disc_state, pd->current_login_state, ea->rc);
+           "%s %8phC DS %d LS %d nvme %x rc %d\n", __func__, fcport->port_name,
+           fcport->disc_state, pd->current_login_state, fcport->fc4f_nvme,
+           ea->rc);
 
        if (fcport->disc_state == DSC_DELETE_PEND)
                return;
@@ -1286,36 +1335,76 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
                return 0;
        }
 
-
        switch (fcport->disc_state) {
        case DSC_DELETED:
-               fcport->login_retry--;
                wwn = wwn_to_u64(fcport->node_name);
-               if (wwn == 0) {
-                       ql_dbg(ql_dbg_disc, vha, 0xffff,
-                           "%s %d %8phC post GNNID\n",
-                           __func__, __LINE__, fcport->port_name);
-                       qla24xx_post_gnnid_work(vha, fcport);
-               } else if (fcport->loop_id == FC_NO_LOOP_ID) {
-                       ql_dbg(ql_dbg_disc, vha, 0x20bd,
-                           "%s %d %8phC post gnl\n",
-                           __func__, __LINE__, fcport->port_name);
-                       qla24xx_post_gnl_work(vha, fcport);
-               } else {
-                       fcport->login_retry--;
-                       qla_chk_n2n_b4_login(vha, fcport);
+               switch (vha->hw->current_topology) {
+               case ISP_CFG_N:
+                       if (fcport_is_smaller(fcport)) {
+                               /* this adapter is bigger */
+                               if (fcport->login_retry) {
+                                       if (fcport->loop_id == FC_NO_LOOP_ID) {
+                                               qla2x00_find_new_loop_id(vha,
+                                                   fcport);
+                                               fcport->fw_login_state =
+                                                   DSC_LS_PORT_UNAVAIL;
+                                       }
+                                       fcport->login_retry--;
+                                       qla_post_els_plogi_work(vha, fcport);
+                               } else {
+                                       ql_log(ql_log_info, vha, 0x705d,
+                                           "Unable to reach remote port %8phC",
+                                           fcport->port_name);
+                               }
+                       } else {
+                               qla24xx_post_gnl_work(vha, fcport);
+                       }
+                       break;
+               default:
+                       if (wwn == 0)    {
+                               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                                   "%s %d %8phC post GNNID\n",
+                                   __func__, __LINE__, fcport->port_name);
+                               qla24xx_post_gnnid_work(vha, fcport);
+                       } else if (fcport->loop_id == FC_NO_LOOP_ID) {
+                               ql_dbg(ql_dbg_disc, vha, 0x20bd,
+                                   "%s %d %8phC post gnl\n",
+                                   __func__, __LINE__, fcport->port_name);
+                               qla24xx_post_gnl_work(vha, fcport);
+                       } else {
+                               qla_chk_n2n_b4_login(vha, fcport);
+                       }
+                       break;
                }
                break;
 
        case DSC_GNL:
-               if (fcport->login_pause) {
-                       fcport->last_rscn_gen = fcport->rscn_gen;
-                       fcport->last_login_gen = fcport->login_gen;
-                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+               switch (vha->hw->current_topology) {
+               case ISP_CFG_N:
+                       if ((fcport->current_login_state & 0xf) == 0x6) {
+                               ql_dbg(ql_dbg_disc, vha, 0x2118,
+                                   "%s %d %8phC post GPDB work\n",
+                                   __func__, __LINE__, fcport->port_name);
+                               fcport->chip_reset =
+                                       vha->hw->base_qpair->chip_reset;
+                               qla24xx_post_gpdb_work(vha, fcport, 0);
+                       }  else {
+                               ql_dbg(ql_dbg_disc, vha, 0x2118,
+                                   "%s %d %8phC post NVMe PRLI\n",
+                                   __func__, __LINE__, fcport->port_name);
+                               qla24xx_post_prli_work(vha, fcport);
+                       }
+                       break;
+               default:
+                       if (fcport->login_pause) {
+                               fcport->last_rscn_gen = fcport->rscn_gen;
+                               fcport->last_login_gen = fcport->login_gen;
+                               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+                               break;
+                       }
+                       qla_chk_n2n_b4_login(vha, fcport);
                        break;
                }
-
-               qla_chk_n2n_b4_login(vha, fcport);
                break;
 
        case DSC_LOGIN_FAILED:
@@ -1429,6 +1518,15 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
        qla24xx_fcport_handle_login(vha, fcport);
 }
 
+
+void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea)
+{
+       ql_dbg(ql_dbg_disc, vha, 0x2118,
+           "%s %d %8phC post PRLI\n",
+           __func__, __LINE__, ea->fcport->port_name);
+       qla24xx_post_prli_work(vha, ea->fcport);
+}
+
 void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 {
        fc_port_t *f, *tf;
@@ -1530,6 +1628,9 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
        case FCME_GFPNID_DONE:
                qla24xx_handle_gfpnid_event(vha, ea);
                break;
+       case FCME_ELS_PLOGI_DONE:
+               qla_handle_els_plogi_done(vha, ea);
+               break;
        default:
                BUG_ON(1);
                break;
@@ -4160,7 +4261,8 @@ qla2x00_configure_hba(scsi_qla_host_t *vha)
        id.b.al_pa = al_pa;
        id.b.rsvd_1 = 0;
        spin_lock_irqsave(&ha->hardware_lock, flags);
-       qlt_update_host_map(vha, id);
+       if (!(topo == 2 && ha->flags.n2n_bigger))
+               qlt_update_host_map(vha, id);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        if (!vha->flags.init_done)
@@ -4813,6 +4915,31 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
        struct qla_hw_data *ha = vha->hw;
        unsigned long flags;
 
+       /* Inititae N2N login. */
+       if (test_and_clear_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags)) {
+               /* borrowing */
+               u32 *bp, i, sz;
+
+               memset(ha->init_cb, 0, ha->init_cb_size);
+               sz = min_t(int, sizeof(struct els_plogi_payload),
+                   ha->init_cb_size);
+               rval = qla24xx_get_port_login_templ(vha, ha->init_cb_dma,
+                   (void *)ha->init_cb, sz);
+               if (rval == QLA_SUCCESS) {
+                       bp = (uint32_t *)ha->init_cb;
+                       for (i = 0; i < sz/4 ; i++, bp++)
+                               *bp = cpu_to_be32(*bp);
+
+                       memcpy(&ha->plogi_els_payld.data, (void *)ha->init_cb,
+                           sizeof(ha->plogi_els_payld.data));
+                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+               } else {
+                       ql_dbg(ql_dbg_init, vha, 0x00d1,
+                           "PLOGI ELS param read fail.\n");
+               }
+               return QLA_SUCCESS;
+       }
+
        found_devs = 0;
        new_fcport = NULL;
        entries = MAX_FIBRE_DEVICES_LOOP;
@@ -5105,9 +5232,19 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
        fcport->deleted = 0;
        fcport->logout_on_delete = 1;
        fcport->login_retry = vha->hw->login_retry_count;
+       fcport->n2n_chip_reset = fcport->n2n_link_reset_cnt = 0;
 
        qla2x00_iidma_fcport(vha, fcport);
 
+       switch (vha->hw->current_topology) {
+       case ISP_CFG_N:
+       case ISP_CFG_NL:
+               fcport->keep_nport_handle = 1;
+               break;
+       default:
+               break;
+       }
+
        if (fcport->fc4f_nvme) {
                qla_nvme_register_remote(vha, fcport);
                fcport->disc_state = DSC_LOGIN_COMPLETE;
@@ -6992,6 +7129,9 @@ qla24xx_nvram_config(scsi_qla_host_t *vha)
        if (ql2xloginretrycount)
                ha->login_retry_count = ql2xloginretrycount;
 
+       /* N2N: driver will initiate Login instead of FW */
+       icb->firmware_options_3 |= BIT_8;
+
        /* Enable ZIO. */
        if (!vha->flags.init_done) {
                ha->zio_mode = le32_to_cpu(icb->firmware_options_2) &
@@ -8076,6 +8216,9 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
         /* enable RIDA Format2 */
        icb->firmware_options_3 |= BIT_0;
 
+       /* N2N: driver will initiate Login instead of FW */
+       icb->firmware_options_3 |= BIT_8;
+
        if (IS_QLA27XX(ha)) {
                icb->firmware_options_3 |= BIT_8;
                ql_dbg(ql_log_info, vha, 0x0075,
index acf6511e8ef7cca4116f25c9318b36244af374e4..a29f8898c68743168c342b5164f20d1bed2c4160 100644 (file)
@@ -280,8 +280,6 @@ qla2x00_init_timer(srb_t *sp, unsigned long tmo)
        init_completion(&sp->comp);
        if (IS_QLAFX00(sp->vha->hw) && (sp->type == SRB_FXIOCB_DCMD))
                init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
-       if (sp->type == SRB_ELS_DCMD)
-               init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
        add_timer(&sp->u.iocb_cmd.timer);
 }
 
index ba14db8d0b8dda801714003aa931c157ab2a91b5..059f2c9dc192b44d0e59f8023c8e8bb7545d1cf8 100644 (file)
@@ -2465,6 +2465,7 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
        sp->fcport = fcport;
        elsio->timeout = qla2x00_els_dcmd_iocb_timeout;
        qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
+       init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
        sp->done = qla2x00_els_dcmd_sp_done;
        sp->free = qla2x00_els_dcmd_sp_free;
 
@@ -2512,7 +2513,6 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
 {
        scsi_qla_host_t *vha = sp->vha;
        struct srb_iocb *elsio = &sp->u.iocb_cmd;
-       uint32_t        dsd_len = 24;
 
        els_iocb->entry_type = ELS_IOCB_TYPE;
        els_iocb->entry_count = 1;
@@ -2535,20 +2535,21 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
        els_iocb->control_flags = 0;
 
        if (elsio->u.els_logo.els_cmd == ELS_DCMD_PLOGI) {
-               els_iocb->tx_byte_count = sizeof(struct els_plogi_payload);
+               els_iocb->tx_byte_count = els_iocb->tx_len =
+                       sizeof(struct els_plogi_payload);
                els_iocb->tx_address[0] =
                        cpu_to_le32(LSD(elsio->u.els_plogi.els_plogi_pyld_dma));
                els_iocb->tx_address[1] =
                        cpu_to_le32(MSD(elsio->u.els_plogi.els_plogi_pyld_dma));
-               els_iocb->tx_len = dsd_len;
 
                els_iocb->rx_dsd_count = 1;
-               els_iocb->rx_byte_count = sizeof(struct els_plogi_payload);
+               els_iocb->rx_byte_count = els_iocb->rx_len =
+                       sizeof(struct els_plogi_payload);
                els_iocb->rx_address[0] =
                        cpu_to_le32(LSD(elsio->u.els_plogi.els_resp_pyld_dma));
                els_iocb->rx_address[1] =
                        cpu_to_le32(MSD(elsio->u.els_plogi.els_resp_pyld_dma));
-               els_iocb->rx_len = dsd_len;
+
                ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
                    "PLOGI ELS IOCB:\n");
                ql_dump_buffer(ql_log_info, vha, 0x0109,
@@ -2577,7 +2578,6 @@ qla2x00_els_dcmd2_iocb_timeout(void *data)
        fc_port_t *fcport = sp->fcport;
        struct scsi_qla_host *vha = sp->vha;
        struct qla_hw_data *ha = vha->hw;
-       struct srb_iocb *lio = &sp->u.iocb_cmd;
        unsigned long flags = 0;
        int res;
 
@@ -2593,7 +2593,7 @@ qla2x00_els_dcmd2_iocb_timeout(void *data)
            (res == QLA_SUCCESS) ? "successful" : "failed");
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-       complete(&lio->u.els_plogi.comp);
+       sp->done(sp, QLA_FUNCTION_TIMEOUT);
 }
 
 static void
@@ -2603,17 +2603,54 @@ qla2x00_els_dcmd2_sp_done(void *ptr, int res)
        fc_port_t *fcport = sp->fcport;
        struct srb_iocb *lio = &sp->u.iocb_cmd;
        struct scsi_qla_host *vha = sp->vha;
+       struct event_arg ea;
+       struct qla_work_evt *e;
+
+       ql_dbg(ql_dbg_disc, vha, 0x3072,
+           "%s ELS done rc %d hdl=%x, portid=%06x %8phC\n",
+           sp->name, res, sp->handle, fcport->d_id.b24, fcport->port_name);
 
-       ql_dbg(ql_dbg_io + ql_dbg_disc, vha, 0x3072,
-           "%s ELS hdl=%x, portid=%06x done %8phC\n",
-           sp->name, sp->handle, fcport->d_id.b24, fcport->port_name);
+       fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
+       del_timer(&sp->u.iocb_cmd.timer);
 
-       complete(&lio->u.els_plogi.comp);
+       if (sp->flags & SRB_WAKEUP_ON_COMP)
+               complete(&lio->u.els_plogi.comp);
+       else {
+               if (res) {
+                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
+               } else {
+                       memset(&ea, 0, sizeof(ea));
+                       ea.fcport = fcport;
+                       ea.rc = res;
+                       ea.event = FCME_ELS_PLOGI_DONE;
+                       qla2x00_fcport_event_handler(vha, &ea);
+               }
+
+               e = qla2x00_alloc_work(vha, QLA_EVT_UNMAP);
+               if (!e) {
+                       struct srb_iocb *elsio = &sp->u.iocb_cmd;
+
+                       if (elsio->u.els_plogi.els_plogi_pyld)
+                               dma_free_coherent(&sp->vha->hw->pdev->dev,
+                                   elsio->u.els_plogi.tx_size,
+                                   elsio->u.els_plogi.els_plogi_pyld,
+                                   elsio->u.els_plogi.els_plogi_pyld_dma);
+
+                       if (elsio->u.els_plogi.els_resp_pyld)
+                               dma_free_coherent(&sp->vha->hw->pdev->dev,
+                                   elsio->u.els_plogi.rx_size,
+                                   elsio->u.els_plogi.els_resp_pyld,
+                                   elsio->u.els_plogi.els_resp_pyld_dma);
+                       sp->free(sp);
+               }
+               e->u.iosb.sp = sp;
+               qla2x00_post_work(vha, e);
+       }
 }
 
 int
 qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
-                      fc_port_t *fcport, port_id_t remote_did)
+    fc_port_t *fcport, bool wait)
 {
        srb_t *sp;
        struct srb_iocb *elsio = NULL;
@@ -2641,9 +2678,13 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 
        elsio->timeout = qla2x00_els_dcmd2_iocb_timeout;
        init_completion(&elsio->u.els_plogi.comp);
-       qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT);
+       if (wait)
+               sp->flags = SRB_WAKEUP_ON_COMP;
+
+       qla2x00_init_timer(sp, ELS_DCMD_TIMEOUT + 2);
 
        sp->done = qla2x00_els_dcmd2_sp_done;
+       elsio->u.els_plogi.tx_size = elsio->u.els_plogi.rx_size = DMA_POOL_SIZE;
 
        ptr = elsio->u.els_plogi.els_plogi_pyld =
            dma_alloc_coherent(&ha->pdev->dev, DMA_POOL_SIZE,
@@ -2668,33 +2709,52 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 
        memset(ptr, 0, sizeof(struct els_plogi_payload));
        memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
+       memcpy(elsio->u.els_plogi.els_plogi_pyld->data,
+           &ha->plogi_els_payld.data,
+           sizeof(elsio->u.els_plogi.els_plogi_pyld->data));
+
        elsio->u.els_plogi.els_cmd = els_opcode;
        elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
-       qla24xx_get_port_login_templ(vha, ptr_dma + 4,
-               &elsio->u.els_plogi.els_plogi_pyld->data[0],
-               sizeof(struct els_plogi_payload));
 
-       ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
-       ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x0109,
+       ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x0109,
            (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
                rval = QLA_FUNCTION_FAILED;
-               goto out;
+       } else {
+               ql_dbg(ql_dbg_disc, vha, 0x3074,
+                   "%s PLOGI sent, hdl=%x, loopid=%x, to port_id %06x from port_id %06x\n",
+                   sp->name, sp->handle, fcport->loop_id,
+                   fcport->d_id.b24, vha->d_id.b24);
        }
 
-       ql_dbg(ql_dbg_io, vha, 0x3074,
-           "%s PLOGI sent, hdl=%x, loopid=%x, portid=%06x\n",
-           sp->name, sp->handle, fcport->loop_id, fcport->d_id.b24);
-
-       wait_for_completion(&elsio->u.els_plogi.comp);
+       if (wait) {
+               wait_for_completion(&elsio->u.els_plogi.comp);
 
-       if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
-               rval = QLA_FUNCTION_FAILED;
+               if (elsio->u.els_plogi.comp_status != CS_COMPLETE)
+                       rval = QLA_FUNCTION_FAILED;
+       } else {
+               goto done;
+       }
 
 out:
+       fcport->flags &= ~(FCF_ASYNC_SENT);
+       if (elsio->u.els_plogi.els_plogi_pyld)
+               dma_free_coherent(&sp->vha->hw->pdev->dev,
+                   elsio->u.els_plogi.tx_size,
+                   elsio->u.els_plogi.els_plogi_pyld,
+                   elsio->u.els_plogi.els_plogi_pyld_dma);
+
+       if (elsio->u.els_plogi.els_resp_pyld)
+               dma_free_coherent(&sp->vha->hw->pdev->dev,
+                   elsio->u.els_plogi.rx_size,
+                   elsio->u.els_plogi.els_resp_pyld,
+                   elsio->u.els_plogi.els_resp_pyld_dma);
+
        sp->free(sp);
+done:
        return rval;
 }
 
index 10847cdca0938a387b6c44c63ae8f3e8416bc04e..7c07a939cf15a9ca2fb143f5883c59fe6ddac71c 100644 (file)
@@ -59,6 +59,7 @@ static struct rom_cmd {
        { MBC_IOCB_COMMAND_A64 },
        { MBC_GET_ADAPTER_LOOP_ID },
        { MBC_READ_SFP },
+       { MBC_GET_RNID_PARAMS },
 };
 
 static int is_rom_cmd(uint16_t cmd)
@@ -3842,30 +3843,68 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                   "Format 1: WWPN %8phC.\n",
                   vha->port_name);
 
-               /* N2N.  direct connect */
-               if (IS_QLA27XX(ha) &&
-                   ((rptid_entry->u.f1.flags>>1) & 0x7) == 2) {
-                       /* if our portname is higher then initiate N2N login */
-                       if (wwn_to_u64(vha->port_name) >
-                           wwn_to_u64(rptid_entry->u.f1.port_name)) {
-                               // ??? qlt_update_host_map(vha, id);
-                               vha->n2n_id = 0x1;
-                               ql_dbg(ql_dbg_async, vha, 0x5075,
-                                   "Format 1: Setting n2n_update_needed for id %d\n",
-                                   vha->n2n_id);
+               switch (rptid_entry->u.f1.flags & TOPO_MASK) {
+               case TOPO_N2N:
+                       ha->current_topology = ISP_CFG_N;
+                       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+                       fcport = qla2x00_find_fcport_by_wwpn(vha,
+                           rptid_entry->u.f1.port_name, 1);
+                       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
+                       if (fcport) {
+                               fcport->plogi_nack_done_deadline = jiffies + HZ;
+                               fcport->dm_login_expire = jiffies + 3*HZ;
+                               fcport->scan_state = QLA_FCPORT_FOUND;
+                               switch (fcport->disc_state) {
+                               case DSC_DELETED:
+                                       set_bit(RELOGIN_NEEDED,
+                                           &vha->dpc_flags);
+                                       break;
+                               case DSC_DELETE_PEND:
+                                       break;
+                               default:
+                                       qlt_schedule_sess_for_deletion(fcport);
+                                       break;
+                               }
                        } else {
-                               ql_dbg(ql_dbg_async, vha, 0x5075,
-                                   "Format 1: Remote login - Waiting for WWPN %8phC.\n",
-                                   rptid_entry->u.f1.port_name);
+                               id.b24 = 0;
+                               if (wwn_to_u64(vha->port_name) >
+                                   wwn_to_u64(rptid_entry->u.f1.port_name)) {
+                                       vha->d_id.b24 = 0;
+                                       vha->d_id.b.al_pa = 1;
+                                       ha->flags.n2n_bigger = 1;
+
+                                       id.b.al_pa = 2;
+                                       ql_dbg(ql_dbg_async, vha, 0x5075,
+                                           "Format 1: assign local id %x remote id %x\n",
+                                           vha->d_id.b24, id.b24);
+                               } else {
+                                       ql_dbg(ql_dbg_async, vha, 0x5075,
+                                           "Format 1: Remote login - Waiting for WWPN %8phC.\n",
+                                           rptid_entry->u.f1.port_name);
+                                       ha->flags.n2n_bigger = 0;
+                               }
+                               qla24xx_post_newsess_work(vha, &id,
+                                   rptid_entry->u.f1.port_name,
+                                   rptid_entry->u.f1.node_name,
+                                   NULL,
+                                   FC4_TYPE_UNKNOWN);
                        }
 
-                       memcpy(vha->n2n_port_name, rptid_entry->u.f1.port_name,
-                           WWN_SIZE);
+                       /* if our portname is higher then initiate N2N login */
+
                        set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
-                       set_bit(REGISTER_FC4_NEEDED, &vha->dpc_flags);
-                       set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
                        ha->flags.n2n_ae = 1;
                        return;
+                       break;
+               case TOPO_FL:
+                       ha->current_topology = ISP_CFG_FL;
+                       break;
+               case TOPO_F:
+                       ha->current_topology = ISP_CFG_F;
+                       break;
+               default:
+                       break;
                }
 
                ha->flags.gpsc_supported = 1;
@@ -4681,7 +4720,7 @@ qla24xx_get_port_login_templ(scsi_qla_host_t *vha, dma_addr_t buf_dma,
                    "Done %s.\n", __func__);
                bp = (uint32_t *) buf;
                for (i = 0; i < (bufsiz-4)/4; i++, bp++)
-                       *bp = cpu_to_be32(*bp);
+                       *bp = le32_to_cpu(*bp);
        }
 
        return rval;
index c5a963c2c86e3297d1f5ee564d8797c1fe9e928c..20d9dc39f0fbe00762e83c0b056be68cd434312b 100644 (file)
@@ -30,6 +30,9 @@ int qla_nvme_register_remote(struct scsi_qla_host *vha, struct fc_port *fcport)
                return 0;
        }
 
+       if (!vha->nvme_local_port && qla_nvme_register_hba(vha))
+               return 0;
+
        if (!(fcport->nvme_prli_service_param &
            (NVME_PRLI_SP_TARGET | NVME_PRLI_SP_DISCOVERY)) ||
                (fcport->nvme_flag & NVME_FLAG_REGISTERED))
@@ -676,15 +679,15 @@ void qla_nvme_delete(struct scsi_qla_host *vha)
        }
 }
 
-void qla_nvme_register_hba(struct scsi_qla_host *vha)
+int qla_nvme_register_hba(struct scsi_qla_host *vha)
 {
        struct nvme_fc_port_template *tmpl;
        struct qla_hw_data *ha;
        struct nvme_fc_port_info pinfo;
-       int ret;
+       int ret = EINVAL;
 
        if (!IS_ENABLED(CONFIG_NVME_FC))
-               return;
+               return ret;
 
        ha = vha->hw;
        tmpl = &qla_nvme_fc_transport;
@@ -711,7 +714,9 @@ void qla_nvme_register_hba(struct scsi_qla_host *vha)
        if (ret) {
                ql_log(ql_log_warn, vha, 0xffff,
                    "register_localport failed: ret=%x\n", ret);
-               return;
+       } else {
+               vha->nvme_local_port->private = vha;
        }
-       vha->nvme_local_port->private = vha;
+
+       return ret;
 }
index 816854ada654a4ea78a1b6423f1cfd8c267a741d..4941d107fb1c31f09211ab491377b9349f90593a 100644 (file)
@@ -142,7 +142,7 @@ struct pt_ls4_rx_unsol {
 /*
  * Global functions prototype in qla_nvme.c source file.
  */
-void qla_nvme_register_hba(struct scsi_qla_host *);
+int qla_nvme_register_hba(struct scsi_qla_host *);
 int  qla_nvme_register_remote(struct scsi_qla_host *, struct fc_port *);
 void qla_nvme_delete(struct scsi_qla_host *);
 void qla_nvme_abort(struct qla_hw_data *, struct srb *sp, int res);
index 48d1003c8178b6e3b0718a25914b81f7507b21f9..15b63136961ca546f718a458b0ef3ff9768927ae 100644 (file)
@@ -4789,7 +4789,6 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
        struct qlt_plogi_ack_t *pla =
            (struct qlt_plogi_ack_t *)e->u.new_sess.pla;
        uint8_t free_fcport = 0;
-       u64 wwn;
 
        ql_dbg(ql_dbg_disc, vha, 0xffff,
            "%s %d %8phC enter\n",
@@ -4817,10 +4816,10 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
                        fcport->d_id = e->u.new_sess.id;
                        fcport->flags |= FCF_FABRIC_DEVICE;
                        fcport->fw_login_state = DSC_LS_PLOGI_PEND;
-                       if (e->u.new_sess.fc4_type & FS_FC4TYPE_FCP)
+                       if (e->u.new_sess.fc4_type == FS_FC4TYPE_FCP)
                                fcport->fc4_type = FC4_TYPE_FCP_SCSI;
 
-                       if (e->u.new_sess.fc4_type & FS_FC4TYPE_NVME) {
+                       if (e->u.new_sess.fc4_type == FS_FC4TYPE_NVME) {
                                fcport->fc4_type = FC4_TYPE_OTHER;
                                fcport->fc4f_nvme = FC4_TYPE_NVME;
                        }
@@ -4862,9 +4861,6 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
        if (fcport) {
-               if (N2N_TOPO(vha->hw))
-                       fcport->flags &= ~FCF_FABRIC_DEVICE;
-
                fcport->id_changed = 1;
                fcport->scan_state = QLA_FCPORT_FOUND;
                memcpy(fcport->node_name, e->u.new_sess.node_name, WWN_SIZE);
@@ -4925,12 +4921,22 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
                        if (dfcp)
                                qlt_schedule_sess_for_deletion(tfcp);
 
-                       wwn = wwn_to_u64(fcport->node_name);
 
-                       if (!wwn)
-                               qla24xx_async_gnnid(vha, fcport);
-                       else
-                               qla24xx_async_gnl(vha, fcport);
+                       if (N2N_TOPO(vha->hw))
+                               fcport->flags &= ~FCF_FABRIC_DEVICE;
+
+                       if (N2N_TOPO(vha->hw)) {
+                               if (vha->flags.nvme_enabled) {
+                                       fcport->fc4f_nvme = 1;
+                                       fcport->n2n_flag = 1;
+                               }
+                               fcport->fw_login_state = 0;
+                               /*
+                                * wait link init done before sending login
+                                */
+                       } else {
+                               qla24xx_fcport_handle_login(vha, fcport);
+                       }
                }
        }
 
@@ -5065,6 +5071,10 @@ qla2x00_do_work(struct scsi_qla_host *vha)
                case QLA_EVT_IIDMA:
                        qla_do_iidma_work(vha, e->u.fcport.fcport);
                        break;
+               case QLA_EVT_ELS_PLOGI:
+                       qla24xx_els_dcmd2_iocb(vha, ELS_DCMD_PLOGI,
+                           e->u.fcport.fcport, false);
+                       break;
                }
                if (e->flags & QLA_EVT_FLAG_FREE)
                        kfree(e);
index f71ec94acc3b4eb7255845d3c7f44ed0497d2576..e03d12a5f986ccbaf9eb8741f35e58f114051a51 100644 (file)
@@ -1619,9 +1619,6 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
 
        sess->conf_compl_supported = conf_compl_supported;
 
-       /* Reset logout parameters to default */
-       sess->logout_on_delete = 1;
-       sess->keep_nport_handle = 0;
 }
 
 /*