mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
Merge branch 'bnxt_en-fix-max_skb_frags-30'
Michael Chan says: ==================== bnxt_en: Fix MAX_SKB_FRAGS > 30 The driver was written with the assumption that MAX_SKB_FRAGS could not exceed what the NIC can support. About 2 years ago, CONFIG_MAX_SKB_FRAGS was added. The value can exceed what the NIC can support and it may cause TX timeout. These 2 patches will fix the issue. ==================== Link: https://patch.msgid.link/20250321211639.3812992-1-michael.chan@broadcom.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
7011ba337d
|
|
@ -485,6 +485,17 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
txr = &bp->tx_ring[bp->tx_ring_map[i]];
|
||||
prod = txr->tx_prod;
|
||||
|
||||
#if (MAX_SKB_FRAGS > TX_MAX_FRAGS)
|
||||
if (skb_shinfo(skb)->nr_frags > TX_MAX_FRAGS) {
|
||||
netdev_warn_once(dev, "SKB has too many (%d) fragments, max supported is %d. SKB will be linearized.\n",
|
||||
skb_shinfo(skb)->nr_frags, TX_MAX_FRAGS);
|
||||
if (skb_linearize(skb)) {
|
||||
dev_kfree_skb_any(skb);
|
||||
dev_core_stats_tx_dropped_inc(dev);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
free_size = bnxt_tx_avail(bp, txr);
|
||||
if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) {
|
||||
/* We must have raced with NAPI cleanup */
|
||||
|
|
@ -564,7 +575,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
TX_BD_FLAGS_LHINT_512_AND_SMALLER |
|
||||
TX_BD_FLAGS_COAL_NOW |
|
||||
TX_BD_FLAGS_PACKET_END |
|
||||
(2 << TX_BD_FLAGS_BD_CNT_SHIFT));
|
||||
TX_BD_CNT(2));
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
tx_push1->tx_bd_hsize_lflags =
|
||||
|
|
@ -639,7 +650,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|||
|
||||
dma_unmap_addr_set(tx_buf, mapping, mapping);
|
||||
flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD |
|
||||
((last_frag + 2) << TX_BD_FLAGS_BD_CNT_SHIFT);
|
||||
TX_BD_CNT(last_frag + 2);
|
||||
|
||||
txbd->tx_bd_haddr = cpu_to_le64(mapping);
|
||||
txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 2 + last_frag);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,12 @@ struct tx_bd {
|
|||
#define TX_OPAQUE_PROD(bp, opq) ((TX_OPAQUE_IDX(opq) + TX_OPAQUE_BDS(opq)) &\
|
||||
(bp)->tx_ring_mask)
|
||||
|
||||
#define TX_BD_CNT(n) (((n) << TX_BD_FLAGS_BD_CNT_SHIFT) & TX_BD_FLAGS_BD_CNT)
|
||||
|
||||
#define TX_MAX_BD_CNT 32
|
||||
|
||||
#define TX_MAX_FRAGS (TX_MAX_BD_CNT - 2)
|
||||
|
||||
struct tx_bd_ext {
|
||||
__le32 tx_bd_hsize_lflags;
|
||||
#define TX_BD_FLAGS_TCP_UDP_CHKSUM (1 << 0)
|
||||
|
|
|
|||
|
|
@ -48,8 +48,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
|
|||
tx_buf->page = virt_to_head_page(xdp->data);
|
||||
|
||||
txbd = &txr->tx_desc_ring[TX_RING(bp, prod)][TX_IDX(prod)];
|
||||
flags = (len << TX_BD_LEN_SHIFT) |
|
||||
((num_frags + 1) << TX_BD_FLAGS_BD_CNT_SHIFT) |
|
||||
flags = (len << TX_BD_LEN_SHIFT) | TX_BD_CNT(num_frags + 1) |
|
||||
bnxt_lhint_arr[len >> 9];
|
||||
txbd->tx_bd_len_flags_type = cpu_to_le32(flags);
|
||||
txbd->tx_bd_opaque = SET_TX_OPAQUE(bp, txr, prod, 1 + num_frags);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user