]> git.baikalelectronics.ru Git - kernel.git/commitdiff
scsi: qla2xxx: Add ability to use GPNFT/GNNFT for RSCN handling
authorQuinn Tran <quinn.tran@cavium.com>
Thu, 28 Dec 2017 20:33:35 +0000 (12:33 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 4 Jan 2018 04:41:07 +0000 (23:41 -0500)
add ability to use gpnft/gnnft to handle RSCN.

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>
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_os.c

index 68b327827739f48d90987a72c45fd0befd187052..0d20f5f8d7abdb88f721c23f733113b159ae43d0 100644 (file)
@@ -2972,6 +2972,11 @@ struct ct_sns_gpnft_pkt {
        } p;
 };
 
+enum scan_flags_t {
+       SF_SCANNING = BIT_0,
+       SF_QUEUED = BIT_1,
+};
+
 struct fab_scan_rp {
        port_id_t id;
        u8 port_name[8];
@@ -2981,6 +2986,8 @@ struct fab_scan_rp {
 struct fab_scan {
        struct fab_scan_rp *l;
        u32 size;
+       enum scan_flags_t scan_flags;
+       struct delayed_work scan_work;
 };
 
 /*
index 643cc536454b157ab2e40c9d1280df2e8a9c5c9b..3f3863c09de2e0fb3b904ef30cccfa7fc8dc11aa 100644 (file)
@@ -668,6 +668,7 @@ int qla24xx_post_gfpnid_work(struct scsi_qla_host *, fc_port_t *);
 int qla24xx_async_gfpnid(scsi_qla_host_t *, fc_port_t *);
 void qla24xx_handle_gfpnid_event(scsi_qla_host_t *, struct event_arg *);
 void qla24xx_sp_unmap(scsi_qla_host_t *, srb_t *);
+void qla_scan_work_fn(struct work_struct *);
 
 /*
  * Global Function Prototypes in qla_attr.c source file.
index fff12d770583b998615b8135bc0549ee32c4b059..963ebcb7cf2ca07f40d8f5cc830b4a2ec018f501 100644 (file)
@@ -2976,8 +2976,10 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
        fc_port_t *fcport = ea->fcport;
 
        ql_dbg(ql_dbg_disc, vha, 0x201d,
-           "%s %8phC login state %d\n",
-           __func__, fcport->port_name, fcport->fw_login_state);
+           "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
+           __func__, fcport->port_name, fcport->disc_state,
+           fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+           fcport->rscn_gen, ea->sp->gen1, fcport->loop_id);
 
        if (fcport->disc_state == DSC_DELETE_PEND)
                return;
@@ -2985,9 +2987,9 @@ void qla24xx_handle_gidpn_event(scsi_qla_host_t *vha, struct event_arg *ea)
        if (ea->sp->gen2 != fcport->login_gen) {
                /* PLOGI/PRLI/LOGO came in while cmd was out.*/
                ql_dbg(ql_dbg_disc, vha, 0x201e,
-                   "%s %8phC generation changed rscn %d|%d login %d|%d \n",
+                   "%s %8phC generation changed rscn %d|%d n",
                    __func__, fcport->port_name, fcport->last_rscn_gen,
-                   fcport->rscn_gen, fcport->last_login_gen, fcport->login_gen);
+                   fcport->rscn_gen);
                return;
        }
 
@@ -3215,11 +3217,10 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
        struct fc_port *fcport = ea->fcport;
 
        ql_dbg(ql_dbg_disc, vha, 0x20d8,
-           "%s %8phC DS %d LS %d rscn %d|%d login %d|%d lid %d\n",
+           "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d lid %d\n",
            __func__, fcport->port_name, fcport->disc_state,
-           fcport->fw_login_state, fcport->last_rscn_gen, fcport->rscn_gen,
-           fcport->last_login_gen, fcport->login_gen,
-           fcport->loop_id);
+           fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
+           ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1, fcport->loop_id);
 
        if (fcport->disc_state == DSC_DELETE_PEND)
                return;
