scsi: lpfc: Clear outstanding active mailbox during PCI function reset
authorJames Smart <jsmart2021@gmail.com>
Wed, 7 Jul 2021 18:43:43 +0000 (11:43 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 19 Jul 2021 02:30:36 +0000 (22:30 -0400)
Mailbox commands sent via ioctl/bsg from user applications may be
interrupted from processing by a concurrently triggered PCI function
reset. The command will not generate a completion due to the reset.  This
results in a user application hang waiting for the mailbox command to
complete.

Resolve by changing the function reset handler to detect that there was an
outstanding mailbox command and simulate a mailbox completion.  Add some
additional debug when a mailbox command times out.

Link: https://lore.kernel.org/r/20210707184351.67872-13-jsmart2021@gmail.com
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c

index 55f720ac6c8ce4d82da3178d565b91d86c20aa56..4fd9a8098e865aec909cf87d0cdbd4cba13ad9e6 100644 (file)
@@ -1852,6 +1852,7 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
 {
        int rc;
        uint32_t intr_mode;
+       LPFC_MBOXQ_t *mboxq;
 
        if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) >=
            LPFC_SLI_INTF_IF_TYPE_2) {
@@ -1871,11 +1872,19 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
                                "Recovery...\n");
 
        /* If we are no wait, the HBA has been reset and is not
-        * functional, thus we should clear LPFC_SLI_ACTIVE flag.
+        * functional, thus we should clear
+        * (LPFC_SLI_ACTIVE | LPFC_SLI_MBOX_ACTIVE) flags.
         */
        if (mbx_action == LPFC_MBX_NO_WAIT) {
                spin_lock_irq(&phba->hbalock);
                phba->sli.sli_flag &= ~LPFC_SLI_ACTIVE;
+               if (phba->sli.mbox_active) {
+                       mboxq = phba->sli.mbox_active;
+                       mboxq->u.mb.mbxStatus = MBX_NOT_FINISHED;
+                       __lpfc_mbox_cmpl_put(phba, mboxq);
+                       phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+                       phba->sli.mbox_active = NULL;
+               }
                spin_unlock_irq(&phba->hbalock);
        }
 
index 1fdb2232729fc8f313492a02c7cc3e0f87d19a7a..c34240819d92c1c986781c63e998b586dca153da 100644 (file)
@@ -8794,8 +8794,11 @@ static int
 lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
 {
        struct lpfc_sli *psli = &phba->sli;
+       LPFC_MBOXQ_t *mboxq;
        int rc = 0;
        unsigned long timeout = 0;
+       u32 sli_flag;
+       u8 cmd, subsys, opcode;
 
        /* Mark the asynchronous mailbox command posting as blocked */
        spin_lock_irq(&phba->hbalock);
@@ -8813,12 +8816,37 @@ lpfc_sli4_async_mbox_block(struct lpfc_hba *phba)
        if (timeout)
                lpfc_sli4_process_missed_mbox_completions(phba);
 
-       /* Wait for the outstnading mailbox command to complete */
+       /* Wait for the outstanding mailbox command to complete */
        while (phba->sli.mbox_active) {
                /* Check active mailbox complete status every 2ms */
                msleep(2);
                if (time_after(jiffies, timeout)) {
-                       /* Timeout, marked the outstanding cmd not complete */
+                       /* Timeout, mark the outstanding cmd not complete */
+
+                       /* Sanity check sli.mbox_active has not completed or
+                        * cancelled from another context during last 2ms sleep,
+                        * so take hbalock to be sure before logging.
+                        */
+                       spin_lock_irq(&phba->hbalock);
+                       if (phba->sli.mbox_active) {
+                               mboxq = phba->sli.mbox_active;
+                               cmd = mboxq->u.mb.mbxCommand;
+                               subsys = lpfc_sli_config_mbox_subsys_get(phba,
+                                                                        mboxq);
+                               opcode = lpfc_sli_config_mbox_opcode_get(phba,
+                                                                        mboxq);
+                               sli_flag = psli->sli_flag;
+                               spin_unlock_irq(&phba->hbalock);
+                               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+                                               "2352 Mailbox command x%x "
+                                               "(x%x/x%x) sli_flag x%x could "
+                                               "not complete\n",
+                                               cmd, subsys, opcode,
+                                               sli_flag);
+                       } else {
+                               spin_unlock_irq(&phba->hbalock);
+                       }
+
                        rc = 1;
                        break;
                }