@@ -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