Skip to content

Commit c41ced0

Browse files
LorenzoBianconiAlexei Starovoitov
authored andcommitted
net: mvneta: add frags support to XDP_TX
Introduce the capability to map non-linear xdp buffer running mvneta_xdp_submit_frame() for XDP_TX and XDP_REDIRECT Acked-by: Toke Hoiland-Jorgensen <[email protected]> Acked-by: John Fastabend <[email protected]> Signed-off-by: Lorenzo Bianconi <[email protected]> Link: https://lore.kernel.org/r/5d46ab63870ffe96fb95e6075a7ff0c81ef6424d.1642758637.git.lorenzo@kernel.org Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 7c48cb0 commit c41ced0

File tree

1 file changed

+76
-36
lines changed

1 file changed

+76
-36
lines changed

drivers/net/ethernet/marvell/mvneta.c

Lines changed: 76 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,8 +1884,8 @@ static void mvneta_txq_bufs_free(struct mvneta_port *pp,
18841884
bytes_compl += buf->skb->len;
18851885
pkts_compl++;
18861886
dev_kfree_skb_any(buf->skb);
1887-
} else if (buf->type == MVNETA_TYPE_XDP_TX ||
1888-
buf->type == MVNETA_TYPE_XDP_NDO) {
1887+
} else if ((buf->type == MVNETA_TYPE_XDP_TX ||
1888+
buf->type == MVNETA_TYPE_XDP_NDO) && buf->xdpf) {
18891889
if (napi && buf->type == MVNETA_TYPE_XDP_TX)
18901890
xdp_return_frame_rx_napi(buf->xdpf);
18911891
else
@@ -2079,47 +2079,87 @@ mvneta_xdp_put_buff(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
20792079

20802080
static int
20812081
mvneta_xdp_submit_frame(struct mvneta_port *pp, struct mvneta_tx_queue *txq,
2082-
struct xdp_frame *xdpf, bool dma_map)
2082+
struct xdp_frame *xdpf, int *nxmit_byte, bool dma_map)
20832083
{
2084-
struct mvneta_tx_desc *tx_desc;
2085-
struct mvneta_tx_buf *buf;
2086-
dma_addr_t dma_addr;
2084+
struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf);
2085+
struct device *dev = pp->dev->dev.parent;
2086+
struct mvneta_tx_desc *tx_desc = NULL;
2087+
int i, num_frames = 1;
2088+
struct page *page;
2089+
2090+
if (unlikely(xdp_frame_has_frags(xdpf)))
2091+
num_frames += sinfo->nr_frags;
20872092

2088-
if (txq->count >= txq->tx_stop_threshold)
2093+
if (txq->count + num_frames >= txq->size)
20892094
return MVNETA_XDP_DROPPED;
20902095

2091-
tx_desc = mvneta_txq_next_desc_get(txq);
2096+
for (i = 0; i < num_frames; i++) {
2097+
struct mvneta_tx_buf *buf = &txq->buf[txq->txq_put_index];
2098+
skb_frag_t *frag = NULL;
2099+
int len = xdpf->len;
2100+
dma_addr_t dma_addr;
20922101

2093-
buf = &txq->buf[txq->txq_put_index];
2094-
if (dma_map) {
2095-
/* ndo_xdp_xmit */
2096-
dma_addr = dma_map_single(pp->dev->dev.parent, xdpf->data,
2097-
xdpf->len, DMA_TO_DEVICE);
2098-
if (dma_mapping_error(pp->dev->dev.parent, dma_addr)) {
2099-
mvneta_txq_desc_put(txq);
2100-
return MVNETA_XDP_DROPPED;
2102+
if (unlikely(i)) { /* paged area */
2103+
frag = &sinfo->frags[i - 1];
2104+
len = skb_frag_size(frag);
21012105
}
2102-
buf->type = MVNETA_TYPE_XDP_NDO;
2103-
} else {
2104-
struct page *page = virt_to_page(xdpf->data);
21052106

2106-
dma_addr = page_pool_get_dma_addr(page) +
2107-
sizeof(*xdpf) + xdpf->headroom;
2108-
dma_sync_single_for_device(pp->dev->dev.parent, dma_addr,
2109-
xdpf->len, DMA_BIDIRECTIONAL);
2110-
buf->type = MVNETA_TYPE_XDP_TX;
2107+
tx_desc = mvneta_txq_next_desc_get(txq);
2108+
if (dma_map) {
2109+
/* ndo_xdp_xmit */
2110+
void *data;
2111+
2112+
data = unlikely(frag) ? skb_frag_address(frag)
2113+
: xdpf->data;
2114+
dma_addr = dma_map_single(dev, data, len,
2115+
DMA_TO_DEVICE);
2116+
if (dma_mapping_error(dev, dma_addr)) {
2117+
mvneta_txq_desc_put(txq);
2118+
goto unmap;
2119+
}
2120+
2121+
buf->type = MVNETA_TYPE_XDP_NDO;
2122+
} else {
2123+
page = unlikely(frag) ? skb_frag_page(frag)
2124+
: virt_to_page(xdpf->data);
2125+
dma_addr = page_pool_get_dma_addr(page);
2126+
if (unlikely(frag))
2127+
dma_addr += skb_frag_off(frag);
2128+
else
2129+
dma_addr += sizeof(*xdpf) + xdpf->headroom;
2130+
dma_sync_single_for_device(dev, dma_addr, len,
2131+
DMA_BIDIRECTIONAL);
2132+
buf->type = MVNETA_TYPE_XDP_TX;
2133+
}
2134+
buf->xdpf = unlikely(i) ? NULL : xdpf;
2135+
2136+
tx_desc->command = unlikely(i) ? 0 : MVNETA_TXD_F_DESC;
2137+
tx_desc->buf_phys_addr = dma_addr;
2138+
tx_desc->data_size = len;
2139+
*nxmit_byte += len;
2140+
2141+
mvneta_txq_inc_put(txq);
21112142
}
2112-
buf->xdpf = xdpf;
21132143

2114-
tx_desc->command = MVNETA_TXD_FLZ_DESC;
2115-
tx_desc->buf_phys_addr = dma_addr;
2116-
tx_desc->data_size = xdpf->len;
2144+
/*last descriptor */
2145+
if (likely(tx_desc))
2146+
tx_desc->command |= MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD;
21172147

2118-
mvneta_txq_inc_put(txq);
2119-
txq->pending++;
2120-
txq->count++;
2148+
txq->pending += num_frames;
2149+
txq->count += num_frames;
21212150

21222151
return MVNETA_XDP_TX;
2152+
2153+
unmap:
2154+
for (i--; i >= 0; i--) {
2155+
mvneta_txq_desc_put(txq);
2156+
tx_desc = txq->descs + txq->next_desc_to_proc;
2157+
dma_unmap_single(dev, tx_desc->buf_phys_addr,
2158+
tx_desc->data_size,
2159+
DMA_TO_DEVICE);
2160+
}
2161+
2162+
return MVNETA_XDP_DROPPED;
21232163
}
21242164

21252165
static int
@@ -2128,8 +2168,8 @@ mvneta_xdp_xmit_back(struct mvneta_port *pp, struct xdp_buff *xdp)
21282168
struct mvneta_pcpu_stats *stats = this_cpu_ptr(pp->stats);
21292169
struct mvneta_tx_queue *txq;
21302170
struct netdev_queue *nq;
2171+
int cpu, nxmit_byte = 0;
21312172
struct xdp_frame *xdpf;
2132-
int cpu;
21332173
u32 ret;
21342174

21352175
xdpf = xdp_convert_buff_to_frame(xdp);
@@ -2141,10 +2181,10 @@ mvneta_xdp_xmit_back(struct mvneta_port *pp, struct xdp_buff *xdp)
21412181
nq = netdev_get_tx_queue(pp->dev, txq->id);
21422182

21432183
__netif_tx_lock(nq, cpu);
2144-
ret = mvneta_xdp_submit_frame(pp, txq, xdpf, false);
2184+
ret = mvneta_xdp_submit_frame(pp, txq, xdpf, &nxmit_byte, false);
21452185
if (ret == MVNETA_XDP_TX) {
21462186
u64_stats_update_begin(&stats->syncp);
2147-
stats->es.ps.tx_bytes += xdpf->len;
2187+
stats->es.ps.tx_bytes += nxmit_byte;
21482188
stats->es.ps.tx_packets++;
21492189
stats->es.ps.xdp_tx++;
21502190
u64_stats_update_end(&stats->syncp);
@@ -2183,11 +2223,11 @@ mvneta_xdp_xmit(struct net_device *dev, int num_frame,
21832223

21842224
__netif_tx_lock(nq, cpu);
21852225
for (i = 0; i < num_frame; i++) {
2186-
ret = mvneta_xdp_submit_frame(pp, txq, frames[i], true);
2226+
ret = mvneta_xdp_submit_frame(pp, txq, frames[i], &nxmit_byte,
2227+
true);
21872228
if (ret != MVNETA_XDP_TX)
21882229
break;
21892230

2190-
nxmit_byte += frames[i]->len;
21912231
nxmit++;
21922232
}
21932233

0 commit comments

Comments
 (0)