aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVijaya Mohan Guvva <vmohan@brocade.com>2013-11-21 04:37:28 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-12-19 10:39:04 -0500
commit28d358d01e1d27c17b6448935693b28cb5624bbe (patch)
treea34eb90f977ecd725873d507f5c278d23a7286e8
parent0e7c60cb8cd7b0250b1cf40012e5015c90bb89db (diff)
[SCSI] bfa: Firmware patch simplification
This patch includes change to enable firmware patch simplication feature. This feature is targeted to address the requirement to have independent patch release for firmware. Prior to 3.2.3, releasing a patch fix for firmware requires changes to bfa, to use new firmware images. But with these changes, if the new firmware is flashed on to the HBA with brocade adapter management utilites, driver uses the new firmware after checking the patch release byte in the firmware version. Signed-off-by: Vijaya Mohan Guvva <vmohan@brocade.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/bfa/bfa_defs.h1
-rw-r--r--drivers/scsi/bfa/bfa_ioc.c727
-rw-r--r--drivers/scsi/bfa/bfa_ioc.h7
-rw-r--r--drivers/scsi/bfa/bfa_ioc_cb.c23
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c15
-rw-r--r--drivers/scsi/bfa/bfad_bsg.h1
-rw-r--r--drivers/scsi/bfa/bfi.h39
7 files changed, 767 insertions, 46 deletions
diff --git a/drivers/scsi/bfa/bfa_defs.h b/drivers/scsi/bfa/bfa_defs.h
index d40a79f5265f..877b86dd2837 100644
--- a/drivers/scsi/bfa/bfa_defs.h
+++ b/drivers/scsi/bfa/bfa_defs.h
@@ -132,6 +132,7 @@ enum bfa_status {
132 BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists, 132 BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if persists,
133 * contact support */ 133 * contact support */
134 BFA_STATUS_EPROTOCOL = 6, /* Protocol error */ 134 BFA_STATUS_EPROTOCOL = 6, /* Protocol error */
135 BFA_STATUS_BADFLASH = 9, /* Flash is bad */
135 BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */ 136 BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */
136 BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */ 137 BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */
137 BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted */ 138 BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted */
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c
index f78bcb6696b2..65180e15de6e 100644
--- a/drivers/scsi/bfa/bfa_ioc.c
+++ b/drivers/scsi/bfa/bfa_ioc.c
@@ -21,6 +21,7 @@
21#include "bfi_reg.h" 21#include "bfi_reg.h"
22#include "bfa_defs.h" 22#include "bfa_defs.h"
23#include "bfa_defs_svc.h" 23#include "bfa_defs_svc.h"
24#include "bfi.h"
24 25
25BFA_TRC_FILE(CNA, IOC); 26BFA_TRC_FILE(CNA, IOC);
26 27
@@ -45,6 +46,14 @@ BFA_TRC_FILE(CNA, IOC);
45 46
46#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn)) 47#define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn))
47 48
49#define bfa_ioc_state_disabled(__sm) \
50 (((__sm) == BFI_IOC_UNINIT) || \
51 ((__sm) == BFI_IOC_INITING) || \
52 ((__sm) == BFI_IOC_HWINIT) || \
53 ((__sm) == BFI_IOC_DISABLED) || \
54 ((__sm) == BFI_IOC_FAIL) || \
55 ((__sm) == BFI_IOC_CFG_DISABLED))
56
48/* 57/*
49 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details. 58 * Asic specific macros : see bfa_hw_cb.c and bfa_hw_ct.c for details.
50 */ 59 */
@@ -102,6 +111,12 @@ static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc);
102static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); 111static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc);
103static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc); 112static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc);
104static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); 113static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc);
114static enum bfi_ioc_img_ver_cmp_e bfa_ioc_fw_ver_patch_cmp(
115 struct bfi_ioc_image_hdr_s *base_fwhdr,
116 struct bfi_ioc_image_hdr_s *fwhdr_to_cmp);
117static enum bfi_ioc_img_ver_cmp_e bfa_ioc_flash_fwver_cmp(
118 struct bfa_ioc_s *ioc,
119 struct bfi_ioc_image_hdr_s *base_fwhdr);
105 120
106/* 121/*
107 * IOC state machine definitions/declarations 122 * IOC state machine definitions/declarations
@@ -1454,28 +1469,42 @@ bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1454} 1469}
1455 1470
1456/* 1471/*
1457 * Returns TRUE if same. 1472 * Returns TRUE if driver is willing to work with current smem f/w version.
1458 */ 1473 */
1459bfa_boolean_t 1474bfa_boolean_t
1460bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) 1475bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc,
1476 struct bfi_ioc_image_hdr_s *smem_fwhdr)
1461{ 1477{
1462 struct bfi_ioc_image_hdr_s *drv_fwhdr; 1478 struct bfi_ioc_image_hdr_s *drv_fwhdr;
1463 int i; 1479 enum bfi_ioc_img_ver_cmp_e smem_flash_cmp, drv_smem_cmp;
1464 1480
1465 drv_fwhdr = (struct bfi_ioc_image_hdr_s *) 1481 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1466 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); 1482 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1467 1483
1468 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { 1484 /*
1469 if (fwhdr->md5sum[i] != cpu_to_le32(drv_fwhdr->md5sum[i])) { 1485 * If smem is incompatible or old, driver should not work with it.
1470 bfa_trc(ioc, i); 1486 */
1471 bfa_trc(ioc, fwhdr->md5sum[i]); 1487 drv_smem_cmp = bfa_ioc_fw_ver_patch_cmp(drv_fwhdr, smem_fwhdr);
1472 bfa_trc(ioc, drv_fwhdr->md5sum[i]); 1488 if (drv_smem_cmp == BFI_IOC_IMG_VER_INCOMP ||
1473 return BFA_FALSE; 1489 drv_smem_cmp == BFI_IOC_IMG_VER_OLD) {
1474 } 1490 return BFA_FALSE;
1475 } 1491 }
1476 1492
1477 bfa_trc(ioc, fwhdr->md5sum[0]); 1493 /*
1478 return BFA_TRUE; 1494 * IF Flash has a better F/W than smem do not work with smem.
1495 * If smem f/w == flash f/w, as smem f/w not old | incmp, work with it.
1496 * If Flash is old or incomp work with smem iff smem f/w == drv f/w.
1497 */
1498 smem_flash_cmp = bfa_ioc_flash_fwver_cmp(ioc, smem_fwhdr);
1499
1500 if (smem_flash_cmp == BFI_IOC_IMG_VER_BETTER) {
1501 return BFA_FALSE;
1502 } else if (smem_flash_cmp == BFI_IOC_IMG_VER_SAME) {
1503 return BFA_TRUE;
1504 } else {
1505 return (drv_smem_cmp == BFI_IOC_IMG_VER_SAME) ?
1506 BFA_TRUE : BFA_FALSE;
1507 }
1479} 1508}
1480 1509
1481/* 1510/*
@@ -1485,17 +1514,9 @@ bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr)
1485static bfa_boolean_t 1514static bfa_boolean_t
1486bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env) 1515bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
1487{ 1516{
1488 struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr; 1517 struct bfi_ioc_image_hdr_s fwhdr;
1489 1518
1490 bfa_ioc_fwver_get(ioc, &fwhdr); 1519 bfa_ioc_fwver_get(ioc, &fwhdr);
1491 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
1492 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
1493
1494 if (fwhdr.signature != cpu_to_le32(drv_fwhdr->signature)) {
1495 bfa_trc(ioc, fwhdr.signature);
1496 bfa_trc(ioc, drv_fwhdr->signature);
1497 return BFA_FALSE;
1498 }
1499 1520
1500 if (swab32(fwhdr.bootenv) != boot_env) { 1521 if (swab32(fwhdr.bootenv) != boot_env) {
1501 bfa_trc(ioc, fwhdr.bootenv); 1522 bfa_trc(ioc, fwhdr.bootenv);
@@ -1506,6 +1527,168 @@ bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env)
1506 return bfa_ioc_fwver_cmp(ioc, &fwhdr); 1527 return bfa_ioc_fwver_cmp(ioc, &fwhdr);
1507} 1528}
1508 1529
1530static bfa_boolean_t
1531bfa_ioc_fwver_md5_check(struct bfi_ioc_image_hdr_s *fwhdr_1,
1532 struct bfi_ioc_image_hdr_s *fwhdr_2)
1533{
1534 int i;
1535
1536 for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++)
1537 if (fwhdr_1->md5sum[i] != fwhdr_2->md5sum[i])
1538 return BFA_FALSE;
1539
1540 return BFA_TRUE;
1541}
1542
1543/*
1544 * Returns TRUE if major minor and maintainence are same.
1545 * If patch versions are same, check for MD5 Checksum to be same.
1546 */
1547static bfa_boolean_t
1548bfa_ioc_fw_ver_compatible(struct bfi_ioc_image_hdr_s *drv_fwhdr,
1549 struct bfi_ioc_image_hdr_s *fwhdr_to_cmp)
1550{
1551 if (drv_fwhdr->signature != fwhdr_to_cmp->signature)
1552 return BFA_FALSE;
1553
1554 if (drv_fwhdr->fwver.major != fwhdr_to_cmp->fwver.major)
1555 return BFA_FALSE;
1556
1557 if (drv_fwhdr->fwver.minor != fwhdr_to_cmp->fwver.minor)
1558 return BFA_FALSE;
1559
1560 if (drv_fwhdr->fwver.maint != fwhdr_to_cmp->fwver.maint)
1561 return BFA_FALSE;
1562
1563 if (drv_fwhdr->fwver.patch == fwhdr_to_cmp->fwver.patch &&
1564 drv_fwhdr->fwver.phase == fwhdr_to_cmp->fwver.phase &&
1565 drv_fwhdr->fwver.build == fwhdr_to_cmp->fwver.build) {
1566 return bfa_ioc_fwver_md5_check(drv_fwhdr, fwhdr_to_cmp);
1567 }
1568
1569 return BFA_TRUE;
1570}
1571
1572static bfa_boolean_t
1573bfa_ioc_flash_fwver_valid(struct bfi_ioc_image_hdr_s *flash_fwhdr)
1574{
1575 if (flash_fwhdr->fwver.major == 0 || flash_fwhdr->fwver.major == 0xFF)
1576 return BFA_FALSE;
1577
1578 return BFA_TRUE;
1579}
1580
1581static bfa_boolean_t fwhdr_is_ga(struct bfi_ioc_image_hdr_s *fwhdr)
1582{
1583 if (fwhdr->fwver.phase == 0 &&
1584 fwhdr->fwver.build == 0)
1585 return BFA_TRUE;
1586
1587 return BFA_FALSE;
1588}
1589
1590/*
1591 * Returns TRUE if both are compatible and patch of fwhdr_to_cmp is better.
1592 */
1593static enum bfi_ioc_img_ver_cmp_e
1594bfa_ioc_fw_ver_patch_cmp(struct bfi_ioc_image_hdr_s *base_fwhdr,
1595 struct bfi_ioc_image_hdr_s *fwhdr_to_cmp)
1596{
1597 if (bfa_ioc_fw_ver_compatible(base_fwhdr, fwhdr_to_cmp) == BFA_FALSE)
1598 return BFI_IOC_IMG_VER_INCOMP;
1599
1600 if (fwhdr_to_cmp->fwver.patch > base_fwhdr->fwver.patch)
1601 return BFI_IOC_IMG_VER_BETTER;
1602
1603 else if (fwhdr_to_cmp->fwver.patch < base_fwhdr->fwver.patch)
1604 return BFI_IOC_IMG_VER_OLD;
1605
1606 /*
1607 * GA takes priority over internal builds of the same patch stream.
1608 * At this point major minor maint and patch numbers are same.
1609 */
1610
1611 if (fwhdr_is_ga(base_fwhdr) == BFA_TRUE) {
1612 if (fwhdr_is_ga(fwhdr_to_cmp))
1613 return BFI_IOC_IMG_VER_SAME;
1614 else
1615 return BFI_IOC_IMG_VER_OLD;
1616 } else {
1617 if (fwhdr_is_ga(fwhdr_to_cmp))
1618 return BFI_IOC_IMG_VER_BETTER;
1619 }
1620
1621 if (fwhdr_to_cmp->fwver.phase > base_fwhdr->fwver.phase)
1622 return BFI_IOC_IMG_VER_BETTER;
1623 else if (fwhdr_to_cmp->fwver.phase < base_fwhdr->fwver.phase)
1624 return BFI_IOC_IMG_VER_OLD;
1625
1626 if (fwhdr_to_cmp->fwver.build > base_fwhdr->fwver.build)
1627 return BFI_IOC_IMG_VER_BETTER;
1628 else if (fwhdr_to_cmp->fwver.build < base_fwhdr->fwver.build)
1629 return BFI_IOC_IMG_VER_OLD;
1630
1631 /*
1632 * All Version Numbers are equal.
1633 * Md5 check to be done as a part of compatibility check.
1634 */
1635 return BFI_IOC_IMG_VER_SAME;
1636}
1637
1638#define BFA_FLASH_PART_FWIMG_ADDR 0x100000 /* fw image address */
1639
1640bfa_status_t
1641bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off,
1642 u32 *fwimg)
1643{
1644 return bfa_flash_raw_read(ioc->pcidev.pci_bar_kva,
1645 BFA_FLASH_PART_FWIMG_ADDR + (off * sizeof(u32)),
1646 (char *)fwimg, BFI_FLASH_CHUNK_SZ);
1647}
1648
1649static enum bfi_ioc_img_ver_cmp_e
1650bfa_ioc_flash_fwver_cmp(struct bfa_ioc_s *ioc,
1651 struct bfi_ioc_image_hdr_s *base_fwhdr)
1652{
1653 struct bfi_ioc_image_hdr_s *flash_fwhdr;
1654 bfa_status_t status;
1655 u32 fwimg[BFI_FLASH_CHUNK_SZ_WORDS];
1656
1657 status = bfa_ioc_flash_img_get_chnk(ioc, 0, fwimg);
1658 if (status != BFA_STATUS_OK)
1659 return BFI_IOC_IMG_VER_INCOMP;
1660
1661 flash_fwhdr = (struct bfi_ioc_image_hdr_s *) fwimg;
1662 if (bfa_ioc_flash_fwver_valid(flash_fwhdr) == BFA_TRUE)
1663 return bfa_ioc_fw_ver_patch_cmp(base_fwhdr, flash_fwhdr);
1664 else
1665 return BFI_IOC_IMG_VER_INCOMP;
1666}
1667
1668
1669/*
1670 * Invalidate fwver signature
1671 */
1672bfa_status_t
1673bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc)
1674{
1675
1676 u32 pgnum, pgoff;
1677 u32 loff = 0;
1678 enum bfi_ioc_state ioc_fwstate;
1679
1680 ioc_fwstate = bfa_ioc_get_cur_ioc_fwstate(ioc);
1681 if (!bfa_ioc_state_disabled(ioc_fwstate))
1682 return BFA_STATUS_ADAPTER_ENABLED;
1683
1684 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1685 pgoff = PSS_SMEM_PGOFF(loff);
1686 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1687 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, BFA_IOC_FW_INV_SIGN);
1688
1689 return BFA_STATUS_OK;
1690}
1691
1509/* 1692/*
1510 * Conditionally flush any pending message from firmware at start. 1693 * Conditionally flush any pending message from firmware at start.
1511 */ 1694 */
@@ -1544,8 +1727,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1544 BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env); 1727 BFA_FALSE : bfa_ioc_fwver_valid(ioc, boot_env);
1545 1728
1546 if (!fwvalid) { 1729 if (!fwvalid) {
1547 bfa_ioc_boot(ioc, boot_type, boot_env); 1730 if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK)
1548 bfa_ioc_poll_fwinit(ioc); 1731 bfa_ioc_poll_fwinit(ioc);
1549 return; 1732 return;
1550 } 1733 }
1551 1734
@@ -1580,8 +1763,8 @@ bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force)
1580 /* 1763 /*
1581 * Initialize the h/w for any other states. 1764 * Initialize the h/w for any other states.
1582 */ 1765 */
1583 bfa_ioc_boot(ioc, boot_type, boot_env); 1766 if (bfa_ioc_boot(ioc, boot_type, boot_env) == BFA_STATUS_OK)
1584 bfa_ioc_poll_fwinit(ioc); 1767 bfa_ioc_poll_fwinit(ioc);
1585} 1768}
1586 1769
1587static void 1770static void
@@ -1684,7 +1867,7 @@ bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc)
1684/* 1867/*
1685 * Initiate a full firmware download. 1868 * Initiate a full firmware download.
1686 */ 1869 */
1687static void 1870static bfa_status_t
1688bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, 1871bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1689 u32 boot_env) 1872 u32 boot_env)
1690{ 1873{
@@ -1694,28 +1877,60 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1694 u32 chunkno = 0; 1877 u32 chunkno = 0;
1695 u32 i; 1878 u32 i;
1696 u32 asicmode; 1879 u32 asicmode;
1880 u32 fwimg_size;
1881 u32 fwimg_buf[BFI_FLASH_CHUNK_SZ_WORDS];
1882 bfa_status_t status;
1883
1884 if (boot_env == BFI_FWBOOT_ENV_OS &&
1885 boot_type == BFI_FWBOOT_TYPE_FLASH) {
1886 fwimg_size = BFI_FLASH_IMAGE_SZ/sizeof(u32);
1887
1888 status = bfa_ioc_flash_img_get_chnk(ioc,
1889 BFA_IOC_FLASH_CHUNK_ADDR(chunkno), fwimg_buf);
1890 if (status != BFA_STATUS_OK)
1891 return status;
1892
1893 fwimg = fwimg_buf;
1894 } else {
1895 fwimg_size = bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc));
1896 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc),
1897 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
1898 }
1899
1900 bfa_trc(ioc, fwimg_size);
1697 1901
1698 bfa_trc(ioc, bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)));
1699 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno);
1700 1902
1701 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff); 1903 pgnum = PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, loff);
1702 pgoff = PSS_SMEM_PGOFF(loff); 1904 pgoff = PSS_SMEM_PGOFF(loff);
1703 1905
1704 writel(pgnum, ioc->ioc_regs.host_page_num_fn); 1906 writel(pgnum, ioc->ioc_regs.host_page_num_fn);
1705 1907
1706 for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) { 1908 for (i = 0; i < fwimg_size; i++) {
1707 1909
1708 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) { 1910 if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) {
1709 chunkno = BFA_IOC_FLASH_CHUNK_NO(i); 1911 chunkno = BFA_IOC_FLASH_CHUNK_NO(i);
1710 fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 1912
1913 if (boot_env == BFI_FWBOOT_ENV_OS &&
1914 boot_type == BFI_FWBOOT_TYPE_FLASH) {
1915 status = bfa_ioc_flash_img_get_chnk(ioc,
1916 BFA_IOC_FLASH_CHUNK_ADDR(chunkno),
1917 fwimg_buf);
1918 if (status != BFA_STATUS_OK)
1919 return status;
1920
1921 fwimg = fwimg_buf;
1922 } else {
1923 fwimg = bfa_cb_image_get_chunk(
1924 bfa_ioc_asic_gen(ioc),
1711 BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); 1925 BFA_IOC_FLASH_CHUNK_ADDR(chunkno));
1926 }
1712 } 1927 }
1713 1928
1714 /* 1929 /*
1715 * write smem 1930 * write smem
1716 */ 1931 */
1717 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, 1932 bfa_mem_write(ioc->ioc_regs.smem_page_start, loff,
1718 cpu_to_le32(fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)])); 1933 fwimg[BFA_IOC_FLASH_OFFSET_IN_CHUNK(i)]);
1719 1934
1720 loff += sizeof(u32); 1935 loff += sizeof(u32);
1721 1936
@@ -1733,8 +1948,12 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1733 ioc->ioc_regs.host_page_num_fn); 1948 ioc->ioc_regs.host_page_num_fn);
1734 1949
1735 /* 1950 /*
1736 * Set boot type and device mode at the end. 1951 * Set boot type, env and device mode at the end.
1737 */ 1952 */
1953 if (boot_env == BFI_FWBOOT_ENV_OS &&
1954 boot_type == BFI_FWBOOT_TYPE_FLASH) {
1955 boot_type = BFI_FWBOOT_TYPE_NORMAL;
1956 }
1738 asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode, 1957 asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode,
1739 ioc->port0_mode, ioc->port1_mode); 1958 ioc->port0_mode, ioc->port1_mode);
1740 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF, 1959 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_DEVMODE_OFF,
@@ -1743,6 +1962,7 @@ bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type,
1743 swab32(boot_type)); 1962 swab32(boot_type));
1744 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF, 1963 bfa_mem_write(ioc->ioc_regs.smem_page_start, BFI_FWBOOT_ENV_OFF,
1745 swab32(boot_env)); 1964 swab32(boot_env));
1965 return BFA_STATUS_OK;
1746} 1966}
1747 1967
1748 1968
@@ -2002,13 +2222,30 @@ bfa_ioc_pll_init(struct bfa_ioc_s *ioc)
2002 * Interface used by diag module to do firmware boot with memory test 2222 * Interface used by diag module to do firmware boot with memory test
2003 * as the entry vector. 2223 * as the entry vector.
2004 */ 2224 */
2005void 2225bfa_status_t
2006bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env) 2226bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
2007{ 2227{
2228 struct bfi_ioc_image_hdr_s *drv_fwhdr;
2229 bfa_status_t status;
2008 bfa_ioc_stats(ioc, ioc_boots); 2230 bfa_ioc_stats(ioc, ioc_boots);
2009 2231
2010 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK) 2232 if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK)
2011 return; 2233 return BFA_STATUS_FAILED;
2234
2235 if (boot_env == BFI_FWBOOT_ENV_OS &&
2236 boot_type == BFI_FWBOOT_TYPE_NORMAL) {
2237
2238 drv_fwhdr = (struct bfi_ioc_image_hdr_s *)
2239 bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0);
2240
2241 /*
2242 * Work with Flash iff flash f/w is better than driver f/w.
2243 * Otherwise push drivers firmware.
2244 */
2245 if (bfa_ioc_flash_fwver_cmp(ioc, drv_fwhdr) ==
2246 BFI_IOC_IMG_VER_BETTER)
2247 boot_type = BFI_FWBOOT_TYPE_FLASH;
2248 }
2012 2249
2013 /* 2250 /*
2014 * Initialize IOC state of all functions on a chip reset. 2251 * Initialize IOC state of all functions on a chip reset.
@@ -2022,8 +2259,14 @@ bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env)
2022 } 2259 }
2023 2260
2024 bfa_ioc_msgflush(ioc); 2261 bfa_ioc_msgflush(ioc);
2025 bfa_ioc_download_fw(ioc, boot_type, boot_env); 2262 status = bfa_ioc_download_fw(ioc, boot_type, boot_env);
2026 bfa_ioc_lpu_start(ioc); 2263 if (status == BFA_STATUS_OK)
2264 bfa_ioc_lpu_start(ioc);
2265 else {
2266 WARN_ON(boot_type == BFI_FWBOOT_TYPE_MEMTEST);
2267 bfa_iocpf_timeout(ioc);
2268 }
2269 return status;
2027} 2270}
2028 2271
2029/* 2272/*
@@ -2419,14 +2662,6 @@ bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc)
2419 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch); 2662 bfa_fsm_cmp_state(&ioc->iocpf, bfa_iocpf_sm_mismatch);
2420} 2663}
2421 2664
2422#define bfa_ioc_state_disabled(__sm) \
2423 (((__sm) == BFI_IOC_UNINIT) || \
2424 ((__sm) == BFI_IOC_INITING) || \
2425 ((__sm) == BFI_IOC_HWINIT) || \
2426 ((__sm) == BFI_IOC_DISABLED) || \
2427 ((__sm) == BFI_IOC_FAIL) || \
2428 ((__sm) == BFI_IOC_CFG_DISABLED))
2429
2430/* 2665/*
2431 * Check if adapter is disabled -- both IOCs should be in a disabled 2666 * Check if adapter is disabled -- both IOCs should be in a disabled
2432 * state. 2667 * state.
@@ -6423,3 +6658,407 @@ bfa_fru_intr(void *fruarg, struct bfi_mbmsg_s *msg)
6423 WARN_ON(1); 6658 WARN_ON(1);
6424 } 6659 }
6425} 6660}
6661
6662/*
6663 * register definitions
6664 */
6665#define FLI_CMD_REG 0x0001d000
6666#define FLI_RDDATA_REG 0x0001d010
6667#define FLI_ADDR_REG 0x0001d004
6668#define FLI_DEV_STATUS_REG 0x0001d014
6669
6670#define BFA_FLASH_FIFO_SIZE 128 /* fifo size */
6671#define BFA_FLASH_CHECK_MAX 10000 /* max # of status check */
6672#define BFA_FLASH_BLOCKING_OP_MAX 1000000 /* max # of blocking op check */
6673#define BFA_FLASH_WIP_MASK 0x01 /* write in progress bit mask */
6674
6675enum bfa_flash_cmd {
6676 BFA_FLASH_FAST_READ = 0x0b, /* fast read */
6677 BFA_FLASH_READ_STATUS = 0x05, /* read status */
6678};
6679
6680/**
6681 * @brief hardware error definition
6682 */
6683enum bfa_flash_err {
6684 BFA_FLASH_NOT_PRESENT = -1, /*!< flash not present */
6685 BFA_FLASH_UNINIT = -2, /*!< flash not initialized */
6686 BFA_FLASH_BAD = -3, /*!< flash bad */
6687 BFA_FLASH_BUSY = -4, /*!< flash busy */
6688 BFA_FLASH_ERR_CMD_ACT = -5, /*!< command active never cleared */
6689 BFA_FLASH_ERR_FIFO_CNT = -6, /*!< fifo count never cleared */
6690 BFA_FLASH_ERR_WIP = -7, /*!< write-in-progress never cleared */
6691 BFA_FLASH_ERR_TIMEOUT = -8, /*!< fli timeout */
6692 BFA_FLASH_ERR_LEN = -9, /*!< invalid length */
6693};
6694
6695/**
6696 * @brief flash command register data structure
6697 */
6698union bfa_flash_cmd_reg_u {
6699 struct {
6700#ifdef __BIG_ENDIAN
6701 u32 act:1;
6702 u32 rsv:1;
6703 u32 write_cnt:9;
6704 u32 read_cnt:9;
6705 u32 addr_cnt:4;
6706 u32 cmd:8;
6707#else
6708 u32 cmd:8;
6709 u32 addr_cnt:4;
6710 u32 read_cnt:9;
6711 u32 write_cnt:9;
6712 u32 rsv:1;
6713 u32 act:1;
6714#endif
6715 } r;
6716 u32 i;
6717};
6718
6719/**
6720 * @brief flash device status register data structure
6721 */
6722union bfa_flash_dev_status_reg_u {
6723 struct {
6724#ifdef __BIG_ENDIAN
6725 u32 rsv:21;
6726 u32 fifo_cnt:6;
6727 u32 busy:1;
6728 u32 init_status:1;
6729 u32 present:1;
6730 u32 bad:1;
6731 u32 good:1;
6732#else
6733 u32 good:1;
6734 u32 bad:1;
6735 u32 present:1;
6736 u32 init_status:1;
6737 u32 busy:1;
6738 u32 fifo_cnt:6;
6739 u32 rsv:21;
6740#endif
6741 } r;
6742 u32 i;
6743};
6744
6745/**
6746 * @brief flash address register data structure
6747 */
6748union bfa_flash_addr_reg_u {
6749 struct {
6750#ifdef __BIG_ENDIAN
6751 u32 addr:24;
6752 u32 dummy:8;
6753#else
6754 u32 dummy:8;
6755 u32 addr:24;
6756#endif
6757 } r;
6758 u32 i;
6759};
6760
6761/**
6762 * dg flash_raw_private Flash raw private functions
6763 */
6764static void
6765bfa_flash_set_cmd(void __iomem *pci_bar, u8 wr_cnt,
6766 u8 rd_cnt, u8 ad_cnt, u8 op)
6767{
6768 union bfa_flash_cmd_reg_u cmd;
6769
6770 cmd.i = 0;
6771 cmd.r.act = 1;
6772 cmd.r.write_cnt = wr_cnt;
6773 cmd.r.read_cnt = rd_cnt;
6774 cmd.r.addr_cnt = ad_cnt;
6775 cmd.r.cmd = op;
6776 writel(cmd.i, (pci_bar + FLI_CMD_REG));
6777}
6778
6779static void
6780bfa_flash_set_addr(void __iomem *pci_bar, u32 address)
6781{
6782 union bfa_flash_addr_reg_u addr;
6783
6784 addr.r.addr = address & 0x00ffffff;
6785 addr.r.dummy = 0;
6786 writel(addr.i, (pci_bar + FLI_ADDR_REG));
6787}
6788
6789static int
6790bfa_flash_cmd_act_check(void __iomem *pci_bar)
6791{
6792 union bfa_flash_cmd_reg_u cmd;
6793
6794 cmd.i = readl(pci_bar + FLI_CMD_REG);
6795
6796 if (cmd.r.act)
6797 return BFA_FLASH_ERR_CMD_ACT;
6798
6799 return 0;
6800}
6801
6802/**
6803 * @brief
6804 * Flush FLI data fifo.
6805 *
6806 * @param[in] pci_bar - pci bar address
6807 * @param[in] dev_status - device status
6808 *
6809 * Return 0 on success, negative error number on error.
6810 */
6811static u32
6812bfa_flash_fifo_flush(void __iomem *pci_bar)
6813{
6814 u32 i;
6815 u32 t;
6816 union bfa_flash_dev_status_reg_u dev_status;
6817
6818 dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
6819
6820 if (!dev_status.r.fifo_cnt)
6821 return 0;
6822
6823 /* fifo counter in terms of words */
6824 for (i = 0; i < dev_status.r.fifo_cnt; i++)
6825 t = readl(pci_bar + FLI_RDDATA_REG);
6826
6827 /*
6828 * Check the device status. It may take some time.
6829 */
6830 for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {
6831 dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
6832 if (!dev_status.r.fifo_cnt)
6833 break;
6834 }
6835
6836 if (dev_status.r.fifo_cnt)
6837 return BFA_FLASH_ERR_FIFO_CNT;
6838
6839 return 0;
6840}
6841
6842/**
6843 * @brief
6844 * Read flash status.
6845 *
6846 * @param[in] pci_bar - pci bar address
6847 *
6848 * Return 0 on success, negative error number on error.
6849*/
6850static u32
6851bfa_flash_status_read(void __iomem *pci_bar)
6852{
6853 union bfa_flash_dev_status_reg_u dev_status;
6854 u32 status;
6855 u32 ret_status;
6856 int i;
6857
6858 status = bfa_flash_fifo_flush(pci_bar);
6859 if (status < 0)
6860 return status;
6861
6862 bfa_flash_set_cmd(pci_bar, 0, 4, 0, BFA_FLASH_READ_STATUS);
6863
6864 for (i = 0; i < BFA_FLASH_CHECK_MAX; i++) {
6865 status = bfa_flash_cmd_act_check(pci_bar);
6866 if (!status)
6867 break;
6868 }
6869
6870 if (status)
6871 return status;
6872
6873 dev_status.i = readl(pci_bar + FLI_DEV_STATUS_REG);
6874 if (!dev_status.r.fifo_cnt)
6875 return BFA_FLASH_BUSY;
6876
6877 ret_status = readl(pci_bar + FLI_RDDATA_REG);
6878 ret_status >>= 24;
6879
6880 status = bfa_flash_fifo_flush(pci_bar);
6881 if (status < 0)
6882 return status;
6883
6884 return ret_status;
6885}
6886
6887/**
6888 * @brief
6889 * Start flash read operation.
6890 *
6891 * @param[in] pci_bar - pci bar address
6892 * @param[in] offset - flash address offset
6893 * @param[in] len - read data length
6894 * @param[in] buf - read data buffer
6895 *
6896 * Return 0 on success, negative error number on error.
6897 */
6898static u32
6899bfa_flash_read_start(void __iomem *pci_bar, u32 offset, u32 len,
6900 char *buf)
6901{
6902 u32 status;
6903
6904 /*
6905 * len must be mutiple of 4 and not exceeding fifo size
6906 */
6907 if (len == 0 || len > BFA_FLASH_FIFO_SIZE || (len & 0x03) != 0)
6908 return BFA_FLASH_ERR_LEN;
6909
6910 /*
6911 * check status
6912 */
6913 status = bfa_flash_status_read(pci_bar);
6914 if (status == BFA_FLASH_BUSY)
6915 status = bfa_flash_status_read(pci_bar);
6916
6917 if (status < 0)
6918 return status;
6919
6920 /*
6921 * check if write-in-progress bit is cleared
6922 */
6923 if (status & BFA_FLASH_WIP_MASK)
6924 return BFA_FLASH_ERR_WIP;
6925
6926 bfa_flash_set_addr(pci_bar, offset);
6927
6928 bfa_flash_set_cmd(pci_bar, 0, (u8)len, 4, BFA_FLASH_FAST_READ);
6929
6930 return 0;
6931}
6932
6933/**
6934 * @brief
6935 * Check flash read operation.
6936 *
6937 * @param[in] pci_bar - pci bar address
6938 *
6939 * Return flash device status, 1 if busy, 0 if not.
6940 */
6941static u32
6942bfa_flash_read_check(void __iomem *pci_bar)
6943{
6944 if (bfa_flash_cmd_act_check(pci_bar))
6945 return 1;
6946
6947 return 0;
6948}
6949/**
6950 * @brief
6951 * End flash read operation.
6952 *
6953 * @param[in] pci_bar - pci bar address
6954 * @param[in] len - read data length
6955 * @param[in] buf - read data buffer
6956 *
6957 */
6958static void
6959bfa_flash_read_end(void __iomem *pci_bar, u32 len, char *buf)
6960{
6961
6962 u32 i;
6963
6964 /*
6965 * read data fifo up to 32 words
6966 */
6967 for (i = 0; i < len; i += 4) {
6968 u32 w = readl(pci_bar + FLI_RDDATA_REG);
6969 *((u32 *) (buf + i)) = swab32(w);
6970 }
6971
6972 bfa_flash_fifo_flush(pci_bar);
6973}
6974
6975/**
6976 * @brief
6977 * Perform flash raw read.
6978 *
6979 * @param[in] pci_bar - pci bar address
6980 * @param[in] offset - flash partition address offset
6981 * @param[in] buf - read data buffer
6982 * @param[in] len - read data length
6983 *
6984 * Return status.
6985 */
6986
6987
6988#define FLASH_BLOCKING_OP_MAX 500
6989#define FLASH_SEM_LOCK_REG 0x18820
6990
6991static int
6992bfa_raw_sem_get(void __iomem *bar)
6993{
6994 int locked;
6995
6996 locked = readl((bar + FLASH_SEM_LOCK_REG));
6997 return !locked;
6998
6999}
7000
7001bfa_status_t
7002bfa_flash_sem_get(void __iomem *bar)
7003{
7004 u32 n = FLASH_BLOCKING_OP_MAX;
7005
7006 while (!bfa_raw_sem_get(bar)) {
7007 if (--n <= 0)
7008 return BFA_STATUS_BADFLASH;
7009 udelay(10000);
7010 }
7011 return BFA_STATUS_OK;
7012}
7013
7014void
7015bfa_flash_sem_put(void __iomem *bar)
7016{
7017 writel(0, (bar + FLASH_SEM_LOCK_REG));
7018}
7019
7020bfa_status_t
7021bfa_flash_raw_read(void __iomem *pci_bar, u32 offset, char *buf,
7022 u32 len)
7023{
7024 u32 n, status;
7025 u32 off, l, s, residue, fifo_sz;
7026
7027 residue = len;
7028 off = 0;
7029 fifo_sz = BFA_FLASH_FIFO_SIZE;
7030 status = bfa_flash_sem_get(pci_bar);
7031 if (status != BFA_STATUS_OK)
7032 return status;
7033
7034 while (residue) {
7035 s = offset + off;
7036 n = s / fifo_sz;
7037 l = (n + 1) * fifo_sz - s;
7038 if (l > residue)
7039 l = residue;
7040
7041 status = bfa_flash_read_start(pci_bar, offset + off, l,
7042 &buf[off]);
7043 if (status < 0) {
7044 bfa_flash_sem_put(pci_bar);
7045 return BFA_STATUS_FAILED;
7046 }
7047
7048 n = BFA_FLASH_BLOCKING_OP_MAX;
7049 while (bfa_flash_read_check(pci_bar)) {
7050 if (--n <= 0) {
7051 bfa_flash_sem_put(pci_bar);
7052 return BFA_STATUS_FAILED;
7053 }
7054 }
7055
7056 bfa_flash_read_end(pci_bar, l, &buf[off]);
7057
7058 residue -= l;
7059 off += l;
7060 }
7061 bfa_flash_sem_put(pci_bar);
7062
7063 return BFA_STATUS_OK;
7064}
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h
index 90814fe85ac1..2e28392c2fb6 100644
--- a/drivers/scsi/bfa/bfa_ioc.h
+++ b/drivers/scsi/bfa/bfa_ioc.h
@@ -515,6 +515,8 @@ void bfa_flash_attach(struct bfa_flash_s *flash, struct bfa_ioc_s *ioc,
515 void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg); 515 void *dev, struct bfa_trc_mod_s *trcmod, bfa_boolean_t mincfg);
516void bfa_flash_memclaim(struct bfa_flash_s *flash, 516void bfa_flash_memclaim(struct bfa_flash_s *flash,
517 u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg); 517 u8 *dm_kva, u64 dm_pa, bfa_boolean_t mincfg);
518bfa_status_t bfa_flash_raw_read(void __iomem *pci_bar_kva,
519 u32 offset, char *buf, u32 len);
518 520
519/* 521/*
520 * DIAG module specific 522 * DIAG module specific
@@ -888,7 +890,7 @@ void bfa_ioc_enable(struct bfa_ioc_s *ioc);
888void bfa_ioc_disable(struct bfa_ioc_s *ioc); 890void bfa_ioc_disable(struct bfa_ioc_s *ioc);
889bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc); 891bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc);
890 892
891void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, 893bfa_status_t bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type,
892 u32 boot_env); 894 u32 boot_env);
893void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg); 895void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg);
894void bfa_ioc_error_isr(struct bfa_ioc_s *ioc); 896void bfa_ioc_error_isr(struct bfa_ioc_s *ioc);
@@ -919,6 +921,7 @@ bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata,
919 int *trclen); 921 int *trclen);
920bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf, 922bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf,
921 u32 *offset, int *buflen); 923 u32 *offset, int *buflen);
924bfa_status_t bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc);
922bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg); 925bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg);
923void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, 926void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc,
924 struct bfi_ioc_image_hdr_s *fwhdr); 927 struct bfi_ioc_image_hdr_s *fwhdr);
@@ -956,6 +959,8 @@ bfa_status_t bfa_ablk_optrom_en(struct bfa_ablk_s *ablk,
956bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, 959bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk,
957 bfa_ablk_cbfn_t cbfn, void *cbarg); 960 bfa_ablk_cbfn_t cbfn, void *cbarg);
958 961
962bfa_status_t bfa_ioc_flash_img_get_chnk(struct bfa_ioc_s *ioc, u32 off,
963 u32 *fwimg);
959/* 964/*
960 * bfa mfg wwn API functions 965 * bfa mfg wwn API functions
961 */ 966 */
diff --git a/drivers/scsi/bfa/bfa_ioc_cb.c b/drivers/scsi/bfa/bfa_ioc_cb.c
index e3b928746674..453c2f5b5561 100644
--- a/drivers/scsi/bfa/bfa_ioc_cb.c
+++ b/drivers/scsi/bfa/bfa_ioc_cb.c
@@ -81,6 +81,29 @@ bfa_ioc_set_cb_hwif(struct bfa_ioc_s *ioc)
81static bfa_boolean_t 81static bfa_boolean_t
82bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) 82bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc)
83{ 83{
84 enum bfi_ioc_state alt_fwstate, cur_fwstate;
85 struct bfi_ioc_image_hdr_s fwhdr;
86
87 cur_fwstate = bfa_ioc_cb_get_cur_ioc_fwstate(ioc);
88 bfa_trc(ioc, cur_fwstate);
89 alt_fwstate = bfa_ioc_cb_get_alt_ioc_fwstate(ioc);
90 bfa_trc(ioc, alt_fwstate);
91
92 /*
93 * Uninit implies this is the only driver as of now.
94 */
95 if (cur_fwstate == BFI_IOC_UNINIT)
96 return BFA_TRUE;
97 /*
98 * Check if another driver with a different firmware is active
99 */
100 bfa_ioc_fwver_get(ioc, &fwhdr);
101 if (!bfa_ioc_fwver_cmp(ioc, &fwhdr) &&
102 alt_fwstate != BFI_IOC_DISABLED) {
103 bfa_trc(ioc, alt_fwstate);
104 return BFA_FALSE;
105 }
106
84 return BFA_TRUE; 107 return BFA_TRUE;
85} 108}
86 109
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 0467c349251a..157f6044a9bb 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -229,6 +229,18 @@ bfad_iocmd_iocfc_get_attr(struct bfad_s *bfad, void *cmd)
229} 229}
230 230
231int 231int
232bfad_iocmd_ioc_fw_sig_inv(struct bfad_s *bfad, void *cmd)
233{
234 struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd;
235 unsigned long flags;
236
237 spin_lock_irqsave(&bfad->bfad_lock, flags);
238 iocmd->status = bfa_ioc_fwsig_invalidate(&bfad->bfa.ioc);
239 spin_unlock_irqrestore(&bfad->bfad_lock, flags);
240 return 0;
241}
242
243int
232bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd) 244bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd)
233{ 245{
234 struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd; 246 struct bfa_bsg_iocfc_intr_s *iocmd = (struct bfa_bsg_iocfc_intr_s *)cmd;
@@ -2893,6 +2905,9 @@ bfad_iocmd_handler(struct bfad_s *bfad, unsigned int cmd, void *iocmd,
2893 case IOCMD_IOC_PCIFN_CFG: 2905 case IOCMD_IOC_PCIFN_CFG:
2894 rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd); 2906 rc = bfad_iocmd_ioc_get_pcifn_cfg(bfad, iocmd);
2895 break; 2907 break;
2908 case IOCMD_IOC_FW_SIG_INV:
2909 rc = bfad_iocmd_ioc_fw_sig_inv(bfad, iocmd);
2910 break;
2896 case IOCMD_PCIFN_CREATE: 2911 case IOCMD_PCIFN_CREATE:
2897 rc = bfad_iocmd_pcifn_create(bfad, iocmd); 2912 rc = bfad_iocmd_pcifn_create(bfad, iocmd);
2898 break; 2913 break;
diff --git a/drivers/scsi/bfa/bfad_bsg.h b/drivers/scsi/bfa/bfad_bsg.h
index 05f0fc9cf063..90abef691585 100644
--- a/drivers/scsi/bfa/bfad_bsg.h
+++ b/drivers/scsi/bfa/bfad_bsg.h
@@ -34,6 +34,7 @@ enum {
34 IOCMD_IOC_RESET_FWSTATS, 34 IOCMD_IOC_RESET_FWSTATS,
35 IOCMD_IOC_SET_ADAPTER_NAME, 35 IOCMD_IOC_SET_ADAPTER_NAME,
36 IOCMD_IOC_SET_PORT_NAME, 36 IOCMD_IOC_SET_PORT_NAME,
37 IOCMD_IOC_FW_SIG_INV,
37 IOCMD_IOCFC_GET_ATTR, 38 IOCMD_IOCFC_GET_ATTR,
38 IOCMD_IOCFC_SET_INTR, 39 IOCMD_IOCFC_SET_INTR,
39 IOCMD_PORT_ENABLE, 40 IOCMD_PORT_ENABLE,
diff --git a/drivers/scsi/bfa/bfi.h b/drivers/scsi/bfa/bfi.h
index 37bd2564e83b..bf05cc831cbc 100644
--- a/drivers/scsi/bfa/bfi.h
+++ b/drivers/scsi/bfa/bfi.h
@@ -46,6 +46,7 @@
46 */ 46 */
47#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */ 47#define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */
48#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32)) 48#define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32))
49#define BFI_FLASH_IMAGE_SZ 0x100000
49 50
50/* 51/*
51 * Msg header common to all msgs 52 * Msg header common to all msgs
@@ -324,7 +325,29 @@ struct bfi_ioc_getattr_reply_s {
324#define BFI_IOC_TRC_ENTS 256 325#define BFI_IOC_TRC_ENTS 256
325 326
326#define BFI_IOC_FW_SIGNATURE (0xbfadbfad) 327#define BFI_IOC_FW_SIGNATURE (0xbfadbfad)
328#define BFA_IOC_FW_INV_SIGN (0xdeaddead)
327#define BFI_IOC_MD5SUM_SZ 4 329#define BFI_IOC_MD5SUM_SZ 4
330
331struct bfi_ioc_fwver_s {
332#ifdef __BIG_ENDIAN
333 uint8_t patch;
334 uint8_t maint;
335 uint8_t minor;
336 uint8_t major;
337 uint8_t rsvd[2];
338 uint8_t build;
339 uint8_t phase;
340#else
341 uint8_t major;
342 uint8_t minor;
343 uint8_t maint;
344 uint8_t patch;
345 uint8_t phase;
346 uint8_t build;
347 uint8_t rsvd[2];
348#endif
349};
350
328struct bfi_ioc_image_hdr_s { 351struct bfi_ioc_image_hdr_s {
329 u32 signature; /* constant signature */ 352 u32 signature; /* constant signature */
330 u8 asic_gen; /* asic generation */ 353 u8 asic_gen; /* asic generation */
@@ -333,10 +356,18 @@ struct bfi_ioc_image_hdr_s {
333 u8 port1_mode; /* device mode for port 1 */ 356 u8 port1_mode; /* device mode for port 1 */
334 u32 exec; /* exec vector */ 357 u32 exec; /* exec vector */
335 u32 bootenv; /* fimware boot env */ 358 u32 bootenv; /* fimware boot env */
336 u32 rsvd_b[4]; 359 u32 rsvd_b[2];
360 struct bfi_ioc_fwver_s fwver;
337 u32 md5sum[BFI_IOC_MD5SUM_SZ]; 361 u32 md5sum[BFI_IOC_MD5SUM_SZ];
338}; 362};
339 363
364enum bfi_ioc_img_ver_cmp_e {
365 BFI_IOC_IMG_VER_INCOMP,
366 BFI_IOC_IMG_VER_OLD,
367 BFI_IOC_IMG_VER_SAME,
368 BFI_IOC_IMG_VER_BETTER
369};
370
340#define BFI_FWBOOT_DEVMODE_OFF 4 371#define BFI_FWBOOT_DEVMODE_OFF 4
341#define BFI_FWBOOT_TYPE_OFF 8 372#define BFI_FWBOOT_TYPE_OFF 8
342#define BFI_FWBOOT_ENV_OFF 12 373#define BFI_FWBOOT_ENV_OFF 12
@@ -346,6 +377,12 @@ struct bfi_ioc_image_hdr_s {
346 ((u32)(__p0_mode)) << 8 | \ 377 ((u32)(__p0_mode)) << 8 | \
347 ((u32)(__p1_mode))) 378 ((u32)(__p1_mode)))
348 379
380enum bfi_fwboot_type {
381 BFI_FWBOOT_TYPE_NORMAL = 0,
382 BFI_FWBOOT_TYPE_FLASH = 1,
383 BFI_FWBOOT_TYPE_MEMTEST = 2,
384};
385
349#define BFI_FWBOOT_TYPE_NORMAL 0 386#define BFI_FWBOOT_TYPE_NORMAL 0
350#define BFI_FWBOOT_TYPE_MEMTEST 2 387#define BFI_FWBOOT_TYPE_MEMTEST 2
351#define BFI_FWBOOT_ENV_OS 0 388#define BFI_FWBOOT_ENV_OS 0