Commit 13989452 authored by James Smart's avatar James Smart Committed by Greg Kroah-Hartman

scsi: lpfc: Fix mailbox hang on adapter init

[ Upstream commit e8869f5b ]

The adapter initialization sequence enables interrupts, initializes the
adapter link_state to LINK_DOWN, then issues commands to initialize the
adapter. The interrupt handler on the adapter validates the link_state (has
to be at least LINK_DOWN) and if invalid, will discard the interrupting
event.

In most cases, there is not a command completion, thus an interrupt until
the initialization commands have been sent which is post the setting of
state to LINK_DOWN.  However, in cases of firmware reset, the reset will
modify the link_state to an invalid value (indicating a reset of the
adapter) and there occasionally are cases where the adapter will generate
an asynchronous event which shares the eq/cq used for mailbox commands. In
the failure case, an interrupt is generated immediately after enabling them
due to the async event.  As link_state is invalid, the eq is list and the
CQ not serviced.  At this point link_state is initialized and the mailbox
command sent.  As the CQ has not been serviced, it is not armed, so no
interrupt event is generated when the mailbox command completes.

Modify the initialization sequence so that interrupts are enabled after
link_state is properly initialized, which avoids the race condition with
the async event.
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>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 4b9e930e
...@@ -7652,12 +7652,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) ...@@ -7652,12 +7652,6 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
phba->cfg_xri_rebalancing = 0; phba->cfg_xri_rebalancing = 0;
} }
/* Arm the CQs and then EQs on device */
lpfc_sli4_arm_cqeq_intr(phba);
/* Indicate device interrupt mode */
phba->sli4_hba.intr_enable = 1;
/* Allow asynchronous mailbox command to go through */ /* Allow asynchronous mailbox command to go through */
spin_lock_irq(&phba->hbalock); spin_lock_irq(&phba->hbalock);
phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK; phba->sli.sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
...@@ -7726,6 +7720,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) ...@@ -7726,6 +7720,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
phba->trunk_link.link3.state = LPFC_LINK_DOWN; phba->trunk_link.link3.state = LPFC_LINK_DOWN;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
/* Arm the CQs and then EQs on device */
lpfc_sli4_arm_cqeq_intr(phba);
/* Indicate device interrupt mode */
phba->sli4_hba.intr_enable = 1;
if (!(phba->hba_flag & HBA_FCOE_MODE) && if (!(phba->hba_flag & HBA_FCOE_MODE) &&
(phba->hba_flag & LINK_DISABLED)) { (phba->hba_flag & LINK_DISABLED)) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI, lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_SLI,
......
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