@@ -3227,10 +3228,8 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
        if (ea->sp->gen2 != fcport->login_gen) {
                /* target side must have changed it. */
                ql_dbg(ql_dbg_disc, vha, 0x20d3,
-                   "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-                   __func__, fcport->port_name, fcport->last_rscn_gen,
-                   fcport->rscn_gen, fcport->last_login_gen,
-                   fcport->login_gen);
+                   "%s %8phC generation changed\n",
+                   __func__, fcport->port_name);
                return;
        } else if (ea->sp->gen1 != fcport->rscn_gen) {
                ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -3862,6 +3861,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
        bool found;
        u8 fc4type = sp->gen2;
        struct fab_scan_rp *rp;
+       unsigned long flags;
 
        ql_dbg(ql_dbg_disc, vha, 0xffff,
            "%s enter\n", __func__);
@@ -3939,16 +3939,15 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
                if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
                        continue;
 
-               if (fcport->scan_state == QLA_FCPORT_SCAN) {
+               if (fcport->scan_state != QLA_FCPORT_FOUND) {
                        if ((qla_dual_mode_enabled(vha) ||
                                qla_ini_mode_enabled(vha)) &&
                            atomic_read(&fcport->state) == FCS_ONLINE) {
                                qla2x00_mark_device_lost(vha, fcport,
                                    ql2xplogiabsentdevice, 0);
+
                                if (fcport->loop_id != FC_NO_LOOP_ID &&
-                                   (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
-                                   fcport->port_type != FCT_INITIATOR &&
-                                   fcport->port_type != FCT_BROADCAST) {
+                                   (fcport->flags & FCF_FCP2_DEVICE) == 0) {
                                        ql_dbg(ql_dbg_disc, vha, 0x20f0,
                                            "%s %d %8phC post del sess\n",
                                            __func__, __LINE__,
@@ -3959,14 +3958,16 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
                                        continue;
                                }
                        }
-               }
-
-               if (fcport->scan_state == QLA_FCPORT_FOUND)
+               } else
                        qla24xx_fcport_handle_login(vha, fcport);
        }
 
 out:
        qla24xx_sp_unmap(vha, sp);
+
+       spin_lock_irqsave(&vha->work_lock, flags);
+       vha->scan.scan_flags &= ~SF_SCANNING;
+       spin_unlock_irqrestore(&vha->work_lock, flags);
 }
 
 static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
@@ -3995,6 +3996,9 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
                    "Async done-%s timed out.\n",
                    sp->name);
                sp->free(sp);
+               spin_lock_irqsave(&vha->work_lock, flags);
+               vha->scan.scan_flags &= ~SF_SCANNING;
+               spin_unlock_irqrestore(&vha->work_lock, flags);
                set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                qla2xxx_wake_dpc(vha);
@@ -4086,14 +4090,17 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
        struct ct_sns_req *ct_req;
        struct ct_sns_pkt *ct_sns;
 
-       if (!vha->flags.online)
+       if (!vha->flags.online) {
+               vha->scan.scan_flags &= ~SF_SCANNING;
                goto done_free_sp;
+       }
 
        if (!sp->u.iocb_cmd.u.ctarg.req || !sp->u.iocb_cmd.u.ctarg.rsp) {
                ql_log(ql_log_warn, vha, 0xffff,
                    "%s: req %p rsp %p are not setup\n",
                    __func__, sp->u.iocb_cmd.u.ctarg.req,
                    sp->u.iocb_cmd.u.ctarg.rsp);
+               vha->scan.scan_flags &= ~SF_SCANNING;
                WARN_ON(1);
                goto done_free_sp;
        }
@@ -4166,14 +4173,25 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
        srb_t *sp;
        struct ct_sns_pkt *ct_sns;
        u32 rspsz;
+       unsigned long flags;
 
        if (!vha->flags.online)
                return rval;
 
-       sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
-       if (!sp)
+       spin_lock_irqsave(&vha->work_lock, flags);
+       if (vha->scan.scan_flags & SF_SCANNING) {
+               spin_unlock_irqrestore(&vha->work_lock, flags);
+               ql_dbg(ql_dbg_disc, vha, 0xffff, "scan active\n");
                return rval;
+       }
+       vha->scan.scan_flags |= SF_SCANNING;
+       spin_unlock_irqrestore(&vha->work_lock, flags);
 
+       sp = qla2x00_get_sp(vha, NULL, GFP_KERNEL);
+       if (!sp) {
+               vha->scan.scan_flags &= ~SF_SCANNING;
+               return rval;
+       }
 
        sp->type = SRB_CT_PTHRU_CMD;
        sp->name = "gpnft";
@@ -4187,6 +4205,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
        if (!sp->u.iocb_cmd.u.ctarg.req) {
                ql_log(ql_log_warn, vha, 0xffff,
                    "Failed to allocate ct_sns request.\n");
+               vha->scan.scan_flags &= ~SF_SCANNING;
                goto done_free_sp;
        }
 
@@ -4199,6 +4218,7 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
        if (!sp->u.iocb_cmd.u.ctarg.rsp) {
                ql_log(ql_log_warn, vha, 0xffff,
                    "Failed to allocate ct_sns request.\n");
+               vha->scan.scan_flags &= ~SF_SCANNING;
                goto done_free_sp;
        }
 
@@ -4219,8 +4239,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type)
        sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 
        rval = qla2x00_start_sp(sp);
