Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bcece5f5 authored by James Smart's avatar James Smart Committed by Christoph Hellwig
Browse files

lpfc: Fix locking for lpfc_hba_down_post



Fix locking for lpfc_hba_down_post

Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Reviewed-By: default avatarDick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 6acb3481
Loading
Loading
Loading
Loading
+60 −19
Original line number Diff line number Diff line
@@ -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.
 *
 * This routine will do uninitialization after the HBA is reset when bring
 * down the SLI Layer.
 * This routine will cleanup posted ELS buffers after the HBA is reset
 * when bringing down the SLI Layer.
 *
 *
 * Return codes
 *   0 - success.
 *   Any other value - error.
 *   void.
 **/
static int
lpfc_hba_down_post_s3(struct lpfc_hba *phba)
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;
	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 */
		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);
@@ -850,27 +849,70 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba)
			lpfc_mbuf_free(phba, mp->virt, mp->phys);
			kfree(mp);
		}
		spin_unlock_irq(&phba->hbalock);
	}
}

	spin_lock_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);
		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;
}

@@ -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