Commit ac8813c0 authored by Shannon Nelson's avatar Shannon Nelson Committed by Jakub Kicinski

ionic: convert Rx queue buffers to use page_pool

Our home-grown buffer management needs to go away and we need
to be playing nicely with the page_pool infrastructure.  This
converts the Rx traffic queues to use page_pool.

Also, since ionic_rx_buf_size() was removed, redefine
IONIC_PAGE_SIZE to account for IONIC_MAX_BUF_LEN being the
largest allowed buffer to prevent overflowing u16 variables,
which could happen when PAGE_SIZE is defined as >= 64KB.

include/linux/minmax.h:93:37: warning: conversion from 'long unsigned int' to 'u16' {aka 'short unsigned int'} changes value from '65536' to '0' [-Woverflow]
Signed-off-by: default avatarShannon Nelson <shannon.nelson@amd.com>
Signed-off-by: default avatarBrett Creeley <brett.creeley@amd.com>
Link: https://patch.msgid.link/20240906232623.39651-7-brett.creeley@amd.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent a7f3f635
...@@ -23,6 +23,7 @@ config IONIC ...@@ -23,6 +23,7 @@ config IONIC
depends on PTP_1588_CLOCK_OPTIONAL depends on PTP_1588_CLOCK_OPTIONAL
select NET_DEVLINK select NET_DEVLINK
select DIMLIB select DIMLIB
select PAGE_POOL
help help
This enables the support for the Pensando family of Ethernet This enables the support for the Pensando family of Ethernet
adapters. More specific information on this driver can be adapters. More specific information on this driver can be
......
...@@ -181,10 +181,7 @@ struct ionic_queue; ...@@ -181,10 +181,7 @@ struct ionic_queue;
struct ionic_qcq; struct ionic_qcq;
#define IONIC_MAX_BUF_LEN ((u16)-1) #define IONIC_MAX_BUF_LEN ((u16)-1)
#define IONIC_PAGE_SIZE PAGE_SIZE #define IONIC_PAGE_SIZE MIN(PAGE_SIZE, IONIC_MAX_BUF_LEN)
#define IONIC_PAGE_SPLIT_SZ (PAGE_SIZE / 2)
#define IONIC_PAGE_GFP_MASK (GFP_ATOMIC | __GFP_NOWARN |\
__GFP_COMP | __GFP_MEMALLOC)
#define IONIC_XDP_MAX_LINEAR_MTU (IONIC_PAGE_SIZE - \ #define IONIC_XDP_MAX_LINEAR_MTU (IONIC_PAGE_SIZE - \
(VLAN_ETH_HLEN + \ (VLAN_ETH_HLEN + \
...@@ -248,11 +245,6 @@ struct ionic_queue { ...@@ -248,11 +245,6 @@ struct ionic_queue {
struct ionic_rxq_desc *rxq; struct ionic_rxq_desc *rxq;
struct ionic_admin_cmd *adminq; struct ionic_admin_cmd *adminq;
}; };
union {
void __iomem *cmb_base;
struct ionic_txq_desc __iomem *cmb_txq;
struct ionic_rxq_desc __iomem *cmb_rxq;
};
union { union {
void *sg_base; void *sg_base;
struct ionic_txq_sg_desc *txq_sgl; struct ionic_txq_sg_desc *txq_sgl;
...@@ -261,8 +253,14 @@ struct ionic_queue { ...@@ -261,8 +253,14 @@ struct ionic_queue {
}; };
struct xdp_rxq_info *xdp_rxq_info; struct xdp_rxq_info *xdp_rxq_info;
struct bpf_prog *xdp_prog; struct bpf_prog *xdp_prog;
struct page_pool *page_pool;
struct ionic_queue *partner; struct ionic_queue *partner;
union {
void __iomem *cmb_base;
struct ionic_txq_desc __iomem *cmb_txq;
struct ionic_rxq_desc __iomem *cmb_rxq;
};
unsigned int type; unsigned int type;
unsigned int hw_index; unsigned int hw_index;
dma_addr_t base_pa; dma_addr_t base_pa;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/crash_dump.h> #include <linux/crash_dump.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <net/page_pool/helpers.h>
#include "ionic.h" #include "ionic.h"
#include "ionic_bus.h" #include "ionic_bus.h"
...@@ -439,6 +440,9 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq) ...@@ -439,6 +440,9 @@ static void ionic_qcq_free(struct ionic_lif *lif, struct ionic_qcq *qcq)
qcq->sg_base_pa = 0; qcq->sg_base_pa = 0;
} }
page_pool_destroy(qcq->q.page_pool);
qcq->q.page_pool = NULL;
ionic_qcq_intr_free(lif, qcq); ionic_qcq_intr_free(lif, qcq);
vfree(qcq->q.info); vfree(qcq->q.info);
qcq->q.info = NULL; qcq->q.info = NULL;
...@@ -553,7 +557,8 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -553,7 +557,8 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
unsigned int cq_desc_size, unsigned int cq_desc_size,
unsigned int sg_desc_size, unsigned int sg_desc_size,
unsigned int desc_info_size, unsigned int desc_info_size,
unsigned int pid, struct ionic_qcq **qcq) unsigned int pid, struct bpf_prog *xdp_prog,
struct ionic_qcq **qcq)
{ {
struct ionic_dev *idev = &lif->ionic->idev; struct ionic_dev *idev = &lif->ionic->idev;
struct device *dev = lif->ionic->dev; struct device *dev = lif->ionic->dev;
...@@ -579,6 +584,31 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -579,6 +584,31 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
goto err_out_free_qcq; goto err_out_free_qcq;
} }
if (type == IONIC_QTYPE_RXQ) {
struct page_pool_params pp_params = {
.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV,
.order = 0,
.pool_size = num_descs,
.nid = NUMA_NO_NODE,
.dev = lif->ionic->dev,
.napi = &new->napi,
.dma_dir = DMA_FROM_DEVICE,
.max_len = PAGE_SIZE,
.netdev = lif->netdev,
};
if (xdp_prog)
pp_params.dma_dir = DMA_BIDIRECTIONAL;
new->q.page_pool = page_pool_create(&pp_params);
if (IS_ERR(new->q.page_pool)) {
netdev_err(lif->netdev, "Cannot create page_pool\n");
err = PTR_ERR(new->q.page_pool);
new->q.page_pool = NULL;
goto err_out_free_q_info;
}
}
new->q.type = type; new->q.type = type;
new->q.max_sg_elems = lif->qtype_info[type].max_sg_elems; new->q.max_sg_elems = lif->qtype_info[type].max_sg_elems;
...@@ -586,12 +616,12 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -586,12 +616,12 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
desc_size, sg_desc_size, pid); desc_size, sg_desc_size, pid);
if (err) { if (err) {
netdev_err(lif->netdev, "Cannot initialize queue\n"); netdev_err(lif->netdev, "Cannot initialize queue\n");
goto err_out_free_q_info; goto err_out_free_page_pool;
} }
err = ionic_alloc_qcq_interrupt(lif, new); err = ionic_alloc_qcq_interrupt(lif, new);
if (err) if (err)
goto err_out_free_q_info; goto err_out_free_page_pool;
err = ionic_cq_init(lif, &new->cq, &new->intr, num_descs, cq_desc_size); err = ionic_cq_init(lif, &new->cq, &new->intr, num_descs, cq_desc_size);
if (err) { if (err) {
...@@ -712,6 +742,8 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type, ...@@ -712,6 +742,8 @@ static int ionic_qcq_alloc(struct ionic_lif *lif, unsigned int type,
devm_free_irq(dev, new->intr.vector, &new->napi); devm_free_irq(dev, new->intr.vector, &new->napi);
ionic_intr_free(lif->ionic, new->intr.index); ionic_intr_free(lif->ionic, new->intr.index);
} }
err_out_free_page_pool:
page_pool_destroy(new->q.page_pool);
err_out_free_q_info: err_out_free_q_info:
vfree(new->q.info); vfree(new->q.info);
err_out_free_qcq: err_out_free_qcq:
...@@ -734,7 +766,7 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif) ...@@ -734,7 +766,7 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
sizeof(struct ionic_admin_comp), sizeof(struct ionic_admin_comp),
0, 0,
sizeof(struct ionic_admin_desc_info), sizeof(struct ionic_admin_desc_info),
lif->kern_pid, &lif->adminqcq); lif->kern_pid, NULL, &lif->adminqcq);
if (err) if (err)
return err; return err;
ionic_debugfs_add_qcq(lif, lif->adminqcq); ionic_debugfs_add_qcq(lif, lif->adminqcq);
...@@ -747,7 +779,7 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif) ...@@ -747,7 +779,7 @@ static int ionic_qcqs_alloc(struct ionic_lif *lif)
sizeof(union ionic_notifyq_comp), sizeof(union ionic_notifyq_comp),
0, 0,
sizeof(struct ionic_admin_desc_info), sizeof(struct ionic_admin_desc_info),
lif->kern_pid, &lif->notifyqcq); lif->kern_pid, NULL, &lif->notifyqcq);
if (err) if (err)
goto err_out; goto err_out;
ionic_debugfs_add_qcq(lif, lif->notifyqcq); ionic_debugfs_add_qcq(lif, lif->notifyqcq);
...@@ -965,7 +997,7 @@ int ionic_lif_create_hwstamp_txq(struct ionic_lif *lif) ...@@ -965,7 +997,7 @@ int ionic_lif_create_hwstamp_txq(struct ionic_lif *lif)
err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, txq_i, "hwstamp_tx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, txq_i, "hwstamp_tx", flags,
num_desc, desc_sz, comp_sz, sg_desc_sz, num_desc, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_tx_desc_info), sizeof(struct ionic_tx_desc_info),
lif->kern_pid, &txq); lif->kern_pid, NULL, &txq);
if (err) if (err)
goto err_qcq_alloc; goto err_qcq_alloc;
...@@ -1025,7 +1057,7 @@ int ionic_lif_create_hwstamp_rxq(struct ionic_lif *lif) ...@@ -1025,7 +1057,7 @@ int ionic_lif_create_hwstamp_rxq(struct ionic_lif *lif)
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, rxq_i, "hwstamp_rx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, rxq_i, "hwstamp_rx", flags,
num_desc, desc_sz, comp_sz, sg_desc_sz, num_desc, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_rx_desc_info), sizeof(struct ionic_rx_desc_info),
lif->kern_pid, &rxq); lif->kern_pid, NULL, &rxq);
if (err) if (err)
goto err_qcq_alloc; goto err_qcq_alloc;
...@@ -2051,7 +2083,7 @@ static int ionic_txrx_alloc(struct ionic_lif *lif) ...@@ -2051,7 +2083,7 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags,
num_desc, desc_sz, comp_sz, sg_desc_sz, num_desc, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_tx_desc_info), sizeof(struct ionic_tx_desc_info),
lif->kern_pid, &lif->txqcqs[i]); lif->kern_pid, NULL, &lif->txqcqs[i]);
if (err) if (err)
goto err_out; goto err_out;
...@@ -2083,7 +2115,8 @@ static int ionic_txrx_alloc(struct ionic_lif *lif) ...@@ -2083,7 +2115,8 @@ static int ionic_txrx_alloc(struct ionic_lif *lif)
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
num_desc, desc_sz, comp_sz, sg_desc_sz, num_desc, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_rx_desc_info), sizeof(struct ionic_rx_desc_info),
lif->kern_pid, &lif->rxqcqs[i]); lif->kern_pid, lif->xdp_prog,
&lif->rxqcqs[i]);
if (err) if (err)
goto err_out; goto err_out;
...@@ -2679,14 +2712,14 @@ static int ionic_register_rxq_info(struct ionic_queue *q, unsigned int napi_id) ...@@ -2679,14 +2712,14 @@ static int ionic_register_rxq_info(struct ionic_queue *q, unsigned int napi_id)
err = xdp_rxq_info_reg(rxq_info, q->lif->netdev, q->index, napi_id); err = xdp_rxq_info_reg(rxq_info, q->lif->netdev, q->index, napi_id);
if (err) { if (err) {
dev_err(q->dev, "Queue %d xdp_rxq_info_reg failed, err %d\n", netdev_err(q->lif->netdev, "q%d xdp_rxq_info_reg failed, err %d\n",
q->index, err); q->index, err);
goto err_out; goto err_out;
} }
err = xdp_rxq_info_reg_mem_model(rxq_info, MEM_TYPE_PAGE_ORDER0, NULL); err = xdp_rxq_info_reg_mem_model(rxq_info, MEM_TYPE_PAGE_POOL, q->page_pool);
if (err) { if (err) {
dev_err(q->dev, "Queue %d xdp_rxq_info_reg_mem_model failed, err %d\n", netdev_err(q->lif->netdev, "q%d xdp_rxq_info_reg_mem_model failed, err %d\n",
q->index, err); q->index, err);
xdp_rxq_info_unreg(rxq_info); xdp_rxq_info_unreg(rxq_info);
goto err_out; goto err_out;
...@@ -2853,7 +2886,16 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif, ...@@ -2853,7 +2886,16 @@ static int ionic_cmb_reconfig(struct ionic_lif *lif,
static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b) static void ionic_swap_queues(struct ionic_qcq *a, struct ionic_qcq *b)
{ {
/* only swapping the queues, not the napi, flags, or other stuff */ /* only swapping the queues and napi, not flags or other stuff */
swap(a->napi, b->napi);
if (a->q.type == IONIC_QTYPE_RXQ) {
swap(a->q.page_pool, b->q.page_pool);
a->q.page_pool->p.napi = &a->napi;
if (b->q.page_pool) /* is NULL when increasing queue count */
b->q.page_pool->p.napi = &b->napi;
}
swap(a->q.features, b->q.features); swap(a->q.features, b->q.features);
swap(a->q.num_descs, b->q.num_descs); swap(a->q.num_descs, b->q.num_descs);
swap(a->q.desc_size, b->q.desc_size); swap(a->q.desc_size, b->q.desc_size);
...@@ -2943,7 +2985,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2943,7 +2985,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags,
4, desc_sz, comp_sz, sg_desc_sz, 4, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_tx_desc_info), sizeof(struct ionic_tx_desc_info),
lif->kern_pid, &lif->txqcqs[i]); lif->kern_pid, NULL, &lif->txqcqs[i]);
if (err) if (err)
goto err_out; goto err_out;
} }
...@@ -2952,7 +2994,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2952,7 +2994,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_TXQ, i, "tx", flags,
num_desc, desc_sz, comp_sz, sg_desc_sz, num_desc, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_tx_desc_info), sizeof(struct ionic_tx_desc_info),
lif->kern_pid, &tx_qcqs[i]); lif->kern_pid, NULL, &tx_qcqs[i]);
if (err) if (err)
goto err_out; goto err_out;
} }
...@@ -2974,7 +3016,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2974,7 +3016,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
4, desc_sz, comp_sz, sg_desc_sz, 4, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_rx_desc_info), sizeof(struct ionic_rx_desc_info),
lif->kern_pid, &lif->rxqcqs[i]); lif->kern_pid, NULL, &lif->rxqcqs[i]);
if (err) if (err)
goto err_out; goto err_out;
} }
...@@ -2983,7 +3025,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif, ...@@ -2983,7 +3025,7 @@ int ionic_reconfigure_queues(struct ionic_lif *lif,
err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags, err = ionic_qcq_alloc(lif, IONIC_QTYPE_RXQ, i, "rx", flags,
num_desc, desc_sz, comp_sz, sg_desc_sz, num_desc, desc_sz, comp_sz, sg_desc_sz,
sizeof(struct ionic_rx_desc_info), sizeof(struct ionic_rx_desc_info),
lif->kern_pid, &rx_qcqs[i]); lif->kern_pid, qparam->xdp_prog, &rx_qcqs[i]);
if (err) if (err)
goto err_out; goto err_out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment