Skip to content

Commit 771efed

Browse files
hayesorzdavem330
authored andcommitted
r8152: modify rtl8152_set_speed function
First, for AUTONEG_DISABLE, we only need to modify MII_BMCR. Second, add advertising parameter for rtl8152_set_speed(). Add RTL_ADVERTISED_xxx for advertising parameter of rtl8152_set_speed(). Then, the advertising settings from ethtool could be saved. Signed-off-by: Hayes Wang <hayeswang@realtek.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 472e12e commit 771efed

File tree

1 file changed

+132
-64
lines changed

1 file changed

+132
-64
lines changed

drivers/net/usb/r8152.c

Lines changed: 132 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,7 @@ struct r8152 {
757757
u32 msg_enable;
758758
u32 tx_qlen;
759759
u32 coalesce;
760+
u32 advertising;
760761
u32 rx_buf_sz;
761762
u32 rx_copybreak;
762763
u32 rx_pending;
@@ -790,6 +791,13 @@ enum tx_csum_stat {
790791
TX_CSUM_NONE
791792
};
792793

794+
#define RTL_ADVERTISED_10_HALF BIT(0)
795+
#define RTL_ADVERTISED_10_FULL BIT(1)
796+
#define RTL_ADVERTISED_100_HALF BIT(2)
797+
#define RTL_ADVERTISED_100_FULL BIT(3)
798+
#define RTL_ADVERTISED_1000_HALF BIT(4)
799+
#define RTL_ADVERTISED_1000_FULL BIT(5)
800+
793801
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
794802
* The RTL chips use a 64 element hash table based on the Ethernet CRC.
795803
*/
@@ -3801,90 +3809,117 @@ static void rtl8153b_disable(struct r8152 *tp)
38013809
r8153b_aldps_en(tp, true);
38023810
}
38033811

3804-
static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
3812+
static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex,
3813+
u32 advertising)
38053814
{
3806-
u16 bmcr, anar, gbcr;
38073815
enum spd_duplex speed_duplex;
3816+
u16 bmcr;
38083817
int ret = 0;
38093818

3810-
anar = r8152_mdio_read(tp, MII_ADVERTISE);
3811-
anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
3812-
ADVERTISE_100HALF | ADVERTISE_100FULL);
3813-
if (tp->mii.supports_gmii) {
3814-
gbcr = r8152_mdio_read(tp, MII_CTRL1000);
3815-
gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
3816-
} else {
3817-
gbcr = 0;
3818-
}
3819-
38203819
if (autoneg == AUTONEG_DISABLE) {
3821-
if (speed == SPEED_10) {
3822-
bmcr = 0;
3823-
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
3824-
speed_duplex = FORCE_10M_HALF;
3825-
} else if (speed == SPEED_100) {
3826-
bmcr = BMCR_SPEED100;
3827-
anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
3828-
speed_duplex = FORCE_100M_HALF;
3829-
} else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
3830-
bmcr = BMCR_SPEED1000;
3831-
gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
3832-
speed_duplex = NWAY_1000M_FULL;
3833-
} else {
3834-
ret = -EINVAL;
3835-
goto out;
3836-
}
3820+
if (duplex != DUPLEX_HALF && duplex != DUPLEX_FULL)
3821+
return -EINVAL;
38373822

