Commit 700f11eb authored by Horatiu Vultur's avatar Horatiu Vultur Committed by Jakub Kicinski

lan966x: Don't use xdp_frame when action is XDP_TX

When the action of an xdp program was XDP_TX, lan966x was creating
a xdp_frame and use this one to send the frame back. But it is also
possible to send back the frame without needing a xdp_frame, because
it is possible to send it back using the page.
And then once the frame is transmitted is possible to use directly
page_pool_recycle_direct as lan966x is using page pools.
This would save some CPU usage on this path, which results in higher
number of transmitted frames. Bellow are the statistics:
Frame size:    Improvement:
64                ~8%
256              ~11%
512               ~8%
1000              ~0%
1500              ~0%
Signed-off-by: default avatarHoratiu Vultur <horatiu.vultur@microchip.com>
Reviewed-by: default avatarAlexander Lobakin <aleksander.lobakin@intel.com>
Link: https://lore.kernel.org/r/20230422142344.3630602-1-horatiu.vultur@microchip.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent ee3392ed
...@@ -390,6 +390,7 @@ static void lan966x_fdma_stop_netdev(struct lan966x *lan966x) ...@@ -390,6 +390,7 @@ static void lan966x_fdma_stop_netdev(struct lan966x *lan966x)
static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight) static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)
{ {
struct lan966x_tx *tx = &lan966x->tx; struct lan966x_tx *tx = &lan966x->tx;
struct lan966x_rx *rx = &lan966x->rx;
struct lan966x_tx_dcb_buf *dcb_buf; struct lan966x_tx_dcb_buf *dcb_buf;
struct xdp_frame_bulk bq; struct xdp_frame_bulk bq;
struct lan966x_db *db; struct lan966x_db *db;
...@@ -432,7 +433,8 @@ static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight) ...@@ -432,7 +433,8 @@ static void lan966x_fdma_tx_clear_buf(struct lan966x *lan966x, int weight)
if (dcb_buf->xdp_ndo) if (dcb_buf->xdp_ndo)
xdp_return_frame_bulk(dcb_buf->data.xdpf, &bq); xdp_return_frame_bulk(dcb_buf->data.xdpf, &bq);
else else
xdp_return_frame_rx_napi(dcb_buf->data.xdpf); page_pool_recycle_direct(rx->page_pool,
dcb_buf->data.page);
} }
clear = true; clear = true;
...@@ -699,15 +701,14 @@ static void lan966x_fdma_tx_start(struct lan966x_tx *tx, int next_to_use) ...@@ -699,15 +701,14 @@ static void lan966x_fdma_tx_start(struct lan966x_tx *tx, int next_to_use)
tx->last_in_use = next_to_use; tx->last_in_use = next_to_use;
} }
int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, void *ptr, u32 len)
struct xdp_frame *xdpf,
struct page *page,
bool dma_map)
{ {
struct lan966x *lan966x = port->lan966x; struct lan966x *lan966x = port->lan966x;
struct lan966x_tx_dcb_buf *next_dcb_buf; struct lan966x_tx_dcb_buf *next_dcb_buf;
struct lan966x_tx *tx = &lan966x->tx; struct lan966x_tx *tx = &lan966x->tx;
struct xdp_frame *xdpf;
dma_addr_t dma_addr; dma_addr_t dma_addr;
struct page *page;
int next_to_use; int next_to_use;
__be32 *ifh; __be32 *ifh;
int ret = 0; int ret = 0;
...@@ -722,8 +723,13 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, ...@@ -722,8 +723,13 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port,
goto out; goto out;
} }
/* Get the next buffer */
next_dcb_buf = &tx->dcbs_buf[next_to_use];
/* Generate new IFH */ /* Generate new IFH */
if (dma_map) { if (!len) {
xdpf = ptr;
if (xdpf->headroom < IFH_LEN_BYTES) { if (xdpf->headroom < IFH_LEN_BYTES) {
ret = NETDEV_TX_OK; ret = NETDEV_TX_OK;
goto out; goto out;
...@@ -743,11 +749,16 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, ...@@ -743,11 +749,16 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port,
goto out; goto out;
} }
next_dcb_buf->data.xdpf = xdpf;
next_dcb_buf->len = xdpf->len + IFH_LEN_BYTES;
/* Setup next dcb */ /* Setup next dcb */
lan966x_fdma_tx_setup_dcb(tx, next_to_use, lan966x_fdma_tx_setup_dcb(tx, next_to_use,
xdpf->len + IFH_LEN_BYTES, xdpf->len + IFH_LEN_BYTES,
dma_addr); dma_addr);
} else { } else {
page = ptr;
ifh = page_address(page) + XDP_PACKET_HEADROOM; ifh = page_address(page) + XDP_PACKET_HEADROOM;
memset(ifh, 0x0, sizeof(__be32) * IFH_LEN); memset(ifh, 0x0, sizeof(__be32) * IFH_LEN);
lan966x_ifh_set_bypass(ifh, 1); lan966x_ifh_set_bypass(ifh, 1);
...@@ -756,21 +767,21 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, ...@@ -756,21 +767,21 @@ int lan966x_fdma_xmit_xdpf(struct lan966x_port *port,
dma_addr = page_pool_get_dma_addr(page); dma_addr = page_pool_get_dma_addr(page);
dma_sync_single_for_device(lan966x->dev, dma_sync_single_for_device(lan966x->dev,
dma_addr + XDP_PACKET_HEADROOM, dma_addr + XDP_PACKET_HEADROOM,
xdpf->len + IFH_LEN_BYTES, len + IFH_LEN_BYTES,
DMA_TO_DEVICE); DMA_TO_DEVICE);
next_dcb_buf->data.page = page;
next_dcb_buf->len = len + IFH_LEN_BYTES;
/* Setup next dcb */ /* Setup next dcb */
lan966x_fdma_tx_setup_dcb(tx, next_to_use, lan966x_fdma_tx_setup_dcb(tx, next_to_use,
xdpf->len + IFH_LEN_BYTES, len + IFH_LEN_BYTES,
dma_addr + XDP_PACKET_HEADROOM); dma_addr + XDP_PACKET_HEADROOM);
} }
/* Fill up the buffer */ /* Fill up the buffer */
next_dcb_buf = &tx->dcbs_buf[next_to_use];
next_dcb_buf->use_skb = false; next_dcb_buf->use_skb = false;
next_dcb_buf->data.xdpf = xdpf; next_dcb_buf->xdp_ndo = !len;
next_dcb_buf->xdp_ndo = dma_map;
next_dcb_buf->len = xdpf->len + IFH_LEN_BYTES;
next_dcb_buf->dma_addr = dma_addr; next_dcb_buf->dma_addr = dma_addr;
next_dcb_buf->used = true; next_dcb_buf->used = true;
next_dcb_buf->ptp = false; next_dcb_buf->ptp = false;
......
...@@ -243,6 +243,7 @@ struct lan966x_tx_dcb_buf { ...@@ -243,6 +243,7 @@ struct lan966x_tx_dcb_buf {
union { union {
struct sk_buff *skb; struct sk_buff *skb;
struct xdp_frame *xdpf; struct xdp_frame *xdpf;
struct page *page;
} data; } data;
u32 len; u32 len;
u32 used : 1; u32 used : 1;
...@@ -541,10 +542,7 @@ int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr); ...@@ -541,10 +542,7 @@ int lan966x_ptp_setup_traps(struct lan966x_port *port, struct ifreq *ifr);
int lan966x_ptp_del_traps(struct lan966x_port *port); int lan966x_ptp_del_traps(struct lan966x_port *port);
int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev); int lan966x_fdma_xmit(struct sk_buff *skb, __be32 *ifh, struct net_device *dev);
int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, int lan966x_fdma_xmit_xdpf(struct lan966x_port *port, void *ptr, u32 len);
struct xdp_frame *frame,
struct page *page,
bool dma_map);
int lan966x_fdma_change_mtu(struct lan966x *lan966x); int lan966x_fdma_change_mtu(struct lan966x *lan966x);
void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *dev); void lan966x_fdma_netdev_init(struct lan966x *lan966x, struct net_device *dev);
void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device *dev); void lan966x_fdma_netdev_deinit(struct lan966x *lan966x, struct net_device *dev);
......
...@@ -62,7 +62,7 @@ int lan966x_xdp_xmit(struct net_device *dev, ...@@ -62,7 +62,7 @@ int lan966x_xdp_xmit(struct net_device *dev,
struct xdp_frame *xdpf = frames[i]; struct xdp_frame *xdpf = frames[i];
int err; int err;
err = lan966x_fdma_xmit_xdpf(port, xdpf, NULL, true); err = lan966x_fdma_xmit_xdpf(port, xdpf, 0);
if (err) if (err)
break; break;
...@@ -76,7 +76,6 @@ int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len) ...@@ -76,7 +76,6 @@ int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len)
{ {
struct bpf_prog *xdp_prog = port->xdp_prog; struct bpf_prog *xdp_prog = port->xdp_prog;
struct lan966x *lan966x = port->lan966x; struct lan966x *lan966x = port->lan966x;
struct xdp_frame *xdpf;
struct xdp_buff xdp; struct xdp_buff xdp;
u32 act; u32 act;
...@@ -90,11 +89,8 @@ int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len) ...@@ -90,11 +89,8 @@ int lan966x_xdp_run(struct lan966x_port *port, struct page *page, u32 data_len)
case XDP_PASS: case XDP_PASS:
return FDMA_PASS; return FDMA_PASS;
case XDP_TX: case XDP_TX:
xdpf = xdp_convert_buff_to_frame(&xdp); return lan966x_fdma_xmit_xdpf(port, page,
if (!xdpf) data_len - IFH_LEN_BYTES) ?
return FDMA_DROP;
return lan966x_fdma_xmit_xdpf(port, xdpf, page, false) ?
FDMA_DROP : FDMA_TX; FDMA_DROP : FDMA_TX;
case XDP_REDIRECT: case XDP_REDIRECT:
if (xdp_do_redirect(port->dev, &xdp, xdp_prog)) if (xdp_do_redirect(port->dev, &xdp, xdp_prog))
......
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