scsi: lpfc: Fix crash receiving ELS while detaching driver
The driver crashes when attempting to use a freed ndpl pointer. The pci_remove_one handler runs on a separate kernel thread. The order of the removal is starting by freeing all of the ndlps and then disabling interrupts. In between these two events the driver can still receive an ELS and process it. When it tries to use the ndlp pointer will be NULL Change the order of the pci_remove_one vs disable interrupts so that interrupts are disabled before the ndlp's are freed. Cc: <stable@vger.kernel.org> # 4.12+ Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <james.smart@broadcom.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:

committed by
Martin K. Petersen

parent
401bb4169d
commit
1234a6d54f
@@ -10632,6 +10632,14 @@ lpfc_sli_issue_abort_iotag(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
||||
(cmdiocb->iocb_flag & LPFC_DRIVER_ABORTED) != 0)
|
||||
return 0;
|
||||
|
||||
if (!pring) {
|
||||
if (cmdiocb->iocb_flag & LPFC_IO_FABRIC)
|
||||
cmdiocb->fabric_iocb_cmpl = lpfc_ignore_els_cmpl;
|
||||
else
|
||||
cmdiocb->iocb_cmpl = lpfc_ignore_els_cmpl;
|
||||
goto abort_iotag_exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're unloading, don't abort iocb on the ELS ring, but change
|
||||
* the callback so that nothing happens when it finishes.
|
||||
@@ -12500,6 +12508,8 @@ lpfc_sli4_els_wcqe_to_rspiocbq(struct lpfc_hba *phba,
|
||||
unsigned long iflags;
|
||||
|
||||
pring = lpfc_phba_elsring(phba);
|
||||
if (unlikely(!pring))
|
||||
return NULL;
|
||||
|
||||
wcqe = &irspiocbq->cq_event.cqe.wcqe_cmpl;
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
@@ -18691,6 +18701,8 @@ lpfc_drain_txq(struct lpfc_hba *phba)
|
||||
uint32_t txq_cnt = 0;
|
||||
|
||||
pring = lpfc_phba_elsring(phba);
|
||||
if (unlikely(!pring))
|
||||
return 0;
|
||||
|
||||
spin_lock_irqsave(&pring->ring_lock, iflags);
|
||||
list_for_each_entry(piocbq, &pring->txq, list) {
|
||||
|
Reference in New Issue
Block a user