| From 4005a995668b8fd58f4cf1460dd4cf63efa18363 Mon Sep 17 00:00:00 2001 |
| From: Quinn Tran <quinn.tran@cavium.com> |
| Date: Mon, 4 Dec 2017 14:45:06 -0800 |
| Subject: scsi: qla2xxx: Fix Relogin being triggered too fast |
| |
| From: Quinn Tran <quinn.tran@cavium.com> |
| |
| commit 4005a995668b8fd58f4cf1460dd4cf63efa18363 upstream. |
| |
| Current driver design schedules relogin process via DPC thread every 1 |
| second. In a large fabric, this DPC thread tries to schedule too many |
| jobs and might get overloaded. As a result of this processing of DPC |
| thread, it can schedule relogin earlier than 1 second. |
| |
| Fixes: 726b85487067d ("qla2xxx: Add framework for async fabric discovery") |
| Cc: <stable@vger.kernel.org> # 4.10+ |
| Signed-off-by: Quinn Tran <quinn.tran@cavium.com> |
| Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> |
| Reviewed-by: Hannes Reinecke <hare@suse.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/qla2xxx/qla_def.h | 1 + |
| drivers/scsi/qla2xxx/qla_mid.c | 22 ++++++++++++++-------- |
| drivers/scsi/qla2xxx/qla_os.c | 22 ++++++++++++++-------- |
| 3 files changed, 29 insertions(+), 16 deletions(-) |
| |
| --- a/drivers/scsi/qla2xxx/qla_def.h |
| +++ b/drivers/scsi/qla2xxx/qla_def.h |
| @@ -4085,6 +4085,7 @@ typedef struct scsi_qla_host { |
| #define LOOP_READY 5 |
| #define LOOP_DEAD 6 |
| |
| + unsigned long relogin_jif; |
| unsigned long dpc_flags; |
| #define RESET_MARKER_NEEDED 0 /* Send marker to ISP. */ |
| #define RESET_ACTIVE 1 |
| --- a/drivers/scsi/qla2xxx/qla_mid.c |
| +++ b/drivers/scsi/qla2xxx/qla_mid.c |
| @@ -343,15 +343,21 @@ qla2x00_do_dpc_vp(scsi_qla_host_t *vha) |
| "FCPort update end.\n"); |
| } |
| |
| - if ((test_and_clear_bit(RELOGIN_NEEDED, &vha->dpc_flags)) && |
| - !test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) && |
| - atomic_read(&vha->loop_state) != LOOP_DOWN) { |
| + if (test_bit(RELOGIN_NEEDED, &vha->dpc_flags) && |
| + !test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) && |
| + atomic_read(&vha->loop_state) != LOOP_DOWN) { |
| |
| - ql_dbg(ql_dbg_dpc, vha, 0x4018, |
| - "Relogin needed scheduled.\n"); |
| - qla2x00_relogin(vha); |
| - ql_dbg(ql_dbg_dpc, vha, 0x4019, |
| - "Relogin needed end.\n"); |
| + if (!vha->relogin_jif || |
| + time_after_eq(jiffies, vha->relogin_jif)) { |
| + vha->relogin_jif = jiffies + HZ; |
| + clear_bit(RELOGIN_NEEDED, &vha->dpc_flags); |
| + |
| + ql_dbg(ql_dbg_dpc, vha, 0x4018, |
| + "Relogin needed scheduled.\n"); |
| + qla2x00_relogin(vha); |
| + ql_dbg(ql_dbg_dpc, vha, 0x4019, |
| + "Relogin needed end.\n"); |
| + } |
| } |
| |
| if (test_and_clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags) && |
| --- a/drivers/scsi/qla2xxx/qla_os.c |
| +++ b/drivers/scsi/qla2xxx/qla_os.c |
| @@ -4860,7 +4860,7 @@ void qla2x00_relogin(struct scsi_qla_hos |
| */ |
| if (atomic_read(&fcport->state) != FCS_ONLINE && |
| fcport->login_retry && !(fcport->flags & FCF_ASYNC_SENT)) { |
| - fcport->login_retry--; |
| + |
| if (fcport->flags & FCF_FABRIC_DEVICE) { |
| ql_dbg(ql_dbg_disc, fcport->vha, 0x2108, |
| "%s %8phC DS %d LS %d\n", __func__, |
| @@ -4871,6 +4871,7 @@ void qla2x00_relogin(struct scsi_qla_hos |
| ea.fcport = fcport; |
| qla2x00_fcport_event_handler(vha, &ea); |
| } else { |
| + fcport->login_retry--; |
| status = qla2x00_local_device_login(vha, |
| fcport); |
| if (status == QLA_SUCCESS) { |
| @@ -5853,16 +5854,21 @@ qla2x00_do_dpc(void *data) |
| } |
| |
| /* Retry each device up to login retry count */ |
| - if ((test_and_clear_bit(RELOGIN_NEEDED, |
| - &base_vha->dpc_flags)) && |
| + if (test_bit(RELOGIN_NEEDED, &base_vha->dpc_flags) && |
| !test_bit(LOOP_RESYNC_NEEDED, &base_vha->dpc_flags) && |
| atomic_read(&base_vha->loop_state) != LOOP_DOWN) { |
| |
| - ql_dbg(ql_dbg_dpc, base_vha, 0x400d, |
| - "Relogin scheduled.\n"); |
| - qla2x00_relogin(base_vha); |
| - ql_dbg(ql_dbg_dpc, base_vha, 0x400e, |
| - "Relogin end.\n"); |
| + if (!base_vha->relogin_jif || |
| + time_after_eq(jiffies, base_vha->relogin_jif)) { |
| + base_vha->relogin_jif = jiffies + HZ; |
| + clear_bit(RELOGIN_NEEDED, &base_vha->dpc_flags); |
| + |
| + ql_dbg(ql_dbg_dpc, base_vha, 0x400d, |
| + "Relogin scheduled.\n"); |
| + qla2x00_relogin(base_vha); |
| + ql_dbg(ql_dbg_dpc, base_vha, 0x400e, |
| + "Relogin end.\n"); |
| + } |
| } |
| loop_resync_check: |
| if (test_and_clear_bit(LOOP_RESYNC_NEEDED, |