[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <pj41zl1rjfqslp.fsf@u68c7b5b1d2d758.ant.amazon.com>
Date: Sun, 6 Sep 2020 10:20:18 +0300
From: Shay Agroskin <shayagr@...zon.com>
To: Lorenzo Bianconi <lorenzo@...nel.org>
CC: <netdev@...r.kernel.org>, <bpf@...r.kernel.org>,
<davem@...emloft.net>, <lorenzo.bianconi@...hat.com>,
<brouer@...hat.com>, <echaudro@...hat.com>, <sameehj@...zon.com>,
<kuba@...nel.org>, <john.fastabend@...il.com>,
<daniel@...earbox.net>, <ast@...nel.org>
Subject: Re: [PATCH v2 net-next 5/9] net: mvneta: add multi buffer support to XDP_TX
Lorenzo Bianconi <lorenzo@...nel.org> writes:
> Introduce the capability to map non-linear xdp buffer running
> mvneta_xdp_submit_frame() for XDP_TX and XDP_REDIRECT
>
> Signed-off-by: Lorenzo Bianconi <lorenzo@...nel.org>
> ---
> drivers/net/ethernet/marvell/mvneta.c | 79
> +++++++++++++++++----------
> 1 file changed, 49 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/mvneta.c
> b/drivers/net/ethernet/marvell/mvneta.c
> index 4f745a2b702a..65fbed957e4f 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -1854,8 +1854,8 @@ static void mvneta_txq_bufs_free(struct
> mvneta_port *pp,
> bytes_compl += buf->skb->len;
> pkts_compl++;
> dev_kfree_skb_any(buf->skb);
> - } else if (buf->type == MVNETA_TYPE_XDP_TX ||
> - buf->type == MVNETA_TYPE_XDP_NDO) {
> + } else if ((buf->type == MVNETA_TYPE_XDP_TX ||
> + buf->type == MVNETA_TYPE_XDP_NDO) &&
> buf->xdpf) {
> xdp_return_frame(buf->xdpf);
> }
> }
> @@ -2040,43 +2040,62 @@ static int
> mvneta_xdp_submit_frame(struct mvneta_port *pp, struct
> mvneta_tx_queue *txq,
> struct xdp_frame *xdpf, bool dma_map)
> {
> - struct mvneta_tx_desc *tx_desc;
> - struct mvneta_tx_buf *buf;
> - dma_addr_t dma_addr;
> + struct skb_shared_info *sinfo =
> xdp_get_shared_info_from_frame(xdpf);
> + int i, num_frames = xdpf->mb ? sinfo->nr_frags + 1 : 1;
> + struct mvneta_tx_desc *tx_desc = NULL;
> + struct page *page;
>
> - if (txq->count >= txq->tx_stop_threshold)
> + if (txq->count + num_frames >= txq->tx_stop_threshold)
> return MVNETA_XDP_DROPPED;
>
> - tx_desc = mvneta_txq_next_desc_get(txq);
> + for (i = 0; i < num_frames; i++) {
> + struct mvneta_tx_buf *buf =
> &txq->buf[txq->txq_put_index];
> + skb_frag_t *frag = i ? &sinfo->frags[i - 1] :
> NULL;
> + int len = frag ? skb_frag_size(frag) : xdpf->len;
> + dma_addr_t dma_addr;
>
> - buf = &txq->buf[txq->txq_put_index];
> - if (dma_map) {
> - /* ndo_xdp_xmit */
> - dma_addr = dma_map_single(pp->dev->dev.parent,
> xdpf->data,
> - xdpf->len,
> DMA_TO_DEVICE);
> - if (dma_mapping_error(pp->dev->dev.parent,
> dma_addr)) {
> - mvneta_txq_desc_put(txq);
> - return MVNETA_XDP_DROPPED;
> + tx_desc = mvneta_txq_next_desc_get(txq);
> + if (dma_map) {
> + /* ndo_xdp_xmit */
> + void *data;
> +
> + data = frag ?
> page_address(skb_frag_page(frag))
> + : xdpf->data;
> + dma_addr =
> dma_map_single(pp->dev->dev.parent, data,
> + len,
> DMA_TO_DEVICE);
> + if (dma_mapping_error(pp->dev->dev.parent,
> dma_addr)) {
> + for (; i >= 0; i--)
> + mvneta_txq_desc_put(txq);
> + return MVNETA_XDP_DROPPED;
> + }
> + buf->type = MVNETA_TYPE_XDP_NDO;
> + } else {
> + page = frag ? skb_frag_page(frag)
> + : virt_to_page(xdpf->data);
> + dma_addr = page_pool_get_dma_addr(page);
> + if (!frag)
> + dma_addr += sizeof(*xdpf) +
> xdpf->headroom;
> +
> dma_sync_single_for_device(pp->dev->dev.parent,
> + dma_addr, len,
> +
> DMA_BIDIRECTIONAL);
> + buf->type = MVNETA_TYPE_XDP_TX;
> }
> - buf->type = MVNETA_TYPE_XDP_NDO;
> - } else {
> - struct page *page = virt_to_page(xdpf->data);
> + buf->xdpf = i ? NULL : xdpf;
>
> - dma_addr = page_pool_get_dma_addr(page) +
> - sizeof(*xdpf) + xdpf->headroom;
> - dma_sync_single_for_device(pp->dev->dev.parent,
> dma_addr,
> - xdpf->len,
> DMA_BIDIRECTIONAL);
> - buf->type = MVNETA_TYPE_XDP_TX;
> + if (!i)
> + tx_desc->command = MVNETA_TXD_F_DESC;
> + tx_desc->buf_phys_addr = dma_addr;
> + tx_desc->data_size = len;
> +
> + mvneta_txq_inc_put(txq);
> }
> - buf->xdpf = xdpf;
>
> - tx_desc->command = MVNETA_TXD_FLZ_DESC;
> - tx_desc->buf_phys_addr = dma_addr;
> - tx_desc->data_size = xdpf->len;
> + /*last descriptor */
> + if (tx_desc)
> + tx_desc->command |= MVNETA_TXD_L_DESC |
> MVNETA_TXD_Z_PAD;
When is this condition not taken ? You initialize tx_desc
to NULL, but it seems to me like you always set it inside
the for loop to the output of mvneta_txq_next_desc_get()
which doesn't look like it returns NULL. The for loop runs 1 iteration or `sinfo->nr_frage
+ 1` iterations (which also equals or larger than 1).
>
> - mvneta_txq_inc_put(txq);
> - txq->pending++;
> - txq->count++;
> + txq->pending += num_frames;
> + txq->count += num_frames;
>
> return MVNETA_XDP_TX;
> }
Powered by blists - more mailing lists