diff mbox series

[v2,04/14] qla2xxx: Optimize NPIV tear down process

Message ID 20190912180918.6436-5-hmadhani@marvell.com (mailing list archive)
State Accepted
Headers show
Series qla2xxx: Bug fixes for the driver | expand

Commit Message

Himanshu Madhani Sept. 12, 2019, 6:09 p.m. UTC
From: Quinn Tran <qutran@marvell.com>

In the case of NPIV port is being torn down, this patch will
set a flag to indicate VPORT_DELETE. This would prevent relogin
to be triggered.

Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
---
 drivers/scsi/qla2xxx/qla_attr.c   |  2 ++
 drivers/scsi/qla2xxx/qla_def.h    |  1 +
 drivers/scsi/qla2xxx/qla_gs.c     |  3 ++-
 drivers/scsi/qla2xxx/qla_mid.c    | 32 ++++++++++++++++++++++----------
 drivers/scsi/qla2xxx/qla_os.c     |  7 ++++++-
 drivers/scsi/qla2xxx/qla_target.c |  1 +
 6 files changed, 34 insertions(+), 12 deletions(-)

Comments

Martin Wilck Sept. 26, 2019, 10:52 a.m. UTC | #1
On Thu, 2019-09-12 at 11:09 -0700, Himanshu Madhani wrote:
> From: Quinn Tran <qutran@marvell.com>
> 
> In the case of NPIV port is being torn down, this patch will
> set a flag to indicate VPORT_DELETE. This would prevent relogin
> to be triggered.
> 
> Signed-off-by: Quinn Tran <qutran@marvell.com>
> Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
> ---
>  drivers/scsi/qla2xxx/qla_attr.c   |  2 ++
>  drivers/scsi/qla2xxx/qla_def.h    |  1 +
>  drivers/scsi/qla2xxx/qla_gs.c     |  3 ++-
>  drivers/scsi/qla2xxx/qla_mid.c    | 32 ++++++++++++++++++++++-------
> ---
>  drivers/scsi/qla2xxx/qla_os.c     |  7 ++++++-
>  drivers/scsi/qla2xxx/qla_target.c |  1 +
>  6 files changed, 34 insertions(+), 12 deletions(-)
> 
> --- a/drivers/scsi/qla2xxx/qla_mid.c
> +++ b/drivers/scsi/qla2xxx/qla_mid.c
> @@ -66,6 +66,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
>  	uint16_t vp_id;
>  	struct qla_hw_data *ha = vha->hw;
>  	unsigned long flags = 0;
> +	u8 i;
>  
>  	mutex_lock(&ha->vport_lock);
>  	/*
> @@ -75,8 +76,9 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
>  	 * ensures no active vp_list traversal while the vport is
> removed
>  	 * from the queue)
>  	 */
> -	wait_event_timeout(vha->vref_waitq, !atomic_read(&vha-
> >vref_count),
> -	    10*HZ);
> +	for (i = 0; i < 10 && atomic_read(&vha->vref_count); i++)
> +		wait_event_timeout(vha->vref_waitq,
> +		    atomic_read(&vha->vref_count), HZ);

Are you missing a negation in this last line?
Also, what's the point of adding this loop? 


> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -1115,9 +1115,14 @@ static inline int
> test_fcport_count(scsi_qla_host_t *vha)
>  void
>  qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
>  {
> +	u8 i;
> +
>  	qla2x00_mark_all_devices_lost(vha, 0);
>  
> -	wait_event_timeout(vha->fcport_waitQ, test_fcport_count(vha),
> 10*HZ);
> +	for (i = 0; i < 10; i++)
> +		wait_event_timeout(vha->fcport_waitQ,
> test_fcport_count(vha),
> +		    HZ);
> +
>  	flush_workqueue(vha->hw->wq);
>  }

Perhaps here, the loop should be exited if test_fcport_count(vha) gets
TRUE? And again, why is the loop necessary?

Regards
Martin
Quinn Tran Sept. 26, 2019, 4:56 p.m. UTC | #2
On 9/26/19, 3:52 AM, "Martin Wilck" <mwilck@suse.de> wrote:

    External Email
    
    ----------------------------------------------------------------------
    On Thu, 2019-09-12 at 11:09 -0700, Himanshu Madhani wrote:
    > From: Quinn Tran <qutran@marvell.com>
    > 
    > In the case of NPIV port is being torn down, this patch will
    > set a flag to indicate VPORT_DELETE. This would prevent relogin
    > to be triggered.
    > 
    > Signed-off-by: Quinn Tran <qutran@marvell.com>
    > Signed-off-by: Himanshu Madhani <hmadhani@marvell.com>
    > ---
    >  drivers/scsi/qla2xxx/qla_attr.c   |  2 ++
    >  drivers/scsi/qla2xxx/qla_def.h    |  1 +
    >  drivers/scsi/qla2xxx/qla_gs.c     |  3 ++-
    >  drivers/scsi/qla2xxx/qla_mid.c    | 32 ++++++++++++++++++++++-------
    > ---
    >  drivers/scsi/qla2xxx/qla_os.c     |  7 ++++++-
    >  drivers/scsi/qla2xxx/qla_target.c |  1 +
    >  6 files changed, 34 insertions(+), 12 deletions(-)
    > 
    > --- a/drivers/scsi/qla2xxx/qla_mid.c
    > +++ b/drivers/scsi/qla2xxx/qla_mid.c
    > @@ -66,6 +66,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
    >  	uint16_t vp_id;
    >  	struct qla_hw_data *ha = vha->hw;
    >  	unsigned long flags = 0;
    > +	u8 i;
    >  
    >  	mutex_lock(&ha->vport_lock);
    >  	/*
    > @@ -75,8 +76,9 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
    >  	 * ensures no active vp_list traversal while the vport is
    > removed
    >  	 * from the queue)
    >  	 */
    > -	wait_event_timeout(vha->vref_waitq, !atomic_read(&vha-
    > >vref_count),
    > -	    10*HZ);
    > +	for (i = 0; i < 10 && atomic_read(&vha->vref_count); i++)
    > +		wait_event_timeout(vha->vref_waitq,
    > +		    atomic_read(&vha->vref_count), HZ);
    
    Are you missing a negation in this last line?
    Also, what's the point of adding this loop? 

QT:  good catch.  The idea is to not sleep the full 10Hz, if the vref_count already reaches zero or reaches zero under 10Hz.  Otherwise, loop/wait for 10Hz.   We're trying to get NPIV tear down to go faster.
    
    
    > --- a/drivers/scsi/qla2xxx/qla_os.c
    > +++ b/drivers/scsi/qla2xxx/qla_os.c
    > @@ -1115,9 +1115,14 @@ static inline int
    > test_fcport_count(scsi_qla_host_t *vha)
    >  void
    >  qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
    >  {
    > +	u8 i;
    > +
    >  	qla2x00_mark_all_devices_lost(vha, 0);
    >  
    > -	wait_event_timeout(vha->fcport_waitQ, test_fcport_count(vha),
    > 10*HZ);
    > +	for (i = 0; i < 10; i++)
    > +		wait_event_timeout(vha->fcport_waitQ,
    > test_fcport_count(vha),
    > +		    HZ);
    > +
    >  	flush_workqueue(vha->hw->wq);
    >  }
    
    Perhaps here, the loop should be exited if test_fcport_count(vha) gets
    TRUE? And again, why is the loop necessary?
QT:  Yes.     Same answer as above with the looping.

    Regards
    Martin
Martin Wilck Sept. 27, 2019, 6:33 a.m. UTC | #3
On Thu, 2019-09-26 at 16:56 +0000, Quinn Tran wrote:
>     
>     Are you missing a negation in this last line?
>     Also, what's the point of adding this loop? 
> 
> QT:  good catch.  The idea is to not sleep the full 10Hz, if the
> vref_count already reaches zero or reaches zero under
> 10Hz.  Otherwise, loop/wait for 10Hz.   We're trying to get NPIV tear
> down to go faster.

AFAIU, wait_event_timeout() returns before the timeout has elapsed, if
the tested condition becomes true _and_ the wait queue is woken up. 
Thus the loop shouldn't be necessary. Are you missing a wake_up() call
to vref_waitq somewhere? 

Perhaps you should replace all calls to 

        atomic_dec(&X->vref_count);

with something like

        if (atomic_dec_and_test(&X->vref_count))
                wake_up(&X->vref_waitq);

??

Martin
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index e9c449ef515c..8b3015361428 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -2920,6 +2920,8 @@  qla24xx_vport_delete(struct fc_vport *fc_vport)
 	struct qla_hw_data *ha = vha->hw;
 	uint16_t id = vha->vp_idx;
 
