All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/3] qca_spi: collection of major fixes
@ 2023-11-29  9:52 Stefan Wahren
  2023-11-29  9:52 ` [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes Stefan Wahren
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Stefan Wahren @ 2023-11-29  9:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Lino Sanfilippo, Florian Fainelli, netdev, linux-kernel,
	Stefan Wahren

This series contains a collection of major fixes for the qca_spi driver,
which has been recently discovered.

Changes in V2:
- Address the crashes caused by TX ring changes in a single patch
  instead of two separate ones ( resource allocation rework will
  be send in a separate series ). As suggested by Paolo the kthread
  is parked during ring parameter changes instead changing the device
  state
- As suggested by Paolo keep the ethtool get_ringparam behavior
  and just fix set_ringparam
- improve commit message in patch #2

Stefan Wahren (3):
  qca_debug: Prevent crash on TX ring changes
  qca_debug: Fix ethtool -G iface tx behavior
  qca_spi: Fix reset behavior

 drivers/net/ethernet/qualcomm/qca_debug.c | 25 +++++++++++++++--------
 drivers/net/ethernet/qualcomm/qca_spi.c   | 15 ++++++++++++--
 drivers/net/ethernet/qualcomm/qca_spi.h   |  2 ++
 3 files changed, 32 insertions(+), 10 deletions(-)

--
2.34.1


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

* [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes
  2023-11-29  9:52 [PATCH V2 0/3] qca_spi: collection of major fixes Stefan Wahren
@ 2023-11-29  9:52 ` Stefan Wahren
  2023-12-02  4:47   ` Jakub Kicinski
  2023-11-29  9:52 ` [PATCH V2 2/3] qca_debug: Fix ethtool -G iface tx behavior Stefan Wahren
  2023-11-29  9:52 ` [PATCH V2 3/3] qca_spi: Fix reset behavior Stefan Wahren
  2 siblings, 1 reply; 5+ messages in thread
From: Stefan Wahren @ 2023-11-29  9:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Lino Sanfilippo, Florian Fainelli, netdev, linux-kernel,
	Stefan Wahren

The qca_spi driver stop and restart the SPI kernel thread
(via ndo_stop & ndo_open) in case of TX ring changes. This is
a big issue because it allows userspace to prevent restart of
the SPI kernel thread (via signals). A subsequent change of
TX ring wrongly assume a valid spi_thread pointer which result
in a crash.

So prevent this by stopping the network queue and temporary park
the SPI thread. Because this could happen during transmission
we also need to call qcaspi_flush_tx_ring().

Fixes: 291ab06ecf67 ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/net/ethernet/qualcomm/qca_debug.c | 17 ++++++++++++-----
 drivers/net/ethernet/qualcomm/qca_spi.c   |  7 ++++++-
 drivers/net/ethernet/qualcomm/qca_spi.h   |  2 ++
 3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/qualcomm/qca_debug.c b/drivers/net/ethernet/qualcomm/qca_debug.c
index 6f2fa2a42770..9777dbb17ac2 100644
--- a/drivers/net/ethernet/qualcomm/qca_debug.c
+++ b/drivers/net/ethernet/qualcomm/qca_debug.c
@@ -263,22 +263,29 @@ qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
 		     struct kernel_ethtool_ringparam *kernel_ring,
 		     struct netlink_ext_ack *extack)
 {
-	const struct net_device_ops *ops = dev->netdev_ops;
 	struct qcaspi *qca = netdev_priv(dev);
+	bool queue_active = !netif_queue_stopped(dev);

 	if ((ring->rx_pending) ||
 	    (ring->rx_mini_pending) ||
 	    (ring->rx_jumbo_pending))
 		return -EINVAL;

-	if (netif_running(dev))
-		ops->ndo_stop(dev);
+	if (queue_active)
+		netif_stop_queue(dev);

+	if (qca->spi_thread)
+		kthread_park(qca->spi_thread);
+
+	qcaspi_flush_tx_ring(qca);
 	qca->txr.count = max_t(u32, ring->tx_pending, TX_RING_MIN_LEN);
 	qca->txr.count = min_t(u16, qca->txr.count, TX_RING_MAX_LEN);

-	if (netif_running(dev))
-		ops->ndo_open(dev);
+	if (qca->spi_thread)
+		kthread_unpark(qca->spi_thread);
+
+	if (queue_active)
+		netif_wake_queue(dev);

 	return 0;
 }
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index bec723028e96..78317b85ad30 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -467,7 +467,7 @@ qcaspi_tx_ring_has_space(struct tx_ring *txr)
  *   call from the qcaspi_spi_thread.
  */

-static void
+void
 qcaspi_flush_tx_ring(struct qcaspi *qca)
 {
 	int i;
@@ -580,6 +580,11 @@ qcaspi_spi_thread(void *data)
 	netdev_info(qca->net_dev, "SPI thread created\n");
 	while (!kthread_should_stop()) {
 		set_current_state(TASK_INTERRUPTIBLE);
+		if (kthread_should_park()) {
+			kthread_parkme();
+			continue;
+		}
+
 		if ((qca->intr_req == qca->intr_svc) &&
 		    !qca->txr.skb[qca->txr.head])
 			schedule();
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.h b/drivers/net/ethernet/qualcomm/qca_spi.h
index 3067356106f0..95d7306e58e9 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.h
+++ b/drivers/net/ethernet/qualcomm/qca_spi.h
@@ -107,4 +107,6 @@ struct qcaspi {
 	u16 burst_len;
 };

+void qcaspi_flush_tx_ring(struct qcaspi *qca);
+
 #endif /* _QCA_SPI_H */
--
2.34.1


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

* [PATCH V2 2/3] qca_debug: Fix ethtool -G iface tx behavior
  2023-11-29  9:52 [PATCH V2 0/3] qca_spi: collection of major fixes Stefan Wahren
  2023-11-29  9:52 ` [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes Stefan Wahren
@ 2023-11-29  9:52 ` Stefan Wahren
  2023-11-29  9:52 ` [PATCH V2 3/3] qca_spi: Fix reset behavior Stefan Wahren
  2 siblings, 0 replies; 5+ messages in thread
From: Stefan Wahren @ 2023-11-29  9:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Lino Sanfilippo, Florian Fainelli, netdev, linux-kernel,
	Stefan Wahren

After calling ethtool -g it was not possible to adjust the TX ring
size again:

  # ethtool -g eth1
  Ring parameters for eth1:
  Pre-set maximums:
  RX:		4
  RX Mini:	n/a
  RX Jumbo:	n/a
  TX:		10
  Current hardware settings:
  RX:		4
  RX Mini:	n/a
  RX Jumbo:	n/a
  TX:		10
  # ethtool -G eth1 tx 8
  netlink error: Invalid argument

The reason for this is that the readonly setting rx_pending get
initialized and after that the range check in qcaspi_set_ringparam()
fails regardless of the provided parameter. So fix this by accepting
the exposed RX defaults. Instead of adding another magic number
better use a new define here.

Fixes: 291ab06ecf67 ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/net/ethernet/qualcomm/qca_debug.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/qualcomm/qca_debug.c b/drivers/net/ethernet/qualcomm/qca_debug.c
index 9777dbb17ac2..c84a1271857e 100644
--- a/drivers/net/ethernet/qualcomm/qca_debug.c
+++ b/drivers/net/ethernet/qualcomm/qca_debug.c
@@ -30,6 +30,8 @@

 #define QCASPI_MAX_REGS 0x20

+#define QCASPI_RX_MAX_FRAMES 4
+
 static const u16 qcaspi_spi_regs[] = {
 	SPI_REG_BFR_SIZE,
 	SPI_REG_WRBUF_SPC_AVA,
@@ -252,9 +254,9 @@ qcaspi_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
 {
 	struct qcaspi *qca = netdev_priv(dev);

-	ring->rx_max_pending = 4;
+	ring->rx_max_pending = QCASPI_RX_MAX_FRAMES;
 	ring->tx_max_pending = TX_RING_MAX_LEN;
-	ring->rx_pending = 4;
+	ring->rx_pending = QCASPI_RX_MAX_FRAMES;
 	ring->tx_pending = qca->txr.count;
 }

@@ -266,7 +268,7 @@ qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
 	struct qcaspi *qca = netdev_priv(dev);
 	bool queue_active = !netif_queue_stopped(dev);

-	if ((ring->rx_pending) ||
+	if (ring->rx_pending != QCASPI_RX_MAX_FRAMES ||
 	    (ring->rx_mini_pending) ||
 	    (ring->rx_jumbo_pending))
 		return -EINVAL;
--
2.34.1


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

* [PATCH V2 3/3] qca_spi: Fix reset behavior
  2023-11-29  9:52 [PATCH V2 0/3] qca_spi: collection of major fixes Stefan Wahren
  2023-11-29  9:52 ` [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes Stefan Wahren
  2023-11-29  9:52 ` [PATCH V2 2/3] qca_debug: Fix ethtool -G iface tx behavior Stefan Wahren
@ 2023-11-29  9:52 ` Stefan Wahren
  2 siblings, 0 replies; 5+ messages in thread
From: Stefan Wahren @ 2023-11-29  9:52 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
  Cc: Lino Sanfilippo, Florian Fainelli, netdev, linux-kernel,
	Stefan Wahren

In case of a reset triggered by the QCA7000 itself, the behavior of the
qca_spi driver was not quite correct:
- in case of a pending RX frame decoding the drop counter must be
  incremented and decoding state machine reseted
- also the reset counter must always be incremented regardless of sync
  state

Fixes: 291ab06ecf67 ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
Signed-off-by: Stefan Wahren <wahrenst@gmx.net>
---
 drivers/net/ethernet/qualcomm/qca_spi.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index 78317b85ad30..0fe2e24a42b2 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -613,11 +613,17 @@ qcaspi_spi_thread(void *data)
 			if (intr_cause & SPI_INT_CPU_ON) {
 				qcaspi_qca7k_sync(qca, QCASPI_EVENT_CPUON);

+				/* Frame decoding in progress */
+				if (qca->frm_handle.state != qca->frm_handle.init)
+					qca->net_dev->stats.rx_dropped++;
+
+				qcafrm_fsm_init_spi(&qca->frm_handle);
+				qca->stats.device_reset++;
+
 				/* not synced. */
 				if (qca->sync != QCASPI_SYNC_READY)
 					continue;

-				qca->stats.device_reset++;
 				netif_wake_queue(qca->net_dev);
 				netif_carrier_on(qca->net_dev);
 			}
--
2.34.1


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

* Re: [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes
  2023-11-29  9:52 ` [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes Stefan Wahren
@ 2023-12-02  4:47   ` Jakub Kicinski
  0 siblings, 0 replies; 5+ messages in thread
From: Jakub Kicinski @ 2023-12-02  4:47 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: David S. Miller, Eric Dumazet, Paolo Abeni, Lino Sanfilippo,
	Florian Fainelli, netdev, linux-kernel

On Wed, 29 Nov 2023 10:52:39 +0100 Stefan Wahren wrote:
> The qca_spi driver stop and restart the SPI kernel thread
> (via ndo_stop & ndo_open) in case of TX ring changes. This is
> a big issue because it allows userspace to prevent restart of
> the SPI kernel thread (via signals). A subsequent change of
> TX ring wrongly assume a valid spi_thread pointer which result
> in a crash.
> 
> So prevent this by stopping the network queue and temporary park
> the SPI thread. Because this could happen during transmission
> we also need to call qcaspi_flush_tx_ring().
> 
> Fixes: 291ab06ecf67 ("net: qualcomm: new Ethernet over SPI driver for QCA7000")
> Signed-off-by: Stefan Wahren <wahrenst@gmx.net>

Still looks a bit racy.

> diff --git a/drivers/net/ethernet/qualcomm/qca_debug.c b/drivers/net/ethernet/qualcomm/qca_debug.c
> index 6f2fa2a42770..9777dbb17ac2 100644
> --- a/drivers/net/ethernet/qualcomm/qca_debug.c
> +++ b/drivers/net/ethernet/qualcomm/qca_debug.c
> @@ -263,22 +263,29 @@ qcaspi_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ring,
>  		     struct kernel_ethtool_ringparam *kernel_ring,
>  		     struct netlink_ext_ack *extack)
>  {
> -	const struct net_device_ops *ops = dev->netdev_ops;
>  	struct qcaspi *qca = netdev_priv(dev);
> +	bool queue_active = !netif_queue_stopped(dev);

nothing prevents stopped -> running or running -> stopped
transitions at this point, so this check can be meaningful

>  	if ((ring->rx_pending) ||
>  	    (ring->rx_mini_pending) ||
>  	    (ring->rx_jumbo_pending))
>  		return -EINVAL;
> 
> -	if (netif_running(dev))
> -		ops->ndo_stop(dev);
> +	if (queue_active)
> +		netif_stop_queue(dev);

This doesn't wait for xmit to finish, it just sets a bit.
You probably want something like netif_tx_disable().

Also - the thread may still be running and wake the queue up right after
we stop it.
-- 
pw-bot: cr

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

end of thread, other threads:[~2023-12-02  4:52 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-29  9:52 [PATCH V2 0/3] qca_spi: collection of major fixes Stefan Wahren
2023-11-29  9:52 ` [PATCH V2 1/3] qca_debug: Prevent crash on TX ring changes Stefan Wahren
2023-12-02  4:47   ` Jakub Kicinski
2023-11-29  9:52 ` [PATCH V2 2/3] qca_debug: Fix ethtool -G iface tx behavior Stefan Wahren
2023-11-29  9:52 ` [PATCH V2 3/3] qca_spi: Fix reset behavior Stefan Wahren

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.