mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 04:29:11 -04:00
octeontx2-pf: AF_XDP zero copy transmit support
This patch implements below changes, 1. To avoid concurrency with normal traffic uses XDP queues. 2. Since there are chances that XDP and AF_XDP can fall under same queue uses separate flags to handle dma buffers. Signed-off-by: Hariprasad Kelam <hkelam@marvell.com> Signed-off-by: Suman Ghosh <sumang@marvell.com> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
@@ -1037,6 +1037,10 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
|
||||
|
||||
sq->stats.bytes = 0;
|
||||
sq->stats.pkts = 0;
|
||||
/* Attach XSK_BUFF_POOL to XDP queue */
|
||||
if (qidx > pfvf->hw.xdp_queues)
|
||||
otx2_attach_xsk_buff(pfvf, sq, (qidx - pfvf->hw.xdp_queues));
|
||||
|
||||
|
||||
chan_offset = qidx % pfvf->hw.tx_chan_cnt;
|
||||
err = pfvf->hw_ops->sq_aq_init(pfvf, qidx, chan_offset, sqb_aura);
|
||||
|
||||
@@ -129,6 +129,12 @@ enum otx2_errcodes_re {
|
||||
ERRCODE_IL4_CSUM = 0x22,
|
||||
};
|
||||
|
||||
enum otx2_xdp_action {
|
||||
OTX2_XDP_TX = BIT(0),
|
||||
OTX2_XDP_REDIRECT = BIT(1),
|
||||
OTX2_AF_XDP_FRAME = BIT(2),
|
||||
};
|
||||
|
||||
struct otx2_dev_stats {
|
||||
u64 rx_bytes;
|
||||
u64 rx_frames;
|
||||
|
||||
@@ -2693,7 +2693,7 @@ static int otx2_xdp_xmit_tx(struct otx2_nic *pf, struct xdp_frame *xdpf,
|
||||
return -ENOMEM;
|
||||
|
||||
err = otx2_xdp_sq_append_pkt(pf, xdpf, dma_addr, xdpf->len,
|
||||
qidx, XDP_REDIRECT);
|
||||
qidx, OTX2_XDP_REDIRECT);
|
||||
if (!err) {
|
||||
otx2_dma_unmap_page(pf, dma_addr, xdpf->len, DMA_TO_DEVICE);
|
||||
xdp_return_frame(xdpf);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "otx2_txrx.h"
|
||||
#include "otx2_ptp.h"
|
||||
#include "cn10k.h"
|
||||
#include "otx2_xsk.h"
|
||||
|
||||
#define CQE_ADDR(CQ, idx) ((CQ)->cqe_base + ((CQ)->cqe_size * (idx)))
|
||||
#define PTP_PORT 0x13F
|
||||
@@ -103,13 +104,19 @@ static unsigned int frag_num(unsigned int i)
|
||||
|
||||
static void otx2_xdp_snd_pkt_handler(struct otx2_nic *pfvf,
|
||||
struct otx2_snd_queue *sq,
|
||||
struct nix_cqe_tx_s *cqe)
|
||||
struct nix_cqe_tx_s *cqe,
|
||||
int *xsk_frames)
|
||||
{
|
||||
struct nix_send_comp_s *snd_comp = &cqe->comp;
|
||||
struct sg_list *sg;
|
||||
|
||||
sg = &sq->sg[snd_comp->sqe_id];
|
||||
if (sg->flags & XDP_REDIRECT)
|
||||
if (sg->flags & OTX2_AF_XDP_FRAME) {
|
||||
(*xsk_frames)++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sg->flags & OTX2_XDP_REDIRECT)
|
||||
otx2_dma_unmap_page(pfvf, sg->dma_addr[0], sg->size[0], DMA_TO_DEVICE);
|
||||
xdp_return_frame((struct xdp_frame *)sg->skb);
|
||||
sg->skb = (u64)NULL;
|
||||
@@ -434,6 +441,18 @@ int otx2_refill_pool_ptrs(void *dev, struct otx2_cq_queue *cq)
|
||||
return cnt - cq->pool_ptrs;
|
||||
}
|
||||
|
||||
static void otx2_zc_submit_pkts(struct otx2_nic *pfvf, struct xsk_buff_pool *xsk_pool,
|
||||
int *xsk_frames, int qidx, int budget)
|
||||
{
|
||||
if (*xsk_frames)
|
||||
xsk_tx_completed(xsk_pool, *xsk_frames);
|
||||
|
||||
if (xsk_uses_need_wakeup(xsk_pool))
|
||||
xsk_set_tx_need_wakeup(xsk_pool);
|
||||
|
||||
otx2_zc_napi_handler(pfvf, xsk_pool, qidx, budget);
|
||||
}
|
||||
|
||||
static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
|
||||
struct otx2_cq_queue *cq, int budget)
|
||||
{
|
||||
@@ -442,16 +461,22 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
|
||||
struct nix_cqe_tx_s *cqe;
|
||||
struct net_device *ndev;
|
||||
int processed_cqe = 0;
|
||||
int xsk_frames = 0;
|
||||
|
||||
qidx = cq->cq_idx - pfvf->hw.rx_queues;
|
||||
sq = &pfvf->qset.sq[qidx];
|
||||
|
||||
if (cq->pend_cqe >= budget)
|
||||
goto process_cqe;
|
||||
|
||||
if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe)
|
||||
if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe) {
|
||||
if (sq->xsk_pool)
|
||||
otx2_zc_submit_pkts(pfvf, sq->xsk_pool, &xsk_frames,
|
||||
qidx, budget);
|
||||
return 0;
|
||||
}
|
||||
|
||||
process_cqe:
|
||||
qidx = cq->cq_idx - pfvf->hw.rx_queues;
|
||||
sq = &pfvf->qset.sq[qidx];
|
||||
|
||||
while (likely(processed_cqe < budget) && cq->pend_cqe) {
|
||||
cqe = (struct nix_cqe_tx_s *)otx2_get_next_cqe(cq);
|
||||
@@ -461,10 +486,8 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
|
||||
break;
|
||||
}
|
||||
|
||||
qidx = cq->cq_idx - pfvf->hw.rx_queues;
|
||||
|
||||
if (cq->cq_type == CQ_XDP)
|
||||
otx2_xdp_snd_pkt_handler(pfvf, sq, cqe);
|
||||
otx2_xdp_snd_pkt_handler(pfvf, sq, cqe, &xsk_frames);
|
||||
else
|
||||
otx2_snd_pkt_handler(pfvf, cq, &pfvf->qset.sq[qidx],
|
||||
cqe, budget, &tx_pkts, &tx_bytes);
|
||||
@@ -505,6 +528,10 @@ static int otx2_tx_napi_handler(struct otx2_nic *pfvf,
|
||||
netif_carrier_ok(ndev))
|
||||
netif_tx_wake_queue(txq);
|
||||
}
|
||||
|
||||
if (sq->xsk_pool)
|
||||
otx2_zc_submit_pkts(pfvf, sq->xsk_pool, &xsk_frames, qidx, budget);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1499,8 +1526,10 @@ static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
|
||||
qidx += pfvf->hw.tx_queues;
|
||||
cq->pool_ptrs++;
|
||||
xdpf = xdp_convert_buff_to_frame(&xdp);
|
||||
return otx2_xdp_sq_append_pkt(pfvf, xdpf, cqe->sg.seg_addr,
|
||||
cqe->sg.seg_size, qidx, XDP_TX);
|
||||
return otx2_xdp_sq_append_pkt(pfvf, xdpf,
|
||||
cqe->sg.seg_addr,
|
||||
cqe->sg.seg_size,
|
||||
qidx, OTX2_XDP_TX);
|
||||
case XDP_REDIRECT:
|
||||
cq->pool_ptrs++;
|
||||
if (xsk_buff) {
|
||||
|
||||
@@ -106,6 +106,8 @@ struct otx2_snd_queue {
|
||||
/* SQE ring and CPT response queue for Inline IPSEC */
|
||||
struct qmem *sqe_ring;
|
||||
struct qmem *cpt_resp;
|
||||
/* Buffer pool for af_xdp zero-copy */
|
||||
struct xsk_buff_pool *xsk_pool;
|
||||
} ____cacheline_aligned_in_smp;
|
||||
|
||||
enum cq_type {
|
||||
|
||||
@@ -140,11 +140,14 @@ int otx2_xsk_pool_disable(struct otx2_nic *pf, u16 qidx)
|
||||
{
|
||||
struct net_device *netdev = pf->netdev;
|
||||
struct xsk_buff_pool *pool;
|
||||
struct otx2_snd_queue *sq;
|
||||
|
||||
pool = xsk_get_pool_from_qid(netdev, qidx);
|
||||
if (!pool)
|
||||
return -EINVAL;
|
||||
|
||||
sq = &pf->qset.sq[qidx + pf->hw.tx_queues];
|
||||
sq->xsk_pool = NULL;
|
||||
otx2_clean_up_rq(pf, qidx);
|
||||
clear_bit(qidx, pf->af_xdp_zc_qidx);
|
||||
xsk_pool_dma_unmap(pool, DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING);
|
||||
@@ -171,7 +174,7 @@ int otx2_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
|
||||
if (pf->flags & OTX2_FLAG_INTF_DOWN)
|
||||
return -ENETDOWN;
|
||||
|
||||
if (queue_id >= pf->hw.rx_queues)
|
||||
if (queue_id >= pf->hw.rx_queues || queue_id >= pf->hw.tx_queues)
|
||||
return -EINVAL;
|
||||
|
||||
cq_poll = &qset->napi[queue_id];
|
||||
@@ -179,8 +182,44 @@ int otx2_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
|
||||
return -EINVAL;
|
||||
|
||||
/* Trigger interrupt */
|
||||
if (!napi_if_scheduled_mark_missed(&cq_poll->napi))
|
||||
if (!napi_if_scheduled_mark_missed(&cq_poll->napi)) {
|
||||
otx2_write64(pf, NIX_LF_CINTX_ENA_W1S(cq_poll->cint_idx), BIT_ULL(0));
|
||||
otx2_write64(pf, NIX_LF_CINTX_INT_W1S(cq_poll->cint_idx), BIT_ULL(0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void otx2_attach_xsk_buff(struct otx2_nic *pfvf, struct otx2_snd_queue *sq, int qidx)
|
||||
{
|
||||
if (test_bit(qidx, pfvf->af_xdp_zc_qidx))
|
||||
sq->xsk_pool = xsk_get_pool_from_qid(pfvf->netdev, qidx);
|
||||
}
|
||||
|
||||
void otx2_zc_napi_handler(struct otx2_nic *pfvf, struct xsk_buff_pool *pool,
|
||||
int queue, int budget)
|
||||
{
|
||||
struct xdp_desc *xdp_desc = pool->tx_descs;
|
||||
int err, i, work_done = 0, batch;
|
||||
|
||||
budget = min(budget, otx2_read_free_sqe(pfvf, queue));
|
||||
batch = xsk_tx_peek_release_desc_batch(pool, budget);
|
||||
if (!batch)
|
||||
return;
|
||||
|
||||
for (i = 0; i < batch; i++) {
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
dma_addr = xsk_buff_raw_get_dma(pool, xdp_desc[i].addr);
|
||||
err = otx2_xdp_sq_append_pkt(pfvf, NULL, dma_addr, xdp_desc[i].len,
|
||||
queue, OTX2_AF_XDP_FRAME);
|
||||
if (!err) {
|
||||
netdev_err(pfvf->netdev, "AF_XDP: Unable to transfer packet err%d\n", err);
|
||||
break;
|
||||
}
|
||||
work_done++;
|
||||
}
|
||||
|
||||
if (work_done)
|
||||
xsk_tx_release(pool);
|
||||
}
|
||||
|
||||
@@ -17,5 +17,8 @@ int otx2_xsk_pool_disable(struct otx2_nic *pf, u16 qid);
|
||||
int otx2_xsk_pool_alloc_buf(struct otx2_nic *pfvf, struct otx2_pool *pool,
|
||||
dma_addr_t *dma, int idx);
|
||||
int otx2_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags);
|
||||
void otx2_zc_napi_handler(struct otx2_nic *pfvf, struct xsk_buff_pool *pool,
|
||||
int queue, int budget);
|
||||
void otx2_attach_xsk_buff(struct otx2_nic *pfvf, struct otx2_snd_queue *sq, int qidx);
|
||||
|
||||
#endif /* OTX2_XSK_H */
|
||||
|
||||
Reference in New Issue
Block a user