3838-
if (duplex == DUPLEX_FULL) {
3839-
bmcr |= BMCR_FULLDPLX;
3840-
if (speed != SPEED_1000)
3841-
speed_duplex++;
3842-
}
3843-
} else {
3844-
if (speed == SPEED_10) {
3823+
switch (speed) {
3824+
case SPEED_10:
3825+
bmcr = BMCR_SPEED10;
38453826
if (duplex == DUPLEX_FULL) {
3846-
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
3847-
speed_duplex = NWAY_10M_FULL;
3827+
bmcr |= BMCR_FULLDPLX;
3828+
speed_duplex = FORCE_10M_FULL;
38483829
} else {
3849-
anar |= ADVERTISE_10HALF;
3850-
speed_duplex = NWAY_10M_HALF;
3830+
speed_duplex = FORCE_10M_HALF;
38513831
}
3852-
} else if (speed == SPEED_100) {
3832+
break;
3833+
case SPEED_100:
3834+
bmcr = BMCR_SPEED100;
38533835
if (duplex == DUPLEX_FULL) {
3854-
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
3855-
anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
3856-
speed_duplex = NWAY_100M_FULL;
3836+
bmcr |= BMCR_FULLDPLX;
3837+
speed_duplex = FORCE_100M_FULL;
38573838
} else {
3858-
anar |= ADVERTISE_10HALF;
3859-
anar |= ADVERTISE_100HALF;
3860-
speed_duplex = NWAY_100M_HALF;
3839+
speed_duplex = FORCE_100M_HALF;
38613840
}
3862-
} else if (speed == SPEED_1000 && tp->mii.supports_gmii) {
3863-
if (duplex == DUPLEX_FULL) {
3864-
anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
3865-
anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
3866-
gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
3867-
} else {
3868-
anar |= ADVERTISE_10HALF;
3869-
anar |= ADVERTISE_100HALF;
3870-
gbcr |= ADVERTISE_1000HALF;
3841+
break;
3842+
case SPEED_1000:
3843+
if (tp->mii.supports_gmii) {
3844+
bmcr = BMCR_SPEED1000 | BMCR_FULLDPLX;
3845+
speed_duplex = NWAY_1000M_FULL;
3846+
break;
38713847
}
3872-
speed_duplex = NWAY_1000M_FULL;
3873-
} else {
3848+
/* fall through */
3849+
default:
38743850
ret = -EINVAL;
38753851
goto out;
38763852
}
38773853

3854+
if (duplex == DUPLEX_FULL)
3855+
tp->mii.full_duplex = 1;
3856+
else
3857+
tp->mii.full_duplex = 0;
3858+
3859+
tp->mii.force_media = 1;
3860+
} else {
3861+
u16 anar, tmp1;
3862+
u32 support;
3863+
3864+
support = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL |
3865+
RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL;
3866+
3867+
if (tp->mii.supports_gmii)
3868+
support |= RTL_ADVERTISED_1000_FULL;
3869+
3870+
if (!(advertising & support))
3871+
return -EINVAL;
3872+
3873+
anar = r8152_mdio_read(tp, MII_ADVERTISE);
3874+
tmp1 = anar & ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
3875+
ADVERTISE_100HALF | ADVERTISE_100FULL);
3876+
if (advertising & RTL_ADVERTISED_10_HALF) {
3877+
tmp1 |= ADVERTISE_10HALF;
3878+
speed_duplex = NWAY_10M_HALF;
3879+
}
3880+
if (advertising & RTL_ADVERTISED_10_FULL) {
3881+
tmp1 |= ADVERTISE_10FULL;
3882+
speed_duplex = NWAY_10M_FULL;
3883+
}
3884+
3885+
if (advertising & RTL_ADVERTISED_100_HALF) {
3886+
tmp1 |= ADVERTISE_100HALF;
3887+
speed_duplex = NWAY_100M_HALF;
3888+
}
3889+
if (advertising & RTL_ADVERTISED_100_FULL) {
3890+
tmp1 |= ADVERTISE_100FULL;
3891+
speed_duplex = NWAY_100M_FULL;
3892+
}
3893+
3894+
if (anar != tmp1) {
3895+
r8152_mdio_write(tp, MII_ADVERTISE, tmp1);
3896+
tp->mii.advertising = tmp1;
3897+
}
3898+
3899+
if (tp->mii.supports_gmii) {
3900+
u16 gbcr;
3901+
3902+
gbcr = r8152_mdio_read(tp, MII_CTRL1000);
3903+
tmp1 = gbcr & ~(ADVERTISE_1000FULL |
3904+
ADVERTISE_1000HALF);
3905+
3906+
if (advertising & RTL_ADVERTISED_1000_FULL) {
3907+
tmp1 |= ADVERTISE_1000FULL;
3908+
speed_duplex = NWAY_1000M_FULL;
3909+
}
3910+
3911+
if (gbcr != tmp1)
3912+
r8152_mdio_write(tp, MII_CTRL1000, tmp1);
3913+
}
3914+
38783915
bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
3916+
3917+
tp->mii.force_media = 0;
38793918
}
38803919

38813920
if (test_and_clear_bit(PHY_RESET, &tp->flags))
38823921
bmcr |= BMCR_RESET;
38833922

3884-
if (tp->mii.supports_gmii)
3885-
r8152_mdio_write(tp, MII_CTRL1000, gbcr);
3886-
3887-
r8152_mdio_write(tp, MII_ADVERTISE, anar);
38883923
r8152_mdio_write(tp, MII_BMCR, bmcr);
38893924

38903925
switch (tp->version) {
@@ -4122,7 +4157,8 @@ static void rtl_hw_phy_work_func_t(struct work_struct *work)
41224157

41234158
tp->rtl_ops.hw_phy_cfg(tp);
41244159

4125-
rtl8152_set_speed(tp, tp->autoneg, tp->speed, tp->duplex);
4160+
rtl8152_set_speed(tp, tp->autoneg, tp->speed, tp->duplex,
4161+
tp->advertising);
41264162

41274163
mutex_unlock(&tp->control);
41284164

@@ -4840,20 +4876,46 @@ static int rtl8152_set_link_ksettings(struct net_device *dev,
48404876
const struct ethtool_link_ksettings *cmd)
48414877
{
48424878
struct r8152 *tp = netdev_priv(dev);
4879+
u32 advertising = 0;
48434880
int ret;
48444881

48454882
ret = usb_autopm_get_interface(tp->intf);
48464883
if (ret < 0)
48474884
goto out;
48484885

4886+
if (test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
4887+
cmd->link_modes.advertising))
4888+
advertising |= RTL_ADVERTISED_10_HALF;
4889+
4890+
if (test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
4891+
cmd->link_modes.advertising))
4892+
advertising |= RTL_ADVERTISED_10_FULL;
4893+
4894+
if (test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
4895+
cmd->link_modes.advertising))
4896+
advertising |= RTL_ADVERTISED_100_HALF;
4897+
4898+
if (test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
4899+
cmd->link_modes.advertising))
4900+
advertising |= RTL_ADVERTISED_100_FULL;
4901+
4902+
if (test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
4903+
cmd->link_modes.advertising))
4904+
advertising |= RTL_ADVERTISED_1000_HALF;
4905+
4906+
if (test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
4907+
cmd->link_modes.advertising))
4908+
advertising |= RTL_ADVERTISED_1000_FULL;
4909+
48494910
mutex_lock(&tp->control);
48504911

48514912
ret = rtl8152_set_speed(tp, cmd->base.autoneg, cmd->base.speed,
4852-
cmd->base.duplex);
4913+
cmd->base.duplex, advertising);
48534914
if (!ret) {
48544915
tp->autoneg = cmd->base.autoneg;
48554916
tp->speed = cmd->base.speed;
48564917
tp->duplex = cmd->base.duplex;
4918+
tp->advertising = advertising;
48574919
}
48584920

48594921
mutex_unlock(&tp->control);
@@ -5568,7 +5630,13 @@ static int rtl8152_probe(struct usb_interface *intf,
55685630
tp->mii.phy_id = R8152_PHY_ID;
55695631

55705632
tp->autoneg = AUTONEG_ENABLE;
5571-
tp->speed = tp->mii.supports_gmii ? SPEED_1000 : SPEED_100;
5633+
tp->speed = SPEED_100;
5634+
tp->advertising = RTL_ADVERTISED_10_HALF | RTL_ADVERTISED_10_FULL |
5635+
RTL_ADVERTISED_100_HALF | RTL_ADVERTISED_100_FULL;
5636+
if (tp->mii.supports_gmii) {
5637+
tp->speed = SPEED_1000;
5638+
tp->advertising |= RTL_ADVERTISED_1000_FULL;
5639+
}
55725640
tp->duplex = DUPLEX_FULL;
55735641

55745642
tp->rx_copybreak = RTL8152_RXFG_HEADSZ;

0 commit comments

Comments
 (0)