From: Quinn Tran <quinn.t...@cavium.com>

- Reduce sess_lock holding to prevent CPU Lock up. sess_lock
was held across fc_port registration and deletion.  These calls
can be blocked by upper layer. Sess_lock is also being accessed
by interrupt thread.
- reduce number of loops in processing work_list to prevent
kernel complain of CPU lockup or holding sess_lock.

Signed-off-by: Quinn Tran <quinn.t...@cavium.com>
Signed-off-by: Himanshu Madhani <himanshu.madh...@cavium.com>
---
 drivers/scsi/qla2xxx/qla_def.h    |  2 +-
 drivers/scsi/qla2xxx/qla_gs.c     | 18 ++++++++++++------
 drivers/scsi/qla2xxx/qla_init.c   | 33 +++++++++++++++++----------------
 drivers/scsi/qla2xxx/qla_os.c     |  3 +--
 drivers/scsi/qla2xxx/qla_target.c |  2 ++
 5 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 3a03fe217ac2..8b8c7c8db1ca 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -262,8 +262,8 @@ struct name_list_extended {
        struct get_name_list_extended *l;
        dma_addr_t              ldma;
        struct list_head        fcports;
-       spinlock_t              fcports_lock;
        u32                     size;
+       u8                      sent;
 };
 /*
  * Timeout timer counts in seconds
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 385c46f2576e..3c8882a3e6bc 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3946,11 +3946,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, 
srb_t *sp)
                        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) {
+                                       if (fcport->flags & FCF_FCP2_DEVICE)
+                                               fcport->logout_on_delete = 0;
 
-                               if (fcport->loop_id != FC_NO_LOOP_ID &&
-                                   (fcport->flags & FCF_FCP2_DEVICE) == 0) {
                                        ql_dbg(ql_dbg_disc, vha, 0x20f0,
                                            "%s %d %8phC post del sess\n",
                                            __func__, __LINE__,
@@ -4188,12 +4187,13 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, 
int res)
 
                sp->rc = res;
                rc = qla2x00_post_nvme_gpnft_done_work(vha, sp, QLA_EVT_GPNFT);
-               if (!rc) {
+               if (rc) {
                        qla24xx_sp_unmap(vha, sp);
                        set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
                        set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                        return;
                }
+               return;
        }
 
        if (cmd == GPN_FT_CMD) {
@@ -4243,6 +4243,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, 
struct srb *sp,
                vha->scan.scan_flags &= ~SF_SCANNING;
                spin_unlock_irqrestore(&vha->work_lock, flags);
                WARN_ON(1);
+               set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+               set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                goto done_free_sp;
        }
 
@@ -4276,8 +4278,12 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, 
struct srb *sp,
        sp->done = qla2x00_async_gpnft_gnnft_sp_done;
 
        rval = qla2x00_start_sp(sp);
-       if (rval != QLA_SUCCESS)
+       if (rval != QLA_SUCCESS) {
+               spin_lock_irqsave(&vha->work_lock, flags);
+               vha->scan.scan_flags &= ~SF_SCANNING;
+               spin_unlock_irqrestore(&vha->work_lock, flags);
                goto done_free_sp;
+       }
 
        ql_dbg(ql_dbg_disc, vha, 0xffff,
            "Async-%s hdl=%x FC4Type %x.\n", sp->name,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 49c8f0119620..c675066b080e 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -790,6 +790,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
            sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
            sp->u.iocb_cmd.u.mbx.in_mb[2]);
 
+       sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
        memset(&ea, 0, sizeof(ea));
        ea.sp = sp;
        ea.rc = res;
@@ -817,25 +818,24 @@ qla24xx_async_gnl_sp_done(void *s, int res)
                    (loop_id & 0x7fff));
        }
 
-       spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
+       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
 
        INIT_LIST_HEAD(&h);
        fcport = tf = NULL;
        if (!list_empty(&vha->gnl.fcports))
                list_splice_init(&vha->gnl.fcports, &h);
+       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
        list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
                list_del_init(&fcport->gnl_entry);
-               spin_lock(&vha->hw->tgt.sess_lock);
+               spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
                fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
-               spin_unlock(&vha->hw->tgt.sess_lock);
+               spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                ea.fcport = fcport;
 
                qla2x00_fcport_event_handler(vha, &ea);
        }
-       spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
 
-       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
        /* create new fcport if fw has knowledge of new sessions */
        for (i = 0; i < n; i++) {
                port_id_t id;
@@ -868,6 +868,8 @@ qla24xx_async_gnl_sp_done(void *s, int res)
                }
        }
 
+       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+       vha->gnl.sent = 0;
        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
        sp->free(sp);
@@ -887,27 +889,24 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, 
fc_port_t *fcport)
        ql_dbg(ql_dbg_disc, vha, 0x20d9,
            "Async-gnlist WWPN %8phC \n", fcport->port_name);
 
-       spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
-       if (!list_empty(&fcport->gnl_entry)) {
-               spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
-               rval = QLA_SUCCESS;
-               goto done;
-       }
-
-       spin_lock(&vha->hw->tgt.sess_lock);
+       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+       fcport->flags |= FCF_ASYNC_SENT;
        fcport->disc_state = DSC_GNL;
        fcport->last_rscn_gen = fcport->rscn_gen;
        fcport->last_login_gen = fcport->login_gen;
-       spin_unlock(&vha->hw->tgt.sess_lock);
 
        list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
-       spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
+       if (vha->gnl.sent) {
+               spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+               return QLA_SUCCESS;
+       }
+       vha->gnl.sent = 1;
+       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
        sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
        if (!sp)
                goto done;
 
-       fcport->flags |= FCF_ASYNC_SENT;
        sp->type = SRB_MB_IOCB;
        sp->name = "gnlist";
        sp->gen1 = fcport->rscn_gen;
@@ -1185,7 +1184,9 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, 
struct event_arg *ea)
                vha->fcport_count++;
                ea->fcport->login_succ = 1;
 
+               spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                qla24xx_sched_upd_fcport(ea->fcport);
+               spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
        } else if (ea->fcport->login_succ) {
                /*
                 * We have an existing session. A late RSCN delivery
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 210e5c2999f4..b8b7415bc59d 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2730,7 +2730,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
                struct scsi_qla_host, iocb_work);
        struct qla_hw_data *ha = vha->hw;
        struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
-       int i = 20;
+       int i = 2;
        unsigned long flags;
 
        if (test_bit(UNLOADING, &base_vha->dpc_flags))
@@ -4603,7 +4603,6 @@ struct scsi_qla_host *qla2x00_create_host(struct 
scsi_host_template *sht,
 
        spin_lock_init(&vha->work_lock);
        spin_lock_init(&vha->cmd_list_lock);
-       spin_lock_init(&vha->gnl.fcports_lock);
        init_waitqueue_head(&vha->fcport_waitQ);
        init_waitqueue_head(&vha->vref_waitq);
 
diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 79c290fc36dd..d5f6ce8c86df 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -601,7 +601,9 @@ void qla2x00_async_nack_sp_done(void *s, int res)
                        sp->fcport->login_succ = 1;
 
                        vha->fcport_count++;
+                       spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
                        qla24xx_sched_upd_fcport(sp->fcport);
+                       spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
                } else {
                        sp->fcport->login_retry = 0;
                        sp->fcport->disc_state = DSC_LOGIN_COMPLETE;
-- 
2.12.0

Reply via email to