/*******************************************************************
* 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-2005 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
lpfc_sli_ringtxcmpl_put(struct lpfc_hba * phba,
struct lpfc_sli_ring * pring, struct lpfc_iocbq * piocb)
{
+ uint16_t iotag;
+
list_add_tail(&piocb->list, &pring->txcmplq);
pring->txcmplq_cnt++;
if (unlikely(pring->ringno == LPFC_ELS_RING))
mod_timer(&phba->els_tmofunc,
jiffies + HZ * (phba->fc_ratov << 1));
+ if (pring->fast_lookup) {
+ /* Setup fast lookup based on iotag for completion */
+ iotag = piocb->iocb.ulpIoTag;
+ if (iotag && (iotag < pring->fast_iotag))
+ *(pring->fast_lookup + iotag) = piocb;
+ else {
+
+ /* Cmd ring <ringno> put: iotag <iotag> greater then
+ configured max <fast_iotag> wd0 <icmd> */
+ lpfc_printf_log(phba,
+ KERN_ERR,
+ LOG_SLI,
+ "%d:0316 Cmd ring %d put: iotag x%x "
+ "greater then configured max x%x "
+ "wd0 x%x\n",
+ phba->brd_no,
+ pring->ringno, iotag,
+ pring->fast_iotag,
+ *(((uint32_t *)(&piocb->iocb)) + 7));
+ }
+ }
return (0);
}
kfree(old_arr);
return iotag;
}
- } else
- spin_unlock_irq(phba->host->host_lock);
+ }
lpfc_printf_log(phba, KERN_ERR,LOG_SLI,
"%d:0318 Failed to allocate IOTAG.last IOTAG is %d\n",
case MBX_SET_MASK:
case MBX_SET_SLIM:
case MBX_UNREG_D_ID:
- case MBX_KILL_BOARD:
case MBX_CONFIG_FARP:
- case MBX_BEACON:
case MBX_LOAD_AREA:
case MBX_RUN_BIU_DIAG64:
case MBX_CONFIG_PORT:
/* Stray Mailbox Interrupt, mbxCommand <cmd> mbxStatus
<status> */
lpfc_printf_log(phba,
- KERN_WARNING,
+ KERN_ERR,
LOG_MBOX | LOG_SLI,
"%d:0304 Stray Mailbox Interrupt "
"mbxCommand x%x mbxStatus x%x\n",
}
/* unSolicited Responses */
if (pring->prt[0].profile) {
- if (pring->prt[0].lpfc_sli_rcv_unsol_event)
- (pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring,
- saveq);
+ (pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring, saveq);
match = 1;
} else {
/* We must search, based on rctl / type
Rctl)
&& (pring->prt[i].
type == Type)) {
- if (pring->prt[i].lpfc_sli_rcv_unsol_event)
- (pring->prt[i].lpfc_sli_rcv_unsol_event)
- (phba, pring, saveq);
+ (pring->prt[i].lpfc_sli_rcv_unsol_event)
+ (phba, pring, saveq);
match = 1;
break;
}
* resources need to be recovered.
*/
if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "%d:0314 IOCB cmd 0x%x"
- " processed. Skipping"
- " completion", phba->brd_no,
- irsp->ulpCommand);
+ printk(KERN_INFO "%s: IOCB cmd 0x%x processed."
+ " Skipping completion\n", __FUNCTION__,
+ irsp->ulpCommand);
break;
}
if (unlikely(irsp->ulpStatus)) {
/* Rsp ring <ringno> error: IOCB */
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
- "%d:0336 Rsp Ring %d error: IOCB Data: "
+ "%d:0326 Rsp Ring %d error: IOCB Data: "
"x%x x%x x%x x%x x%x x%x x%x x%x\n",
phba->brd_no, pring->ringno,
irsp->un.ulpWord[0], irsp->un.ulpWord[1],
* resources need to be recovered.
*/
if (unlikely(irsp->ulpCommand == CMD_XRI_ABORTED_CX)) {
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "%d:0333 IOCB cmd 0x%x"
- " processed. Skipping"
- " completion\n", phba->brd_no,
- irsp->ulpCommand);
+ printk(KERN_INFO "%s: IOCB cmd 0x%x processed. "
+ "Skipping completion\n", __FUNCTION__,
+ irsp->ulpCommand);
break;
}
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
- if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
- &rspiocbq);
- } else {
- spin_unlock_irqrestore(
- phba->host->host_lock, iflag);
- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
- &rspiocbq);
- spin_lock_irqsave(phba->host->host_lock,
- iflag);
- }
+ spin_unlock_irqrestore(
+ phba->host->host_lock, iflag);
+ (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
+ &rspiocbq);
+ spin_lock_irqsave(phba->host->host_lock,
+ iflag);
}
break;
default:
} else {
/* Unknown IOCB command */
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "%d:0334 Unknown IOCB command "
+ "%d:0321 Unknown IOCB command "
"Data: x%x, x%x x%x x%x x%x\n",
phba->brd_no, type, irsp->ulpCommand,
irsp->ulpStatus, irsp->ulpIoTag,
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
- "%d:0303 Ring %d handler: portRspPut %d "
+ "%d:0312 Ring %d handler: portRspPut %d "
"is bigger then rsp ring %d\n",
phba->brd_no,
pring->ringno, portRspPut, portRspMax);
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
- "%d:0335 Unknown IOCB command "
+ "%d:0321 Unknown IOCB command "
"Data: x%x x%x x%x x%x\n",
phba->brd_no,
irsp->ulpCommand,
next_iocb,
&saveq->list,
list) {
- list_del(&rspiocbp->list);
lpfc_sli_release_iocbq(phba,
rspiocbp);
}
}
+
lpfc_sli_release_iocbq(phba, saveq);
}
}
return errcnt;
}
-int
-lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
-{
- uint32_t status;
- int i = 0;
- int retval = 0;
-
- /* Read the HBA Host Status Register */
- status = readl(phba->HSregaddr);
-
- /*
- * Check status register every 100ms for 5 retries, then every
- * 500ms for 5, then every 2.5 sec for 5, then reset board and
- * every 2.5 sec for 4.
- * Break our of the loop if errors occurred during init.
- */
- while (((status & mask) != mask) &&
- !(status & HS_FFERM) &&
- i++ < 20) {
-
- if (i <= 5)
- msleep(10);
- else if (i <= 10)
- msleep(500);
- else
- msleep(2500);
-
- if (i == 15) {
- phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
- lpfc_sli_brdrestart(phba);
- }
- /* Read the HBA Host Status Register */
- status = readl(phba->HSregaddr);
- }
-
- /* Check to see if any errors occurred during init */
- if ((status & HS_FFERM) || (i >= 20)) {
- phba->hba_state = LPFC_HBA_ERROR;
- retval = 1;
- }
-
- return retval;
-}
-
-#define BARRIER_TEST_PATTERN (0xdeadbeef)
-
-void lpfc_reset_barrier(struct lpfc_hba * phba)
-{
- uint32_t __iomem *resp_buf;
- uint32_t __iomem *mbox_buf;
- volatile uint32_t mbox;
- uint32_t hc_copy;
- int i;
- uint8_t hdrtype;
-
- pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
- if (hdrtype != 0x80 ||
- (FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID &&
- FC_JEDEC_ID(phba->vpd.rev.biuRev) != THOR_JEDEC_ID))
- return;
-
- /*
- * Tell the other part of the chip to suspend temporarily all
- * its DMA activity.
- */
- resp_buf = phba->MBslimaddr;
-
- /* Disable the error attention */
- hc_copy = readl(phba->HCregaddr);
- writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
- readl(phba->HCregaddr); /* flush */
-
- if (readl(phba->HAregaddr) & HA_ERATT) {
- /* Clear Chip error bit */
- writel(HA_ERATT, phba->HAregaddr);
- phba->stopped = 1;
- }
-
- mbox = 0;
- ((MAILBOX_t *)&mbox)->mbxCommand = MBX_KILL_BOARD;
- ((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP;
-
- writel(BARRIER_TEST_PATTERN, (resp_buf + 1));
- mbox_buf = phba->MBslimaddr;
- writel(mbox, mbox_buf);
-
- for (i = 0;
- readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++)
- mdelay(1);
-
- if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
- if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
- phba->stopped)
- goto restore_hc;
- else
- goto clear_errat;
- }
-
- ((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
- for (i = 0; readl(resp_buf) != mbox && i < 500; i++)
- mdelay(1);
-
-clear_errat:
-
- while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500)
- mdelay(1);
-
- if (readl(phba->HAregaddr) & HA_ERATT) {
- writel(HA_ERATT, phba->HAregaddr);
- phba->stopped = 1;
- }
-
-restore_hc:
- writel(hc_copy, phba->HCregaddr);
- readl(phba->HCregaddr); /* flush */
-}
-
-int
-lpfc_sli_brdkill(struct lpfc_hba * phba)
+/******************************************************************************
+* lpfc_sli_send_reset
+*
+* Note: After returning from this function, the HBA cannot be accessed for
+* 1 ms. Since we do not wish to delay in interrupt context, it is the
+* responsibility of the caller to perform the mdelay(1) and flush via readl().
+******************************************************************************/
+static int
+lpfc_sli_send_reset(struct lpfc_hba * phba, uint16_t skip_post)
{
- struct lpfc_sli *psli;
- LPFC_MBOXQ_t *pmb;
- uint32_t status;
- uint32_t ha_copy;
- int retval;
- int i = 0;
-
- psli = &phba->sli;
+ MAILBOX_t *swpmb;
+ volatile uint32_t word0;
+ void __iomem *to_slim;
+ unsigned long flags = 0;
- /* Kill HBA */
- lpfc_printf_log(phba,
- KERN_INFO,
- LOG_SLI,
- "%d:0329 Kill HBA Data: x%x x%x\n",
- phba->brd_no,
- phba->hba_state,
- psli->sli_flag);
+ spin_lock_irqsave(phba->host->host_lock, flags);
- if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
- GFP_KERNEL)) == 0)
- return 1;
+ /* A board reset must use REAL SLIM. */
+ phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
- /* Disable the error attention */
- spin_lock_irq(phba->host->host_lock);
- status = readl(phba->HCregaddr);
- status &= ~HC_ERINT_ENA;
- writel(status, phba->HCregaddr);
- readl(phba->HCregaddr); /* flush */
- spin_unlock_irq(phba->host->host_lock);
+ word0 = 0;
+ swpmb = (MAILBOX_t *) & word0;
+ swpmb->mbxCommand = MBX_RESTART;
+ swpmb->mbxHc = 1;
- lpfc_kill_board(phba, pmb);
- pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
- retval = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+ to_slim = phba->MBslimaddr;
+ writel(*(uint32_t *) swpmb, to_slim);
+ readl(to_slim); /* flush */
- if (retval != MBX_SUCCESS) {
- if (retval != MBX_BUSY)
- mempool_free(pmb, phba->mbox_mem_pool);
- return 1;
+ /* Only skip post after fc_ffinit is completed */
+ if (skip_post) {
+ word0 = 1; /* This is really setting up word1 */
+ } else {
+ word0 = 0; /* This is really setting up word1 */
}
+ to_slim = phba->MBslimaddr + sizeof (uint32_t);
+ writel(*(uint32_t *) swpmb, to_slim);
+ readl(to_slim); /* flush */
- psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-
- mempool_free(pmb, phba->mbox_mem_pool);
-
- /* There is no completion for a KILL_BOARD mbox cmd. Check for an error
- * attention every 100ms for 3 seconds. If we don't get ERATT after
- * 3 seconds we still set HBA_ERROR state because the status of the
- * board is now undefined.
- */
- ha_copy = readl(phba->HAregaddr);
-
- while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
- mdelay(100);
- ha_copy = readl(phba->HAregaddr);
- }
+ /* Turn off parity checking and serr during the physical reset */
+ pci_read_config_word(phba->pcidev, PCI_COMMAND, &phba->pci_cfg_value);
+ pci_write_config_word(phba->pcidev, PCI_COMMAND,
+ (phba->pci_cfg_value &
+ ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
- del_timer_sync(&psli->mbox_tmo);
- if (ha_copy & HA_ERATT) {
- writel(HA_ERATT, phba->HAregaddr);
- phba->stopped = 1;
- }
- spin_lock_irq(phba->host->host_lock);
- psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
- spin_unlock_irq(phba->host->host_lock);
+ writel(HC_INITFF, phba->HCregaddr);
- psli->mbox_active = NULL;
- lpfc_hba_down_post(phba);
- phba->hba_state = LPFC_HBA_ERROR;
+ phba->hba_state = LPFC_INIT_START;
+ spin_unlock_irqrestore(phba->host->host_lock, flags);
- return (ha_copy & HA_ERATT ? 0 : 1);
+ return 0;
}
-int
-lpfc_sli_brdreset(struct lpfc_hba * phba)
+static int
+lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
{
- struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
- uint16_t cfg_value;
int i;
+ struct lpfc_dmabuf *mp, *next_mp;
+ unsigned long flags = 0;
- psli = &phba->sli;
-
- /* Reset HBA */
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "%d:0325 Reset HBA Data: x%x x%x\n", phba->brd_no,
- phba->hba_state, psli->sli_flag);
-
- /* perform board reset */
- phba->fc_eventTag = 0;
- phba->fc_myDID = 0;
- phba->fc_prevDID = 0;
-
- /* Turn off parity checking and serr during the physical reset */
- pci_read_config_word(phba->pcidev, PCI_COMMAND, &cfg_value);
- pci_write_config_word(phba->pcidev, PCI_COMMAND,
- (cfg_value &
- ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
-
- psli->sli_flag &= ~(LPFC_SLI2_ACTIVE | LPFC_PROCESS_LA);
- /* Now toggle INITFF bit in the Host Control Register */
- writel(HC_INITFF, phba->HCregaddr);
+ lpfc_sli_send_reset(phba, skip_post);
mdelay(1);
+
+ spin_lock_irqsave(phba->host->host_lock, flags);
+ /* Risk the write on flush case ie no delay after the readl */
readl(phba->HCregaddr); /* flush */
+ /* Now toggle INITFF bit set by lpfc_sli_send_reset */
writel(0, phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
/* Restore PCI cmd register */
- pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
+ pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->pci_cfg_value);
+
+ /* perform board reset */
+ phba->fc_eventTag = 0;
+ phba->fc_myDID = 0;
+ phba->fc_prevDID = Mask_DID;
+
+ /* Reset HBA */
+ lpfc_printf_log(phba,
+ KERN_INFO,
+ LOG_SLI,
+ "%d:0325 Reset HBA Data: x%x x%x x%x\n",
+ phba->brd_no,
+ phba->hba_state,
+ phba->sli.sli_flag,
+ skip_post);
/* Initialize relevant SLI info */
- for (i = 0; i < psli->num_rings; i++) {
- pring = &psli->ring[i];
+ for (i = 0; i < phba->sli.num_rings; i++) {
+ pring = &phba->sli.ring[i];
pring->flag = 0;
pring->rspidx = 0;
pring->next_cmdidx = 0;
pring->cmdidx = 0;
pring->missbufcnt = 0;
}
+ spin_unlock_irqrestore(phba->host->host_lock, flags);
- phba->hba_state = LPFC_WARM_START;
- return 0;
-}
-
-int
-lpfc_sli_brdrestart(struct lpfc_hba * phba)
-{
- MAILBOX_t *mb;
- struct lpfc_sli *psli;
- uint16_t skip_post;
- volatile uint32_t word0;
- void __iomem *to_slim;
-
- spin_lock_irq(phba->host->host_lock);
-
- psli = &phba->sli;
-
- /* Restart HBA */
- lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
- "%d:0337 Restart HBA Data: x%x x%x\n", phba->brd_no,
- phba->hba_state, psli->sli_flag);
-
- word0 = 0;
- mb = (MAILBOX_t *) &word0;
- mb->mbxCommand = MBX_RESTART;
- mb->mbxHc = 1;
-
- lpfc_reset_barrier(phba);
-
- to_slim = phba->MBslimaddr;
- writel(*(uint32_t *) mb, to_slim);
- readl(to_slim); /* flush */
-
- /* Only skip post after fc_ffinit is completed */
- if (phba->hba_state) {
- skip_post = 1;
- word0 = 1; /* This is really setting up word1 */
+ if (skip_post) {
+ mdelay(100);
} else {
- skip_post = 0;
- word0 = 0; /* This is really setting up word1 */
+ mdelay(2000);
}
- to_slim = phba->MBslimaddr + sizeof (uint32_t);
- writel(*(uint32_t *) mb, to_slim);
- readl(to_slim); /* flush */
-
- lpfc_sli_brdreset(phba);
- phba->stopped = 0;
- phba->hba_state = LPFC_INIT_START;
-
- spin_unlock_irq(phba->host->host_lock);
-
- memset(&psli->lnk_stat_offsets, 0, sizeof(psli->lnk_stat_offsets));
- psli->stats_start = get_seconds();
- if (skip_post)
- mdelay(100);
- else
- mdelay(2000);
+ spin_lock_irqsave(phba->host->host_lock, flags);
+ /* Cleanup preposted buffers on the ELS ring */
+ pring = &phba->sli.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_irqrestore(phba->host->host_lock, flags);
- lpfc_hba_down_post(phba);
+ for (i = 0; i < phba->sli.num_rings; i++)
+ lpfc_sli_abort_iocb_ring(phba, &phba->sli.ring[i]);
return 0;
}
}
if (i == 15) {
- phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
- lpfc_sli_brdrestart(phba);
+ lpfc_sli_brdreset(phba, 0);
}
/* Read the HBA Host Status Register */
status = readl(phba->HSregaddr);
}
while (resetcount < 2 && !done) {
- spin_lock_irq(phba->host->host_lock);
- phba->sli.sli_flag |= LPFC_SLI_MBOX_ACTIVE;
- spin_unlock_irq(phba->host->host_lock);
- phba->hba_state = LPFC_STATE_UNKNOWN;
- lpfc_sli_brdrestart(phba);
+ phba->hba_state = 0;
+ lpfc_sli_brdreset(phba, 0);
msleep(2500);
rc = lpfc_sli_chipset_init(phba);
if (rc)
break;
- spin_lock_irq(phba->host->host_lock);
- phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
- spin_unlock_irq(phba->host->host_lock);
resetcount++;
/* Call pre CONFIG_PORT mailbox command initialization. A value of 0
mb = &pmbox->mb;
status = MBX_SUCCESS;
- if (phba->hba_state == LPFC_HBA_ERROR) {
- spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
-
- /* Mbox command <mbxCommand> cannot issue */
- LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
- return (MBX_NOT_FINISHED);
- }
-
- if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
- !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
- spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
- LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
- return (MBX_NOT_FINISHED);
- }
-
if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
/* Polling for a mbox command when another one is already active
* is not allowed in SLI. Also, the driver must have established
/* If we are not polling, we MUST be in SLI2 mode */
if (flag != MBX_POLL) {
- if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
- (mb->mbxCommand != MBX_KILL_BOARD)) {
+ if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
return (MBX_NOT_FINISHED);
}
/* timeout active mbox command */
- mod_timer(&psli->mbox_tmo, (jiffies +
- (HZ * lpfc_mbox_tmo_val(phba, mb->mbxCommand))));
+ mod_timer(&psli->mbox_tmo, jiffies + HZ * LPFC_MBOX_TMO);
}
/* Mailbox cmd <cmd> issue */
break;
case MBX_POLL:
+ i = 0;
psli->mbox_active = NULL;
if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
/* First read mbox status word */
/* Read the HBA Host Attention Register */
ha_copy = readl(phba->HAregaddr);
- i = lpfc_mbox_tmo_val(phba, mb->mbxCommand);
- i *= 1000; /* Convert to ms */
-
/* Wait for command to complete */
- while (((word0 & OWN_CHIP) == OWN_CHIP) ||
- (!(ha_copy & HA_MBATT) &&
- (phba->hba_state > LPFC_WARM_START))) {
- if (i-- <= 0) {
+ while (((word0 & OWN_CHIP) == OWN_CHIP)
+ || !(ha_copy & HA_MBATT)) {
+ if (i++ >= 100) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
/* Can be in interrupt context, do not sleep */
/* (or might be called with interrupts disabled) */
- mdelay(1);
+ mdelay(i);
spin_lock_irqsave(phba->host->host_lock, drvr_flag);
!(phba->sli.sli_flag & LPFC_PROCESS_LA)))
goto iocb_busy;
+ /*
+ * Check to see if this is a high priority command.
+ * If so bypass tx queue processing.
+ */
+ if (unlikely((flag & SLI_IOCB_HIGH_PRIORITY) &&
+ (iocb = lpfc_sli_next_iocb_slot(phba, pring)))) {
+ lpfc_sli_submit_iocb(phba, pring, iocb, piocb);
+ piocb = NULL;
+ }
+
while ((iocb = lpfc_sli_next_iocb_slot(phba, pring)) &&
(nextiocb = lpfc_sli_next_iocb(phba, pring, &piocb)))
lpfc_sli_submit_iocb(phba, pring, iocb, nextiocb);
return IOCB_BUSY;
}
-static int
-lpfc_extra_ring_setup( struct lpfc_hba *phba)
-{
- struct lpfc_sli *psli;
- struct lpfc_sli_ring *pring;
-
- psli = &phba->sli;
-
- /* Adjust cmd/rsp ring iocb entries more evenly */
- pring = &psli->ring[psli->fcp_ring];
- pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES;
- pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES;
- pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES;
- pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES;
-
- pring = &psli->ring[1];
- pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES;
- pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
- pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
- pring->numRiocb += SLI2_IOCB_RSP_R3XTRA_ENTRIES;
-
- /* Setup default profile for this ring */
- pring->iotag_max = 4096;
- pring->num_mask = 1;
- pring->prt[0].profile = 0; /* Mask 0 */
- pring->prt[0].rctl = FC_UNSOL_DATA;
- pring->prt[0].type = 5;
- pring->prt[0].lpfc_sli_rcv_unsol_event = NULL;
- return 0;
-}
-
int
lpfc_sli_setup(struct lpfc_hba *phba)
{
"SLI2 SLIM Data: x%x x%x\n",
phba->brd_no, totiocb, MAX_SLI2_IOCB);
}
- if (phba->cfg_multi_ring_support == 2)
- lpfc_extra_ring_setup(phba);
return 0;
}
INIT_LIST_HEAD(&(pring->txq));
+ kfree(pring->fast_lookup);
+ pring->fast_lookup = NULL;
}
spin_unlock_irqrestore(phba->host->host_lock, flags);
spin_unlock_irqrestore(phba->host->host_lock, flags);
+ /*
+ * Provided the hba is not in an error state, reset it. It is not
+ * capable of IO anymore.
+ */
+ if (phba->hba_state != LPFC_HBA_ERROR) {
+ phba->hba_state = LPFC_INIT_START;
+ lpfc_sli_brdreset(phba, 1);
+ }
+
return 1;
}
if (timeleft == 0) {
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
- "%d:0338 IOCB wait timeout error - no "
+ "%d:0329 IOCB wait timeout error - no "
"wake response Data x%x\n",
phba->brd_no, timeout);
retval = IOCB_TIMEDOUT;
pmboxq->context1 = NULL;
/* if schedule_timeout returns 0, we timed out and were not
woken up */
- if ((timeleft == 0) || signal_pending(current))
+ if (timeleft == 0) {
retval = MBX_TIMEOUT;
- else
+ } else {
retval = MBX_SUCCESS;
+ }
}
return retval;
}
-int
-lpfc_sli_flush_mbox_queue(struct lpfc_hba * phba)
-{
- int i = 0;
-
- while (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE && !phba->stopped) {
- if (i++ > LPFC_MBOX_TMO * 1000)
- return 1;
-
- if (lpfc_sli_handle_mb_event(phba) == 0)
- i = 0;
-
- msleep(1);
- }
-
- return (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE) ? 1 : 0;
-}
-
irqreturn_t
lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
{
/* Clear Chip error bit */
writel(HA_ERATT, phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
- phba->stopped = 1;
+
+ /*
+ * Reseting the HBA is the only reliable way
+ * to shutdown interrupt when there is a
+ * ERROR.
+ */
+ lpfc_sli_send_reset(phba, phba->hba_state);
}
spin_lock(phba->host->host_lock);