lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 21 Jul 2022 17:48:05 -0400
From:   Sean Anderson <sean.anderson@...o.com>
To:     "Russell King (Oracle)" <linux@...linux.org.uk>
Cc:     netdev@...r.kernel.org, Andrew Lunn <andrew@...n.ch>,
        Heiner Kallweit <hkallweit1@...il.com>,
        Alexandru Marginean <alexandru.marginean@....com>,
        Paolo Abeni <pabeni@...hat.com>,
        "David S . Miller" <davem@...emloft.net>,
        linux-kernel@...r.kernel.org, Vladimir Oltean <olteanv@...il.com>,
        Eric Dumazet <edumazet@...gle.com>,
        Jakub Kicinski <kuba@...nel.org>
Subject: Re: [PATCH v2 07/11] net: phylink: Adjust link settings based on rate
 adaptation



On 7/20/22 2:32 PM, Russell King (Oracle) wrote:
> On Wed, Jul 20, 2022 at 07:50:52AM +0100, Russell King (Oracle) wrote:
>> We can do that by storing the PHY rate adaption state, and processing
>> that in phylink_link_up().
> 
> Something like this? I haven't included the IPG (open loop) stuff in
> this - I think when we come to implement that, we need a new mac
> method to call to set the IPG just before calling mac_link_up().
> Something like:
> 
>  void mac_set_ipg(struct phylink_config *config, int packet_speed,
> 		  int interface_speed);
> 
> Note that we also have PCS that do rate adaption too, and I think
> fitting those in with the code below may be easier than storing the
> media and phy interface speed/duplex separately.

This is another area where the MAC has to know a lot about the PCS.
We don't keep track of the PCS interface mode, so the MAC has to know
how to connect to the PCS. That could already include some rate
adaptation, but I suspect it is all done like GMII (where the clock
speed changes).

The only drawback I see with this approach is that we don't use the
MAC/PCS's speed/duplex when in in-band mode. But I think that only
matters for things like SGMII, which (as noted below) probably
shouldn't use rate adaptation.

> A few further question though - does rate adaption make sense with
> interface modes that can already natively handle the different speeds,
> such as SGMII, RGMII, USXGMII, etc?

Generally, no. I think it's reasonable to let the phy decide what's
going on, and just do whatever it says.

