| From foo@baz Thu May 24 11:23:00 CEST 2018 |
| From: James Smart <jsmart2021@gmail.com> |
| Date: Tue, 30 Jan 2018 15:58:54 -0800 |
| Subject: scsi: lpfc: Fix soft lockup in lpfc worker thread during LIP testing |
| |
| From: James Smart <jsmart2021@gmail.com> |
| |
| [ Upstream commit 161df4f09987ae2e9f0f97f0b38eee298b4a39ff ] |
| |
| During link bounce testing in a point-to-point topology, the host may |
| enter a soft lockup on the lpfc_worker thread: |
| |
| Call Trace: |
| lpfc_work_done+0x1f3/0x1390 [lpfc] |
| lpfc_do_work+0x16f/0x180 [lpfc] |
| kthread+0xc7/0xe0 |
| ret_from_fork+0x3f/0x70 |
| |
| The driver was simultaneously setting a combination of flags that caused |
| lpfc_do_work()to effectively spin between slow path work and new event |
| data, causing the lockup. |
| |
| Ensure in the typical wq completions, that new event data flags are set |
| if the slow path flag is running. The slow path will eventually |
| reschedule the wq handling. |
| |
| Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> |
| Signed-off-by: James Smart <james.smart@broadcom.com> |
| Reviewed-by: Hannes Reinecke <hare@suse.com> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/scsi/lpfc/lpfc_hbadisc.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/scsi/lpfc/lpfc_hbadisc.c |
| +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c |
| @@ -690,8 +690,9 @@ lpfc_work_done(struct lpfc_hba *phba) |
| (phba->hba_flag & HBA_SP_QUEUE_EVT)) { |
| if (pring->flag & LPFC_STOP_IOCB_EVENT) { |
| pring->flag |= LPFC_DEFERRED_RING_EVENT; |
| - /* Set the lpfc data pending flag */ |
| - set_bit(LPFC_DATA_READY, &phba->data_flags); |
| + /* Preserve legacy behavior. */ |
| + if (!(phba->hba_flag & HBA_SP_QUEUE_EVT)) |
| + set_bit(LPFC_DATA_READY, &phba->data_flags); |
| } else { |
| if (phba->link_state >= LPFC_LINK_UP) { |
| pring->flag &= ~LPFC_DEFERRED_RING_EVENT; |