All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/12] ENETC BD ring cleanup
@ 2023-01-17 23:02 Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 01/12] net: enetc: set next_to_clean/next_to_use just from enetc_setup_txbdr() Vladimir Oltean
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

The highlights of this patch set are:

- Installing a BPF program and changing PTP RX timestamping settings are
  currently implemented through a port reconfiguration procedure which
  triggers an AN restart on the PHY, and these procedures are not
  generally guaranteed to leave the port in a sane state. Patches 9/12
  and 11/12 address that.

- Attempting to put the port down (or trying to reconfigure it) has the
  driver oppose some resistance if it's bombarded with RX traffic
  (it won't go down). Patch 12/12 addresses that.

The other 9 patches are just cleanup in the BD ring setup/teardown code,
which gradually led to bringing the driver in a position where resolving
those 2 issues was possible.

Vladimir Oltean (12):
  net: enetc: set next_to_clean/next_to_use just from
    enetc_setup_txbdr()
  net: enetc: set up RX ring indices from enetc_setup_rxbdr()
  net: enetc: create enetc_dma_free_bdr()
  net: enetc: rx_swbd and tx_swbd are never NULL in
    enetc_free_rxtx_rings()
  net: enetc: drop redundant enetc_free_tx_frame() call from
    enetc_free_txbdr()
  net: enetc: bring "bool extended" to top-level in enetc_open()
  net: enetc: split ring resource allocation from assignment
  net: enetc: move phylink_start/stop out of enetc_start/stop
  net: enetc: implement ring reconfiguration procedure for PTP RX
    timestamping
  net: enetc: rename "xdp" and "dev" in enetc_setup_bpf()
  net: enetc: set up XDP program under enetc_reconfigure()
  net: enetc: prioritize ability to go down over packet processing

 drivers/net/ethernet/freescale/enetc/enetc.c | 502 +++++++++++++------
 drivers/net/ethernet/freescale/enetc/enetc.h |  21 +-
 2 files changed, 357 insertions(+), 166 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH net-next 01/12] net: enetc: set next_to_clean/next_to_use just from enetc_setup_txbdr()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 02/12] net: enetc: set up RX ring indices from enetc_setup_rxbdr() Vladimir Oltean
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

enetc_alloc_txbdr() deals with allocating resources necessary for a TX
ring to work (the array of software BDs and the array of TSO headers).

The next_to_clean and next_to_use pointers are overwritten with proper
values which are read from hardware here:

enetc_open
-> enetc_alloc_tx_resources
   -> enetc_alloc_txbdr
      -> set to zero
-> enetc_setup_bdrs
   -> enetc_setup_txbdr
      -> read from hardware

So their initialization with zeroes is pointless and confusing.
Delete it.

Consequently, since enetc_setup_txbdr() has no opposite cleanup
function, also delete the resetting of these indices from
enetc_free_tx_ring().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 5ad0b259e623..911686df16e4 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1753,9 +1753,6 @@ static int enetc_alloc_txbdr(struct enetc_bdr *txr)
 		goto err_alloc_tso;
 	}
 
-	txr->next_to_clean = 0;
-	txr->next_to_use = 0;
-
 	return 0;
 
 err_alloc_tso:
@@ -1897,9 +1894,6 @@ static void enetc_free_tx_ring(struct enetc_bdr *tx_ring)
 
 		enetc_free_tx_frame(tx_ring, tx_swbd);
 	}
-
-	tx_ring->next_to_clean = 0;
-	tx_ring->next_to_use = 0;
 }
 
 static void enetc_free_rx_ring(struct enetc_bdr *rx_ring)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 02/12] net: enetc: set up RX ring indices from enetc_setup_rxbdr()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 01/12] net: enetc: set next_to_clean/next_to_use just from enetc_setup_txbdr() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 03/12] net: enetc: create enetc_dma_free_bdr() Vladimir Oltean
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

There is only one place which needs to set up indices in the RX ring.
Be consistent with what was done in the TX path and do this in
enetc_setup_rxbdr().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 911686df16e4..4f8c94957a8e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1832,9 +1832,6 @@ static int enetc_alloc_rxbdr(struct enetc_bdr *rxr, bool extended)
 		return err;
 	}
 
-	rxr->next_to_clean = 0;
-	rxr->next_to_use = 0;
-	rxr->next_to_alloc = 0;
 	rxr->ext_en = extended;
 
 	return 0;
@@ -1914,10 +1911,6 @@ static void enetc_free_rx_ring(struct enetc_bdr *rx_ring)
 		__free_page(rx_swbd->page);
 		rx_swbd->page = NULL;
 	}
-
-	rx_ring->next_to_clean = 0;
-	rx_ring->next_to_use = 0;
-	rx_ring->next_to_alloc = 0;
 }
 
 static void enetc_free_rxtx_rings(struct enetc_ndev_priv *priv)
@@ -2084,6 +2077,10 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 	rx_ring->rcir = hw->reg + ENETC_BDR(RX, idx, ENETC_RBCIR);
 	rx_ring->idr = hw->reg + ENETC_SIRXIDR;
 
+	rx_ring->next_to_clean = 0;
+	rx_ring->next_to_use = 0;
+	rx_ring->next_to_alloc = 0;
+
 	enetc_lock_mdio();
 	enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
 	enetc_unlock_mdio();
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 03/12] net: enetc: create enetc_dma_free_bdr()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 01/12] net: enetc: set next_to_clean/next_to_use just from enetc_setup_txbdr() Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 02/12] net: enetc: set up RX ring indices from enetc_setup_rxbdr() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 04/12] net: enetc: rx_swbd and tx_swbd are never NULL in enetc_free_rxtx_rings() Vladimir Oltean
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

This is a refactoring change which introduces the opposite function of
enetc_dma_alloc_bdr().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 25 +++++++++-----------
 1 file changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 4f8c94957a8e..ca1dacccf9fe 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1732,6 +1732,13 @@ static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size)
 	return 0;
 }
 
