Skip to contentSkip to conversation

net: stmmac: replace speed_mode_2500() method

PATCH Applied Russell King (Oracle) 4 participants 15 messages May 1, 2025 – May 3, 2025

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

cover net: stmmac: replace speed_mode_2500() method

Hi,

This series replaces the speed_mode_2500() method with a new method that is more flexible, allowing the platform glue driver to populate phylink's supported_interfaces and set the PHY-side interface mode.

The only user of this method is currently dwmac-intel, which we update to use this new method.

 drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 33 +++++++------
 drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h |  1 -
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 56 +++++++++++++----------
 include/linux/stmmac.h                            |  3 +-
 4 files changed, 49 insertions(+), 44 deletions(-)
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
#1 lore raw

PATCH 1/6 net: stmmac: use a local variable for priv->phylink_config

Use a local variable for priv->phylink_config in stmmac_phy_setup() which makes the code a bit easier to read, allowing some lines to be merged.

---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c | 37 +++++++++----------
 1 file changed, 18 insertions(+), 19 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +18 -19
index f59a2363f150..fe7f9e3a92a5 100644
@@ -1259,19 +1259,22 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 {
 	struct stmmac_mdio_bus_data *mdio_bus_data;
 	int mode = priv->plat->phy_interface;
+	struct phylink_config *config;
 	struct fwnode_handle *fwnode;
 	struct phylink_pcs *pcs;
 	struct phylink *phylink;
 
-	priv->phylink_config.dev = &priv->dev->dev;
-	priv->phylink_config.type = PHYLINK_NETDEV;
-	priv->phylink_config.mac_managed_pm = true;
+	config = &priv->phylink_config;
+
+	config->dev = &priv->dev->dev;
+	config->type = PHYLINK_NETDEV;
+	config->mac_managed_pm = true;
 
 	/* Stmmac always requires an RX clock for hardware initialization */
-	priv->phylink_config.mac_requires_rxc = true;
+	config->mac_requires_rxc = true;
 
 	if (!(priv->plat->flags & STMMAC_FLAG_RX_CLK_RUNS_IN_LPI))
-		priv->phylink_config.eee_rx_clk_stop_enable = true;
+		config->eee_rx_clk_stop_enable = true;
 
 	/* Set the default transmit clock stop bit based on the platform glue */
 	priv->tx_lpi_clk_stop = priv->plat->flags &
@@ -1279,13 +1282,12 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 
 	mdio_bus_data = priv->plat->mdio_bus_data;
 	if (mdio_bus_data)
-		priv->phylink_config.default_an_inband =
-			mdio_bus_data->default_an_inband;
+		config->default_an_inband = mdio_bus_data->default_an_inband;
 
 	/* Set the platform/firmware specified interface mode. Note, phylink
 	 * deals with the PHY interface mode, not the MAC interface mode.
 	 */
-	__set_bit(mode, priv->phylink_config.supported_interfaces);
+	__set_bit(mode, config->supported_interfaces);
 
 	/* If we have an xpcs, it defines which PHY interfaces are supported. */
 	if (priv->hw->xpcs)
@@ -1294,29 +1296,26 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 		pcs = priv->hw->phylink_pcs;
 
 	if (pcs)
-		phy_interface_or(priv->phylink_config.supported_interfaces,
-				 priv->phylink_config.supported_interfaces,
+		phy_interface_or(config->supported_interfaces,
+				 config->supported_interfaces,
 				 pcs->supported_interfaces);
 
 	if (priv->dma_cap.eee) {
 		/* Assume all supported interfaces also support LPI */
-		memcpy(priv->phylink_config.lpi_interfaces,
-		       priv->phylink_config.supported_interfaces,
-		       sizeof(priv->phylink_config.lpi_interfaces));
+		memcpy(config->lpi_interfaces, config->supported_interfaces,
+		       sizeof(config->lpi_interfaces));
 
 		/* All full duplex speeds above 100Mbps are supported */
-		priv->phylink_config.lpi_capabilities = ~(MAC_1000FD - 1) |
-							MAC_100FD;
-		priv->phylink_config.lpi_timer_default = eee_timer * 1000;
-		priv->phylink_config.eee_enabled_default = true;
+		config->lpi_capabilities = ~(MAC_1000FD - 1) | MAC_100FD;
+		config->lpi_timer_default = eee_timer * 1000;
+		config->eee_enabled_default = true;
 	}
 
 	fwnode = priv->plat->port_node;
 	if (!fwnode)
 		fwnode = dev_fwnode(priv->device);
 
-	phylink = phylink_create(&priv->phylink_config, fwnode,
-				 mode, &stmmac_phylink_mac_ops);
+	phylink = phylink_create(config, fwnode, mode, &stmmac_phylink_mac_ops);
 	if (IS_ERR(phylink))
 		return PTR_ERR(phylink);
 
Signature · 1 line
2.30.2
#3 lore raw

PATCH 2/6 net: stmmac: use priv->plat->phy_interface directly

In reply to Russell King (Oracle)

Avoid using a local variable for priv->plat->phy_interface as this may be modified in the .get_interfaces() method added in a future commit.

---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +3 -3
index fe7f9e3a92a5..ac6ab121eb33 100644
@@ -1258,7 +1258,6 @@ static int stmmac_init_phy(struct net_device *dev)
 static int stmmac_phy_setup(struct stmmac_priv *priv)
 {
 	struct stmmac_mdio_bus_data *mdio_bus_data;
-	int mode = priv->plat->phy_interface;
 	struct phylink_config *config;
 	struct fwnode_handle *fwnode;
 	struct phylink_pcs *pcs;
@@ -1287,7 +1286,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 	/* Set the platform/firmware specified interface mode. Note, phylink
 	 * deals with the PHY interface mode, not the MAC interface mode.
 	 */
-	__set_bit(mode, config->supported_interfaces);
+	__set_bit(priv->plat->phy_interface, config->supported_interfaces);
 
 	/* If we have an xpcs, it defines which PHY interfaces are supported. */
 	if (priv->hw->xpcs)
@@ -1315,7 +1314,8 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 	if (!fwnode)
 		fwnode = dev_fwnode(priv->device);
 
-	phylink = phylink_create(config, fwnode, mode, &stmmac_phylink_mac_ops);
+	phylink = phylink_create(config, fwnode, priv->plat->phy_interface,
+				 &stmmac_phylink_mac_ops);
 	if (IS_ERR(phylink))
 		return PTR_ERR(phylink);
 
Signature · 1 line
2.30.2
#5 lore raw

PATCH 3/6 net: stmmac: add get_interfaces() platform method

In reply to Russell King (Oracle)

Add a get_interfaces() platform method to allow platforms to indicate to phylink which interface modes they support - which then allows phylink to validate on initialisation that the configured PHY interface mode is actually supported.

---
 .../net/ethernet/stmicro/stmmac/stmmac_main.c    | 16 +++++++++++++---
 include/linux/stmmac.h                           |  2 ++
 2 files changed, 15 insertions(+), 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +13 -3
index ac6ab121eb33..5f66f816a249 100644
@@ -1283,10 +1283,20 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
 	if (mdio_bus_data)
 		config->default_an_inband = mdio_bus_data->default_an_inband;
 
-	/* Set the platform/firmware specified interface mode. Note, phylink
-	 * deals with the PHY interface mode, not the MAC interface mode.
+	/* Get the PHY interface modes (at the PHY end of the link) that
+	 * are supported by the platform.
 	 */
-	__set_bit(priv->plat->phy_interface, config->supported_interfaces);
+	if (priv->plat->get_interfaces)
+		priv->plat->get_interfaces(priv, priv->plat->bsp_priv,
+					   config->supported_interfaces);
+
+	/* Set the platform/firmware specified interface mode if the
+	 * supported interfaces have not already been provided using
+	 * phy_interface as a last resort.
+	 */
+	if (phy_interface_empty(config->supported_interfaces))
+		__set_bit(priv->plat->phy_interface,
+			  config->supported_interfaces);
 
 	/* If we have an xpcs, it defines which PHY interfaces are supported. */
 	if (priv->hw->xpcs)
include/linux/stmmac.h +2 -0
index 8aed09d65b4a..537bced69c46 100644
@@ -233,6 +233,8 @@ struct plat_stmmacenet_data {
 	u8 tx_sched_algorithm;
 	struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
 	struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
+	void (*get_interfaces)(struct stmmac_priv *priv, void *bsp_priv,
+			       unsigned long *interfaces);
 	int (*set_clk_tx_rate)(void *priv, struct clk *clk_tx_i,
 			       phy_interface_t interface, int speed);
 	void (*fix_mac_speed)(void *priv, int speed, unsigned int mode);
Signature · 1 line
2.30.2
#6 lore raw

PATCH 4/6 net: stmmac: intel: move phy_interface init to tgl_common_data()

In reply to Russell King (Oracle)

Move the initialisation of plat->phy_interface to tgl_common_data() as all callers set this same interface mode. This moves it to a single location to make the change to get_interfaces() more obvious.

---
 drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +1 -4
index 96c893dd262f..4b263a3c65a4 100644
@@ -929,6 +929,7 @@ static int tgl_common_data(struct pci_dev *pdev,
 	plat->rx_queues_to_use = 6;
 	plat->tx_queues_to_use = 4;
 	plat->clk_ptp_rate = 204800000;
+	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
 	plat->speed_mode_2500 = intel_speed_mode_2500;
 
 	plat->safety_feat_cfg->tsoee = 1;
@@ -948,7 +949,6 @@ static int tgl_sgmii_phy0_data(struct pci_dev *pdev,
 			       struct plat_stmmacenet_data *plat)
 {
 	plat->bus_id = 1;
-	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
 	plat->serdes_powerup = intel_serdes_powerup;
 	plat->serdes_powerdown = intel_serdes_powerdown;
 	return tgl_common_data(pdev, plat);
@@ -962,7 +962,6 @@ static int tgl_sgmii_phy1_data(struct pci_dev *pdev,
 			       struct plat_stmmacenet_data *plat)
 {
 	plat->bus_id = 2;
-	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
 	plat->serdes_powerup = intel_serdes_powerup;
 	plat->serdes_powerdown = intel_serdes_powerdown;
 	return tgl_common_data(pdev, plat);
@@ -976,7 +975,6 @@ static int adls_sgmii_phy0_data(struct pci_dev *pdev,
 				struct plat_stmmacenet_data *plat)
 {
 	plat->bus_id = 1;
-	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
 
 	/* SerDes power up and power down are done in BIOS for ADL */
 
@@ -991,7 +989,6 @@ static int adls_sgmii_phy1_data(struct pci_dev *pdev,
 				struct plat_stmmacenet_data *plat)
 {
 	plat->bus_id = 2;
-	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
 
 	/* SerDes power up and power down are done in BIOS for ADL */
 
Signature · 1 line
2.30.2
Reviewed-by on v1 4/6
#7 lore raw

Re: [PATCH net-next 4/6] net: stmmac: intel: move phy_interface init to tgl_common_data()

Quoted 5 lines · Russell King (Oracle)

Move the initialisation of plat->phy_interface to tgl_common_data() as all callers set this same interface mode. This moves it to a single location to make the change to get_interfaces() more obvious.

Andrew

#8 lore raw

PATCH 5/6 net: stmmac: intel: convert speed_mode_2500() to get_interfaces()

In reply to Russell King (Oracle)

TGL platforms support either SGMII or 2500BASE-X, which is determined by reading a SERDES register.

Thus, plat->phy_interface (and phylink's supported_interfaces) depend on this. Use the new .get_interfaces() method to set both plat->phy_interface and the supported_interfaces bitmap.

This removes the only user of the .speed_mode_2500() method.

---
 .../net/ethernet/stmicro/stmmac/dwmac-intel.c | 30 ++++++++++---------
 .../net/ethernet/stmicro/stmmac/dwmac-intel.h |  1 -
 2 files changed, 16 insertions(+), 15 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +16 -14
index 4b263a3c65a4..9a47015254bb 100644
@@ -284,25 +284,28 @@ static void intel_serdes_powerdown(struct net_device *ndev, void *intel_data)
 	}
 }
 
-static void intel_speed_mode_2500(struct net_device *ndev, void *intel_data)
+static void tgl_get_interfaces(struct stmmac_priv *priv, void *bsp_priv,
+			       unsigned long *interfaces)
 {
-	struct intel_priv_data *intel_priv = intel_data;
-	struct stmmac_priv *priv = netdev_priv(ndev);
-	int serdes_phy_addr = 0;
-	u32 data = 0;
-
-	serdes_phy_addr = intel_priv->mdio_adhoc_addr;
+	struct intel_priv_data *intel_priv = bsp_priv;
+	phy_interface_t interface;
+	int data;
 
 	/* Determine the link speed mode: 2.5Gbps/1Gbps */
-	data = mdiobus_read(priv->mii, serdes_phy_addr,
-			    SERDES_GCR);
+	data = mdiobus_read(priv->mii, intel_priv->mdio_adhoc_addr, SERDES_GCR);
+	if (data < 0)
+		return;
 
-	if (((data & SERDES_LINK_MODE_MASK) >> SERDES_LINK_MODE_SHIFT) ==
-	    SERDES_LINK_MODE_2G5) {
+	if (FIELD_GET(SERDES_LINK_MODE_MASK, data) == SERDES_LINK_MODE_2G5) {
 		dev_info(priv->device, "Link Speed Mode: 2.5Gbps\n");
-		priv->plat->phy_interface = PHY_INTERFACE_MODE_2500BASEX;
 		priv->plat->mdio_bus_data->default_an_inband = false;
+		interface = PHY_INTERFACE_MODE_2500BASEX;
+	} else {
+		interface = PHY_INTERFACE_MODE_SGMII;
 	}
+
+	__set_bit(interface, interfaces);
+	priv->plat->phy_interface = interface;
 }
 
 /* Program PTP Clock Frequency for different variant of
@@ -929,8 +932,7 @@ static int tgl_common_data(struct pci_dev *pdev,
 	plat->rx_queues_to_use = 6;
 	plat->tx_queues_to_use = 4;
 	plat->clk_ptp_rate = 204800000;
-	plat->phy_interface = PHY_INTERFACE_MODE_SGMII;
-	plat->speed_mode_2500 = intel_speed_mode_2500;
+	plat->get_interfaces = tgl_get_interfaces;
 
 	plat->safety_feat_cfg->tsoee = 1;
 	plat->safety_feat_cfg->mrxpee = 0;
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.h +0 -1
index a12f8e65f89f..7511c224b312 100644
@@ -21,7 +21,6 @@
 #define SERDES_RATE_MASK	GENMASK(9, 8)
 #define SERDES_PCLK_MASK	GENMASK(14, 12)	/* PCLK rate to PHY */
 #define SERDES_LINK_MODE_MASK	GENMASK(2, 1)
-#define SERDES_LINK_MODE_SHIFT	1
 #define SERDES_PWR_ST_SHIFT	4
 #define SERDES_PWR_ST_P0	0x0
 #define SERDES_PWR_ST_P3	0x3
Signature · 1 line
2.30.2
Reviewed-by on v1 5/6
#9 lore raw

Re: [PATCH net-next 5/6] net: stmmac: intel: convert speed_mode_2500() to get_interfaces()

Quoted 10 lines · Russell King (Oracle)

TGL platforms support either SGMII or 2500BASE-X, which is determined by reading a SERDES register.

Thus, plat->phy_interface (and phylink's supported_interfaces) depend on this. Use the new .get_interfaces() method to set both plat->phy_interface and the supported_interfaces bitmap.

This removes the only user of the .speed_mode_2500() method.

Andrew

#10 lore raw

PATCH 6/6 net: stmmac: remove speed_mode_2500() method

In reply to Russell King (Oracle)

Remove the speed_mode_2500() platform method which is no longer used or necessary, being superseded by the more flexible get_interfaces() method.

---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ---
 include/linux/stmmac.h                            | 1 -
 2 files changed, 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0 -3
index 5f66f816a249..28b62bd73e23 100644
@@ -7736,9 +7736,6 @@ int stmmac_dvr_probe(struct device *device,
 		goto error_mdio_register;
 	}
 
-	if (priv->plat->speed_mode_2500)
-		priv->plat->speed_mode_2500(ndev, priv->plat->bsp_priv);
-
 	ret = stmmac_pcs_setup(ndev);
 	if (ret)
 		goto error_pcs_setup;
include/linux/stmmac.h +0 -1
index 537bced69c46..26ddf95d23f9 100644
@@ -241,7 +241,6 @@ struct plat_stmmacenet_data {
 	int (*fix_soc_reset)(void *priv, void __iomem *ioaddr);
 	int (*serdes_powerup)(struct net_device *ndev, void *priv);
 	void (*serdes_powerdown)(struct net_device *ndev, void *priv);
-	void (*speed_mode_2500)(struct net_device *ndev, void *priv);
 	int (*mac_finish)(struct net_device *ndev,
 			  void *priv,
 			  unsigned int mode,
Signature · 1 line
2.30.2
#12 lore raw
In reply to Russell King (Oracle)
This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:

Hello:

This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:

Quoted 10 lines · On Thu, 1 May 2025 12:45:21 +0100 you wrote:

Hi,

This series replaces the speed_mode_2500() method with a new method that is more flexible, allowing the platform glue driver to populate phylink's supported_interfaces and set the PHY-side interface mode.

The only user of this method is currently dwmac-intel, which we update to use this new method.

[...]

Here is the summary with links:
- [net-next,1/6] net: stmmac: use a local variable for priv->phylink_config

    https://git.kernel.org/netdev/net-next/c/5ad39ceaea00
  - [net-next,2/6] net: stmmac: use priv->plat->phy_interface directly
    https://git.kernel.org/netdev/net-next/c/1966be55da5b
  - [net-next,3/6] net: stmmac: add get_interfaces() platform method
    https://git.kernel.org/netdev/net-next/c/ca732e990fc8
  - [net-next,4/6] net: stmmac: intel: move phy_interface init to tgl_common_data()
    https://git.kernel.org/netdev/net-next/c/0f455d2d1bbe
  - [net-next,5/6] net: stmmac: intel: convert speed_mode_2500() to get_interfaces()
    https://git.kernel.org/netdev/net-next/c/d3836052fe09
  - [net-next,6/6] net: stmmac: remove speed_mode_2500() method
    https://git.kernel.org/netdev/net-next/c/9d165dc58055

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
#13 lore raw

Err, I sent v2 a couple of days ago, did patchwork not see it?

Quoted 38 lines · On Sat, May 03, 2025 at 01:30:36AM +0000, [email protected]…

Hello:

This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:

Quoted 10 lines · On Thu, 1 May 2025 12:45:21 +0100 you wrote:

Hi,

This series replaces the speed_mode_2500() method with a new method that is more flexible, allowing the platform glue driver to populate phylink's supported_interfaces and set the PHY-side interface mode.

The only user of this method is currently dwmac-intel, which we update to use this new method.

[...]

Here is the summary with links:
- [net-next,1/6] net: stmmac: use a local variable for priv->phylink_config

    https://git.kernel.org/netdev/net-next/c/5ad39ceaea00
  - [net-next,2/6] net: stmmac: use priv->plat->phy_interface directly
    https://git.kernel.org/netdev/net-next/c/1966be55da5b
  - [net-next,3/6] net: stmmac: add get_interfaces() platform method
    https://git.kernel.org/netdev/net-next/c/ca732e990fc8
  - [net-next,4/6] net: stmmac: intel: move phy_interface init to tgl_common_data()
    https://git.kernel.org/netdev/net-next/c/0f455d2d1bbe
  - [net-next,5/6] net: stmmac: intel: convert speed_mode_2500() to get_interfaces()
    https://git.kernel.org/netdev/net-next/c/d3836052fe09
  - [net-next,6/6] net: stmmac: remove speed_mode_2500() method
    https://git.kernel.org/netdev/net-next/c/9d165dc58055

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
#14 lore raw

Ignore me, not enough coffee. Sorry for the noise.

Quoted 45 lines · Russell King (Oracle)

Err, I sent v2 a couple of days ago, did patchwork not see it?

Quoted 38 lines · On Sat, May 03, 2025 at 01:30:36AM +0000, [email protected]…

Hello:

This series was applied to netdev/net-next.git (main) by Jakub Kicinski <[email protected]>:

Quoted 10 lines · On Thu, 1 May 2025 12:45:21 +0100 you wrote:

Hi,

This series replaces the speed_mode_2500() method with a new method that is more flexible, allowing the platform glue driver to populate phylink's supported_interfaces and set the PHY-side interface mode.

The only user of this method is currently dwmac-intel, which we update to use this new method.

[...]

Here is the summary with links:
- [net-next,1/6] net: stmmac: use a local variable for priv->phylink_config

    https://git.kernel.org/netdev/net-next/c/5ad39ceaea00
  - [net-next,2/6] net: stmmac: use priv->plat->phy_interface directly
    https://git.kernel.org/netdev/net-next/c/1966be55da5b
  - [net-next,3/6] net: stmmac: add get_interfaces() platform method
    https://git.kernel.org/netdev/net-next/c/ca732e990fc8
  - [net-next,4/6] net: stmmac: intel: move phy_interface init to tgl_common_data()
    https://git.kernel.org/netdev/net-next/c/0f455d2d1bbe
  - [net-next,5/6] net: stmmac: intel: convert speed_mode_2500() to get_interfaces()
    https://git.kernel.org/netdev/net-next/c/d3836052fe09
  - [net-next,6/6] net: stmmac: remove speed_mode_2500() method
    https://git.kernel.org/netdev/net-next/c/9d165dc58055

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Signature · 2 lines
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!