diff mbox series

[v2,net-next,3/5] ionic: use per-queue xdp_prog

Message ID 20240826184422.21895-4-brett.creeley@amd.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series ionic: convert Rx queue buffers to use page_pool | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 7 this patch: 7
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 5 maintainers not CCed: bpf@vger.kernel.org ast@kernel.org hawk@kernel.org daniel@iogearbox.net john.fastabend@gmail.com
netdev/build_clang success Errors and warnings before: 16 this patch: 16
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 16 this patch: 16
netdev/checkpatch warning WARNING: line length of 82 exceeds 80 columns WARNING: line length of 87 exceeds 80 columns
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-08-27--03-00 (tests: 713)

Commit Message

Brett Creeley Aug. 26, 2024, 6:44 p.m. UTC
From: Shannon Nelson <shannon.nelson@amd.com>

We originally were using a per-interface xdp_prog variable to track
a loaded XDP program since we knew there would never be support for a
per-queue XDP program.  With that, we only built the per queue rxq_info
struct when an XDP program was loaded and removed it on XDP program unload,
and used the pointer as an indicator in the Rx hotpath to know to how build
the buffers.  However, that's really not the model generally used, and
makes a conversion to page_pool Rx buffer cacheing a little problematic.

This patch converts the driver to use the more common approach of using
a per-queue xdp_prog pointer to work out buffer allocations and need
for bpf_prog_run_xdp().  We jostle a couple of fields in the queue struct
in order to keep the new xdp_prog pointer in a warm cacheline.

Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
Signed-off-by: Brett Creeley <brett.creeley@amd.com>
---
 .../net/ethernet/pensando/ionic/ionic_dev.h   |  7 +++++--
 .../net/ethernet/pensando/ionic/ionic_lif.c   | 14 +++++++------
 .../net/ethernet/pensando/ionic/ionic_txrx.c  | 21 +++++++++----------
 3 files changed, 23 insertions(+), 19 deletions(-)

Comments

Larysa Zaremba Aug. 27, 2024, 11:44 a.m. UTC | #1
On Mon, Aug 26, 2024 at 11:44:20AM -0700, Brett Creeley wrote:
> From: Shannon Nelson <shannon.nelson@amd.com>
> 
> We originally were using a per-interface xdp_prog variable to track
> a loaded XDP program since we knew there would never be support for a
> per-queue XDP program.  With that, we only built the per queue rxq_info
> struct when an XDP program was loaded and removed it on XDP program unload,
> and used the pointer as an indicator in the Rx hotpath to know to how build
> the buffers.  However, that's really not the model generally used, and
> makes a conversion to page_pool Rx buffer cacheing a little problematic.
> 
> This patch converts the driver to use the more common approach of using
> a per-queue xdp_prog pointer to work out buffer allocations and need
> for bpf_prog_run_xdp().  We jostle a couple of fields in the queue struct
> in order to keep the new xdp_prog pointer in a warm cacheline.
> 
> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
> Signed-off-by: Brett Creeley <brett.creeley@amd.com>

Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>

If you happen to send another version, please include in a commit message a note 
about READ_ONCE() removal. The removal itself is OK, but an indication that this 
was intentional would be nice.

> ---
>  .../net/ethernet/pensando/ionic/ionic_dev.h   |  7 +++++--
>  .../net/ethernet/pensando/ionic/ionic_lif.c   | 14 +++++++------
>  .../net/ethernet/pensando/ionic/ionic_txrx.c  | 21 +++++++++----------
>  3 files changed, 23 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
> index c647033f3ad2..19ae68a86a0b 100644
> --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
> +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
> @@ -238,9 +238,8 @@ struct ionic_queue {
>  	unsigned int index;
>  	unsigned int num_descs;
>  	unsigned int max_sg_elems;
> +
>  	u64 features;
> -	unsigned int type;
> -	unsigned int hw_index;
>  	unsigned int hw_type;
>  	bool xdp_flush;
>  	union {
> @@ -261,7 +260,11 @@ struct ionic_queue {
>  		struct ionic_rxq_sg_desc *rxq_sgl;
>  	};
>  	struct xdp_rxq_info *xdp_rxq_info;
> +	struct bpf_prog *xdp_prog;
>  	struct ionic_queue *partner;
> +
> +	unsigned int type;
> +	unsigned int hw_index;
>  	dma_addr_t base_pa;
>  	dma_addr_t cmb_base_pa;
>  	dma_addr_t sg_base_pa;
> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
> index aa0cc31dfe6e..0fba2df33915 100644
> --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
> +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
> @@ -2700,24 +2700,24 @@ static int ionic_xdp_register_rxq_info(struct ionic_queue *q, unsigned int napi_
>  
>  static int ionic_xdp_queues_config(struct ionic_lif *lif)
>  {
> +	struct bpf_prog *xdp_prog;
>  	unsigned int i;
>  	int err;
>  
>  	if (!lif->rxqcqs)
>  		return 0;
>  
> -	/* There's no need to rework memory if not going to/from NULL program.
> -	 * If there is no lif->xdp_prog, there should also be no q.xdp_rxq_info
> -	 * This way we don't need to keep an *xdp_prog in every queue struct.
> -	 */
> -	if (!lif->xdp_prog == !lif->rxqcqs[0]->q.xdp_rxq_info)
> +	/* There's no need to rework memory if not going to/from NULL program.  */
> +	xdp_prog = READ_ONCE(lif->xdp_prog);
> +	if (!xdp_prog == !lif->rxqcqs[0]->q.xdp_prog)
>  		return 0;
>  
>  	for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
>  		struct ionic_queue *q = &lif->rxqcqs[i]->q;
>  
> -		if (q->xdp_rxq_info) {
> +		if (q->xdp_prog) {
>  			ionic_xdp_unregister_rxq_info(q);
> +			q->xdp_prog = NULL;
>  			continue;
>  		}
>  
> @@ -2727,6 +2727,7 @@ static int ionic_xdp_queues_config(struct ionic_lif *lif)
>  				i, err);
>  			goto err_out;
>  		}
> +		q->xdp_prog = xdp_prog;
>  	}
>  
>  	return 0;
> @@ -2878,6 +2879,7 @@ static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
>  	swap(a->q.base,       b->q.base);
>  	swap(a->q.base_pa,    b->q.base_pa);
>  	swap(a->q.info,       b->q.info);
> +	swap(a->q.xdp_prog,   b->q.xdp_prog);
>  	swap(a->q.xdp_rxq_info, b->q.xdp_rxq_info);
>  	swap(a->q.partner,    b->q.partner);
>  	swap(a->q_base,       b->q_base);
> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
> index d62b2b60b133..858ab4fd9218 100644
> --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
> +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
> @@ -190,7 +190,7 @@ static bool ionic_rx_buf_recycle(struct ionic_queue *q,
>  	if (page_to_nid(buf_info->page) != numa_mem_id())
>  		return false;
>  
> -	size = ALIGN(len, q->xdp_rxq_info ? IONIC_PAGE_SIZE : IONIC_PAGE_SPLIT_SZ);
> +	size = ALIGN(len, q->xdp_prog ? IONIC_PAGE_SIZE : IONIC_PAGE_SPLIT_SZ);
>  	buf_info->page_offset += size;
>  	if (buf_info->page_offset >= IONIC_PAGE_SIZE)
>  		return false;
> @@ -639,8 +639,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
>  	struct net_device *netdev = q->lif->netdev;
>  	struct ionic_qcq *qcq = q_to_qcq(q);
>  	struct ionic_rx_stats *stats;
> -	struct bpf_prog *xdp_prog;
> -	unsigned int headroom;
> +	unsigned int headroom = 0;
>  	struct sk_buff *skb;
>  	bool synced = false;
>  	bool use_copybreak;
> @@ -664,14 +663,13 @@ static void ionic_rx_clean(struct ionic_queue *q,
>  	stats->pkts++;
>  	stats->bytes += len;
>  
> -	xdp_prog = READ_ONCE(q->lif->xdp_prog);
> -	if (xdp_prog) {
> -		if (ionic_run_xdp(stats, netdev, xdp_prog, q, desc_info->bufs, len))
> +	if (q->xdp_prog) {
> +		if (ionic_run_xdp(stats, netdev, q->xdp_prog, q, desc_info->bufs, len))
>  			return;
>  		synced = true;
> +		headroom = XDP_PACKET_HEADROOM;
>  	}
>  
> -	headroom = q->xdp_rxq_info ? XDP_PACKET_HEADROOM : 0;
>  	use_copybreak = len <= q->lif->rx_copybreak;
>  	if (use_copybreak)
>  		skb = ionic_rx_copybreak(netdev, q, desc_info,
> @@ -814,7 +812,7 @@ void ionic_rx_fill(struct ionic_queue *q)
>  	len = netdev->mtu + VLAN_ETH_HLEN;
>  
>  	for (i = n_fill; i; i--) {
> -		unsigned int headroom;
> +		unsigned int headroom = 0;
>  		unsigned int buf_len;
>  
>  		nfrags = 0;
> @@ -835,11 +833,12 @@ void ionic_rx_fill(struct ionic_queue *q)
>  		 * XDP uses space in the first buffer, so account for
>  		 * head room, tail room, and ip header in the first frag size.
>  		 */
> -		headroom = q->xdp_rxq_info ? XDP_PACKET_HEADROOM : 0;
> -		if (q->xdp_rxq_info)
> +		if (q->xdp_prog) {
>  			buf_len = IONIC_XDP_MAX_LINEAR_MTU + VLAN_ETH_HLEN;
> -		else
> +			headroom = XDP_PACKET_HEADROOM;
> +		} else {
>  			buf_len = ionic_rx_buf_size(buf_info);
> +		}
>  		frag_len = min_t(u16, len, buf_len);
>  
>  		desc->addr = cpu_to_le64(ionic_rx_buf_pa(buf_info) + headroom);
> -- 
> 2.17.1
> 
>
Larysa Zaremba Aug. 27, 2024, 11:57 a.m. UTC | #2
On Tue, Aug 27, 2024 at 01:44:10PM +0200, Larysa Zaremba wrote:
> On Mon, Aug 26, 2024 at 11:44:20AM -0700, Brett Creeley wrote:
> > From: Shannon Nelson <shannon.nelson@amd.com>
> > 
> > We originally were using a per-interface xdp_prog variable to track
> > a loaded XDP program since we knew there would never be support for a
> > per-queue XDP program.  With that, we only built the per queue rxq_info
> > struct when an XDP program was loaded and removed it on XDP program unload,
> > and used the pointer as an indicator in the Rx hotpath to know to how build
> > the buffers.  However, that's really not the model generally used, and
> > makes a conversion to page_pool Rx buffer cacheing a little problematic.
> > 
> > This patch converts the driver to use the more common approach of using
> > a per-queue xdp_prog pointer to work out buffer allocations and need
> > for bpf_prog_run_xdp().  We jostle a couple of fields in the queue struct
> > in order to keep the new xdp_prog pointer in a warm cacheline.
> > 
> > Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
> > Signed-off-by: Brett Creeley <brett.creeley@amd.com>
> 
> Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
>

I would like to rewoke the tag, see below why.

> If you happen to send another version, please include in a commit message a note 
> about READ_ONCE() removal. The removal itself is OK, but an indication that this 
> was intentional would be nice.
> 
> > ---
> >  .../net/ethernet/pensando/ionic/ionic_dev.h   |  7 +++++--
> >  .../net/ethernet/pensando/ionic/ionic_lif.c   | 14 +++++++------
> >  .../net/ethernet/pensando/ionic/ionic_txrx.c  | 21 +++++++++----------
> >  3 files changed, 23 insertions(+), 19 deletions(-)
> > 
> > diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
> > index c647033f3ad2..19ae68a86a0b 100644
> > --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
> > +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
> > @@ -238,9 +238,8 @@ struct ionic_queue {
> >  	unsigned int index;
> >  	unsigned int num_descs;
> >  	unsigned int max_sg_elems;
> > +
> >  	u64 features;
> > -	unsigned int type;
> > -	unsigned int hw_index;
> >  	unsigned int hw_type;
> >  	bool xdp_flush;
> >  	union {
> > @@ -261,7 +260,11 @@ struct ionic_queue {
> >  		struct ionic_rxq_sg_desc *rxq_sgl;
> >  	};
> >  	struct xdp_rxq_info *xdp_rxq_info;
> > +	struct bpf_prog *xdp_prog;
> >  	struct ionic_queue *partner;
> > +
> > +	unsigned int type;
> > +	unsigned int hw_index;
> >  	dma_addr_t base_pa;
> >  	dma_addr_t cmb_base_pa;
> >  	dma_addr_t sg_base_pa;
> > diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
> > index aa0cc31dfe6e..0fba2df33915 100644
> > --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
> > +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
> > @@ -2700,24 +2700,24 @@ static int ionic_xdp_register_rxq_info(struct ionic_queue *q, unsigned int napi_
> >  
> >  static int ionic_xdp_queues_config(struct ionic_lif *lif)
> >  {
> > +	struct bpf_prog *xdp_prog;
> >  	unsigned int i;
> >  	int err;
> >  
> >  	if (!lif->rxqcqs)
> >  		return 0;
> >  
> > -	/* There's no need to rework memory if not going to/from NULL program.
> > -	 * If there is no lif->xdp_prog, there should also be no q.xdp_rxq_info
> > -	 * This way we don't need to keep an *xdp_prog in every queue struct.
> > -	 */
> > -	if (!lif->xdp_prog == !lif->rxqcqs[0]->q.xdp_rxq_info)
> > +	/* There's no need to rework memory if not going to/from NULL program.  */
> > +	xdp_prog = READ_ONCE(lif->xdp_prog);
> > +	if (!xdp_prog == !lif->rxqcqs[0]->q.xdp_prog)
> >  		return 0;

In a case when we replace a non-NULL program with another non-NULL program this 
would create a situation where lif and queues have different pointers on them.

> >  
> >  	for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
> >  		struct ionic_queue *q = &lif->rxqcqs[i]->q;
> >  
> > -		if (q->xdp_rxq_info) {
> > +		if (q->xdp_prog) {
> >  			ionic_xdp_unregister_rxq_info(q);
> > +			q->xdp_prog = NULL;
> >  			continue;
> >  		}
> >  
> > @@ -2727,6 +2727,7 @@ static int ionic_xdp_queues_config(struct ionic_lif *lif)
> >  				i, err);
> >  			goto err_out;
> >  		}
> > +		q->xdp_prog = xdp_prog;
> >  	}
> >  
> >  	return 0;

[...]
Brett Creeley Aug. 27, 2024, 9:40 p.m. UTC | #3
On 8/27/2024 4:44 AM, Larysa Zaremba wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> On Mon, Aug 26, 2024 at 11:44:20AM -0700, Brett Creeley wrote:
>> From: Shannon Nelson <shannon.nelson@amd.com>
>>
>> We originally were using a per-interface xdp_prog variable to track
>> a loaded XDP program since we knew there would never be support for a
>> per-queue XDP program.  With that, we only built the per queue rxq_info
>> struct when an XDP program was loaded and removed it on XDP program unload,
>> and used the pointer as an indicator in the Rx hotpath to know to how build
>> the buffers.  However, that's really not the model generally used, and
>> makes a conversion to page_pool Rx buffer cacheing a little problematic.
>>
>> This patch converts the driver to use the more common approach of using
>> a per-queue xdp_prog pointer to work out buffer allocations and need
>> for bpf_prog_run_xdp().  We jostle a couple of fields in the queue struct
>> in order to keep the new xdp_prog pointer in a warm cacheline.
>>
>> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
>> Signed-off-by: Brett Creeley <brett.creeley@amd.com>
> 
> Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
> 
> If you happen to send another version, please include in a commit message a note
> about READ_ONCE() removal. The removal itself is OK, but an indication that this
> was intentional would be nice.

Sure, will do. Thanks for the review.

Brett

<snip>
Brett Creeley Aug. 27, 2024, 10:27 p.m. UTC | #4
On 8/27/2024 4:57 AM, Larysa Zaremba wrote:
> Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
> 
> 
> On Tue, Aug 27, 2024 at 01:44:10PM +0200, Larysa Zaremba wrote:
>> On Mon, Aug 26, 2024 at 11:44:20AM -0700, Brett Creeley wrote:
>>> From: Shannon Nelson <shannon.nelson@amd.com>
>>>
>>> We originally were using a per-interface xdp_prog variable to track
>>> a loaded XDP program since we knew there would never be support for a
>>> per-queue XDP program.  With that, we only built the per queue rxq_info
>>> struct when an XDP program was loaded and removed it on XDP program unload,
>>> and used the pointer as an indicator in the Rx hotpath to know to how build
>>> the buffers.  However, that's really not the model generally used, and
>>> makes a conversion to page_pool Rx buffer cacheing a little problematic.
>>>
>>> This patch converts the driver to use the more common approach of using
>>> a per-queue xdp_prog pointer to work out buffer allocations and need
>>> for bpf_prog_run_xdp().  We jostle a couple of fields in the queue struct
>>> in order to keep the new xdp_prog pointer in a warm cacheline.
>>>
>>> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
>>> Signed-off-by: Brett Creeley <brett.creeley@amd.com>
>>
>> Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
>>
> 
> I would like to rewoke the tag, see below why.
> 
>> If you happen to send another version, please include in a commit message a note
>> about READ_ONCE() removal. The removal itself is OK, but an indication that this
>> was intentional would be nice.
>>
>>> ---
>>>   .../net/ethernet/pensando/ionic/ionic_dev.h   |  7 +++++--
>>>   .../net/ethernet/pensando/ionic/ionic_lif.c   | 14 +++++++------
>>>   .../net/ethernet/pensando/ionic/ionic_txrx.c  | 21 +++++++++----------
>>>   3 files changed, 23 insertions(+), 19 deletions(-)
>>>
>>> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
>>> index c647033f3ad2..19ae68a86a0b 100644
>>> --- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
>>> +++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
>>> @@ -238,9 +238,8 @@ struct ionic_queue {
>>>      unsigned int index;
>>>      unsigned int num_descs;
>>>      unsigned int max_sg_elems;
>>> +
>>>      u64 features;
>>> -   unsigned int type;
>>> -   unsigned int hw_index;
>>>      unsigned int hw_type;
>>>      bool xdp_flush;
>>>      union {
>>> @@ -261,7 +260,11 @@ struct ionic_queue {
>>>              struct ionic_rxq_sg_desc *rxq_sgl;
>>>      };
>>>      struct xdp_rxq_info *xdp_rxq_info;
>>> +   struct bpf_prog *xdp_prog;
>>>      struct ionic_queue *partner;
>>> +
>>> +   unsigned int type;
>>> +   unsigned int hw_index;
>>>      dma_addr_t base_pa;
>>>      dma_addr_t cmb_base_pa;
>>>      dma_addr_t sg_base_pa;
>>> diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
>>> index aa0cc31dfe6e..0fba2df33915 100644
>>> --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
>>> +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
>>> @@ -2700,24 +2700,24 @@ static int ionic_xdp_register_rxq_info(struct ionic_queue *q, unsigned int napi_
>>>
>>>   static int ionic_xdp_queues_config(struct ionic_lif *lif)
>>>   {
>>> +   struct bpf_prog *xdp_prog;
>>>      unsigned int i;
>>>      int err;
>>>
>>>      if (!lif->rxqcqs)
>>>              return 0;
>>>
>>> -   /* There's no need to rework memory if not going to/from NULL program.
>>> -    * If there is no lif->xdp_prog, there should also be no q.xdp_rxq_info
>>> -    * This way we don't need to keep an *xdp_prog in every queue struct.
>>> -    */
>>> -   if (!lif->xdp_prog == !lif->rxqcqs[0]->q.xdp_rxq_info)
>>> +   /* There's no need to rework memory if not going to/from NULL program.  */
>>> +   xdp_prog = READ_ONCE(lif->xdp_prog);
>>> +   if (!xdp_prog == !lif->rxqcqs[0]->q.xdp_prog)
>>>              return 0;
> 
> In a case when we replace a non-NULL program with another non-NULL program this
> would create a situation where lif and queues have different pointers on them.

Yeah, you are right. Good catch. We will get this fixed up in the next 
version.

Thanks,

Brett

> 
>>>
>>>      for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
>>>              struct ionic_queue *q = &lif->rxqcqs[i]->q;
>>>
>>> -           if (q->xdp_rxq_info) {
>>> +           if (q->xdp_prog) {
>>>                      ionic_xdp_unregister_rxq_info(q);
>>> +                   q->xdp_prog = NULL;
>>>                      continue;
>>>              }
>>>
>>> @@ -2727,6 +2727,7 @@ static int ionic_xdp_queues_config(struct ionic_lif *lif)
>>>                              i, err);
>>>                      goto err_out;
>>>              }
>>> +           q->xdp_prog = xdp_prog;
>>>      }
>>>
>>>      return 0;
> 
> [...]
diff mbox series

Patch

diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
index c647033f3ad2..19ae68a86a0b 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
@@ -238,9 +238,8 @@  struct ionic_queue {
 	unsigned int index;
 	unsigned int num_descs;
 	unsigned int max_sg_elems;
+
 	u64 features;
-	unsigned int type;
-	unsigned int hw_index;
 	unsigned int hw_type;
 	bool xdp_flush;
 	union {
@@ -261,7 +260,11 @@  struct ionic_queue {
 		struct ionic_rxq_sg_desc *rxq_sgl;
 	};
 	struct xdp_rxq_info *xdp_rxq_info;
+	struct bpf_prog *xdp_prog;
 	struct ionic_queue *partner;
+
+	unsigned int type;
+	unsigned int hw_index;
 	dma_addr_t base_pa;
 	dma_addr_t cmb_base_pa;
 	dma_addr_t sg_base_pa;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index aa0cc31dfe6e..0fba2df33915 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -2700,24 +2700,24 @@  static int ionic_xdp_register_rxq_info(struct ionic_queue *q, unsigned int napi_
 
 static int ionic_xdp_queues_config(struct ionic_lif *lif)
 {
+	struct bpf_prog *xdp_prog;
 	unsigned int i;
 	int err;
 
 	if (!lif->rxqcqs)
 		return 0;
 
-	/* There's no need to rework memory if not going to/from NULL program.
-	 * If there is no lif->xdp_prog, there should also be no q.xdp_rxq_info
-	 * This way we don't need to keep an *xdp_prog in every queue struct.
-	 */
-	if (!lif->xdp_prog == !lif->rxqcqs[0]->q.xdp_rxq_info)
+	/* There's no need to rework memory if not going to/from NULL program.  */
+	xdp_prog = READ_ONCE(lif->xdp_prog);
+	if (!xdp_prog == !lif->rxqcqs[0]->q.xdp_prog)
 		return 0;
 
 	for (i = 0; i < lif->ionic->nrxqs_per_lif && lif->rxqcqs[i]; i++) {
 		struct ionic_queue *q = &lif->rxqcqs[i]->q;
 
-		if (q->xdp_rxq_info) {
+		if (q->xdp_prog) {
 			ionic_xdp_unregister_rxq_info(q);
+			q->xdp_prog = NULL;
 			continue;
 		}
 
@@ -2727,6 +2727,7 @@  static int ionic_xdp_queues_config(struct ionic_lif *lif)
 				i, err);
 			goto err_out;
 		}
+		q->xdp_prog = xdp_prog;
 	}
 
 	return 0;
@@ -2878,6 +2879,7 @@  static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
 	swap(a->q.base,       b->q.base);
 	swap(a->q.base_pa,    b->q.base_pa);
 	swap(a->q.info,       b->q.info);
+	swap(a->q.xdp_prog,   b->q.xdp_prog);
 	swap(a->q.xdp_rxq_info, b->q.xdp_rxq_info);
 	swap(a->q.partner,    b->q.partner);
 	swap(a->q_base,       b->q_base);
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
index d62b2b60b133..858ab4fd9218 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c
@@ -190,7 +190,7 @@  static bool ionic_rx_buf_recycle(struct ionic_queue *q,
 	if (page_to_nid(buf_info->page) != numa_mem_id())
 		return false;
 
-	size = ALIGN(len, q->xdp_rxq_info ? IONIC_PAGE_SIZE : IONIC_PAGE_SPLIT_SZ);
+	size = ALIGN(len, q->xdp_prog ? IONIC_PAGE_SIZE : IONIC_PAGE_SPLIT_SZ);
 	buf_info->page_offset += size;
 	if (buf_info->page_offset >= IONIC_PAGE_SIZE)
 		return false;
@@ -639,8 +639,7 @@  static void ionic_rx_clean(struct ionic_queue *q,
 	struct net_device *netdev = q->lif->netdev;
 	struct ionic_qcq *qcq = q_to_qcq(q);
 	struct ionic_rx_stats *stats;
-	struct bpf_prog *xdp_prog;
-	unsigned int headroom;
+	unsigned int headroom = 0;
 	struct sk_buff *skb;
 	bool synced = false;
 	bool use_copybreak;
@@ -664,14 +663,13 @@  static void ionic_rx_clean(struct ionic_queue *q,
 	stats->pkts++;
 	stats->bytes += len;
 
-	xdp_prog = READ_ONCE(q->lif->xdp_prog);
-	if (xdp_prog) {
-		if (ionic_run_xdp(stats, netdev, xdp_prog, q, desc_info->bufs, len))
+	if (q->xdp_prog) {
+		if (ionic_run_xdp(stats, netdev, q->xdp_prog, q, desc_info->bufs, len))
 			return;
 		synced = true;
+		headroom = XDP_PACKET_HEADROOM;
 	}
 
-	headroom = q->xdp_rxq_info ? XDP_PACKET_HEADROOM : 0;
 	use_copybreak = len <= q->lif->rx_copybreak;
 	if (use_copybreak)
 		skb = ionic_rx_copybreak(netdev, q, desc_info,
@@ -814,7 +812,7 @@  void ionic_rx_fill(struct ionic_queue *q)
 	len = netdev->mtu + VLAN_ETH_HLEN;
 
 	for (i = n_fill; i; i--) {
-		unsigned int headroom;
+		unsigned int headroom = 0;
 		unsigned int buf_len;
 
 		nfrags = 0;
@@ -835,11 +833,12 @@  void ionic_rx_fill(struct ionic_queue *q)
 		 * XDP uses space in the first buffer, so account for
 		 * head room, tail room, and ip header in the first frag size.
 		 */
-		headroom = q->xdp_rxq_info ? XDP_PACKET_HEADROOM : 0;
-		if (q->xdp_rxq_info)
+		if (q->xdp_prog) {
 			buf_len = IONIC_XDP_MAX_LINEAR_MTU + VLAN_ETH_HLEN;
-		else
+			headroom = XDP_PACKET_HEADROOM;
+		} else {
 			buf_len = ionic_rx_buf_size(buf_info);
+		}
 		frag_len = min_t(u16, len, buf_len);
 
 		desc->addr = cpu_to_le64(ionic_rx_buf_pa(buf_info) + headroom);