684d04b2561c75366ac6fad76af85737cd85a4a9
[openwrt/staging/mkresin.git] /
1 From e89db675171a7a12f19b6ec0089a9cc62807cdf1 Mon Sep 17 00:00:00 2001
2 From: Camelia Groza <camelia.groza@nxp.com>
3 Date: Tue, 29 Oct 2019 16:34:08 +0200
4 Subject: [PATCH] sdk_dpaa: ls1043a errata: update and optimize the
5 restrictions
6
7 An skb is in no danger of triggering the errata under the following
8 conditions:
9 - the paged data doesn't cross a 4K page boundary OR the linear data
10 is aligned to 256 bytes when crossing a 4K page boundary
11 - the linear and the paged data are 16 byte aligned
12 - the paged data is a multiple of 16 bytes in size
13
14 Optimize the detection for each skb that might trigger the errata. Parse
15 the skb twice, at most, and realign it only once.
16
17 Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
18 ---
19 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h | 2 +-
20 .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c | 147 +++++++++++++++------
21 2 files changed, 111 insertions(+), 38 deletions(-)
22
23 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h
24 +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h
25 @@ -662,7 +662,7 @@ static inline void _dpa_bp_free_pf(void
26 #ifndef CONFIG_PPC
27 extern bool dpaa_errata_a010022; /* SoC affected by A010022 errata */
28 #define NONREC_MARK 0x01
29 -#define HAS_DMA_ISSUE(start, size) \
30 +#define CROSS_4K(start, size) \
31 (((uintptr_t)(start) + (size)) > \
32 (((uintptr_t)(start) + 0x1000) & ~0xFFF))
33 /* The headroom needs to accommodate our private data (64 bytes) but
34 --- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c
35 +++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c
36 @@ -771,32 +771,73 @@ int __hot skb_to_contig_fd(struct dpa_pr
37 EXPORT_SYMBOL(skb_to_contig_fd);
38
39 #ifndef CONFIG_PPC
40 -/* Verify the conditions that trigger the A010022 errata: data unaligned to
41 - * 16 bytes, 4K memory address crossings and S/G fragments.
42 +/* Verify the conditions that trigger the A010022 errata:
43 + * - 4K memory address boundary crossings when the data/SG fragments aren't
44 + * aligned to 256 bytes
45 + * - data and SG fragments that aren't aligned to 16 bytes
46 + * - SG fragments that aren't mod 16 bytes in size (except for the last
47 + * fragment)
48 */
49 static bool a010022_check_skb(struct sk_buff *skb, struct dpa_priv_s *priv)
50 {
51 - /* Check if the headroom is aligned */
52 - if (((uintptr_t)skb->data - priv->tx_headroom) %
53 - priv->buf_layout[TX].data_align != 0)
54 - return true;
55 + skb_frag_t *frag;
56 + int i, nr_frags;
57
58 - /* Check for paged data in the skb. We do not support S/G fragments */
59 - if (skb_is_nonlinear(skb))
60 + nr_frags = skb_shinfo(skb)->nr_frags;
61 +
62 + /* Check if the linear data is 16 byte aligned */
63 + if ((uintptr_t)skb->data % 16)
64 return true;
65
66 - /* Check if the headroom crosses a boundary */
67 - if (HAS_DMA_ISSUE(skb->head, skb_headroom(skb)))
68 + /* Check if the needed headroom crosses a 4K address boundary without
69 + * being 256 byte aligned
70 + */
71 + if (CROSS_4K(skb->data - priv->tx_headroom, priv->tx_headroom) &&
72 + (((uintptr_t)skb->data - priv->tx_headroom) % 256))
73 return true;
74
75 - /* Check if the non-paged data crosses a boundary */
76 - if (HAS_DMA_ISSUE(skb->data, skb_headlen(skb)))
77 + /* Check if the linear data crosses a 4K address boundary without
78 + * being 256 byte aligned
79 + */
80 + if (CROSS_4K(skb->data, skb_headlen(skb)) &&
81 + ((uintptr_t)skb->data % 256))
82 return true;
83
84 - /* Check if the entire linear skb crosses a boundary */
85 - if (HAS_DMA_ISSUE(skb->head, skb_end_offset(skb)))
86 + /* When using Scatter/Gather, the linear data becomes the first
87 + * fragment in the list and must follow the same restrictions as the
88 + * other fragments.
89 + *
90 + * Check if the linear data is mod 16 bytes in size.
91 + */
92 + if (nr_frags && (skb_headlen(skb) % 16))
93 return true;
94
95 + /* Check the SG fragments. They must follow the same rules as the
96 + * linear data with and additional restriction: they must be multiple
97 + * of 16 bytes in size to account for the hardware carryover effect.
98 + */
99 + for (i = 0; i < nr_frags; i++) {
100 + frag = &skb_shinfo(skb)->frags[i];
101 +
102 + /* Check if the fragment is a multiple of 16 bytes in size.
103 + * The last fragment is exempt from this restriction.
104 + */
105 + if ((i != (nr_frags - 1)) && (skb_frag_size(frag) % 16))
106 + return true;
107 +
108 + /* Check if the fragment is 16 byte aligned */
109 + if (skb_frag_off(frag) % 16)
110 + return true;
111 +
112 + /* Check if the fragment crosses a 4K address boundary. Since
113 + * the alignment of previous fragments can influence the
114 + * current fragment, checking for the 256 byte alignment
115 + * isn't relevant.
116 + */
117 + if (CROSS_4K(skb_frag_off(frag), skb_frag_size(frag)))
118 + return true;
119 + }
120 +
121 return false;
122 }
123
124 @@ -1062,10 +1103,24 @@ int __hot dpa_tx_extended(struct sk_buff
125 struct dpa_percpu_priv_s *percpu_priv;
126 struct rtnl_link_stats64 *percpu_stats;
127 int err = 0;
128 - bool nonlinear;
129 + bool nonlinear, skb_changed, skb_need_wa;
130 int *countptr, offset = 0;
131 struct sk_buff *nskb;
132
133 + /* Flags to help optimize the A010022 errata restriction checks.
134 + *
135 + * First flag marks if the skb changed between the first A010022 check
136 + * and the moment it's converted to an FD.
137 + *
138 + * The second flag marks if the skb needs to be realigned in order to
139 + * avoid the errata.
140 + *
141 + * The flags should have minimal impact on platforms not impacted by
142 + * the errata.
143 + */
144 + skb_changed = false;
145 + skb_need_wa = false;
146 +
147 priv = netdev_priv(net_dev);
148 /* Non-migratable context, safe to use raw_cpu_ptr */
149 percpu_priv = raw_cpu_ptr(priv->percpu_priv);
150 @@ -1075,13 +1130,8 @@ int __hot dpa_tx_extended(struct sk_buff
151 clear_fd(&fd);
152
153 #ifndef CONFIG_PPC
154 - if (unlikely(dpaa_errata_a010022) && a010022_check_skb(skb, priv)) {
155 - nskb = a010022_realign_skb(skb, priv);
156 - if (!nskb)
157 - goto skb_to_fd_failed;
158 - dev_kfree_skb(skb);
159 - skb = nskb;
160 - }
161 + if (unlikely(dpaa_errata_a010022) && a010022_check_skb(skb, priv))
162 + skb_need_wa = true;
163 #endif
164
165 nonlinear = skb_is_nonlinear(skb);
166 @@ -1102,8 +1152,8 @@ int __hot dpa_tx_extended(struct sk_buff
167 * Btw, we're using the first sgt entry to store the linear part of
168 * the skb, so we're one extra frag short.
169 */
170 - if (nonlinear &&
171 - likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) {
172 + if (nonlinear && !skb_need_wa &&
173 + likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) {
174 /* Just create a S/G fd based on the skb */
175 err = skb_to_sg_fd(priv, skb, &fd);
176 percpu_priv->tx_frag_skbuffs++;
177 @@ -1128,39 +1178,62 @@ int __hot dpa_tx_extended(struct sk_buff
178
179 dev_kfree_skb(skb);
180 skb = skb_new;
181 + skb_changed = true;
182 }
183
184 /* We're going to store the skb backpointer at the beginning
185 * of the data buffer, so we need a privately owned skb
186 + *
187 + * Under the A010022 errata, we are going to have a privately
188 + * owned skb after realigning the current one, so no point in
189 + * copying it here in that case.
190 */
191
192 /* Code borrowed from skb_unshare(). */
193 - if (skb_cloned(skb)) {
194 + if (skb_cloned(skb) && !skb_need_wa) {
195 nskb = skb_copy(skb, GFP_ATOMIC);
196 kfree_skb(skb);
197 skb = nskb;
198 -#ifndef CONFIG_PPC
199 - if (unlikely(dpaa_errata_a010022) &&
200 - a010022_check_skb(skb, priv)) {
201 - nskb = a010022_realign_skb(skb, priv);
202 - if (!nskb)
203 - goto skb_to_fd_failed;
204 - dev_kfree_skb(skb);
205 - skb = nskb;
206 - }
207 -#endif
208 + skb_changed = true;
209 +
210 /* skb_copy() has now linearized the skbuff. */
211 - } else if (unlikely(nonlinear)) {
212 + } else if (unlikely(nonlinear) && !skb_need_wa) {
213 /* We are here because the egress skb contains
214 * more fragments than we support. In this case,
215 * we have no choice but to linearize it ourselves.
216 */
217 - err = __skb_linearize(skb);
218 +#ifndef CONFIG_PPC
219 + /* No point in linearizing the skb now if we are going
220 + * to realign and linearize it again further down due
221 + * to the A010022 errata
222 + */
223 + if (unlikely(dpaa_errata_a010022))
224 + skb_need_wa = true;
225 + else
226 +#endif
227 + err = __skb_linearize(skb);
228 }
229 if (unlikely(!skb || err < 0))
230 /* Common out-of-memory error path */
231 goto enomem;
232
233 +#ifndef CONFIG_PPC
234 + /* Verify the skb a second time if it has been updated since
235 + * the previous check
236 + */
237 + if (unlikely(dpaa_errata_a010022) && skb_changed &&
238 + a010022_check_skb(skb, priv))
239 + skb_need_wa = true;
240 +
241 + if (unlikely(dpaa_errata_a010022) && skb_need_wa) {
242 + nskb = a010022_realign_skb(skb, priv);
243 + if (!nskb)
244 + goto skb_to_fd_failed;
245 + dev_kfree_skb(skb);
246 + skb = nskb;
247 + }
248 +#endif
249 +
250 err = skb_to_contig_fd(priv, skb, &fd, countptr, &offset);
251 }
252 if (unlikely(err < 0))