mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
r8152: Add support for 5Gbit Link Speeds and EEE
The RTL8157 supports 5GBit Link speeds. Add support for this speed in the setup and setting/getting through ethtool. Also add 5GBit EEE. Add functionality for setup and ethtool get/set methods. Signed-off-by: Birger Koblitz <mail@birger-koblitz.de> Link: https://patch.msgid.link/20260404-rtl8157_next-v7-1-039121318f23@birger-koblitz.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
committed by
Paolo Abeni
parent
58dd34dbd5
commit
ebe5fd2ed2
@@ -606,6 +606,7 @@ enum spd_duplex {
|
||||
FORCE_100M_FULL,
|
||||
FORCE_1000M_FULL,
|
||||
NWAY_2500M_FULL,
|
||||
NWAY_5000M_FULL,
|
||||
};
|
||||
|
||||
/* OCP_ALDPS_CONFIG */
|
||||
@@ -727,6 +728,7 @@ enum spd_duplex {
|
||||
#define BP4_SUPER_ONLY 0x1578 /* RTL_VER_04 only */
|
||||
|
||||
enum rtl_register_content {
|
||||
_5000bps = BIT(12),
|
||||
_2500bps = BIT(10),
|
||||
_1250bps = BIT(9),
|
||||
_500bps = BIT(8),
|
||||
@@ -740,6 +742,7 @@ enum rtl_register_content {
|
||||
};
|
||||
|
||||
#define is_speed_2500(_speed) (((_speed) & (_2500bps | LINK_STATUS)) == (_2500bps | LINK_STATUS))
|
||||
#define is_speed_5000(_speed) (((_speed) & (_5000bps | LINK_STATUS)) == (_5000bps | LINK_STATUS))
|
||||
#define is_flow_control(_speed) (((_speed) & (_tx_flow | _rx_flow)) == (_tx_flow | _rx_flow))
|
||||
|
||||
#define RTL8152_MAX_TX 4
|
||||
@@ -946,6 +949,7 @@ struct r8152 {
|
||||
unsigned int pipe_in, pipe_out, pipe_intr, pipe_ctrl_in, pipe_ctrl_out;
|
||||
|
||||
u32 support_2500full:1;
|
||||
u32 support_5000full:1;
|
||||
u32 lenovo_macpassthru:1;
|
||||
u32 dell_tb_rx_agg_bug:1;
|
||||
u16 ocp_base;
|
||||
@@ -1196,6 +1200,7 @@ enum tx_csum_stat {
|
||||
#define RTL_ADVERTISED_1000_HALF BIT(4)
|
||||
#define RTL_ADVERTISED_1000_FULL BIT(5)
|
||||
#define RTL_ADVERTISED_2500_FULL BIT(6)
|
||||
#define RTL_ADVERTISED_5000_FULL BIT(7)
|
||||
|
||||
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
|
||||
* The RTL chips use a 64 element hash table based on the Ethernet CRC.
|
||||
@@ -5421,12 +5426,23 @@ static void r8153_eee_en(struct r8152 *tp, bool enable)
|
||||
|
||||
static void r8156_eee_en(struct r8152 *tp, bool enable)
|
||||
{
|
||||
u16 config;
|
||||
|
||||
r8153_eee_en(tp, enable);
|
||||
|
||||
config = ocp_reg_read(tp, OCP_EEE_ADV2);
|
||||
|
||||
if (enable && (tp->eee_adv2 & MDIO_EEE_2_5GT))
|
||||
ocp_reg_set_bits(tp, OCP_EEE_ADV2, MDIO_EEE_2_5GT);
|
||||
config |= MDIO_EEE_2_5GT;
|
||||
else
|
||||
ocp_reg_clr_bits(tp, OCP_EEE_ADV2, MDIO_EEE_2_5GT);
|
||||
config &= ~MDIO_EEE_2_5GT;
|
||||
|
||||
if (enable && (tp->eee_adv2 & MDIO_EEE_5GT))
|
||||
config |= MDIO_EEE_5GT;
|
||||
else
|
||||
config &= ~MDIO_EEE_5GT;
|
||||
|
||||
ocp_reg_write(tp, OCP_EEE_ADV2, config);
|
||||
}
|
||||
|
||||
static void rtl_eee_enable(struct r8152 *tp, bool enable)
|
||||
@@ -6190,9 +6206,13 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
|
||||
|
||||
if (tp->support_2500full)
|
||||
support |= RTL_ADVERTISED_2500_FULL;
|
||||
|
||||
if (tp->support_5000full)
|
||||
support |= RTL_ADVERTISED_5000_FULL;
|
||||
}
|
||||
|
||||
if (!(advertising & support))
|
||||
advertising &= support;
|
||||
if (!advertising)
|
||||
return -EINVAL;
|
||||
|
||||
orig = r8152_mdio_read(tp, MII_ADVERTISE);
|
||||
@@ -6235,15 +6255,20 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
|
||||
r8152_mdio_write(tp, MII_CTRL1000, new1);
|
||||
}
|
||||
|
||||
if (tp->support_2500full) {
|
||||
if (tp->support_2500full || tp->support_5000full) {
|
||||
orig = ocp_reg_read(tp, OCP_10GBT_CTRL);
|
||||
new1 = orig & ~MDIO_AN_10GBT_CTRL_ADV2_5G;
|
||||
new1 = orig & ~(MDIO_AN_10GBT_CTRL_ADV2_5G | MDIO_AN_10GBT_CTRL_ADV5G);
|
||||
|
||||
if (advertising & RTL_ADVERTISED_2500_FULL) {
|
||||
new1 |= MDIO_AN_10GBT_CTRL_ADV2_5G;
|
||||
tp->ups_info.speed_duplex = NWAY_2500M_FULL;
|
||||
}
|
||||
|
||||
if (advertising & RTL_ADVERTISED_5000_FULL) {
|
||||
new1 |= MDIO_AN_10GBT_CTRL_ADV5G;
|
||||
tp->ups_info.speed_duplex = NWAY_5000M_FULL;
|
||||
}
|
||||
|
||||
if (orig != new1)
|
||||
ocp_reg_write(tp, OCP_10GBT_CTRL, new1);
|
||||
}
|
||||
@@ -8220,17 +8245,38 @@ int rtl8152_get_link_ksettings(struct net_device *netdev,
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
cmd->link_modes.supported, tp->support_2500full);
|
||||
|
||||
if (tp->support_2500full) {
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
cmd->link_modes.advertising,
|
||||
ocp_reg_read(tp, OCP_10GBT_CTRL) & MDIO_AN_10GBT_CTRL_ADV2_5G);
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
|
||||
cmd->link_modes.supported, tp->support_5000full);
|
||||
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
cmd->link_modes.lp_advertising,
|
||||
ocp_reg_read(tp, OCP_10GBT_STAT) & MDIO_AN_10GBT_STAT_LP2_5G);
|
||||
if (tp->support_2500full || tp->support_5000full) {
|
||||
u16 ocp_10gbt_ctrl = ocp_reg_read(tp, OCP_10GBT_CTRL);
|
||||
u16 ocp_10gbt_stat = ocp_reg_read(tp, OCP_10GBT_STAT);
|
||||
|
||||
if (is_speed_2500(rtl8152_get_speed(tp)))
|
||||
cmd->base.speed = SPEED_2500;
|
||||
if (tp->support_2500full) {
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
cmd->link_modes.advertising,
|
||||
ocp_10gbt_ctrl & MDIO_AN_10GBT_CTRL_ADV2_5G);
|
||||
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
||||
cmd->link_modes.lp_advertising,
|
||||
ocp_10gbt_stat & MDIO_AN_10GBT_STAT_LP2_5G);
|
||||
|
||||
if (is_speed_2500(rtl8152_get_speed(tp)))
|
||||
cmd->base.speed = SPEED_2500;
|
||||
}
|
||||
|
||||
if (tp->support_5000full) {
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
|
||||
cmd->link_modes.advertising,
|
||||
ocp_10gbt_ctrl & MDIO_AN_10GBT_CTRL_ADV5G);
|
||||
|
||||
linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
|
||||
cmd->link_modes.lp_advertising,
|
||||
ocp_10gbt_stat & MDIO_AN_10GBT_STAT_LP5G);
|
||||
|
||||
if (is_speed_5000(rtl8152_get_speed(tp)))
|
||||
cmd->base.speed = SPEED_5000;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&tp->control);
|
||||
@@ -8280,6 +8326,10 @@ static int rtl8152_set_link_ksettings(struct net_device *dev,
|
||||
cmd->link_modes.advertising))
|
||||
advertising |= RTL_ADVERTISED_2500_FULL;
|
||||
|
||||
if (test_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
|
||||
cmd->link_modes.advertising))
|
||||
advertising |= RTL_ADVERTISED_5000_FULL;
|
||||
|
||||
mutex_lock(&tp->control);
|
||||
|
||||
ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed,
|
||||
@@ -8397,7 +8447,7 @@ static int r8152_set_eee(struct r8152 *tp, struct ethtool_keee *eee)
|
||||
|
||||
tp->eee_en = eee->eee_enabled;
|
||||
tp->eee_adv = val;
|
||||
if (tp->support_2500full) {
|
||||
if (tp->support_2500full || tp->support_5000full) {
|
||||
val = linkmode_to_mii_eee_cap2_t(eee->advertised);
|
||||
tp->eee_adv2 = val;
|
||||
}
|
||||
@@ -8421,19 +8471,28 @@ static int r8153_get_eee(struct r8152 *tp, struct ethtool_keee *eee)
|
||||
val = ocp_reg_read(tp, OCP_EEE_LPABLE);
|
||||
mii_eee_cap1_mod_linkmode_t(eee->lp_advertised, val);
|
||||
|
||||
if (tp->support_2500full) {
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, eee->supported);
|
||||
|
||||
if (tp->support_2500full || tp->support_5000full) {
|
||||
val = ocp_reg_read(tp, OCP_EEE_ADV2);
|
||||
mii_eee_cap2_mod_linkmode_adv_t(eee->advertised, val);
|
||||
|
||||
val = ocp_reg_read(tp, OCP_EEE_LPABLE2);
|
||||
mii_eee_cap2_mod_linkmode_adv_t(eee->lp_advertised, val);
|
||||
}
|
||||
|
||||
if (tp->support_2500full) {
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, eee->supported);
|
||||
|
||||
if (speed & _2500bps)
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, common);
|
||||
}
|
||||
|
||||
if (tp->support_5000full) {
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, eee->supported);
|
||||
|
||||
if (speed & _5000bps)
|
||||
linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, common);
|
||||
}
|
||||
|
||||
eee->eee_enabled = tp->eee_en;
|
||||
|
||||
if (speed & _1000bps)
|
||||
@@ -9374,6 +9433,11 @@ static int rtl8152_probe_once(struct usb_interface *intf,
|
||||
} else {
|
||||
tp->speed = SPEED_1000;
|
||||
}
|
||||
if (tp->support_5000full &&
|
||||
tp->udev->speed >= USB_SPEED_SUPER) {
|
||||
tp->speed = SPEED_5000;
|
||||
tp->advertising |= RTL_ADVERTISED_5000_FULL;
|
||||
}
|
||||
tp->advertising |= RTL_ADVERTISED_1000_FULL;
|
||||
}
|
||||
tp->duplex = DUPLEX_FULL;
|
||||
|
||||
Reference in New Issue
Block a user