| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | From f6413a7e32d1f98a258e0ed9abd4df3159902fd3 Mon Sep 17 00:00:00 2001 |
| 2 | From: Camelia Groza <camelia.groza@nxp.com> |
| 3 | Date: Mon, 4 Sep 2017 13:57:21 +0300 |
| 4 | Subject: [PATCH] sdk_dpaa: ls1043a errata: verify and resize headroom |
| 5 | alignment |
| 6 | |
| 7 | If the skb's headroom isn't aligned to 16 bytes, reallocate the entire |
| 8 | skb and resize its headroom to priv->tx_headroom. Update the pointers |
| 9 | to the network and transport headers accordingly. |
| 10 | |
| 11 | Signed-off-by: Camelia Groza <camelia.groza@nxp.com> |
| 12 | --- |
| 13 | .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 38 +++++++++++++++------- |
| 14 | 1 file changed, 27 insertions(+), 11 deletions(-) |
| 15 | |
| 16 | --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c |
| 17 | +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c |
| 18 | @@ -742,14 +742,19 @@ int __hot skb_to_contig_fd(struct dpa_pr |
| 19 | EXPORT_SYMBOL(skb_to_contig_fd); |
| 20 | |
| 21 | #ifndef CONFIG_PPC |
| 22 | -/* Verify the conditions that trigger the A010022 errata: 4K memory address |
| 23 | - * crossings. |
| 24 | +/* Verify the conditions that trigger the A010022 errata: data unaligned to |
| 25 | + * 16 bytes and 4K memory address crossings. |
| 26 | */ |
| 27 | -bool a010022_check_skb(struct sk_buff *skb) |
| 28 | +static bool a010022_check_skb(struct sk_buff *skb, struct dpa_priv_s *priv) |
| 29 | { |
| 30 | int nr_frags, i = 0; |
| 31 | skb_frag_t *frag; |
| 32 | |
| 33 | + /* Check if the headroom is aligned */ |
| 34 | + if (((u16)skb->data - priv->tx_headroom) % |
| 35 | + priv->buf_layout[TX].data_align != 0) |
| 36 | + return true; |
| 37 | + |
| 38 | /* Check if the headroom crosses a boundary */ |
| 39 | if (HAS_DMA_ISSUE(skb->head, skb_headroom(skb))) |
| 40 | return true; |
| 41 | @@ -767,7 +772,7 @@ bool a010022_check_skb(struct sk_buff *s |
| 42 | while (i < nr_frags) { |
| 43 | frag = &skb_shinfo(skb)->frags[i]; |
| 44 | |
| 45 | - /* Check if the paged fragment crosses a boundary from its |
| 46 | + /* Check if a paged fragment crosses a boundary from its |
| 47 | * offset to its end. |
| 48 | */ |
| 49 | if (HAS_DMA_ISSUE(frag->page_offset, frag->size)) |
| 50 | @@ -783,13 +788,17 @@ bool a010022_check_skb(struct sk_buff *s |
| 51 | * page. Build a new skb around the new buffer and release the old one. |
| 52 | * A performance drop should be expected. |
| 53 | */ |
| 54 | -struct sk_buff *a010022_realign_skb(struct sk_buff *skb) |
| 55 | +static struct sk_buff *a010022_realign_skb(struct sk_buff *skb, |
| 56 | + struct dpa_priv_s *priv) |
| 57 | { |
| 58 | - int headroom = skb_headroom(skb); |
| 59 | + int trans_offset = skb_transport_offset(skb); |
| 60 | + int net_offset = skb_network_offset(skb); |
| 61 | struct sk_buff *nskb = NULL; |
| 62 | + int nsize, headroom; |
| 63 | struct page *npage; |
| 64 | void *npage_addr; |
| 65 | - int nsize; |
| 66 | + |
| 67 | + headroom = priv->tx_headroom; |
| 68 | |
| 69 | npage = alloc_page(GFP_ATOMIC); |
| 70 | if (unlikely(!npage)) { |
| 71 | @@ -822,6 +831,13 @@ struct sk_buff *a010022_realign_skb(stru |
| 72 | } |
| 73 | copy_skb_header(nskb, skb); |
| 74 | |
| 75 | + /* We move the headroom when we align it so we have to reset the |
| 76 | + * network and transport header offsets relative to the new data |
| 77 | + * pointer. The checksum offload relies on these offsets. |
| 78 | + */ |
| 79 | + skb_set_network_header(nskb, net_offset); |
| 80 | + skb_set_transport_header(nskb, trans_offset); |
| 81 | + |
| 82 | dev_kfree_skb(skb); |
| 83 | return nskb; |
| 84 | |
| 85 | @@ -1024,8 +1040,8 @@ int __hot dpa_tx_extended(struct sk_buff |
| 86 | #endif /* CONFIG_FSL_DPAA_TS */ |
| 87 | |
| 88 | #ifndef CONFIG_PPC |
| 89 | - if (unlikely(dpaa_errata_a010022) && a010022_check_skb(skb)) { |
| 90 | - skb = a010022_realign_skb(skb); |
| 91 | + if (unlikely(dpaa_errata_a010022) && a010022_check_skb(skb, priv)) { |
| 92 | + skb = a010022_realign_skb(skb, priv); |
| 93 | if (!skb) |
| 94 | goto skb_to_fd_failed; |
| 95 | } |
| 96 | @@ -1072,8 +1088,8 @@ int __hot dpa_tx_extended(struct sk_buff |
| 97 | skb = nskb; |
| 98 | #ifndef CONFIG_PPC |
| 99 | if (unlikely(dpaa_errata_a010022) && |
| 100 | - a010022_check_skb(skb)) { |
| 101 | - skb = realign_skb(skb); |
| 102 | + a010022_check_skb(skb, priv)) { |
| 103 | + skb = a010022_realign_skb(skb, priv); |
| 104 | if (!skb) |
| 105 | goto skb_to_fd_failed; |
| 106 | } |