+static void enetc_dma_free_bdr(struct enetc_bdr *r, size_t bd_size)
+{
+	dma_free_coherent(r->dev, r->bd_count * bd_size, r->bd_base,
+			  r->bd_dma_base);
+	r->bd_base = NULL;
+}
+
 static int enetc_alloc_txbdr(struct enetc_bdr *txr)
 {
 	int err;
@@ -1756,9 +1763,7 @@ static int enetc_alloc_txbdr(struct enetc_bdr *txr)
 	return 0;
 
 err_alloc_tso:
-	dma_free_coherent(txr->dev, txr->bd_count * sizeof(union enetc_tx_bd),
-			  txr->bd_base, txr->bd_dma_base);
-	txr->bd_base = NULL;
+	enetc_dma_free_bdr(txr, sizeof(union enetc_tx_bd));
 err_alloc_bdr:
 	vfree(txr->tx_swbd);
 	txr->tx_swbd = NULL;
@@ -1768,19 +1773,16 @@ static int enetc_alloc_txbdr(struct enetc_bdr *txr)
 
 static void enetc_free_txbdr(struct enetc_bdr *txr)
 {
-	int size, i;
+	int i;
 
 	for (i = 0; i < txr->bd_count; i++)
 		enetc_free_tx_frame(txr, &txr->tx_swbd[i]);
 
-	size = txr->bd_count * sizeof(union enetc_tx_bd);
-
 	dma_free_coherent(txr->dev, txr->bd_count * TSO_HEADER_SIZE,
 			  txr->tso_headers, txr->tso_headers_dma);
 	txr->tso_headers = NULL;
 
-	dma_free_coherent(txr->dev, size, txr->bd_base, txr->bd_dma_base);
-	txr->bd_base = NULL;
+	enetc_dma_free_bdr(txr, sizeof(union enetc_tx_bd));
 
 	vfree(txr->tx_swbd);
 	txr->tx_swbd = NULL;
@@ -1839,12 +1841,7 @@ static int enetc_alloc_rxbdr(struct enetc_bdr *rxr, bool extended)
 
 static void enetc_free_rxbdr(struct enetc_bdr *rxr)
 {
-	int size;
-
-	size = rxr->bd_count * sizeof(union enetc_rx_bd);
-
-	dma_free_coherent(rxr->dev, size, rxr->bd_base, rxr->bd_dma_base);
-	rxr->bd_base = NULL;
+	enetc_dma_free_bdr(rxr, sizeof(union enetc_rx_bd));
 
 	vfree(rxr->rx_swbd);
 	rxr->rx_swbd = NULL;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 04/12] net: enetc: rx_swbd and tx_swbd are never NULL in enetc_free_rxtx_rings()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (2 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 03/12] net: enetc: create enetc_dma_free_bdr() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 05/12] net: enetc: drop redundant enetc_free_tx_frame() call from enetc_free_txbdr() Vladimir Oltean
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

The call path in enetc_close() is:

enetc_close()
-> enetc_free_rxtx_rings()
   -> enetc_free_rx_ring()
      -> tests whether rx_ring->rx_swbd is NULL
   -> enetc_free_tx_ring()
      -> tests whether tx_ring->tx_swbd is NULL
-> enetc_free_rx_resources()
   -> enetc_free_rxbdr()
      -> sets rxr->rx_swbd to NULL
-> enetc_free_tx_resources()
   -> enetc_free_txbdr()
      -> setx txr->tx_swbd to NULL

From the above, it is clear that due to the function ordering, the
checks for NULL are redundant, since the software buffer descriptor
arrays have not yet been set to NULL. Drop these checks.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index ca1dacccf9fe..f41a02c2213e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1880,9 +1880,6 @@ static void enetc_free_tx_ring(struct enetc_bdr *tx_ring)
 {
 	int i;
 
-	if (!tx_ring->tx_swbd)
-		return;
-
 	for (i = 0; i < tx_ring->bd_count; i++) {
 		struct enetc_tx_swbd *tx_swbd = &tx_ring->tx_swbd[i];
 
@@ -1894,9 +1891,6 @@ static void enetc_free_rx_ring(struct enetc_bdr *rx_ring)
 {
 	int i;
 
-	if (!rx_ring->rx_swbd)
-		return;
-
 	for (i = 0; i < rx_ring->bd_count; i++) {
 		struct enetc_rx_swbd *rx_swbd = &rx_ring->rx_swbd[i];
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 05/12] net: enetc: drop redundant enetc_free_tx_frame() call from enetc_free_txbdr()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (3 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 04/12] net: enetc: rx_swbd and tx_swbd are never NULL in enetc_free_rxtx_rings() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 06/12] net: enetc: bring "bool extended" to top-level in enetc_open() Vladimir Oltean
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

The call path in enetc_close() is:

enetc_close()
-> enetc_free_rxtx_rings()
   -> enetc_free_tx_ring()
      -> enetc_free_tx_frame()
-> enetc_free_tx_resources()
   -> enetc_free_txbdr()
      -> enetc_free_tx_frame()

The enetc_free_tx_frame() function is written such that the second call
exits without doing anything, but nonetheless, it is completely
redundant. Delete it. This makes the TX teardown path more similar to
the RX one, where rx_swbd freeing is done in enetc_free_rx_ring(), not
in enetc_free_rxbdr().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index f41a02c2213e..94580496ef64 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1773,11 +1773,6 @@ static int enetc_alloc_txbdr(struct enetc_bdr *txr)
 
 static void enetc_free_txbdr(struct enetc_bdr *txr)
 {
-	int i;
-
-	for (i = 0; i < txr->bd_count; i++)
-		enetc_free_tx_frame(txr, &txr->tx_swbd[i]);
-
 	dma_free_coherent(txr->dev, txr->bd_count * TSO_HEADER_SIZE,
 			  txr->tso_headers, txr->tso_headers_dma);
 	txr->tso_headers = NULL;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 06/12] net: enetc: bring "bool extended" to top-level in enetc_open()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (4 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 05/12] net: enetc: drop redundant enetc_free_tx_frame() call from enetc_free_txbdr() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 07/12] net: enetc: split ring resource allocation from assignment Vladimir Oltean
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

Extended RX buffer descriptors are necessary if they carry RX
timestamps, which will be true when PTP timestamping is enabled.

Right now, the rx_ring->ext_en is set from the function that allocates
ring resources (enetc_alloc_rx_resources() -> enetc_alloc_rxbdr()), and
also used later, in enetc_setup_rxbdr(). It is also used in the
enetc_rxbd() and enetc_rxbd_next() fast path helpers.

We want to decouple resource allocation from BD ring setup, but both
procedures depend on BD size (extended or not). Move the "extended"
boolean to enetc_open() and pass it both to the RX allocation procedure
as well as to the RX ring setup procedure. The latter will set
rx_ring->ext_en from now on.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 94580496ef64..67471c8ea447 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1829,8 +1829,6 @@ static int enetc_alloc_rxbdr(struct enetc_bdr *rxr, bool extended)
 		return err;
 	}
 
-	rxr->ext_en = extended;
-
 	return 0;
 }
 
@@ -1842,9 +1840,8 @@ static void enetc_free_rxbdr(struct enetc_bdr *rxr)
 	rxr->rx_swbd = NULL;
 }
 
-static int enetc_alloc_rx_resources(struct enetc_ndev_priv *priv)
+static int enetc_alloc_rx_resources(struct enetc_ndev_priv *priv, bool extended)
 {
-	bool extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP);
 	int i, err;
 
 	for (i = 0; i < priv->num_rx_rings; i++) {
@@ -2022,7 +2019,8 @@ static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
 	tx_ring->idr = hw->reg + ENETC_SITXIDR;
 }
 
-static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
+static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
+			      bool extended)
 {
 	int idx = rx_ring->index;
 	u32 rbmr;
@@ -2054,6 +2052,7 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 
 	rbmr = ENETC_RBMR_EN;
 
+	rx_ring->ext_en = extended;
 	if (rx_ring->ext_en)
 		rbmr |= ENETC_RBMR_BDS;
 
@@ -2075,7 +2074,7 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
 }
 
-static void enetc_setup_bdrs(struct enetc_ndev_priv *priv)
+static void enetc_setup_bdrs(struct enetc_ndev_priv *priv, bool extended)
 {
 	struct enetc_hw *hw = &priv->si->hw;
 	int i;
@@ -2084,7 +2083,7 @@ static void enetc_setup_bdrs(struct enetc_ndev_priv *priv)
 		enetc_setup_txbdr(hw, priv->tx_ring[i]);
 
 	for (i = 0; i < priv->num_rx_rings; i++)
-		enetc_setup_rxbdr(hw, priv->rx_ring[i]);
+		enetc_setup_rxbdr(hw, priv->rx_ring[i], extended);
 }
 
 static void enetc_clear_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
@@ -2308,8 +2307,11 @@ int enetc_open(struct net_device *ndev)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 	int num_stack_tx_queues;
+	bool extended;
 	int err;
 
+	extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP);
+
 	err = enetc_setup_irqs(priv);
 	if (err)
 		return err;
@@ -2322,7 +2324,7 @@ int enetc_open(struct net_device *ndev)
 	if (err)
 		goto err_alloc_tx;
 
-	err = enetc_alloc_rx_resources(priv);
+	err = enetc_alloc_rx_resources(priv, extended);
 	if (err)
 		goto err_alloc_rx;
 
@@ -2337,7 +2339,7 @@ int enetc_open(struct net_device *ndev)
 		goto err_set_queues;
 
 	enetc_tx_onestep_tstamp_init(priv);