-       if (rval != QLA_SUCCESS)
+       if (rval != QLA_SUCCESS) {
+               vha->scan.scan_flags &= ~SF_SCANNING;
                goto done_free_sp;
+       }
 
        ql_dbg(ql_dbg_disc, vha, 0xffff,
            "Async-%s hdl=%x FC4Type %x.\n", sp->name,
@@ -4248,6 +4270,24 @@ done_free_sp:
        return rval;
 }
 
+void qla_scan_work_fn(struct work_struct *work)
+{
+       struct fab_scan *s = container_of(to_delayed_work(work),
+           struct fab_scan, scan_work);
+       struct scsi_qla_host *vha = container_of(s, struct scsi_qla_host,
+           scan);
+       unsigned long flags;
+
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s: schedule loop resync\n", __func__);
+       set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+       set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+       qla2xxx_wake_dpc(vha);
+       spin_lock_irqsave(&vha->work_lock, flags);
+       vha->scan.scan_flags &= ~SF_QUEUED;
+       spin_unlock_irqrestore(&vha->work_lock, flags);
+}
+
 /* GNN_ID */
 void qla24xx_handle_gnnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
@@ -4367,9 +4407,10 @@ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
        fc_port_t *fcport = ea->fcport;
 
        ql_dbg(ql_dbg_disc, vha, 0xffff,
-           "%s %d %8phC post gpsc fcp_cnt %d\n",
-           __func__, __LINE__, fcport->port_name,
-           vha->fcport_count);
+           "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d fcpcnt %d\n",
+           __func__, fcport->port_name, fcport->disc_state,
+           fcport->fw_login_state, ea->rc, fcport->login_gen, ea->sp->gen2,
+           fcport->rscn_gen, ea->sp->gen1, vha->fcport_count);
 
        if (fcport->disc_state == DSC_DELETE_PEND)
                return;
@@ -4377,10 +4418,8 @@ void qla24xx_handle_gfpnid_event(scsi_qla_host_t *vha, struct event_arg *ea)
        if (ea->sp->gen2 != fcport->login_gen) {
                /* target side must have changed it. */
                ql_dbg(ql_dbg_disc, vha, 0x20d3,
-                   "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-                   __func__, fcport->port_name, fcport->last_rscn_gen,
-                   fcport->rscn_gen, fcport->last_login_gen,
-                   fcport->login_gen);
+                   "%s %8phC generation changed\n",
+                   __func__, fcport->port_name);
                return;
        } else if (ea->sp->gen1 != fcport->rscn_gen) {
                ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
index 75dc76587f4342f5ae48b587f24ec3f77dedd79c..61534b9bef7bf978db3647000aeb055730817786 100644 (file)
@@ -453,6 +453,12 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
        u8 current_login_state;
 
        fcport = ea->fcport;
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s %8phC DS %d LS rc %d %d login %d|%d rscn %d|%d lid %d\n",
+           __func__, fcport->port_name, fcport->disc_state,
+           fcport->fw_login_state, ea->rc,
+           fcport->login_gen, fcport->last_login_gen,
+           fcport->rscn_gen, fcport->last_rscn_gen, vha->loop_id);
 
        if (fcport->disc_state == DSC_DELETE_PEND)
                return;
@@ -476,9 +482,8 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha,
                return;
        } else if (fcport->last_login_gen != fcport->login_gen) {
                ql_dbg(ql_dbg_disc, vha, 0x20e0,
-                   "%s %8phC login gen changed login %d|%d\n",
-                   __func__, fcport->port_name,
-                   fcport->last_login_gen, fcport->login_gen);
+                   "%s %8phC login gen changed\n",
+                   __func__, fcport->port_name);
                return;
        }
 
@@ -1058,7 +1063,6 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 static
 void qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-       int rval = ea->rc;
        fc_port_t *fcport = ea->fcport;
        struct port_database_24xx *pd;
        struct srb *sp = ea->sp;
@@ -1068,8 +1072,8 @@ 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 rval %d\n", __func__, fcport->port_name,
-           fcport->disc_state, pd->current_login_state, rval);
+           "%s %8phC DS %d LS %d rc %d\n", __func__, fcport->port_name,
+           fcport->disc_state, pd->current_login_state, ea->rc);
 
        if (fcport->disc_state == DSC_DELETE_PEND)
                return;
@@ -1139,11 +1143,11 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
        u64 wwn;
 
        ql_dbg(ql_dbg_disc, vha, 0x20d8,
-           "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d|%d retry %d lid %d scan %d\n",
+           "%s %8phC DS %d LS %d P %d fl %x confl %p rscn %d|%d login %d retry %d lid %d scan %d\n",
            __func__, fcport->port_name, fcport->disc_state,
            fcport->fw_login_state, fcport->login_pause, fcport->flags,
            fcport->conflict, fcport->last_rscn_gen, fcport->rscn_gen,
-           fcport->last_login_gen, fcport->login_gen, fcport->login_retry,
+           fcport->login_gen, fcport->login_retry,
            fcport->loop_id, fcport->scan_state);
 
        if (fcport->login_retry == 0)
