diff options
| -rw-r--r-- | drivers/net/ethernet/realtek/Makefile | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/realtek/r8169_firmware.c | 231 | ||||
| -rw-r--r-- | drivers/net/ethernet/realtek/r8169_firmware.h | 39 | ||||
| -rw-r--r-- | drivers/net/ethernet/realtek/r8169_main.c (renamed from drivers/net/ethernet/realtek/r8169.c) | 243 |
4 files changed, 274 insertions, 240 deletions
diff --git a/drivers/net/ethernet/realtek/Makefile b/drivers/net/ethernet/realtek/Makefile index 33be8c5ad0c9..d5304bad2372 100644 --- a/drivers/net/ethernet/realtek/Makefile +++ b/drivers/net/ethernet/realtek/Makefile | |||
| @@ -6,4 +6,5 @@ | |||
| 6 | obj-$(CONFIG_8139CP) += 8139cp.o | 6 | obj-$(CONFIG_8139CP) += 8139cp.o |
| 7 | obj-$(CONFIG_8139TOO) += 8139too.o | 7 | obj-$(CONFIG_8139TOO) += 8139too.o |
| 8 | obj-$(CONFIG_ATP) += atp.o | 8 | obj-$(CONFIG_ATP) += atp.o |
| 9 | r8169-objs += r8169_main.o r8169_firmware.o | ||
| 9 | obj-$(CONFIG_R8169) += r8169.o | 10 | obj-$(CONFIG_R8169) += r8169.o |
diff --git a/drivers/net/ethernet/realtek/r8169_firmware.c b/drivers/net/ethernet/realtek/r8169_firmware.c new file mode 100644 index 000000000000..8f54a2c832eb --- /dev/null +++ b/drivers/net/ethernet/realtek/r8169_firmware.c | |||
| @@ -0,0 +1,231 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | /* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw> | ||
| 5 | * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com> | ||
| 6 | * Copyright (c) a lot of people too. Please respect their work. | ||
| 7 | * | ||
| 8 | * See MAINTAINERS file for support contact information. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/delay.h> | ||
| 12 | #include <linux/firmware.h> | ||
| 13 | |||
| 14 | #include "r8169_firmware.h" | ||
| 15 | |||
| 16 | enum rtl_fw_opcode { | ||
| 17 | PHY_READ = 0x0, | ||
| 18 | PHY_DATA_OR = 0x1, | ||
| 19 | PHY_DATA_AND = 0x2, | ||
| 20 | PHY_BJMPN = 0x3, | ||
| 21 | PHY_MDIO_CHG = 0x4, | ||
| 22 | PHY_CLEAR_READCOUNT = 0x7, | ||
| 23 | PHY_WRITE = 0x8, | ||
| 24 | PHY_READCOUNT_EQ_SKIP = 0x9, | ||
| 25 | PHY_COMP_EQ_SKIPN = 0xa, | ||
| 26 | PHY_COMP_NEQ_SKIPN = 0xb, | ||
| 27 | PHY_WRITE_PREVIOUS = 0xc, | ||
| 28 | PHY_SKIPN = 0xd, | ||
| 29 | PHY_DELAY_MS = 0xe, | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct fw_info { | ||
| 33 | u32 magic; | ||
| 34 | char version[RTL_VER_SIZE]; | ||
| 35 | __le32 fw_start; | ||
| 36 | __le32 fw_len; | ||
| 37 | u8 chksum; | ||
| 38 | } __packed; | ||
| 39 | |||
| 40 | #define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) | ||
| 41 | |||
| 42 | static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw) | ||
| 43 | { | ||
| 44 | const struct firmware *fw = rtl_fw->fw; | ||
| 45 | struct fw_info *fw_info = (struct fw_info *)fw->data; | ||
| 46 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
| 47 | |||
| 48 | if (fw->size < FW_OPCODE_SIZE) | ||
| 49 | return false; | ||
| 50 | |||
| 51 | if (!fw_info->magic) { | ||
| 52 | size_t i, size, start; | ||
| 53 | u8 checksum = 0; | ||
| 54 | |||
| 55 | if (fw->size < sizeof(*fw_info)) | ||
| 56 | return false; | ||
| 57 | |||
| 58 | for (i = 0; i < fw->size; i++) | ||
| 59 | checksum += fw->data[i]; | ||
| 60 | if (checksum != 0) | ||
| 61 | return false; | ||
| 62 | |||
| 63 | start = le32_to_cpu(fw_info->fw_start); | ||
| 64 | if (start > fw->size) | ||
| 65 | return false; | ||
| 66 | |||
| 67 | size = le32_to_cpu(fw_info->fw_len); | ||
| 68 | if (size > (fw->size - start) / FW_OPCODE_SIZE) | ||
| 69 | return false; | ||
| 70 | |||
| 71 | strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE); | ||
| 72 | |||
| 73 | pa->code = (__le32 *)(fw->data + start); | ||
| 74 | pa->size = size; | ||
| 75 | } else { | ||
| 76 | if (fw->size % FW_OPCODE_SIZE) | ||
| 77 | return false; | ||
| 78 | |||
| 79 | strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE); | ||
| 80 | |||
| 81 | pa->code = (__le32 *)fw->data; | ||
| 82 | pa->size = fw->size / FW_OPCODE_SIZE; | ||
| 83 | } | ||
| 84 | |||
| 85 | return true; | ||
| 86 | } | ||
| 87 | |||
| 88 | static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw) | ||
| 89 | { | ||
| 90 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
| 91 | size_t index; | ||
| 92 | |||
| 93 | for (index = 0; index < pa->size; index++) { | ||
| 94 | u32 action = le32_to_cpu(pa->code[index]); | ||
| 95 | u32 regno = (action & 0x0fff0000) >> 16; | ||
| 96 | |||
| 97 | switch (action >> 28) { | ||
| 98 | case PHY_READ: | ||
| 99 | case PHY_DATA_OR: | ||
| 100 | case PHY_DATA_AND: | ||
| 101 | case PHY_MDIO_CHG: | ||
| 102 | case PHY_CLEAR_READCOUNT: | ||
| 103 | case PHY_WRITE: | ||
| 104 | case PHY_WRITE_PREVIOUS: | ||
| 105 | case PHY_DELAY_MS: | ||
| 106 | break; | ||
| 107 | |||
| 108 | case PHY_BJMPN: | ||
| 109 | if (regno > index) | ||
| 110 | goto out; | ||
| 111 | break; | ||
| 112 | case PHY_READCOUNT_EQ_SKIP: | ||
| 113 | if (index + 2 >= pa->size) | ||
| 114 | goto out; | ||
| 115 | break; | ||
| 116 | case PHY_COMP_EQ_SKIPN: | ||
| 117 | case PHY_COMP_NEQ_SKIPN: | ||
| 118 | case PHY_SKIPN: | ||
| 119 | if (index + 1 + regno >= pa->size) | ||
| 120 | goto out; | ||
| 121 | break; | ||
| 122 | |||
| 123 | default: | ||
| 124 | dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); | ||
| 125 | return false; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | return true; | ||
| 130 | out: | ||
| 131 | dev_err(rtl_fw->dev, "Out of range of firmware\n"); | ||
| 132 | return false; | ||
| 133 | } | ||
| 134 | |||
| 135 | void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) | ||
| 136 | { | ||
| 137 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
| 138 | rtl_fw_write_t fw_write = rtl_fw->phy_write; | ||
| 139 | rtl_fw_read_t fw_read = rtl_fw->phy_read; | ||
| 140 | int predata = 0, count = 0; | ||
| 141 | size_t index; | ||
| 142 | |||
| 143 | for (index = 0; index < pa->size; index++) { | ||
| 144 | u32 action = le32_to_cpu(pa->code[index]); | ||
| 145 | u32 data = action & 0x0000ffff; | ||
| 146 | u32 regno = (action & 0x0fff0000) >> 16; | ||
| 147 | enum rtl_fw_opcode opcode = action >> 28; | ||
| 148 | |||
| 149 | if (!action) | ||
| 150 | break; | ||
| 151 | |||
| 152 | switch (opcode) { | ||
| 153 | case PHY_READ: | ||
| 154 | predata = fw_read(tp, regno); | ||
| 155 | count++; | ||
| 156 | break; | ||
| 157 | case PHY_DATA_OR: | ||
| 158 | predata |= data; | ||
| 159 | break; | ||
| 160 | case PHY_DATA_AND: | ||
| 161 | predata &= data; | ||
| 162 | break; | ||
| 163 | case PHY_BJMPN: | ||
| 164 | index -= (regno + 1); | ||
| 165 | break; | ||
| 166 | case PHY_MDIO_CHG: | ||
| 167 | if (data == 0) { | ||
| 168 | fw_write = rtl_fw->phy_write; | ||
| 169 | fw_read = rtl_fw->phy_read; | ||
| 170 | } else if (data == 1) { | ||
| 171 | fw_write = rtl_fw->mac_mcu_write; | ||
| 172 | fw_read = rtl_fw->mac_mcu_read; | ||
| 173 | } | ||
| 174 | |||
| 175 | break; | ||
| 176 | case PHY_CLEAR_READCOUNT: | ||
| 177 | count = 0; | ||
| 178 | break; | ||
| 179 | case PHY_WRITE: | ||
| 180 | fw_write(tp, regno, data); | ||
| 181 | break; | ||
| 182 | case PHY_READCOUNT_EQ_SKIP: | ||
| 183 | if (count == data) | ||
| 184 | index++; | ||
| 185 | break; | ||
| 186 | case PHY_COMP_EQ_SKIPN: | ||
| 187 | if (predata == data) | ||
| 188 | index += regno; | ||
| 189 | break; | ||
| 190 | case PHY_COMP_NEQ_SKIPN: | ||
| 191 | if (predata != data) | ||
| 192 | index += regno; | ||
| 193 | break; | ||
| 194 | case PHY_WRITE_PREVIOUS: | ||
| 195 | fw_write(tp, regno, predata); | ||
| 196 | break; | ||
| 197 | case PHY_SKIPN: | ||
| 198 | index += regno; | ||
| 199 | break; | ||
| 200 | case PHY_DELAY_MS: | ||
| 201 | mdelay(data); | ||
| 202 | break; | ||
| 203 | } | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | void rtl_fw_release_firmware(struct rtl_fw *rtl_fw) | ||
| 208 | { | ||
| 209 | release_firmware(rtl_fw->fw); | ||
| 210 | } | ||
| 211 | |||
| 212 | int rtl_fw_request_firmware(struct rtl_fw *rtl_fw) | ||
| 213 | { | ||
| 214 | int rc; | ||
| 215 | |||
| 216 | rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); | ||
| 217 | if (rc < 0) | ||
| 218 | goto out; | ||
| 219 | |||
| 220 | if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) { | ||
| 221 | release_firmware(rtl_fw->fw); | ||
| 222 | rc = -EINVAL; | ||
| 223 | goto out; | ||
| 224 | } | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | out: | ||
| 228 | dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", | ||
| 229 | rtl_fw->fw_name, rc); | ||
| 230 | return rc; | ||
| 231 | } | ||
diff --git a/drivers/net/ethernet/realtek/r8169_firmware.h b/drivers/net/ethernet/realtek/r8169_firmware.h new file mode 100644 index 000000000000..7dc348ed8345 --- /dev/null +++ b/drivers/net/ethernet/realtek/r8169_firmware.h | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | ||
| 2 | /* r8169_firmware.h: RealTek 8169/8168/8101 ethernet driver. | ||
| 3 | * | ||
| 4 | * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw> | ||
| 5 | * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com> | ||
| 6 | * Copyright (c) a lot of people too. Please respect their work. | ||
| 7 | * | ||
| 8 | * See MAINTAINERS file for support contact information. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/device.h> | ||
| 12 | #include <linux/firmware.h> | ||
| 13 | |||
| 14 | struct rtl8169_private; | ||
| 15 | typedef void (*rtl_fw_write_t)(struct rtl8169_private *tp, int reg, int val); | ||
| 16 | typedef int (*rtl_fw_read_t)(struct rtl8169_private *tp, int reg); | ||
| 17 | |||
| 18 | #define RTL_VER_SIZE 32 | ||
| 19 | |||
| 20 | struct rtl_fw { | ||
| 21 | rtl_fw_write_t phy_write; | ||
| 22 | rtl_fw_read_t phy_read; | ||
| 23 | rtl_fw_write_t mac_mcu_write; | ||
| 24 | rtl_fw_read_t mac_mcu_read; | ||
| 25 | const struct firmware *fw; | ||
| 26 | const char *fw_name; | ||
| 27 | struct device *dev; | ||
| 28 | |||
| 29 | char version[RTL_VER_SIZE]; | ||
| 30 | |||
| 31 | struct rtl_fw_phy_action { | ||
| 32 | __le32 *code; | ||
| 33 | size_t size; | ||
| 34 | } phy_action; | ||
| 35 | }; | ||
| 36 | |||
| 37 | int rtl_fw_request_firmware(struct rtl_fw *rtl_fw); | ||
| 38 | void rtl_fw_release_firmware(struct rtl_fw *rtl_fw); | ||
| 39 | void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw); | ||
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169_main.c index 6a48d11af4ef..d34cc855f7db 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169_main.c | |||
| @@ -27,12 +27,13 @@ | |||
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
| 29 | #include <linux/pm_runtime.h> | 29 | #include <linux/pm_runtime.h> |
| 30 | #include <linux/firmware.h> | ||
| 31 | #include <linux/prefetch.h> | 30 | #include <linux/prefetch.h> |
| 32 | #include <linux/pci-aspm.h> | 31 | #include <linux/pci-aspm.h> |
| 33 | #include <linux/ipv6.h> | 32 | #include <linux/ipv6.h> |
| 34 | #include <net/ip6_checksum.h> | 33 | #include <net/ip6_checksum.h> |
| 35 | 34 | ||
| 35 | #include "r8169_firmware.h" | ||
| 36 | |||
| 36 | #define MODULENAME "r8169" | 37 | #define MODULENAME "r8169" |
| 37 | 38 | ||
| 38 | #define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" | 39 | #define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" |
| @@ -626,10 +627,6 @@ struct rtl8169_stats { | |||
| 626 | struct u64_stats_sync syncp; | 627 | struct u64_stats_sync syncp; |
| 627 | }; | 628 | }; |
| 628 | 629 | ||
| 629 | struct rtl8169_private; | ||
| 630 | typedef void (*rtl_fw_write_t)(struct rtl8169_private *tp, int reg, int val); | ||
| 631 | typedef int (*rtl_fw_read_t)(struct rtl8169_private *tp, int reg); | ||
| 632 | |||
| 633 | struct rtl8169_private { | 630 | struct rtl8169_private { |
| 634 | void __iomem *mmio_addr; /* memory map physical address */ | 631 | void __iomem *mmio_addr; /* memory map physical address */ |
| 635 | struct pci_dev *pci_dev; | 632 | struct pci_dev *pci_dev; |
| @@ -671,24 +668,7 @@ struct rtl8169_private { | |||
| 671 | u32 saved_wolopts; | 668 | u32 saved_wolopts; |
| 672 | 669 | ||
| 673 | const char *fw_name; | 670 | const char *fw_name; |
| 674 | struct rtl_fw { | 671 | struct rtl_fw *rtl_fw; |
| 675 | rtl_fw_write_t phy_write; | ||
| 676 | rtl_fw_read_t phy_read; | ||
| 677 | rtl_fw_write_t mac_mcu_write; | ||
| 678 | rtl_fw_read_t mac_mcu_read; | ||
| 679 | const struct firmware *fw; | ||
| 680 | const char *fw_name; | ||
| 681 | struct device *dev; | ||
| 682 | |||
| 683 | #define RTL_VER_SIZE 32 | ||
| 684 | |||
| 685 | char version[RTL_VER_SIZE]; | ||
| 686 | |||
| 687 | struct rtl_fw_phy_action { | ||
| 688 | __le32 *code; | ||
| 689 | size_t size; | ||
| 690 | } phy_action; | ||
| 691 | } *rtl_fw; | ||
| 692 | 672 | ||
| 693 | u32 ocp_base; | 673 | u32 ocp_base; |
| 694 | }; | 674 | }; |
| @@ -2300,203 +2280,6 @@ static void __rtl_writephy_batch(struct rtl8169_private *tp, | |||
| 2300 | 2280 | ||
| 2301 | #define rtl_writephy_batch(tp, a) __rtl_writephy_batch(tp, a, ARRAY_SIZE(a)) | 2281 | #define rtl_writephy_batch(tp, a) __rtl_writephy_batch(tp, a, ARRAY_SIZE(a)) |
| 2302 | 2282 | ||
| 2303 | enum rtl_fw_opcode { | ||
| 2304 | PHY_READ = 0x0, | ||
| 2305 | PHY_DATA_OR = 0x1, | ||
| 2306 | PHY_DATA_AND = 0x2, | ||
| 2307 | PHY_BJMPN = 0x3, | ||
| 2308 | PHY_MDIO_CHG = 0x4, | ||
| 2309 | PHY_CLEAR_READCOUNT = 0x7, | ||
| 2310 | PHY_WRITE = 0x8, | ||
| 2311 | PHY_READCOUNT_EQ_SKIP = 0x9, | ||
| 2312 | PHY_COMP_EQ_SKIPN = 0xa, | ||
| 2313 | PHY_COMP_NEQ_SKIPN = 0xb, | ||
| 2314 | PHY_WRITE_PREVIOUS = 0xc, | ||
| 2315 | PHY_SKIPN = 0xd, | ||
| 2316 | PHY_DELAY_MS = 0xe, | ||
| 2317 | }; | ||
| 2318 | |||
| 2319 | struct fw_info { | ||
| 2320 | u32 magic; | ||
| 2321 | char version[RTL_VER_SIZE]; | ||
| 2322 | __le32 fw_start; | ||
| 2323 | __le32 fw_len; | ||
| 2324 | u8 chksum; | ||
| 2325 | } __packed; | ||
| 2326 | |||
| 2327 | #define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) | ||
| 2328 | |||
| 2329 | static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw) | ||
| 2330 | { | ||
| 2331 | const struct firmware *fw = rtl_fw->fw; | ||
| 2332 | struct fw_info *fw_info = (struct fw_info *)fw->data; | ||
| 2333 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
| 2334 | |||
| 2335 | if (fw->size < FW_OPCODE_SIZE) | ||
| 2336 | return false; | ||
| 2337 | |||
| 2338 | if (!fw_info->magic) { | ||
| 2339 | size_t i, size, start; | ||
| 2340 | u8 checksum = 0; | ||
| 2341 | |||
| 2342 | if (fw->size < sizeof(*fw_info)) | ||
| 2343 | return false; | ||
| 2344 | |||
| 2345 | for (i = 0; i < fw->size; i++) | ||
| 2346 | checksum += fw->data[i]; | ||
| 2347 | if (checksum != 0) | ||
| 2348 | return false; | ||
| 2349 | |||
| 2350 | start = le32_to_cpu(fw_info->fw_start); | ||
| 2351 | if (start > fw->size) | ||
| 2352 | return false; | ||
| 2353 | |||
| 2354 | size = le32_to_cpu(fw_info->fw_len); | ||
| 2355 | if (size > (fw->size - start) / FW_OPCODE_SIZE) | ||
| 2356 | return false; | ||
| 2357 | |||
| 2358 | strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE); | ||
| 2359 | |||
| 2360 | pa->code = (__le32 *)(fw->data + start); | ||
| 2361 | pa->size = size; | ||
| 2362 | } else { | ||
| 2363 | if (fw->size % FW_OPCODE_SIZE) | ||
| 2364 | return false; | ||
| 2365 | |||
| 2366 | strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE); | ||
| 2367 | |||
| 2368 | pa->code = (__le32 *)fw->data; | ||
| 2369 | pa->size = fw->size / FW_OPCODE_SIZE; | ||
| 2370 | } | ||
| 2371 | |||
| 2372 | return true; | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw) | ||
| 2376 | { | ||
| 2377 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
| 2378 | size_t index; | ||
| 2379 | |||
| 2380 | for (index = 0; index < pa->size; index++) { | ||
| 2381 | u32 action = le32_to_cpu(pa->code[index]); | ||
| 2382 | u32 regno = (action & 0x0fff0000) >> 16; | ||
| 2383 | |||
| 2384 | switch (action >> 28) { | ||
| 2385 | case PHY_READ: | ||
| 2386 | case PHY_DATA_OR: | ||
| 2387 | case PHY_DATA_AND: | ||
| 2388 | case PHY_MDIO_CHG: | ||
| 2389 | case PHY_CLEAR_READCOUNT: | ||
| 2390 | case PHY_WRITE: | ||
| 2391 | case PHY_WRITE_PREVIOUS: | ||
| 2392 | case PHY_DELAY_MS: | ||
| 2393 | break; | ||
| 2394 | |||
| 2395 | case PHY_BJMPN: | ||
| 2396 | if (regno > index) | ||
| 2397 | goto out; | ||
| 2398 | break; | ||
| 2399 | case PHY_READCOUNT_EQ_SKIP: | ||
| 2400 | if (index + 2 >= pa->size) | ||
| 2401 | goto out; | ||
| 2402 | break; | ||
| 2403 | case PHY_COMP_EQ_SKIPN: | ||
| 2404 | case PHY_COMP_NEQ_SKIPN: | ||
| 2405 | case PHY_SKIPN: | ||
| 2406 | if (index + 1 + regno >= pa->size) | ||
| 2407 | goto out; | ||
| 2408 | break; | ||
| 2409 | |||
| 2410 | default: | ||
| 2411 | dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); | ||
| 2412 | return false; | ||
| 2413 | } | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | return true; | ||
| 2417 | out: | ||
| 2418 | dev_err(rtl_fw->dev, "Out of range of firmware\n"); | ||
| 2419 | return false; | ||
| 2420 | } | ||
| 2421 | |||
| 2422 | static void rtl_fw_write_firmware(struct rtl8169_private *tp, | ||
| 2423 | struct rtl_fw *rtl_fw) | ||
| 2424 | { | ||
| 2425 | struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; | ||
| 2426 | rtl_fw_write_t fw_write = rtl_fw->phy_write; | ||
| 2427 | rtl_fw_read_t fw_read = rtl_fw->phy_read; | ||
| 2428 | int predata = 0, count = 0; | ||
| 2429 | size_t index; | ||
| 2430 | |||
| 2431 | for (index = 0; index < pa->size; index++) { | ||
| 2432 | u32 action = le32_to_cpu(pa->code[index]); | ||
| 2433 | u32 data = action & 0x0000ffff; | ||
| 2434 | u32 regno = (action & 0x0fff0000) >> 16; | ||
| 2435 | enum rtl_fw_opcode opcode = action >> 28; | ||
| 2436 | |||
| 2437 | if (!action) | ||
| 2438 | break; | ||
| 2439 | |||
| 2440 | switch (opcode) { | ||
| 2441 | case PHY_READ: | ||
| 2442 | predata = fw_read(tp, regno); | ||
| 2443 | count++; | ||
| 2444 | break; | ||
| 2445 | case PHY_DATA_OR: | ||
| 2446 | predata |= data; | ||
| 2447 | break; | ||
| 2448 | case PHY_DATA_AND: | ||
| 2449 | predata &= data; | ||
| 2450 | break; | ||
| 2451 | case PHY_BJMPN: | ||
| 2452 | index -= (regno + 1); | ||
| 2453 | break; | ||
| 2454 | case PHY_MDIO_CHG: | ||
| 2455 | if (data == 0) { | ||
| 2456 | fw_write = rtl_fw->phy_write; | ||
| 2457 | fw_read = rtl_fw->phy_read; | ||
| 2458 | } else if (data == 1) { | ||
| 2459 | fw_write = rtl_fw->mac_mcu_write; | ||
| 2460 | fw_read = rtl_fw->mac_mcu_read; | ||
| 2461 | } | ||
| 2462 | |||
| 2463 | break; | ||
| 2464 | case PHY_CLEAR_READCOUNT: | ||
| 2465 | count = 0; | ||
| 2466 | break; | ||
| 2467 | case PHY_WRITE: | ||
| 2468 | fw_write(tp, regno, data); | ||
| 2469 | break; | ||
| 2470 | case PHY_READCOUNT_EQ_SKIP: | ||
| 2471 | if (count == data) | ||
| 2472 | index++; | ||
| 2473 | break; | ||
| 2474 | case PHY_COMP_EQ_SKIPN: | ||
| 2475 | if (predata == data) | ||
| 2476 | index += regno; | ||
| 2477 | break; | ||
| 2478 | case PHY_COMP_NEQ_SKIPN: | ||
| 2479 | if (predata != data) | ||
| 2480 | index += regno; | ||
| 2481 | break; | ||
| 2482 | case PHY_WRITE_PREVIOUS: | ||
| 2483 | fw_write(tp, regno, predata); | ||
| 2484 | break; | ||
| 2485 | case PHY_SKIPN: | ||
| 2486 | index += regno; | ||
| 2487 | break; | ||
| 2488 | case PHY_DELAY_MS: | ||
| 2489 | mdelay(data); | ||
| 2490 | break; | ||
| 2491 | } | ||
| 2492 | } | ||
| 2493 | } | ||
| 2494 | |||
| 2495 | static void rtl_fw_release_firmware(struct rtl_fw *rtl_fw) | ||
| 2496 | { | ||
| 2497 | release_firmware(rtl_fw->fw); | ||
| 2498 | } | ||
| 2499 | |||
| 2500 | static void rtl_release_firmware(struct rtl8169_private *tp) | 2283 | static void rtl_release_firmware(struct rtl8169_private *tp) |
| 2501 | { | 2284 | { |
| 2502 | if (tp->rtl_fw) { | 2285 | if (tp->rtl_fw) { |
| @@ -4254,26 +4037,6 @@ static void rtl_hw_reset(struct rtl8169_private *tp) | |||
| 4254 | rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); | 4037 | rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); |
| 4255 | } | 4038 | } |
| 4256 | 4039 | ||
| 4257 | static int rtl_fw_request_firmware(struct rtl_fw *rtl_fw) | ||
| 4258 | { | ||
| 4259 | int rc; | ||
| 4260 | |||
| 4261 | rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); | ||
| 4262 | if (rc < 0) | ||
| 4263 | goto out; | ||
| 4264 | |||
| 4265 | if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) { | ||
| 4266 | release_firmware(rtl_fw->fw); | ||
| 4267 | goto out; | ||
| 4268 | } | ||
| 4269 | |||
| 4270 | return 0; | ||
| 4271 | out: | ||
| 4272 | dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", | ||
| 4273 | rtl_fw->fw_name, rc); | ||
| 4274 | return rc; | ||
| 4275 | } | ||
| 4276 | |||
| 4277 | static void rtl_request_firmware(struct rtl8169_private *tp) | 4040 | static void rtl_request_firmware(struct rtl8169_private *tp) |
| 4278 | { | 4041 | { |
| 4279 | struct rtl_fw *rtl_fw; | 4042 | struct rtl_fw *rtl_fw; |
