Commit 5a9eeff5 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: Fix kernel Oops due to null pring pointers

Driver is hitting null pring pointers in lpfc_do_work().

Pointer assignment occurs based on SLI-revision. If recovering after an
error, its possible the sli revision for the port was cleared, making the
lpfc_phba_elsring() not return a ring pointer, thus the null pointer.

Add SLI revision checking to lpfc_phba_elsring() and status checking to all
callers.
Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 2c4c9141
...@@ -1277,6 +1277,12 @@ lpfc_sli_read_hs(struct lpfc_hba *phba) ...@@ -1277,6 +1277,12 @@ lpfc_sli_read_hs(struct lpfc_hba *phba)
static inline struct lpfc_sli_ring * static inline struct lpfc_sli_ring *
lpfc_phba_elsring(struct lpfc_hba *phba) lpfc_phba_elsring(struct lpfc_hba *phba)
{ {
/* Return NULL if sli_rev has become invalid due to bad fw */
if (phba->sli_rev != LPFC_SLI_REV4 &&
phba->sli_rev != LPFC_SLI_REV3 &&
phba->sli_rev != LPFC_SLI_REV2)
return NULL;
if (phba->sli_rev == LPFC_SLI_REV4) { if (phba->sli_rev == LPFC_SLI_REV4) {
if (phba->sli4_hba.els_wq) if (phba->sli4_hba.els_wq)
return phba->sli4_hba.els_wq->pring; return phba->sli4_hba.els_wq->pring;
......
...@@ -1343,6 +1343,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba) ...@@ -1343,6 +1343,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
Fabric_DID); Fabric_DID);
pring = lpfc_phba_elsring(phba); pring = lpfc_phba_elsring(phba);
if (unlikely(!pring))
return -EIO;
/* /*
* Check the txcmplq for an iocb that matches the nport the driver is * Check the txcmplq for an iocb that matches the nport the driver is
......
...@@ -1797,7 +1797,12 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action, ...@@ -1797,7 +1797,12 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
lpfc_offline(phba); lpfc_offline(phba);
/* release interrupt for possible resource change */ /* release interrupt for possible resource change */
lpfc_sli4_disable_intr(phba); lpfc_sli4_disable_intr(phba);
lpfc_sli_brdrestart(phba); rc = lpfc_sli_brdrestart(phba);
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"6309 Failed to restart board\n");
return rc;
}
/* request and enable interrupt */ /* request and enable interrupt */
intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode); intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
if (intr_mode == LPFC_INTR_ERROR) { if (intr_mode == LPFC_INTR_ERROR) {
......
...@@ -4687,6 +4687,8 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba) ...@@ -4687,6 +4687,8 @@ lpfc_sli_brdrestart_s4(struct lpfc_hba *phba)
hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED; hba_aer_enabled = phba->hba_flag & HBA_AER_ENABLED;
rc = lpfc_sli4_brdreset(phba); rc = lpfc_sli4_brdreset(phba);
if (rc)
return rc;
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
phba->pport->stopped = 0; phba->pport->stopped = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment