|
@@ -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);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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++) {
|
|
|
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);
|
|
|
- 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 */
|
|
|
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
|