diff options
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_crtn.h | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 99 |
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 *); | |||
139 | void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); | 139 | void lpfc_sli_release_iocbq(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); |
140 | uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); | 140 | uint16_t lpfc_sli_next_iotag(struct lpfc_hba * phba, struct lpfc_iocbq * iocb); |
141 | 141 | ||
142 | void lpfc_reset_barrier(struct lpfc_hba * phba); | ||
142 | int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); | 143 | int lpfc_sli_brdready(struct lpfc_hba *, uint32_t); |
143 | int lpfc_sli_brdkill(struct lpfc_hba *); | 144 | int lpfc_sli_brdkill(struct lpfc_hba *); |
144 | int lpfc_sli_brdreset(struct lpfc_hba *); | 145 | int 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 | |||
1571 | void 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 | |||
1627 | clear_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 | |||
1637 | restore_hc: | ||
1638 | writel(hc_copy, phba->HCregaddr); | ||
1639 | readl(phba->HCregaddr); /* flush */ | ||
1640 | } | ||
1641 | |||
1569 | int | 1642 | int |
1570 | lpfc_sli_brdkill(struct lpfc_hba * phba) | 1643 | lpfc_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); |