mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 10:04:12 +08:00
lpfc: Fix locking for lpfc_hba_down_post
Fix locking for lpfc_hba_down_post Signed-off-by: James Smart <james.smart@emulex.com> Reviewed-By: Dick Kennedy <dick.kennedy@emulex.com> Signed-off-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
6acb348149
commit
bcece5f557
@ -819,8 +819,86 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_hba_free_post_buf - Perform lpfc uninitialization after HBA reset
|
||||
* @phba: pointer to lpfc HBA data structure.
|
||||
*
|
||||
* This routine will cleanup posted ELS buffers after the HBA is reset
|
||||
* when bringing down the SLI Layer.
|
||||
*
|
||||
*
|
||||
* Return codes
|
||||
* void.
|
||||
**/
|
||||
static void
|
||||
lpfc_hba_free_post_buf(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_dmabuf *mp, *next_mp;
|
||||
|
||||
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
|
||||
lpfc_sli_hbqbuf_free_all(phba);
|
||||
else {
|
||||
/* Cleanup preposted buffers on the ELS ring */
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
pring = &psli->ring[LPFC_ELS_RING];
|
||||
list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
|
||||
list_del(&mp->list);
|
||||
pring->postbufq_cnt--;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
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;
|
||||
|
||||
|
||||
|
||||
for (i = 0; i < psli->num_rings; 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
|
||||
* way, nothing should be on txcmplq as it will NEVER complete.
|
||||
*/
|
||||
list_splice_init(&pring->txcmplq, &completions);
|
||||
|
||||
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 */
|
||||
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
|
||||
IOERR_SLI_ABORTED);
|
||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -833,44 +911,8 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
|
||||
static int
|
||||
lpfc_hba_down_post_s3(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_dmabuf *mp, *next_mp;
|
||||
LIST_HEAD(completions);
|
||||
int i;
|
||||
|
||||
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
|
||||
lpfc_sli_hbqbuf_free_all(phba);
|
||||
else {
|
||||
/* Cleanup preposted buffers on the ELS ring */
|
||||
pring = &psli->ring[LPFC_ELS_RING];
|
||||
list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
|
||||
list_del(&mp->list);
|
||||
pring->postbufq_cnt--;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
|
||||
/* At this point in time the HBA is either reset or DOA. Either
|
||||
* way, nothing should be on txcmplq as it will NEVER complete.
|
||||
*/
|
||||
list_splice_init(&pring->txcmplq, &completions);
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
/* Cancel all the IOCBs from the completions list */
|
||||
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
|
||||
IOERR_SLI_ABORTED);
|
||||
|
||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||
spin_lock_irq(&phba->hbalock);
|
||||
}
|
||||
spin_unlock_irq(&phba->hbalock);
|
||||
|
||||
lpfc_hba_free_post_buf(phba);
|
||||
lpfc_hba_clean_txcmplq(phba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -890,13 +932,12 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_scsi_buf *psb, *psb_next;
|
||||
LIST_HEAD(aborts);
|
||||
int ret;
|
||||
unsigned long iflag = 0;
|
||||
struct lpfc_sglq *sglq_entry = NULL;
|
||||
|
||||
ret = lpfc_hba_down_post_s3(phba);
|
||||
if (ret)
|
||||
return ret;
|
||||
lpfc_hba_free_post_buf(phba);
|
||||
lpfc_hba_clean_txcmplq(phba);
|
||||
|
||||
/* 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
|
||||
* on the lpfc_sgl_list so that it can either be freed if the
|
||||
|
Loading…
Reference in New Issue
Block a user