aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2006-03-07 15:04:13 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-03-12 09:56:58 -0500
commit9290831f00879d4a66d3bffb609949d5ea5576fb (patch)
treef66748c875962518f9d4784fd684e189feb50d84
parent1a169689c2152ea599c94d622204f7bf5b7dc09f (diff)
[SCSI] lpfc 8.1.4 : Introduce lpfc_reset_barrier() function for resets on dual channel adapters
Introduce lpfc_reset_barrier() function for resets on dual channel adapters Workaround for a hardware errata on dual channel asics. There is a potential for the chip to lock up on a reset if a shared dma engine is in use. The (ugly) work around requires a reset process which uses a mailbox command to synchronize the independent channels prior to the reset to avoid the issue. Unfortunately, the timing windows required to ensure this workaround succeeds are very specific, meaning we can't release the cpu during the barrier. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_crtn.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c99
5 files changed, 100 insertions, 9 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 2f67a8a92599..087c44539a16 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -197,6 +197,7 @@ struct lpfc_hba {
197#define LPFC_HBA_READY 32 197#define LPFC_HBA_READY 32
198#define LPFC_HBA_ERROR -1 198#define LPFC_HBA_ERROR -1
199 199
200 int32_t stopped; /* HBA has not been restarted since last ERATT */
200 uint8_t fc_linkspeed; /* Link speed after last READ_LA */ 201 uint8_t fc_linkspeed; /* Link speed after last READ_LA */
201 202
202 uint32_t fc_eventTag; /* event tag for link attention */ 203 uint32_t fc_eventTag; /* event tag for link attention */
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h
index f716c1d85f41..fad607b2e6f4 100644
--- a/drivers/scsi/lpfc/lpfc_crtn.h
+++ b/drivers/scsi/lpfc/lpfc_crtn.h
@@ -139,6 +139,7 @@ struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
139void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); 139void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
140uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); 140uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb);
141 141
142void lpfc_reset_barrier(struct lpfc_hba * phba);
142int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); 143int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
143int lpfc_sli_brdkill(struct lpfc_hba *); 144int lpfc_sli_brdkill(struct lpfc_hba *);
144int lpfc_sli_brdreset(struct lpfc_hba *); 145int lpfc_sli_brdreset(struct lpfc_hba *);
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 82704148d5d4..f54089fe4732 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -155,6 +155,7 @@ lpfc_work_list_done(struct lpfc_hba * phba)
155 case LPFC_EVT_WARM_START: 155 case LPFC_EVT_WARM_START:
156 if (phba->hba_state >= LPFC_LINK_DOWN) 156 if (phba->hba_state >= LPFC_LINK_DOWN)
157 lpfc_offline(phba); 157 lpfc_offline(phba);
158 lpfc_reset_barrier(phba);
158 lpfc_sli_brdreset(phba); 159 lpfc_sli_brdreset(phba);
159 lpfc_hba_down_post(phba); 160 lpfc_hba_down_post(phba);
160 *(int *)(evtp->evt_arg1) = 161 *(int *)(evtp->evt_arg1) =
@@ -164,7 +165,8 @@ lpfc_work_list_done(struct lpfc_hba * phba)
164 case LPFC_EVT_KILL: 165 case LPFC_EVT_KILL:
165 if (phba->hba_state >= LPFC_LINK_DOWN) 166 if (phba->hba_state >= LPFC_LINK_DOWN)
166 lpfc_offline(phba); 167 lpfc_offline(phba);
167 *(int *)(evtp->evt_arg1) = lpfc_sli_brdkill(phba); 168 *(int *)(evtp->evt_arg1)
169 = (phba->stopped) ? 0 : lpfc_sli_brdkill(phba);
168 complete((struct completion *)(evtp->evt_arg2)); 170 complete((struct completion *)(evtp->evt_arg2));
169 break; 171 break;
170 } 172 }
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index a2e15436730e..66d5d003555d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -464,8 +464,6 @@ lpfc_hba_down_prep(struct lpfc_hba * phba)
464 lpfc_els_flush_cmd(phba); 464 lpfc_els_flush_cmd(phba);
465 lpfc_disc_flush_list(phba); 465 lpfc_disc_flush_list(phba);
466 466
467 /* Disable SLI2 since we disabled interrupts */
468 phba->sli.sli_flag &= ~LPFC_SLI2_ACTIVE;
469 return (0); 467 return (0);
470} 468}
471 469
@@ -526,6 +524,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
526 phba->work_status[0], phba->work_status[1]); 524 phba->work_status[0], phba->work_status[1]);
527 spin_lock_irq(phba->host->host_lock); 525 spin_lock_irq(phba->host->host_lock);
528 phba->fc_flag |= FC_ESTABLISH_LINK; 526 phba->fc_flag |= FC_ESTABLISH_LINK;
527 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
529 spin_unlock_irq(phba->host->host_lock); 528 spin_unlock_irq(phba->host->host_lock);
530 529
531 /* 530 /*
@@ -559,6 +558,7 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
559 phba->brd_no, phba->work_hs, 558 phba->brd_no, phba->work_hs,
560 phba->work_status[0], phba->work_status[1]); 559 phba->work_status[0], phba->work_status[1]);
561 560
561 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
562 lpfc_offline(phba); 562 lpfc_offline(phba);
563 phba->hba_state = LPFC_HBA_ERROR; 563 phba->hba_state = LPFC_HBA_ERROR;
564 lpfc_hba_down_post(phba); 564 lpfc_hba_down_post(phba);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 764aadbec71b..bb69a7a1ec59 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -1566,6 +1566,79 @@ lpfc_sli_brdready(struct lpfc_hba * phba, uint32_t mask)
1566 return retval; 1566 return retval;
1567} 1567}
1568 1568
1569#define BARRIER_TEST_PATTERN (0xdeadbeef)
1570
1571void lpfc_reset_barrier(struct lpfc_hba * phba)
1572{
1573 uint32_t * resp_buf;
1574 uint32_t * mbox_buf;
1575 volatile uint32_t mbox;
1576 uint32_t hc_copy;
1577 int i;
1578 uint8_t hdrtype;
1579
1580 pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
1581 if (hdrtype != 0x80 ||
1582 (FC_JEDEC_ID(phba->vpd.rev.biuRev) != HELIOS_JEDEC_ID &&
1583 FC_JEDEC_ID(phba->vpd.rev.biuRev) != THOR_JEDEC_ID))
1584 return;
1585
1586 /*
1587 * Tell the other part of the chip to suspend temporarily all
1588 * its DMA activity.
1589 */
1590 resp_buf = (uint32_t *)phba->MBslimaddr;
1591
1592 /* Disable the error attention */
1593 hc_copy = readl(phba->HCregaddr);
1594 writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
1595 readl(phba->HCregaddr); /* flush */
1596
1597 if (readl(phba->HAregaddr) & HA_ERATT) {
1598 /* Clear Chip error bit */
1599 writel(HA_ERATT, phba->HAregaddr);
1600 phba->stopped = 1;
1601 }
1602
1603 mbox = 0;
1604 ((MAILBOX_t *)&mbox)->mbxCommand = MBX_KILL_BOARD;
1605 ((MAILBOX_t *)&mbox)->mbxOwner = OWN_CHIP;
1606
1607 writel(BARRIER_TEST_PATTERN, (resp_buf + 1));
1608 mbox_buf = (uint32_t *)phba->MBslimaddr;
1609 writel(mbox, mbox_buf);
1610
1611 for (i = 0;
1612 readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++)
1613 mdelay(1);
1614
1615 if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
1616 if (phba->sli.sli_flag & LPFC_SLI2_ACTIVE ||
1617 phba->stopped)
1618 goto restore_hc;
1619 else
1620 goto clear_errat;
1621 }
1622
1623 ((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
1624 for (i = 0; readl(resp_buf) != mbox && i < 500; i++)
1625 mdelay(1);
1626
1627clear_errat:
1628
1629 while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500)
1630 mdelay(1);
1631
1632 if (readl(phba->HAregaddr) & HA_ERATT) {
1633 writel(HA_ERATT, phba->HAregaddr);
1634 phba->stopped = 1;
1635 }
1636
1637restore_hc:
1638 writel(hc_copy, phba->HCregaddr);
1639 readl(phba->HCregaddr); /* flush */
1640}
1641
1569int 1642int
1570lpfc_sli_brdkill(struct lpfc_hba * phba) 1643lpfc_sli_brdkill(struct lpfc_hba * phba)
1571{ 1644{
@@ -1588,9 +1661,8 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
1588 psli->sli_flag); 1661 psli->sli_flag);
1589 1662
1590 if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, 1663 if ((pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool,
1591 GFP_ATOMIC)) == 0) { 1664 GFP_KERNEL)) == 0)
1592 return 1; 1665 return 1;
1593 }
1594 1666
1595 /* Disable the error attention */ 1667 /* Disable the error attention */
1596 spin_lock_irq(phba->host->host_lock); 1668 spin_lock_irq(phba->host->host_lock);
@@ -1610,6 +1682,8 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
1610 return 1; 1682 return 1;
1611 } 1683 }
1612 1684
1685 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
1686
1613 mempool_free(pmb, phba->mbox_mem_pool); 1687 mempool_free(pmb, phba->mbox_mem_pool);
1614 1688
1615 /* There is no completion for a KILL_BOARD mbox cmd. Check for an error 1689 /* There is no completion for a KILL_BOARD mbox cmd. Check for an error
@@ -1625,7 +1699,10 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
1625 } 1699 }
1626 1700
1627 del_timer_sync(&psli->mbox_tmo); 1701 del_timer_sync(&psli->mbox_tmo);
1628 1702 if (ha_copy & HA_ERATT) {
1703 writel(HA_ERATT, phba->HAregaddr);
1704 phba->stopped = 1;
1705 }
1629 spin_lock_irq(phba->host->host_lock); 1706 spin_lock_irq(phba->host->host_lock);
1630 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; 1707 psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
1631 spin_unlock_irq(phba->host->host_lock); 1708 spin_unlock_irq(phba->host->host_lock);
@@ -1665,6 +1742,7 @@ lpfc_sli_brdreset(struct lpfc_hba * phba)
1665 (cfg_value & 1742 (cfg_value &
1666 ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR))); 1743 ~(PCI_COMMAND_PARITY | PCI_COMMAND_SERR)));
1667 1744
1745 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
1668 /* Now toggle INITFF bit in the Host Control Register */ 1746 /* Now toggle INITFF bit in the Host Control Register */
1669 writel(HC_INITFF, phba->HCregaddr); 1747 writel(HC_INITFF, phba->HCregaddr);
1670 mdelay(1); 1748 mdelay(1);
@@ -1713,6 +1791,8 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
1713 mb->mbxCommand = MBX_RESTART; 1791 mb->mbxCommand = MBX_RESTART;
1714 mb->mbxHc = 1; 1792 mb->mbxHc = 1;
1715 1793
1794 lpfc_reset_barrier(phba);
1795
1716 to_slim = phba->MBslimaddr; 1796 to_slim = phba->MBslimaddr;
1717 writel(*(uint32_t *) mb, to_slim); 1797 writel(*(uint32_t *) mb, to_slim);
1718 readl(to_slim); /* flush */ 1798 readl(to_slim); /* flush */
@@ -1730,7 +1810,7 @@ lpfc_sli_brdrestart(struct lpfc_hba * phba)
1730 readl(to_slim); /* flush */ 1810 readl(to_slim); /* flush */
1731 1811
1732 lpfc_sli_brdreset(phba); 1812 lpfc_sli_brdreset(phba);
1733 1813 phba->stopped = 0;
1734 phba->hba_state = LPFC_INIT_START; 1814 phba->hba_state = LPFC_INIT_START;
1735 1815
1736 spin_unlock_irq(phba->host->host_lock); 1816 spin_unlock_irq(phba->host->host_lock);
@@ -2038,6 +2118,13 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
2038 return (MBX_NOT_FINISHED); 2118 return (MBX_NOT_FINISHED);
2039 } 2119 }
2040 2120
2121 if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
2122 !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
2123 spin_unlock_irqrestore(phba->host->host_lock, drvr_flag);
2124 LOG_MBOX_CANNOT_ISSUE_DATA( phba, mb, psli, flag)
2125 return (MBX_NOT_FINISHED);
2126 }
2127
2041 if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) { 2128 if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
2042 /* Polling for a mbox command when another one is already active 2129 /* Polling for a mbox command when another one is already active
2043 * is not allowed in SLI. Also, the driver must have established 2130 * is not allowed in SLI. Also, the driver must have established
@@ -2154,8 +2241,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
2154 /* First copy command data to host SLIM area */ 2241 /* First copy command data to host SLIM area */
2155 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE); 2242 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, MAILBOX_CMD_SIZE);
2156 } else { 2243 } else {
2157 if (mb->mbxCommand == MBX_CONFIG_PORT || 2244 if (mb->mbxCommand == MBX_CONFIG_PORT) {
2158 mb->mbxCommand == MBX_KILL_BOARD) {
2159 /* copy command data into host mbox for cmpl */ 2245 /* copy command data into host mbox for cmpl */
2160 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx, 2246 lpfc_sli_pcimem_bcopy(mb, &phba->slim2p->mbx,
2161 MAILBOX_CMD_SIZE); 2247 MAILBOX_CMD_SIZE);
@@ -3121,6 +3207,7 @@ lpfc_intr_handler(int irq, void *dev_id, struct pt_regs * regs)
3121 /* Clear Chip error bit */ 3207 /* Clear Chip error bit */
3122 writel(HA_ERATT, phba->HAregaddr); 3208 writel(HA_ERATT, phba->HAregaddr);
3123 readl(phba->HAregaddr); /* flush */ 3209 readl(phba->HAregaddr); /* flush */
3210 phba->stopped = 1;
3124 } 3211 }
3125 3212
3126 spin_lock(phba->host->host_lock); 3213 spin_lock(phba->host->host_lock);