+	set_bit(VPORT_DELETE, &vha->dpc_flags);
+
 	while (test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags) ||
 	    test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
 		msleep(1000);
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 873a6aef1c5c..fa038568beb6 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -4394,6 +4394,7 @@  typedef struct scsi_qla_host {
 #define IOCB_WORK_ACTIVE	31
 #define SET_ZIO_THRESHOLD_NEEDED 32
 #define ISP_ABORT_TO_ROM	33
+#define VPORT_DELETE		34
 
 	unsigned long	pci_flags;
 #define PFLG_DISCONNECTED	0	/* PCI device removed */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index dc0e36676313..5298ed10059f 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3102,7 +3102,8 @@  int qla24xx_post_gpnid_work(struct scsi_qla_host *vha, port_id_t *id)
 {
 	struct qla_work_evt *e;
 
-	if (test_bit(UNLOADING, &vha->dpc_flags))
+	if (test_bit(UNLOADING, &vha->dpc_flags) ||
+	    (vha->vp_idx && test_bit(VPORT_DELETE, &vha->dpc_flags)))
 		return 0;
 
 	e = qla2x00_alloc_work(vha, QLA_EVT_GPNID);
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 1a9a11ae7285..6afad68e5ba2 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -66,6 +66,7 @@  qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
 	uint16_t vp_id;
 	struct qla_hw_data *ha = vha->hw;
 	unsigned long flags = 0;
+	u8 i;
 
 	mutex_lock(&ha->vport_lock);
 	/*
@@ -75,8 +76,9 @@  qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
 	 * ensures no active vp_list traversal while the vport is removed
 	 * from the queue)
 	 */
-	wait_event_timeout(vha->vref_waitq, !atomic_read(&vha->vref_count),
-	    10*HZ);
+	for (i = 0; i < 10 && atomic_read(&vha->vref_count); i++)
+		wait_event_timeout(vha->vref_waitq,
+		    atomic_read(&vha->vref_count), HZ);
 
 	spin_lock_irqsave(&ha->vport_slock, flags);
 	if (atomic_read(&vha->vref_count)) {
@@ -262,6 +264,9 @@  qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
 	spin_lock_irqsave(&ha->vport_slock, flags);
 	list_for_each_entry(vha, &ha->vp_list, list) {
 		if (vha->vp_idx) {
+			if (test_bit(VPORT_DELETE, &vha->dpc_flags))
+				continue;
+
 			atomic_inc(&vha->vref_count);
 			spin_unlock_irqrestore(&ha->vport_slock, flags);
 
@@ -300,6 +305,20 @@  qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
 int
 qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
 {
+	fc_port_t *fcport;
+
+	/*
+	 * To exclusively reset vport, we need to log it out first.
+	 * Note: This control_vp can fail if ISP reset is already
+	 * issued, this is expected, as the vp would be already
+	 * logged out due to ISP reset.
+	 */
+	if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) {
+		qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
+		list_for_each_entry(fcport, &vha->vp_fcports, list)
+			fcport->logout_on_delete = 0;
+	}
+
 	/*
 	 * Physical port will do most of the abort and recovery work. We can
 	 * just treat it as a loop down
@@ -312,16 +331,9 @@  qla2x00_vp_abort_isp(scsi_qla_host_t *vha)
 			atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 	}
 
-	/*
-	 * To exclusively reset vport, we need to log it out first.  Note: this
-	 * control_vp can fail if ISP reset is already issued, this is
-	 * expected, as the vp would be already logged out due to ISP reset.
-	 */
-	if (!test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags))
-		qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
-
 	ql_dbg(ql_dbg_taskm, vha, 0x801d,
 	    "Scheduling enable of Vport %d.\n", vha->vp_idx);
+
 	return qla24xx_enable_vp(vha);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 42980e52fb41..5eda86ff6606 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1115,9 +1115,14 @@  static inline int test_fcport_count(scsi_qla_host_t *vha)
 void
 qla2x00_wait_for_sess_deletion(scsi_qla_host_t *vha)
 {
+	u8 i;
+
 	qla2x00_mark_all_devices_lost(vha, 0);
 
-	wait_event_timeout(vha->fcport_waitQ, test_fcport_count(vha), 10*HZ);
+	for (i = 0; i < 10; i++)
+		wait_event_timeout(vha->fcport_waitQ, test_fcport_count(vha),
+		    HZ);
+
 	flush_workqueue(vha->hw->wq);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index b5315be00b4d..a06e56224a55 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -1115,6 +1115,7 @@  void qlt_free_session_done(struct work_struct *work)
 		wake_up_all(&tgt->waitQ);
 
 	if (!test_bit(PFLG_DRIVER_REMOVING, &base_vha->pci_flags) &&
+	    !(vha->vp_idx && test_bit(VPORT_DELETE, &vha->dpc_flags)) &&
 	    (!tgt || !tgt->tgt_stop) && !LOOP_TRANSITION(vha)) {
 		switch (vha->host->active_mode) {
 		case MODE_INITIATOR: