diff mbox series

[RFC,net-next,2/3] net: stmmac: Activate Inband/PCS flag based on the selected iface

Message ID 20240524210304.9164-2-fancer.lancer@gmail.com (mailing list archive)
State New, archived
Headers show
Series [RFC,net-next,1/3] net: stmmac: Prevent RGSMIIIS IRQs flood | expand

Commit Message

Serge Semin May 24, 2024, 9:02 p.m. UTC
The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
into the DW GMAC controller. It's always done if the controller supports
at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
interfaces support was activated during the IP-core synthesize the PCS
block won't be activated either and the HWFEATURE.PCSSEL flag won't be
set. Based on that the RGMII in-band status detection procedure
implemented in the driver hasn't been working for the devices with the
RGMII interface support and with none of the SGMII, TBI, RTBI PHY
interfaces available in the device.

Fix that just by dropping the dma_cap.pcs flag check from the conditional
statement responsible for the In-band/PCS functionality activation. If the
RGMII interface is supported by the device then the in-band link status
detection will be also supported automatically (it's always embedded into
the RGMII RTL code). If the SGMII interface is supported by the device
then the PCS block will be supported too (it's unconditionally synthesized
into the controller). The later is also correct for the TBI/RTBI PHY
interfaces.

Note while at it drop the netdev_dbg() calls since at the moment of the
stmmac_check_pcs_mode() invocation the network device isn't registered. So
the debug prints will be for the unknown/NULL device.

Fixes: e58bb43f5e43 ("stmmac: initial support to manage pcs modes")
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c    | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

Comments

Russell King (Oracle) May 26, 2024, 4:49 p.m. UTC | #1
On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> into the DW GMAC controller. It's always done if the controller supports
> at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> interfaces support was activated during the IP-core synthesize the PCS
> block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> set. Based on that the RGMII in-band status detection procedure
> implemented in the driver hasn't been working for the devices with the
> RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> interfaces available in the device.
> 
> Fix that just by dropping the dma_cap.pcs flag check from the conditional
> statement responsible for the In-band/PCS functionality activation. If the
> RGMII interface is supported by the device then the in-band link status
> detection will be also supported automatically (it's always embedded into
> the RGMII RTL code). If the SGMII interface is supported by the device
> then the PCS block will be supported too (it's unconditionally synthesized
> into the controller). The later is also correct for the TBI/RTBI PHY
> interfaces.
> 
> Note while at it drop the netdev_dbg() calls since at the moment of the
> stmmac_check_pcs_mode() invocation the network device isn't registered. So
> the debug prints will be for the unknown/NULL device.

Thanks. As this is a fix, shouldn't it be submitted for the net tree as
it seems to be fixing a bug in the driver as it stands today?

Also, a build fix is required here:

> -	if (priv->dma_cap.pcs) {
> -		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> -		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> -		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> -		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> -			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> -			priv->hw->pcs = STMMAC_PCS_RGMII;
> -		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> -			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> -			priv->hw->pcs = STMMAC_PCS_SGMII;
> -		}
> -	}
> +	if (phy_interface_mode_is_rgmii(interface))
> +		priv->hw.pcs = STMMAC_PCS_RGMII;
> +	else if (interface == PHY_INTERFACE_MODE_SGMII)
> +		priv->hw.pcs = STMMAC_PCS_SGMII;

Both of these assignments should be priv->hw->pcs not priv->hw.pcs.

I think there's also another bug that needs fixing along with this.
See stmmac_ethtool_set_link_ksettings(). Note that this denies the
ability to disable autoneg, which (a) doesn't make sense for RGMII
with an attached PHY, and (b) this code should be passing the
ethtool op to phylink for it to pass on to phylib so the PHY can
be appropriately configured for the users desired autoneg and
link mode settings.

I also don't think it makes any sense for the STMMAC_PCS_SGMII case
given that it means Cisco SGMII - which implies that there is also
a PHY (since Cisco SGMII with inband is designed to be coupled with
something that looks like a PHY to send the inband signalling
necessary to configure e.g. the SGMII link symbol replication.

In both of these cases, even if the user requests autoneg to be
disabled, that _shouldn't_ affect internal network driver links.
This ethtool op is about configuring the externally visible media
side of the network driver, not the internal links.
Russell King (Oracle) May 26, 2024, 6 p.m. UTC | #2
On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > into the DW GMAC controller. It's always done if the controller supports
> > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > interfaces support was activated during the IP-core synthesize the PCS
> > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > set. Based on that the RGMII in-band status detection procedure
> > implemented in the driver hasn't been working for the devices with the
> > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > interfaces available in the device.
> > 
> > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > statement responsible for the In-band/PCS functionality activation. If the
> > RGMII interface is supported by the device then the in-band link status
> > detection will be also supported automatically (it's always embedded into
> > the RGMII RTL code). If the SGMII interface is supported by the device
> > then the PCS block will be supported too (it's unconditionally synthesized
> > into the controller). The later is also correct for the TBI/RTBI PHY
> > interfaces.
> > 
> > Note while at it drop the netdev_dbg() calls since at the moment of the
> > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > the debug prints will be for the unknown/NULL device.
> 
> Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> it seems to be fixing a bug in the driver as it stands today?
> 
> Also, a build fix is required here:
> 
> > -	if (priv->dma_cap.pcs) {
> > -		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> > -		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> > -		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> > -		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> > -			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> > -			priv->hw->pcs = STMMAC_PCS_RGMII;
> > -		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> > -			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> > -			priv->hw->pcs = STMMAC_PCS_SGMII;
> > -		}
> > -	}
> > +	if (phy_interface_mode_is_rgmii(interface))
> > +		priv->hw.pcs = STMMAC_PCS_RGMII;
> > +	else if (interface == PHY_INTERFACE_MODE_SGMII)
> > +		priv->hw.pcs = STMMAC_PCS_SGMII;
> 
> Both of these assignments should be priv->hw->pcs not priv->hw.pcs.
> 
> I think there's also another bug that needs fixing along with this.
> See stmmac_ethtool_set_link_ksettings(). Note that this denies the
> ability to disable autoneg, which (a) doesn't make sense for RGMII
> with an attached PHY, and (b) this code should be passing the
> ethtool op to phylink for it to pass on to phylib so the PHY can
> be appropriately configured for the users desired autoneg and
> link mode settings.
> 
> I also don't think it makes any sense for the STMMAC_PCS_SGMII case
> given that it means Cisco SGMII - which implies that there is also
> a PHY (since Cisco SGMII with inband is designed to be coupled with
> something that looks like a PHY to send the inband signalling
> necessary to configure e.g. the SGMII link symbol replication.
> 
> In both of these cases, even if the user requests autoneg to be
> disabled, that _shouldn't_ affect internal network driver links.
> This ethtool op is about configuring the externally visible media
> side of the network driver, not the internal links.

I have a concern about this patch. Have you considered dwmac-intel with
its XPCS support, where the XPCS is used for Cisco SGMII and 1000base-X
support. Does the dwmac-intel version of the core set
priv->dma_cap.pcs? If it doesn't, then removing the test on this will
cause a regression, since in Cisco SGMII mode, we end up setting
priv->hw->pcs to SYMMAC_PCS_SGMII where we didn't before. As
priv->flags will not have STMMAC_FLAG_HAS_INTEGRATED_PCS, this will
enable all the "integrated PCS" code paths despite XPCS clearly
intending to be used for Cisco SGMII.

I'm also wondering whether the same applies to the lynx PCS as well,
or in the general case if we have any kind of external PCS.

Hence, I think this probably needs to be:

	if (phy_interface_mode_is_rgmii(interface))
		priv->hw->pcs = STMMAC_PCS_RGMII;
	else if (interface == PHY_INTERFACE_MODE_SGMII && priv->dma_cap.pcs)
		priv->hw->pcs = STMMAC_PCS_SGMII;

At least this is what unpicking the awful stmmac code suggests (and I
do feel that my point about the shocking state of this driver is proven
as details like this are extremely difficult to unpick, and not
unpicking them correctly will lead to regressions.) Therefore, I would
suggest that it would be wise if you also double-checked this.

If my analysis is correct, then my changes to stmmac_mac_select_pcs()
are also wrong.
Serge Semin May 26, 2024, 9:57 p.m. UTC | #3
On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > into the DW GMAC controller. It's always done if the controller supports
> > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > interfaces support was activated during the IP-core synthesize the PCS
> > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > set. Based on that the RGMII in-band status detection procedure
> > implemented in the driver hasn't been working for the devices with the
> > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > interfaces available in the device.
> > 
> > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > statement responsible for the In-band/PCS functionality activation. If the
> > RGMII interface is supported by the device then the in-band link status
> > detection will be also supported automatically (it's always embedded into
> > the RGMII RTL code). If the SGMII interface is supported by the device
> > then the PCS block will be supported too (it's unconditionally synthesized
> > into the controller). The later is also correct for the TBI/RTBI PHY
> > interfaces.
> > 
> > Note while at it drop the netdev_dbg() calls since at the moment of the
> > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > the debug prints will be for the unknown/NULL device.
> 

> Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> it seems to be fixing a bug in the driver as it stands today?

From one point of view it could be submitted for the net tree indeed,
but on the second thought are you sure we should be doing that seeing
it will activate the RGMII-inband detection and the code with the
netif-carrier toggling behind the phylink back? Who knows what new
regressions the activated PCS-code can cause?..

> 
> Also, a build fix is required here:
> 
> > -	if (priv->dma_cap.pcs) {
> > -		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> > -		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> > -		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> > -		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> > -			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> > -			priv->hw->pcs = STMMAC_PCS_RGMII;
> > -		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> > -			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> > -			priv->hw->pcs = STMMAC_PCS_SGMII;
> > -		}
> > -	}
> > +	if (phy_interface_mode_is_rgmii(interface))
> > +		priv->hw.pcs = STMMAC_PCS_RGMII;
> > +	else if (interface == PHY_INTERFACE_MODE_SGMII)
> > +		priv->hw.pcs = STMMAC_PCS_SGMII;
> 
> Both of these assignments should be priv->hw->pcs not priv->hw.pcs.

Ah, right. Originally I applied your patchset on top of my fixes,
cleanups and platform glue-driver patchsets. One of the cleanups
implied the mac_device_info instance movement to the stmmac_priv
structure. When I was moving my changes onto your original series I
just missed that part of the patch. Sorry about that. The rest of my
patches seems free from such problem.

> 
> I think there's also another bug that needs fixing along with this.
> See stmmac_ethtool_set_link_ksettings(). Note that this denies the
> ability to disable autoneg, which (a) doesn't make sense for RGMII
> with an attached PHY, and 

This doesn't make sense for RGMII also due to DW GMAC/QoS Eth not having
anything AN-related for the RGMII PHY interface. RGMII mode permits
the Link status detection via the in-band signal retrieved from the
PHY and nothing else. AN, if enabled, is performed on the PHY side.

> (b) this code should be passing the
> ethtool op to phylink for it to pass on to phylib so the PHY can
> be appropriately configured for the users desired autoneg and
> link mode settings.

I am not that well aware of the phylink internals to be saying for
100% sure, but thinking logically it would be indeed better if phylink
was aware of the PCS state changes. But in case of the STMMAC PCS
implementation I guess that the original PCS-code was designed to work
with no PHY being involved:
e58bb43f5e43 ("stmmac: initial support to manage pcs modes")
See that commit prevented the MDIO-bus registration and PHY
initialization in case of the PCS/RGMII-inband being available. But in
practice the implementation turned to be not that well thought
through. So eventually, commit-by-commit, the implementation was
effectively converted to the no longer used code. At least for the
MACs with just RGMII interface and no additional SGMII/TBI/RTBI
interfaces, which I guess is the vast majority of the real devices
with RGMII.

> 
> I also don't think it makes any sense for the STMMAC_PCS_SGMII case
> given that it means Cisco SGMII - which implies that there is also
> a PHY (since Cisco SGMII with inband is designed to be coupled with
> something that looks like a PHY to send the inband signalling
> necessary to configure e.g. the SGMII link symbol replication.

AFAICS the STMMAC driver supports the MAC2MAC case connected over
SGMII with no intermediate PHY. In that case the speed will be just
fixed to what was set in the "snps,ps-speed" property. The RAL (Rate
Adapter Layer) is configured to do that by having the SGMRAL flag set
(see your dwmac_pcs_config() and what is done if hw->ps is non-zero).

> 
> In both of these cases, even if the user requests autoneg to be
> disabled, that _shouldn't_ affect internal network driver links.
> This ethtool op is about configuring the externally visible media
> side of the network driver, not the internal links.

IMO considering all the driver over-complexity (that's the most polite
definition I managed to come up to.)) it would be much easier and
likely safer not to try to fix the PCS-code and just convert it to
something sane. At least the RGMII/In-band functionality we'll be able
to test on my device. If the PCS SGMII part is still utilized by
anybody, then if there are problems there the new kernel RCs will get
to reveal them.

-Serge(y)

> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle) May 28, 2024, 10:21 a.m. UTC | #4
On Mon, May 27, 2024 at 12:57:02AM +0300, Serge Semin wrote:
> On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> > On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > > into the DW GMAC controller. It's always done if the controller supports
> > > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > > interfaces support was activated during the IP-core synthesize the PCS
> > > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > > set. Based on that the RGMII in-band status detection procedure
> > > implemented in the driver hasn't been working for the devices with the
> > > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > > interfaces available in the device.
> > > 
> > > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > > statement responsible for the In-band/PCS functionality activation. If the
> > > RGMII interface is supported by the device then the in-band link status
> > > detection will be also supported automatically (it's always embedded into
> > > the RGMII RTL code). If the SGMII interface is supported by the device
> > > then the PCS block will be supported too (it's unconditionally synthesized
> > > into the controller). The later is also correct for the TBI/RTBI PHY
> > > interfaces.
> > > 
> > > Note while at it drop the netdev_dbg() calls since at the moment of the
> > > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > > the debug prints will be for the unknown/NULL device.
> > 
> 
> > Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> > it seems to be fixing a bug in the driver as it stands today?
> 
> From one point of view it could be submitted for the net tree indeed,
> but on the second thought are you sure we should be doing that seeing
> it will activate the RGMII-inband detection and the code with the
> netif-carrier toggling behind the phylink back? Who knows what new
> regressions the activated PCS-code can cause?..

If it's not a fix that is suitable without the remainder of the patch
set, this should be stated in the commit description and it shouldn't
have a Fixes: tag.

The reason is because it wouldn't be stable kernel material without the
other patches - if stable picks it up without the other patches then
it could end up being applied without the other patches resulting in
the situation you mention above.

Shall I remove the Fixes: tag?
Serge Semin May 28, 2024, 12:22 p.m. UTC | #5
On Tue, May 28, 2024 at 11:21:39AM +0100, Russell King (Oracle) wrote:
> On Mon, May 27, 2024 at 12:57:02AM +0300, Serge Semin wrote:
> > On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> > > On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > > > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > > > into the DW GMAC controller. It's always done if the controller supports
> > > > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > > > interfaces support was activated during the IP-core synthesize the PCS
> > > > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > > > set. Based on that the RGMII in-band status detection procedure
> > > > implemented in the driver hasn't been working for the devices with the
> > > > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > > > interfaces available in the device.
> > > > 
> > > > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > > > statement responsible for the In-band/PCS functionality activation. If the
> > > > RGMII interface is supported by the device then the in-band link status
> > > > detection will be also supported automatically (it's always embedded into
> > > > the RGMII RTL code). If the SGMII interface is supported by the device
> > > > then the PCS block will be supported too (it's unconditionally synthesized
> > > > into the controller). The later is also correct for the TBI/RTBI PHY
> > > > interfaces.
> > > > 
> > > > Note while at it drop the netdev_dbg() calls since at the moment of the
> > > > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > > > the debug prints will be for the unknown/NULL device.
> > > 
> > 
> > > Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> > > it seems to be fixing a bug in the driver as it stands today?
> > 
> > From one point of view it could be submitted for the net tree indeed,
> > but on the second thought are you sure we should be doing that seeing
> > it will activate the RGMII-inband detection and the code with the
> > netif-carrier toggling behind the phylink back? Who knows what new
> > regressions the activated PCS-code can cause?..
> 
> If it's not a fix that is suitable without the remainder of the patch
> set, this should be stated in the commit description and it shouldn't
> have a Fixes: tag.
> 
> The reason is because it wouldn't be stable kernel material without the
> other patches - if stable picks it up without the other patches then
> it could end up being applied without the other patches resulting in
> the situation you mention above.
> 
> Shall I remove the Fixes: tag?

Let's drop it then, so not to cause confusion for the maintainers.

-Serge(y)

> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Serge Semin May 28, 2024, 1:19 p.m. UTC | #6
On Sun, May 26, 2024 at 07:00:22PM +0100, Russell King (Oracle) wrote:
> On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> > On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > > into the DW GMAC controller. It's always done if the controller supports
> > > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > > interfaces support was activated during the IP-core synthesize the PCS
> > > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > > set. Based on that the RGMII in-band status detection procedure
> > > implemented in the driver hasn't been working for the devices with the
> > > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > > interfaces available in the device.
> > > 
> > > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > > statement responsible for the In-band/PCS functionality activation. If the
> > > RGMII interface is supported by the device then the in-band link status
> > > detection will be also supported automatically (it's always embedded into
> > > the RGMII RTL code). If the SGMII interface is supported by the device
> > > then the PCS block will be supported too (it's unconditionally synthesized
> > > into the controller). The later is also correct for the TBI/RTBI PHY
> > > interfaces.
> > > 
> > > Note while at it drop the netdev_dbg() calls since at the moment of the
> > > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > > the debug prints will be for the unknown/NULL device.
> > 
> > Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> > it seems to be fixing a bug in the driver as it stands today?
> > 
> > Also, a build fix is required here:
> > 
> > > -	if (priv->dma_cap.pcs) {
> > > -		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> > > -		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> > > -		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> > > -		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> > > -			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> > > -			priv->hw->pcs = STMMAC_PCS_RGMII;
> > > -		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> > > -			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> > > -			priv->hw->pcs = STMMAC_PCS_SGMII;
> > > -		}
> > > -	}
> > > +	if (phy_interface_mode_is_rgmii(interface))
> > > +		priv->hw.pcs = STMMAC_PCS_RGMII;
> > > +	else if (interface == PHY_INTERFACE_MODE_SGMII)
> > > +		priv->hw.pcs = STMMAC_PCS_SGMII;
> > 
> > Both of these assignments should be priv->hw->pcs not priv->hw.pcs.
> > 
> > I think there's also another bug that needs fixing along with this.
> > See stmmac_ethtool_set_link_ksettings(). Note that this denies the
> > ability to disable autoneg, which (a) doesn't make sense for RGMII
> > with an attached PHY, and (b) this code should be passing the
> > ethtool op to phylink for it to pass on to phylib so the PHY can
> > be appropriately configured for the users desired autoneg and
> > link mode settings.
> > 
> > I also don't think it makes any sense for the STMMAC_PCS_SGMII case
> > given that it means Cisco SGMII - which implies that there is also
> > a PHY (since Cisco SGMII with inband is designed to be coupled with
> > something that looks like a PHY to send the inband signalling
> > necessary to configure e.g. the SGMII link symbol replication.
> > 
> > In both of these cases, even if the user requests autoneg to be
> > disabled, that _shouldn't_ affect internal network driver links.
> > This ethtool op is about configuring the externally visible media
> > side of the network driver, not the internal links.
> 

> I have a concern about this patch. Have you considered dwmac-intel with
> its XPCS support, where the XPCS is used for Cisco SGMII and 1000base-X
> support. Does the dwmac-intel version of the core set
> priv->dma_cap.pcs? If it doesn't, then removing the test on this will
> cause a regression, since in Cisco SGMII mode, we end up setting
> priv->hw->pcs to SYMMAC_PCS_SGMII where we didn't before. As
> priv->flags will not have STMMAC_FLAG_HAS_INTEGRATED_PCS, this will
> enable all the "integrated PCS" code paths despite XPCS clearly
> intending to be used for Cisco SGMII.
> 
> I'm also wondering whether the same applies to the lynx PCS as well,
> or in the general case if we have any kind of external PCS.
> 
> Hence, I think this probably needs to be:
> 
> 	if (phy_interface_mode_is_rgmii(interface))
> 		priv->hw->pcs = STMMAC_PCS_RGMII;
> 	else if (interface == PHY_INTERFACE_MODE_SGMII && priv->dma_cap.pcs)
> 		priv->hw->pcs = STMMAC_PCS_SGMII;
> 
> At least this is what unpicking the awful stmmac code suggests (and I
> do feel that my point about the shocking state of this driver is proven
> as details like this are extremely difficult to unpick, and not
> unpicking them correctly will lead to regressions.) Therefore, I would
> suggest that it would be wise if you also double-checked this.

Double-checked that part. Indeed this is what I forgot to take into
account. (Just realized I had a glimpse thought about checking the DW
xGMAC/XPCS for supporting the SGMII interface, but the thought got
away from my mind forgotten.) DW XPCS can be synthesized with having
the GMII/MII interface connected to the MAC and SGMII downstream
interface over a single 1000Base-X lane.

In anyway AFAICS that case has nothing to do with the PCS embedded
into the DW GMAC or DW QoS Eth synthesized with the SGMII support. DW
XGMAC has no embedded PCS, but could be attached to the separate DW
XPCS device.

About the correct implementation. Right, priv->dma_cap.pcs indicates
that there is an embedded PCS and the flag can be set for DW GMAC or DW
QoS Eth only. Although I would change the order:

       if (phy_interface_mode_is_rgmii(interface))
               priv->hw->pcs = STMMAC_PCS_RGMII;
       else if (priv->dma_cap.pcs && interface == PHY_INTERFACE_MODE_SGMII)
               priv->hw->pcs = STMMAC_PCS_SGMII;

since priv->dma_cap.pcs is a primary flag. If it isn't set the
interface will be irrelevant.

Alternative solution could be to use the has_gmac/has_gmac4 flags
instead. That will emphasize that the embedded PCS is expected to be
specific for the DW GMAC and DW QoS Eth IP-cores:

       if (phy_interface_mode_is_rgmii(interface))
               priv->hw->pcs = STMMAC_PCS_RGMII;
       else if ((priv->plat.has_gmac || priv->plat.has_gmac4) &&
		interface == PHY_INTERFACE_MODE_SGMII)
               priv->hw->pcs = STMMAC_PCS_SGMII;

-Serge(y)

> 
> If my analysis is correct, then my changes to stmmac_mac_select_pcs()
> are also wrong.
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle) May 28, 2024, 2:13 p.m. UTC | #7
On Tue, May 28, 2024 at 04:19:49PM +0300, Serge Semin wrote:
> On Sun, May 26, 2024 at 07:00:22PM +0100, Russell King (Oracle) wrote:
> > On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> > > On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > > > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > > > into the DW GMAC controller. It's always done if the controller supports
> > > > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > > > interfaces support was activated during the IP-core synthesize the PCS
> > > > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > > > set. Based on that the RGMII in-band status detection procedure
> > > > implemented in the driver hasn't been working for the devices with the
> > > > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > > > interfaces available in the device.
> > > > 
> > > > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > > > statement responsible for the In-band/PCS functionality activation. If the
> > > > RGMII interface is supported by the device then the in-band link status
> > > > detection will be also supported automatically (it's always embedded into
> > > > the RGMII RTL code). If the SGMII interface is supported by the device
> > > > then the PCS block will be supported too (it's unconditionally synthesized
> > > > into the controller). The later is also correct for the TBI/RTBI PHY
> > > > interfaces.
> > > > 
> > > > Note while at it drop the netdev_dbg() calls since at the moment of the
> > > > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > > > the debug prints will be for the unknown/NULL device.
> > > 
> > > Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> > > it seems to be fixing a bug in the driver as it stands today?
> > > 
> > > Also, a build fix is required here:
> > > 
> > > > -	if (priv->dma_cap.pcs) {
> > > > -		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> > > > -		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> > > > -		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> > > > -		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> > > > -			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> > > > -			priv->hw->pcs = STMMAC_PCS_RGMII;
> > > > -		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> > > > -			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> > > > -			priv->hw->pcs = STMMAC_PCS_SGMII;
> > > > -		}
> > > > -	}
> > > > +	if (phy_interface_mode_is_rgmii(interface))
> > > > +		priv->hw.pcs = STMMAC_PCS_RGMII;
> > > > +	else if (interface == PHY_INTERFACE_MODE_SGMII)
> > > > +		priv->hw.pcs = STMMAC_PCS_SGMII;
> > > 
> > > Both of these assignments should be priv->hw->pcs not priv->hw.pcs.
> > > 
> > > I think there's also another bug that needs fixing along with this.
> > > See stmmac_ethtool_set_link_ksettings(). Note that this denies the
> > > ability to disable autoneg, which (a) doesn't make sense for RGMII
> > > with an attached PHY, and (b) this code should be passing the
> > > ethtool op to phylink for it to pass on to phylib so the PHY can
> > > be appropriately configured for the users desired autoneg and
> > > link mode settings.
> > > 
> > > I also don't think it makes any sense for the STMMAC_PCS_SGMII case
> > > given that it means Cisco SGMII - which implies that there is also
> > > a PHY (since Cisco SGMII with inband is designed to be coupled with
> > > something that looks like a PHY to send the inband signalling
> > > necessary to configure e.g. the SGMII link symbol replication.
> > > 
> > > In both of these cases, even if the user requests autoneg to be
> > > disabled, that _shouldn't_ affect internal network driver links.
> > > This ethtool op is about configuring the externally visible media
> > > side of the network driver, not the internal links.
> > 
> 
> > I have a concern about this patch. Have you considered dwmac-intel with
> > its XPCS support, where the XPCS is used for Cisco SGMII and 1000base-X
> > support. Does the dwmac-intel version of the core set
> > priv->dma_cap.pcs? If it doesn't, then removing the test on this will
> > cause a regression, since in Cisco SGMII mode, we end up setting
> > priv->hw->pcs to SYMMAC_PCS_SGMII where we didn't before. As
> > priv->flags will not have STMMAC_FLAG_HAS_INTEGRATED_PCS, this will
> > enable all the "integrated PCS" code paths despite XPCS clearly
> > intending to be used for Cisco SGMII.
> > 
> > I'm also wondering whether the same applies to the lynx PCS as well,
> > or in the general case if we have any kind of external PCS.
> > 
> > Hence, I think this probably needs to be:
> > 
> > 	if (phy_interface_mode_is_rgmii(interface))
> > 		priv->hw->pcs = STMMAC_PCS_RGMII;
> > 	else if (interface == PHY_INTERFACE_MODE_SGMII && priv->dma_cap.pcs)
> > 		priv->hw->pcs = STMMAC_PCS_SGMII;
> > 
> > At least this is what unpicking the awful stmmac code suggests (and I
> > do feel that my point about the shocking state of this driver is proven
> > as details like this are extremely difficult to unpick, and not
> > unpicking them correctly will lead to regressions.) Therefore, I would
> > suggest that it would be wise if you also double-checked this.
> 
> Double-checked that part. Indeed this is what I forgot to take into
> account.

Thanks for double-checking it.

> (Just realized I had a glimpse thought about checking the DW
> xGMAC/XPCS for supporting the SGMII interface, but the thought got
> away from my mind forgotten.) DW XPCS can be synthesized with having
> the GMII/MII interface connected to the MAC and SGMII downstream
> interface over a single 1000Base-X lane.
> 
> In anyway AFAICS that case has nothing to do with the PCS embedded
> into the DW GMAC or DW QoS Eth synthesized with the SGMII support. DW
> XGMAC has no embedded PCS, but could be attached to the separate DW
> XPCS device.

This is where my head starts spinning, because identifying what
"DW GMAC" and "DW QoS Eth" refer to is difficult unless one, I guess,
has the documentation.

The only references to QoS that I can find in the driver refer to
per-DMA channel interrupts, dwmac5* and one mention for a platform
driver in the Kconfig.

Grepping for "DW GMAC" doesn't give anything.

Conversely, I know from the code that only dwmac4 and dwmac1000
have support for the integrated PCS. So trying to put this together
doesn't make much sense to me. :/

Maybe "DW QoS Eth" refers to dwmac-dwc-qos-eth.c?

> About the correct implementation. Right, priv->dma_cap.pcs indicates
> that there is an embedded PCS and the flag can be set for DW GMAC or DW
> QoS Eth only. Although I would change the order:
> 
>        if (phy_interface_mode_is_rgmii(interface))
>                priv->hw->pcs = STMMAC_PCS_RGMII;
>        else if (priv->dma_cap.pcs && interface == PHY_INTERFACE_MODE_SGMII)
>                priv->hw->pcs = STMMAC_PCS_SGMII;
> 
> since priv->dma_cap.pcs is a primary flag. If it isn't set the
> interface will be irrelevant.

As this is generic code, it probably makes sense to go with that, since
priv->dma_cap.pcs indicates whether the internal PCS for SGMII is
present or not rather than...

> Alternative solution could be to use the has_gmac/has_gmac4 flags
> instead. That will emphasize that the embedded PCS is expected to be
> specific for the DW GMAC and DW QoS Eth IP-cores:
> 
>        if (phy_interface_mode_is_rgmii(interface))
>                priv->hw->pcs = STMMAC_PCS_RGMII;
>        else if ((priv->plat.has_gmac || priv->plat.has_gmac4) &&
> 		interface == PHY_INTERFACE_MODE_SGMII)
>                priv->hw->pcs = STMMAC_PCS_SGMII;

which implies that gmac (dwgmac1000_core.c) and gmac4 (dwgmac4_core.c)
will always have its internal PCS if we're using SGMII mode. Does this
mean it is true that these cores will never be used with an external
PCS?

If there is a hardware flag that indicates the PCS is implemented, then
I think using that to gate whether SGMII uses the internal PCS is
better rather than using the core type.

Please can you confirm that if an external PCS (e.g. xpcs, lynx PCS)
is being used, the internal PCS will not have been synthesized, and
thus priv->dma_cap.pcs will be false? The reason I'd like to know
this is because in the future, I'd like to eliminate priv->hw->pcs,
and just have dwmac1000/dwmac4's phylink_select_pcs() method make
the decisions.

If not, then we need to think about the behaviour that
stmmac_mac_select_pcs(0 should have. Should it give priority to the
internal PCS over external PCS, or external PCS first (in which case
what do we need to do with the internal PCS.)
Russell King (Oracle) May 28, 2024, 4:21 p.m. UTC | #8
On Tue, May 28, 2024 at 03:13:32PM +0100, Russell King (Oracle) wrote:
> > Alternative solution could be to use the has_gmac/has_gmac4 flags
> > instead. That will emphasize that the embedded PCS is expected to be
> > specific for the DW GMAC and DW QoS Eth IP-cores:
> > 
> >        if (phy_interface_mode_is_rgmii(interface))
> >                priv->hw->pcs = STMMAC_PCS_RGMII;
> >        else if ((priv->plat.has_gmac || priv->plat.has_gmac4) &&
> > 		interface == PHY_INTERFACE_MODE_SGMII)
> >                priv->hw->pcs = STMMAC_PCS_SGMII;
> 
> which implies that gmac (dwgmac1000_core.c) and gmac4 (dwgmac4_core.c)
> will always have its internal PCS if we're using SGMII mode. Does this
> mean it is true that these cores will never be used with an external
> PCS?

Sorry to go off on a related tangent, but I've just been looking at
hw->ps which is related to this.

As I understand, hw->ps comes from the "snps,ps-speed" property in DT,
which is used for SGMII and MAC2MAC connections. Presumably for the
SGMII case, this is used where the port is made to look like the PHY
end of the SGMII link.

I'm guessing MAC2MAC refers to RGMII, or does that also refer to
SGMII-as-PHY?

I think it would've been nice to have picked SGMII-as-PHY up in the
driver earlier - we don't tend to use the "normal" PHY interface
mode names, instead we have the REVxxx modes, so I think this
_should_ have introduced PHY_INTERFACE_MODE_REVSGMII.

In any case, moving on... in stmmac_hw_setup(), we have:

        /* PS and related bits will be programmed according to the speed */
        if (priv->hw->pcs) {
                int speed = priv->plat->mac_port_sel_speed;

                if ((speed == SPEED_10) || (speed == SPEED_100) ||
                    (speed == SPEED_1000)) {
                        priv->hw->ps = speed;
                } else {
                        dev_warn(priv->device, "invalid port speed\n");
                        priv->hw->ps = 0;
                }
        }

Which means that if we're using the integrated PCS, then we basically
require the "snps,ps-speed" property otherwise we'll issue a warning
at this point... this seems to imply that reverse mode is the only
mode supported, which I'm fairly sure is false. So, maybe this
shouldn't be issuing the warning if mac_port_sel_speed was zero?

Moving on... hw->ps can only be 10M, 100M or 1G speeds and nothing else
- which is fine since RGMII and Cisco SGMII only support these speeds.

dwmac1000 tests for this against these speeds, so it is also fine.

dwmac4 is basically the same as dwmac1000, so is also fine.

The core code as it stands today passes this into the pcs_ctrl_ane
method's rsgmi_ral argument, which sets GMAC_AN_CTRL_SGMRAL. Presumably
this selects "reverse" mode for both SGMII and RGMII?

Persuing this a bit futher, qcom-ethqos always calls this with rsgmi_ral
clear. Presumably, qcom-ethqos never specifies "snps,ps-speed" in DT,
and thus always gets the warning above?

Finally, we get to the core issue, which is dwxgmac2_core.c.
dwxgmac2 tests this member against 10G, 2.5G and "any other non-zero
value". Out of all of these, the only possible path through that code
would be the one which results in:

	tx |= hw->link.speed1000;

Neither of the other two (2.5G and 10G) are possible because those
aren't legal values for hw->ps. Moreover, it doesn't appear to have
any kind of PCS, so I'm wondering whether any of this code gets used.


So, I suspect some of this is "not quite right" either, and I wonder
about the implications of changing how hw->pcs is set - whether we
first need to fix the code above dealing with priv->hw->ps ?

I'm also wondering what impact this has on my PCS conversion.
Serge Semin May 31, 2024, 5:13 p.m. UTC | #9
On Tue, May 28, 2024 at 03:13:32PM +0100, Russell King (Oracle) wrote:
> On Tue, May 28, 2024 at 04:19:49PM +0300, Serge Semin wrote:
> > On Sun, May 26, 2024 at 07:00:22PM +0100, Russell King (Oracle) wrote:
> > > On Sun, May 26, 2024 at 05:49:48PM +0100, Russell King (Oracle) wrote:
> > > > On Sat, May 25, 2024 at 12:02:58AM +0300, Serge Semin wrote:
> > > > > The HWFEATURE.PCSSEL flag is set if the PCS block has been synthesized
> > > > > into the DW GMAC controller. It's always done if the controller supports
> > > > > at least one of the SGMII, TBI, RTBI PHY interfaces. If none of these
> > > > > interfaces support was activated during the IP-core synthesize the PCS
> > > > > block won't be activated either and the HWFEATURE.PCSSEL flag won't be
> > > > > set. Based on that the RGMII in-band status detection procedure
> > > > > implemented in the driver hasn't been working for the devices with the
> > > > > RGMII interface support and with none of the SGMII, TBI, RTBI PHY
> > > > > interfaces available in the device.
> > > > > 
> > > > > Fix that just by dropping the dma_cap.pcs flag check from the conditional
> > > > > statement responsible for the In-band/PCS functionality activation. If the
> > > > > RGMII interface is supported by the device then the in-band link status
> > > > > detection will be also supported automatically (it's always embedded into
> > > > > the RGMII RTL code). If the SGMII interface is supported by the device
> > > > > then the PCS block will be supported too (it's unconditionally synthesized
> > > > > into the controller). The later is also correct for the TBI/RTBI PHY
> > > > > interfaces.
> > > > > 
> > > > > Note while at it drop the netdev_dbg() calls since at the moment of the
> > > > > stmmac_check_pcs_mode() invocation the network device isn't registered. So
> > > > > the debug prints will be for the unknown/NULL device.
> > > > 
> > > > Thanks. As this is a fix, shouldn't it be submitted for the net tree as
> > > > it seems to be fixing a bug in the driver as it stands today?
> > > > 
> > > > Also, a build fix is required here:
> > > > 
> > > > > -	if (priv->dma_cap.pcs) {
> > > > > -		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
> > > > > -		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
> > > > > -		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
> > > > > -		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
> > > > > -			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
> > > > > -			priv->hw->pcs = STMMAC_PCS_RGMII;
> > > > > -		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
> > > > > -			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
> > > > > -			priv->hw->pcs = STMMAC_PCS_SGMII;
> > > > > -		}
> > > > > -	}
> > > > > +	if (phy_interface_mode_is_rgmii(interface))
> > > > > +		priv->hw.pcs = STMMAC_PCS_RGMII;
> > > > > +	else if (interface == PHY_INTERFACE_MODE_SGMII)
> > > > > +		priv->hw.pcs = STMMAC_PCS_SGMII;
> > > > 
> > > > Both of these assignments should be priv->hw->pcs not priv->hw.pcs.
> > > > 
> > > > I think there's also another bug that needs fixing along with this.
> > > > See stmmac_ethtool_set_link_ksettings(). Note that this denies the
> > > > ability to disable autoneg, which (a) doesn't make sense for RGMII
> > > > with an attached PHY, and (b) this code should be passing the
> > > > ethtool op to phylink for it to pass on to phylib so the PHY can
> > > > be appropriately configured for the users desired autoneg and
> > > > link mode settings.
> > > > 
> > > > I also don't think it makes any sense for the STMMAC_PCS_SGMII case
> > > > given that it means Cisco SGMII - which implies that there is also
> > > > a PHY (since Cisco SGMII with inband is designed to be coupled with
> > > > something that looks like a PHY to send the inband signalling
> > > > necessary to configure e.g. the SGMII link symbol replication.
> > > > 
> > > > In both of these cases, even if the user requests autoneg to be
> > > > disabled, that _shouldn't_ affect internal network driver links.
> > > > This ethtool op is about configuring the externally visible media
> > > > side of the network driver, not the internal links.
> > > 
> > 
> > > I have a concern about this patch. Have you considered dwmac-intel with
> > > its XPCS support, where the XPCS is used for Cisco SGMII and 1000base-X
> > > support. Does the dwmac-intel version of the core set
> > > priv->dma_cap.pcs? If it doesn't, then removing the test on this will
> > > cause a regression, since in Cisco SGMII mode, we end up setting
> > > priv->hw->pcs to SYMMAC_PCS_SGMII where we didn't before. As
> > > priv->flags will not have STMMAC_FLAG_HAS_INTEGRATED_PCS, this will
> > > enable all the "integrated PCS" code paths despite XPCS clearly
> > > intending to be used for Cisco SGMII.
> > > 
> > > I'm also wondering whether the same applies to the lynx PCS as well,
> > > or in the general case if we have any kind of external PCS.
> > > 
> > > Hence, I think this probably needs to be:
> > > 
> > > 	if (phy_interface_mode_is_rgmii(interface))
> > > 		priv->hw->pcs = STMMAC_PCS_RGMII;
> > > 	else if (interface == PHY_INTERFACE_MODE_SGMII && priv->dma_cap.pcs)
> > > 		priv->hw->pcs = STMMAC_PCS_SGMII;
> > > 
> > > At least this is what unpicking the awful stmmac code suggests (and I
> > > do feel that my point about the shocking state of this driver is proven
> > > as details like this are extremely difficult to unpick, and not
> > > unpicking them correctly will lead to regressions.) Therefore, I would
> > > suggest that it would be wise if you also double-checked this.
> > 
> > Double-checked that part. Indeed this is what I forgot to take into
> > account.
> 
> Thanks for double-checking it.
> 
> > (Just realized I had a glimpse thought about checking the DW
> > xGMAC/XPCS for supporting the SGMII interface, but the thought got
> > away from my mind forgotten.) DW XPCS can be synthesized with having
> > the GMII/MII interface connected to the MAC and SGMII downstream
> > interface over a single 1000Base-X lane.
> > 
> > In anyway AFAICS that case has nothing to do with the PCS embedded
> > into the DW GMAC or DW QoS Eth synthesized with the SGMII support. DW
> > XGMAC has no embedded PCS, but could be attached to the separate DW
> > XPCS device.
> 

> This is where my head starts spinning, because identifying what
> "DW GMAC" and "DW QoS Eth" refer to is difficult unless one, I guess,
> has the documentation.
> 
> The only references to QoS that I can find in the driver refer to
> per-DMA channel interrupts, dwmac5* and one mention for a platform
> driver in the Kconfig.
> 
> Grepping for "DW GMAC" doesn't give anything.
> 
> Conversely, I know from the code that only dwmac4 and dwmac1000
> have support for the integrated PCS. So trying to put this together
> doesn't make much sense to me. :/
> 
> Maybe "DW QoS Eth" refers to dwmac-dwc-qos-eth.c?

DW QoS Eth is the new generation of the Synopsys Gigabit Ethernet
IP-cores. Old ones are considered of version 3.74a and older:
https://www.synopsys.com/dw/ipdir.php?ds=dwc_ether_mac10_100_1000_unive
The new ones are of the version 4.0 and higher (the most modern
DW QoS Eth IP-core is of v5.40a):
https://www.synopsys.com/dw/ipdir.php?ds=dwc_ether_qos

This is better summarised in the driver doc:

Documentation/networking/device_drivers/ethernet/stmicro/stmmac.rst

which has outdated a bit, but the summary table looks correct anyway:

+-------------------------------+--------------+--------------+--------------+
| Controller Name               | Min. Version | Max. Version | Abbrev. Name |
+===============================+==============+==============+==============+
| Ethernet MAC Universal        | N/A          | 3.73a        | GMAC         |
+-------------------------------+--------------+--------------+--------------+
| Ethernet Quality-of-Service   | 4.00a        | N/A          | GMAC4+       |
+-------------------------------+--------------+--------------+--------------+
| XGMAC - 10G Ethernet MAC      | 2.10a        | N/A          | XGMAC2+      |
+-------------------------------+--------------+--------------+--------------+
| XLGMAC - 100G Ethernet MAC    | 2.00a        | N/A          | XLGMAC2+     |
+-------------------------------+--------------+--------------+--------------+

See the abbreviation and controller names. When I say just DW GMAC
then it means DW Ether MAC 10/100/1000 Universal, which driver is
implemented in the dwmac1000* files. If you see DW GMAC4/GMAC5 or DW
GAC4+ or DW QoE Eth, then it means DW Ethernet Quality-of-Service
IP-core, which driver could be found in dwmac4*/dwmac5* files.

As it inferable from the IP-core names the main difference between DW
Ether MAC 10/100/1000 Universal and DW Ethernet Quality-of-Service is
that the later one supports multiple queues and channels with a
comprehensive list of the optional traffic scheduling features (FPE,
TBS, DCB, AV-bridging, etc). DW GMAC doesn't have as many such
features. The only way to have DW GMAC synthesized with the multiple
DMA channels support is to enable a singly available traffic
scheduling feature - AV-bridging. Note AV-bridging enabled on the DW
GMAC v3.73a is the case of the Loongson GNET controller, which support
is implemented in the Yanteng Si patchset recently submitted for v13
review:
https://lore.kernel.org/netdev/cover.1716973237.git.siyanteng@loongson.cn/

In some extent the CSRs mapping is also different in DW GMAC v3.x and
GMAC v4.x/v5.x, but the main part is in the QoS features.

> 
> > About the correct implementation. Right, priv->dma_cap.pcs indicates
> > that there is an embedded PCS and the flag can be set for DW GMAC or DW
> > QoS Eth only. Although I would change the order:
> > 
> >        if (phy_interface_mode_is_rgmii(interface))
> >                priv->hw->pcs = STMMAC_PCS_RGMII;
> >        else if (priv->dma_cap.pcs && interface == PHY_INTERFACE_MODE_SGMII)
> >                priv->hw->pcs = STMMAC_PCS_SGMII;
> > 
> > since priv->dma_cap.pcs is a primary flag. If it isn't set the
> > interface will be irrelevant.
> 

> As this is generic code, it probably makes sense to go with that, since
> priv->dma_cap.pcs indicates whether the internal PCS for SGMII is
> present or not rather than...

Right.

> 
> > Alternative solution could be to use the has_gmac/has_gmac4 flags
> > instead. That will emphasize that the embedded PCS is expected to be
> > specific for the DW GMAC and DW QoS Eth IP-cores:
> > 
> >        if (phy_interface_mode_is_rgmii(interface))
> >                priv->hw->pcs = STMMAC_PCS_RGMII;
> >        else if ((priv->plat.has_gmac || priv->plat.has_gmac4) &&
> > 		interface == PHY_INTERFACE_MODE_SGMII)
> >                priv->hw->pcs = STMMAC_PCS_SGMII;
> 

> which implies that gmac (dwgmac1000_core.c) and gmac4 (dwgmac4_core.c)
> will always have its internal PCS if we're using SGMII mode.

Right. If the DW GMAC/QoS Eth IP-core is synthesized with the
SGMII/RTBI/RBI PHY interface then the internal PCS will always be
available and the HWFEATURE.PCSSEL flag will be set. Here is the
PCSSEL flag value definition:
DW QoS Eth: DWC_EQOS_PCS_EN = DWC_EQOS_TBI_EN || DWC_EQOS_SGMII_EN || DWC_EQOS_RTBI_EN
DW GMAC: if TBI, SGMII, or RTBI PHY interface is enabled.

> Does this
> mean it is true that these cores will never be used with an external
> PCS?

Sorry, I was wrong to suggest the (priv->plat.has_gmac ||
priv->plat.has_gmac4)-based statement. Indeed there is a case of having DW
QoS Eth and DW XPCS synthesized together with the SGMII/1000Base-X
downstream interface. Not sure why it was needed to implement that way
seeing DW QoS Eth IP-core supports optional SGMII PHY interface out of
box, but AFAICS Intel mGBE is that case. Anyway the correct way to
detect the internal PCS support is to check the PCSSEL flag set in the
HWFEATURE register (preserved in the stmmac_priv::dma_cap::pcs field).

> 
> If there is a hardware flag that indicates the PCS is implemented, then
> I think using that to gate whether SGMII uses the internal PCS is
> better rather than using the core type.

Right.

> 
> Please can you confirm that if an external PCS (e.g. xpcs, lynx PCS)
> is being used, the internal PCS will not have been synthesized, and
> thus priv->dma_cap.pcs will be false?

Alas I can't confirm that. priv->dma_cap.pcs only indicates the
internal PCS availability. External PCS is an independent entity from
the DW *MAC IP-core point of view. So the DW GMAC/QoS Eth/XGMAC
controllers aren't aware of its existence. It's the low-level platform
driver/code responsibility to somehow detect it being available
("pcs-handle" property, plat->mdio_bus_data->has_xpcs flag, etc).

Regarding the internal PCS, as long as the DW GMAC or DW QoS Eth is
synthesized with the SGMII/TBI/RTBI PHY interface support
priv->dma_cap.pcs will get to be true. Note the device can be
synthesized with several PHY interfaces supported. As long as
SGMII/TBI/RTBI PHY interface is any of them, the flag will be set
irrespective from the PHY interface activated at runtime. 

> The reason I'd like to know
> this is because in the future, I'd like to eliminate priv->hw->pcs,
> and just have dwmac1000/dwmac4's phylink_select_pcs() method make
> the decisions.

You can extend the priv->dma_cap.pcs flag semantics. So it could
be indicating three types of the PCS'es:
RGMII, SGMII, XPCS (or TBI/RTBI in future).

> 
> If not, then we need to think about the behaviour that
> stmmac_mac_select_pcs(0 should have. Should it give priority to the
> internal PCS over external PCS, or external PCS first (in which case
> what do we need to do with the internal PCS.)

I guess the DW XPCS implementation might be more preferable. From one
side DW XPCS SGMII can support up to 2.5Gbps speed, while the DW
GMAC/QoS Eth SGMII can work with up to 1Gbps speed only. On the other
hand the DW XPCS might be available over the MDIO-bus, which is slower
to access than the internal PCS CSRs available in the DW GMAC/QoS Eth
CSRs space. So the more performant link speed seems more useful
feature over the faster device setup process.

One thing I am not sure about is that there is a real case of having
the DW GMAC/QoS Eth synthesized with the native SGMII/TBI/RTBI PHY
interface support and being attached to the DW XPCS controller, which
would have the SGMII downstream PHY interface. DW XPCS has only the
XGMII or GMII/MII upstream interfaces over which the MAC can be
attached. So DW GMAC/QoS Eth and DW XPCS can be connected via the
GMII/MII interface only. Regarding Intel mGBE, it likely is having a
setup like this:

+------------+          +---------+
|            | GMII/MII |         |   SGMII
| DW QoS Eth +----------+ DW XPCS +------------
|            |          |         | 1000Base-X
+------------+          +---------+

-Serge(y)

> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Serge Semin May 31, 2024, 7:11 p.m. UTC | #10
On Tue, May 28, 2024 at 05:21:44PM +0100, Russell King (Oracle) wrote:
> On Tue, May 28, 2024 at 03:13:32PM +0100, Russell King (Oracle) wrote:
> > > Alternative solution could be to use the has_gmac/has_gmac4 flags
> > > instead. That will emphasize that the embedded PCS is expected to be
> > > specific for the DW GMAC and DW QoS Eth IP-cores:
> > > 
> > >        if (phy_interface_mode_is_rgmii(interface))
> > >                priv->hw->pcs = STMMAC_PCS_RGMII;
> > >        else if ((priv->plat.has_gmac || priv->plat.has_gmac4) &&
> > > 		interface == PHY_INTERFACE_MODE_SGMII)
> > >                priv->hw->pcs = STMMAC_PCS_SGMII;
> > 
> > which implies that gmac (dwgmac1000_core.c) and gmac4 (dwgmac4_core.c)
> > will always have its internal PCS if we're using SGMII mode. Does this
> > mean it is true that these cores will never be used with an external
> > PCS?
> 

> Sorry to go off on a related tangent, but I've just been looking at
> hw->ps which is related to this.

I was meditating around the hw->ps part for several days on the last
week and just gave up in finding of how that semantics could be
incorporated in the phylink pcs logic...

> 
> As I understand, hw->ps comes from the "snps,ps-speed" property in DT,
> which is used for SGMII and MAC2MAC connections. Presumably for the
> SGMII case, this is used where the port is made to look like the PHY
> end of the SGMII link.

Right. The speed comes from the "snps,ps-speed" property and is
utilized to set the particular port speed in the MAC2MAC case. But
neither DW QoS Eth nor DW GMAC HW-manual explicitly describe that
case. The only SGMII MAC2MAC mention there is GMAC_AN_CTRL_SGMRAL flag
description:

"SGMII RAL Control

When set, this bit forces the SGMII RAL block to operate in the speed
configured in the Speed and Port Select bits of the MAC Configuration
register. This is useful when the SGMII interface is used in a direct
MAC to MAC connection (without a PHY) and any MAC must reconfigure the
speed.  When reset, the SGMII RAL block operates according to the link
speed status received on SGMII (from the PHY).

This bit is reserved (and RO) if the SGMII PHY interface is not
selected during core configuration."

> 
> I'm guessing MAC2MAC refers to RGMII, or does that also refer to
> SGMII-as-PHY?

I guess that it can be utilized in both cases: RGMII-to-RGMII and
SGMII-to-SGMII MAC2MAC setups. The only difference is that the
GMAC_AN_CTRL_SGMRAL flag setting would be useless for RGMII. But
originally the mac_device_info::ps field was introduced for the SGMII
MAC2MAC config here:
02e57b9d7c8c ("drivers: net: stmmac: add port selection programming")
and the "snps,ps-speed" property can be spotted alongside with 
phy-mode = "sgmii" only, here:
arch/arm64/boot/dts/qcom/sa8775p-ride.dts

Although AFAICS the dwmac1000_core_init()/dwmac4_core_init() methods
lack of the GMAC_CONTROL_TC/GMAC_PHYIF_CTRLSTATUS_TC flags set in the
(hw->ps)-related if-clause. Without that the specified speed setting
won't be in-bend delivered to the other side of the MAC2MAC link and
the internal PCS functionality won't work. Synopsys DW GMAC/Qos Eth
databooks explicitly say that these flags need to be set for the MAC
to be sending its Port speed, Duplex mode and Link Up/Down flag
setting over the RGMII/SGMII in-band signal:

SGMII: "The tx_config_reg[15:0] bits sent by the MAC during
Auto-negotiation depend on whether the Transmit Configuration register
bit is enabled for the SGMII interface."

RGMII: "When the RGMII interface is configured to transmit the
configuration during the IFG, then rgmii_txd[3:0] reflects the Duplex
Mode, Port Select, Speed (encoded as 00 for 10 Mbps, 01 for 100 Mbps
and 10 for 1000 Mbps), and Link Up/Down bits of the MAC Configuration
Register,"

TC flag description:
"Transmit Configuration in RGMII, SGMII, or SMII

When set, this bit enables the transmission of duplex mode, link
speed, and link up or down information to the PHY in the RGMII, SMII,
or SGMII port. When this bit is reset, no such information is driven
to the PHY. This bit is reserved (and RO) if the RGMII, SMII, or SGMII
PHY port is not selected during core configuration."

> 
> I think it would've been nice to have picked SGMII-as-PHY up in the
> driver earlier - we don't tend to use the "normal" PHY interface
> mode names, instead we have the REVxxx modes, so I think this
> _should_ have introduced PHY_INTERFACE_MODE_REVSGMII.

Not sure whether it would be a correct thing to do. RevMII is a real
interface. DW GMAC/QoS Eth can be synthesized with RevMII PHY
interface support. Mac2Mac SGMII/RGMII is a feature of the standard
SGMII/RGMII interfaces.

On the other hand we already have the set of the artificial modes like
"rgmii-id/rgmii-txid/rgmii-rxid" indicating the MAC-side delays but
describing the same interfaces. So I don't have a strong opinion
against have the modes like "rev-rgmii"/"rev-sgmii".

> 
> In any case, moving on... in stmmac_hw_setup(), we have:
> 
>         /* PS and related bits will be programmed according to the speed */
>         if (priv->hw->pcs) {
>                 int speed = priv->plat->mac_port_sel_speed;
> 
>                 if ((speed == SPEED_10) || (speed == SPEED_100) ||
>                     (speed == SPEED_1000)) {
>                         priv->hw->ps = speed;
>                 } else {
>                         dev_warn(priv->device, "invalid port speed\n");
>                         priv->hw->ps = 0;
>                 }
>         }
> 

> Which means that if we're using the integrated PCS, then we basically
> require the "snps,ps-speed" property otherwise we'll issue a warning
> at this point... this seems to imply that reverse mode is the only
> mode supported, which I'm fairly sure is false. So, maybe this
> shouldn't be issuing the warning if mac_port_sel_speed was zero?

Seeing the link state could be delivered over the in-band path, I
guess the "snps,ps-speed" property is supposed to be optional so the
mac_port_sel_speed being zero is a possible case. Thus the warning is
indeed misleading and it is totally ok to have mac_port_sel_speed
being set to zero. If it is, then the link state shall be determined
either over in-band or from the PHY.

> 
> Moving on... hw->ps can only be 10M, 100M or 1G speeds and nothing else
> - which is fine since RGMII and Cisco SGMII only support these speeds.
> 
> dwmac1000 tests for this against these speeds, so it is also fine.
> 
> dwmac4 is basically the same as dwmac1000, so is also fine.
> 
> The core code as it stands today passes this into the pcs_ctrl_ane
> method's rsgmi_ral argument, which sets GMAC_AN_CTRL_SGMRAL. Presumably
> this selects "reverse" mode for both SGMII and RGMII?

No, GMAC_AN_CTRL_SGMRAL flag works for SGMII only, which enables the
fixed link speed (see my second comment in this email message) by
forcing the SGMII RAL (Rate Adaptation Layer) working with the
pre-defined speed. AFAIU RGMII interface doesn't need that flag since
it always works with the pre-defined speed and has no Rate Adaptation
engine.

> 
> Persuing this a bit futher, qcom-ethqos always calls this with rsgmi_ral
> clear. Presumably, qcom-ethqos never specifies "snps,ps-speed" in DT,
> and thus always gets the warning above?

Interesting situation. Actually no. The only DW QoS Eth device for
which "snps,ps-speed = 1000" is specified is "qcom,sa8775p-ethqosi"
(see arch/arm64/boot/dts/qcom/sa8775p-ride.dts), due to that no
warning is printed. But on the other hand the low-level driver
(drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c) also sets
the STMMAC_FLAG_HAS_INTEGRATED_PCS flag exactly for that device, which
effectively disables the entire internal PCS functionality (except the
speed setup performed in dwmac4_core_init()).

Holy mother of ...

> 
> Finally, we get to the core issue, which is dwxgmac2_core.c.
> dwxgmac2 tests this member against 10G, 2.5G and "any other non-zero
> value". Out of all of these, the only possible path through that code
> would be the one which results in:
> 
> 	tx |= hw->link.speed1000;
> 
> Neither of the other two (2.5G and 10G) are possible because those
> aren't legal values for hw->ps. Moreover, it doesn't appear to have
> any kind of PCS, so I'm wondering whether any of this code gets used.

I guess the (hw->ps)-related code snippet has been just dummy-copied from
another dwmac*_core.c file to DW XGMAC. So IMO it can be freely
dropped. After all the bindings define the snps,ps-speed as:

      "Port selection speed that can be passed to the core when PCS
      is supported. For example, this is used in case of SGMII and
      MAC2MAC connection."

I doubt DW XGMAC could be used in the MAC2MAC setup, and it doesn't
have any internal PCS (may have externally connected DW XPCS though).

> 
> 
> So, I suspect some of this is "not quite right" either, and I wonder
> about the implications of changing how hw->pcs is set - whether we
> first need to fix the code above dealing with priv->hw->ps ?
> 
> I'm also wondering what impact this has on my PCS conversion.

My brain got blown up thinking about this one week ago. So I gave up
in looking for a portable way of fixing the MAC2MAC part and sent my
three patches as is to you. I thought after some time I could come up
with some ideas about that. Alas the time-break didn't help.)

I can't say for sure what could be a better way to align the things
around the internal PCS and MAC2MAC case. But IMO seeing the code is
vastly messy and unlikely has been widely used I'd suggest to preserve
the semantics as required by the Qualcomm QoS Eth
(dwmac-qcom-ethqos.c), and free redefining the rest of the
things as you wish.

-Serge(y)

> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Russell King (Oracle) May 31, 2024, 7:30 p.m. UTC | #11
Hi Serge,

Thanks for the reply. I've attempted to deal with most of these in my
v2 posting, but maybe not in the best way yet.

On Fri, May 31, 2024 at 08:13:49PM +0300, Serge Semin wrote:
> > Does this
> > mean it is true that these cores will never be used with an external
> > PCS?
> 
> Sorry, I was wrong to suggest the (priv->plat.has_gmac ||
> priv->plat.has_gmac4)-based statement. Indeed there is a case of having DW
> QoS Eth and DW XPCS synthesized together with the SGMII/1000Base-X
> downstream interface. Not sure why it was needed to implement that way
> seeing DW QoS Eth IP-core supports optional SGMII PHY interface out of
> box, but AFAICS Intel mGBE is that case. Anyway the correct way to
> detect the internal PCS support is to check the PCSSEL flag set in the
> HWFEATURE register (preserved in the stmmac_priv::dma_cap::pcs field).

We can only wonder why!

> > Please can you confirm that if an external PCS (e.g. xpcs, lynx PCS)
> > is being used, the internal PCS will not have been synthesized, and
> > thus priv->dma_cap.pcs will be false?
> 
> Alas I can't confirm that. priv->dma_cap.pcs only indicates the
> internal PCS availability. External PCS is an independent entity from
> the DW *MAC IP-core point of view. So the DW GMAC/QoS Eth/XGMAC
> controllers aren't aware of its existence. It's the low-level platform
> driver/code responsibility to somehow detect it being available
> ("pcs-handle" property, plat->mdio_bus_data->has_xpcs flag, etc).
> 
> Regarding the internal PCS, as long as the DW GMAC or DW QoS Eth is
> synthesized with the SGMII/TBI/RTBI PHY interface support
> priv->dma_cap.pcs will get to be true. Note the device can be
> synthesized with several PHY interfaces supported. As long as
> SGMII/TBI/RTBI PHY interface is any of them, the flag will be set
> irrespective from the PHY interface activated at runtime. 

I've been debating about this, and given your response, I'm wondering
whether we should change stmmac_mac_select_pcs() to instead do:

static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
						 phy_interface_t interface)
{
	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
	struct phylink_pcs *pcs;

	if (priv->plat->select_pcs) {
		pcs = priv->plat->select_pcs(priv, interface);
		if (!IS_ERR(pcs))
			return pcs;
	}

	return stmmac_mac_phylink_select_pcs(priv, interface);
}

and push the problem of whether to provide a PCS that overrides
the MAC internal PCS into platform code. That would mean Intel mGBE
would be able to override with XPCS. rzn1 and socfpga can then do
their own thing as well.

I'm trying hard not to go down another rabbit hole... I've just
spotted that socfpga sets mac_interface to PHY_INTERFACE_MODE_SGMII.
That's another reason for pushing this down into platform drivers -
if platform drivers are doing weird stuff, then we can contain their
weirdness in the platform drivers moving it out of the core code.

> You can extend the priv->dma_cap.pcs flag semantics. So it could
> be indicating three types of the PCS'es:
> RGMII, SGMII, XPCS (or TBI/RTBI in future).

If TBI/RTBI gets supported, then this would have to be extended, but I
get the impression that this isn't popular.

> I guess the DW XPCS implementation might be more preferable. From one
> side DW XPCS SGMII can support up to 2.5Gbps speed, while the DW
> GMAC/QoS Eth SGMII can work with up to 1Gbps speed only. On the other
> hand the DW XPCS might be available over the MDIO-bus, which is slower
> to access than the internal PCS CSRs available in the DW GMAC/QoS Eth
> CSRs space. So the more performant link speed seems more useful
> feature over the faster device setup process.

I think which should be used would depend on how the hardware is wired
up. This brings us back to platform specifics again, which points
towards moving the decision making into platform code as per the above.

> One thing I am not sure about is that there is a real case of having
> the DW GMAC/QoS Eth synthesized with the native SGMII/TBI/RTBI PHY
> interface support and being attached to the DW XPCS controller, which
> would have the SGMII downstream PHY interface. DW XPCS has only the
> XGMII or GMII/MII upstream interfaces over which the MAC can be
> attached.

That gives us another possibility, but needs platforms to be doing
the right thing. If mac_interface were set to XGMII or GMII/MII, then
that would exclude the internal MAC PCS.

> So DW GMAC/QoS Eth and DW XPCS can be connected via the
> GMII/MII interface only. Regarding Intel mGBE, it likely is having a
> setup like this:
> 
> +------------+          +---------+
> |            | GMII/MII |         |   SGMII
> | DW QoS Eth +----------+ DW XPCS +------------
> |            |          |         | 1000Base-X
> +------------+          +---------+


So as an alternative, 

     mac_interface            phy_interface

     XGMII/GMII/MII           SGMII/1000Base-X
MAC ---------------- DW XPCS ------------------

     INTERNAL                SGMII/TBI/RTBI
MAC ---------- Internal PCS ----------------

     INTERNAL                  RGMII
MAC ---------- Internal "PCS" --------------

One of the problems here, though, is socfpga. It uses mac_interface
with RGMII*, MII, GMII, SGMII and RMII. I think it's confusing
mac_interface for phy_interface, but I haven't read through enough
of it to be certain.

So that again leads me back to my proposal above for
stmmac_mac_select_pcs() as the least likely to break proposition -
at least given how things are at the moment.
Serge Semin June 2, 2024, 11:25 p.m. UTC | #12
Hi Russel

On Fri, May 31, 2024 at 08:30:27PM +0100, Russell King (Oracle) wrote:
> Hi Serge,
> 
> Thanks for the reply. I've attempted to deal with most of these in my
> v2 posting, but maybe not in the best way yet.

I've got your v2 series. I'll have a look at it and test it out later
on the next week, sometime around Wednesday.

> 
> On Fri, May 31, 2024 at 08:13:49PM +0300, Serge Semin wrote:
> > > Does this
> > > mean it is true that these cores will never be used with an external
> > > PCS?
> > 
> > Sorry, I was wrong to suggest the (priv->plat.has_gmac ||
> > priv->plat.has_gmac4)-based statement. Indeed there is a case of having DW
> > QoS Eth and DW XPCS synthesized together with the SGMII/1000Base-X
> > downstream interface. Not sure why it was needed to implement that way
> > seeing DW QoS Eth IP-core supports optional SGMII PHY interface out of
> > box, but AFAICS Intel mGBE is that case. Anyway the correct way to
> > detect the internal PCS support is to check the PCSSEL flag set in the
> > HWFEATURE register (preserved in the stmmac_priv::dma_cap::pcs field).
> 
> We can only wonder why!
> 
> > > Please can you confirm that if an external PCS (e.g. xpcs, lynx PCS)
> > > is being used, the internal PCS will not have been synthesized, and
> > > thus priv->dma_cap.pcs will be false?
> > 
> > Alas I can't confirm that. priv->dma_cap.pcs only indicates the
> > internal PCS availability. External PCS is an independent entity from
> > the DW *MAC IP-core point of view. So the DW GMAC/QoS Eth/XGMAC
> > controllers aren't aware of its existence. It's the low-level platform
> > driver/code responsibility to somehow detect it being available
> > ("pcs-handle" property, plat->mdio_bus_data->has_xpcs flag, etc).
> > 
> > Regarding the internal PCS, as long as the DW GMAC or DW QoS Eth is
> > synthesized with the SGMII/TBI/RTBI PHY interface support
> > priv->dma_cap.pcs will get to be true. Note the device can be
> > synthesized with several PHY interfaces supported. As long as
> > SGMII/TBI/RTBI PHY interface is any of them, the flag will be set
> > irrespective from the PHY interface activated at runtime. 
> 
> I've been debating about this, and given your response, I'm wondering
> whether we should change stmmac_mac_select_pcs() to instead do:
> 
> static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config,
> 						 phy_interface_t interface)
> {
> 	struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
> 	struct phylink_pcs *pcs;
> 
> 	if (priv->plat->select_pcs) {
> 		pcs = priv->plat->select_pcs(priv, interface);
> 		if (!IS_ERR(pcs))
> 			return pcs;
> 	}
> 
> 	return stmmac_mac_phylink_select_pcs(priv, interface);
> }
> 
> and push the problem of whether to provide a PCS that overrides
> the MAC internal PCS into platform code. That would mean Intel mGBE
> would be able to override with XPCS. rzn1 and socfpga can then do
> their own thing as well.

Well, AFAICS the only device that currently have the DW XPCS
connected to a non DW XGMAC controller is indeed the Intel mGBE with its
DW QoS Eth+DW XPCS weird setup. At the same time the Intel mGBE
controller can also support RGMII interface. Thus there is no internal
SGMII/TBI/RTBI PCS in there.

Qualcomm QoS Eth uses the internal SGMII PCS and by setting up the
STMMAC_FLAG_HAS_INTEGRATED_PCS flag its driver almost completely
disables the STMMAC PCS functionality (except the
stmmac_pcs_ctrl_ane() being called in stmmac_hw_setup()).

So from the perspective of these two devices the PCS selection looks
quiet certain. It's either internal or external one. There is no
device with both of them available.

SoCFPGA... Well, it's another and more complicated story. Based on
what said in a comment in
socfpga_gen5_set_phy_mode()/socfpga_gen10_set_phy_mode() the only
possibility to have some internal interface converted to the external
one is when a "splitter" is available. But IMO the comment is
misleading because the only thing that is then done with the
"splitter" CSR is just the clock divider selection. What is actually
done, if the "splitter" is available or if the SGMII/GMII/MII
_MAC-interface_ is requested, then the internal interface is fixed to
"GMII/MII". It looks weird because based on the "mac-mode" DT-property
semantics it was supposed to indicate the internal interface only. But
EMAC is never tuned to have the SGMII interface (see the values saved
in the "*val" argument of socfpga_set_phy_mode_common()). So all of
that makes me to conclude the next points:

1. "mac-mode" property has never been utilized for the SoG-FPGA GMAC
platform. The plat_stmmacenet_data::mac_interface field has always
defaulted to plat_stmmacenet_data::phy_interface.

2. SoG-FPGA GMAC IP-core itself doesn't support the native/internal
SGMII interface.  It's implemented by means of the so called
"gmii-to-sgmii"-converter, which is the Lynx PCS.

Thus unless I've missed something the SoC-FPGA network controller
structure can be depicted as follows:


                   +---- SYSMGR:PHYSEL
      phy_intf_sel |
+------------------+                     +--------------+ 
|          RMII    |                     |              | Internal Interface
|       +----------+                     |          off +--------------------------+
|          RGMII   | Internal Interface  | SGMII        |                          | External Interface*
| EMAC  +----------+---------------------+              |          +-------+       +--------+-----------
|         GMII/MII |                     | adapter      | GMII/MII | Lynx  | SGMII |        |
|       +----------+                     |           on +----------+       +-------+        |
|                  +--+                  |              |          |  PCS  |                |
+------------------+  |                  +--------------+          +---+---+                |
                      |                                                |                    |
                      |              +------------+                    |                    |
                      +--------------+ Splitter** +--------------------+--------------------+
                                     +-----+------+
                                           |
                                     +-----+------+
                                     | Oscillator |
                                     +------------+

* No idea whether the external interface is represented as a single IO
port or as multiple interface ports handled by the same MAC.

** As I explained above, judging by the SoC-FPGA driver code the
"splitter" is just the reference clock divider responsible for the
clock rate adjustment based on the requested link speed.

Based on the logic depicted on the sketch above, I guess that there is
no internal SGMII/TBI/RTBI PCS in SoC-FPGA GMAC either. The SGMII
interface is implemented by means of the Lynx PCS.

> 
> I'm trying hard not to go down another rabbit hole... I've just
> spotted that socfpga sets mac_interface to PHY_INTERFACE_MODE_SGMII.
> That's another reason for pushing this down into platform drivers -
> if platform drivers are doing weird stuff, then we can contain their
> weirdness in the platform drivers moving it out of the core code.

Oh, that damn "mac-mode" property... First of all as I already
mentioned once AFAICS originally it was introduced for the SoC-FPGA
GMAC, but the property has never been defined in any DT-node so far,
neither in SoC-FPGA nodes nor in the rest of the DW *MAC-based nodes.
Moreover based on my consideration above the SoC-FPGA internal
interface is always determined based on the external one seeing
plat_stmmacenet_data::mac_interface defaults to
plat_stmmacenet_data::phy_interface. Secondly I also have much
certainty that the rest of the glue drivers utilizing
plat_stmmacenet_data::mac_interface field should in fact be using
plat_stmmacenet_data::phy_interface instead. Based on the history of
the mac_interface-related changes it's likely that all of them have
just either been missed during the conversion to utilizing the
phy_interface-field or incorrectly utilized the mac_interface field
instead of phy_interface in the first place.

So to speak before going further it might be worth re-checking once
again the entire history of the "mac-mode" property-related change,
but as an experimental A/B-test patch for net-next it may be a good
idea to either drop the mac_interface field completely, or convert the
driver to forgetting about the internal PCS if the external one is
enabled, or, as a less invasive option, make SoC-FPGA explicitly
setting up the mac_interface field to GMII/MII if it configures the
internal interface to that value. Then, if these changes don't break
any platform (most importantly the SoF-FPGA GMAC case), then we can go
further and carefully convert the rest of the glue-drivers not using
the mac_interface field.

> 
> > You can extend the priv->dma_cap.pcs flag semantics. So it could
> > be indicating three types of the PCS'es:
> > RGMII, SGMII, XPCS (or TBI/RTBI in future).
> 
> If TBI/RTBI gets supported, then this would have to be extended, but I
> get the impression that this isn't popular.

Irrespective from the TBI/RTBI interface support, using the
priv->dma_cap.pcs field for all possible PCS'es shall also improve the
code readability. Currently we have four versions of the PCS fields:
dma_features::pcs
mac_device_info::pcs
mac_device_info::xpcs
mac_device_info::lynx_pcs
which are being checked here and there in the driver...

> 
> > I guess the DW XPCS implementation might be more preferable. From one
> > side DW XPCS SGMII can support up to 2.5Gbps speed, while the DW
> > GMAC/QoS Eth SGMII can work with up to 1Gbps speed only. On the other
> > hand the DW XPCS might be available over the MDIO-bus, which is slower
> > to access than the internal PCS CSRs available in the DW GMAC/QoS Eth
> > CSRs space. So the more performant link speed seems more useful
> > feature over the faster device setup process.
> 
> I think which should be used would depend on how the hardware is wired
> up. This brings us back to platform specifics again, which points
> towards moving the decision making into platform code as per the above.
> 
> > One thing I am not sure about is that there is a real case of having
> > the DW GMAC/QoS Eth synthesized with the native SGMII/TBI/RTBI PHY
> > interface support and being attached to the DW XPCS controller, which
> > would have the SGMII downstream PHY interface. DW XPCS has only the
> > XGMII or GMII/MII upstream interfaces over which the MAC can be
> > attached.
> 
> That gives us another possibility, but needs platforms to be doing
> the right thing. If mac_interface were set to XGMII or GMII/MII, then
> that would exclude the internal MAC PCS.
> 
> > So DW GMAC/QoS Eth and DW XPCS can be connected via the
> > GMII/MII interface only. Regarding Intel mGBE, it likely is having a
> > setup like this:
> > 
> > +------------+          +---------+
> > |            | GMII/MII |         |   SGMII
> > | DW QoS Eth +----------+ DW XPCS +------------
> > |            |          |         | 1000Base-X
> > +------------+          +---------+
> 
> 
> So as an alternative, 
> 
>      mac_interface            phy_interface
> 
>      XGMII/GMII/MII           SGMII/1000Base-X
> MAC ---------------- DW XPCS ------------------
> 
>      INTERNAL                SGMII/TBI/RTBI
> MAC ---------- Internal PCS ----------------
> 
>      INTERNAL                  RGMII
> MAC ---------- Internal "PCS" --------------

+ SoC-FPGA (presumably)

       GMII/MII                  SGMII
  MAC ---------------- Lynx PCS --------------

Please also note, based on the DW GMAC/QoS Eth hardware manual each
internal interface block is connected to MAC by the GMII/MII
interface. So the internal PCS cases more precisely could be
represented as follows:

       GMII                     SGMII (AN)
  MAC ---------- Internal PCS ------------------

       GMII                     TBI/RTBI (AN)
  MAC ---------- Internal PCS ------------------
  
       GMII                      RGMII (In-band)
  MAC ---------- Internal "PCS" ----------------

       GMII                      RevMII
  MAC ----------  RevMII block  ----------------

       GMII                      GMII
  MAC ------------------------------------------

       MII                       SMII (In-band)
  MAC ---------- Internal "PCS" ----------------

       MII                       RMII
  MAC ----------   RMII block   ----------------

       MII                       MII
  MAC ------------------------------------------

There is a special input signal phy_intf_sel[2:0], which tells to MAC
what interface to activate (grep -i the glue drivers for "intf",
"physel", etc).

> 
> One of the problems here, though, is socfpga. It uses mac_interface
> with RGMII*, MII, GMII, SGMII and RMII. I think it's confusing
> mac_interface for phy_interface, but I haven't read through enough
> of it to be certain.
> 
> So that again leads me back to my proposal above for
> stmmac_mac_select_pcs() as the least likely to break proposition -
> at least given how things are at the moment.

Please see my notes above regarding the internal interface
initialization in the SoC-FPGA glue driver. I guess we could at least
try to A/B-test the SoC-FPGA code in the next net-next by setting
mac_interface to GMII/MII when the internal interface is enabled as
GMII/MII in the glue-driver, and converting the rest of the glue
driver to using phy_interface. If nothing breaks, then SoC-FPGA has
never used the "mac-mode" property and we could mark the property as
deprecated and could carefully covert the rest of the STMMAC platform
driver to using the phy_interface field.

-Serge(y)

> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 90c065920af2..6c4e90b1fea3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1146,18 +1146,10 @@  static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
 {
 	int interface = priv->plat->mac_interface;
 
-	if (priv->dma_cap.pcs) {
-		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
-		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
-		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
-		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
-			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
-			priv->hw->pcs = STMMAC_PCS_RGMII;
-		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
-			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
-			priv->hw->pcs = STMMAC_PCS_SGMII;
-		}
-	}
+	if (phy_interface_mode_is_rgmii(interface))
+		priv->hw.pcs = STMMAC_PCS_RGMII;
+	else if (interface == PHY_INTERFACE_MODE_SGMII)
+		priv->hw.pcs = STMMAC_PCS_SGMII;
 }
 
 /**