@@ -1320,9 +1324,9 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 
 void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
 {
-       fc_port_t *fcport, *f, *tf;
+       fc_port_t *f, *tf;
        uint32_t id = 0, mask, rid;
-       int rc;
+       unsigned long flags;
 
        switch (ea->event) {
        case FCME_RSCN:
@@ -1350,20 +1354,15 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
                        return;
                switch (ea->id.b.rsvd_1) {
                case RSCN_PORT_ADDR:
-                       fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
-                       if (!fcport) {
-                               /* cable moved */
-                               rc = qla24xx_post_gpnid_work(vha, &ea->id);
-                               if (rc) {
-                                       ql_log(ql_log_warn, vha, 0xd044,
-                                           "RSCN GPNID work failed %02x%02x%02x\n",
-                                           ea->id.b.domain, ea->id.b.area,
-                                           ea->id.b.al_pa);
-                               }
-                       } else {
-                               ea->fcport = fcport;
-                               qla24xx_handle_rscn_event(fcport, ea);
+                       spin_lock_irqsave(&vha->work_lock, flags);
+                       if (vha->scan.scan_flags == 0) {
+                               ql_dbg(ql_dbg_disc, vha, 0xffff,
+                                   "%s: schedule\n", __func__);
+                               vha->scan.scan_flags |= SF_QUEUED;
+                               schedule_delayed_work(&vha->scan.scan_work, 5);
                        }
+                       spin_unlock_irqrestore(&vha->work_lock, flags);
+
                        break;
                case RSCN_AREA_ADDR:
                case RSCN_DOM_ADDR:
@@ -1642,6 +1641,13 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
        unsigned long flags;
        struct fc_port *fcport = ea->fcport;
 
+       ql_dbg(ql_dbg_disc, vha, 0xffff,
+           "%s %8phC DS %d LS %d rc %d login %d|%d rscn %d|%d data %x|%x iop %x|%x\n",
+           __func__, fcport->port_name, fcport->disc_state,
+           fcport->fw_login_state, ea->rc, ea->sp->gen2, fcport->login_gen,
+           ea->sp->gen2, fcport->rscn_gen|ea->sp->gen1,
+           ea->data[0], ea->data[1], ea->iop[0], ea->iop[1]);
+
        if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
            (fcport->fw_login_state == DSC_LS_PRLI_PEND)) {
                ql_dbg(ql_dbg_disc, vha, 0x20ea,
@@ -1656,10 +1662,9 @@ qla24xx_handle_plogi_done_event(struct scsi_qla_host *vha, struct event_arg *ea)
        if (ea->sp->gen2 != fcport->login_gen) {
                /* target side must have changed it. */
                ql_dbg(ql_dbg_disc, vha, 0x20d3,
-                   "%s %8phC generation changed rscn %d|%d login %d|%d\n",
-                   __func__, fcport->port_name, fcport->last_rscn_gen,
-                   fcport->rscn_gen, fcport->last_login_gen,
-                   fcport->login_gen);
+                   "%s %8phC generation changed\n",
+                   __func__, fcport->port_name);
+               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
                return;
        } else if (ea->sp->gen1 != fcport->rscn_gen) {
                ql_dbg(ql_dbg_disc, vha, 0x20d4, "%s %d %8phC post gidpn\n",
@@ -5214,9 +5219,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                        }
                }
 
-               list_for_each_entry(fcport, &vha->vp_fcports, list) {
-                       fcport->scan_state = QLA_FCPORT_SCAN;
-               }
 
                /* Mark the time right before querying FW for connected ports.
                 * This process is long, asynchronous and by the time it's done,
@@ -5232,6 +5234,9 @@ qla2x00_configure_fabric(scsi_qla_host_t *vha)
                        if (rval)
                                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                } else  {
+                       list_for_each_entry(fcport, &vha->vp_fcports, list)
+                               fcport->scan_state = QLA_FCPORT_SCAN;
+
                        rval = qla2x00_find_all_fabric_devs(vha);
                }
                if (rval != QLA_SUCCESS)
index 506119df56a8bf44a7f813383bfb01e3f5d88b3a..605100e3c6c6439fd4b9352ad59e7eb0b8e3a28a 100644 (file)
@@ -4600,6 +4600,7 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,
                scsi_remove_host(vha->host);
                return NULL;
        }
+       INIT_DELAYED_WORK(&vha->scan.scan_work, qla_scan_work_fn);
 
        sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
        ql_dbg(ql_dbg_init, vha, 0x0041,