Intel-Wired-Lan Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
To: "Behera, VIVEK" <vivek.behera@siemens.com>
Cc: "aleksandr.loktionov@intel.com" <aleksandr.loktionov@intel.com>,
	"jacob.e.keller@intel.com" <jacob.e.keller@intel.com>,
	"anthony.l.nguyen@intel.com" <anthony.l.nguyen@intel.com>,
	"przemyslaw.kitszel@intel.com" <przemyslaw.kitszel@intel.com>,
	"sriram.yagnaraman@ericsson.com" <sriram.yagnaraman@ericsson.com>,
	"kurt@linutronix.de" <kurt@linutronix.de>,
	"intel-wired-lan@lists.osuosl.org"
	<intel-wired-lan@lists.osuosl.org>,
	"magnus.karlsson@intel.com" <magnus.karlsson@intel.com>
Subject: Re: [Intel-wired-lan] [PATCH iwl-net v5] igb: Fix trigger of incorrect irq in igb_xsk_wakeup
Date: Wed, 14 Jan 2026 19:20:42 +0100	[thread overview]
Message-ID: <aWfeeu8r38dti0n8@boxer> (raw)
In-Reply-To: <AS1PR10MB53927D6755EA818A29A8B0EE8F8FA@AS1PR10MB5392.EURPRD10.PROD.OUTLOOK.COM>

On Wed, Jan 14, 2026 at 08:19:37AM +0000, Behera, VIVEK wrote:

(...)

