[PATCH net-next v4 6/8] r8152: add TGPHY register access for RTL8157 and RTL8159
From: Chih Kai Hsu <hidden>
Date: 2026-09-17 07:07:20
Also in:
linux-usb, lkml
Subsystem:
networking drivers, the rest, usb networking drivers · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
RTL8157 and RTL8159 read/write PHY registers through a new TGPHY command interface (USB_TGPHY_ADDR/DATA/CMD) instead of the OCP-base-switching path used by every earlier chip: ocp_reg_read/ write() reprograms PLA_OCP_GPHY_BASE whenever the top nibble of the requested address changes. Support for these chips needs a second PHY access path, so ocp_reg_read()/ocp_reg_write() can no longer hardcode the single implementation shared by all versions. Rename the existing implementations to r8152_phy_read()/ r8152_phy_write(), and turn ocp_reg_read()/ocp_reg_write() into dispatch wrappers over new tp->rtl_ops.phy_read/phy_write function pointers, set per-chip in rtl_ops_init(). Add r8157_phy_read()/ r8157_phy_write(), built on rtl_tgphy_access(), which polls TGPHY_CMD_BUSY the same way wait_autoload_done() polls for autoload completion. Unlike wait_autoload_done() though, rtl_tgphy_access() aborts the remaining steps of the access on a busy-wait failure instead of falling through: USB_TGPHY_ADDR/CMD/DATA form a single hardware transaction gated by TGPHY_CMD_BUSY, not a sequence of independent register writes, so proceeding past an unresolved busy bit would race the in-flight command rather than just leaving an unrelated register unset. Since ocp_reg_read()/ocp_reg_write() can now fail on a TGPHY timeout, every helper built on top of them (sram_read/write, sram2_read/write, the ocp_reg_*_bits and MDIO bit helpers) is converted from void/raw- value returns to int, propagating the failure to callers instead of silently operating on stale data. Signed-off-by: Chih Kai Hsu <redacted> --- drivers/net/usb/r8152.c | 430 +++++++++++++++++++++++++++++++--------- 1 file changed, 334 insertions(+), 96 deletions(-)
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index f44dcb88b5c6a..3473061af129a 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c@@ -162,6 +162,9 @@ #define USB_ADV_ADDR 0xd5d6 #define USB_ADV_DATA 0xd5d8 #define USB_ADV_CMD 0xd5dc +#define USB_TGPHY_ADDR 0xd630 +#define USB_TGPHY_DATA 0xd632 +#define USB_TGPHY_CMD 0xd634 #define USB_UPS_CTRL 0xd800 #define USB_POWER_CUT 0xd80a #define USB_MISC_0 0xd81a
@@ -511,6 +514,10 @@ #define ADV_CMD_WR BIT(1) #define ADV_CMD_IP BIT(2) +/* USB_TGPHY_CMD */ +#define TGPHY_CMD_BUSY BIT(0) +#define TGPHY_CMD_WR BIT(1) + /* USB_UPS_CTRL */ #define POWER_CUT 0x0100
@@ -959,6 +966,8 @@ struct r8152 { void (*hw_phy_cfg)(struct r8152 *tp); void (*autosuspend_en)(struct r8152 *tp, bool enable); void (*change_mtu)(struct r8152 *tp); + int (*phy_read)(struct r8152 *tp, u16 addr, u16 *data); + int (*phy_write)(struct r8152 *tp, u16 addr, u16 data); } rtl_ops; struct ups_info {
@@ -1638,7 +1647,7 @@ static void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data) generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type); } -static u16 ocp_reg_read(struct r8152 *tp, u16 addr) +static int r8152_phy_read(struct r8152 *tp, u16 addr, u16 *data) { u16 ocp_base, ocp_index;
@@ -1649,10 +1658,12 @@ static u16 ocp_reg_read(struct r8152 *tp, u16 addr) } ocp_index = (addr & 0x0fff) | 0xb000; - return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index); + *data = ocp_read_word(tp, MCU_TYPE_PLA, ocp_index); + + return 0; } -static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) +static int r8152_phy_write(struct r8152 *tp, u16 addr, u16 data) { u16 ocp_base, ocp_index;
@@ -1664,16 +1675,33 @@ static void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) ocp_index = (addr & 0x0fff) | 0xb000; ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data); + + return 0; +} + +static int ocp_reg_read(struct r8152 *tp, u16 addr, u16 *data) +{ + return tp->rtl_ops.phy_read(tp, addr, data); +} + +static int ocp_reg_write(struct r8152 *tp, u16 addr, u16 data) +{ + return tp->rtl_ops.phy_write(tp, addr, data); } -static inline void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value) +static inline int r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value) { - ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value); + return ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value); } static inline int r8152_mdio_read(struct r8152 *tp, u32 reg_addr) { - return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2); + u16 data; + int ret; + + ret = ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2, &data); + + return ret < 0 ? ret : data; } static int wait_cmd_ready(struct r8152 *tp, u16 cmd)
@@ -1792,16 +1820,32 @@ static int rtl_ip_set_bits(struct r8152 *tp, u16 addr, u32 set) return rtl_ip_w0w1(tp, addr, 0, set); } -static void sram_write(struct r8152 *tp, u16 addr, u16 data) +static int sram_write(struct r8152 *tp, u16 addr, u16 data) { - ocp_reg_write(tp, OCP_SRAM_ADDR, addr); + int ret; + + ret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr); + if (ret < 0) + goto out; + ocp_reg_write(tp, OCP_SRAM_DATA, data); + +out: + return ret; } -static u16 sram_read(struct r8152 *tp, u16 addr) +static int sram_read(struct r8152 *tp, u16 addr, u16 *data) { - ocp_reg_write(tp, OCP_SRAM_ADDR, addr); - return ocp_reg_read(tp, OCP_SRAM_DATA); + int ret; + + ret = ocp_reg_write(tp, OCP_SRAM_ADDR, addr); + if (ret < 0) + goto out; + + ret = ocp_reg_read(tp, OCP_SRAM_DATA, data); + +out: + return ret; } static int read_mii_word(struct net_device *netdev, int phy_id, int reg)
@@ -1906,100 +1950,217 @@ static void ocp_byte_set_bits(struct r8152 *tp, u16 type, u16 index, u8 set) ocp_byte_w0w1(tp, type, index, 0, set); } -static void ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) +static int ocp_reg_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) { u16 data; + int ret; + + ret = ocp_reg_read(tp, addr, &data); + if (ret < 0) + goto out; - data = ocp_reg_read(tp, addr); data = (data & ~clear) | set; - ocp_reg_write(tp, addr, data); + ret = ocp_reg_write(tp, addr, data); + +out: + return ret; } -static void ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear) +static int ocp_reg_clr_bits(struct r8152 *tp, u16 addr, u16 clear) { - ocp_reg_w0w1(tp, addr, clear, 0); + return ocp_reg_w0w1(tp, addr, clear, 0); } -static void ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set) +static int ocp_reg_set_bits(struct r8152 *tp, u16 addr, u16 set) { - ocp_reg_w0w1(tp, addr, 0, set); + return ocp_reg_w0w1(tp, addr, 0, set); } -static void sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) +static int sram_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) { u16 data; + int ret; + + ret = sram_read(tp, addr, &data); + if (ret < 0) + goto out; - data = sram_read(tp, addr); data = (data & ~clear) | set; - ocp_reg_write(tp, OCP_SRAM_DATA, data); + ret = ocp_reg_write(tp, OCP_SRAM_DATA, data); + +out: + return ret; } -static void sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear) +static int sram_clr_bits(struct r8152 *tp, u16 addr, u16 clear) { - sram_write_w0w1(tp, addr, clear, 0); + return sram_write_w0w1(tp, addr, clear, 0); } -static void sram_set_bits(struct r8152 *tp, u16 addr, u16 set) +static int sram_set_bits(struct r8152 *tp, u16 addr, u16 set) { - sram_write_w0w1(tp, addr, 0, set); + return sram_write_w0w1(tp, addr, 0, set); } -static void sram2_write(struct r8152 *tp, u16 addr, u16 data) +static int sram2_write(struct r8152 *tp, u16 addr, u16 data) { - ocp_reg_write(tp, OCP_SRAM2_ADDR, addr); - ocp_reg_write(tp, OCP_SRAM2_DATA, data); + int ret; + + ret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr); + if (ret < 0) + goto out; + + ret = ocp_reg_write(tp, OCP_SRAM2_DATA, data); + +out: + return ret; } -static u16 sram2_read(struct r8152 *tp, u16 addr) +static int sram2_read(struct r8152 *tp, u16 addr, u16 *data) { - ocp_reg_write(tp, OCP_SRAM2_ADDR, addr); - return ocp_reg_read(tp, OCP_SRAM2_DATA); + int ret; + + ret = ocp_reg_write(tp, OCP_SRAM2_ADDR, addr); + if (ret < 0) + goto out; + + ret = ocp_reg_read(tp, OCP_SRAM2_DATA, data); + +out: + return ret; } -static void sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) +static int sram2_write_w0w1(struct r8152 *tp, u16 addr, u16 clear, u16 set) { u16 data; + int ret; + + ret = sram2_read(tp, addr, &data); + if (ret < 0) + goto out; - data = sram2_read(tp, addr); data = (data & ~clear) | set; - ocp_reg_write(tp, OCP_SRAM2_DATA, data); + ret = ocp_reg_write(tp, OCP_SRAM2_DATA, data); + +out: + return ret; } -static void sram2_set_bits(struct r8152 *tp, u16 addr, u16 set) +static int sram2_set_bits(struct r8152 *tp, u16 addr, u16 set) { - sram2_write_w0w1(tp, addr, 0, set); + return sram2_write_w0w1(tp, addr, 0, set); } -static void sram2_clr_bits(struct r8152 *tp, u16 addr, u16 clear) +static int sram2_clr_bits(struct r8152 *tp, u16 addr, u16 clear) { - sram2_write_w0w1(tp, addr, clear, 0); + return sram2_write_w0w1(tp, addr, clear, 0); } -static void r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear) +static int r8152_mdio_clr_bit(struct r8152 *tp, u16 addr, u16 clear) { int data; data = r8152_mdio_read(tp, addr); - r8152_mdio_write(tp, addr, data & ~clear); + if (data < 0) + goto out; + + data = r8152_mdio_write(tp, addr, data & ~clear); + +out: + return data; } -static void r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set) +static int r8152_mdio_set_bit(struct r8152 *tp, u16 addr, u16 set) { int data; data = r8152_mdio_read(tp, addr); - r8152_mdio_write(tp, addr, data | set); + if (data < 0) + goto out; + + data = r8152_mdio_write(tp, addr, data | set); + +out: + return data; } static int r8152_mdio_test_and_clr_bit(struct r8152 *tp, u16 addr, u16 clear) { - int data; + int data, ret; - data = r8152_mdio_read(tp, addr); - if (data & clear) - r8152_mdio_write(tp, addr, data & ~clear); + ret = r8152_mdio_read(tp, addr); + if (ret < 0) + goto out; - return data & clear; + data = ret; + if (data & clear) { + ret = r8152_mdio_write(tp, addr, data & ~clear); + if (ret < 0) + goto out; + } + + ret = !!(data & clear); + +out: + return ret; +} + +static int wait_tgphy_cmd_ready(struct r8152 *tp) +{ + u16 ocp_data; + int ret; + + ret = read_poll_timeout(ocp_read_word, ocp_data, + test_bit(RTL8152_INACCESSIBLE, &tp->flags) || + !(ocp_data & TGPHY_CMD_BUSY), + 2000, 20000, false, tp, + MCU_TYPE_USB, USB_TGPHY_CMD); + + if (ret) + dev_err(&tp->intf->dev, "TGPHY cmd busy timeout\n"); + + return test_bit(RTL8152_INACCESSIBLE, &tp->flags) ? -ENODEV : ret; +} + +static int rtl_tgphy_access(struct r8152 *tp, u16 addr, u16 *data, bool write) +{ + u16 cmd = 0; + int ret; + + ret = wait_tgphy_cmd_ready(tp); + if (ret < 0) + goto out; + + if (write) { + cmd |= TGPHY_CMD_WR; + ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA, *data); + } + + ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_ADDR, addr); + + cmd |= TGPHY_CMD_BUSY; + ocp_write_word(tp, MCU_TYPE_USB, USB_TGPHY_CMD, cmd); + + if (!write) { + ret = wait_tgphy_cmd_ready(tp); + if (ret < 0) + goto out; + + *data = ocp_read_word(tp, MCU_TYPE_USB, USB_TGPHY_DATA); + } + +out: + return ret; +} + +static int r8157_phy_read(struct r8152 *tp, u16 addr, u16 *data) +{ + return rtl_tgphy_access(tp, addr, data, false); +} + +static int r8157_phy_write(struct r8152 *tp, u16 addr, u16 data) +{ + return rtl_tgphy_access(tp, addr, &data, true); } static int
@@ -4177,11 +4338,13 @@ static void r8153b_green_en(struct r8152 *tp, bool enable) static u16 r8153_phy_status(struct r8152 *tp, u16 desired) { - u16 data; + u16 data = 0; int i; for (i = 0; i < 500; i++) { - data = ocp_reg_read(tp, OCP_PHY_STATUS); + if (ocp_reg_read(tp, OCP_PHY_STATUS, &data) < 0) + break; + data &= PHY_STAT_MASK; if (desired) { if (data == desired)
@@ -4587,7 +4750,8 @@ static inline void rtl_reset_ocp_base(struct r8152 *tp) static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) { u16 check; - int i; + u16 ocp_data = 0; + int i, ret; if (request) { ocp_reg_set_bits(tp, OCP_PHY_PATCH_CMD, PATCH_REQUEST);
@@ -4598,25 +4762,23 @@ static int rtl_phy_patch_request(struct r8152 *tp, bool request, bool wait) } for (i = 0; wait && i < 5000; i++) { - u32 ocp_data; - if (test_bit(RTL8152_INACCESSIBLE, &tp->flags)) return -ENODEV; usleep_range(1000, 2000); - ocp_data = ocp_reg_read(tp, OCP_PHY_PATCH_STAT); - if ((ocp_data & PATCH_READY) ^ check) + ret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, &ocp_data); + if (ret < 0 || (ocp_data & PATCH_READY) ^ check) break; } - if (request && wait && - !(ocp_reg_read(tp, OCP_PHY_PATCH_STAT) & PATCH_READY)) { + ret = ocp_reg_read(tp, OCP_PHY_PATCH_STAT, &ocp_data); + if (request && wait && (ret < 0 || !(ocp_data & PATCH_READY))) { dev_err(&tp->intf->dev, "PHY patch request fail\n"); rtl_phy_patch_request(tp, false, false); return -ETIME; - } else { - return 0; } + + return 0; } static void rtl_patch_key_set(struct r8152 *tp, u16 key_addr, u16 patch_key)
@@ -5331,10 +5493,12 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, { u32 len; u8 *data; + u16 ver = 0; rtl_reset_ocp_base(tp); - if (sram_read(tp, SRAM_GPHY_FW_VER) >= __le16_to_cpu(phy->version)) { + sram_read(tp, SRAM_GPHY_FW_VER, &ver); + if (ver >= __le16_to_cpu(phy->version)) { dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); return; }
@@ -5381,7 +5545,9 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, rtl_phy_patch_request(tp, false, wait); - if (sram_read(tp, SRAM_GPHY_FW_VER) == __le16_to_cpu(phy->version)) + ver = 0; + sram_read(tp, SRAM_GPHY_FW_VER, &ver); + if (ver == __le16_to_cpu(phy->version)) dev_dbg(&tp->intf->dev, "successfully applied %s\n", phy->info); else dev_err(&tp->intf->dev, "ram code speedup mode fail\n");
@@ -5389,14 +5555,15 @@ static void rtl_ram_code_speed_up(struct r8152 *tp, struct fw_phy_speed_up *phy, static int rtl8152_fw_phy_ver(struct r8152 *tp, struct fw_phy_ver *phy_ver) { - u16 ver_addr, ver; + u16 ver_addr, ver, cur_ver = 0; ver_addr = __le16_to_cpu(phy_ver->ver.addr); ver = __le16_to_cpu(phy_ver->ver.data); rtl_reset_ocp_base(tp); - if (sram_read(tp, ver_addr) >= ver) { + sram_read(tp, ver_addr, &cur_ver); + if (cur_ver >= ver) { dev_dbg(&tp->intf->dev, "PHY firmware has been the newest\n"); return 0; }
@@ -5415,7 +5582,8 @@ static void rtl8152_fw_phy_fixup(struct r8152 *tp, struct fw_phy_fixup *fix) rtl_reset_ocp_base(tp); addr = __le16_to_cpu(fix->setting.addr); - data = ocp_reg_read(tp, addr); + if (ocp_reg_read(tp, addr, &data) < 0) + return; switch (__le16_to_cpu(fix->bit_cmd)) { case FW_FIXUP_AND:
@@ -5719,10 +5887,10 @@ static inline void r8152_mmd_indirect(struct r8152 *tp, u16 dev, u16 reg) static u16 r8152_mmd_read(struct r8152 *tp, u16 dev, u16 reg) { - u16 data; + u16 data = 0; r8152_mmd_indirect(tp, dev, reg); - data = ocp_reg_read(tp, OCP_EEE_DATA); + ocp_reg_read(tp, OCP_EEE_DATA, &data); ocp_reg_write(tp, OCP_EEE_AR, 0x0000); return data;
@@ -5787,7 +5955,8 @@ static void r8156_eee_en(struct r8152 *tp, bool enable) r8153_eee_en(tp, enable); - config = ocp_reg_read(tp, OCP_EEE_ADV2); + if (ocp_reg_read(tp, OCP_EEE_ADV2, &config) < 0) + return; if (enable && (tp->eee_adv2 & MDIO_EEE_2_5GT)) config |= MDIO_EEE_2_5GT;
@@ -6243,8 +6412,8 @@ static void r8153b_hw_phy_cfg(struct r8152 *tp) * rg_saw_cnt = OCP reg 0xC426 Bit[13:0] * swr_cnt_1ms_ini = 16000000 / rg_saw_cnt */ - ocp_data = ocp_reg_read(tp, 0xc426); - ocp_data &= 0x3fff; + ocp_reg_read(tp, 0xc426, &data); + ocp_data = data & 0x3fff; if (ocp_data) { u32 swr_cnt_1ms_ini;
@@ -6601,7 +6770,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, if (!advertising) return -EINVAL; - orig = r8152_mdio_read(tp, MII_ADVERTISE); + ret = r8152_mdio_read(tp, MII_ADVERTISE); + if (ret < 0) + goto out; + + orig = ret; new1 = orig & ~(ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL); if (advertising & RTL_ADVERTISED_10_HALF) {
@@ -6628,7 +6801,11 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, } if (tp->mii.supports_gmii) { - orig = r8152_mdio_read(tp, MII_CTRL1000); + ret = r8152_mdio_read(tp, MII_CTRL1000); + if (ret < 0) + goto out; + + orig = ret; new1 = orig & ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
@@ -6642,7 +6819,10 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, } if (tp->support_2500full || tp->support_5000full || tp->support_10000full) { - orig = ocp_reg_read(tp, OCP_10GBT_CTRL); + ret = ocp_reg_read(tp, OCP_10GBT_CTRL, &orig); + if (ret < 0) + goto out; + new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G | MDIO_AN_10GBT_CTRL_ADV10G);
@@ -6686,7 +6866,7 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, } out: - return ret; + return ret < 0 ? ret : 0; } static void rtl8152_up(struct r8152 *tp)
@@ -7136,7 +7316,12 @@ static bool rtl8152_in_nway(struct r8152 *tp) static bool rtl8153_in_nway(struct r8152 *tp) { - u16 phy_state = ocp_reg_read(tp, OCP_PHY_STATE) & 0xff; + u16 phy_state; + + if (ocp_reg_read(tp, OCP_PHY_STATE, &phy_state) < 0) + return false; + + phy_state &= 0xff; if (phy_state == TXDIS_STATE || phy_state == ABD_STATE) return false;
@@ -7152,7 +7337,9 @@ static void r8156_mdio_force_mode(struct r8152 *tp) * 0: MDIO force mode * 1: MMD force mode */ - data = ocp_reg_read(tp, 0xa5b4); + if (ocp_reg_read(tp, 0xa5b4, &data) < 0) + return; + if (data & BIT(15)) { data &= ~BIT(15); ocp_reg_write(tp, 0xa5b4, data);
@@ -7791,19 +7978,20 @@ static void r8156_hw_phy_cfg(struct r8152 *tp) ocp_reg_clr_bits(tp, 0xa86a, BIT(0)); /* MDI SWAP */ + ocp_reg_read(tp, 0xd068, &data); if ((ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CFG) & MID_REVERSE) && - (ocp_reg_read(tp, 0xd068) & BIT(1))) { + (data & BIT(1))) { u16 swap_a, swap_b; - data = ocp_reg_read(tp, 0xd068); + ocp_reg_read(tp, 0xd068, &data); data &= ~0x1f; data |= 0x1; /* p0 */ ocp_reg_write(tp, 0xd068, data); - swap_a = ocp_reg_read(tp, 0xd06a); + ocp_reg_read(tp, 0xd06a, &swap_a); data &= ~0x18; data |= 0x18; /* p3 */ ocp_reg_write(tp, 0xd068, data); - swap_b = ocp_reg_read(tp, 0xd06a); + ocp_reg_read(tp, 0xd06a, &swap_b); data &= ~0x18; /* p0 */ ocp_reg_write(tp, 0xd068, data); ocp_reg_write(tp, 0xd06a,
@@ -7815,11 +8003,11 @@ static void r8156_hw_phy_cfg(struct r8152 *tp) data &= ~0x18; data |= 0x08; /* p1 */ ocp_reg_write(tp, 0xd068, data); - swap_a = ocp_reg_read(tp, 0xd06a); + ocp_reg_read(tp, 0xd06a, &swap_a); data &= ~0x18; data |= 0x10; /* p2 */ ocp_reg_write(tp, 0xd068, data); - swap_b = ocp_reg_read(tp, 0xd06a); + ocp_reg_read(tp, 0xd06a, &swap_b); data &= ~0x18; data |= 0x08; /* p1 */ ocp_reg_write(tp, 0xd068, data);
@@ -7830,16 +8018,16 @@ static void r8156_hw_phy_cfg(struct r8152 *tp) ocp_reg_write(tp, 0xd068, data); ocp_reg_write(tp, 0xd06a, (swap_b & ~0x7ff) | (swap_a & 0x7ff)); - swap_a = ocp_reg_read(tp, 0xbd5a); - swap_b = ocp_reg_read(tp, 0xbd5c); + ocp_reg_read(tp, 0xbd5a, &swap_a); + ocp_reg_read(tp, 0xbd5c, &swap_b); ocp_reg_write(tp, 0xbd5a, (swap_a & ~0x1f1f) | ((swap_b & 0x1f) << 8) | ((swap_b >> 8) & 0x1f)); ocp_reg_write(tp, 0xbd5c, (swap_b & ~0x1f1f) | ((swap_a & 0x1f) << 8) | ((swap_a >> 8) & 0x1f)); - swap_a = ocp_reg_read(tp, 0xbc18); - swap_b = ocp_reg_read(tp, 0xbc1a); + ocp_reg_read(tp, 0xbc18, &swap_a); + ocp_reg_read(tp, 0xbc1a, &swap_b); ocp_reg_write(tp, 0xbc18, (swap_a & ~0x1f1f) | ((swap_b & 0x1f) << 8) | ((swap_b >> 8) & 0x1f));
@@ -9436,8 +9624,16 @@ int rtl8152_get_link_ksettings(struct net_device *netdev, cmd->link_modes.supported, tp->support_10000full); if (tp->support_2500full || tp->support_5000full || tp->support_10000full) { - u16 ocp_10gbt_ctrl = ocp_reg_read(tp, OCP_10GBT_CTRL); - u16 ocp_10gbt_stat = ocp_reg_read(tp, OCP_10GBT_STAT); + u16 ocp_10gbt_ctrl; + u16 ocp_10gbt_stat; + + ret = ocp_reg_read(tp, OCP_10GBT_CTRL, &ocp_10gbt_ctrl); + if (ret < 0) + goto out_unlock; + + ret = ocp_reg_read(tp, OCP_10GBT_STAT, &ocp_10gbt_stat); + if (ret < 0) + goto out_unlock; if (tp->support_2500full) { linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
@@ -9479,12 +9675,13 @@ int rtl8152_get_link_ksettings(struct net_device *netdev, } } +out_unlock: mutex_unlock(&tp->control); usb_autopm_put_interface(tp->intf); out: - return ret; + return ret < 0 ? ret : 0; } static int rtl8152_set_link_ksettings(struct net_device *dev,
@@ -9665,21 +9862,37 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee) __ETHTOOL_DECLARE_LINK_MODE_MASK(common) = {}; u16 speed = rtl8152_get_speed(tp); u16 val; + int ret; + + ret = ocp_reg_read(tp, OCP_EEE_ABLE, &val); + if (ret < 0) + goto out; - val = ocp_reg_read(tp, OCP_EEE_ABLE); mii_eee_cap1_mod_linkmode_t(eee->supported, val); - val = ocp_reg_read(tp, OCP_EEE_ADV); + ret = ocp_reg_read(tp, OCP_EEE_ADV, &val); + if (ret < 0) + goto out; + mii_eee_cap1_mod_linkmode_t(eee->advertised, val); - val = ocp_reg_read(tp, OCP_EEE_LPABLE); + ret = ocp_reg_read(tp, OCP_EEE_LPABLE, &val); + if (ret < 0) + goto out; + mii_eee_cap1_mod_linkmode_t(eee->lp_advertised, val); if (tp->support_2500full || tp->support_5000full) { - val = ocp_reg_read(tp, OCP_EEE_ADV2); + ret = ocp_reg_read(tp, OCP_EEE_ADV2, &val); + if (ret < 0) + goto out; + mii_eee_cap2_mod_linkmode_adv_t(eee->advertised, val); - val = ocp_reg_read(tp, OCP_EEE_LPABLE2); + ret = ocp_reg_read(tp, OCP_EEE_LPABLE2, &val); + if (ret < 0) + goto out; + mii_eee_cap2_mod_linkmode_adv_t(eee->lp_advertised, val); }
@@ -9715,7 +9928,8 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee) linkmode_and(common, common, eee->lp_advertised); eee->eee_active = !linkmode_empty(common); - return 0; +out: + return ret < 0 ? ret : 0; } static int
@@ -10002,7 +10216,11 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus mutex_lock(&tp->control); - if (pause->autoneg && !(r8152_mdio_read(tp, MII_BMCR) & BMCR_ANENABLE)) { + ret = r8152_mdio_read(tp, MII_BMCR); + if (ret < 0) + goto out; + + if (pause->autoneg && !(ret & BMCR_ANENABLE)) { ret = -EINVAL; goto out; }
@@ -10013,7 +10231,11 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus if (pause->tx_pause) cap |= FLOW_CTRL_TX; - old = r8152_mdio_read(tp, MII_ADVERTISE); + ret = r8152_mdio_read(tp, MII_ADVERTISE); + if (ret < 0) + goto out; + + old = ret; new1 = (old & ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)) | mii_advertise_flowctrl(cap); if (old != new1) r8152_mdio_write(tp, MII_ADVERTISE, new1);
@@ -10022,7 +10244,7 @@ static int rtl8152_set_pauseparam(struct net_device *netdev, struct ethtool_paus mutex_unlock(&tp->control); usb_autopm_put_interface(tp->intf); - return ret; + return ret < 0 ? ret : 0; } static const struct ethtool_ops ops = {
@@ -10245,6 +10467,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->in_nway = rtl8152_in_nway; ops->hw_phy_cfg = r8152b_hw_phy_cfg; ops->autosuspend_en = rtl_runtime_suspend_enable; + ops->phy_read = r8152_phy_read; + ops->phy_write = r8152_phy_write; tp->rx_buf_sz = 16 * 1024; tp->eee_en = true; tp->eee_adv = MDIO_EEE_100TX;
@@ -10267,6 +10491,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8153_hw_phy_cfg; ops->autosuspend_en = rtl8153_runtime_enable; ops->change_mtu = rtl8153_change_mtu; + ops->phy_read = r8152_phy_read; + ops->phy_write = r8152_phy_write; if (tp->udev->speed < USB_SPEED_SUPER) tp->rx_buf_sz = 16 * 1024; else
@@ -10290,6 +10516,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8153b_hw_phy_cfg; ops->autosuspend_en = rtl8153b_runtime_enable; ops->change_mtu = rtl8153_change_mtu; + ops->phy_read = r8152_phy_read; + ops->phy_write = r8152_phy_write; tp->rx_buf_sz = 32 * 1024; tp->eee_en = true; tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX;
@@ -10314,6 +10542,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8156_hw_phy_cfg; ops->autosuspend_en = rtl8156_runtime_enable; ops->change_mtu = rtl8156_change_mtu; + ops->phy_read = r8152_phy_read; + ops->phy_write = r8152_phy_write; tp->rx_buf_sz = 48 * 1024; tp->support_2500full = 1; r8152_desc_init(tp);
@@ -10339,6 +10569,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8156b_hw_phy_cfg; ops->autosuspend_en = rtl8156_runtime_enable; ops->change_mtu = rtl8156_change_mtu; + ops->phy_read = r8152_phy_read; + ops->phy_write = r8152_phy_write; tp->rx_buf_sz = 48 * 1024; r8152_desc_init(tp); break;
@@ -10356,6 +10588,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8153c_hw_phy_cfg; ops->autosuspend_en = rtl8153c_runtime_enable; ops->change_mtu = rtl8153c_change_mtu; + ops->phy_read = r8152_phy_read; + ops->phy_write = r8152_phy_write; tp->rx_buf_sz = 32 * 1024; tp->eee_en = true; tp->eee_adv = MDIO_EEE_1000T | MDIO_EEE_100TX;
@@ -10378,6 +10612,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8157_hw_phy_cfg; ops->autosuspend_en = rtl8157_runtime_enable; ops->change_mtu = rtl8157_change_mtu; + ops->phy_read = r8157_phy_read; + ops->phy_write = r8157_phy_write; tp->rx_buf_sz = 32 * 1024; tp->support_2500full = 1; tp->support_5000full = 1;
@@ -10401,6 +10637,8 @@ static int rtl_ops_init(struct r8152 *tp) ops->hw_phy_cfg = r8159_hw_phy_cfg; ops->autosuspend_en = rtl8157_runtime_enable; ops->change_mtu = rtl8157_change_mtu; + ops->phy_read = r8157_phy_read; + ops->phy_write = r8157_phy_write; tp->rx_buf_sz = 48 * 1024; tp->support_2500full = 1; tp->support_5000full = 1;
--
2.34.1