/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2006 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2007 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
hc_copy = readl(phba->HCregaddr);
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
+ phba->fc_flag |= FC_IGNORE_ERATT;
if (readl(phba->HAregaddr) & HA_ERATT) {
/* Clear Chip error bit */
}
restore_hc:
+ phba->fc_flag &= ~FC_IGNORE_ERATT;
writel(hc_copy, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
}
status &= ~HC_ERINT_ENA;
writel(status, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
+ phba->fc_flag |= FC_IGNORE_ERATT;
spin_unlock_irq(phba->host->host_lock);
lpfc_kill_board(phba, pmb);
if (retval != MBX_SUCCESS) {
if (retval != MBX_BUSY)
mempool_free(pmb, phba->mbox_mem_pool);
+ spin_lock_irq(phba->host->host_lock);
+ phba->fc_flag &= ~FC_IGNORE_ERATT;
+ spin_unlock_irq(phba->host->host_lock);
return 1;
}
}
spin_lock_irq(phba->host->host_lock);
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
+ phba->fc_flag &= ~FC_IGNORE_ERATT;
spin_unlock_irq(phba->host->host_lock);
psli->mbox_active = NULL;
if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
/*
- * Only CREATE_XRI, CLOSE_XRI, ABORT_XRI, and QUE_RING_BUF
+ * Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
* can be issued if the link is not up.
*/
switch (piocb->iocb.ulpCommand) {
piocb->iocb_cmpl = NULL;
/*FALLTHROUGH*/
case CMD_CREATE_XRI_CR:
+ case CMD_CLOSE_XRI_CN:
+ case CMD_CLOSE_XRI_CX:
break;
default:
goto iocb_busy;
lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
struct lpfc_iocbq * rspiocb)
{
+ IOCB_t *irsp;
+ uint16_t abort_iotag, abort_context;
+ struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
+ struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+
+ abort_iocb = NULL;
+ irsp = &rspiocb->iocb;
+
spin_lock_irq(phba->host->host_lock);
+
+ if (irsp->ulpStatus) {
+ abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
+ abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
+
+ if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
+ abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+ "%d:0327 Cannot abort els iocb %p"
+ " with tag %x context %x\n",
+ phba->brd_no, abort_iocb,
+ abort_iotag, abort_context);
+
+ /*
+ * make sure we have the right iocbq before taking it
+ * off the txcmplq and try to call completion routine.
+ */
+ if (abort_iocb &&
+ abort_iocb->iocb.ulpContext == abort_context &&
+ abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
+ list_del(&abort_iocb->list);
+ pring->txcmplq_cnt--;
+
+ rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
+ if (rsp_ab_iocb == NULL)
+ lpfc_sli_release_iocbq(phba, abort_iocb);
+ else {
+ abort_iocb->iocb_flag &=
+ ~LPFC_DRIVER_ABORTED;
+ rsp_ab_iocb->iocb.ulpStatus =
+ IOSTAT_LOCAL_REJECT;
+ rsp_ab_iocb->iocb.un.ulpWord[4] =
+ IOERR_SLI_ABORTED;
+ spin_unlock_irq(phba->host->host_lock);
+ (abort_iocb->iocb_cmpl)
+ (phba, abort_iocb, rsp_ab_iocb);
+ spin_lock_irq(phba->host->host_lock);
+ lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
+ }
+ }
+ }
+
lpfc_sli_release_iocbq(phba, cmdiocb);
spin_unlock_irq(phba->host->host_lock);
return;
*/
spin_lock(phba->host->host_lock);
ha_copy = readl(phba->HAregaddr);
+ /* If somebody is waiting to handle an eratt don't process it
+ * here. The brdkill function will do this.
+ */
+ if (phba->fc_flag & FC_IGNORE_ERATT)
+ ha_copy &= ~HA_ERATT;
writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
spin_unlock(phba->host->host_lock);