aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/brocade/bna
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/brocade/bna')
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c618
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.h1
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi.h33
-rw-r--r--drivers/net/ethernet/brocade/bna/cna.h4
4 files changed, 626 insertions, 30 deletions
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index b81132a8ee79..537bba14f913 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -22,6 +22,14 @@
22 22
23/* IOC local definitions */ 23/* IOC local definitions */
24 24
25#define bfa_ioc_state_disabled(__sm) \
26 (((__sm) == BFI_IOC_UNINIT) || \
27 ((__sm) == BFI_IOC_INITING) || \
28 ((__sm) == BFI_IOC_HWINIT) || \
29 ((__sm) == BFI_IOC_DISABLED) || \
30 ((__sm) == BFI_IOC_FAIL) || \
31 ((__sm) == BFI_IOC_CFG_DISABLED))
32
25/* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. */ 33/* Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. */
26 34
27#define bfa_ioc_firmware_lock(__ioc) \ 35#define bfa_ioc_firmware_lock(__ioc) \
@@ -84,8 +92,8 @@ static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc);
84static void bfa_ioc_pf_failed(struct bfa_ioc *ioc); 92static void bfa_ioc_pf_failed(struct bfa_ioc *ioc);
85static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc); 93static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc);
86static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc); 94static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc);
87static void bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type, 95static enum bfa_status bfa_ioc_boot(struct bfa_ioc *ioc,
88 u32 boot_param); 96 enum bfi_fwboot_type boot_type, u32 boot_param);
89static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr); 97static u32 bfa_ioc_smem_pgnum(struct bfa_ioc *ioc, u32 fmaddr);
90static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, 98static void bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc,
91 char *serial_num); 99 char *serial_num);
@@ -1139,6 +1147,25 @@ bfa_nw_ioc_sem_release(void __iomem *sem_reg)
1139 writel(1, sem_reg); 1147 writel(1, sem_reg);
1140} 1148}
1141 1149
1150/* Invalidate fwver signature */
1151enum bfa_status
1152bfa_nw_ioc_fwsig_invalidate(struct bfa_ioc *ioc)
1153{
1154 u32 pgnum, pgoff;
1155 u32 loff = 0;
1156 enum bfi_ioc_state ioc_fwstate;
1157
1158 ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
1159 if (!bfa_ioc_state_disabled(ioc_fwstate))
1160 return BFA_STATUS_ADAPTER_ENABLED;
1161
1162 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
1163 pgoff = PSS_SMEM_PGOFF(loff);
1164 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1165 writel(BFI_IOC_FW_INV_SIGN, ioc->ioc_regs.smem_page_start + loff);
1166 return BFA_STATUS_OK;
1167}
1168
1142/* Clear fwver hdr */ 1169/* Clear fwver hdr */
1143static void 1170static void
1144bfa_ioc_fwver_clear(struct bfa_ioc *ioc) 1171bfa_ioc_fwver_clear(struct bfa_ioc *ioc)
@@ -1317,22 +1344,510 @@ bfa_nw_ioc_fwver_get(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
1317 } 1344 }
1318} 1345}
1319 1346
1320/* Returns TRUE if same. */ 1347static bool
1348bfa_ioc_fwver_md5_check(struct bfi_ioc_image_hdr *fwhdr_1,
1349 struct bfi_ioc_image_hdr *fwhdr_2)
1350{
1351 int i;
1352
1353 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) {
1354 if (fwhdr_1->md5sum[i] != fwhdr_2->md5sum[i])
1355 return false;
1356 }
1357
1358 return true;
1359}
1360
1361/* Returns TRUE if major minor and maintainence are same.
1362 * If patch version are same, check for MD5 Checksum to be same.
1363 */
1364static bool
1365bfa_ioc_fw_ver_compatible(struct bfi_ioc_image_hdr *drv_fwhdr,
1366 struct bfi_ioc_image_hdr *fwhdr_to_cmp)
1367{
1368 if (drv_fwhdr->signature != fwhdr_to_cmp->signature)
1369 return false;
1370 if (drv_fwhdr->fwver.major != fwhdr_to_cmp->fwver.major)
1371 return false;
1372 if (drv_fwhdr->fwver.minor != fwhdr_to_cmp->fwver.minor)
1373 return false;
1374 if (drv_fwhdr->fwver.maint != fwhdr_to_cmp->fwver.maint)
1375 return false;
1376 if (drv_fwhdr->fwver.patch == fwhdr_to_cmp->fwver.patch &&
1377 drv_fwhdr->fwver.phase == fwhdr_to_cmp->fwver.phase &&
1378 drv_fwhdr->fwver.build == fwhdr_to_cmp->fwver.build)
1379 return bfa_ioc_fwver_md5_check(drv_fwhdr, fwhdr_to_cmp);
1380
1381 return true;
1382}
1383
1384static bool
1385bfa_ioc_flash_fwver_valid(struct bfi_ioc_image_hdr *flash_fwhdr)
1386{
1387 if (flash_fwhdr->fwver.major == 0 || flash_fwhdr->fwver.major == 0xFF)
1388 return false;
1389
1390 return true;
1391}
1392
1393static bool
1394fwhdr_is_ga(struct bfi_ioc_image_hdr *fwhdr)
1395{
1396 if (fwhdr->fwver.phase == 0 &&
1397 fwhdr->fwver.build == 0)
1398 return false;
1399
1400 return true;
1401}
1402
1403/* Returns TRUE if both are compatible and patch of fwhdr_to_cmp is better. */
1404static enum bfi_ioc_img_ver_cmp
1405bfa_ioc_fw_ver_patch_cmp(struct bfi_ioc_image_hdr *base_fwhdr,
1406 struct bfi_ioc_image_hdr *fwhdr_to_cmp)
1407{
1408 if (bfa_ioc_fw_ver_compatible(base_fwhdr, fwhdr_to_cmp) == false)
1409 return BFI_IOC_IMG_VER_INCOMP;
1410
1411 if (fwhdr_to_cmp->fwver.patch > base_fwhdr->fwver.patch)
1412 return BFI_IOC_IMG_VER_BETTER;
1413 else if (fwhdr_to_cmp->fwver.patch < base_fwhdr->fwver.patch)
1414 return BFI_IOC_IMG_VER_OLD;
1415
1416 /* GA takes priority over internal builds of the same patch stream.
1417 * At this point major minor maint and patch numbers are same.
1418 */
1419 if (fwhdr_is_ga(base_fwhdr) == true)
1420 if (fwhdr_is_ga(fwhdr_to_cmp))
1421 return BFI_IOC_IMG_VER_SAME;
1422 else
1423 return BFI_IOC_IMG_VER_OLD;
1424 else
1425 if (fwhdr_is_ga(fwhdr_to_cmp))
1426 return BFI_IOC_IMG_VER_BETTER;
1427
1428 if (fwhdr_to_cmp->fwver.phase > base_fwhdr->fwver.phase)
1429 return BFI_IOC_IMG_VER_BETTER;
1430 else if (fwhdr_to_cmp->fwver.phase < base_fwhdr->fwver.phase)
1431 return BFI_IOC_IMG_VER_OLD;
1432
1433 if (fwhdr_to_cmp->fwver.build > base_fwhdr->fwver.build)
1434 return BFI_IOC_IMG_VER_BETTER;
1435 else if (fwhdr_to_cmp->fwver.build < base_fwhdr->fwver.build)
1436 return BFI_IOC_IMG_VER_OLD;
1437
1438 /* All Version Numbers are equal.
1439 * Md5 check to be done as a part of compatibility check.
1440 */
1441 return BFI_IOC_IMG_VER_SAME;
1442}
1443
1444/* register definitions */
1445#define FLI_CMD_REG 0x0001d000
1446#define FLI_WRDATA_REG 0x0001d00c
1447#define FLI_RDDATA_REG 0x0001d010
1448#define FLI_ADDR_REG 0x0001d004
1449#define FLI_DEV_STATUS_REG 0x0001d014
1450
1451#define BFA_FLASH_FIFO_SIZE 128 /* fifo size */
1452#define BFA_FLASH_CHECK_MAX 10000 /* max # of status check */
1453#define BFA_FLASH_BLOCKING_OP_MAX 1000000 /* max # of blocking op check */
1454#define BFA_FLASH_WIP_MASK 0x01 /* write in progress bit mask */
1455
1456#define NFC_STATE_RUNNING 0x20000001
1457#define NFC_STATE_PAUSED 0x00004560
1458#define NFC_VER_VALID 0x147
1459
1460enum bfa_flash_cmd {
1461 BFA_FLASH_FAST_READ = 0x0b, /* fast read */
1462 BFA_FLASH_WRITE_ENABLE = 0x06, /* write enable */
1463 BFA_FLASH_SECTOR_ERASE = 0xd8, /* sector erase */
1464 BFA_FLASH_WRITE = 0x02, /* write */
1465 BFA_FLASH_READ_STATUS = 0x05, /* read status */
1466};
1467
1468/* hardware error definition */
1469enum bfa_flash_err {
1470 BFA_FLASH_NOT_PRESENT = -1, /*!< flash not present */
1471 BFA_FLASH_UNINIT = -2, /*!< flash not initialized */
1472 BFA_FLASH_BAD = -3, /*!< flash bad */
1473 BFA_FLASH_BUSY = -4, /*!< flash busy */
1474 BFA_FLASH_ERR_CMD_ACT = -5, /*!< command active never cleared */
1475 BFA_FLASH_ERR_FIFO_CNT = -6, /*!< fifo count never cleared */
1476 BFA_FLASH_ERR_WIP = -7, /*!< write-in-progress never cleared */
1477 BFA_FLASH_ERR_TIMEOUT = -8, /*!< fli timeout */
1478 BFA_FLASH_ERR_LEN = -9, /*!< invalid length */
1479};
1480
1481/* flash command register data structure */
1482union bfa_flash_cmd_reg {
1483 struct {
1484#ifdef __BIG_ENDIAN
1485 u32 act:1;
1486 u32 rsv:1;
1487 u32 write_cnt:9;
1488 u32 read_cnt:9;
1489 u32 addr_cnt:4;
1490 u32 cmd:8;
1491#else
1492 u32 cmd:8;
1493 u32 addr_cnt:4;
1494 u32 read_cnt:9;
1495 u32 write_cnt:9;
1496 u32 rsv:1;
1497 u32 act:1;
1498#endif
1499 } r;
1500 u32 i;
1501};
1502
1503/* flash device status register data structure */
1504union bfa_flash_dev_status_reg {
1505 struct {
1506#ifdef __BIG_ENDIAN
1507 u32 rsv:21;
1508 u32 fifo_cnt:6;
1509 u32 busy:1;
1510 u32 init_status:1;
1511 u32 present:1;
1512 u32 bad:1;
1513 u32 good:1;
1514#else
1515 u32 good:1;
1516 u32 bad:1;
1517 u32 present:1;
1518 u32 init_status:1;
1519 u32 busy:1;
1520 u32 fifo_cnt:6;
1521 u32 rsv:21;
1522#endif
1523 } r;
1524 u32 i;
1525};
1526
1527/* flash address register data structure */
1528union bfa_flash_addr_reg {
1529 struct {
1530#ifdef __BIG_ENDIAN
1531 u32 addr:24;
1532 u32 dummy:8;
1533#else
1534 u32 dummy:8;
1535 u32 addr:24;
1536#endif
1537 } r;
1538 u32 i;
1539};
1540
1541/* Flash raw private functions */
1542static void
1543bfa_flash_set_cmd(void __iomem *pci_bar, u8 wr_cnt,
1544 u8 rd_cnt, u8 ad_cnt, u8 op)
1545{
1546 union bfa_flash_cmd_reg cmd;
1547
1548 cmd.i = 0;
1549 cmd.r.act = 1;
1550 cmd.r.write_cnt = wr_cnt;
1551 cmd.r.read_cnt = rd_cnt;
1552 cmd.r.addr_cnt = ad_cnt;
1553 cmd.r.cmd = op;
1554 writel(cmd.i, (pci_bar + FLI_CMD_REG));
1555}
1556
1557static void
1558bfa_flash_set_addr(void __iomem *pci_bar, u32 address)
1559{
1560 union bfa_flash_addr_reg addr;
1561
1562 addr.r.addr = address & 0x00ffffff;
1563 addr.r.dummy = 0;
1564 writel(addr.i, (pci_bar + FLI_ADDR_REG));
1565}
1566
1567static int
1568bfa_flash_cmd_act_check(void __iomem *pci_bar)
1569{
1570 union bfa_flash_cmd_reg cmd;
1571
1572 cmd.i = readl(pci_bar + FLI_CMD_REG);
1573
1574 if (cmd.r.act)
1575 return BFA_FLASH_ERR_CMD_ACT;
1576
1577 return 0;
1578}
1579
1580/* Flush FLI data fifo. */
1581static u32
1582bfa_flash_fifo_flush(void __iomem *pci_bar)
1583{
1584 u32 i;
1585 u32 t;
1586 union bfa_flash_dev_status_reg dev_status;
1587
1588 dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
1589
1590 if (!dev_status.r.fifo_cnt)
1591 return 0;
1592
1593 /* fifo counter in terms of words */
1594 for (i = 0; i < dev_status.r.fifo_cnt; i++)
1595 t = readl(pci_bar + FLI_RDDATA_REG);
1596
1597 /* Check the device status. It may take some time. */
1598 for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {
1599 dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
1600 if (!dev_status.r.fifo_cnt)
1601 break;
1602 }
1603
1604 if (dev_status.r.fifo_cnt)
1605 return BFA_FLASH_ERR_FIFO_CNT;
1606
1607 return 0;
1608}
1609
1610/* Read flash status. */
1611static u32
1612bfa_flash_status_read(void __iomem *pci_bar)
1613{
1614 union bfa_flash_dev_status_reg dev_status;
1615 u32 status;
1616 u32 ret_status;
1617 int i;
1618
1619 status = bfa_flash_fifo_flush(pci_bar);
1620 if (status < 0)
1621 return status;
1622
1623 bfa_flash_set_cmd(pci_bar, 0, 4, 0, BFA_FLASH_READ_STATUS);
1624
1625 for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {
1626 status = bfa_flash_cmd_act_check(pci_bar);
1627 if (!status)
1628 break;
1629 }
1630
1631 if (status)
1632 return status;
1633
1634 dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
1635 if (!dev_status.r.fifo_cnt)
1636 return BFA_FLASH_BUSY;
1637
1638 ret_status = readl(pci_bar + FLI_RDDATA_REG);
1639 ret_status >>= 24;
1640
1641 status = bfa_flash_fifo_flush(pci_bar);
1642 if (status < 0)
1643 return status;
1644
1645 return ret_status;
1646}
1647
1648/* Start flash read operation. */
1649static u32
1650bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len,
1651 char *buf)
1652{
1653 u32 status;
1654
1655 /* len must be mutiple of 4 and not exceeding fifo size */
1656 if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0)
1657 return BFA_FLASH_ERR_LEN;
1658
1659 /* check status */
1660 status = bfa_flash_status_read(pci_bar);
1661 if (status == BFA_FLASH_BUSY)
1662 status = bfa_flash_status_read(pci_bar);
1663
1664 if (status < 0)
1665 return status;
1666
1667 /* check if write-in-progress bit is cleared */
1668 if (status & BFA_FLASH_WIP_MASK)
1669 return BFA_FLASH_ERR_WIP;
1670
1671 bfa_flash_set_addr(pci_bar, offset);
1672
1673 bfa_flash_set_cmd(pci_bar, 0, (u8)len, 4, BFA_FLASH_FAST_READ);
1674
1675 return 0;
1676}
1677
1678/* Check flash read operation. */
1679static u32
1680bfa_flash_read_check(void __iomem *pci_bar)
1681{
1682 if (bfa_flash_cmd_act_check(pci_bar))
1683 return 1;
1684
1685 return 0;
1686}
1687
1688/* End flash read operation. */
1689static void
1690bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf)
1691{
1692 u32 i;
1693
1694 /* read data fifo up to 32 words */
1695 for (i = 0; i < len; i += 4) {
1696 u32 w = readl(pci_bar + FLI_RDDATA_REG);
1697 *((u32 *)(buf + i)) = swab32(w);
1698 }
1699
1700 bfa_flash_fifo_flush(pci_bar);
1701}
1702
1703/* Perform flash raw read. */
1704
1705#define FLASH_BLOCKING_OP_MAX 500
1706#define FLASH_SEM_LOCK_REG 0x18820
1707
1708static int
1709bfa_raw_sem_get(void __iomem *bar)
1710{
1711 int locked;
1712
1713 locked = readl((bar + FLASH_SEM_LOCK_REG));
1714
1715 return !locked;
1716}
1717
1718static enum bfa_status
1719bfa_flash_sem_get(void __iomem *bar)
1720{
1721 u32 n = FLASH_BLOCKING_OP_MAX;
1722
1723 while (!bfa_raw_sem_get(bar)) {
1724 if (--n <= 0)
1725 return BFA_STATUS_BADFLASH;
1726 udelay(10000);
1727 }
1728 return BFA_STATUS_OK;
1729}
1730
1731static void
1732bfa_flash_sem_put(void __iomem *bar)
1733{
1734 writel(0, (bar + FLASH_SEM_LOCK_REG));
1735}
1736
1737static enum bfa_status
1738bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf,
1739 u32 len)
1740{
1741 u32 n, status;
1742 u32 off, l, s, residue, fifo_sz;
1743
1744 residue = len;
1745 off = 0;
1746 fifo_sz = BFA_FLASH_FIFO_SIZE;
1747 status = bfa_flash_sem_get(pci_bar);
1748 if (status != BFA_STATUS_OK)
1749 return status;
1750
1751 while (residue) {
1752 s = offset + off;
1753 n = s / fifo_sz;
1754 l = (n + 1) * fifo_sz - s;
1755 if (l > residue)
1756 l = residue;
1757
1758 status = bfa_flash_read_start(pci_bar, offset + off, l,
1759 &buf[off]);
1760 if (status < 0) {
1761 bfa_flash_sem_put(pci_bar);
1762 return BFA_STATUS_FAILED;
1763 }
1764
1765 n = BFA_FLASH_BLOCKING_OP_MAX;
1766 while (bfa_flash_read_check(pci_bar)) {
1767 if (--n <= 0) {
1768 bfa_flash_sem_put(pci_bar);
1769 return BFA_STATUS_FAILED;
1770 }
1771 }
1772
1773 bfa_flash_read_end(pci_bar, l, &buf[off]);
1774
1775 residue -= l;
1776 off += l;
1777 }
1778 bfa_flash_sem_put(pci_bar);
1779
1780 return BFA_STATUS_OK;
1781}
1782
1783u32
1784bfa_nw_ioc_flash_img_get_size(struct bfa_ioc *ioc)
1785{
1786 return BFI_FLASH_IMAGE_SZ/sizeof(u32);
1787}
1788
1789#define BFA_FLASH_PART_FWIMG_ADDR 0x100000 /* fw image address */
1790
1791enum bfa_status
1792bfa_nw_ioc_flash_img_get_chnk(struct bfa_ioc *ioc, u32 off,
1793 u32 *fwimg)
1794{
1795 return bfa_flash_raw_read(ioc->pcidev.pci_bar_kva,
1796 BFA_FLASH_PART_FWIMG_ADDR + (off * sizeof(u32)),
1797 (char *)fwimg, BFI_FLASH_CHUNK_SZ);
1798}
1799
1800static enum bfi_ioc_img_ver_cmp
1801bfa_ioc_flash_fwver_cmp(struct bfa_ioc *ioc,
1802 struct bfi_ioc_image_hdr *base_fwhdr)
1803{
1804 struct bfi_ioc_image_hdr *flash_fwhdr;
1805 enum bfa_status status;
1806 u32 fwimg[BFI_FLASH_CHUNK_SZ_WORDS];
1807
1808 status = bfa_nw_ioc_flash_img_get_chnk(ioc, 0, fwimg);
1809 if (status != BFA_STATUS_OK)
1810 return BFI_IOC_IMG_VER_INCOMP;
1811
1812 flash_fwhdr = (struct bfi_ioc_image_hdr *)fwimg;
1813 if (bfa_ioc_flash_fwver_valid(flash_fwhdr))
1814 return bfa_ioc_fw_ver_patch_cmp(base_fwhdr, flash_fwhdr);
1815 else
1816 return BFI_IOC_IMG_VER_INCOMP;
1817}
1818
1819/**
1820 * Returns TRUE if driver is willing to work with current smem f/w version.
1821 */
1321bool 1822bool
1322bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) 1823bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
1323{ 1824{
1324 struct bfi_ioc_image_hdr *drv_fwhdr; 1825 struct bfi_ioc_image_hdr *drv_fwhdr;
1325 int i; 1826 enum bfi_ioc_img_ver_cmp smem_flash_cmp, drv_smem_cmp;
1326 1827
1327 drv_fwhdr = (struct bfi_ioc_image_hdr *) 1828 drv_fwhdr = (struct bfi_ioc_image_hdr *)
1328 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); 1829 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1329 1830
1330 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { 1831 /* If smem is incompatible or old, driver should not work with it. */
1331 if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) 1832 drv_smem_cmp = bfa_ioc_fw_ver_patch_cmp(drv_fwhdr, fwhdr);
1332 return false; 1833 if (drv_smem_cmp == BFI_IOC_IMG_VER_INCOMP ||
1834 drv_smem_cmp == BFI_IOC_IMG_VER_OLD) {
1835 return false;
1333 } 1836 }
1334 1837
1335 return true; 1838 /* IF Flash has a better F/W than smem do not work with smem.
1839 * If smem f/w == flash f/w, as smem f/w not old | incmp, work with it.
1840 * If Flash is old or incomp work with smem iff smem f/w == drv f/w.
1841 */
1842 smem_flash_cmp = bfa_ioc_flash_fwver_cmp(ioc, fwhdr);
1843
1844 if (smem_flash_cmp == BFI_IOC_IMG_VER_BETTER)
1845 return false;
1846 else if (smem_flash_cmp == BFI_IOC_IMG_VER_SAME)
1847 return true;
1848 else
1849 return (drv_smem_cmp == BFI_IOC_IMG_VER_SAME) ?
1850 true : false;
1336} 1851}
1337 1852
1338/* Return true if current running version is valid. Firmware signature and 1853/* Return true if current running version is valid. Firmware signature and
@@ -1341,15 +1856,9 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
1341static bool 1856static bool
1342bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env) 1857bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
1343{ 1858{
1344 struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr; 1859 struct bfi_ioc_image_hdr fwhdr;
1345 1860
1346 bfa_nw_ioc_fwver_get(ioc, &fwhdr); 1861 bfa_nw_ioc_fwver_get(ioc, &fwhdr);
1347 drv_fwhdr = (struct bfi_ioc_image_hdr *)
1348 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1349
1350 if (fwhdr.signature != drv_fwhdr->signature)
1351 return false;
1352
1353 if (swab32(fwhdr.bootenv) != boot_env) 1862 if (swab32(fwhdr.bootenv) != boot_env)
1354 return false; 1863 return false;
1355 1864
@@ -1388,8 +1897,10 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
1388 false : bfa_ioc_fwver_valid(ioc, boot_env); 1897 false : bfa_ioc_fwver_valid(ioc, boot_env);
1389 1898
1390 if (!fwvalid) { 1899 if (!fwvalid) {
1391 bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env); 1900 if (bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env) ==
1392 bfa_ioc_poll_fwinit(ioc); 1901 BFA_STATUS_OK)
1902 bfa_ioc_poll_fwinit(ioc);
1903
1393 return; 1904 return;
1394 } 1905 }
1395 1906
@@ -1419,8 +1930,9 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
1419 /** 1930 /**
1420 * Initialize the h/w for any other states. 1931 * Initialize the h/w for any other states.
1421 */ 1932 */
1422 bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env); 1933 if (bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env) ==
1423 bfa_ioc_poll_fwinit(ioc); 1934 BFA_STATUS_OK)
1935 bfa_ioc_poll_fwinit(ioc);
1424} 1936}
1425 1937
1426void 1938void
@@ -1525,7 +2037,7 @@ bfa_ioc_hb_stop(struct bfa_ioc *ioc)
1525} 2037}
1526 2038
1527/* Initiate a full firmware download. */ 2039/* Initiate a full firmware download. */
1528static void 2040static enum bfa_status
1529bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, 2041bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
1530 u32 boot_env) 2042 u32 boot_env)
1531{ 2043{
@@ -1535,18 +2047,47 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
1535 u32 chunkno = 0; 2047 u32 chunkno = 0;
1536 u32 i; 2048 u32 i;
1537 u32 asicmode; 2049 u32 asicmode;
2050 u32 fwimg_size;
2051 u32 fwimg_buf[BFI_FLASH_CHUNK_SZ_WORDS];
2052 enum bfa_status status;
2053
2054 if (boot_env == BFI_FWBOOT_ENV_OS &&
2055 boot_type == BFI_FWBOOT_TYPE_FLASH) {
2056 fwimg_size = BFI_FLASH_IMAGE_SZ/sizeof(u32);
2057
2058 status = bfa_nw_ioc_flash_img_get_chnk(ioc,
2059 BFA_IOC_FLASH_CHUNK_ADDR(chunkno), fwimg_buf);
2060 if (status != BFA_STATUS_OK)
2061 return status;
1538 2062
1539 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno); 2063 fwimg = fwimg_buf;
2064 } else {
2065 fwimg_size = bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc));
2066 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
2067 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
2068 }
1540 2069
1541 pgnum = bfa_ioc_smem_pgnum(ioc, loff); 2070 pgnum = bfa_ioc_smem_pgnum(ioc, loff);
1542 2071
1543 writel(pgnum, ioc->ioc_regs.host_page_num_fn); 2072 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1544 2073
1545 for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) { 2074 for (i = 0; i < fwimg_size; i++) {
1546 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) { 2075 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1547 chunkno = BFA_IOC_FLASH_CHUNK_NO(i); 2076 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
1548 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 2077 if (boot_env == BFI_FWBOOT_ENV_OS &&
2078 boot_type == BFI_FWBOOT_TYPE_FLASH) {
2079 status = bfa_nw_ioc_flash_img_get_chnk(ioc,
2080 BFA_IOC_FLASH_CHUNK_ADDR(chunkno),
2081 fwimg_buf);
2082 if (status != BFA_STATUS_OK)
2083 return status;
2084
2085 fwimg = fwimg_buf;
2086 } else {
2087 fwimg = bfa_cb_image_get_chunk(
2088 bfa_ioc_asic_gen(ioc),
1549 BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); 2089 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
2090 }
1550 } 2091 }
1551 2092
1552 /** 2093 /**
@@ -1574,6 +2115,10 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
1574 /* 2115 /*
1575 * Set boot type, env and device mode at the end. 2116 * Set boot type, env and device mode at the end.
1576 */ 2117 */
2118 if (boot_env == BFI_FWBOOT_ENV_OS &&
2119 boot_type == BFI_FWBOOT_TYPE_FLASH) {
2120 boot_type = BFI_FWBOOT_TYPE_NORMAL;
2121 }
1577 asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode, 2122 asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
1578 ioc->port0_mode, ioc->port1_mode); 2123 ioc->port0_mode, ioc->port1_mode);
1579 writel(asicmode, ((ioc->ioc_regs.smem_page_start) 2124 writel(asicmode, ((ioc->ioc_regs.smem_page_start)
@@ -1582,6 +2127,7 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
1582 + (BFI_FWBOOT_TYPE_OFF))); 2127 + (BFI_FWBOOT_TYPE_OFF)));
1583 writel(boot_env, ((ioc->ioc_regs.smem_page_start) 2128 writel(boot_env, ((ioc->ioc_regs.smem_page_start)
1584 + (BFI_FWBOOT_ENV_OFF))); 2129 + (BFI_FWBOOT_ENV_OFF)));
2130 return BFA_STATUS_OK;
1585} 2131}
1586 2132
1587static void 2133static void
@@ -1854,14 +2400,27 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
1854/* Interface used by diag module to do firmware boot with memory test 2400/* Interface used by diag module to do firmware boot with memory test
1855 * as the entry vector. 2401 * as the entry vector.
1856 */ 2402 */
1857static void 2403static enum bfa_status
1858bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type, 2404bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
1859 u32 boot_env) 2405 u32 boot_env)
1860{ 2406{
2407 struct bfi_ioc_image_hdr *drv_fwhdr;
2408 enum bfa_status status;
1861 bfa_ioc_stats(ioc, ioc_boots); 2409 bfa_ioc_stats(ioc, ioc_boots);
1862 2410
1863 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK) 2411 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
1864 return; 2412 return BFA_STATUS_FAILED;
2413 if (boot_env == BFI_FWBOOT_ENV_OS &&
2414 boot_type == BFI_FWBOOT_TYPE_NORMAL) {
2415 drv_fwhdr = (struct bfi_ioc_image_hdr *)
2416 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
2417 /* Work with Flash iff flash f/w is better than driver f/w.
2418 * Otherwise push drivers firmware.
2419 */
2420 if (bfa_ioc_flash_fwver_cmp(ioc, drv_fwhdr) ==
2421 BFI_IOC_IMG_VER_BETTER)
2422 boot_type = BFI_FWBOOT_TYPE_FLASH;
2423 }
1865 2424
1866 /** 2425 /**
1867 * Initialize IOC state of all functions on a chip reset. 2426 * Initialize IOC state of all functions on a chip reset.
@@ -1875,8 +2434,13 @@ bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type,
1875 } 2434 }
1876 2435
1877 bfa_ioc_msgflush(ioc); 2436 bfa_ioc_msgflush(ioc);
1878 bfa_ioc_download_fw(ioc, boot_type, boot_env); 2437 status = bfa_ioc_download_fw(ioc, boot_type, boot_env);
1879 bfa_ioc_lpu_start(ioc); 2438 if (status == BFA_STATUS_OK)
2439 bfa_ioc_lpu_start(ioc);
2440 else
2441 bfa_nw_iocpf_timeout(ioc);
2442
2443 return status;
1880} 2444}
1881 2445
1882/* Enable/disable IOC failure auto recovery. */ 2446/* Enable/disable IOC failure auto recovery. */
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.h b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
index 9521cbf446a8..20cff7df4b55 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
@@ -298,6 +298,7 @@ void bfa_nw_ioc_error_isr(struct bfa_ioc *ioc);
298bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc); 298bool bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc);
299bool bfa_nw_ioc_is_operational(struct bfa_ioc *ioc); 299bool bfa_nw_ioc_is_operational(struct bfa_ioc *ioc);
300void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr); 300void bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr);
301enum bfa_status bfa_nw_ioc_fwsig_invalidate(struct bfa_ioc *ioc);
301void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc, 302void bfa_nw_ioc_notify_register(struct bfa_ioc *ioc,
302 struct bfa_ioc_notify *notify); 303 struct bfa_ioc_notify *notify);
303bool bfa_nw_ioc_sem_get(void __iomem *sem_reg); 304bool bfa_nw_ioc_sem_get(void __iomem *sem_reg);
diff --git a/drivers/net/ethernet/brocade/bna/bfi.h b/drivers/net/ethernet/brocade/bna/bfi.h
index 1f24c23dc786..8c563a77cdf6 100644
--- a/drivers/net/ethernet/brocade/bna/bfi.h
+++ b/drivers/net/ethernet/brocade/bna/bfi.h
@@ -25,6 +25,7 @@
25/* BFI FW image type */ 25/* BFI FW image type */
26#define BFI_FLASH_CHUNK_SZ 256 /*!< Flash chunk size */ 26#define BFI_FLASH_CHUNK_SZ 256 /*!< Flash chunk size */
27#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32)) 27#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
28#define BFI_FLASH_IMAGE_SZ 0x100000
28 29
29/* Msg header common to all msgs */ 30/* Msg header common to all msgs */
30struct bfi_mhdr { 31struct bfi_mhdr {
@@ -233,7 +234,29 @@ struct bfi_ioc_getattr_reply {
233#define BFI_IOC_TRC_HDR_SZ 32 234#define BFI_IOC_TRC_HDR_SZ 32
234 235
235#define BFI_IOC_FW_SIGNATURE (0xbfadbfad) 236#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
237#define BFI_IOC_FW_INV_SIGN (0xdeaddead)
236#define BFI_IOC_MD5SUM_SZ 4 238#define BFI_IOC_MD5SUM_SZ 4
239
240struct bfi_ioc_fwver {
241#ifdef __BIG_ENDIAN
242 u8 patch;
243 u8 maint;
244 u8 minor;
245 u8 major;
246 u8 rsvd[2];
247 u8 build;
248 u8 phase;
249#else
250 u8 major;
251 u8 minor;
252 u8 maint;
253 u8 patch;
254 u8 phase;
255 u8 build;
256 u8 rsvd[2];
257#endif
258};
259
237struct bfi_ioc_image_hdr { 260struct bfi_ioc_image_hdr {
238 u32 signature; /*!< constant signature */ 261 u32 signature; /*!< constant signature */
239 u8 asic_gen; /*!< asic generation */ 262 u8 asic_gen; /*!< asic generation */
@@ -242,10 +265,18 @@ struct bfi_ioc_image_hdr {
242 u8 port1_mode; /*!< device mode for port 1 */ 265 u8 port1_mode; /*!< device mode for port 1 */
243 u32 exec; /*!< exec vector */ 266 u32 exec; /*!< exec vector */
244 u32 bootenv; /*!< firmware boot env */ 267 u32 bootenv; /*!< firmware boot env */
245 u32 rsvd_b[4]; 268 u32 rsvd_b[2];
269 struct bfi_ioc_fwver fwver;
246 u32 md5sum[BFI_IOC_MD5SUM_SZ]; 270 u32 md5sum[BFI_IOC_MD5SUM_SZ];
247}; 271};
248 272
273enum bfi_ioc_img_ver_cmp {
274 BFI_IOC_IMG_VER_INCOMP,
275 BFI_IOC_IMG_VER_OLD,
276 BFI_IOC_IMG_VER_SAME,
277 BFI_IOC_IMG_VER_BETTER
278};
279
249#define BFI_FWBOOT_DEVMODE_OFF 4 280#define BFI_FWBOOT_DEVMODE_OFF 4
250#define BFI_FWBOOT_TYPE_OFF 8 281#define BFI_FWBOOT_TYPE_OFF 8
251#define BFI_FWBOOT_ENV_OFF 12 282#define BFI_FWBOOT_ENV_OFF 12
diff --git a/drivers/net/ethernet/brocade/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h
index 43405f654b4a..b3ff6d507951 100644
--- a/drivers/net/ethernet/brocade/bna/cna.h
+++ b/drivers/net/ethernet/brocade/bna/cna.h
@@ -37,8 +37,8 @@
37 37
38extern char bfa_version[]; 38extern char bfa_version[];
39 39
40#define CNA_FW_FILE_CT "ctfw-3.2.1.1.bin" 40#define CNA_FW_FILE_CT "ctfw-3.2.3.0.bin"
41#define CNA_FW_FILE_CT2 "ct2fw-3.2.1.1.bin" 41#define CNA_FW_FILE_CT2 "ct2fw-3.2.3.0.bin"
42#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */ 42#define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */
43 43
44#pragma pack(1) 44#pragma pack(1)