-	enetc_setup_bdrs(priv);
+	enetc_setup_bdrs(priv, extended);
 	enetc_start(ndev);
 
 	return 0;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 07/12] net: enetc: split ring resource allocation from assignment
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (5 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 06/12] net: enetc: bring "bool extended" to top-level in enetc_open() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 08/12] net: enetc: move phylink_start/stop out of enetc_start/stop Vladimir Oltean
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

We have a few instances in the enetc driver where the ring resources
(BD ring iomem, software BD ring, software TSO headers, basically
everything except RX buffers) need to be reallocated. For example, when
RX timestamping is enabled, the RX BD format changes to an extended one
(twice as large).

Currently, this is done using a simplistic enetc_close() -> enetc_open()
procedure. But this is quite crude, since it also invokes phylink_stop()
-> phylink_start(), the link is lost, and a few seconds need to pass for
autoneg to complete again.

In fact it's bad also due to the improper (yolo) error checking. In case
we fail to allocate new resources, we've already freed the old ones, so
the interface is more or less stuck.

To avoid that, we need a system where reconfiguration is possible in a
way in which resources are allocated upfront. This means that there will
be a higher memory usage temporarily, but the assignment of resources to
rings can be done when both the old and new resources are still available.

Introduce a struct enetc_bdr_resource which holds the resources for a
ring, be it RX or TX. This structure duplicates a lot of fields from
struct enetc_bdr (and access to the same fields in the ring structure
was left duplicated, to not change cache characteristics in the fast
path).

When enetc_alloc_tx_resources() runs, it returns an array of resource
elements (one per TX ring), in addition to the existing priv->tx_res.
To populate priv->tx_res with that array, one must call
enetc_assign_tx_resources(), and this also frees the old resources.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 231 +++++++++++++------
 drivers/net/ethernet/freescale/enetc/enetc.h |  19 ++
 2 files changed, 180 insertions(+), 70 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 67471c8ea447..543ae8875bc9 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -1715,47 +1715,54 @@ void enetc_get_si_caps(struct enetc_si *si)
 		si->hw_features |= ENETC_SI_F_PSFP;
 }
 
-static int enetc_dma_alloc_bdr(struct enetc_bdr *r, size_t bd_size)
+static int enetc_dma_alloc_bdr(struct enetc_bdr_resource *res)
 {
-	r->bd_base = dma_alloc_coherent(r->dev, r->bd_count * bd_size,
-					&r->bd_dma_base, GFP_KERNEL);
-	if (!r->bd_base)
+	size_t bd_base_size = res->bd_count * res->bd_size;
+
+	res->bd_base = dma_alloc_coherent(res->dev, bd_base_size,
+					  &res->bd_dma_base, GFP_KERNEL);
+	if (!res->bd_base)
 		return -ENOMEM;
 
 	/* h/w requires 128B alignment */
-	if (!IS_ALIGNED(r->bd_dma_base, 128)) {
-		dma_free_coherent(r->dev, r->bd_count * bd_size, r->bd_base,
-				  r->bd_dma_base);
+	if (!IS_ALIGNED(res->bd_dma_base, 128)) {
+		dma_free_coherent(res->dev, bd_base_size, res->bd_base,
+				  res->bd_dma_base);
 		return -EINVAL;
 	}
 
 	return 0;
 }
 
-static void enetc_dma_free_bdr(struct enetc_bdr *r, size_t bd_size)
+static void enetc_dma_free_bdr(const struct enetc_bdr_resource *res)
 {
-	dma_free_coherent(r->dev, r->bd_count * bd_size, r->bd_base,
-			  r->bd_dma_base);
-	r->bd_base = NULL;
+	size_t bd_base_size = res->bd_count * res->bd_size;
+
+	dma_free_coherent(res->dev, bd_base_size, res->bd_base,
+			  res->bd_dma_base);
 }
 
-static int enetc_alloc_txbdr(struct enetc_bdr *txr)
+static int enetc_alloc_tx_resource(struct enetc_bdr_resource *res,
+				   struct device *dev, size_t bd_count)
 {
 	int err;
 
-	txr->tx_swbd = vzalloc(txr->bd_count * sizeof(struct enetc_tx_swbd));
-	if (!txr->tx_swbd)
+	res->dev = dev;
+	res->bd_count = bd_count;
+	res->bd_size = sizeof(union enetc_tx_bd);
+
+	res->tx_swbd = vzalloc(bd_count * sizeof(*res->tx_swbd));
+	if (!res->tx_swbd)
 		return -ENOMEM;
 
-	err = enetc_dma_alloc_bdr(txr, sizeof(union enetc_tx_bd));
+	err = enetc_dma_alloc_bdr(res);
 	if (err)
 		goto err_alloc_bdr;
 
-	txr->tso_headers = dma_alloc_coherent(txr->dev,
-					      txr->bd_count * TSO_HEADER_SIZE,
-					      &txr->tso_headers_dma,
+	res->tso_headers = dma_alloc_coherent(dev, bd_count * TSO_HEADER_SIZE,
+					      &res->tso_headers_dma,
 					      GFP_KERNEL);
-	if (!txr->tso_headers) {
+	if (!res->tso_headers) {
 		err = -ENOMEM;
 		goto err_alloc_tso;
 	}
@@ -1763,109 +1770,183 @@ static int enetc_alloc_txbdr(struct enetc_bdr *txr)
 	return 0;
 
 err_alloc_tso:
-	enetc_dma_free_bdr(txr, sizeof(union enetc_tx_bd));
+	enetc_dma_free_bdr(res);
 err_alloc_bdr:
-	vfree(txr->tx_swbd);
-	txr->tx_swbd = NULL;
+	vfree(res->tx_swbd);
+	res->tx_swbd = NULL;
 
 	return err;
 }
 
-static void enetc_free_txbdr(struct enetc_bdr *txr)
+static void enetc_free_tx_resource(const struct enetc_bdr_resource *res)
 {
-	dma_free_coherent(txr->dev, txr->bd_count * TSO_HEADER_SIZE,
-			  txr->tso_headers, txr->tso_headers_dma);
-	txr->tso_headers = NULL;
-
-	enetc_dma_free_bdr(txr, sizeof(union enetc_tx_bd));
-
-	vfree(txr->tx_swbd);
-	txr->tx_swbd = NULL;
+	dma_free_coherent(res->dev, res->bd_count * TSO_HEADER_SIZE,
+			  res->tso_headers, res->tso_headers_dma);
+	enetc_dma_free_bdr(res);
+	vfree(res->tx_swbd);
 }
 
-static int enetc_alloc_tx_resources(struct enetc_ndev_priv *priv)
+static struct enetc_bdr_resource *
+enetc_alloc_tx_resources(struct enetc_ndev_priv *priv)
 {
+	struct enetc_bdr_resource *tx_res;
 	int i, err;
 
+	tx_res = kcalloc(priv->num_tx_rings, sizeof(*tx_res), GFP_KERNEL);
+	if (!tx_res)
+		return ERR_PTR(-ENOMEM);
+
 	for (i = 0; i < priv->num_tx_rings; i++) {
-		err = enetc_alloc_txbdr(priv->tx_ring[i]);
+		struct enetc_bdr *tx_ring = priv->tx_ring[i];
 
+		err = enetc_alloc_tx_resource(&tx_res[i], tx_ring->dev,
+					      tx_ring->bd_count);
 		if (err)
 			goto fail;
 	}
 
-	return 0;
+	return tx_res;
 
 fail:
 	while (i-- > 0)
-		enetc_free_txbdr(priv->tx_ring[i]);
+		enetc_free_tx_resource(&tx_res[i]);
 
-	return err;
+	kfree(tx_res);
+
+	return ERR_PTR(err);
 }
 
-static void enetc_free_tx_resources(struct enetc_ndev_priv *priv)
+static void enetc_free_tx_resources(const struct enetc_bdr_resource *tx_res,
+				    size_t num_resources)
 {
-	int i;
+	size_t i;
 
-	for (i = 0; i < priv->num_tx_rings; i++)
-		enetc_free_txbdr(priv->tx_ring[i]);
+	for (i = 0; i < num_resources; i++)
+		enetc_free_tx_resource(&tx_res[i]);
+
+	kfree(tx_res);
 }
 
-static int enetc_alloc_rxbdr(struct enetc_bdr *rxr, bool extended)
+static int enetc_alloc_rx_resource(struct enetc_bdr_resource *res,
+				   struct device *dev, size_t bd_count,
+				   bool extended)
 {
-	size_t size = sizeof(union enetc_rx_bd);
 	int err;
 
-	rxr->rx_swbd = vzalloc(rxr->bd_count * sizeof(struct enetc_rx_swbd));
-	if (!rxr->rx_swbd)
-		return -ENOMEM;
-
+	res->dev = dev;
+	res->bd_count = bd_count;
+	res->bd_size = sizeof(union enetc_rx_bd);
 	if (extended)
-		size *= 2;
+		res->bd_size *= 2;
 
-	err = enetc_dma_alloc_bdr(rxr, size);
+	res->rx_swbd = vzalloc(bd_count * sizeof(struct enetc_rx_swbd));
+	if (!res->rx_swbd)
+		return -ENOMEM;
+
+	err = enetc_dma_alloc_bdr(res);
 	if (err) {
-		vfree(rxr->rx_swbd);
+		vfree(res->rx_swbd);
 		return err;
 	}
 
 	return 0;
 }
 
-static void enetc_free_rxbdr(struct enetc_bdr *rxr)
+static void enetc_free_rx_resource(const struct enetc_bdr_resource *res)
 {
-	enetc_dma_free_bdr(rxr, sizeof(union enetc_rx_bd));
-
-	vfree(rxr->rx_swbd);
-	rxr->rx_swbd = NULL;
+	enetc_dma_free_bdr(res);
+	vfree(res->rx_swbd);
 }
 
-static int enetc_alloc_rx_resources(struct enetc_ndev_priv *priv, bool extended)
+static struct enetc_bdr_resource *
+enetc_alloc_rx_resources(struct enetc_ndev_priv *priv, bool extended)
 {
+	struct enetc_bdr_resource *rx_res;
 	int i, err;
 
+	rx_res = kcalloc(priv->num_rx_rings, sizeof(*rx_res), GFP_KERNEL);
+	if (!rx_res)
+		return ERR_PTR(-ENOMEM);
+
 	for (i = 0; i < priv->num_rx_rings; i++) {
-		err = enetc_alloc_rxbdr(priv->rx_ring[i], extended);
+		struct enetc_bdr *rx_ring = priv->rx_ring[i];
 
+		err = enetc_alloc_rx_resource(&rx_res[i], rx_ring->dev,
+					      rx_ring->bd_count, extended);
 		if (err)
 			goto fail;
 	}
 
-	return 0;
+	return rx_res;
 
 fail:
 	while (i-- > 0)
-		enetc_free_rxbdr(priv->rx_ring[i]);
+		enetc_free_rx_resource(&rx_res[i]);
 
-	return err;
+	kfree(rx_res);
+
+	return ERR_PTR(err);
+}
+
+static void enetc_free_rx_resources(const struct enetc_bdr_resource *rx_res,
+				    size_t num_resources)
+{
+	size_t i;
+
+	for (i = 0; i < num_resources; i++)
+		enetc_free_rx_resource(&rx_res[i]);
+
+	kfree(rx_res);
 }
 
-static void enetc_free_rx_resources(struct enetc_ndev_priv *priv)
+static void enetc_assign_tx_resource(struct enetc_bdr *tx_ring,
+				     const struct enetc_bdr_resource *res)
+{
+	tx_ring->bd_base = res ? res->bd_base : NULL;
+	tx_ring->bd_dma_base = res ? res->bd_dma_base : 0;
+	tx_ring->tx_swbd = res ? res->tx_swbd : NULL;
+	tx_ring->tso_headers = res ? res->tso_headers : NULL;
+	tx_ring->tso_headers_dma = res ? res->tso_headers_dma : 0;
+}
+
+static void enetc_assign_rx_resource(struct enetc_bdr *rx_ring,
+				     const struct enetc_bdr_resource *res)
+{
+	rx_ring->bd_base = res ? res->bd_base : NULL;
+	rx_ring->bd_dma_base = res ? res->bd_dma_base : 0;
+	rx_ring->rx_swbd = res ? res->rx_swbd : NULL;
+}
+
+static void enetc_assign_tx_resources(struct enetc_ndev_priv *priv,
+				      const struct enetc_bdr_resource *res)
 {
 	int i;
 
-	for (i = 0; i < priv->num_rx_rings; i++)
-		enetc_free_rxbdr(priv->rx_ring[i]);
+	if (priv->tx_res)
+		enetc_free_tx_resources(priv->tx_res, priv->num_tx_rings);
+
+	for (i = 0; i < priv->num_tx_rings; i++) {
+		enetc_assign_tx_resource(priv->tx_ring[i],
+					 res ? &res[i] : NULL);
+	}
+
+	priv->tx_res = res;
+}
+
+static void enetc_assign_rx_resources(struct enetc_ndev_priv *priv,
+				      const struct enetc_bdr_resource *res)
+{
+	int i;
+
+	if (priv->rx_res)
+		enetc_free_rx_resources(priv->rx_res, priv->num_rx_rings);
+
+	for (i = 0; i < priv->num_rx_rings; i++) {
+		enetc_assign_rx_resource(priv->rx_ring[i],
+					 res ? &res[i] : NULL);
+	}
+
+	priv->rx_res = res;
 }
 
 static void enetc_free_tx_ring(struct enetc_bdr *tx_ring)
@@ -2306,6 +2387,7 @@ void enetc_start(struct net_device *ndev)
 int enetc_open(struct net_device *ndev)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	struct enetc_bdr_resource *tx_res, *rx_res;
 	int num_stack_tx_queues;
 	bool extended;
 	int err;
@@ -2320,13 +2402,17 @@ int enetc_open(struct net_device *ndev)
 	if (err)
 		goto err_phy_connect;
 
-	err = enetc_alloc_tx_resources(priv);
-	if (err)
+	tx_res = enetc_alloc_tx_resources(priv);
+	if (IS_ERR(tx_res)) {
+		err = PTR_ERR(tx_res);
 		goto err_alloc_tx;
+	}
 
-	err = enetc_alloc_rx_resources(priv, extended);
-	if (err)
+	rx_res = enetc_alloc_rx_resources(priv, extended);
+	if (IS_ERR(rx_res)) {
+		err = PTR_ERR(rx_res);
 		goto err_alloc_rx;
+	}
 
 	num_stack_tx_queues = enetc_num_stack_tx_queues(priv);
 
@@ -2339,15 +2425,17 @@ int enetc_open(struct net_device *ndev)
 		goto err_set_queues;
 
 	enetc_tx_onestep_tstamp_init(priv);
+	enetc_assign_tx_resources(priv, tx_res);
+	enetc_assign_rx_resources(priv, rx_res);
 	enetc_setup_bdrs(priv, extended);
 	enetc_start(ndev);
 
 	return 0;
 
 err_set_queues:
-	enetc_free_rx_resources(priv);
+	enetc_free_rx_resources(rx_res, priv->num_rx_rings);
 err_alloc_rx:
-	enetc_free_tx_resources(priv);
+	enetc_free_tx_resources(tx_res, priv->num_tx_rings);
 err_alloc_tx:
 	if (priv->phylink)
 		phylink_disconnect_phy(priv->phylink);
@@ -2391,8 +2479,11 @@ int enetc_close(struct net_device *ndev)
 	if (priv->phylink)
 		phylink_disconnect_phy(priv->phylink);
 	enetc_free_rxtx_rings(priv);
-	enetc_free_rx_resources(priv);
-	enetc_free_tx_resources(priv);
+
+	/* Avoids dangling pointers and also frees old resources */
+	enetc_assign_rx_resources(priv, NULL);
+	enetc_assign_tx_resources(priv, NULL);
+
 	enetc_free_irqs(priv);
 
 	return 0;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 416e4138dbaf..fd161a60a797 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -85,6 +85,23 @@ struct enetc_xdp_data {
 #define ENETC_TX_RING_DEFAULT_SIZE	2048
 #define ENETC_DEFAULT_TX_WORK		(ENETC_TX_RING_DEFAULT_SIZE / 2)
 
+struct enetc_bdr_resource {
+	/* Input arguments saved for teardown */
+	struct device *dev; /* for DMA mapping */
+	size_t bd_count;
+	size_t bd_size;
+
+	/* Resource proper */
+	void *bd_base; /* points to Rx or Tx BD ring */
+	dma_addr_t bd_dma_base;
+	union {
+		struct enetc_tx_swbd *tx_swbd;
+		struct enetc_rx_swbd *rx_swbd;
+	};
+	char *tso_headers;
+	dma_addr_t tso_headers_dma;
+};
+
 struct enetc_bdr {
 	struct device *dev; /* for DMA mapping */
 	struct net_device *ndev;
@@ -344,6 +361,8 @@ struct enetc_ndev_priv {
 	struct enetc_bdr **xdp_tx_ring;
 	struct enetc_bdr *tx_ring[16];
 	struct enetc_bdr *rx_ring[16];
+	const struct enetc_bdr_resource *tx_res;
+	const struct enetc_bdr_resource *rx_res;
 
 	struct enetc_cls_rule *cls_rules;
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 08/12] net: enetc: move phylink_start/stop out of enetc_start/stop
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (6 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 07/12] net: enetc: split ring resource allocation from assignment Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping Vladimir Oltean
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

We want to introduce a fast interface reconfiguration procedure, which
involves temporarily stopping the rings.

But we want enetc_start() and enetc_stop() to not restart PHY autoneg,
because that can take a few seconds until it completes again.

So we need part of enetc_start() and enetc_stop(), but not all of them.
Move phylink_start() right next to phylink_of_phy_connect(), and
phylink_stop() right next to phylink_disconnect_phy(), both still in
ndo_open() and ndo_stop().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 26 ++++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 543ae8875bc9..014de5425b81 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2322,8 +2322,11 @@ static int enetc_phylink_connect(struct net_device *ndev)
 	struct ethtool_eee edata;
 	int err;
 
-	if (!priv->phylink)
-		return 0; /* phy-less mode */
+	if (!priv->phylink) {
+		/* phy-less mode */
+		netif_carrier_on(ndev);
+		return 0;
+	}
 
 	err = phylink_of_phy_connect(priv->phylink, priv->dev->of_node, 0);
 	if (err) {
@@ -2335,6 +2338,8 @@ static int enetc_phylink_connect(struct net_device *ndev)
 	memset(&edata, 0, sizeof(struct ethtool_eee));
 	phylink_ethtool_set_eee(priv->phylink, &edata);
 
+	phylink_start(priv->phylink);
+
 	return 0;
 }
 
@@ -2376,11 +2381,6 @@ void enetc_start(struct net_device *ndev)
 		enable_irq(irq);
 	}
 
-	if (priv->phylink)
-		phylink_start(priv->phylink);
-	else
-		netif_carrier_on(ndev);
-
 	netif_tx_start_all_queues(ndev);
 }
 
@@ -2461,11 +2461,6 @@ void enetc_stop(struct net_device *ndev)
 		napi_disable(&priv->int_vector[i]->napi);
 	}
 
-	if (priv->phylink)
-		phylink_stop(priv->phylink);
-	else
-		netif_carrier_off(ndev);
-
 	enetc_clear_interrupts(priv);
 }
 
@@ -2476,8 +2471,13 @@ int enetc_close(struct net_device *ndev)
 	enetc_stop(ndev);
 	enetc_clear_bdrs(priv);
 
-	if (priv->phylink)
+	if (priv->phylink) {
+		phylink_stop(priv->phylink);
 		phylink_disconnect_phy(priv->phylink);
+	} else {
+		netif_carrier_off(ndev);
+	}
+
 	enetc_free_rxtx_rings(priv);
 
 	/* Avoids dangling pointers and also frees old resources */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (7 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 08/12] net: enetc: move phylink_start/stop out of enetc_start/stop Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-18 10:51   ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 10/12] net: enetc: rename "xdp" and "dev" in enetc_setup_bpf() Vladimir Oltean
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

The crude enetc_stop() -> enetc_open() mechanism suffers from 2
problems:

1. improper error checking
2. it involves phylink_stop() -> phylink_start() which loses the link

Right now, the driver is prepared to offer a better alternative: a ring
reconfiguration procedure which takes the RX BD size (normal or
extended) as argument. It allocates new resources (failing if that
fails), stops the traffic, and assigns the new resources to the rings.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 68 ++++++++++++++++----
 1 file changed, 56 insertions(+), 12 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 014de5425b81..dc54fe7b4e86 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2489,6 +2489,46 @@ int enetc_close(struct net_device *ndev)
 	return 0;
 }
 
+static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended)
+{
+	struct enetc_bdr_resource *tx_res, *rx_res;
+	int err;
+
+	ASSERT_RTNL();
+
+	/* If the interface is down, do nothing. */
+	if (!netif_running(priv->ndev))
+		return 0;
+
+	tx_res = enetc_alloc_tx_resources(priv);
+	if (IS_ERR(tx_res)) {
+		err = PTR_ERR(tx_res);
+		goto out;
+	}
+
+	rx_res = enetc_alloc_rx_resources(priv, extended);
+	if (IS_ERR(rx_res)) {
+		err = PTR_ERR(rx_res);
+		goto out_free_tx_res;
+	}
+
+	enetc_stop(priv->ndev);
+	enetc_clear_bdrs(priv);
+	enetc_free_rxtx_rings(priv);
+
+	enetc_assign_tx_resources(priv, tx_res);
+	enetc_assign_rx_resources(priv, rx_res);
+	enetc_setup_bdrs(priv, extended);
+	enetc_start(priv->ndev);
+
+	return 0;
+
+out_free_tx_res:
+	enetc_free_tx_resources(tx_res, priv->num_tx_rings);
+out:
+	return err;
+}
+
 int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
@@ -2681,43 +2721,47 @@ void enetc_set_features(struct net_device *ndev, netdev_features_t features)
 static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
 {
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	int err, new_offloads = priv->active_offloads;
 	struct hwtstamp_config config;
-	int ao;
 
 	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
 		return -EFAULT;
 
 	switch (config.tx_type) {
 	case HWTSTAMP_TX_OFF:
-		priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
+		new_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
 		break;
 	case HWTSTAMP_TX_ON:
-		priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
-		priv->active_offloads |= ENETC_F_TX_TSTAMP;
+		new_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
+		new_offloads |= ENETC_F_TX_TSTAMP;
 		break;
 	case HWTSTAMP_TX_ONESTEP_SYNC:
-		priv->active_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
-		priv->active_offloads |= ENETC_F_TX_ONESTEP_SYNC_TSTAMP;
+		new_offloads &= ~ENETC_F_TX_TSTAMP_MASK;
+		new_offloads |= ENETC_F_TX_ONESTEP_SYNC_TSTAMP;
 		break;
 	default:
 		return -ERANGE;
 	}
 
-	ao = priv->active_offloads;
 	switch (config.rx_filter) {
 	case HWTSTAMP_FILTER_NONE:
-		priv->active_offloads &= ~ENETC_F_RX_TSTAMP;
+		new_offloads &= ~ENETC_F_RX_TSTAMP;
 		break;
 	default:
-		priv->active_offloads |= ENETC_F_RX_TSTAMP;
+		new_offloads |= ENETC_F_RX_TSTAMP;
 		config.rx_filter = HWTSTAMP_FILTER_ALL;
 	}
 
-	if (netif_running(ndev) && ao != priv->active_offloads) {
-		enetc_close(ndev);
-		enetc_open(ndev);
+	if ((new_offloads ^ priv->active_offloads) & ENETC_F_RX_TSTAMP) {
+		bool extended = !!(new_offloads & ENETC_F_RX_TSTAMP);
+
+		err = enetc_reconfigure(priv, extended);
+		if (err)
+			return err;
 	}
 
+	priv->active_offloads = new_offloads;
+
 	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
 	       -EFAULT : 0;
 }
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 10/12] net: enetc: rename "xdp" and "dev" in enetc_setup_bpf()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (8 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 11/12] net: enetc: set up XDP program under enetc_reconfigure() Vladimir Oltean
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

Follow the convention from this driver, which is to name "struct
net_device *" as "ndev", and the convention from other drivers, to name
"struct netdev_bpf *" as "bpf".

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 16 ++++++++--------
 drivers/net/ethernet/freescale/enetc/enetc.h |  2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index dc54fe7b4e86..ce3319f55573 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2586,10 +2586,10 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
 	return 0;
 }
 
-static int enetc_setup_xdp_prog(struct net_device *dev, struct bpf_prog *prog,
+static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog,
 				struct netlink_ext_ack *extack)
 {
-	struct enetc_ndev_priv *priv = netdev_priv(dev);
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 	struct bpf_prog *old_prog;
 	bool is_up;
 	int i;
@@ -2597,9 +2597,9 @@ static int enetc_setup_xdp_prog(struct net_device *dev, struct bpf_prog *prog,
 	/* The buffer layout is changing, so we need to drain the old
 	 * RX buffers and seed new ones.
 	 */
-	is_up = netif_running(dev);
+	is_up = netif_running(ndev);
 	if (is_up)
-		dev_close(dev);
+		dev_close(ndev);
 
 	old_prog = xchg(&priv->xdp_prog, prog);
 	if (old_prog)
@@ -2617,16 +2617,16 @@ static int enetc_setup_xdp_prog(struct net_device *dev, struct bpf_prog *prog,
 	}
 
 	if (is_up)
-		return dev_open(dev, extack);
+		return dev_open(ndev, extack);
 
 	return 0;
 }
 
-int enetc_setup_bpf(struct net_device *dev, struct netdev_bpf *xdp)
+int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
 {
-	switch (xdp->command) {
+	switch (bpf->command) {
 	case XDP_SETUP_PROG:
-		return enetc_setup_xdp_prog(dev, xdp->prog, xdp->extack);
+		return enetc_setup_xdp_prog(ndev, bpf->prog, bpf->extack);
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index fd161a60a797..6a87aa972e1e 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -415,7 +415,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev);
 void enetc_set_features(struct net_device *ndev, netdev_features_t features);
 int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
 int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data);
-int enetc_setup_bpf(struct net_device *dev, struct netdev_bpf *xdp);
+int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf);
 int enetc_xdp_xmit(struct net_device *ndev, int num_frames,
 		   struct xdp_frame **frames, u32 flags);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 11/12] net: enetc: set up XDP program under enetc_reconfigure()
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (9 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 10/12] net: enetc: rename "xdp" and "dev" in enetc_setup_bpf() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-17 23:02 ` [PATCH net-next 12/12] net: enetc: prioritize ability to go down over packet processing Vladimir Oltean
  2023-01-19  5:10 ` [PATCH net-next 00/12] ENETC BD ring cleanup patchwork-bot+netdevbpf
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

Offloading a BPF program to the RX path of the driver suffers from the
same problems as the PTP reconfiguration - improper error checking can
leave the driver in an invalid state, and the link on the PHY is lost.

Reuse the enetc_reconfigure() procedure, but here, we need to run some
code in the middle of the ring reconfiguration procedure - while the
interface is still down. Introduce a callback which makes that possible.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 51 ++++++++++++--------
 1 file changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index ce3319f55573..eeff69336a80 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2489,16 +2489,24 @@ int enetc_close(struct net_device *ndev)
 	return 0;
 }
 
-static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended)
+static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended,
+			     int (*cb)(struct enetc_ndev_priv *priv, void *ctx),
+			     void *ctx)
 {
 	struct enetc_bdr_resource *tx_res, *rx_res;
 	int err;
 
 	ASSERT_RTNL();
 
-	/* If the interface is down, do nothing. */
-	if (!netif_running(priv->ndev))
+	/* If the interface is down, run the callback right away,
+	 * without reconfiguration.
+	 */
+	if (!netif_running(priv->ndev)) {
+		if (cb)
+			cb(priv, ctx);
+
 		return 0;
+	}
 
 	tx_res = enetc_alloc_tx_resources(priv);
 	if (IS_ERR(tx_res)) {
@@ -2516,6 +2524,10 @@ static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended)
 	enetc_clear_bdrs(priv);
 	enetc_free_rxtx_rings(priv);
 
+	/* Interface is down, run optional callback now */
+	if (cb)
+		cb(priv, ctx);
+
 	enetc_assign_tx_resources(priv, tx_res);
 	enetc_assign_rx_resources(priv, rx_res);
 	enetc_setup_bdrs(priv, extended);
@@ -2586,21 +2598,11 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
 	return 0;
 }
 
-static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog,
-				struct netlink_ext_ack *extack)
+static int enetc_reconfigure_xdp_cb(struct enetc_ndev_priv *priv, void *ctx)
 {
-	struct enetc_ndev_priv *priv = netdev_priv(ndev);
-	struct bpf_prog *old_prog;
-	bool is_up;
+	struct bpf_prog *old_prog, *prog = ctx;
 	int i;
 
-	/* The buffer layout is changing, so we need to drain the old
-	 * RX buffers and seed new ones.
-	 */
-	is_up = netif_running(ndev);
-	if (is_up)
-		dev_close(ndev);
-
 	old_prog = xchg(&priv->xdp_prog, prog);
 	if (old_prog)
 		bpf_prog_put(old_prog);
@@ -2616,12 +2618,23 @@ static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog,
 			rx_ring->buffer_offset = ENETC_RXB_PAD;
 	}
 
-	if (is_up)
-		return dev_open(ndev, extack);
-
 	return 0;
 }
 
+static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog,
+				struct netlink_ext_ack *extack)
+{
+	struct enetc_ndev_priv *priv = netdev_priv(ndev);
+	bool extended;
+
+	extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP);
+
+	/* The buffer layout is changing, so we need to drain the old
+	 * RX buffers and seed new ones.
+	 */
+	return enetc_reconfigure(priv, extended, enetc_reconfigure_xdp_cb, prog);
+}
+
 int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
 {
 	switch (bpf->command) {
@@ -2755,7 +2768,7 @@ static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr)
 	if ((new_offloads ^ priv->active_offloads) & ENETC_F_RX_TSTAMP) {
 		bool extended = !!(new_offloads & ENETC_F_RX_TSTAMP);
 
-		err = enetc_reconfigure(priv, extended);
+		err = enetc_reconfigure(priv, extended, NULL, NULL);
 		if (err)
 			return err;
 	}
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH net-next 12/12] net: enetc: prioritize ability to go down over packet processing
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (10 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 11/12] net: enetc: set up XDP program under enetc_reconfigure() Vladimir Oltean
@ 2023-01-17 23:02 ` Vladimir Oltean
  2023-01-19  5:10 ` [PATCH net-next 00/12] ENETC BD ring cleanup patchwork-bot+netdevbpf
  12 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-17 23:02 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

napi_synchronize() from enetc_stop() waits until the softirq has
finished execution and no longer wants to be rescheduled. However under
high traffic load, this will never happen, and the interface can never
be closed.

The problem is the fact that the NAPI poll routine is written to update
the consumer index which makes the device want to put more buffers in
the RX ring, which restarts the madness again.

Browsing around, it seems that some drivers like i40e keep a bit
(__I40E_VSI_DOWN) which they use as communication between the control
path and the data path. But that isn't my first choice, because
complications ensue - since the enetc hardirq may trigger while we are
in a theoretical ENETC_DOWN state, it may happen that enetc_msix() masks
it, but enetc_poll() never unmasks it. To prevent a stall in that case,
one would need to schedule all NAPI instances when ENETC_DOWN gets
cleared, to process what's pending.

I find it more desirable for the control path - enetc_stop() - to just
quiesce the RX ring and let the softirq finish what remains there,
without any explicit communication, just by making hardware not provide
any more packets.

This seems possible with the Enable bit of the RX BD ring (RBaMR[EN]).
I can't seem to find an exact definition of what this bit does, but when
the RX ring is disabled, the port seems to no longer update the producer
index, and not react to software updates of the consumer index.

In fact, the RBaMR[EN] bit is already toggled by the driver, but too
late for what we want:

enetc_close()
-> enetc_stop()
   -> napi_synchronize()
-> enetc_clear_bdrs()
   -> enetc_clear_rxbdr()

The enetc_clear_bdrs() function contains not only logic to disable the
RX and TX rings, but also logic to wait for the TX ring stop being busy.

We split enetc_clear_bdrs() into enetc_disable_bdrs() and
enetc_wait_bdrs(). One needs to run before napi_synchronize() and the
other after (NAPI also processes TX completions, so we maximize our
chances of not waiting for the ENETC_TBSR_BUSY bit - unless a packet is
stuck for some reason, ofc).

We also split off enetc_enable_bdrs() from enetc_setup_bdrs(), and call
this from the mirror position in enetc_start() compared to enetc_stop(),
i.e. right before netif_tx_start_all_queues().

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
 drivers/net/ethernet/freescale/enetc/enetc.c | 81 +++++++++++++++-----
 1 file changed, 63 insertions(+), 18 deletions(-)

diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index eeff69336a80..6e54d49176ad 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -2088,7 +2088,7 @@ static void enetc_setup_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
 	/* enable Tx ints by setting pkt thr to 1 */
 	enetc_txbdr_wr(hw, idx, ENETC_TBICR0, ENETC_TBICR0_ICEN | 0x1);
 
-	tbmr = ENETC_TBMR_EN | ENETC_TBMR_SET_PRIO(tx_ring->prio);
+	tbmr = ENETC_TBMR_SET_PRIO(tx_ring->prio);
 	if (tx_ring->ndev->features & NETIF_F_HW_VLAN_CTAG_TX)
 		tbmr |= ENETC_TBMR_VIH;
 
@@ -2104,7 +2104,7 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
 			      bool extended)
 {
 	int idx = rx_ring->index;
-	u32 rbmr;
+	u32 rbmr = 0;
 
 	enetc_rxbdr_wr(hw, idx, ENETC_RBBAR0,
 		       lower_32_bits(rx_ring->bd_dma_base));
@@ -2131,8 +2131,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
 	/* enable Rx ints by setting pkt thr to 1 */
 	enetc_rxbdr_wr(hw, idx, ENETC_RBICR0, ENETC_RBICR0_ICEN | 0x1);
 
-	rbmr = ENETC_RBMR_EN;
-
 	rx_ring->ext_en = extended;
 	if (rx_ring->ext_en)
 		rbmr |= ENETC_RBMR_BDS;
@@ -2151,7 +2149,6 @@ static void enetc_setup_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring,
 	enetc_refill_rx_ring(rx_ring, enetc_bd_unused(rx_ring));
 	enetc_unlock_mdio();
 
-	/* enable ring */
 	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
 }
 
@@ -2167,7 +2164,39 @@ static void enetc_setup_bdrs(struct enetc_ndev_priv *priv, bool extended)
 		enetc_setup_rxbdr(hw, priv->rx_ring[i], extended);
 }
 
-static void enetc_clear_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
+static void enetc_enable_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
+{
+	int idx = tx_ring->index;
+	u32 tbmr;
+
+	tbmr = enetc_txbdr_rd(hw, idx, ENETC_TBMR);
+	tbmr |= ENETC_TBMR_EN;
+	enetc_txbdr_wr(hw, idx, ENETC_TBMR, tbmr);
+}
+
+static void enetc_enable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
+{
+	int idx = rx_ring->index;
+	u32 rbmr;
+
+	rbmr = enetc_rxbdr_rd(hw, idx, ENETC_RBMR);
+	rbmr |= ENETC_RBMR_EN;
+	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, rbmr);
+}
+
+static void enetc_enable_bdrs(struct enetc_ndev_priv *priv)
+{
+	struct enetc_hw *hw = &priv->si->hw;
+	int i;
+
+	for (i = 0; i < priv->num_tx_rings; i++)
+		enetc_enable_txbdr(hw, priv->tx_ring[i]);
+
+	for (i = 0; i < priv->num_rx_rings; i++)
+		enetc_enable_rxbdr(hw, priv->rx_ring[i]);
+}
+
+static void enetc_disable_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 {
 	int idx = rx_ring->index;
 
@@ -2175,13 +2204,30 @@ static void enetc_clear_rxbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 	enetc_rxbdr_wr(hw, idx, ENETC_RBMR, 0);
 }
 
-static void enetc_clear_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
+static void enetc_disable_txbdr(struct enetc_hw *hw, struct enetc_bdr *rx_ring)
 {
-	int delay = 8, timeout = 100;
-	int idx = tx_ring->index;
+	int idx = rx_ring->index;
 
 	/* disable EN bit on ring */
 	enetc_txbdr_wr(hw, idx, ENETC_TBMR, 0);
+}
+
+static void enetc_disable_bdrs(struct enetc_ndev_priv *priv)
+{
+	struct enetc_hw *hw = &priv->si->hw;
+	int i;
+
+	for (i = 0; i < priv->num_tx_rings; i++)
+		enetc_disable_txbdr(hw, priv->tx_ring[i]);
+
+	for (i = 0; i < priv->num_rx_rings; i++)
+		enetc_disable_rxbdr(hw, priv->rx_ring[i]);
+}
+
+static void enetc_wait_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
+{
+	int delay = 8, timeout = 100;
+	int idx = tx_ring->index;
 
 	/* wait for busy to clear */
 	while (delay < timeout &&
@@ -2195,18 +2241,13 @@ static void enetc_clear_txbdr(struct enetc_hw *hw, struct enetc_bdr *tx_ring)
 			    idx);
 }
 
-static void enetc_clear_bdrs(struct enetc_ndev_priv *priv)
+static void enetc_wait_bdrs(struct enetc_ndev_priv *priv)
 {
 	struct enetc_hw *hw = &priv->si->hw;
 	int i;
 
 	for (i = 0; i < priv->num_tx_rings; i++)
-		enetc_clear_txbdr(hw, priv->tx_ring[i]);
-
-	for (i = 0; i < priv->num_rx_rings; i++)
-		enetc_clear_rxbdr(hw, priv->rx_ring[i]);
-
-	udelay(1);
+		enetc_wait_txbdr(hw, priv->tx_ring[i]);
 }
 
 static int enetc_setup_irqs(struct enetc_ndev_priv *priv)
@@ -2381,6 +2422,8 @@ void enetc_start(struct net_device *ndev)
 		enable_irq(irq);
 	}
 
+	enetc_enable_bdrs(priv);
+
 	netif_tx_start_all_queues(ndev);
 }
 
@@ -2452,6 +2495,8 @@ void enetc_stop(struct net_device *ndev)
 
 	netif_tx_stop_all_queues(ndev);
 
+	enetc_disable_bdrs(priv);
+
 	for (i = 0; i < priv->bdr_int_num; i++) {
 		int irq = pci_irq_vector(priv->si->pdev,
 					 ENETC_BDR_INT_BASE_IDX + i);
@@ -2461,6 +2506,8 @@ void enetc_stop(struct net_device *ndev)
 		napi_disable(&priv->int_vector[i]->napi);
 	}
 
+	enetc_wait_bdrs(priv);
+
 	enetc_clear_interrupts(priv);
 }
 
@@ -2469,7 +2516,6 @@ int enetc_close(struct net_device *ndev)
 	struct enetc_ndev_priv *priv = netdev_priv(ndev);
 
 	enetc_stop(ndev);
-	enetc_clear_bdrs(priv);
 
 	if (priv->phylink) {
 		phylink_stop(priv->phylink);
@@ -2521,7 +2567,6 @@ static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended,
 	}
 
 	enetc_stop(priv->ndev);
-	enetc_clear_bdrs(priv);
 	enetc_free_rxtx_rings(priv);
 
 	/* Interface is down, run optional callback now */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping
  2023-01-17 23:02 ` [PATCH net-next 09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping Vladimir Oltean
@ 2023-01-18 10:51   ` Vladimir Oltean
  0 siblings, 0 replies; 15+ messages in thread
From: Vladimir Oltean @ 2023-01-18 10:51 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Claudiu Manoil

On Wed, Jan 18, 2023 at 01:02:31AM +0200, Vladimir Oltean wrote:
> The crude enetc_stop() -> enetc_open() mechanism suffers from 2
> problems:
> 
> 1. improper error checking
> 2. it involves phylink_stop() -> phylink_start() which loses the link
> 
> Right now, the driver is prepared to offer a better alternative: a ring
> reconfiguration procedure which takes the RX BD size (normal or
> extended) as argument. It allocates new resources (failing if that
> fails), stops the traffic, and assigns the new resources to the rings.
> 
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---

There is a transient build warning here which I didn't notice at home:

../drivers/net/ethernet/freescale/enetc/enetc.c:2492:12: warning: ‘enetc_reconfigure’ defined but not used [-Wunused-function]
 2492 | static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended)
      |            ^~~~~~~~~~~~~~~~~

because enetc_hwtstamp_set() (the caller of enetc_reconfigure()) is
apparently under #ifdef CONFIG_FSL_ENETC_PTP_CLOCK.

A later patch also uses enetc_reconfigure() from enetc_setup_xdp_prog(),
which isn't conditionally compiled, so the warning goes away.

What do the experts think, resend or leave it as is?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH net-next 00/12] ENETC BD ring cleanup
  2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
                   ` (11 preceding siblings ...)
  2023-01-17 23:02 ` [PATCH net-next 12/12] net: enetc: prioritize ability to go down over packet processing Vladimir Oltean
@ 2023-01-19  5:10 ` patchwork-bot+netdevbpf
  12 siblings, 0 replies; 15+ messages in thread
From: patchwork-bot+netdevbpf @ 2023-01-19  5:10 UTC (permalink / raw)
  To: Vladimir Oltean; +Cc: netdev, davem, edumazet, kuba, pabeni, claudiu.manoil

Hello:

This series was applied to netdev/net-next.git (master)
by Jakub Kicinski <kuba@kernel.org>:

On Wed, 18 Jan 2023 01:02:22 +0200 you wrote:
> The highlights of this patch set are:
> 
> - Installing a BPF program and changing PTP RX timestamping settings are
>   currently implemented through a port reconfiguration procedure which
>   triggers an AN restart on the PHY, and these procedures are not
>   generally guaranteed to leave the port in a sane state. Patches 9/12
>   and 11/12 address that.
> 
> [...]

Here is the summary with links:
  - [net-next,01/12] net: enetc: set next_to_clean/next_to_use just from enetc_setup_txbdr()
    https://git.kernel.org/netdev/net-next/c/1cbf19c575dd
  - [net-next,02/12] net: enetc: set up RX ring indices from enetc_setup_rxbdr()
    https://git.kernel.org/netdev/net-next/c/fbf1cff98c95
  - [net-next,03/12] net: enetc: create enetc_dma_free_bdr()
    https://git.kernel.org/netdev/net-next/c/0d6cfd0f5e4d
  - [net-next,04/12] net: enetc: rx_swbd and tx_swbd are never NULL in enetc_free_rxtx_rings()
    https://git.kernel.org/netdev/net-next/c/2c3387109d11
  - [net-next,05/12] net: enetc: drop redundant enetc_free_tx_frame() call from enetc_free_txbdr()
    https://git.kernel.org/netdev/net-next/c/bbd6043f74e1
  - [net-next,06/12] net: enetc: bring "bool extended" to top-level in enetc_open()
    https://git.kernel.org/netdev/net-next/c/d075db51e013
  - [net-next,07/12] net: enetc: split ring resource allocation from assignment
    https://git.kernel.org/netdev/net-next/c/f3ce29e169d0
  - [net-next,08/12] net: enetc: move phylink_start/stop out of enetc_start/stop
    https://git.kernel.org/netdev/net-next/c/598ca0d09056
  - [net-next,09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping
    https://git.kernel.org/netdev/net-next/c/5093406c784f
  - [net-next,10/12] net: enetc: rename "xdp" and "dev" in enetc_setup_bpf()
    https://git.kernel.org/netdev/net-next/c/766338c79b10
  - [net-next,11/12] net: enetc: set up XDP program under enetc_reconfigure()
    https://git.kernel.org/netdev/net-next/c/c33bfaf91c4c
  - [net-next,12/12] net: enetc: prioritize ability to go down over packet processing
    https://git.kernel.org/netdev/net-next/c/ff58fda09096

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-01-19  5:12 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-17 23:02 [PATCH net-next 00/12] ENETC BD ring cleanup Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 01/12] net: enetc: set next_to_clean/next_to_use just from enetc_setup_txbdr() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 02/12] net: enetc: set up RX ring indices from enetc_setup_rxbdr() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 03/12] net: enetc: create enetc_dma_free_bdr() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 04/12] net: enetc: rx_swbd and tx_swbd are never NULL in enetc_free_rxtx_rings() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 05/12] net: enetc: drop redundant enetc_free_tx_frame() call from enetc_free_txbdr() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 06/12] net: enetc: bring "bool extended" to top-level in enetc_open() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 07/12] net: enetc: split ring resource allocation from assignment Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 08/12] net: enetc: move phylink_start/stop out of enetc_start/stop Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 09/12] net: enetc: implement ring reconfiguration procedure for PTP RX timestamping Vladimir Oltean
2023-01-18 10:51   ` Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 10/12] net: enetc: rename "xdp" and "dev" in enetc_setup_bpf() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 11/12] net: enetc: set up XDP program under enetc_reconfigure() Vladimir Oltean
2023-01-17 23:02 ` [PATCH net-next 12/12] net: enetc: prioritize ability to go down over packet processing Vladimir Oltean
2023-01-19  5:10 ` [PATCH net-next 00/12] ENETC BD ring cleanup patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.