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