Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 341b2aa8 authored by Dick Kennedy's avatar Dick Kennedy Committed by Martin K. Petersen
Browse files

scsi: lpfc: Fix hard lock up NMI in els timeout handling.



System crashed due to a hard lockup at lpfc_els_timeout_handler+0x128.

The els ring's txcmplq list is corrupted: the last element in the list
does not point back the the head causing a loop. Issue is the els
processing path for sli4 hbas are using the hbalock instead of the
ring_lock for removing elements from the txcmplq list.

Use the adapter SLI_REV to determine which lock should be used for
removing iocbqs from the els rings txcmplq.

note: the future refactoring will address this so that we don't have
this ugly type-based lock code.

Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Reviewed-by: default avatarEwan D. Milne <emilne@redhat.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 268eb498
Loading
Loading
Loading
Loading
+10 −3
Original line number Diff line number Diff line
@@ -2732,7 +2732,8 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
 *
 * This function looks up the iocb_lookup table to get the command iocb
 * corresponding to the given response iocb using the iotag of the
 * response iocb. This function is called with the hbalock held.
 * response iocb. This function is called with the hbalock held
 * for sli3 devices or the ring_lock for sli4 devices.
 * This function returns the command iocb object if it finds the command
 * iocb else returns NULL.
 **/
@@ -2828,8 +2829,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
	unsigned long iflag;
	/* Based on the iotag field, get the cmd IOCB from the txcmplq */
	if (phba->sli_rev == LPFC_SLI_REV4)
		spin_lock_irqsave(&pring->ring_lock, iflag);
	else
		spin_lock_irqsave(&phba->hbalock, iflag);
	cmdiocbp = lpfc_sli_iocbq_lookup(phba, pring, saveq);
	if (phba->sli_rev == LPFC_SLI_REV4)
		spin_unlock_irqrestore(&pring->ring_lock, iflag);
	else
		spin_unlock_irqrestore(&phba->hbalock, iflag);
	if (cmdiocbp) {