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@xxxxxxxxxxxx> Signed-off-by: James Smart <james.smart@xxxxxxxxxxxx> --- drivers/scsi/lpfc/lpfc_sli.c | 34 ++++++++++++---------------------- 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; -- 2.13.1