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: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
2c4c91415a
commit
5a9eeff57f
|
@ -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)
|
||||||
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,
|
||||||
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)
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue