summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShannon Nelson <shannon.nelson@amd.com>2024-09-06 16:26:19 -0700
committerJakub Kicinski <kuba@kernel.org>2024-09-09 19:18:14 -0700
commit7b4ec51f165f37b0102f98df1b0c13b64b5178e8 (patch)
tree5d788aa43a8a955be99a2ccfef1ba8e912fbc963
parent7639a6e058155614d638072de6be2fba485813d6 (diff)
downloadlinux-7b4ec51f165f37b0102f98df1b0c13b64b5178e8.tar.gz
linux-7b4ec51f165f37b0102f98df1b0c13b64b5178e8.tar.bz2
linux-7b4ec51f165f37b0102f98df1b0c13b64b5178e8.zip
ionic: use per-queue xdp_prog
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> Link: https://patch.msgid.link/20240906232623.39651-4-brett.creeley@amd.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_dev.h7
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c37
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_txrx.c21
3 files changed, 34 insertions, 31 deletions
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h
index f2f07bf88545..3ae6b34cc85f 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 86774d9922d8..68b540d26702 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -46,7 +46,7 @@ static int ionic_start_queues(struct ionic_lif *lif);
static void ionic_stop_queues(struct ionic_lif *lif);
static void ionic_lif_queue_identify(struct ionic_lif *lif);
-static int ionic_xdp_queues_config(struct ionic_lif *lif);
+static int ionic_xdp_rxqs_update(struct ionic_lif *lif);
static void ionic_xdp_unregister_rxq_info(struct ionic_queue *q);
static void ionic_dim_work(struct work_struct *work)
@@ -2143,7 +2143,7 @@ static int ionic_txrx_enable(struct ionic_lif *lif)
int derr = 0;
int i, err;
- err = ionic_xdp_queues_config(lif);
+ err = ionic_xdp_rxqs_update(lif);
if (err)
return err;
@@ -2192,7 +2192,7 @@ err_out:
derr = ionic_qcq_disable(lif, lif->rxqcqs[i], derr);
}
- ionic_xdp_queues_config(lif);
+ ionic_xdp_rxqs_update(lif);
return err;
}
@@ -2698,35 +2698,35 @@ err_out:
return err;
}
-static int ionic_xdp_queues_config(struct ionic_lif *lif)
+static int ionic_xdp_rxqs_update(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)
- return 0;
-
+ xdp_prog = READ_ONCE(lif->xdp_prog);
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);
- continue;
+ q->xdp_prog = NULL;
}
- err = ionic_xdp_register_rxq_info(q, lif->rxqcqs[i]->napi.napi_id);
- if (err) {
- dev_err(lif->ionic->dev, "failed to register RX queue %d info for XDP, err %d\n",
- i, err);
- goto err_out;
+ if (xdp_prog) {
+ unsigned int napi_id = lif->rxqcqs[i]->napi.napi_id;
+
+ err = ionic_xdp_register_rxq_info(q, napi_id);
+ if (err) {
+ dev_err(lif->ionic->dev, "failed to register RX queue %d info for XDP, err %d\n",
+ i, err);
+ goto err_out;
+ }
}
+ q->xdp_prog = xdp_prog;
}
return 0;
@@ -2878,6 +2878,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);