diff options
author | Quinn Tran <qutran@marvell.com> | 2022-12-22 05:39:29 +0100 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2023-01-12 05:48:26 +0100 |
commit | 129a7c40294fd4ab9e9bccf76e8002818f492d8a (patch) | |
tree | a57d3688e0801788d235e5078bc9c44fef5972c4 /drivers/scsi/qla2xxx | |
parent | scsi: qla2xxx: edif: Fix performance dip due to lock contention (diff) | |
download | linux-129a7c40294fd4ab9e9bccf76e8002818f492d8a.tar.xz linux-129a7c40294fd4ab9e9bccf76e8002818f492d8a.zip |
scsi: qla2xxx: edif: Fix stall session after app start
For N2N, qla2x00_wait_for_sess_deletion call flushes
a session which accidentally clear the scan_flag and thus prevents
re-login to occur and causes session to stall.
Use session delete to avoid the accidental clearing of scan_flag.
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qla2xxx')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_edif.c | 56 |
1 files changed, 49 insertions, 7 deletions
diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index ba58d8cb3183..06e68a7ad86a 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -480,6 +480,49 @@ void qla2x00_release_all_sadb(struct scsi_qla_host *vha, struct fc_port *fcport) } /** + * qla_delete_n2n_sess_and_wait: search for N2N session, tear it down and + * wait for tear down to complete. In N2N topology, there is only one + * session being active in tracking the remote device. + * @vha: host adapter pointer + * return code: 0 - found the session and completed the tear down. + * 1 - timeout occurred. Caller to use link bounce to reset. + */ +static int qla_delete_n2n_sess_and_wait(scsi_qla_host_t *vha) +{ + struct fc_port *fcport; + int rc = -EIO; + ulong expire = jiffies + 23 * HZ; + + if (!N2N_TOPO(vha->hw)) + return 0; + + fcport = NULL; + list_for_each_entry(fcport, &vha->vp_fcports, list) { + if (!fcport->n2n_flag) + continue; + + ql_dbg(ql_dbg_disc, fcport->vha, 0x2016, + "%s reset sess at app start \n", __func__); + + qla_edif_sa_ctl_init(vha, fcport); + qlt_schedule_sess_for_deletion(fcport); + + while (time_before_eq(jiffies, expire)) { + if (fcport->disc_state != DSC_DELETE_PEND) { + rc = 0; + break; + } + msleep(1); + } + + set_bit(RELOGIN_NEEDED, &vha->dpc_flags); + break; + } + + return rc; +} + +/** * qla_edif_app_start: application has announce its present * @vha: host adapter pointer * @bsg_job: user request @@ -518,18 +561,17 @@ qla_edif_app_start(scsi_qla_host_t *vha, struct bsg_job *bsg_job) fcport->n2n_link_reset_cnt = 0; if (vha->hw->flags.n2n_fw_acc_sec) { - list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) - qla_edif_sa_ctl_init(vha, fcport); - + bool link_bounce = false; /* * While authentication app was not running, remote device * could still try to login with this local port. Let's - * clear the state and try again. + * reset the session, reconnect and re-authenticate. */ - qla2x00_wait_for_sess_deletion(vha); + if (qla_delete_n2n_sess_and_wait(vha)) + link_bounce = true; - /* bounce the link to get the other guy to relogin */ - if (!vha->hw->flags.n2n_bigger) { + /* bounce the link to start login */ + if (!vha->hw->flags.n2n_bigger || link_bounce) { set_bit(N2N_LINK_RESET, &vha->dpc_flags); qla2xxx_wake_dpc(vha); } |