scsi: lpfc: Correct soft lockup when running mds diagnostics
authorJames Smart <jsmart2021@gmail.com>
Mon, 10 Sep 2018 17:30:45 +0000 (10:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2018 19:16:53 +0000 (11:16 -0800)
[ Upstream commit 0ef01a2d95fd62bb4f536e7ce4d5e8e74b97a244 ]

When running an mds diagnostic that passes frames with the switch, soft
lockups are detected. The driver is in a CQE processing loop and has
sufficient amount of traffic that it never exits the ring processing routine,
thus the "lockup".

Cap the number of elements in the work processing routine to 64 elements. This
ensures that the cpu will be given up and the handler reschedule to process
additional items.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/scsi/lpfc/lpfc_sli.c

index 6df06e716da1274b5cfc7397c1c6af573e40e61e..c05fc61a383b265c11cbf8d8d78ebfce176d8f1b 100644 (file)
@@ -3512,6 +3512,7 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
        struct hbq_dmabuf *dmabuf;
        struct lpfc_cq_event *cq_event;
        unsigned long iflag;
+       int count = 0;
 
        spin_lock_irqsave(&phba->hbalock, iflag);
        phba->hba_flag &= ~HBA_SP_QUEUE_EVT;
@@ -3533,16 +3534,22 @@ lpfc_sli_handle_slow_ring_event_s4(struct lpfc_hba *phba,
                        if (irspiocbq)
                                lpfc_sli_sp_handle_rspiocb(phba, pring,
                                                           irspiocbq);
+                       count++;
                        break;
                case CQE_CODE_RECEIVE:
                case CQE_CODE_RECEIVE_V1:
                        dmabuf = container_of(cq_event, struct hbq_dmabuf,
                                              cq_event);
                        lpfc_sli4_handle_received_buffer(phba, dmabuf);
+                       count++;
                        break;
                default:
                        break;
                }
+
+               /* Limit the number of events to 64 to avoid soft lockups */
+               if (count == 64)
+                       break;
        }
 }