>  drivers/net/phy/phylink.c | 103 ++++++++++++++++++++++++++++++++++++++++++++--
>  include/linux/phylink.h   |   1 +
>  2 files changed, 100 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 9bd69328dc4d..c89eb74458cd 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -994,23 +994,105 @@ static const char *phylink_pause_to_str(int pause)
>  	}
>  }
>  
> +static int phylink_interface_max_speed(phy_interface_t interface)
> +{
> +	switch (interface) {
> +	case PHY_INTERFACE_MODE_100BASEX:
> +	case PHY_INTERFACE_MODE_REVRMII:
> +	case PHY_INTERFACE_MODE_RMII:
> +	case PHY_INTERFACE_MODE_SMII:
> +	case PHY_INTERFACE_MODE_REVMII:
> +	case PHY_INTERFACE_MODE_MII:
> +		return SPEED_100;
> +
> +	case PHY_INTERFACE_MODE_TBI:
> +	case PHY_INTERFACE_MODE_MOCA:
> +	case PHY_INTERFACE_MODE_RTBI:
> +	case PHY_INTERFACE_MODE_1000BASEX:
> +	case PHY_INTERFACE_MODE_1000BASEKX:
> +	case PHY_INTERFACE_MODE_TRGMII:
> +	case PHY_INTERFACE_MODE_RGMII_TXID:
> +	case PHY_INTERFACE_MODE_RGMII_RXID:
> +	case PHY_INTERFACE_MODE_RGMII_ID:
> +	case PHY_INTERFACE_MODE_RGMII:
> +	case PHY_INTERFACE_MODE_QSGMII:
> +	case PHY_INTERFACE_MODE_SGMII:
> +	case PHY_INTERFACE_MODE_GMII:
> +		return SPEED_1000;
> +
> +	case PHY_INTERFACE_MODE_2500BASEX:
> +		return SPEED_2500;
> +
> +	case PHY_INTERFACE_MODE_5GBASER:
> +		return SPEED_5000;
> +
> +	case PHY_INTERFACE_MODE_XGMII:
> +	case PHY_INTERFACE_MODE_RXAUI:
> +	case PHY_INTERFACE_MODE_XAUI:
> +	case PHY_INTERFACE_MODE_10GBASER:
> +	case PHY_INTERFACE_MODE_10GKR:
> +	case PHY_INTERFACE_MODE_USXGMII:
> +		return SPEED_10000;
> +
> +	case PHY_INTERFACE_MODE_25GBASER:
> +		return SPEED_25000;
> +
> +	case PHY_INTERFACE_MODE_XLGMII:
> +		return SPEED_40000;
> +
> +	case PHY_INTERFACE_MODE_INTERNAL:
> +		/* Rate adaption is probably not supported */
> +		return 0;
> +
> +	case PHY_INTERFACE_MODE_NA:
> +	case PHY_INTERFACE_MODE_MAX:
> +		return SPEED_UNKNOWN;
> +	}
> +}
> +
>  static void phylink_link_up(struct phylink *pl,
>  			    struct phylink_link_state link_state)
>  {
>  	struct net_device *ndev = pl->netdev;
> +	int speed, duplex;
> +	bool rx_pause;
> +
> +	speed = link_state.speed;
> +	duplex = link_state.duplex;
> +	rx_pause = !!(link_state.pause & MLO_PAUSE_RX);
> +
> +	switch (state->rate_adaption) {
> +	case RATE_ADAPT_PAUSE:
> +		/* The PHY is doing rate adaption from the media rate (in
> +		 * the link_state) to the interface speed, and will send
> +		 * pause frames to the MAC to limit its transmission speed.
> +		 */
> +		speed = phylink_interface_max_speed(link_state.interface);
> +		duplex = DUPLEX_FULL;
> +		rx_pause = true;
> +		break;
> +
> +	case RATE_ADAPT_CRS:
> +		/* The PHY is doing rate adaption from the media rate (in
> +		 * the link_state) to the interface speed, and will cause
> +		 * collisions to the MAC to limit its transmission speed.
> +		 */
> +		speed = phylink_interface_max_speed(link_state.interface);
> +		duplex = DUPLEX_HALF;
> +		break;
> +	}
>  
>  	pl->cur_interface = link_state.interface;
>  
>  	if (pl->pcs && pl->pcs->ops->pcs_link_up)
>  		pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode,
> -					 pl->cur_interface,
> -					 link_state.speed, link_state.duplex);
> +					 pl->cur_interface, speed, duplex);
>  
>  	pl->mac_ops->mac_link_up(pl->config, pl->phydev,
>  				 pl->cur_link_an_mode, pl->cur_interface,
> -				 link_state.speed, link_state.duplex,
> +				 speed, duplex,
>  				 !!(link_state.pause & MLO_PAUSE_TX),
> -				 !!(link_state.pause & MLO_PAUSE_RX));
> +				 rx_pause);
>  
>  	if (ndev)
>  		netif_carrier_on(ndev);
> @@ -1102,6 +1184,17 @@ static void phylink_resolve(struct work_struct *w)
>  				}
>  				link_state.interface = pl->phy_state.interface;
>  
> +				/* If we are doing rate adaption, then the
> +				 * media speed/duplex has to come from the PHY.
> +				 */
> +				if (pl->phy_state.rate_adaption) {
> +					link_state.rate_adaption =
> +						pl->phy_state.rate_adaption;
> +					link_state.speed = pl->phy_state.speed;
> +					link_state.duplex =
> +						pl->phy_state.duplex;
> +				}
> +
>  				/* If we have a PHY, we need to update with
>  				 * the PHY flow control bits.
>  				 */
> @@ -1337,6 +1430,7 @@ static void phylink_phy_change(struct phy_device *phydev, bool up)
>  	pl->phy_state.speed = phydev->speed;
>  	pl->phy_state.duplex = phydev->duplex;
>  	pl->phy_state.pause = MLO_PAUSE_NONE;
> +	pl->phy_state.rate_adaption = phydev->rate_adaption;
>  	if (tx_pause)
>  		pl->phy_state.pause |= MLO_PAUSE_TX;
>  	if (rx_pause)
> @@ -1414,6 +1508,7 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
>  	pl->phy_state.pause = MLO_PAUSE_NONE;
>  	pl->phy_state.speed = SPEED_UNKNOWN;
>  	pl->phy_state.duplex = DUPLEX_UNKNOWN;
> +	pl->phy_state.rate_adaption = RATE_ADAPT_NONE;
>  	linkmode_copy(pl->supported, supported);
>  	linkmode_copy(pl->link_config.advertising, config.advertising);
>  
> diff --git a/include/linux/phylink.h b/include/linux/phylink.h
> index 6d06896fc20d..65301e7961b0 100644
> --- a/include/linux/phylink.h
> +++ b/include/linux/phylink.h
> @@ -70,6 +70,7 @@ struct phylink_link_state {
>  	int speed;
>  	int duplex;
>  	int pause;
> +	int rate_adaption;
>  	unsigned int link:1;
>  	unsigned int an_enabled:1;
>  	unsigned int an_complete:1;
> 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