All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] AF_XDP patches for zero-copy in igc driver
@ 2022-04-20  1:26 jeff.evanson
  2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
  2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
  0 siblings, 2 replies; 7+ messages in thread
From: jeff.evanson @ 2022-04-20  1:26 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, David S. Miller,
	Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
	open list:XDP (eXpress Data Path),
	open list:XDP (eXpress Data Path)
  Cc: Jeff Evanson

From: Jeff Evanson <jeff.evanson@qsc.com>

Patch 1/2
In igc_xdp_xmit_zc, the local variable ntu is initialized from ring->next_to_use 
without holding the __netif_tx_lock. If another thread already held the lock, the 
ntu value is potentially incorrect. Various bad behaviors were observed ranging
from transmit timeouts to an outright hard-lock of the host. The behavior is
corrected by simply initializing ntu while __netif_tx_lock is held.

Patch 2/2
In igc_xsk_wakeup, only the q_vector interrupt for the passed queue_id was
being triggered. This worked fine so long as both the tx and rx queues shared
the same interrupt. If the tx and rx queues use separate interrupts, only
the rx interrupt would be triggered, regardless of whether flags contained
XDP_WAKEUP_TX. This patch changes the behavior so that q_vectors (rxq_vector 
and txq_vector) are looked up from the referenced tx and/or rx queues instead
of from the adapter q_vector array. If only XDP_WAKEUP_RX is set, rxq_vector
is triggered. If only XDP_WAKEUP_TX is set txq_vector is triggered. If both
are set, rxq_vector is triggered and txq_vector is triggered only if it is
not equal to rxq_vector.
The bad behavior here is apparent when packets are queued up to an AF_XDP
socket and then sendmsg is called on the socket. The packets would not be
sent until the q_vector was triggered via some other mechanism (IE
igc_xmit_frame).


Jeff Evanson (2):
  igc: Fix race in igc_xdp_xmit_zc
  igc: Trigger proper interrupts in igc_xsk_wakeup

 drivers/net/ethernet/intel/igc/igc_main.c | 44 +++++++++++++++++------
 1 file changed, 34 insertions(+), 10 deletions(-)

-- 
2.17.1


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

* [PATCH v2 1/2] igc: Fix race in igc_xdp_xmit_zc
  2022-04-20  1:26 [PATCH v2 0/2] AF_XDP patches for zero-copy in igc driver jeff.evanson
@ 2022-04-20  1:26   ` jeff.evanson
  2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
  1 sibling, 0 replies; 7+ messages in thread
From: jeff.evanson @ 2022-04-20  1:26 UTC (permalink / raw)
  To: Jesse Brandeburg, Tony Nguyen, David S. Miller, Jakub Kicinski,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Vedang Patel, Andre Guedes, Maciej Fijalkowski,
	Jithu Joseph, moderated list:INTEL ETHERNET DRIVERS,
	open list:NETWORKING DRIVERS, open list,
	open list:XDP (eXpress Data Path)
  Cc: Jeff Evanson

From: Jeff Evanson <jeff.evanson@qsc.com>

In igc_xdp_xmit_zc, initialize next_to_use while holding the netif_tx_lock
to prevent racing with other users of the tx ring.

Fixes: 9acf59a752d4 (igc: Enable TX via AF_XDP zero-copy)
---
 drivers/net/ethernet/intel/igc/igc_main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 1c00ee310c19..a36a18c84aeb 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2598,7 +2598,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
 	struct netdev_queue *nq = txring_txq(ring);
 	union igc_adv_tx_desc *tx_desc = NULL;
 	int cpu = smp_processor_id();
-	u16 ntu = ring->next_to_use;
+	u16 ntu;
 	struct xdp_desc xdp_desc;
 	u16 budget;
 
@@ -2607,6 +2607,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
 
 	__netif_tx_lock(nq, cpu);
 
+	ntu = ring->next_to_use;
+
 	budget = igc_desc_unused(ring);
 
 	while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
-- 
2.17.1


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

* [Intel-wired-lan] [PATCH v2 1/2] igc: Fix race in igc_xdp_xmit_zc
@ 2022-04-20  1:26   ` jeff.evanson
  0 siblings, 0 replies; 7+ messages in thread
From: jeff.evanson @ 2022-04-20  1:26 UTC (permalink / raw)
  To: intel-wired-lan

