diff options
-rw-r--r-- | drivers/scsi/bfa/bfa_defs.h | 1 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.c | 727 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc.h | 7 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfa_ioc_cb.c | 23 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.c | 15 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfad_bsg.h | 1 | ||||
-rw-r--r-- | drivers/scsi/bfa/bfi.h | 39 |
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 | ||
25 | BFA_TRC_FILE(CNA, IOC); | 26 | BFA_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); | |||
102 | static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); | 111 | static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); |
103 | static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc); | 112 | static void bfa_ioc_fail_notify(struct bfa_ioc_s *ioc); |
104 | static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); | 113 | static void bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc); |
114 | static 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); | ||
117 | static 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 | */ |
1459 | bfa_boolean_t | 1474 | bfa_boolean_t |
1460 | bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) | 1475 | bfa_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) | |||
1485 | static bfa_boolean_t | 1514 | static bfa_boolean_t |
1486 | bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc, u32 boot_env) | 1515 | bfa_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 | ||
1530 | static bfa_boolean_t | ||
1531 | bfa_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 | */ | ||
1547 | static bfa_boolean_t | ||
1548 | bfa_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 | |||
1572 | static bfa_boolean_t | ||
1573 | bfa_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 | |||
1581 | static 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 | */ | ||
1593 | static enum bfi_ioc_img_ver_cmp_e | ||
1594 | bfa_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 | |||
1640 | bfa_status_t | ||
1641 | bfa_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 | |||
1649 | static enum bfi_ioc_img_ver_cmp_e | ||
1650 | bfa_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 | */ | ||
1672 | bfa_status_t | ||
1673 | bfa_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 | ||
1587 | static void | 1770 | static 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 | */ |
1687 | static void | 1870 | static bfa_status_t |
1688 | bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, | 1871 | bfa_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 | */ |
2005 | void | 2225 | bfa_status_t |
2006 | bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_env) | 2226 | bfa_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 | |||
6675 | enum 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 | */ | ||
6683 | enum 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 | */ | ||
6698 | union 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 | */ | ||
6722 | union 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 | */ | ||
6748 | union 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 | */ | ||
6764 | static void | ||
6765 | bfa_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 | |||
6779 | static void | ||
6780 | bfa_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 | |||
6789 | static int | ||
6790 | bfa_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 | */ | ||
6811 | static u32 | ||
6812 | bfa_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 | */ | ||
6850 | static u32 | ||
6851 | bfa_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 | */ | ||
6898 | static u32 | ||
6899 | bfa_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 | */ | ||
6941 | static u32 | ||
6942 | bfa_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 | */ | ||
6958 | static void | ||
6959 | bfa_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 | |||
6991 | static int | ||
6992 | bfa_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 | |||
7001 | bfa_status_t | ||
7002 | bfa_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 | |||
7014 | void | ||
7015 | bfa_flash_sem_put(void __iomem *bar) | ||
7016 | { | ||
7017 | writel(0, (bar + FLASH_SEM_LOCK_REG)); | ||
7018 | } | ||
7019 | |||
7020 | bfa_status_t | ||
7021 | bfa_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); |
516 | void bfa_flash_memclaim(struct bfa_flash_s *flash, | 516 | void 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); |
518 | bfa_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); | |||
888 | void bfa_ioc_disable(struct bfa_ioc_s *ioc); | 890 | void bfa_ioc_disable(struct bfa_ioc_s *ioc); |
889 | bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc); | 891 | bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc); |
890 | 892 | ||
891 | void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, | 893 | bfa_status_t bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, |
892 | u32 boot_env); | 894 | u32 boot_env); |
893 | void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg); | 895 | void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg); |
894 | void bfa_ioc_error_isr(struct bfa_ioc_s *ioc); | 896 | void 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); |
920 | bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf, | 922 | bfa_status_t bfa_ioc_debug_fwcore(struct bfa_ioc_s *ioc, void *buf, |
921 | u32 *offset, int *buflen); | 923 | u32 *offset, int *buflen); |
924 | bfa_status_t bfa_ioc_fwsig_invalidate(struct bfa_ioc_s *ioc); | ||
922 | bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg); | 925 | bfa_boolean_t bfa_ioc_sem_get(void __iomem *sem_reg); |
923 | void bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, | 926 | void 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, | |||
956 | bfa_status_t bfa_ablk_optrom_dis(struct bfa_ablk_s *ablk, | 959 | bfa_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 | ||
962 | bfa_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) | |||
81 | static bfa_boolean_t | 81 | static bfa_boolean_t |
82 | bfa_ioc_cb_firmware_lock(struct bfa_ioc_s *ioc) | 82 | bfa_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 | ||
231 | int | 231 | int |
232 | bfad_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 | |||
243 | int | ||
232 | bfad_iocmd_iocfc_set_intr(struct bfad_s *bfad, void *cmd) | 244 | bfad_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 | |||
331 | struct 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 | |||
328 | struct bfi_ioc_image_hdr_s { | 351 | struct 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 | ||
364 | enum 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 | ||
380 | enum 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 |