summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-22 19:47:24 +0100
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-22 19:47:24 +0100
commit2152f8536668a957ea3214735b4761e7b22ef7d8 (patch)
tree56723fc51445b1bc930c6400d4c00fd6fc831f88 /drivers/scsi/lpfc/lpfc_sli.c
parent[PATCH] SELinux: add slab cache for inode security struct (diff)
parent[SCSI] libata: implement minimal transport template for ->eh_timed_out (diff)
downloadlinux-2152f8536668a957ea3214735b4761e7b22ef7d8.tar.xz
linux-2152f8536668a957ea3214735b4761e7b22ef7d8.zip
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (138 commits) [SCSI] libata: implement minimal transport template for ->eh_timed_out [SCSI] eliminate rphy allocation in favour of expander/end device allocation [SCSI] convert mptsas over to end_device/expander allocations [SCSI] allow displaying and setting of cache type via sysfs [SCSI] add scsi_mode_select to scsi_lib.c [SCSI] 3ware 9000 add big endian support [SCSI] qla2xxx: update MAINTAINERS [SCSI] scsi: move target_destroy call [SCSI] fusion - bump version [SCSI] fusion - expander hotplug suport in mptsas module [SCSI] fusion - exposing raid components in mptsas [SCSI] fusion - memory leak, and initializing fields [SCSI] fusion - exclosure misspelled [SCSI] fusion - cleanup mptsas event handling functions [SCSI] fusion - removing target_id/bus_id from the VirtDevice structure [SCSI] fusion - static fix's [SCSI] fusion - move some debug firmware event debug msgs to verbose level [SCSI] fusion - loginfo header update [SCSI] add scsi_reprobe_device [SCSI] megaraid_sas: fix extended timeout handling ...
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c470
1 files changed, 342 insertions, 128 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 7b785ade8b07..bb69a7a1ec59 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2005 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2006 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
@@ -513,7 +513,9 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand)
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:
@@ -764,7 +766,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
}
/* unSolicited Responses */
if (pring->prt[0].profile) {
- (pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring, saveq);
+ if (pring->prt[0].lpfc_sli_rcv_unsol_event)
+ (pring->prt[0].lpfc_sli_rcv_unsol_event) (phba, pring,
+ saveq);
match = 1;
} else {
/* We must search, based on rctl / type
@@ -775,8 +779,9 @@ lpfc_sli_process_unsol_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
Rctl)
&& (pring->prt[i].
type == Type)) {
- (pring->prt[i].lpfc_sli_rcv_unsol_event)
- (phba, pring, saveq);
+ if (pring->prt[i].lpfc_sli_rcv_unsol_event)
+ (pring->prt[i].lpfc_sli_rcv_unsol_event)
+ (phba, pring, saveq);
match = 1;
break;
}
@@ -1149,12 +1154,17 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
cmdiocbq = lpfc_sli_iocbq_lookup(phba, pring,
&rspiocbq);
if ((cmdiocbq) && (cmdiocbq->iocb_cmpl)) {
- spin_unlock_irqrestore(
- phba->host->host_lock, iflag);
- (cmdiocbq->iocb_cmpl)(phba, cmdiocbq,
- &rspiocbq);
- spin_lock_irqsave(phba->host->host_lock,
- iflag);
+ 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);
+ }
}
break;
default:
@@ -1512,98 +1522,240 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
return errcnt;
}
-/******************************************************************************
-* 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)
+int
+lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
{
- MAILBOX_t *swpmb;
- volatile uint32_t word0;
- void __iomem *to_slim;
- unsigned long flags = 0;
-
- spin_lock_irqsave(phba->host->host_lock, flags);
+ uint32_t status;
+ int i = 0;
+ int retval = 0;
- /* A board reset must use REAL SLIM. */
- phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
+ /* Read the HBA Host Status Register */
+ status = readl(phba->HSregaddr);
- word0 = 0;
- swpmb = (MAILBOX_t *) & word0;
- swpmb->mbxCommand = MBX_RESTART;
- swpmb->mbxHc = 1;
+ /*
+ * 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) {
- to_slim = phba->MBslimaddr;
- writel(*(uint32_t *) swpmb, to_slim);
- readl(to_slim); /* flush */
+ if (i <= 5)
+ msleep(10);
+ else if (i <= 10)
+ msleep(500);
+ else
+ msleep(2500);
- /* 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 */
+ 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);
}
- to_slim = phba->MBslimaddr + sizeof (uint32_t);
- writel(*(uint32_t *) swpmb, to_slim);
- readl(to_slim); /* flush */
-
- /* 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)));
-
- writel(HC_INITFF, phba->HCregaddr);
- phba->hba_state = LPFC_INIT_START;
- spin_unlock_irqrestore(phba->host->host_lock, flags);
+ /* Check to see if any errors occurred during init */
+ if ((status & HS_FFERM) || (i >= 20)) {
+ phba->hba_state = LPFC_HBA_ERROR;
+ retval = 1;
+ }
- return 0;
+ return retval;
}
-static int
-lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
+#define BARRIER_TEST_PATTERN (0xdeadbeef)
+
+void lpfc_reset_barrier(struct lpfc_hba * phba)
{
- struct lpfc_sli_ring *pring;
- int i;
- struct lpfc_dmabuf *mp, *next_mp;
- unsigned long flags = 0;
+ uint32_t * resp_buf;
+ uint32_t * 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;
- lpfc_sli_send_reset(phba, skip_post);
- mdelay(1);
+ /*
+ * Tell the other part of the chip to suspend temporarily all
+ * its DMA activity.
+ */
+ resp_buf = (uint32_t *)phba->MBslimaddr;
- spin_lock_irqsave(phba->host->host_lock, flags);
- /* Risk the write on flush case ie no delay after the readl */
+ /* Disable the error attention */
+ hc_copy = readl(phba->HCregaddr);
+ writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
readl(phba->HCregaddr); /* flush */
- /* Now toggle INITFF bit set by lpfc_sli_send_reset */
- writel(0, phba->HCregaddr);
+
+ 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 = (uint32_t *)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 */
+}
- /* Restore PCI cmd register */
- pci_write_config_word(phba->pcidev, PCI_COMMAND, phba->pci_cfg_value);
+int
+lpfc_sli_brdkill(struct lpfc_hba * phba)
+{
+ struct lpfc_sli *psli;
+ LPFC_MBOXQ_t *pmb;
+ uint32_t status;
+ uint32_t ha_copy;
+ int retval;
+ int i = 0;
- /* perform board reset */
- phba->fc_eventTag = 0;
- phba->fc_myDID = 0;
- phba->fc_prevDID = Mask_DID;
+ psli = &phba->sli;
- /* Reset HBA */
+ /* Kill HBA */
lpfc_printf_log(phba,
KERN_INFO,
LOG_SLI,
- "%d:0325 Reset HBA Data: x%x x%x x%x\n",
+ "%d:0329 Kill HBA Data: x%x x%x\n",
phba->brd_no,
phba->hba_state,
- phba->sli.sli_flag,
- skip_post);
+ psli->sli_flag);
+
+ if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
+ GFP_KERNEL)) == 0)
+ return 1;
+
+ /* 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);
+
+ lpfc_kill_board(phba, pmb);
+ pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+ retval = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+
+ if (retval != MBX_SUCCESS) {
+ if (retval != MBX_BUSY)
+ mempool_free(pmb, phba->mbox_mem_pool);
+ return 1;
+ }
+
+ 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);
+ }
+
+ 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);
+
+ psli->mbox_active = NULL;
+ lpfc_hba_down_post(phba);
+ phba->hba_state = LPFC_HBA_ERROR;
+
+ return (ha_copy & HA_ERATT ? 0 : 1);
+}
+
+int
+lpfc_sli_brdreset(struct lpfc_hba * phba)
+{
+ struct lpfc_sli *psli;
+ struct lpfc_sli_ring *pring;
+ uint16_t cfg_value;
+ int i;
+
+ 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;
+
+ psli->sli_flag = 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;
+ /* Now toggle INITFF bit in the Host Control Register */
+ writel(HC_INITFF, phba->HCregaddr);
+ mdelay(1);
+ readl(phba->HCregaddr); /* flush */
+ writel(0, phba->HCregaddr);
+ readl(phba->HCregaddr); /* flush */
+
+ /* Restore PCI cmd register */
+ pci_write_config_word(phba->pcidev, PCI_COMMAND, cfg_value);
/* Initialize relevant SLI info */
- for (i = 0; i < phba->sli.num_rings; i++) {
- pring = &phba->sli.ring[i];
+ for (i = 0; i < psli->num_rings; i++) {
+ pring = &psli->ring[i];
pring->flag = 0;
pring->rspidx = 0;
pring->next_cmdidx = 0;
@@ -1611,27 +1763,64 @@ lpfc_sli_brdreset(struct lpfc_hba * phba, uint16_t skip_post)
pring->cmdidx = 0;
pring->missbufcnt = 0;
}
- spin_unlock_irqrestore(phba->host->host_lock, flags);
- if (skip_post) {
- mdelay(100);
+ 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:0328 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 */
} else {
- mdelay(2000);
+ skip_post = 0;
+ word0 = 0; /* This is really setting up word1 */
}
+ to_slim = (uint8_t *) phba->MBslimaddr + sizeof (uint32_t);
+ writel(*(uint32_t *) mb, to_slim);
+ readl(to_slim); /* flush */
- 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_sli_brdreset(phba);
+ phba->stopped = 0;
+ phba->hba_state = LPFC_INIT_START;
+
+ spin_unlock_irq(phba->host->host_lock);
+
+ if (skip_post)
+ mdelay(100);
+ else
+ mdelay(2000);
- for (i = 0; i < phba->sli.num_rings; i++)
- lpfc_sli_abort_iocb_ring(phba, &phba->sli.ring[i]);
+ lpfc_hba_down_post(phba);
return 0;
}
@@ -1691,7 +1880,8 @@ lpfc_sli_chipset_init(struct lpfc_hba *phba)
}
if (i == 15) {
- lpfc_sli_brdreset(phba, 0);
+ phba->hba_state = LPFC_STATE_UNKNOWN; /* Do post */
+ lpfc_sli_brdrestart(phba);
}
/* Read the HBA Host Status Register */
status = readl(phba->HSregaddr);
@@ -1735,8 +1925,8 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
}
while (resetcount < 2 && !done) {
- phba->hba_state = 0;
- lpfc_sli_brdreset(phba, 0);
+ phba->hba_state = LPFC_STATE_UNKNOWN;
+ lpfc_sli_brdrestart(phba);
msleep(2500);
rc = lpfc_sli_chipset_init(phba);
if (rc)
@@ -1920,6 +2110,21 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
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
@@ -2002,7 +2207,8 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
/* If we are not polling, we MUST be in SLI2 mode */
if (flag != MBX_POLL) {
- if (!(psli->sli_flag & LPFC_SLI2_ACTIVE)) {
+ if (!(psli->sli_flag & LPFC_SLI2_ACTIVE) &&
+ (mb->mbxCommand != MBX_KILL_BOARD)) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock,
drvr_flag);
@@ -2086,8 +2292,9 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
ha_copy = readl(phba->HAregaddr);
/* Wait for command to complete */
- while (((word0 & OWN_CHIP) == OWN_CHIP)
- || !(ha_copy & HA_MBATT)) {
+ while (((word0 & OWN_CHIP) == OWN_CHIP) ||
+ (!(ha_copy & HA_MBATT) &&
+ (phba->hba_state > LPFC_WARM_START))) {
if (i++ >= 100) {
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
spin_unlock_irqrestore(phba->host->host_lock,
@@ -2237,16 +2444,6 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
!(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);
@@ -2274,6 +2471,37 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
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)
{
@@ -2357,6 +2585,8 @@ 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;
}
@@ -2465,15 +2695,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
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;
}
@@ -2877,11 +3098,10 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
pmboxq->context1 = NULL;
/* if schedule_timeout returns 0, we timed out and were not
woken up */
- if (timeleft == 0) {
+ if ((timeleft == 0) || signal_pending(current))
retval = MBX_TIMEOUT;
- } else {
+ else
retval = MBX_SUCCESS;
- }
}
@@ -2987,13 +3207,7 @@ 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 */
-
- /*
- * Reseting the HBA is the only reliable way
- * to shutdown interrupt when there is a
- * ERROR.
- */
- lpfc_sli_send_reset(phba, phba->hba_state);
+ phba->stopped = 1;
}
spin_lock(phba->host->host_lock);