diff options
author | Ajit Khaparde <ajitk@serverengines.com> | 2009-09-03 23:12:16 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-07 04:56:38 -0400 |
commit | 84517482e19bc775de7b3b4e998dee2f506bc34e (patch) | |
tree | ae3491a5cf8891feef8c2896ef50758d763646f2 /drivers/net/benet/be_main.c | |
parent | 384824281caa9ac4b76664033416f1eac4a652fe (diff) |
be2net: Changes to support flashing of the be2 network adapter
Changes to support flashing of the be2 network adapter using the
request_firmware() & ethtool infrastructure. The trigger to flash the device
will come from ethtool utility. The driver will invoke request_firmware()
to start the flash process. The file containing the flash image is expected
to be available in /lib/firmware/
Signed-off-by: Ajit Khaparde <ajitk@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/benet/be_main.c')
-rw-r--r-- | drivers/net/benet/be_main.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index bac85f950394..d09106f2e084 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -1699,6 +1699,173 @@ static int be_close(struct net_device *netdev) | |||
1699 | return 0; | 1699 | return 0; |
1700 | } | 1700 | } |
1701 | 1701 | ||
1702 | #define FW_FILE_HDR_SIGN "ServerEngines Corp. " | ||
1703 | char flash_cookie[2][16] = {"*** SE FLAS", | ||
1704 | "H DIRECTORY *** "}; | ||
1705 | static int be_flash_image(struct be_adapter *adapter, | ||
1706 | const struct firmware *fw, | ||
1707 | struct be_dma_mem *flash_cmd, u32 flash_type) | ||
1708 | { | ||
1709 | int status; | ||
1710 | u32 flash_op, image_offset = 0, total_bytes, image_size = 0; | ||
1711 | int num_bytes; | ||
1712 | const u8 *p = fw->data; | ||
1713 | struct be_cmd_write_flashrom *req = flash_cmd->va; | ||
1714 | |||
1715 | switch (flash_type) { | ||
1716 | case FLASHROM_TYPE_ISCSI_ACTIVE: | ||
1717 | image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START; | ||
1718 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1719 | break; | ||
1720 | case FLASHROM_TYPE_ISCSI_BACKUP: | ||
1721 | image_offset = FLASH_iSCSI_BACKUP_IMAGE_START; | ||
1722 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1723 | break; | ||
1724 | case FLASHROM_TYPE_FCOE_FW_ACTIVE: | ||
1725 | image_offset = FLASH_FCoE_PRIMARY_IMAGE_START; | ||
1726 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1727 | break; | ||
1728 | case FLASHROM_TYPE_FCOE_FW_BACKUP: | ||
1729 | image_offset = FLASH_FCoE_BACKUP_IMAGE_START; | ||
1730 | image_size = FLASH_IMAGE_MAX_SIZE; | ||
1731 | break; | ||
1732 | case FLASHROM_TYPE_BIOS: | ||
1733 | image_offset = FLASH_iSCSI_BIOS_START; | ||
1734 | image_size = FLASH_BIOS_IMAGE_MAX_SIZE; | ||
1735 | break; | ||
1736 | case FLASHROM_TYPE_FCOE_BIOS: | ||
1737 | image_offset = FLASH_FCoE_BIOS_START; | ||
1738 | image_size = FLASH_BIOS_IMAGE_MAX_SIZE; | ||
1739 | break; | ||
1740 | case FLASHROM_TYPE_PXE_BIOS: | ||
1741 | image_offset = FLASH_PXE_BIOS_START; | ||
1742 | image_size = FLASH_BIOS_IMAGE_MAX_SIZE; | ||
1743 | break; | ||
1744 | default: | ||
1745 | return 0; | ||
1746 | } | ||
1747 | |||
1748 | p += sizeof(struct flash_file_hdr) + image_offset; | ||
1749 | if (p + image_size > fw->data + fw->size) | ||
1750 | return -1; | ||
1751 | |||
1752 | total_bytes = image_size; | ||
1753 | |||
1754 | while (total_bytes) { | ||
1755 | if (total_bytes > 32*1024) | ||
1756 | num_bytes = 32*1024; | ||
1757 | else | ||
1758 | num_bytes = total_bytes; | ||
1759 | total_bytes -= num_bytes; | ||
1760 | |||
1761 | if (!total_bytes) | ||
1762 | flash_op = FLASHROM_OPER_FLASH; | ||
1763 | else | ||
1764 | flash_op = FLASHROM_OPER_SAVE; | ||
1765 | memcpy(req->params.data_buf, p, num_bytes); | ||
1766 | p += num_bytes; | ||
1767 | status = be_cmd_write_flashrom(adapter, flash_cmd, | ||
1768 | flash_type, flash_op, num_bytes); | ||
1769 | if (status) { | ||
1770 | dev_err(&adapter->pdev->dev, | ||
1771 | "cmd to write to flash rom failed. type/op %d/%d\n", | ||
1772 | flash_type, flash_op); | ||
1773 | return -1; | ||
1774 | } | ||
1775 | yield(); | ||
1776 | } | ||
1777 | |||
1778 | return 0; | ||
1779 | } | ||
1780 | |||
1781 | int be_load_fw(struct be_adapter *adapter, u8 *func) | ||
1782 | { | ||
1783 | char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; | ||
1784 | const struct firmware *fw; | ||
1785 | struct flash_file_hdr *fhdr; | ||
1786 | struct flash_section_info *fsec = NULL; | ||
1787 | struct be_dma_mem flash_cmd; | ||
1788 | int status; | ||
1789 | const u8 *p; | ||
1790 | bool entry_found = false; | ||
1791 | int flash_type; | ||
1792 | char fw_ver[FW_VER_LEN]; | ||
1793 | char fw_cfg; | ||
1794 | |||
1795 | status = be_cmd_get_fw_ver(adapter, fw_ver); | ||
1796 | if (status) | ||
1797 | return status; | ||
1798 | |||
1799 | fw_cfg = *(fw_ver + 2); | ||
1800 | if (fw_cfg == '0') | ||
1801 | fw_cfg = '1'; | ||
1802 | strcpy(fw_file, func); | ||
1803 | |||
1804 | status = request_firmware(&fw, fw_file, &adapter->pdev->dev); | ||
1805 | if (status) | ||
1806 | goto fw_exit; | ||
1807 | |||
1808 | p = fw->data; | ||
1809 | fhdr = (struct flash_file_hdr *) p; | ||
1810 | if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) { | ||
1811 | dev_err(&adapter->pdev->dev, | ||
1812 | "Firmware(%s) load error (signature did not match)\n", | ||
1813 | fw_file); | ||
1814 | status = -1; | ||
1815 | goto fw_exit; | ||
1816 | } | ||
1817 | |||
1818 | dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); | ||
1819 | |||
1820 | p += sizeof(struct flash_file_hdr); | ||
1821 | while (p < (fw->data + fw->size)) { | ||
1822 | fsec = (struct flash_section_info *)p; | ||
1823 | if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) { | ||
1824 | entry_found = true; | ||
1825 | break; | ||
1826 | } | ||
1827 | p += 32; | ||
1828 | } | ||
1829 | |||
1830 | if (!entry_found) { | ||
1831 | status = -1; | ||
1832 | dev_err(&adapter->pdev->dev, | ||
1833 | "Flash cookie not found in firmware image\n"); | ||
1834 | goto fw_exit; | ||
1835 | } | ||
1836 | |||
1837 | flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; | ||
1838 | flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size, | ||
1839 | &flash_cmd.dma); | ||
1840 | if (!flash_cmd.va) { | ||
1841 | status = -ENOMEM; | ||
1842 | dev_err(&adapter->pdev->dev, | ||
1843 | "Memory allocation failure while flashing\n"); | ||
1844 | goto fw_exit; | ||
1845 | } | ||
1846 | |||
1847 | for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE; | ||
1848 | flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) { | ||
1849 | status = be_flash_image(adapter, fw, &flash_cmd, | ||
1850 | flash_type); | ||
1851 | if (status) | ||
1852 | break; | ||
1853 | } | ||
1854 | |||
1855 | pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va, | ||
1856 | flash_cmd.dma); | ||
1857 | if (status) { | ||
1858 | dev_err(&adapter->pdev->dev, "Firmware load error\n"); | ||
1859 | goto fw_exit; | ||
1860 | } | ||
1861 | |||
1862 | dev_info(&adapter->pdev->dev, "Firmware flashed succesfully\n"); | ||
1863 | |||
1864 | fw_exit: | ||
1865 | release_firmware(fw); | ||
1866 | return status; | ||
1867 | } | ||
1868 | |||
1702 | static struct net_device_ops be_netdev_ops = { | 1869 | static struct net_device_ops be_netdev_ops = { |
1703 | .ndo_open = be_open, | 1870 | .ndo_open = be_open, |
1704 | .ndo_stop = be_close, | 1871 | .ndo_stop = be_close, |