mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-06 02:24:14 +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;
|
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
|
* lpfc_hba_down_post_s3 - Perform lpfc uninitialization after HBA reset
|
||||||
|
int i;
|
||||||
* @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 do uninitialization after the HBA is reset when bring
|
||||||
@ -833,44 +911,8 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
|
|||||||
static int
|
static int
|
||||||
lpfc_hba_down_post_s3(struct lpfc_hba *phba)
|
lpfc_hba_down_post_s3(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
lpfc_hba_free_post_buf(phba);
|
||||||
struct lpfc_sli_ring *pring;
|
lpfc_hba_clean_txcmplq(phba);
|
||||||
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);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user