diff options
author | Hayes Wang <hayeswang@realtek.com> | 2011-06-18 05:37:48 -0400 |
---|---|---|
committer | Francois Romieu <romieu@fr.zoreil.com> | 2011-06-18 05:40:33 -0400 |
commit | 960aee6c7d5951ac20c0227ad73bad56392f0afc (patch) | |
tree | 5558117cf58749141f4b8256b059548a1b4975c7 /drivers/net/r8169.c | |
parent | 1c361efb226d609a07403057a71557faf500b17a (diff) |
r8169: support new firmware format.
The new firmware format adds versioning as firmware for a specific
chipset appears to be subject to change. Current "legacy" format is
still supported.
Signed-off-by: Hayes Wang <hayeswang@realtek.com>
Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r-- | drivers/net/r8169.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 8fc9af246944..7074989d5f75 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
@@ -1754,18 +1754,52 @@ static void rtl_writephy_batch(struct rtl8169_private *tp, | |||
1754 | #define PHY_DELAY_MS 0xe0000000 | 1754 | #define PHY_DELAY_MS 0xe0000000 |
1755 | #define PHY_WRITE_ERI_WORD 0xf0000000 | 1755 | #define PHY_WRITE_ERI_WORD 0xf0000000 |
1756 | 1756 | ||
1757 | struct fw_info { | ||
1758 | u32 magic; | ||
1759 | char version[RTL_VER_SIZE]; | ||
1760 | __le32 fw_start; | ||
1761 | __le32 fw_len; | ||
1762 | u8 chksum; | ||
1763 | } __packed; | ||
1764 | |||
1757 | #define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) | 1765 | #define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) |
1758 | 1766 | ||
1759 | static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | 1767 | static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) |
1760 | { | 1768 | { |
1761 | const struct firmware *fw = rtl_fw->fw; | 1769 | const struct firmware *fw = rtl_fw->fw; |
1770 | struct fw_info *fw_info = (struct fw_info *)fw->data; | ||
1762 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | 1771 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; |
1763 | char *version = rtl_fw->version; | 1772 | char *version = rtl_fw->version; |
1764 | bool rc = false; | 1773 | bool rc = false; |
1765 | 1774 | ||
1766 | if (fw->size < FW_OPCODE_SIZE) | 1775 | if (fw->size < FW_OPCODE_SIZE) |
1767 | goto out; | 1776 | goto out; |
1768 | else { | 1777 | |
1778 | if (!fw_info->magic) { | ||
1779 | size_t i, size, start; | ||
1780 | u8 checksum = 0; | ||
1781 | |||
1782 | if (fw->size < sizeof(*fw_info)) | ||
1783 | goto out; | ||
1784 | |||
1785 | for (i = 0; i < fw->size; i++) | ||
1786 | checksum += fw->data[i]; | ||
1787 | if (checksum != 0) | ||
1788 | goto out; | ||
1789 | |||
1790 | start = le32_to_cpu(fw_info->fw_start); | ||
1791 | if (start > fw->size) | ||
1792 | goto out; | ||
1793 | |||
1794 | size = le32_to_cpu(fw_info->fw_len); | ||
1795 | if (size > (fw->size - start) / FW_OPCODE_SIZE) | ||
1796 | goto out; | ||
1797 | |||
1798 | memcpy(version, fw_info->version, RTL_VER_SIZE); | ||
1799 | |||
1800 | pa->code = (__le32 *)(fw->data + start); | ||
1801 | pa->size = size; | ||
1802 | } else { | ||
1769 | if (fw->size % FW_OPCODE_SIZE) | 1803 | if (fw->size % FW_OPCODE_SIZE) |
1770 | goto out; | 1804 | goto out; |
1771 | 1805 | ||