From: Jeff Evanson <jeff.evanson@qsc.com>

In igc_xdp_xmit_zc, initialize next_to_use while holding the netif_tx_lock
to prevent racing with other users of the tx ring.

Fixes: 9acf59a752d4 (igc: Enable TX via AF_XDP zero-copy)
---
 drivers/net/ethernet/intel/igc/igc_main.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 1c00ee310c19..a36a18c84aeb 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2598,7 +2598,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
 	struct netdev_queue *nq = txring_txq(ring);
 	union igc_adv_tx_desc *tx_desc = NULL;
 	int cpu = smp_processor_id();
-	u16 ntu = ring->next_to_use;
+	u16 ntu;
 	struct xdp_desc xdp_desc;
 	u16 budget;
 
@@ -2607,6 +2607,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
 
 	__netif_tx_lock(nq, cpu);
 
+	ntu = ring->next_to_use;
+
 	budget = igc_desc_unused(ring);
 
 	while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
-- 
2.17.1


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

* [PATCH v2 2/2] igc: Trigger proper interrupts in igc_xsk_wakeup
  2022-04-20  1:26 [PATCH v2 0/2] AF_XDP patches for zero-copy in igc driver jeff.evanson
@ 2022-04-20  1:26   ` jeff.evanson
  2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
  1 sibling, 0 replies; 7+ messages in thread
From: jeff.evanson @ 2022-04-20  1:26 UTC (permalink / raw)
  To: Jesse Brandeburg, Tony Nguyen, David S. Miller, Jakub Kicinski,
	Vedang Patel, Andre Guedes, Maciej Fijalkowski, Jithu Joseph,
	moderated list:INTEL ETHERNET DRIVERS,
	open list:NETWORKING DRIVERS, open list
  Cc: Jeff Evanson

From: Jeff Evanson <jeff.evanson@qsc.com>

In igc_xsk_wakeup, trigger the proper interrupt based on whether flags
contains XDP_WAKEUP_RX and/or XDP_WAKEUP_TX.

Consider a scenario where the transmit queue interrupt is mapped to a
different irq from the receive queue. If XDP_WAKEUP_TX is set in the
flags argument, the interrupt for transmit queue must be triggered,
otherwise the transmit queue's napi_struct will never be scheduled.

In the case where both XDP_WAKEUP_TX and XDP_WAKEUP_RX are both set,
the receive interrupt should always be triggered, but the transmit
interrupt should only be triggered if its q_vector differs from the
receive queue's interrupt.

Fixes: fc9df2a0b520 ("igc: Enable RX via AF_XDP zero-copy")
---
 drivers/net/ethernet/intel/igc/igc_main.c | 40 ++++++++++++++++++-----
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index a36a18c84aeb..41b5d1ac8bc1 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6072,8 +6072,8 @@ static void igc_trigger_rxtxq_interrupt(struct igc_adapter *adapter,
 
 int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
 {
+	struct igc_q_vector *txq_vector = NULL, *rxq_vector = NULL;
 	struct igc_adapter *adapter = netdev_priv(dev);
-	struct igc_q_vector *q_vector;
 	struct igc_ring *ring;
 
 	if (test_bit(__IGC_DOWN, &adapter->state))
@@ -6082,17 +6082,39 @@ int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
 	if (!igc_xdp_is_enabled(adapter))
 		return -ENXIO;
 
-	if (queue_id >= adapter->num_rx_queues)
-		return -EINVAL;
+	if (flags & XDP_WAKEUP_RX) {
+		if (queue_id >= adapter->num_rx_queues)
+			return -EINVAL;
 
-	ring = adapter->rx_ring[queue_id];
+		ring = adapter->rx_ring[queue_id];
+		if (!ring->xsk_pool)
+			return -ENXIO;
 
-	if (!ring->xsk_pool)
-		return -ENXIO;
+		rxq_vector = ring->q_vector;
+	}
+
+	if (flags & XDP_WAKEUP_TX) {
+		if (queue_id >= adapter->num_tx_queues)
+			return -EINVAL;
+
+		ring = adapter->tx_ring[queue_id];
+		if (!ring->xsk_pool)
+			return -ENXIO;
+
+		txq_vector = ring->q_vector;
+	}
+
+	if (rxq_vector != NULL &&
+	    !napi_if_scheduled_mark_missed(&rxq_vector->napi))
+		igc_trigger_rxtxq_interrupt(adapter, rxq_vector);
 
-	q_vector = adapter->q_vector[queue_id];
-	if (!napi_if_scheduled_mark_missed(&q_vector->napi))
-		igc_trigger_rxtxq_interrupt(adapter, q_vector);
+	/* only trigger tx interrupt if the receive interrupt was not
+	 * triggered or if its irq differs from the receive queue's irq
+	 */
+	if (txq_vector != NULL &&
+            txq_vector != rxq_vector &&
+	    !napi_if_scheduled_mark_missed(&txq_vector->napi))
+		igc_trigger_rxtxq_interrupt(adapter, txq_vector);
 
 	return 0;
 }
-- 
2.17.1


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

* [Intel-wired-lan] [PATCH v2 2/2] igc: Trigger proper interrupts in igc_xsk_wakeup
@ 2022-04-20  1:26   ` jeff.evanson
  0 siblings, 0 replies; 7+ messages in thread
From: jeff.evanson @ 2022-04-20  1:26 UTC (permalink / raw)
  To: intel-wired-lan

From: Jeff Evanson <jeff.evanson@qsc.com>

In igc_xsk_wakeup, trigger the proper interrupt based on whether flags
contains XDP_WAKEUP_RX and/or XDP_WAKEUP_TX.

Consider a scenario where the transmit queue interrupt is mapped to a
different irq from the receive queue. If XDP_WAKEUP_TX is set in the
flags argument, the interrupt for transmit queue must be triggered,
otherwise the transmit queue's napi_struct will never be scheduled.

In the case where both XDP_WAKEUP_TX and XDP_WAKEUP_RX are both set,
the receive interrupt should always be triggered, but the transmit
interrupt should only be triggered if its q_vector differs from the
receive queue's interrupt.

Fixes: fc9df2a0b520 ("igc: Enable RX via AF_XDP zero-copy")
---
 drivers/net/ethernet/intel/igc/igc_main.c | 40 ++++++++++++++++++-----
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index a36a18c84aeb..41b5d1ac8bc1 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -6072,8 +6072,8 @@ static void igc_trigger_rxtxq_interrupt(struct igc_adapter *adapter,
 
 int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
 {
+	struct igc_q_vector *txq_vector = NULL, *rxq_vector = NULL;
 	struct igc_adapter *adapter = netdev_priv(dev);
-	struct igc_q_vector *q_vector;
 	struct igc_ring *ring;
 
 	if (test_bit(__IGC_DOWN, &adapter->state))
@@ -6082,17 +6082,39 @@ int igc_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
 	if (!igc_xdp_is_enabled(adapter))
 		return -ENXIO;
 
-	if (queue_id >= adapter->num_rx_queues)
-		return -EINVAL;
+	if (flags & XDP_WAKEUP_RX) {
+		if (queue_id >= adapter->num_rx_queues)
+			return -EINVAL;
 
-	ring = adapter->rx_ring[queue_id];
+		ring = adapter->rx_ring[queue_id];
+		if (!ring->xsk_pool)
+			return -ENXIO;
 
-	if (!ring->xsk_pool)
-		return -ENXIO;
+		rxq_vector = ring->q_vector;
+	}
+
+	if (flags & XDP_WAKEUP_TX) {
+		if (queue_id >= adapter->num_tx_queues)
+			return -EINVAL;
+
+		ring = adapter->tx_ring[queue_id];
+		if (!ring->xsk_pool)
+			return -ENXIO;
+
+		txq_vector = ring->q_vector;
+	}
+
+	if (rxq_vector != NULL &&
+	    !napi_if_scheduled_mark_missed(&rxq_vector->napi))
+		igc_trigger_rxtxq_interrupt(adapter, rxq_vector);
 
-	q_vector = adapter->q_vector[queue_id];
-	if (!napi_if_scheduled_mark_missed(&q_vector->napi))
-		igc_trigger_rxtxq_interrupt(adapter, q_vector);
+	/* only trigger tx interrupt if the receive interrupt was not
+	 * triggered or if its irq differs from the receive queue's irq
+	 */
+	if (txq_vector != NULL &&
+            txq_vector != rxq_vector &&
+	    !napi_if_scheduled_mark_missed(&txq_vector->napi))
+		igc_trigger_rxtxq_interrupt(adapter, txq_vector);
 
 	return 0;
 }
-- 
2.17.1


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

* Re: [PATCH v2 2/2] igc: Trigger proper interrupts in igc_xsk_wakeup
  2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
@ 2022-04-21 20:23     ` Tony Nguyen
  -1 siblings, 0 replies; 7+ messages in thread
From: Tony Nguyen @ 2022-04-21 20:23 UTC (permalink / raw)
  To: jeff.evanson, Jesse Brandeburg, David S. Miller, Jakub Kicinski,
	Vedang Patel, Andre Guedes, Maciej Fijalkowski, Jithu Joseph,
	moderated list:INTEL ETHERNET DRIVERS,
	open list:NETWORKING DRIVERS, open list
  Cc: Jeff Evanson


On 4/19/2022 6:26 PM, jeff.evanson@gmail.com wrote:
> From: Jeff Evanson <jeff.evanson@qsc.com>
>
> In igc_xsk_wakeup, trigger the proper interrupt based on whether flags
> contains XDP_WAKEUP_RX and/or XDP_WAKEUP_TX.
>
> Consider a scenario where the transmit queue interrupt is mapped to a
> different irq from the receive queue. If XDP_WAKEUP_TX is set in the
> flags argument, the interrupt for transmit queue must be triggered,
> otherwise the transmit queue's napi_struct will never be scheduled.
>
> In the case where both XDP_WAKEUP_TX and XDP_WAKEUP_RX are both set,
> the receive interrupt should always be triggered, but the transmit
> interrupt should only be triggered if its q_vector differs from the
> receive queue's interrupt.
>
> Fixes: fc9df2a0b520 ("igc: Enable RX via AF_XDP zero-copy")

You're missing your sign-off; same for patch 1. Also, there's a handful 
of issues being reported by checkpatch [1]

Thanks,

Tony

[1] 
https://patchwork.kernel.org/project/netdevbpf/patch/20220420012635.13733-3-jeff.evanson@qsc.com/


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

* [Intel-wired-lan] [PATCH v2 2/2] igc: Trigger proper interrupts in igc_xsk_wakeup
@ 2022-04-21 20:23     ` Tony Nguyen
  0 siblings, 0 replies; 7+ messages in thread
From: Tony Nguyen @ 2022-04-21 20:23 UTC (permalink / raw)
  To: intel-wired-lan


On 4/19/2022 6:26 PM, jeff.evanson at gmail.com wrote:
> From: Jeff Evanson <jeff.evanson@qsc.com>
>
> In igc_xsk_wakeup, trigger the proper interrupt based on whether flags
> contains XDP_WAKEUP_RX and/or XDP_WAKEUP_TX.
>
> Consider a scenario where the transmit queue interrupt is mapped to a
> different irq from the receive queue. If XDP_WAKEUP_TX is set in the
> flags argument, the interrupt for transmit queue must be triggered,
> otherwise the transmit queue's napi_struct will never be scheduled.
>
> In the case where both XDP_WAKEUP_TX and XDP_WAKEUP_RX are both set,
> the receive interrupt should always be triggered, but the transmit
> interrupt should only be triggered if its q_vector differs from the
> receive queue's interrupt.
>
> Fixes: fc9df2a0b520 ("igc: Enable RX via AF_XDP zero-copy")

You're missing your sign-off; same for patch 1. Also, there's a handful 
of issues being reported by checkpatch [1]

Thanks,

Tony

[1] 
https://patchwork.kernel.org/project/netdevbpf/patch/20220420012635.13733-3-jeff.evanson at qsc.com/


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

end of thread, other threads:[~2022-04-21 20:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-20  1:26 [PATCH v2 0/2] AF_XDP patches for zero-copy in igc driver jeff.evanson
2022-04-20  1:26 ` [PATCH v2 1/2] igc: Fix race in igc_xdp_xmit_zc jeff.evanson
2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
2022-04-20  1:26 ` [PATCH v2 2/2] igc: Trigger proper interrupts in igc_xsk_wakeup jeff.evanson
2022-04-20  1:26   ` [Intel-wired-lan] " jeff.evanson
2022-04-21 20:23   ` Tony Nguyen
2022-04-21 20:23     ` [Intel-wired-lan] " Tony Nguyen

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.