> > >
> > > diff --git a/drivers/net/ethernet/intel/igb/e1000_defines.h
> > > b/drivers/net/ethernet/intel/igb/e1000_defines.h
> > > index fa028928482f..9357564a2d58 100644
> > > --- a/drivers/net/ethernet/intel/igb/e1000_defines.h
> > > +++ b/drivers/net/ethernet/intel/igb/e1000_defines.h
> > > @@ -443,6 +443,7 @@
> > >  #define E1000_ICS_LSC       E1000_ICR_LSC       /* Link Status Change */
> > >  #define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold
> > */
> > >  #define E1000_ICS_DRSTA     E1000_ICR_DRSTA     /* Device Reset Aserted */
> > > +#define E1000_ICS_TXDW      E1000_ICR_TXDW	/* Transmit desc written
> > back */
> > >
> > >  /* Extended Interrupt Cause Set */
> > >  /* E1000_EITR_CNT_IGNR is only for 82576 and newer */ diff --git
> > > a/drivers/net/ethernet/intel/igb/igb_xsk.c
> > > b/drivers/net/ethernet/intel/igb/igb_xsk.c
> > > index 30ce5fbb5b77..6e51b5b6f131 100644
> > > --- a/drivers/net/ethernet/intel/igb/igb_xsk.c
> > > +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
> > > @@ -529,6 +529,13 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32
> > flags)
> > >  	struct igb_adapter *adapter = netdev_priv(dev);
> > >  	struct e1000_hw *hw = &adapter->hw;
> > >  	struct igb_ring *ring;
> > > +	struct igb_q_vector *q_vector;
> > > +	struct napi_struct *rx_napi;
> > > +	struct napi_struct *tx_napi;
> > > +	bool trigger_irq_tx = false;
> > > +	bool trigger_irq_rx = false;
> > > +	u32 eics_tx = 0;
> > > +	u32 eics_rx = 0;
> > >  	u32 eics = 0;
> > >
> > >  	if (test_bit(__IGB_DOWN, &adapter->state)) @@ -536,27 +543,65 @@ int
> > > igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
> > >
> > >  	if (!igb_xdp_is_enabled(adapter))
> > >  		return -EINVAL;
> > > -
> > > -	if (qid >= adapter->num_tx_queues)
> > > +	/* Check if queue_id is valid. Tx and Rx queue numbers are always same */
> > > +	if (qid >= adapter->num_rx_queues)
> > >  		return -EINVAL;
> > > -
> > > -	ring = adapter->tx_ring[qid];
> > > -
> > > -	if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> > > -		return -ENETDOWN;
> > > -
> > > -	if (!READ_ONCE(ring->xsk_pool))
> > > +	/* Check if flags are valid */
> > > +	if (!(flags & XDP_WAKEUP_RX) && !(flags & XDP_WAKEUP_TX))
> > >  		return -EINVAL;
> > > -
> > > -	if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
> > > -		/* Cause software interrupt */
> > > +	if (flags & XDP_WAKEUP_RX) {
> > > +		/* IRQ trigger preparation for Rx */
> > > +		ring = adapter->rx_ring[qid];
> > > +		if (!READ_ONCE(ring->xsk_pool))
> > > +			return -ENXIO;
> > > +		q_vector = ring->q_vector;
> > > +		rx_napi = &q_vector->napi;
> > > +		/* Extend the BIT mask for eics */
> > > +		eics_rx = ring->q_vector->eims_value;
> > > +		trigger_irq_rx = true;
> > > +	}
> > > +	if (flags & XDP_WAKEUP_TX) {
> > > +		if (adapter->flags & IGB_FLAG_QUEUE_PAIRS) {
> > > +		/* In queue-pair mode, rx_ring and tx_ring share the same q_vector,
> > > +		 * so a single IRQ trigger will wake both RX and TX processing
> > > +		 */
> > > +		} else {
> > > +			/* IRQ trigger preparation for Tx */
> > > +			ring = adapter->tx_ring[qid];
> > > +			if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
> > > +				return -ENETDOWN;
> > > +
> > > +			if (!READ_ONCE(ring->xsk_pool))
> > > +				return -ENXIO;
> > > +			q_vector = ring->q_vector;
> > > +			tx_napi = &q_vector->napi;
> > > +			/* Extend the BIT mask for eics */
> > > +			eics_tx = ring->q_vector->eims_value;
> > > +			trigger_irq_tx = true;
> > > +		}
> > > +	}
> > > +	/* All error checks are finished. Check and update napi states for rx and tx */
> > > +	if (trigger_irq_rx) {
> > > +		if (!napi_if_scheduled_mark_missed(rx_napi))
> > > +			eics |= eics_rx;
> > > +	}
> > > +	if (trigger_irq_tx) {
> > > +		if (!napi_if_scheduled_mark_missed(tx_napi))
> > > +			eics |= eics_tx;
> > > +	}
> > > +	/* Now we trigger the required irqs for Rx and Tx */
> > > +	if ((trigger_irq_rx) || (trigger_irq_tx)) {
> > >  		if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> > > -			eics |= ring->q_vector->eims_value;
> > >  			wr32(E1000_EICS, eics);
> > >  		} else {
> > > -			wr32(E1000_ICS, E1000_ICS_RXDMT0);
> > > +			if ((trigger_irq_rx) && (trigger_irq_tx))
> > > +				wr32(E1000_ICS,
> > > +				     E1000_ICS_RXDMT0 | E1000_ICS_TXDW);
> > > +			else if (trigger_irq_rx)
> > > +				wr32(E1000_ICS, E1000_ICS_RXDMT0);
> > > +			else
> > > +				wr32(E1000_ICS, E1000_ICS_TXDW);
> > 
> > My understanding is something below would be sufficient. Bits set on E1000_ICS are
> > not handled in any way so we don't have to distinguish between rx/tx, it's just the
> > matter of irq trigger and napi schedule.
> > 
> Hi see my comments below
> > -----------------8<-----------------
> > 
> > diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c
> > b/drivers/net/ethernet/intel/igb/igb_xsk.c
> > index 30ce5fbb5b77..0aba7afd6a03 100644
> > --- a/drivers/net/ethernet/intel/igb/igb_xsk.c
> > +++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
> > @@ -524,12 +524,26 @@ bool igb_xmit_zc(struct igb_ring *tx_ring, struct
> > xsk_buff_pool *xsk_pool)
> >  	return nb_pkts < budget;
> >  }
> > 
> > +static void igb_sw_irq(struct igb_q_vector *q_vector) {
> > +	u32 eics = 0;
> > +
> > +	if (!napi_if_scheduled_mark_missed(&q_vector->napi)) {
> > +		/* Cause software interrupt */
> > +		if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> > +			eics |= ring->q_vector->eims_value;
> > +			wr32(E1000_EICS, eics);
> > +		} else {
> > +			wr32(E1000_ICS, E1000_ICS_RXDMT0);
> So here it is sufficient to rely on the E1000_ICS_RXDMT0 bit to trigger the correct irq (Tx and Rx)?
>  I remember I received a review comment from Intel point to E1000_ICS_TXDW as being the correct bit of triggering TX for non MSIX case. 
> I can't really evaluate this since I don't have a setup to test this. But okay 

I don't see in irq handlers that we do any specific handling for txdw vs
rxdmt0. It's rather a matter of getting an irq here.

> > +		}
> > +	}
> > +}
> > +
> >  int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)  {
> >  	struct igb_adapter *adapter = netdev_priv(dev);
> >  	struct e1000_hw *hw = &adapter->hw;
> >  	struct igb_ring *ring;
> > -	u32 eics = 0;
> > 
> >  	if (test_bit(__IGB_DOWN, &adapter->state))
> >  		return -ENETDOWN;
> > @@ -548,14 +562,15 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32
> > flags)
> >  	if (!READ_ONCE(ring->xsk_pool))
> >  		return -EINVAL;
> > 
> > -	if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
> > -		/* Cause software interrupt */
> > -		if (adapter->flags & IGB_FLAG_HAS_MSIX) {
> > -			eics |= ring->q_vector->eims_value;
> > -			wr32(E1000_EICS, eics);
> > -		} else {
> > -			wr32(E1000_ICS, E1000_ICS_RXDMT0);
> > -		}
> > +	if (flags & XDP_WAKEUP_TX)
> > +		igb_sw_irq(ring->q_vector);
> > +
> > +	if (flags & XDP_WAKEUP_RX) {
> > +		ring = adapter->rx_ring[qid];
> > +		/* for !IGB_FLAG_QUEUE_PAIRS, this will be NOP as NAPI has
> > +		 * been already marked with NAPIF_STATE_MISSED
> > +		 */
> I think you meant for the case IGB_FLAG_QUEUE_PAIRS. Since when the queue pairs are not active 
> the Tx AND Rx queues don't share the same qvector and consequently not the same NAPI

yes, correct

> > +		igb_sw_irq(ring->q_vector);
> Okay so you would be triggering soft irq's in two steps if both TX and RX flags are set. 
> Honestly, I have tried to avoid doing this in my patch.  Which is the reason why I wait to finish all the error checks,
> Napi updates before triggering the required irq vectors by writing to eics with a single write. 
> But okay the other approach also works 



>  
> >  	}
> > 
> >  	return 0;
> > 
> > ----------------->8-----------------
> > 
> > >  		}
> > >  	}
> > > -
> > >  	return 0;
> > >  }
> > > --
> > > 2.34.1
> > >
> I think the strategy of triggering interrupts in one step after performing all the necessary checks is what might make this approach look complex. 
> IMHO the one step strategy is better and more intuitive.
> Unfortunately, there isn't a reference here to go by since none of the xsk_wakeup hooks implemented in the kernel care about the flags 
> I can submit a v6 of the patch based the one step approach with further simplifications. v6 would also include review suggestions I received for v5. 
> Like this I can also submit the next version to the igc patch. It follows the same logic as the igb 
> I have our regression tests with RTC testbench and our Siemens Profinet RT tester running with these patches with I210 and I226
> 
> Alternatively, you could submit patches following the igb and igc following the two-step logic. 

How about we meet the half way and something below? that would include
your request of having a single write to E1000_ICS.


diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c
index 30ce5fbb5b77..432b4c7c1850 100644
--- a/drivers/net/ethernet/intel/igb/igb_xsk.c
+++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
@@ -524,6 +524,17 @@ bool igb_xmit_zc(struct igb_ring *tx_ring, struct xsk_buff_pool *xsk_pool)
 	return nb_pkts < budget;
 }
 
+static u32 igb_sw_irq_prep(struct igb_q_vector *q_vector)
+{
+	u32 eics = 0;
+
+	if (!napi_if_scheduled_mark_missed(&q_vector->napi))
+		eics = adapter->flags & IGB_FLAG_HAS_MSIX ?
+			q_vector->eims_value : 1;
+
+	return eics;
+}
+
 int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
 {
 	struct igb_adapter *adapter = netdev_priv(dev);
@@ -548,14 +559,23 @@ int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
 	if (!READ_ONCE(ring->xsk_pool))
 		return -EINVAL;
 
-	if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
-		/* Cause software interrupt */
-		if (adapter->flags & IGB_FLAG_HAS_MSIX) {
-			eics |= ring->q_vector->eims_value;
+	if (flags & XDP_WAKEUP_TX)
+		eics |= igb_sw_irq_prep(ring->q_vector);
+
+	if (flags & XDP_WAKEUP_RX) {
+		ring = adapter->rx_ring[qid];
+		/* for IGB_FLAG_QUEUE_PAIRS, this will be NOP as NAPI has
+		 * been already marked with NAPIF_STATE_MISSED
+		 */
+		eics |= igb_sw_irq_prep(ring->q_vector);
+	}
+
+	/* Cause software interrupt */
+	if (eics) {
+		if (adapter->flags & IGB_FLAG_HAS_MSIX)
 			wr32(E1000_EICS, eics);
-		} else {
+		else
 			wr32(E1000_ICS, E1000_ICS_RXDMT0);
-		}
 	}
 
 	return 0;

> 
> Regards
> 
> Vivek    

  reply	other threads:[~2026-01-14 18:28 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-12 13:03 [Intel-wired-lan] [PATCH iwl-net v5] igb: Fix trigger of incorrect irq in igb_xsk_wakeup Vivek Behera via Intel-wired-lan
2026-01-12 14:11 ` Paul Menzel
2026-01-13  6:58   ` Behera, VIVEK via Intel-wired-lan
2026-01-12 14:53 ` Kwapulinski, Piotr
2026-01-13  6:55   ` Behera, VIVEK via Intel-wired-lan
2026-01-13  4:04 ` Behera, VIVEK via Intel-wired-lan
2026-01-13  9:00 ` Loktionov, Aleksandr
2026-01-13 10:02   ` Behera, VIVEK via Intel-wired-lan
2026-01-13 11:41 ` Maciej Fijalkowski
2026-01-14  8:19   ` Behera, VIVEK via Intel-wired-lan
2026-01-14 18:20     ` Maciej Fijalkowski [this message]
2026-01-15 11:05       ` Behera, VIVEK via Intel-wired-lan
2026-01-15 19:53         ` Maciej Fijalkowski
2026-01-16 11:44           ` Behera, VIVEK via Intel-wired-lan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aWfeeu8r38dti0n8@boxer \
    --to=maciej.fijalkowski@intel.com \
    --cc=aleksandr.loktionov@intel.com \
    --cc=anthony.l.nguyen@intel.com \
    --cc=intel-wired-lan@lists.osuosl.org \
    --cc=jacob.e.keller@intel.com \
    --cc=kurt@linutronix.de \
    --cc=magnus.karlsson@intel.com \
    --cc=przemyslaw.kitszel@intel.com \
    --cc=sriram.yagnaraman@ericsson.com \
    --cc=vivek.behera@siemens.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox