2022-07-29 15:39:10

by Maxime Chevallier

[permalink] [raw]
Subject: [PATCH net-next v3 0/4] net: Introduce QUSGMII phy mode

Hello everyone,

This is the V3 of a previous series [1] initially aimed at introducing
inband extensions, with modes like QUSGMII. This mode allows passing
info in the ethernet preamble between the MAC and the PHY, such s
timestamps.

This series has now become a preliminary series, that simply introduces
the new interface mode, without support for inband extensions, that will
come later.

The reasonning is that work will need to be done in the networking
subsystem, but also in the generic phy driver subsystem to allow serdes
configuration for qusgmii.

This series add the mode, the relevant binding changes, adds support for
it in the lan966x driver, and also introduces a small helper to get the
number of links a given phy mode can carry (think 1 for SGMII and 4 for
QSGMII). This allows for better readability and will prove useful
when (if) we support PSGMII (5 links on 1 interface) and OUSGMII (8
links on one interface).

V3 includes small fixups on the ports-per-interface assignment and some
missing documentation, thanks Andrew and Florian for the review !

Best regards,

Maxime

[1] : https://lore.kernel.org/netdev/[email protected]/

Maxime Chevallier (4):
net: phy: Introduce QUSGMII PHY mode
dt-bindings: net: ethernet-controller: add QUSGMII mode
net: phy: Add helper to derive the number of ports from a phy mode
net: lan966x: Add QUSGMII support for lan966x

.../bindings/net/ethernet-controller.yaml | 1 +
Documentation/networking/phy.rst | 9 ++++
.../ethernet/microchip/lan966x/lan966x_main.c | 2 +
.../microchip/lan966x/lan966x_phylink.c | 3 +-
.../ethernet/microchip/lan966x/lan966x_port.c | 22 +++++---
.../ethernet/microchip/lan966x/lan966x_regs.h | 6 +++
drivers/net/phy/phy-core.c | 52 +++++++++++++++++++
drivers/net/phy/phylink.c | 3 ++
include/linux/phy.h | 6 +++
9 files changed, 97 insertions(+), 7 deletions(-)

--
2.37.1


2022-07-29 15:39:19

by Maxime Chevallier

[permalink] [raw]
Subject: [PATCH net-next v3 2/4] dt-bindings: net: ethernet-controller: add QUSGMII mode

Add a new QUSGMII mode, standing for "Quad Universal Serial Gigabit
Media Independent Interface", a derivative of USGMII which, similarly to
QSGMII, allows to multiplex 4 1Gbps links to a Quad-PHY.

The main difference with QSGMII is that QUSGMII can include an extension
instead of the standard 7bytes ethernet preamble, allowing to convey
arbitrary data such as Timestamps.

Signed-off-by: Maxime Chevallier <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
V1->V2 : Added Rob's acked-by
V2->V3 : No changes

Documentation/devicetree/bindings/net/ethernet-controller.yaml | 1 +
1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/net/ethernet-controller.yaml b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
index c138a1022879..4b3c590fcebf 100644
--- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml
@@ -67,6 +67,7 @@ properties:
- gmii
- sgmii
- qsgmii
+ - qusgmii
- tbi
- rev-mii
- rmii
--
2.37.1

2022-07-29 15:39:20

by Maxime Chevallier

[permalink] [raw]
Subject: [PATCH net-next v3 3/4] net: phy: Add helper to derive the number of ports from a phy mode

Some phy modes such as QSGMII multiplex several MAC<->PHY links on one
single physical interface. QSGMII used to be the only one supported, but
other modes such as QUSGMII also carry multiple links.

This helper allows getting the number of links that are multiplexed
on a given interface.

Signed-off-by: Maxime Chevallier <[email protected]>
---
V1->V2 : New patch
V2->V3 : Made PHY_INTERFACE_MODE_INTERNAL 1 port, and added the MAX
case.

drivers/net/phy/phy-core.c | 52 ++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 2 ++
2 files changed, 54 insertions(+)

diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 1f2531a1a876..f8ec12d3d6ae 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned int duplex)
}
EXPORT_SYMBOL_GPL(phy_duplex_to_str);

+/**
+ * phy_interface_num_ports - Return the number of links that can be carried by
+ * a given MAC-PHY physical link. Returns 0 if this is
+ * unknown, the number of links else.
+ *
+ * @interface: The interface mode we want to get the number of ports
+ */
+int phy_interface_num_ports(phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_NA:
+ return 0;
+ case PHY_INTERFACE_MODE_INTERNAL:
+ case PHY_INTERFACE_MODE_MII:
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_TBI:
+ case PHY_INTERFACE_MODE_REVMII:
+ case PHY_INTERFACE_MODE_RMII:
+ case PHY_INTERFACE_MODE_REVRMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RTBI:
+ case PHY_INTERFACE_MODE_XGMII:
+ case PHY_INTERFACE_MODE_XLGMII:
+ case PHY_INTERFACE_MODE_MOCA:
+ case PHY_INTERFACE_MODE_TRGMII:
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_SMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_25GBASER:
+ case PHY_INTERFACE_MODE_10GKR:
+ case PHY_INTERFACE_MODE_100BASEX:
+ case PHY_INTERFACE_MODE_RXAUI:
+ case PHY_INTERFACE_MODE_XAUI:
+ return 1;
+ case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_QUSGMII:
+ return 4;
+ case PHY_INTERFACE_MODE_MAX:
+ WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");
+ return 0;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(phy_interface_num_ports);
+
/* A mapping of all SUPPORTED settings to speed/duplex. This table
* must be grouped by speed and sorted in descending match priority
* - iow, descending speed.
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 9eeab9b9a74c..7c49ab95441b 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -968,6 +968,8 @@ struct phy_fixup {
const char *phy_speed_to_str(int speed);
const char *phy_duplex_to_str(unsigned int duplex);

+int phy_interface_num_ports(phy_interface_t interface);
+
/* A structure for mapping a particular speed and duplex
* combination to a particular SUPPORTED and ADVERTISED value
*/
--
2.37.1

2022-07-29 15:39:20

by Maxime Chevallier

[permalink] [raw]
Subject: [PATCH net-next v3 4/4] net: lan966x: Add QUSGMII support for lan966x

The Lan996x controller supports the QUSGMII mode, which is very similar
to QSGMII in the way it's configured and the autonegociation
capababilities it provides.

This commit adds support for that mode, treating it most of the time
like QSGMII, making sure that we do configure the PCS how we should.

Signed-off-by: Maxime Chevallier <[email protected]>
---
V1->V2 : Pass the QUSGMII mode as-is to the generic PHY driver, and use
phy_interface_num_ports, as per Russell's review
V2->V3 : No changes

.../ethernet/microchip/lan966x/lan966x_main.c | 2 ++
.../microchip/lan966x/lan966x_phylink.c | 3 ++-
.../ethernet/microchip/lan966x/lan966x_port.c | 22 ++++++++++++++-----
.../ethernet/microchip/lan966x/lan966x_regs.h | 6 +++++
4 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
index 1d6e3b641b2e..1e604e8db20c 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
@@ -778,6 +778,8 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_QSGMII,
port->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_QUSGMII,
+ port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_1000BASEX,
port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_2500BASEX,
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
index 38a7e95d69b4..87f3d3a57aed 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
@@ -28,11 +28,12 @@ static int lan966x_phylink_mac_prepare(struct phylink_config *config,
phy_interface_t iface)
{
struct lan966x_port *port = netdev_priv(to_net_dev(config->dev));
+ phy_interface_t serdes_mode = iface;
int err;

if (port->serdes) {
err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET,
- iface);
+ serdes_mode);
if (err) {
netdev_err(to_net_dev(config->dev),
"Could not set mode of SerDes\n");
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
index f141644e4372..bbf42fc8c8d5 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c
@@ -168,7 +168,7 @@ static void lan966x_port_link_up(struct lan966x_port *port)
/* Also the GIGA_MODE_ENA(1) needs to be set regardless of the
* port speed for QSGMII ports.
*/
- if (config->portmode == PHY_INTERFACE_MODE_QSGMII)
+ if (phy_interface_num_ports(config->portmode) == 4)
mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);

lan_wr(config->duplex | mode,
@@ -331,10 +331,14 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
struct lan966x *lan966x = port->lan966x;
bool inband_aneg = false;
bool outband;
+ bool full_preamble = false;
+
+ if (config->portmode == PHY_INTERFACE_MODE_QUSGMII)
+ full_preamble = true;

if (config->inband) {
if (config->portmode == PHY_INTERFACE_MODE_SGMII ||
- config->portmode == PHY_INTERFACE_MODE_QSGMII)
+ phy_interface_num_ports(config->portmode) == 4)
inband_aneg = true; /* Cisco-SGMII in-band-aneg */
else if (config->portmode == PHY_INTERFACE_MODE_1000BASEX &&
config->autoneg)
@@ -345,9 +349,15 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
outband = true;
}

- /* Disable or enable inband */
- lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband),
- DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA,
+ /* Disable or enable inband.
+ * For QUSGMII, we rely on the preamble to transmit data such as
+ * timestamps, therefore force full preamble transmission, and prevent
+ * premable shortening
+ */
+ lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband) |
+ DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_SET(full_preamble),
+ DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA |
+ DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA,
lan966x, DEV_PCS1G_MODE_CFG(port->chip_port));

/* Enable PCS */
@@ -396,7 +406,7 @@ void lan966x_port_init(struct lan966x_port *port)
if (lan966x->fdma)
lan966x_fdma_netdev_init(lan966x, port->dev);

- if (config->portmode != PHY_INTERFACE_MODE_QSGMII)
+ if (phy_interface_num_ports(config->portmode) != 4)
return;

lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(0) |
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
index 8265ad89f0bc..c53bae5d8dbd 100644
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
@@ -504,6 +504,12 @@ enum lan966x_target {
#define DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_GET(x)\
FIELD_GET(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA, x)

+#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA BIT(1)
+#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_SET(x)\
+ FIELD_PREP(DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA, x)
+#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_GET(x)\
+ FIELD_GET(DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA, x)
+
/* DEV:PCS1G_CFG_STATUS:PCS1G_SD_CFG */
#define DEV_PCS1G_SD_CFG(t) __REG(TARGET_DEV, t, 8, 72, 0, 1, 68, 8, 0, 1, 4)

--
2.37.1

2022-07-29 17:24:20

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next v3 3/4] net: phy: Add helper to derive the number of ports from a phy mode

On 7/29/22 08:33, Maxime Chevallier wrote:
> Some phy modes such as QSGMII multiplex several MAC<->PHY links on one
> single physical interface. QSGMII used to be the only one supported, but
> other modes such as QUSGMII also carry multiple links.
>
> This helper allows getting the number of links that are multiplexed
> on a given interface.
>
> Signed-off-by: Maxime Chevallier <[email protected]>
> ---
> V1->V2 : New patch
> V2->V3 : Made PHY_INTERFACE_MODE_INTERNAL 1 port, and added the MAX
> case.
>
> drivers/net/phy/phy-core.c | 52 ++++++++++++++++++++++++++++++++++++++
> include/linux/phy.h | 2 ++
> 2 files changed, 54 insertions(+)
>
> diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
> index 1f2531a1a876..f8ec12d3d6ae 100644
> --- a/drivers/net/phy/phy-core.c
> +++ b/drivers/net/phy/phy-core.c
> @@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned int duplex)
> }
> EXPORT_SYMBOL_GPL(phy_duplex_to_str);
>
> +/**
> + * phy_interface_num_ports - Return the number of links that can be carried by
> + * a given MAC-PHY physical link. Returns 0 if this is
> + * unknown, the number of links else.
> + *
> + * @interface: The interface mode we want to get the number of ports
> + */
> +int phy_interface_num_ports(phy_interface_t interface)
> +{
> + switch (interface) {
> + case PHY_INTERFACE_MODE_NA:
> + return 0;
> + case PHY_INTERFACE_MODE_INTERNAL:

Maybe this was covered in the previous iteration, but cannot the default case return 1, and all of the cases that need an explicit non-1 return value are handled? Enumeration all of those that do need to return 1 does not really scale.
--
Florian

2022-07-30 04:00:16

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v3 2/4] dt-bindings: net: ethernet-controller: add QUSGMII mode

On Fri, Jul 29, 2022 at 05:33:54PM +0200, Maxime Chevallier wrote:
> Add a new QUSGMII mode, standing for "Quad Universal Serial Gigabit
> Media Independent Interface", a derivative of USGMII which, similarly to
> QSGMII, allows to multiplex 4 1Gbps links to a Quad-PHY.
>
> The main difference with QSGMII is that QUSGMII can include an extension
> instead of the standard 7bytes ethernet preamble, allowing to convey
> arbitrary data such as Timestamps.
>
> Signed-off-by: Maxime Chevallier <[email protected]>
> Acked-by: Rob Herring <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2022-07-30 04:26:09

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v3 3/4] net: phy: Add helper to derive the number of ports from a phy mode

> > +int phy_interface_num_ports(phy_interface_t interface)
> > +{
> > + switch (interface) {
> > + case PHY_INTERFACE_MODE_NA:
> > + return 0;
> > + case PHY_INTERFACE_MODE_INTERNAL:
>

> Maybe this was covered in the previous iteration, but cannot the
> default case return 1, and all of the cases that need an explicit
> non-1 return value are handled? Enumeration all of those that do
> need to return 1 does not really scale.

It is a trade off. In the current form, when somebody adds a new enum
value, gcc will give a warning if they forget to add it here. If we
default to 1, new values are probably going to be missed here, and
could end up with the incorrect return value.

I think the compiler warning actually does make it scale. And the
generated code probably very similar either way.

Andrew