Commit 587fc3f0 authored by Shannon Nelson's avatar Shannon Nelson Committed by David S. Miller

ionic: Add XDP_REDIRECT support

The XDP_REDIRECT packets are given to the XDP stack and
we drop the use of the related page: it will get freed
by the driver that ends up doing the Tx.  Because we have
some hardware configurations with limited queue resources,
we use the existing datapath Tx queues rather than creating
and managing a separate set of xdp_tx queues.
Co-developed-by: default avatarBrett Creeley <brett.creeley@amd.com>
Signed-off-by: default avatarBrett Creeley <brett.creeley@amd.com>
Signed-off-by: default avatarShannon Nelson <shannon.nelson@amd.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8eeed837
...@@ -266,6 +266,7 @@ struct ionic_queue { ...@@ -266,6 +266,7 @@ struct ionic_queue {
}; };
struct xdp_rxq_info *xdp_rxq_info; struct xdp_rxq_info *xdp_rxq_info;
struct ionic_queue *partner; struct ionic_queue *partner;
bool xdp_flush;
dma_addr_t base_pa; dma_addr_t base_pa;
dma_addr_t cmb_base_pa; dma_addr_t cmb_base_pa;
dma_addr_t sg_base_pa; dma_addr_t sg_base_pa;
......
...@@ -1649,7 +1649,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif) ...@@ -1649,7 +1649,8 @@ static int ionic_init_nic_features(struct ionic_lif *lif)
netdev->priv_flags |= IFF_UNICAST_FLT | netdev->priv_flags |= IFF_UNICAST_FLT |
IFF_LIVE_ADDR_CHANGE; IFF_LIVE_ADDR_CHANGE;
netdev->xdp_features = NETDEV_XDP_ACT_BASIC; netdev->xdp_features = NETDEV_XDP_ACT_BASIC |
NETDEV_XDP_ACT_REDIRECT;
return 0; return 0;
} }
......
...@@ -56,6 +56,7 @@ struct ionic_rx_stats { ...@@ -56,6 +56,7 @@ struct ionic_rx_stats {
u64 xdp_aborted; u64 xdp_aborted;
u64 xdp_pass; u64 xdp_pass;
u64 xdp_tx; u64 xdp_tx;
u64 xdp_redirect;
}; };
#define IONIC_QCQ_F_INITED BIT(0) #define IONIC_QCQ_F_INITED BIT(0)
...@@ -144,6 +145,7 @@ struct ionic_lif_sw_stats { ...@@ -144,6 +145,7 @@ struct ionic_lif_sw_stats {
u64 xdp_aborted; u64 xdp_aborted;
u64 xdp_pass; u64 xdp_pass;
u64 xdp_tx; u64 xdp_tx;
u64 xdp_redirect;
u64 xdp_frames; u64 xdp_frames;
}; };
......
...@@ -31,6 +31,7 @@ static const struct ionic_stat_desc ionic_lif_stats_desc[] = { ...@@ -31,6 +31,7 @@ static const struct ionic_stat_desc ionic_lif_stats_desc[] = {
IONIC_LIF_STAT_DESC(xdp_aborted), IONIC_LIF_STAT_DESC(xdp_aborted),
IONIC_LIF_STAT_DESC(xdp_pass), IONIC_LIF_STAT_DESC(xdp_pass),
IONIC_LIF_STAT_DESC(xdp_tx), IONIC_LIF_STAT_DESC(xdp_tx),
IONIC_LIF_STAT_DESC(xdp_redirect),
IONIC_LIF_STAT_DESC(xdp_frames), IONIC_LIF_STAT_DESC(xdp_frames),
}; };
...@@ -159,6 +160,7 @@ static const struct ionic_stat_desc ionic_rx_stats_desc[] = { ...@@ -159,6 +160,7 @@ static const struct ionic_stat_desc ionic_rx_stats_desc[] = {
IONIC_RX_STAT_DESC(xdp_aborted), IONIC_RX_STAT_DESC(xdp_aborted),
IONIC_RX_STAT_DESC(xdp_pass), IONIC_RX_STAT_DESC(xdp_pass),
IONIC_RX_STAT_DESC(xdp_tx), IONIC_RX_STAT_DESC(xdp_tx),
IONIC_RX_STAT_DESC(xdp_redirect),
}; };
#define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc) #define IONIC_NUM_LIF_STATS ARRAY_SIZE(ionic_lif_stats_desc)
...@@ -200,6 +202,7 @@ static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num, ...@@ -200,6 +202,7 @@ static void ionic_add_lif_rxq_stats(struct ionic_lif *lif, int q_num,
stats->xdp_aborted += rxstats->xdp_aborted; stats->xdp_aborted += rxstats->xdp_aborted;
stats->xdp_pass += rxstats->xdp_pass; stats->xdp_pass += rxstats->xdp_pass;
stats->xdp_tx += rxstats->xdp_tx; stats->xdp_tx += rxstats->xdp_tx;
stats->xdp_redirect += rxstats->xdp_redirect;
} }
static void ionic_get_lif_stats(struct ionic_lif *lif, static void ionic_get_lif_stats(struct ionic_lif *lif,
......
...@@ -446,6 +446,20 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats, ...@@ -446,6 +446,20 @@ static bool ionic_run_xdp(struct ionic_rx_stats *stats,
break; break;
case XDP_REDIRECT: case XDP_REDIRECT:
/* unmap the pages before handing them to a different device */
dma_unmap_page(rxq->dev, buf_info->dma_addr,
IONIC_PAGE_SIZE, DMA_FROM_DEVICE);
err = xdp_do_redirect(netdev, &xdp_buf, xdp_prog);
if (err) {
netdev_dbg(netdev, "xdp_do_redirect err %d\n", err);
goto out_xdp_abort;
}
buf_info->page = NULL;
rxq->xdp_flush = true;
stats->xdp_redirect++;
break;
case XDP_ABORTED: case XDP_ABORTED:
default: default:
goto out_xdp_abort; goto out_xdp_abort;
...@@ -809,6 +823,14 @@ int ionic_tx_napi(struct napi_struct *napi, int budget) ...@@ -809,6 +823,14 @@ int ionic_tx_napi(struct napi_struct *napi, int budget)
return work_done; return work_done;
} }
static void ionic_xdp_do_flush(struct ionic_cq *cq)
{
if (cq->bound_q->xdp_flush) {
xdp_do_flush();
cq->bound_q->xdp_flush = false;
}
}
int ionic_rx_napi(struct napi_struct *napi, int budget) int ionic_rx_napi(struct napi_struct *napi, int budget)
{ {
struct ionic_qcq *qcq = napi_to_qcq(napi); struct ionic_qcq *qcq = napi_to_qcq(napi);
...@@ -829,6 +851,7 @@ int ionic_rx_napi(struct napi_struct *napi, int budget) ...@@ -829,6 +851,7 @@ int ionic_rx_napi(struct napi_struct *napi, int budget)
ionic_rx_fill(cq->bound_q); ionic_rx_fill(cq->bound_q);
ionic_xdp_do_flush(cq);
if (work_done < budget && napi_complete_done(napi, work_done)) { if (work_done < budget && napi_complete_done(napi, work_done)) {
ionic_dim_update(qcq, IONIC_LIF_F_RX_DIM_INTR); ionic_dim_update(qcq, IONIC_LIF_F_RX_DIM_INTR);
flags |= IONIC_INTR_CRED_UNMASK; flags |= IONIC_INTR_CRED_UNMASK;
...@@ -878,6 +901,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget) ...@@ -878,6 +901,7 @@ int ionic_txrx_napi(struct napi_struct *napi, int budget)
ionic_rx_fill(rxcq->bound_q); ionic_rx_fill(rxcq->bound_q);
ionic_xdp_do_flush(rxcq);
if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) { if (rx_work_done < budget && napi_complete_done(napi, rx_work_done)) {
ionic_dim_update(rxqcq, 0); ionic_dim_update(rxqcq, 0);
flags |= IONIC_INTR_CRED_UNMASK; flags |= IONIC_INTR_CRED_UNMASK;
......
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