aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/lpfc/lpfc_sli.c
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 /drivers/scsi/lpfc/lpfc_sli.c
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>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c99
1 files changed, 93 insertions, 6 deletions
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);