diff options
author | James Smart <jsmart2021@gmail.com> | 2018-03-05 23:04:07 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2018-03-13 04:55:24 +0300 |
commit | e29d74f8eb1450b0b6c4736210d76cb56ef40e1d (patch) | |
tree | f449dc44b6d2df5d62457dbf84ef6e8a03836f53 /drivers | |
parent | a3da825b499f495f959052b848e893550ddaf626 (diff) | |
download | linux-e29d74f8eb1450b0b6c4736210d76cb56ef40e1d.tar.xz |
scsi: lpfc: Fix mailbox wait for POST_SGL mbox command
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 34 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.h | 1 |
2 files changed, 13 insertions, 22 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7999a40e1370..1a9083adef1f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -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; } diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index ad7b2e0a2018..431754195505 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -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; |