scsi: lpfc: Fix mailbox wait for POST_SGL mbox command
authorJames Smart <jsmart2021@gmail.com>
Mon, 5 Mar 2018 20:04:07 +0000 (12:04 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 13 Mar 2018 01:55:24 +0000 (21:55 -0400)
POST_SGL_PAGES mailbox command failed with status (timeout).

wait_event_interruptible_timeout when called from mailbox wait interface,
gets interrupted, and will randomly fail. Behavior seems very specific to 1
particular server type.

Fix by changing from wait_event_interruptible_timeout to
wait_for_completion_timeout.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/lpfc/lpfc_sli.h

index 7999a40e1370ce6029bd5fadd72b8901f5712091..1a9083adef1f0ff36ecf36055bda110bd3b65df3 100644 (file)
@@ -2388,18 +2388,18 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
 void
 lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
 {
-       wait_queue_head_t *pdone_q;
        unsigned long drvr_flag;
+       struct completion *pmbox_done;
 
        /*
-        * If pdone_q is empty, the driver thread gave up waiting and
+        * If pmbox_done is empty, the driver thread gave up waiting and
         * continued running.
         */
        pmboxq->mbox_flag |= LPFC_MBX_WAKE;
        spin_lock_irqsave(&phba->hbalock, drvr_flag);
-       pdone_q = (wait_queue_head_t *) pmboxq->context1;
-       if (pdone_q)
-               wake_up_interruptible(pdone_q);
+       pmbox_done = (struct completion *)pmboxq->context3;
+       if (pmbox_done)
+               complete(pmbox_done);
        spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
        return;
 }
@@ -11665,31 +11665,25 @@ int
 lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
                         uint32_t timeout)
 {
-       DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
-       MAILBOX_t *mb = NULL;
+       struct completion mbox_done;
        int retval;
        unsigned long flag;
 
-       /* The caller might set context1 for extended buffer */
-       if (pmboxq->context1)
-               mb = (MAILBOX_t *)pmboxq->context1;
-
        pmboxq->mbox_flag &= ~LPFC_MBX_WAKE;
        /* setup wake call as IOCB callback */
        pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait;
-       /* setup context field to pass wait_queue pointer to wake function  */
-       pmboxq->context1 = &done_q;
 
+       /* setup context3 field to pass wait_queue pointer to wake function  */
+       init_completion(&mbox_done);
+       pmboxq->context3 = &mbox_done;
        /* now issue the command */
        retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
        if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
-               wait_event_interruptible_timeout(done_q,
-                               pmboxq->mbox_flag & LPFC_MBX_WAKE,
-                               msecs_to_jiffies(timeout * 1000));
+               wait_for_completion_timeout(&mbox_done,
+                                           msecs_to_jiffies(timeout * 1000));
 
                spin_lock_irqsave(&phba->hbalock, flag);
-               /* restore the possible extended buffer for free resource */
-               pmboxq->context1 = (uint8_t *)mb;
+               pmboxq->context3 = NULL;
                /*
                 * if LPFC_MBX_WAKE flag is set the mailbox is completed
                 * else do not free the resources.
@@ -11701,11 +11695,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
                        pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
                }
                spin_unlock_irqrestore(&phba->hbalock, flag);
-       } else {
-               /* restore the possible extended buffer for free resource */
-               pmboxq->context1 = (uint8_t *)mb;
        }
-
        return retval;
 }
 
index ad7b2e0a2018469eeea487a5e0895e258796a6ae..431754195505d04bb75087c80751d00b3408ee0a 100644 (file)
@@ -147,6 +147,7 @@ typedef struct lpfcMboxq {
        struct lpfc_vport *vport;/* virtual port pointer */
        void *context1;         /* caller context information */
        void *context2;         /* caller context information */
+       void *context3;
 
        void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
        uint8_t mbox_flag;