提交 bcece5f5 编写于 作者: J James Smart 提交者: Christoph Hellwig

lpfc: Fix locking for lpfc_hba_down_post

Fix locking for lpfc_hba_down_post
Signed-off-by: NJames Smart <james.smart@emulex.com>
Reviewed-By: NDick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: NChristoph Hellwig <hch@lst.de>
上级 6acb3481
...@@ -820,29 +820,28 @@ lpfc_hba_down_prep(struct lpfc_hba *phba) ...@@ -820,29 +820,28 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
} }
/** /**
* lpfc_hba_down_post_s3 - Perform lpfc uninitialization after HBA reset * lpfc_hba_free_post_buf - Perform lpfc uninitialization after HBA reset
* @phba: pointer to lpfc HBA data structure. * @phba: pointer to lpfc HBA data structure.
* *
* This routine will do uninitialization after the HBA is reset when bring * This routine will cleanup posted ELS buffers after the HBA is reset
* down the SLI Layer. * when bringing down the SLI Layer.
*
* *
* Return codes * Return codes
* 0 - success. * void.
* Any other value - error.
**/ **/
static int static void
lpfc_hba_down_post_s3(struct lpfc_hba *phba) lpfc_hba_free_post_buf(struct lpfc_hba *phba)
{ {
struct lpfc_sli *psli = &phba->sli; struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring; struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp; struct lpfc_dmabuf *mp, *next_mp;
LIST_HEAD(completions);
int i;
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
lpfc_sli_hbqbuf_free_all(phba); lpfc_sli_hbqbuf_free_all(phba);
else { else {
/* Cleanup preposted buffers on the ELS ring */ /* Cleanup preposted buffers on the ELS ring */
spin_lock_irq(&phba->hbalock);
pring = &psli->ring[LPFC_ELS_RING]; pring = &psli->ring[LPFC_ELS_RING];
list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) { list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
list_del(&mp->list); list_del(&mp->list);
...@@ -850,27 +849,70 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba) ...@@ -850,27 +849,70 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba)
lpfc_mbuf_free(phba, mp->virt, mp->phys); lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp); kfree(mp);
} }
spin_unlock_irq(&phba->hbalock);
} }
}
/**
* lpfc_hba_clean_txcmplq - Perform lpfc uninitialization after HBA reset
* @phba: pointer to lpfc HBA data structure.
*
* This routine will cleanup the txcmplq after the HBA is reset when bringing
* down the SLI Layer.
*
* Return codes
* void
**/
static void
lpfc_hba_clean_txcmplq(struct lpfc_hba *phba)
{
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
LIST_HEAD(completions);
int i;
spin_lock_irq(&phba->hbalock);
for (i = 0; i < psli->num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i]; pring = &psli->ring[i];
if (phba->sli_rev >= LPFC_SLI_REV4)
spin_lock_irq(&pring->ring_lock);
else
spin_lock_irq(&phba->hbalock);
/* At this point in time the HBA is either reset or DOA. Either /* At this point in time the HBA is either reset or DOA. Either
* way, nothing should be on txcmplq as it will NEVER complete. * way, nothing should be on txcmplq as it will NEVER complete.
*/ */
list_splice_init(&pring->txcmplq, &completions); list_splice_init(&pring->txcmplq, &completions);
spin_unlock_irq(&phba->hbalock);
if (phba->sli_rev >= LPFC_SLI_REV4)
spin_unlock_irq(&pring->ring_lock);
else
spin_unlock_irq(&phba->hbalock);
/* Cancel all the IOCBs from the completions list */ /* Cancel all the IOCBs from the completions list */
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
IOERR_SLI_ABORTED); IOERR_SLI_ABORTED);
lpfc_sli_abort_iocb_ring(phba, pring); lpfc_sli_abort_iocb_ring(phba, pring);
spin_lock_irq(&phba->hbalock);
} }
spin_unlock_irq(&phba->hbalock); }
/**
* lpfc_hba_down_post_s3 - Perform lpfc uninitialization after HBA reset
int i;
* @phba: pointer to lpfc HBA data structure.
*
* This routine will do uninitialization after the HBA is reset when bring
* down the SLI Layer.
*
* Return codes
* 0 - success.
* Any other value - error.
**/
static int
lpfc_hba_down_post_s3(struct lpfc_hba *phba)
{
lpfc_hba_free_post_buf(phba);
lpfc_hba_clean_txcmplq(phba);
return 0; return 0;
} }
...@@ -890,13 +932,12 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba) ...@@ -890,13 +932,12 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
{ {
struct lpfc_scsi_buf *psb, *psb_next; struct lpfc_scsi_buf *psb, *psb_next;
LIST_HEAD(aborts); LIST_HEAD(aborts);
int ret;
unsigned long iflag = 0; unsigned long iflag = 0;
struct lpfc_sglq *sglq_entry = NULL; struct lpfc_sglq *sglq_entry = NULL;
ret = lpfc_hba_down_post_s3(phba); lpfc_hba_free_post_buf(phba);
if (ret) lpfc_hba_clean_txcmplq(phba);
return ret;
/* At this point in time the HBA is either reset or DOA. Either /* At this point in time the HBA is either reset or DOA. Either
* way, nothing should be on lpfc_abts_els_sgl_list, it needs to be * way, nothing should be on lpfc_abts_els_sgl_list, it needs to be
* on the lpfc_sgl_list so that it can either be freed if the * on the lpfc_sgl_list so that it can either be freed if the
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册