lpfc: Fix SLI4 s abort loop to process all FCP rings and under ring_lock
Fix SLI4 s abort loop to process all FCP rings and under ring_lock 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
ee62021a11
commit
db55fba8dc
|
@ -289,6 +289,7 @@ int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t,
|
||||||
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
|
void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t);
|
||||||
void lpfc_sli_bemem_bcopy(void *, void *, uint32_t);
|
void lpfc_sli_bemem_bcopy(void *, void *, uint32_t);
|
||||||
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
|
void lpfc_sli_abort_iocb_ring(struct lpfc_hba *, struct lpfc_sli_ring *);
|
||||||
|
void lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba);
|
||||||
void lpfc_sli_hba_iocb_abort(struct lpfc_hba *);
|
void lpfc_sli_hba_iocb_abort(struct lpfc_hba *);
|
||||||
void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
|
void lpfc_sli_flush_fcp_rings(struct lpfc_hba *);
|
||||||
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
|
int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||||
|
|
|
@ -880,8 +880,6 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba)
|
||||||
LIST_HEAD(completions);
|
LIST_HEAD(completions);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
if (phba->sli_rev >= LPFC_SLI_REV4)
|
||||||
|
@ -892,6 +890,7 @@ lpfc_hba_clean_txcmplq(struct lpfc_hba *phba)
|
||||||
* 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);
|
||||||
|
pring->txcmplq_cnt = 0;
|
||||||
|
|
||||||
if (phba->sli_rev >= LPFC_SLI_REV4)
|
if (phba->sli_rev >= LPFC_SLI_REV4)
|
||||||
spin_unlock_irq(&pring->ring_lock);
|
spin_unlock_irq(&pring->ring_lock);
|
||||||
|
@ -1300,7 +1299,6 @@ static void
|
||||||
lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
|
lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
uint32_t old_host_status = phba->work_hs;
|
uint32_t old_host_status = phba->work_hs;
|
||||||
struct lpfc_sli_ring *pring;
|
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
|
|
||||||
/* If the pci channel is offline, ignore possible errors,
|
/* If the pci channel is offline, ignore possible errors,
|
||||||
|
@ -1329,8 +1327,7 @@ lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
|
||||||
* dropped by the firmware. Error iocb (I/O) on txcmplq and let the
|
* dropped by the firmware. Error iocb (I/O) on txcmplq and let the
|
||||||
* SCSI layer retry it after re-establishing link.
|
* SCSI layer retry it after re-establishing link.
|
||||||
*/
|
*/
|
||||||
pring = &psli->ring[psli->fcp_ring];
|
lpfc_sli_abort_fcp_rings(phba);
|
||||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There was a firmware error. Take the hba offline and then
|
* There was a firmware error. Take the hba offline and then
|
||||||
|
@ -1398,7 +1395,6 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct lpfc_vport *vport = phba->pport;
|
struct lpfc_vport *vport = phba->pport;
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
struct lpfc_sli_ring *pring;
|
|
||||||
uint32_t event_data;
|
uint32_t event_data;
|
||||||
unsigned long temperature;
|
unsigned long temperature;
|
||||||
struct temp_event temp_event_data;
|
struct temp_event temp_event_data;
|
||||||
|
@ -1450,8 +1446,7 @@ lpfc_handle_eratt_s3(struct lpfc_hba *phba)
|
||||||
* Error iocb (I/O) on txcmplq and let the SCSI layer
|
* Error iocb (I/O) on txcmplq and let the SCSI layer
|
||||||
* retry it after re-establishing link.
|
* retry it after re-establishing link.
|
||||||
*/
|
*/
|
||||||
pring = &psli->ring[psli->fcp_ring];
|
lpfc_sli_abort_fcp_rings(phba);
|
||||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There was a firmware error. Take the hba offline and then
|
* There was a firmware error. Take the hba offline and then
|
||||||
|
@ -9716,9 +9711,6 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev)
|
||||||
static void
|
static void
|
||||||
lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)
|
lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
|
||||||
struct lpfc_sli_ring *pring;
|
|
||||||
|
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
"2723 PCI channel I/O abort preparing for recovery\n");
|
"2723 PCI channel I/O abort preparing for recovery\n");
|
||||||
|
|
||||||
|
@ -9726,8 +9718,7 @@ lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)
|
||||||
* There may be errored I/Os through HBA, abort all I/Os on txcmplq
|
* There may be errored I/Os through HBA, abort all I/Os on txcmplq
|
||||||
* and let the SCSI mid-layer to retry them to recover.
|
* and let the SCSI mid-layer to retry them to recover.
|
||||||
*/
|
*/
|
||||||
pring = &psli->ring[psli->fcp_ring];
|
lpfc_sli_abort_fcp_rings(phba);
|
||||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -10470,17 +10461,13 @@ lpfc_pci_resume_one_s4(struct pci_dev *pdev)
|
||||||
static void
|
static void
|
||||||
lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba)
|
lpfc_sli4_prep_dev_for_recover(struct lpfc_hba *phba)
|
||||||
{
|
{
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
|
||||||
struct lpfc_sli_ring *pring;
|
|
||||||
|
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||||
"2828 PCI channel I/O abort preparing for recovery\n");
|
"2828 PCI channel I/O abort preparing for recovery\n");
|
||||||
/*
|
/*
|
||||||
* There may be errored I/Os through HBA, abort all I/Os on txcmplq
|
* There may be errored I/Os through HBA, abort all I/Os on txcmplq
|
||||||
* and let the SCSI mid-layer to retry them to recover.
|
* and let the SCSI mid-layer to retry them to recover.
|
||||||
*/
|
*/
|
||||||
pring = &psli->ring[psli->fcp_ring];
|
lpfc_sli_abort_fcp_rings(phba);
|
||||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3532,20 +3532,63 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
||||||
/* Error everything on txq and txcmplq
|
/* Error everything on txq and txcmplq
|
||||||
* First do the txq.
|
* First do the txq.
|
||||||
*/
|
*/
|
||||||
spin_lock_irq(&phba->hbalock);
|
if (phba->sli_rev >= LPFC_SLI_REV4) {
|
||||||
list_splice_init(&pring->txq, &completions);
|
spin_lock_irq(&pring->ring_lock);
|
||||||
|
list_splice_init(&pring->txq, &completions);
|
||||||
|
pring->txq_cnt = 0;
|
||||||
|
spin_unlock_irq(&pring->ring_lock);
|
||||||
|
|
||||||
/* Next issue ABTS for everything on the txcmplq */
|
spin_lock_irq(&phba->hbalock);
|
||||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
/* Next issue ABTS for everything on the txcmplq */
|
||||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
||||||
|
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
} else {
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
list_splice_init(&pring->txq, &completions);
|
||||||
|
pring->txq_cnt = 0;
|
||||||
|
|
||||||
spin_unlock_irq(&phba->hbalock);
|
/* Next issue ABTS for everything on the txcmplq */
|
||||||
|
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
||||||
|
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
||||||
|
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_fcp_rings - Abort all iocbs in all FCP rings
|
||||||
|
* @phba: Pointer to HBA context object.
|
||||||
|
* @pring: Pointer to driver SLI ring object.
|
||||||
|
*
|
||||||
|
* This function aborts all iocbs in FCP rings and frees all the iocb
|
||||||
|
* objects in txq. This function issues an abort iocb for all the iocb commands
|
||||||
|
* in txcmplq. The iocbs in the txcmplq is not guaranteed to complete before
|
||||||
|
* the return of this function. The caller is not required to hold any locks.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
lpfc_sli_abort_fcp_rings(struct lpfc_hba *phba)
|
||||||
|
{
|
||||||
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
|
struct lpfc_sli_ring *pring;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
/* Look on all the FCP Rings for the iotag */
|
||||||
|
if (phba->sli_rev >= LPFC_SLI_REV4) {
|
||||||
|
for (i = 0; i < phba->cfg_fcp_io_channel; i++) {
|
||||||
|
pring = &psli->ring[i + MAX_SLI3_CONFIGURED_RINGS];
|
||||||
|
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pring = &psli->ring[psli->fcp_ring];
|
||||||
|
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring
|
* lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring
|
||||||
* @phba: Pointer to HBA context object.
|
* @phba: Pointer to HBA context object.
|
||||||
|
@ -3563,28 +3606,55 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba)
|
||||||
LIST_HEAD(txcmplq);
|
LIST_HEAD(txcmplq);
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
struct lpfc_sli_ring *pring;
|
struct lpfc_sli_ring *pring;
|
||||||
|
uint32_t i;
|
||||||
/* Currently, only one fcp ring */
|
|
||||||
pring = &psli->ring[psli->fcp_ring];
|
|
||||||
|
|
||||||
spin_lock_irq(&phba->hbalock);
|
spin_lock_irq(&phba->hbalock);
|
||||||
/* Retrieve everything on txq */
|
|
||||||
list_splice_init(&pring->txq, &txq);
|
|
||||||
|
|
||||||
/* Retrieve everything on the txcmplq */
|
|
||||||
list_splice_init(&pring->txcmplq, &txcmplq);
|
|
||||||
|
|
||||||
/* Indicate the I/O queues are flushed */
|
/* Indicate the I/O queues are flushed */
|
||||||
phba->hba_flag |= HBA_FCP_IOQ_FLUSH;
|
phba->hba_flag |= HBA_FCP_IOQ_FLUSH;
|
||||||
spin_unlock_irq(&phba->hbalock);
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
/* Flush the txq */
|
/* Look on all the FCP Rings for the iotag */
|
||||||
lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT,
|
if (phba->sli_rev >= LPFC_SLI_REV4) {
|
||||||
IOERR_SLI_DOWN);
|
for (i = 0; i < phba->cfg_fcp_io_channel; i++) {
|
||||||
|
pring = &psli->ring[i + MAX_SLI3_CONFIGURED_RINGS];
|
||||||
|
|
||||||
/* Flush the txcmpq */
|
spin_lock_irq(&pring->ring_lock);
|
||||||
lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT,
|
/* Retrieve everything on txq */
|
||||||
IOERR_SLI_DOWN);
|
list_splice_init(&pring->txq, &txq);
|
||||||
|
/* Retrieve everything on the txcmplq */
|
||||||
|
list_splice_init(&pring->txcmplq, &txcmplq);
|
||||||
|
pring->txq_cnt = 0;
|
||||||
|
pring->txcmplq_cnt = 0;
|
||||||
|
spin_unlock_irq(&pring->ring_lock);
|
||||||
|
|
||||||
|
/* Flush the txq */
|
||||||
|
lpfc_sli_cancel_iocbs(phba, &txq,
|
||||||
|
IOSTAT_LOCAL_REJECT,
|
||||||
|
IOERR_SLI_DOWN);
|
||||||
|
/* Flush the txcmpq */
|
||||||
|
lpfc_sli_cancel_iocbs(phba, &txcmplq,
|
||||||
|
IOSTAT_LOCAL_REJECT,
|
||||||
|
IOERR_SLI_DOWN);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pring = &psli->ring[psli->fcp_ring];
|
||||||
|
|
||||||
|
spin_lock_irq(&phba->hbalock);
|
||||||
|
/* Retrieve everything on txq */
|
||||||
|
list_splice_init(&pring->txq, &txq);
|
||||||
|
/* Retrieve everything on the txcmplq */
|
||||||
|
list_splice_init(&pring->txcmplq, &txcmplq);
|
||||||
|
pring->txq_cnt = 0;
|
||||||
|
pring->txcmplq_cnt = 0;
|
||||||
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
|
/* Flush the txq */
|
||||||
|
lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT,
|
||||||
|
IOERR_SLI_DOWN);
|
||||||
|
/* Flush the txcmpq */
|
||||||
|
lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT,
|
||||||
|
IOERR_SLI_DOWN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -6722,7 +6792,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
|
||||||
LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
|
LPFC_MBOXQ_t *pmbox = phba->sli.mbox_active;
|
||||||
MAILBOX_t *mb = &pmbox->u.mb;
|
MAILBOX_t *mb = &pmbox->u.mb;
|
||||||
struct lpfc_sli *psli = &phba->sli;
|
struct lpfc_sli *psli = &phba->sli;
|
||||||
struct lpfc_sli_ring *pring;
|
|
||||||
|
|
||||||
/* If the mailbox completed, process the completion and return */
|
/* If the mailbox completed, process the completion and return */
|
||||||
if (lpfc_sli4_process_missed_mbox_completions(phba))
|
if (lpfc_sli4_process_missed_mbox_completions(phba))
|
||||||
|
@ -6764,8 +6833,7 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
|
||||||
psli->sli_flag &= ~LPFC_SLI_ACTIVE;
|
psli->sli_flag &= ~LPFC_SLI_ACTIVE;
|
||||||
spin_unlock_irq(&phba->hbalock);
|
spin_unlock_irq(&phba->hbalock);
|
||||||
|
|
||||||
pring = &psli->ring[psli->fcp_ring];
|
lpfc_sli_abort_fcp_rings(phba);
|
||||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
|
||||||
|
|
||||||
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
|
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
|
||||||
"0345 Resetting board due to mailbox timeout\n");
|
"0345 Resetting board due to mailbox timeout\n");
|
||||||
|
@ -9804,43 +9872,6 @@ abort_iotag_exit:
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* lpfc_sli_iocb_ring_abort - Unconditionally abort all iocbs on an iocb ring
|
|
||||||
* @phba: Pointer to HBA context object.
|
|
||||||
* @pring: Pointer to driver SLI ring object.
|
|
||||||
*
|
|
||||||
* This function aborts all iocbs in the given ring and frees all the iocb
|
|
||||||
* objects in txq. This function issues abort iocbs unconditionally for all
|
|
||||||
* the iocb commands in txcmplq. The iocbs in the txcmplq is not guaranteed
|
|
||||||
* to complete before the return of this function. The caller is not required
|
|
||||||
* to hold any locks.
|
|
||||||
**/
|
|
||||||
static void
|
|
||||||
lpfc_sli_iocb_ring_abort(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
|
||||||
{
|
|
||||||
LIST_HEAD(completions);
|
|
||||||
struct lpfc_iocbq *iocb, *next_iocb;
|
|
||||||
|
|
||||||
if (pring->ringno == LPFC_ELS_RING)
|
|
||||||
lpfc_fabric_abort_hba(phba);
|
|
||||||
|
|
||||||
spin_lock_irq(&phba->hbalock);
|
|
||||||
|
|
||||||
/* Take off all the iocbs on txq for cancelling */
|
|
||||||
list_splice_init(&pring->txq, &completions);
|
|
||||||
pring->txq_cnt = 0;
|
|
||||||
|
|
||||||
/* Next issue ABTS for everything on the txcmplq */
|
|
||||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
|
||||||
lpfc_sli_abort_iotag_issue(phba, pring, iocb);
|
|
||||||
|
|
||||||
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_hba_iocb_abort - Abort all iocbs to an hba.
|
* lpfc_sli_hba_iocb_abort - Abort all iocbs to an hba.
|
||||||
* @phba: pointer to lpfc HBA data structure.
|
* @phba: pointer to lpfc HBA data structure.
|
||||||
|
@ -9856,7 +9887,7 @@ lpfc_sli_hba_iocb_abort(struct lpfc_hba *phba)
|
||||||
|
|
||||||
for (i = 0; i < psli->num_rings; i++) {
|
for (i = 0; i < psli->num_rings; i++) {
|
||||||
pring = &psli->ring[i];
|
pring = &psli->ring[i];
|
||||||
lpfc_sli_iocb_ring_abort(phba, pring);
|
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue