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>
This commit is contained in:
parent
a3da825b49
commit
e29d74f8eb
|
@ -2388,18 +2388,18 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
|
||||||
void
|
void
|
||||||
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
|
lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
|
||||||
{
|
{
|
||||||
wait_queue_head_t *pdone_q;
|
|
||||||
unsigned long drvr_flag;
|
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.
|
* continued running.
|
||||||
*/
|
*/
|
||||||
pmboxq->mbox_flag |= LPFC_MBX_WAKE;
|
pmboxq->mbox_flag |= LPFC_MBX_WAKE;
|
||||||
spin_lock_irqsave(&phba->hbalock, drvr_flag);
|
spin_lock_irqsave(&phba->hbalock, drvr_flag);
|
||||||
pdone_q = (wait_queue_head_t *) pmboxq->context1;
|
pmbox_done = (struct completion *)pmboxq->context3;
|
||||||
if (pdone_q)
|
if (pmbox_done)
|
||||||
wake_up_interruptible(pdone_q);
|
complete(pmbox_done);
|
||||||
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -11665,31 +11665,25 @@ int
|
||||||
lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
|
lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq,
|
||||||
uint32_t timeout)
|
uint32_t timeout)
|
||||||
{
|
{
|
||||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
|
struct completion mbox_done;
|
||||||
MAILBOX_t *mb = NULL;
|
|
||||||
int retval;
|
int retval;
|
||||||
unsigned long flag;
|
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;
|
pmboxq->mbox_flag &= ~LPFC_MBX_WAKE;
|
||||||
/* setup wake call as IOCB callback */
|
/* setup wake call as IOCB callback */
|
||||||
pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait;
|
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 */
|
/* now issue the command */
|
||||||
retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
|
retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
|
||||||
if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
|
if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
|
||||||
wait_event_interruptible_timeout(done_q,
|
wait_for_completion_timeout(&mbox_done,
|
||||||
pmboxq->mbox_flag & LPFC_MBX_WAKE,
|
msecs_to_jiffies(timeout * 1000));
|
||||||
msecs_to_jiffies(timeout * 1000));
|
|
||||||
|
|
||||||
spin_lock_irqsave(&phba->hbalock, flag);
|
spin_lock_irqsave(&phba->hbalock, flag);
|
||||||
/* restore the possible extended buffer for free resource */
|
pmboxq->context3 = NULL;
|
||||||
pmboxq->context1 = (uint8_t *)mb;
|
|
||||||
/*
|
/*
|
||||||
* if LPFC_MBX_WAKE flag is set the mailbox is completed
|
* if LPFC_MBX_WAKE flag is set the mailbox is completed
|
||||||
* else do not free the resources.
|
* 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;
|
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&phba->hbalock, flag);
|
spin_unlock_irqrestore(&phba->hbalock, flag);
|
||||||
} else {
|
|
||||||
/* restore the possible extended buffer for free resource */
|
|
||||||
pmboxq->context1 = (uint8_t *)mb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ typedef struct lpfcMboxq {
|
||||||
struct lpfc_vport *vport;/* virtual port pointer */
|
struct lpfc_vport *vport;/* virtual port pointer */
|
||||||
void *context1; /* caller context information */
|
void *context1; /* caller context information */
|
||||||
void *context2; /* caller context information */
|
void *context2; /* caller context information */
|
||||||
|
void *context3;
|
||||||
|
|
||||||
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
||||||
uint8_t mbox_flag;
|
uint8_t mbox_flag;
|
||||||
|
|
Loading…
Reference in New Issue