Skip to content

Commit

Permalink
nfp: fix issue of skb segments exceeds descriptor limitation
Browse files Browse the repository at this point in the history
TCP packets will be dropped if the segments number in the tx skb
exceeds limitation when sending iperf3 traffic with --zerocopy option.

we make the following changes:

Get nr_frags in nfp_nfdk_tx_maybe_close_block instead of passing from
outside because it will be changed after skb_linearize operation.

Fill maximum dma_len in first tx descriptor to make sure the whole
head is included in the first descriptor.

Fixes: c10d12e ("nfp: add support for NFDK data path")
Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com>
Reviewed-by: Louis Peens <louis.peens@corigine.com>
Signed-off-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Baowen Zheng authored and David S. Miller committed Jul 9, 2022
1 parent 6676d72 commit 9c840d5
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions drivers/net/ethernet/netronome/nfp/nfdk/dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,18 @@ nfp_nfdk_tx_csum(struct nfp_net_dp *dp, struct nfp_net_r_vector *r_vec,

static int
nfp_nfdk_tx_maybe_close_block(struct nfp_net_tx_ring *tx_ring,
unsigned int nr_frags, struct sk_buff *skb)
struct sk_buff *skb)
{
unsigned int n_descs, wr_p, nop_slots;
const skb_frag_t *frag, *fend;
struct nfp_nfdk_tx_desc *txd;
unsigned int nr_frags;
unsigned int wr_idx;
int err;

recount_descs:
n_descs = nfp_nfdk_headlen_to_segs(skb_headlen(skb));

nr_frags = skb_shinfo(skb)->nr_frags;
frag = skb_shinfo(skb)->frags;
fend = frag + nr_frags;
for (; frag < fend; frag++)
Expand Down Expand Up @@ -281,10 +282,13 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)
if (unlikely((int)metadata < 0))
goto err_flush;

nr_frags = skb_shinfo(skb)->nr_frags;
if (nfp_nfdk_tx_maybe_close_block(tx_ring, nr_frags, skb))
if (nfp_nfdk_tx_maybe_close_block(tx_ring, skb))
goto err_flush;

/* nr_frags will change after skb_linearize so we get nr_frags after
* nfp_nfdk_tx_maybe_close_block function
*/
nr_frags = skb_shinfo(skb)->nr_frags;
/* DMA map all */
wr_idx = D_IDX(tx_ring, tx_ring->wr_p);
txd = &tx_ring->ktxds[wr_idx];
Expand All @@ -310,7 +314,16 @@ netdev_tx_t nfp_nfdk_tx(struct sk_buff *skb, struct net_device *netdev)

/* FIELD_PREP() implicitly truncates to chunk */
dma_len -= 1;
dlen_type = FIELD_PREP(NFDK_DESC_TX_DMA_LEN_HEAD, dma_len) |

/* We will do our best to pass as much data as we can in descriptor
* and we need to make sure the first descriptor includes whole head
* since there is limitation in firmware side. Sometimes the value of
* dma_len bitwise and NFDK_DESC_TX_DMA_LEN_HEAD will less than
* headlen.
*/
dlen_type = FIELD_PREP(NFDK_DESC_TX_DMA_LEN_HEAD,
dma_len > NFDK_DESC_TX_DMA_LEN_HEAD ?
NFDK_DESC_TX_DMA_LEN_HEAD : dma_len) |
FIELD_PREP(NFDK_DESC_TX_TYPE_HEAD, type);

txd->dma_len_type = cpu_to_le16(dlen_type);
Expand Down Expand Up @@ -925,7 +938,9 @@ nfp_nfdk_tx_xdp_buf(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring,

/* FIELD_PREP() implicitly truncates to chunk */
dma_len -= 1;
dlen_type = FIELD_PREP(NFDK_DESC_TX_DMA_LEN_HEAD, dma_len) |
dlen_type = FIELD_PREP(NFDK_DESC_TX_DMA_LEN_HEAD,
dma_len > NFDK_DESC_TX_DMA_LEN_HEAD ?
NFDK_DESC_TX_DMA_LEN_HEAD : dma_len) |
FIELD_PREP(NFDK_DESC_TX_TYPE_HEAD, type);

txd->dma_len_type = cpu_to_le16(dlen_type);
Expand Down Expand Up @@ -1303,7 +1318,7 @@ nfp_nfdk_ctrl_tx_one(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
skb_push(skb, 4));
}

if (nfp_nfdk_tx_maybe_close_block(tx_ring, 0, skb))
if (nfp_nfdk_tx_maybe_close_block(tx_ring, skb))
goto err_free;

/* DMA map all */
Expand All @@ -1328,7 +1343,9 @@ nfp_nfdk_ctrl_tx_one(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
txbuf++;

dma_len -= 1;
dlen_type = FIELD_PREP(NFDK_DESC_TX_DMA_LEN_HEAD, dma_len) |
dlen_type = FIELD_PREP(NFDK_DESC_TX_DMA_LEN_HEAD,
dma_len > NFDK_DESC_TX_DMA_LEN_HEAD ?
NFDK_DESC_TX_DMA_LEN_HEAD : dma_len) |
FIELD_PREP(NFDK_DESC_TX_TYPE_HEAD, type);

txd->dma_len_type = cpu_to_le16(dlen_type);
Expand Down

0 comments on commit 9c840d5

Please sign in to comment.