xref: /linux/drivers/net/dsa/motorcomm/tc.c (revision 279d5c8afcd38bd841832a39bfe1aa4f8518d98e)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2026 David Yang
4  */
5 
6 #include "chip.h"
7 #include "smi.h"
8 #include "tc.h"
9 
10 static int yt921x_mtu_fetch(struct yt921x_priv *priv, int port)
11 {
12 	struct dsa_port *dp = dsa_to_port(&priv->ds, port);
13 
14 	return dp->user ? READ_ONCE(dp->user->mtu) : ETH_DATA_LEN;
15 }
16 
17 /* v * 2^e */
18 static u64 ldexpu64(u64 v, int e)
19 {
20 	return e >= 0 ? v << e : v >> -e;
21 }
22 
23 /* slot (ns) * rate (/s) / 10^9 (ns/s) = 2^C * token * 4^unit */
24 static u32 rate2token(u64 rate, unsigned int slot_ns, int unit, int C)
25 {
26 	int e = 2 * unit + C + YT921X_TOKEN_RATE_C;
27 
28 	return div_u64(ldexpu64(slot_ns * rate, -e), NSEC_PER_SEC);
29 }
30 
31 static u64 token2rate(u32 token, unsigned int slot_ns, int unit, int C)
32 {
33 	int e = 2 * unit + C + YT921X_TOKEN_RATE_C;
34 
35 	return div_u64(ldexpu64(mul_u32_u32(NSEC_PER_SEC, token), e), slot_ns);
36 }
37 
38 /* burst = 2^C * token * 4^unit */
39 static u32 burst2token(u64 burst, int unit, int C)
40 {
41 	return ldexpu64(burst, -(2 * unit + C));
42 }
43 
44 static u64 token2burst(u32 token, int unit, int C)
45 {
46 	return ldexpu64(token, 2 * unit + C);
47 }
48 
49 struct yt921x_marker {
50 	u32 cir;
51 	u32 cbs;
52 	u32 ebs;
53 	int unit;
54 	bool pkt_mode;
55 };
56 
57 #define YT921X_MARKER_PKT_MODE		BIT(0)
58 #define YT921X_MARKER_SINGLE_BUCKET	BIT(1)
59 
60 static int
61 yt921x_marker_tfm(struct yt921x_marker *marker, u64 rate, u64 burst,
62 		  unsigned int flags, unsigned int slot_ns, u32 cir_max,
63 		  u32 cbs_max, int unit_max, struct yt921x_priv *priv, int port,
64 		  struct netlink_ext_ack *extack)
65 {
66 	const int C = flags & YT921X_MARKER_PKT_MODE ? YT921X_TOKEN_PKT_C :
67 		      YT921X_TOKEN_BYTE_C;
68 	struct device *dev = yt921x_priv_to_device(priv);
69 	struct yt921x_marker m;
70 	u64 burst_est;
71 	u64 burst_sug;
72 	u64 burst_max;
73 	u64 rate_max;
74 
75 	m.unit = unit_max;
76 	rate_max = token2rate(cir_max, slot_ns, m.unit, C);
77 	burst_max = token2burst(cbs_max, m.unit, C);
78 
79 	/* Check for unusual values */
80 	if (rate > rate_max || burst > burst_max) {
81 		NL_SET_ERR_MSG_MOD(extack, "Unexpected tremendous rate");
82 		return -ERANGE;
83 	}
84 
85 	/* Check for matching burst */
86 	burst_est = div_u64(slot_ns * rate, NSEC_PER_SEC);
87 	burst_sug = burst_est;
88 	if (flags & YT921X_MARKER_PKT_MODE)
89 		burst_sug++;
90 	else
91 		burst_sug += ETH_HLEN + yt921x_mtu_fetch(priv, port) +
92 			     ETH_FCS_LEN;
93 	if (burst_sug > burst)
94 		NL_SET_ERR_MSG_FMT_MOD(extack,
95 				       "Consider match rate %llu with burst at least %llu",
96 				       rate, burst_sug);
97 
98 	/* Select unit */
99 	for (; m.unit > 0; m.unit--) {
100 		if (rate > (rate_max >> 2) || burst > (burst_max >> 2))
101 			break;
102 		rate_max >>= 2;
103 		burst_max >>= 2;
104 	}
105 
106 	/* Calculate information rate and bucket size */
107 	m.cir = rate2token(rate, slot_ns, m.unit, C);
108 	if (!m.cir)
109 		m.cir = 1;
110 	else if (WARN_ON(m.cir > cir_max))
111 		m.cir = cir_max;
112 	m.cbs = burst2token(burst, m.unit, C);
113 	if (!m.cbs)
114 		m.cbs = 1;
115 	else if (WARN_ON(m.cbs > cbs_max))
116 		m.cbs = cbs_max;
117 
118 	/* Cut EBS */
119 	m.ebs = 0;
120 	if (!(flags & YT921X_MARKER_SINGLE_BUCKET)) {
121 		/* We don't have a chance to adjust rate when MTU is changed */
122 		if (flags & YT921X_MARKER_PKT_MODE)
123 			burst_est++;
124 		else
125 			burst_est += YT921X_FRAME_SIZE_MAX;
126 
127 		if (burst_est < burst) {
128 			u32 pbs = m.cbs;
129 
130 			m.cbs = burst2token(burst_est, m.unit, C);
131 			if (!m.cbs)
132 				m.cbs = 1;
133 			else if (WARN_ON(m.cbs > cbs_max))
134 				m.cbs = cbs_max;
135 
136 			if (pbs > m.cbs)
137 				m.ebs = pbs - m.cbs;
138 		}
139 	}
140 
141 	dev_dbg(dev,
142 		"slot %u ns, rate %llu, burst %llu -> unit %d, cir %u, cbs %u, ebs %u\n",
143 		slot_ns, rate, burst, m.unit, m.cir, m.cbs, m.ebs);
144 
145 	m.pkt_mode = flags & YT921X_MARKER_PKT_MODE;
146 	*marker = m;
147 	return 0;
148 }
149 
150 static int
151 yt921x_marker_tfm_police(struct yt921x_marker *marker,
152 			 const struct flow_action_police *police,
153 			 unsigned int flags, struct yt921x_priv *priv, int port,
154 			 struct netlink_ext_ack *extack)
155 {
156 	bool pkt_mode = !!police->rate_pkt_ps;
157 	u64 burst;
158 	u64 rate;
159 
160 	rate = pkt_mode ? police->rate_pkt_ps : police->rate_bytes_ps;
161 	burst = pkt_mode ? police->burst_pkt : police->burst;
162 	if (pkt_mode)
163 		flags |= YT921X_MARKER_PKT_MODE;
164 
165 	return yt921x_marker_tfm(marker, rate, burst, flags,
166 				 priv->meter_slot_ns, YT921X_METER_CIR_MAX,
167 				 YT921X_METER_CBS_MAX, YT921X_METER_UNIT_MAX,
168 				 priv, port, extack);
169 }
170 
171 static int
172 yt921x_marker_tfm_shape(struct yt921x_marker *marker, u64 rate, u64 burst,
173 			unsigned int flags, struct yt921x_priv *priv, int port,
174 			struct netlink_ext_ack *extack)
175 {
176 	return yt921x_marker_tfm(marker, rate, burst, flags,
177 				 priv->port_shape_slot_ns, YT921X_SHAPE_CIR_MAX,
178 				 YT921X_SHAPE_CBS_MAX, YT921X_SHAPE_UNIT_MAX,
179 				 priv, port, extack);
180 }
181 
182 static int
183 yt921x_police_validate(const struct flow_action_police *police,
184 		       const struct flow_action *action,
185 		       const struct flow_action_entry *act,
186 		       struct netlink_ext_ack *extack)
187 {
188 	if (police->exceed.act_id != FLOW_ACTION_DROP) {
189 		NL_SET_ERR_MSG_MOD(extack,
190 				   "Offload not supported when exceed action is not drop");
191 		return -EOPNOTSUPP;
192 	}
193 
194 	if (police->notexceed.act_id != FLOW_ACTION_PIPE &&
195 	    police->notexceed.act_id != FLOW_ACTION_ACCEPT) {
196 		NL_SET_ERR_MSG_MOD(extack,
197 				   "Offload not supported when conform action is not pipe or ok");
198 		return -EOPNOTSUPP;
199 	}
200 
201 	if (police->notexceed.act_id == FLOW_ACTION_ACCEPT && action && act &&
202 	    !flow_action_is_last_entry(action, act)) {
203 		NL_SET_ERR_MSG_MOD(extack,
204 				   "Offload not supported when conform action is ok, but action is not last");
205 		return -EOPNOTSUPP;
206 	}
207 
208 	/* mtu defaults to unlimited but we got 2040 here, don't know why */
209 	if (police->peakrate_bytes_ps || police->avrate || police->overhead) {
210 		NL_SET_ERR_MSG_MOD(extack,
211 				   "Offload not supported when peakrate/avrate/overhead is configured");
212 		return -EOPNOTSUPP;
213 	}
214 
215 	return 0;
216 }
217 
218 static int
219 yt921x_meter_config(struct yt921x_priv *priv, unsigned int id,
220 		    const struct yt921x_marker *marker)
221 {
222 	u32 ctrls[3];
223 
224 	ctrls[0] = 0;
225 	ctrls[1] = YT921X_METER_CTRLb_CIR(marker->cir);
226 	ctrls[2] = YT921X_METER_CTRLc_UNIT(marker->unit) |
227 		   YT921X_METER_CTRLc_DROP_R |
228 		   YT921X_METER_CTRLc_TOKEN_OVERFLOW_EN |
229 		   YT921X_METER_CTRLc_METER_EN;
230 	if (marker->pkt_mode)
231 		ctrls[2] |= YT921X_METER_CTRLc_PKT_MODE;
232 	update_ctrls_unaligned(&ctrls[0], &ctrls[1],
233 			       YT921X_METER_CTRLab_EBS_M,
234 			       YT921X_METER_CTRLab_EBS(marker->ebs));
235 	update_ctrls_unaligned(&ctrls[1], &ctrls[2],
236 			       YT921X_METER_CTRLbc_CBS_M,
237 			       YT921X_METER_CTRLbc_CBS(marker->cbs));
238 
239 	return yt921x_reg96_write(priv, YT921X_METERn_CTRL(id), ctrls);
240 }
241 
242 void yt921x_dsa_port_policer_del(struct dsa_switch *ds, int port)
243 {
244 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
245 	struct device *dev = yt921x_priv_to_device(priv);
246 	int res;
247 
248 	mutex_lock(&priv->reg_lock);
249 	res = yt921x_reg_write(priv, YT921X_PORTn_METER(port), 0);
250 	mutex_unlock(&priv->reg_lock);
251 
252 	if (res)
253 		dev_err(dev, "Failed to %s port %d: %i\n", "delete policer on",
254 			port, res);
255 }
256 
257 int
258 yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port,
259 			    const struct flow_action_police *police,
260 			    struct netlink_ext_ack *extack)
261 {
262 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
263 	struct yt921x_marker marker;
264 	u32 ctrl;
265 	int res;
266 
267 	res = yt921x_police_validate(police, NULL, NULL, extack);
268 	if (res)
269 		return res;
270 
271 	res = yt921x_marker_tfm_police(&marker, police, 0, priv, port, extack);
272 	if (res)
273 		return res;
274 
275 	mutex_lock(&priv->reg_lock);
276 	res = yt921x_meter_config(priv, port + YT921X_METER_NUM, &marker);
277 	if (res)
278 		goto end;
279 
280 	ctrl = YT921X_PORT_METER_ID(port) | YT921X_PORT_METER_EN;
281 	res = yt921x_reg_write(priv, YT921X_PORTn_METER(port), ctrl);
282 end:
283 	mutex_unlock(&priv->reg_lock);
284 
285 	return res;
286 }
287 
288 static int
289 yt921x_dsa_port_setup_tc_tbf_port(struct dsa_switch *ds, int port,
290 				  const struct tc_tbf_qopt_offload *qopt)
291 {
292 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
293 	struct netlink_ext_ack *extack = qopt->extack;
294 	u32 ctrls[2];
295 	int res;
296 
297 	if (qopt->parent != TC_H_ROOT)
298 		return -EOPNOTSUPP;
299 
300 	switch (qopt->command) {
301 	case TC_TBF_STATS:
302 		/* Unfortunately the convention for TC_*_STATS is a mess,
303 		 * neither 0 nor -EOPNOTSUPP is perfect here.
304 		 */
305 		return -EOPNOTSUPP;
306 	case TC_TBF_DESTROY:
307 		ctrls[0] = 0;
308 		ctrls[1] = 0;
309 		break;
310 	case TC_TBF_REPLACE: {
311 		const struct tc_tbf_qopt_offload_replace_params *p;
312 		struct yt921x_marker marker;
313 
314 		p = &qopt->replace_params;
315 
316 		res = yt921x_marker_tfm_shape(&marker, p->rate.rate_bytes_ps,
317 					      p->max_size,
318 					      YT921X_MARKER_SINGLE_BUCKET,
319 					      priv, port, extack);
320 		if (res)
321 			return res;
322 
323 		ctrls[0] = YT921X_PORT_SHAPE_CTRLa_CIR(marker.cir) |
324 			   YT921X_PORT_SHAPE_CTRLa_CBS(marker.cbs);
325 		ctrls[1] = YT921X_PORT_SHAPE_CTRLb_UNIT(marker.unit) |
326 			   YT921X_PORT_SHAPE_CTRLb_EN;
327 		break;
328 	}
329 	default:
330 		return -EOPNOTSUPP;
331 	}
332 
333 	mutex_lock(&priv->reg_lock);
334 	res = yt921x_reg64_write(priv, YT921X_PORTn_SHAPE_CTRL(port), ctrls);
335 	mutex_unlock(&priv->reg_lock);
336 
337 	return res;
338 }
339 
340 int
341 yt921x_dsa_port_setup_tc(struct dsa_switch *ds, int port,
342 			 enum tc_setup_type type, void *type_data)
343 {
344 	switch (type) {
345 	case TC_SETUP_QDISC_TBF: {
346 		const struct tc_tbf_qopt_offload *qopt = type_data;
347 
348 		return yt921x_dsa_port_setup_tc_tbf_port(ds, port, qopt);
349 	}
350 	default:
351 		return -EOPNOTSUPP;
352 	}
353 }
354 
355 /* ACL: 48 blocks * 8 entries
356  *
357  * One rule can span multiple entries, but within a block.
358  */
359 
360 static void
361 yt921x_acl_entry_set(struct yt921x_acl_entry *entry, unsigned int offset,
362 		     u32 flags, bool set)
363 {
364 	if (set)
365 		entry->key[offset] |= flags;
366 	entry->mask[offset] |= flags;
367 }
368 
369 static unsigned int
370 yt921x_acl_entries_set_is_fragment(struct yt921x_acl_entry *entries,
371 				   unsigned int size, bool set)
372 {
373 	for (unsigned int i = 0; i < size; i++)
374 		switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) {
375 		case YT921X_ACL_TYPE_IPV4_DA:
376 		case YT921X_ACL_TYPE_IPV4_SA:
377 			yt921x_acl_entry_set(&entries[i], 1,
378 					     YT921X_ACL_BINb_IPV4_FRAG, set);
379 			return size;
380 		case YT921X_ACL_TYPE_IPV6_DA3:
381 		case YT921X_ACL_TYPE_IPV6_SA3:
382 			yt921x_acl_entry_set(&entries[i], 1,
383 					     YT921X_ACL_BINb_IPV6_xA3_FRAG,
384 					     set);
385 			return size;
386 		case YT921X_ACL_TYPE_MISC:
387 			yt921x_acl_entry_set(&entries[i], 1,
388 					     YT921X_ACL_BINb_MISC_FRAG, set);
389 			return size;
390 		case YT921X_ACL_TYPE_L4:
391 			yt921x_acl_entry_set(&entries[i], 1,
392 					     YT921X_ACL_BINb_L4_FRAG, set);
393 			return size;
394 		}
395 
396 	if (size >= YT921X_ACL_ENT_PER_BLK)
397 		return 0;
398 
399 	entries[size] = (typeof(*entries)){};
400 	entries[size].key[1] = YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC);
401 	yt921x_acl_entry_set(&entries[size], 1, YT921X_ACL_BINb_MISC_FRAG, set);
402 
403 	return size + 1;
404 }
405 
406 static unsigned int
407 yt921x_acl_entries_set_first_frag(struct yt921x_acl_entry *entries,
408 				  unsigned int size, bool set)
409 {
410 	for (unsigned int i = 0; i < size; i++)
411 		switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) {
412 		case YT921X_ACL_TYPE_IPV6_DA2:
413 		case YT921X_ACL_TYPE_IPV6_SA2:
414 			yt921x_acl_entry_set(&entries[i], 1,
415 					     YT921X_ACL_BINb_IPV6_xA2_FIRST_FRAG,
416 					     set);
417 			return size;
418 		case YT921X_ACL_TYPE_MISC:
419 			yt921x_acl_entry_set(&entries[i], 0,
420 					     YT921X_ACL_BINa_MISC_FIRST_FRAG,
421 					     set);
422 			return size;
423 		}
424 
425 	if (size >= YT921X_ACL_ENT_PER_BLK)
426 		return 0;
427 
428 	entries[size] = (typeof(*entries)){};
429 	entries[size].key[1] = YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC);
430 	yt921x_acl_entry_set(&entries[size], 0,
431 			     YT921X_ACL_BINa_MISC_FIRST_FRAG, set);
432 
433 	return size + 1;
434 }
435 
436 static unsigned int
437 yt921x_acl_entries_set_l3_type(struct yt921x_acl_entry *entries,
438 			       unsigned int size, enum yt921x_l3_type type)
439 {
440 	for (unsigned int i = 0; i < size; i++)
441 		switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) {
442 		case YT921X_ACL_TYPE_MAC_DA0:
443 		case YT921X_ACL_TYPE_MAC_SA0:
444 			entries[i].key[1] |= YT921X_ACL_BINb_MAC_xA0_L3_TYPE(type);
445 			entries[i].mask[1] |= YT921X_ACL_BINb_MAC_xA0_L3_TYPE_M;
446 			return size;
447 		case YT921X_ACL_TYPE_MISC:
448 			entries[i].key[0] |= YT921X_ACL_BINa_MISC_L3_TYPE(type);
449 			entries[i].mask[0] |= YT921X_ACL_BINa_MISC_L3_TYPE_M;
450 			return size;
451 		}
452 
453 	if (size >= YT921X_ACL_ENT_PER_BLK)
454 		return 0;
455 
456 	entries[size] = (typeof(*entries)){};
457 	entries[size].key[0] = YT921X_ACL_BINa_MISC_L3_TYPE(type);
458 	entries[size].key[1] = YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC);
459 	entries[size].mask[0] = YT921X_ACL_BINa_MISC_L3_TYPE_M;
460 
461 	return size + 1;
462 }
463 
464 static unsigned int
465 yt921x_acl_entries_set_l4_type(struct yt921x_acl_entry *entries,
466 			       unsigned int size, enum yt921x_l4_type type)
467 {
468 	for (unsigned int i = 0; i < size; i++)
469 		switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) {
470 		case YT921X_ACL_TYPE_IPV4_DA:
471 		case YT921X_ACL_TYPE_IPV4_SA:
472 			entries[i].key[1] |= YT921X_ACL_BINb_IPV4_L4_TYPE(type);
473 			entries[i].mask[1] |= YT921X_ACL_BINb_IPV4_L4_TYPE_M;
474 			return size;
475 		case YT921X_ACL_TYPE_IPV6_DA0:
476 		case YT921X_ACL_TYPE_IPV6_DA1:
477 		case YT921X_ACL_TYPE_IPV6_DA2:
478 		case YT921X_ACL_TYPE_IPV6_DA3:
479 		case YT921X_ACL_TYPE_IPV6_SA0:
480 		case YT921X_ACL_TYPE_IPV6_SA1:
481 		case YT921X_ACL_TYPE_IPV6_SA2:
482 		case YT921X_ACL_TYPE_IPV6_SA3:
483 			entries[i].key[1] |= YT921X_ACL_BINb_IPV6_L4_TYPE(type);
484 			entries[i].mask[1] |= YT921X_ACL_BINb_IPV6_L4_TYPE_M;
485 			return size;
486 		case YT921X_ACL_TYPE_L4:
487 			entries[i].key[1] |= YT921X_ACL_BINb_L4_TYPE(type);
488 			entries[i].mask[1] |= YT921X_ACL_BINb_L4_TYPE_M;
489 			return size;
490 		case YT921X_ACL_TYPE_MISC:
491 			entries[i].key[1] |= YT921X_ACL_BINb_MISC_L4_TYPE(type);
492 			entries[i].mask[1] |= YT921X_ACL_BINb_MISC_L4_TYPE_M;
493 			return size;
494 		}
495 
496 	if (size >= YT921X_ACL_ENT_PER_BLK)
497 		return 0;
498 
499 	entries[size] = (typeof(*entries)){};
500 	entries[size].key[1] = YT921X_ACL_BINb_MISC_L4_TYPE(type) |
501 			       YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC);
502 	entries[size].mask[1] = YT921X_ACL_BINb_MISC_L4_TYPE_M;
503 
504 	return size + 1;
505 }
506 
507 static struct yt921x_acl_entry *
508 yt921x_acl_entries_new(struct yt921x_acl_entry *entries, unsigned int *sizep,
509 		       u32 type)
510 {
511 	unsigned int size = *sizep;
512 
513 	if (size >= YT921X_ACL_ENT_PER_BLK)
514 		return NULL;
515 
516 	entries[size] = (typeof(*entries)){};
517 	entries[size].key[1] = YT921X_ACL_KEYb_TYPE(type);
518 
519 	(*sizep)++;
520 	return &entries[size];
521 }
522 
523 static struct yt921x_acl_entry *
524 yt921x_acl_entries_find(struct yt921x_acl_entry *entries, unsigned int *sizep,
525 			u32 type)
526 {
527 	for (unsigned int i = 0; i < *sizep; i++)
528 		if (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1]) ==
529 		    type)
530 			return &entries[i];
531 	return yt921x_acl_entries_new(entries, sizep, type);
532 }
533 
534 static void
535 yt921x_acl_rule_set_ports(struct yt921x_acl_rule *aclrule, u16 ord,
536 			  u16 ports_mask)
537 {
538 	struct yt921x_acl_entry *entries = aclrule->entries;
539 
540 	for (unsigned int i = 0; i < hweight8(aclrule->mask); i++) {
541 		entries[i].key[1] |= YT921X_ACL_KEYb_SPORTS(ports_mask) |
542 				     YT921X_ACL_KEYb_ORD(ord);
543 	}
544 }
545 
546 struct yt921x_udf_entry {
547 	unsigned char type;
548 	unsigned char offset;
549 	u8 key;
550 	u8 mask;
551 };
552 
553 struct yt921x_udf_map {
554 	unsigned char type;
555 	unsigned char offset;
556 };
557 
558 /* UDF windows are preselected - that's enough for now. */
559 static struct yt921x_udf_map yt921x_udf_maps[] = {
560 	{YT921X_UDF_TYPE_L3, 7},
561 	{YT921X_UDF_TYPE_L4, 0},
562 };
563 
564 struct yt921x_acl_rule_ext {
565 	struct yt921x_acl_rule r;
566 
567 	struct yt921x_marker marker;
568 };
569 
570 static int
571 yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext,
572 				       const struct flow_cls_offload *cls)
573 {
574 	const struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
575 	struct yt921x_acl_entry *entries = ruleext->r.entries;
576 	struct netlink_ext_ack *extack = cls->common.extack;
577 	struct yt921x_udf_entry udfs[YT921X_UDF_NUM];
578 	const struct flow_dissector *dissector;
579 	struct yt921x_acl_entry *entry;
580 	unsigned int udfs_cnt = 0;
581 	unsigned int size = 0;
582 	__be16 n_proto = 0;
583 	u8 ip_proto = 0;
584 	bool use_dport;
585 	bool use_sport;
586 
587 	/* Incomplete and probably won't, since it supports custom u32 filters.
588 	 * New adapters are welcome.
589 	 */
590 	dissector = rule->match.dissector;
591 	if (dissector->used_keys &
592 	    ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
593 	      BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
594 	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
595 	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
596 	      BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
597 	      BIT_ULL(FLOW_DISSECTOR_KEY_PORTS_RANGE) |
598 	      BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
599 	      BIT_ULL(FLOW_DISSECTOR_KEY_IP) |
600 	      BIT_ULL(FLOW_DISSECTOR_KEY_TCP) |
601 	      BIT_ULL(FLOW_DISSECTOR_KEY_ICMP))) {
602 		NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used");
603 		return -EOPNOTSUPP;
604 	}
605 
606 	/* Entries */
607 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
608 		struct flow_match_ipv4_addrs match;
609 
610 		flow_rule_match_ipv4_addrs(rule, &match);
611 
612 		if (match.mask->dst) {
613 			entry = yt921x_acl_entries_new(entries, &size,
614 						       YT921X_ACL_TYPE_IPV4_DA);
615 			if (!entry)
616 				goto err;
617 
618 			entry->key[0] |= ntohl(match.key->dst);
619 			entry->mask[0] |= ntohl(match.mask->dst);
620 		}
621 
622 		if (match.mask->src) {
623 			entry = yt921x_acl_entries_new(entries, &size,
624 						       YT921X_ACL_TYPE_IPV4_SA);
625 			if (!entry)
626 				goto err;
627 
628 			entry->key[0] |= ntohl(match.key->src);
629 			entry->mask[0] |= ntohl(match.mask->src);
630 		}
631 	}
632 
633 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) {
634 		struct flow_match_ipv6_addrs match;
635 
636 		flow_rule_match_ipv6_addrs(rule, &match);
637 
638 		for (unsigned int i = 0; i < 4; i++) {
639 			if (!match.mask->dst.s6_addr32[i])
640 				continue;
641 
642 			entry = yt921x_acl_entries_new(entries, &size,
643 						       YT921X_ACL_TYPE_IPV6_DA0 + i);
644 			if (!entry)
645 				goto err;
646 
647 			entry->key[0] |= ntohl(match.key->dst.s6_addr32[i]);
648 			entry->mask[0] |= ntohl(match.mask->dst.s6_addr32[i]);
649 		}
650 
651 		for (unsigned int i = 0; i < 4; i++) {
652 			if (!match.mask->src.s6_addr32[i])
653 				continue;
654 
655 			entry = yt921x_acl_entries_new(entries, &size,
656 						       YT921X_ACL_TYPE_IPV6_SA0 + i);
657 			if (!entry)
658 				goto err;
659 
660 			entry->key[0] |= ntohl(match.key->src.s6_addr32[i]);
661 			entry->mask[0] |= ntohl(match.mask->src.s6_addr32[i]);
662 		}
663 	}
664 
665 	use_dport = false;
666 	use_sport = false;
667 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
668 		struct flow_match_ports match;
669 
670 		entry = yt921x_acl_entries_new(entries, &size,
671 					       YT921X_ACL_TYPE_L4);
672 		if (!entry)
673 			goto err;
674 
675 		flow_rule_match_ports(rule, &match);
676 
677 		use_dport = !!match.mask->dst;
678 		use_sport = !!match.mask->src;
679 
680 		entry->key[0] |= (ntohs(match.key->dst) << 16) |
681 				 ntohs(match.key->src);
682 		entry->mask[0] |= (ntohs(match.mask->dst) << 16) |
683 				  ntohs(match.mask->src);
684 	}
685 
686 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS_RANGE)) {
687 		struct flow_match_ports_range match;
688 
689 		entry = yt921x_acl_entries_find(entries, &size,
690 						YT921X_ACL_TYPE_L4);
691 		if (!entry)
692 			goto err;
693 
694 		flow_rule_match_ports_range(rule, &match);
695 
696 		if ((use_dport && match.mask->tp.dst) ||
697 		    (use_sport && match.mask->tp.src)) {
698 			NL_SET_ERR_MSG_MOD(extack,
699 					   "Port mask and range are mutually exclusive");
700 			return -EINVAL;
701 		}
702 
703 		if (match.mask->tp.dst) {
704 			entry->key[0] |= ntohs(match.key->tp_min.dst) << 16;
705 			entry->key[1] |= YT921X_ACL_KEYb_L4_DPORT_RANGE_EN;
706 			entry->mask[0] |= ntohs(match.key->tp_max.dst) << 16;
707 		}
708 
709 		if (match.mask->tp.src) {
710 			entry->key[0] |= ntohs(match.key->tp_min.src);
711 			entry->key[1] |= YT921X_ACL_KEYb_L4_SPORT_RANGE_EN;
712 			entry->mask[0] |= ntohs(match.key->tp_max.src);
713 		}
714 	}
715 
716 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
717 		struct flow_match_eth_addrs match;
718 		u32 mask;
719 
720 		flow_rule_match_eth_addrs(rule, &match);
721 
722 		mask = ethaddr_hi4_to_u32(match.mask->dst);
723 		if (mask) {
724 			entry = yt921x_acl_entries_new(entries, &size,
725 						       YT921X_ACL_TYPE_MAC_DA0);
726 			if (!entry)
727 				goto err;
728 
729 			entry->key[0] |= ethaddr_hi4_to_u32(match.key->dst);
730 			entry->mask[0] |= mask;
731 		}
732 
733 		mask = ethaddr_hi4_to_u32(match.mask->src);
734 		if (mask) {
735 			entry = yt921x_acl_entries_new(entries, &size,
736 						       YT921X_ACL_TYPE_MAC_SA0);
737 			if (!entry)
738 				goto err;
739 
740 			entry->key[0] |= ethaddr_hi4_to_u32(match.key->src);
741 			entry->mask[0] |= mask;
742 		}
743 
744 		mask = (ethaddr_lo2_to_u32(match.mask->dst) << 16) |
745 		       ethaddr_lo2_to_u32(match.mask->src);
746 		if (mask) {
747 			entry = yt921x_acl_entries_new(entries, &size,
748 						       YT921X_ACL_TYPE_MAC_DA1_SA1);
749 			if (!entry)
750 				goto err;
751 
752 			entry->key[0] |= (ethaddr_lo2_to_u32(match.key->dst) << 16) |
753 					 ethaddr_lo2_to_u32(match.key->src);
754 			entry->mask[0] |= mask;
755 		}
756 	}
757 
758 	/* Entries + Misc */
759 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
760 		struct flow_match_basic match;
761 
762 		flow_rule_match_basic(rule, &match);
763 
764 		if (match.mask->n_proto) {
765 			enum yt921x_l3_type l3type = YT921X_L3_TYPE_OTHER;
766 
767 			if (match.mask->n_proto == htons(~0)) {
768 				n_proto = match.key->n_proto;
769 
770 				switch (match.key->n_proto) {
771 				case htons(ETH_P_IP):
772 					l3type = YT921X_L3_TYPE_IPV4;
773 					break;
774 				case htons(ETH_P_IPV6):
775 					l3type = YT921X_L3_TYPE_IPV6;
776 					break;
777 				case htons(ETH_P_ARP):
778 					l3type = YT921X_L3_TYPE_ARP;
779 					break;
780 				case htons(ETH_P_LLDP):
781 					l3type = YT921X_L3_TYPE_LLDP;
782 					break;
783 				case htons(ETH_P_PAE):
784 					l3type = YT921X_L3_TYPE_PAE;
785 					break;
786 				case htons(ETH_P_CFM):
787 					l3type = YT921X_L3_TYPE_ERP;
788 					break;
789 				}
790 			}
791 
792 			if (l3type != YT921X_L3_TYPE_OTHER) {
793 				size = yt921x_acl_entries_set_l3_type(entries,
794 								      size,
795 								      l3type);
796 				if (!size)
797 					goto err;
798 			} else {
799 				entry = yt921x_acl_entries_new(entries, &size,
800 							       YT921X_ACL_TYPE_ETHERTYPE);
801 				if (!entry)
802 					goto err;
803 
804 				entry->key[0] |= ntohs(match.key->n_proto);
805 				entry->mask[0] |= ntohs(match.mask->n_proto);
806 			}
807 		}
808 
809 		if (match.mask->ip_proto) {
810 			enum yt921x_l4_type l4type = YT921X_L4_TYPE_OTHER;
811 
812 			if (match.mask->ip_proto == (u8)~0) {
813 				ip_proto = match.key->ip_proto;
814 
815 				switch (match.key->ip_proto) {
816 				case IPPROTO_TCP:
817 					l4type = YT921X_L4_TYPE_TCP;
818 					break;
819 				case IPPROTO_UDP:
820 					l4type = YT921X_L4_TYPE_UDP;
821 					break;
822 				case IPPROTO_UDPLITE:
823 					l4type = YT921X_L4_TYPE_UDPLITE;
824 					break;
825 				case IPPROTO_ICMP:
826 					l4type = YT921X_L4_TYPE_ICMP;
827 					break;
828 				case IPPROTO_IGMP:
829 					l4type = YT921X_L4_TYPE_IGMP;
830 					break;
831 				}
832 			}
833 
834 			if (l4type != YT921X_L4_TYPE_OTHER) {
835 				size = yt921x_acl_entries_set_l4_type(entries,
836 								      size,
837 								      l4type);
838 				if (!size)
839 					goto err;
840 			} else {
841 				entry = yt921x_acl_entries_find(entries, &size,
842 								YT921X_ACL_TYPE_MISC);
843 				if (!entry)
844 					goto err;
845 
846 				entry->key[0] |= YT921X_ACL_BINa_MISC_IP_PROTO(match.key->ip_proto);
847 				entry->mask[0] |= YT921X_ACL_BINa_MISC_IP_PROTO(match.mask->ip_proto);
848 			}
849 		}
850 	}
851 
852 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
853 		u32 supp_flags = FLOW_DIS_IS_FRAGMENT | FLOW_DIS_FIRST_FRAG;
854 		struct flow_match_control match;
855 
856 		flow_rule_match_control(rule, &match);
857 		if (!flow_rule_is_supp_control_flags(supp_flags,
858 						     match.mask->flags, extack))
859 			return -EOPNOTSUPP;
860 
861 		if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) {
862 			bool set = match.key->flags & FLOW_DIS_IS_FRAGMENT;
863 
864 			size = yt921x_acl_entries_set_is_fragment(entries, size,
865 								  set);
866 			if (!size)
867 				goto err;
868 		}
869 		if (match.mask->flags & FLOW_DIS_FIRST_FRAG) {
870 			bool set = match.key->flags & FLOW_DIS_FIRST_FRAG;
871 
872 			size = yt921x_acl_entries_set_first_frag(entries, size,
873 								 set);
874 			if (!size)
875 				goto err;
876 		}
877 	}
878 
879 	/* Misc only */
880 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
881 		struct flow_match_ip match;
882 
883 		flow_rule_match_ip(rule, &match);
884 
885 		if (match.mask->ttl) {
886 			if (n_proto != htons(ETH_P_IP) &&
887 			    n_proto != htons(ETH_P_IPV6)) {
888 				NL_SET_ERR_MSG_MOD(extack,
889 						   "Matching on TTL requires protocol ip or ipv6");
890 				return -EOPNOTSUPP;
891 			}
892 
893 			if (udfs_cnt >= YT921X_UDF_NUM)
894 				goto err;
895 
896 			udfs[udfs_cnt] = (struct yt921x_udf_entry){
897 				.type = YT921X_UDF_TYPE_L3,
898 				.offset = n_proto == htons(ETH_P_IP) ? 8 : 7,
899 				.key = match.key->ttl,
900 				.mask = match.mask->ttl,
901 			};
902 			udfs_cnt++;
903 		}
904 
905 		if (match.mask->tos) {
906 			entry = yt921x_acl_entries_find(entries, &size,
907 							YT921X_ACL_TYPE_MISC);
908 			if (!entry)
909 				goto err;
910 
911 			entry->key[0] |= YT921X_ACL_BINa_MISC_TOS(match.key->tos);
912 			entry->mask[0] |= YT921X_ACL_BINa_MISC_TOS(match.mask->tos);
913 		}
914 	}
915 
916 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) {
917 		struct flow_match_tcp match;
918 
919 		flow_rule_match_tcp(rule, &match);
920 		if (match.mask->flags & htons(~0xff)) {
921 			NL_SET_ERR_MSG_MOD(extack, "Unsupported TCP flags");
922 			return -EOPNOTSUPP;
923 		}
924 
925 		if (match.mask->flags) {
926 			entry = yt921x_acl_entries_find(entries, &size,
927 							YT921X_ACL_TYPE_MISC);
928 			if (!entry)
929 				goto err;
930 
931 			entry->key[0] |= YT921X_ACL_BINa_MISC_TCP_FLAGS(ntohs(match.key->flags));
932 			entry->mask[0] |= YT921X_ACL_BINa_MISC_TCP_FLAGS(ntohs(match.mask->flags));
933 		}
934 	}
935 
936 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) {
937 		struct flow_match_icmp match;
938 
939 		flow_rule_match_icmp(rule, &match);
940 
941 		if (match.mask->type || match.mask->code) {
942 			if (ip_proto != IPPROTO_ICMP &&
943 			    ip_proto != IPPROTO_ICMPV6) {
944 				NL_SET_ERR_MSG_MOD(extack,
945 						   "Matching on ICMP type/code requires ip_proto icmp or icmpv6");
946 				return -EOPNOTSUPP;
947 			}
948 
949 			if (match.mask->type) {
950 				if (udfs_cnt >= YT921X_UDF_NUM)
951 					goto err;
952 
953 				udfs[udfs_cnt] = (struct yt921x_udf_entry){
954 					.type = YT921X_UDF_TYPE_L4,
955 					.offset = 0,
956 					.key = match.key->type,
957 					.mask = match.mask->type,
958 				};
959 				udfs_cnt++;
960 			}
961 
962 			if (match.mask->code) {
963 				if (udfs_cnt >= YT921X_UDF_NUM)
964 					goto err;
965 
966 				udfs[udfs_cnt] = (struct yt921x_udf_entry){
967 					.type = YT921X_UDF_TYPE_L4,
968 					.offset = 1,
969 					.key = match.key->code,
970 					.mask = match.mask->code,
971 				};
972 				udfs_cnt++;
973 			}
974 		}
975 	}
976 
977 	/* Compile UDFs */
978 	for (unsigned int i = 0; i < udfs_cnt; i++) {
979 		unsigned int o;
980 		u32 mask;
981 		u32 key;
982 
983 		for (o = 0; o < ARRAY_SIZE(yt921x_udf_maps); o++)
984 			if (udfs[i].type == yt921x_udf_maps[o].type &&
985 			    (udfs[i].offset == yt921x_udf_maps[o].offset ||
986 			     udfs[i].offset == yt921x_udf_maps[o].offset + 1))
987 				break;
988 
989 		if (WARN_ON(o == ARRAY_SIZE(yt921x_udf_maps)))
990 			return -EOPNOTSUPP;
991 
992 		entry = yt921x_acl_entries_find(entries, &size,
993 						YT921X_ACL_TYPE_UDF0 + o / 2);
994 		if (!entry)
995 			goto err;
996 
997 		key = udfs[i].key;
998 		mask = udfs[i].mask;
999 		if (udfs[i].offset == yt921x_udf_maps[o].offset) {
1000 			key <<= 8;
1001 			mask <<= 8;
1002 		}
1003 		if (!(o % 2)) {
1004 			key <<= 16;
1005 			mask <<= 16;
1006 		}
1007 
1008 		entry->key[0] |= key;
1009 		entry->mask[0] |= mask;
1010 	}
1011 
1012 	if (!size) {
1013 		NL_SET_ERR_MSG_MOD(extack, "Empty rule generated, this should not happen");
1014 		return -EOPNOTSUPP;
1015 	}
1016 
1017 	ruleext->r.mask = (1 << size) - 1;
1018 	return 0;
1019 
1020 err:
1021 	NL_SET_ERR_MSG_MOD(extack, "Rule too complex");
1022 	return -EOPNOTSUPP;
1023 }
1024 
1025 static int
1026 yt921x_acl_rule_ext_parse_flow_action(struct yt921x_acl_rule_ext *ruleext,
1027 				      const struct flow_cls_offload *cls,
1028 				      struct yt921x_priv *priv, int port)
1029 {
1030 	const struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
1031 	const struct flow_action *flow_action = &rule->action;
1032 	struct netlink_ext_ack *extack = cls->common.extack;
1033 	enum flow_action_id redir_act = NUM_FLOW_ACTIONS;
1034 	const struct flow_action_entry *act;
1035 	u32 *action = ruleext->r.action;
1036 	bool seen_priority = false;
1037 	const char *reason = NULL;
1038 	bool seen_police = false;
1039 	unsigned int i;
1040 	int res;
1041 
1042 	memset(action, 0, 3 * sizeof(*action));
1043 	flow_action_for_each(i, act, flow_action)
1044 		switch (act->id) {
1045 		case FLOW_ACTION_ACCEPT:
1046 		case FLOW_ACTION_DROP:
1047 		case FLOW_ACTION_REDIRECT:
1048 			if (redir_act != NUM_FLOW_ACTIONS &&
1049 			    redir_act != act->id) {
1050 				reason = "Different redirect actions";
1051 				goto fallback;
1052 			}
1053 			redir_act = act->id;
1054 
1055 			switch (act->id) {
1056 			case FLOW_ACTION_ACCEPT:
1057 				action[2] |= YT921X_ACL_ACTc_FWD_EN |
1058 					     YT921X_ACL_ACTc_FWD_FWD;
1059 				break;
1060 			case FLOW_ACTION_DROP:
1061 				action[2] |= YT921X_ACL_ACTc_FWD_EN |
1062 					     YT921X_ACL_ACTc_FWD_REDIR;
1063 				break;
1064 			case FLOW_ACTION_REDIRECT: {
1065 				struct dsa_port *to_dp;
1066 
1067 				to_dp = dsa_port_from_netdev(act->dev);
1068 				if (IS_ERR(to_dp) || to_dp->ds != &priv->ds) {
1069 					reason = "Redirect to non-local port";
1070 					goto fallback;
1071 				}
1072 
1073 				action[2] |= YT921X_ACL_ACTc_FWD_EN |
1074 					     YT921X_ACL_ACTc_FWD_REDIR |
1075 					     YT921X_ACL_ACTc_FWD_REDIR_DPORTn(to_dp->index);
1076 				break;
1077 			}
1078 			default:
1079 				break;
1080 			}
1081 			break;
1082 		case FLOW_ACTION_PRIORITY:
1083 			if (seen_priority) {
1084 				action[0] &= ~YT921X_ACL_ACTa_PRIO_EN;
1085 				action[1] &= ~YT921X_ACL_ACTb_PRIO_M;
1086 
1087 				reason = "Multiple priority actions";
1088 				goto fallback;
1089 			}
1090 			seen_priority = true;
1091 
1092 			if (act->priority >= YT921X_PRIO_NUM) {
1093 				NL_SET_ERR_MSG_MOD(extack,
1094 						   "Priority value is too high");
1095 				return -EOPNOTSUPP;
1096 			}
1097 			action[0] |= YT921X_ACL_ACTa_PRIO_EN;
1098 			action[1] |= YT921X_ACL_ACTb_PRIO(act->priority);
1099 			break;
1100 		case FLOW_ACTION_POLICE: {
1101 			const struct flow_action_police *police = &act->police;
1102 
1103 			if (seen_police) {
1104 				action[0] &= ~YT921X_ACL_ACTa_METER_EN;
1105 
1106 				reason = "Multiple police actions";
1107 				goto fallback;
1108 			}
1109 			seen_police = true;
1110 
1111 			res = yt921x_police_validate(police, flow_action, act,
1112 						     extack);
1113 			if (res)
1114 				return res;
1115 
1116 			res = yt921x_marker_tfm_police(&ruleext->marker, police,
1117 						       0, priv, port, extack);
1118 			if (res)
1119 				return res;
1120 
1121 			action[0] |= YT921X_ACL_ACTa_METER_EN;
1122 			break;
1123 		}
1124 		default:
1125 fallback:
1126 			if (cls->common.skip_sw) {
1127 				NL_SET_ERR_MSG_FMT_MOD(extack,
1128 						       "Action not supported when skip_sw: %s",
1129 						       reason);
1130 				return -EOPNOTSUPP;
1131 			}
1132 			fallthrough;
1133 		case FLOW_ACTION_TRAP:
1134 			redir_act = FLOW_ACTION_TRAP;
1135 
1136 			action[2] &= ~YT921X_ACL_ACTc_FWD_REDIR_DPORTS_M &
1137 				     ~YT921X_ACL_ACTc_FWD_M;
1138 			action[2] |= YT921X_ACL_ACTc_FWD_EN |
1139 				     YT921X_ACL_ACTc_FWD_TRAP;
1140 			break;
1141 		}
1142 
1143 	ruleext->r.sw_assisted = !cls->common.skip_sw;
1144 	return 0;
1145 }
1146 
1147 static int
1148 yt921x_acl_rule_ext_parse_flow(struct yt921x_acl_rule_ext *ruleext, int port,
1149 			       const struct flow_cls_offload *cls, bool ingress,
1150 			       struct yt921x_priv *priv)
1151 {
1152 	const unsigned int scale = (U16_MAX + 1) / YT921X_ACL_ORD_NUM;
1153 	struct netlink_ext_ack *extack = cls->common.extack;
1154 	u32 prio = cls->common.prio;
1155 	u32 ord;
1156 	int res;
1157 
1158 	if (!ingress) {
1159 		NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported");
1160 		return -EOPNOTSUPP;
1161 	}
1162 
1163 	if (cls->common.chain_index) {
1164 		NL_SET_ERR_MSG(extack, "Only chain 0 is supported");
1165 		return -EOPNOTSUPP;
1166 	}
1167 
1168 	/* Lower TC priorities take precedence, while larger orders win in
1169 	 * hardware. Spread the 512 hardware orders over the TC priority range
1170 	 * as evenly as possible, retaining the relative order:
1171 	 *
1172 	 *   prio 65535 -> ORD 0    catchall filter
1173 	 *   prio 65408 -> ORD 1    highest mappable TC priority
1174 	 *   ...
1175 	 *   prio 49152 -> ORD 128  default value for the first tc flower rule
1176 	 *   ...
1177 	 *   prio   128 -> ORD 511
1178 	 *   prio     0             (invalid TC priority)
1179 	 *
1180 	 * The catchall filter always comes with priority 65535; pin it to ORD
1181 	 * 0, the lowest hardware order, instead of rejecting it.
1182 	 *
1183 	 * Prefer explicit rejects over implicit behaviour changes: reject
1184 	 * the priorities which do not map onto a hardware order instead of
1185 	 * silently colliding with a neighbouring one.
1186 	 */
1187 	if (prio == U16_MAX) {
1188 		ord = 0;
1189 	} else if (!(prio % scale)) {
1190 		ord = YT921X_ACL_ORD_NUM - prio / scale;
1191 	} else {
1192 		NL_SET_ERR_MSG_FMT_MOD(extack,
1193 				       "Invalid priority %u, must be a multiple of %u or 65535",
1194 				       prio, scale);
1195 		return -EOPNOTSUPP;
1196 	}
1197 
1198 	res = yt921x_acl_rule_ext_parse_flow_action(ruleext, cls, priv, port);
1199 	if (res)
1200 		return res;
1201 	res = yt921x_acl_rule_ext_parse_flow_entries(ruleext, cls);
1202 	if (res)
1203 		return res;
1204 
1205 	yt921x_acl_rule_set_ports(&ruleext->r, ord, BIT(port));
1206 	ruleext->r.tag = cls->cookie;
1207 	ruleext->r.type = TC_SETUP_CLSFLOWER;
1208 	return 0;
1209 }
1210 
1211 /* Ports that _should_ have ACL activated on. ACL_PORT \succeq activated_ports()
1212  */
1213 static u16 yt921x_acl_activated_ports(const struct yt921x_priv *priv)
1214 {
1215 	u16 mask = 0;
1216 
1217 	for (int port = 0; port < YT921X_PORT_NUM; port++)
1218 		if (priv->ports[port].acl_cnt)
1219 			mask |= BIT(port);
1220 
1221 	return mask;
1222 }
1223 
1224 static unsigned int
1225 yt921x_acl_find(const struct yt921x_priv *priv, enum tc_setup_type type,
1226 		unsigned long tag)
1227 {
1228 	for (unsigned int blkid = 0; blkid < YT921X_ACL_BLK_NUM; blkid++) {
1229 		const struct yt921x_acl_blk *aclblk = priv->acl_blks[blkid];
1230 
1231 		if (!aclblk)
1232 			continue;
1233 
1234 		for (unsigned int i = 0; i < YT921X_ACL_ENT_PER_BLK; i++)
1235 			if (aclblk->rules[i] && aclblk->rules[i]->tag == tag &&
1236 			    aclblk->rules[i]->type == type)
1237 				return YT921X_ACL_ENT_PER_BLK * blkid + i;
1238 	}
1239 
1240 	return UINT_MAX;
1241 }
1242 
1243 static unsigned int
1244 yt921x_acl_reserve(struct yt921x_priv *priv, unsigned int entscnt,
1245 		   struct netlink_ext_ack *extack)
1246 {
1247 	int candidates[YT921X_ACL_ENT_PER_BLK + 1];
1248 	unsigned int acl_used_cnt = 0;
1249 
1250 	if (WARN_ON(entscnt > YT921X_ACL_ENT_PER_BLK))
1251 		return UINT_MAX;
1252 
1253 	for (unsigned int i = 0; i < ARRAY_SIZE(candidates); i++)
1254 		candidates[i] = -1;
1255 	for (unsigned int i = YT921X_ACL_BLK_NUM; i-- > 0;) {
1256 		unsigned int blk_used_cnt = hweight8(priv->acl_masks[i]);
1257 
1258 		candidates[blk_used_cnt] = i;
1259 		acl_used_cnt += blk_used_cnt;
1260 	}
1261 
1262 	if (acl_used_cnt >= YT921X_ACL_NUM) {
1263 		NL_SET_ERR_MSG_MOD(extack, "ACL entry limit reached");
1264 		return UINT_MAX;
1265 	}
1266 	if (acl_used_cnt + entscnt <= YT921X_ACL_NUM)
1267 		for (unsigned int i = YT921X_ACL_ENT_PER_BLK - entscnt + 1;
1268 		     i-- > 0;)
1269 			if (candidates[i] >= 0)
1270 				return YT921X_ACL_ENT_PER_BLK * candidates[i] +
1271 				       ffz(priv->acl_masks[candidates[i]]);
1272 
1273 	NL_SET_ERR_MSG_MOD(extack,
1274 			   "ACL entry allocation failed, simplify your rules or remove existing rules");
1275 	return UINT_MAX;
1276 }
1277 
1278 static int
1279 yt921x_acl_commit(struct yt921x_priv *priv, unsigned int entid, u8 entsmask)
1280 {
1281 	const struct yt921x_acl_rule *aclrule;
1282 	const struct yt921x_acl_blk *aclblk;
1283 	unsigned int blkid;
1284 	unsigned int binid;
1285 	unsigned long mask;
1286 	u32 zeros[3] = {};
1287 	unsigned int i;
1288 	unsigned int o;
1289 	u32 ctrl;
1290 	int res;
1291 
1292 	blkid = entid / YT921X_ACL_ENT_PER_BLK;
1293 	binid = entid % YT921X_ACL_ENT_PER_BLK;
1294 	aclblk = priv->acl_blks[blkid];
1295 	aclrule = aclblk->rules[binid];
1296 
1297 	/* Write actions */
1298 	res = yt921x_reg96_write(priv, YT921X_ACLn_ACT(entid),
1299 				 aclrule ? aclrule->action : zeros);
1300 	if (res)
1301 		return res;
1302 
1303 	/* Select the block */
1304 	ctrl = YT921X_ACL_BLK_CMD_MODIFY | YT921X_ACL_BLK_CMD_BLKID(blkid);
1305 	res = yt921x_reg_write(priv, YT921X_ACL_BLK_CMD, ctrl);
1306 	if (res)
1307 		return res;
1308 
1309 	/* Write keys and masks */
1310 	ctrl = 0;
1311 	for (unsigned int i = 0; i < YT921X_ACL_ENT_PER_BLK; i++)
1312 		ctrl |= YT921X_ACL_BLK_KEEP_KEEPn(i);
1313 
1314 	mask = entsmask;
1315 	i = 0;
1316 	for_each_set_bit(o, &mask, YT921X_ACL_ENT_PER_BLK) {
1317 		res = yt921x_reg64_write(priv, YT921X_ACLn_KEYm(blkid, o),
1318 					 aclrule ? aclrule->entries[i].key :
1319 					 zeros);
1320 		if (res)
1321 			return res;
1322 
1323 		res = yt921x_reg64_write(priv, YT921X_ACLn_MASKm(blkid, o),
1324 					 aclrule ? aclrule->entries[i].mask :
1325 					 zeros);
1326 		if (res)
1327 			return res;
1328 
1329 		ctrl &= ~YT921X_ACL_BLK_KEEP_KEEPn(o);
1330 		i++;
1331 	}
1332 
1333 	res = yt921x_reg_write(priv, YT921X_ACL_BLK_KEEP, ctrl);
1334 	if (res)
1335 		return res;
1336 
1337 	ctrl = 0;
1338 	for (unsigned int i = 0; i < YT921X_ACL_ENT_PER_BLK; i++) {
1339 		const struct yt921x_acl_rule *other = aclblk->rules[i];
1340 
1341 		if (!other)
1342 			continue;
1343 
1344 		mask = other->mask;
1345 		for_each_set_bit(o, &mask, YT921X_ACL_ENT_PER_BLK)
1346 			ctrl |= YT921X_ACL_ENTRY_ENm(o) |
1347 				YT921X_ACL_ENTRY_GRPIDm(o, i);
1348 	}
1349 	res = yt921x_reg_write(priv, YT921X_ACLn_ENTRY(blkid), ctrl);
1350 	if (res)
1351 		return res;
1352 
1353 	/* Commit the block */
1354 	ctrl = YT921X_ACL_BLK_CMD_BLKID(blkid);
1355 	res = yt921x_reg_write(priv, YT921X_ACL_BLK_CMD, ctrl);
1356 	if (res)
1357 		return res;
1358 
1359 	return 0;
1360 }
1361 
1362 static int
1363 yt921x_acl_del(struct yt921x_priv *priv, enum tc_setup_type type,
1364 	       unsigned long tag)
1365 {
1366 	struct yt921x_acl_rule *aclrule;
1367 	struct yt921x_acl_blk *aclblk;
1368 	bool refresh_en = false;
1369 	unsigned int binid;
1370 	unsigned int blkid;
1371 	unsigned int entid;
1372 	unsigned long m;
1373 	unsigned int o;
1374 	u32 ctrl;
1375 	int res;
1376 	int ret;
1377 
1378 	entid = yt921x_acl_find(priv, type, tag);
1379 	if (entid == UINT_MAX)
1380 		return -ENOENT;
1381 
1382 	blkid = entid / YT921X_ACL_ENT_PER_BLK;
1383 	binid = entid % YT921X_ACL_ENT_PER_BLK;
1384 	aclblk = priv->acl_blks[blkid];
1385 	aclrule = aclblk->rules[binid];
1386 
1387 	aclblk->rules[binid] = NULL;
1388 	ret = yt921x_acl_commit(priv, entid, aclrule->mask);
1389 	/* the kernel never rolls back on failure */
1390 
1391 	m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, aclrule->entries[0].key[1]);
1392 	for_each_set_bit(o, &m, YT921X_PORT_NUM) {
1393 		struct yt921x_port *pp = &priv->ports[o];
1394 
1395 		if (!WARN_ON(!pp->acl_cnt)) {
1396 			pp->acl_cnt--;
1397 			if (pp->acl_cnt)
1398 				continue;
1399 		}
1400 		refresh_en = true;
1401 	}
1402 	if (refresh_en) {
1403 		ctrl = yt921x_acl_activated_ports(priv);
1404 		res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl);
1405 		if (res)
1406 			ret = res;
1407 	}
1408 
1409 	if (aclrule->action[0] & YT921X_ACL_ACTa_METER_EN)
1410 		clear_bit(FIELD_GET(YT921X_ACL_ACTa_METER_ID_M,
1411 				    aclrule->action[0]),
1412 			  priv->meters_map);
1413 	priv->acl_masks[blkid] &= ~aclrule->mask;
1414 	kvfree(aclrule);
1415 	if (!priv->acl_masks[blkid]) {
1416 		kvfree(aclblk);
1417 		priv->acl_blks[blkid] = NULL;
1418 	}
1419 	return ret;
1420 }
1421 
1422 static int
1423 yt921x_acl_add(struct yt921x_priv *priv,
1424 	       const struct yt921x_acl_rule_ext *ruleext,
1425 	       struct netlink_ext_ack *extack)
1426 {
1427 	unsigned int entscnt = hweight8(ruleext->r.mask);
1428 	struct yt921x_acl_rule *aclrule;
1429 	struct yt921x_acl_blk *aclblk;
1430 	bool use_trap = false;
1431 	unsigned int meterid;
1432 	unsigned int binid;
1433 	unsigned int blkid;
1434 	unsigned int entid;
1435 	unsigned long m;
1436 	unsigned int o;
1437 	u32 ctrl;
1438 	int res;
1439 
1440 	/* Allocate resources */
1441 	entid = yt921x_acl_reserve(priv, entscnt, extack);
1442 	if (entid == UINT_MAX)
1443 		return -EOPNOTSUPP;
1444 
1445 	if (!(ruleext->r.action[0] & YT921X_ACL_ACTa_METER_EN)) {
1446 		meterid = YT921X_METER_NUM;
1447 	} else {
1448 		meterid = find_first_zero_bit(priv->meters_map,
1449 					      YT921X_METER_NUM);
1450 		if (meterid < YT921X_METER_NUM) {
1451 			res = yt921x_meter_config(priv, meterid,
1452 						  &ruleext->marker);
1453 			if (res)
1454 				return res;
1455 		} else if (ruleext->r.sw_assisted) {
1456 			use_trap = true;
1457 		} else {
1458 			NL_SET_ERR_MSG_MOD(extack,
1459 					   "No more meters available");
1460 			return -EOPNOTSUPP;
1461 		}
1462 	}
1463 
1464 	/* Prepare acl block ctrlblk */
1465 	blkid = entid / YT921X_ACL_ENT_PER_BLK;
1466 	binid = entid % YT921X_ACL_ENT_PER_BLK;
1467 	aclblk = priv->acl_blks[blkid];
1468 	if (!aclblk) {
1469 		aclblk = kvzalloc_obj(*aclblk);
1470 		if (!aclblk)
1471 			return -ENOMEM;
1472 		priv->acl_blks[blkid] = aclblk;
1473 	}
1474 
1475 	/* Prepare acl rule ctrlblk */
1476 	aclrule = kvmemdup(&ruleext->r,
1477 			   offsetof(struct yt921x_acl_rule, entries[entscnt]),
1478 			   GFP_KERNEL);
1479 	if (!aclrule) {
1480 		res = -ENOMEM;
1481 		goto err;
1482 	}
1483 
1484 	/* Replace the placeholder resource IDs */
1485 	aclrule->mask = 0;
1486 	m = priv->acl_masks[blkid];
1487 	for_each_clear_bit(o, &m, YT921X_ACL_ENT_PER_BLK) {
1488 		aclrule->mask |= BIT(o);
1489 		entscnt--;
1490 		if (!entscnt)
1491 			break;
1492 	}
1493 
1494 	if (use_trap) {
1495 		aclrule->action[2] &= ~YT921X_ACL_ACTc_FWD_REDIR_DPORTS_M &
1496 				      ~YT921X_ACL_ACTc_FWD_M;
1497 		aclrule->action[2] |= YT921X_ACL_ACTc_FWD_EN |
1498 				      YT921X_ACL_ACTc_FWD_TRAP;
1499 	}
1500 	if (meterid < YT921X_METER_NUM)
1501 		aclrule->action[0] |= YT921X_ACL_ACTa_METER_ID(meterid);
1502 	else
1503 		aclrule->action[0] &= ~YT921X_ACL_ACTa_METER_EN;
1504 
1505 	/* Activate ACL if needed */
1506 	ctrl = 0;
1507 	m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, ruleext->r.entries[0].key[1]);
1508 	for_each_set_bit(o, &m, YT921X_PORT_NUM)
1509 		if (!priv->ports[o].acl_cnt)
1510 			ctrl |= YT921X_ACL_PORT_PORTn(o);
1511 	if (ctrl) {
1512 		ctrl |= yt921x_acl_activated_ports(priv);
1513 		res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl);
1514 		if (res)
1515 			goto err;
1516 	}
1517 
1518 	/* Write rules */
1519 	aclblk->rules[binid] = aclrule;
1520 	res = yt921x_acl_commit(priv, entid, aclrule->mask);
1521 	if (res) {
1522 		aclblk->rules[binid] = NULL;
1523 		goto err;
1524 	}
1525 
1526 	/* Bookkeeping */
1527 	m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, ruleext->r.entries[0].key[1]);
1528 	for_each_set_bit(o, &m, YT921X_PORT_NUM)
1529 		priv->ports[o].acl_cnt++;
1530 
1531 	if (meterid < YT921X_METER_NUM)
1532 		set_bit(meterid, priv->meters_map);
1533 	priv->acl_masks[blkid] |= aclrule->mask;
1534 	return 0;
1535 
1536 err:
1537 	kvfree(aclrule);
1538 	if (!priv->acl_masks[blkid]) {
1539 		kvfree(aclblk);
1540 		priv->acl_blks[blkid] = NULL;
1541 	}
1542 	return res;
1543 }
1544 
1545 int
1546 yt921x_dsa_cls_flower_del(struct dsa_switch *ds, int port,
1547 			  struct flow_cls_offload *cls, bool ingress)
1548 {
1549 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
1550 	int res;
1551 
1552 	mutex_lock(&priv->reg_lock);
1553 	res = yt921x_acl_del(priv, TC_SETUP_CLSFLOWER, cls->cookie);
1554 	mutex_unlock(&priv->reg_lock);
1555 
1556 	return res;
1557 }
1558 
1559 int
1560 yt921x_dsa_cls_flower_add(struct dsa_switch *ds, int port,
1561 			  struct flow_cls_offload *cls, bool ingress)
1562 {
1563 	struct netlink_ext_ack *extack = cls->common.extack;
1564 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
1565 	struct yt921x_acl_rule_ext ruleext;
1566 	int res;
1567 
1568 	res = yt921x_acl_rule_ext_parse_flow(&ruleext, port, cls, ingress,
1569 					     priv);
1570 	if (res)
1571 		return res;
1572 
1573 	mutex_lock(&priv->reg_lock);
1574 	res = yt921x_acl_add(priv, &ruleext, extack);
1575 	mutex_unlock(&priv->reg_lock);
1576 
1577 	return res;
1578 }
1579 
1580 static int
1581 yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress)
1582 {
1583 	u32 mask;
1584 
1585 	if (ingress)
1586 		mask = YT921X_MIRROR_IGR_PORTn(port);
1587 	else
1588 		mask = YT921X_MIRROR_EGR_PORTn(port);
1589 	return yt921x_reg_clear_bits(priv, YT921X_MIRROR, mask);
1590 }
1591 
1592 static int
1593 yt921x_mirror_add(struct yt921x_priv *priv, int port, bool ingress,
1594 		  int to_local_port, struct netlink_ext_ack *extack)
1595 {
1596 	u32 srcs;
1597 	u32 ctrl;
1598 	u32 val;
1599 	u32 dst;
1600 	int res;
1601 
1602 	if (ingress)
1603 		srcs = YT921X_MIRROR_IGR_PORTn(port);
1604 	else
1605 		srcs = YT921X_MIRROR_EGR_PORTn(port);
1606 	dst = YT921X_MIRROR_PORT(to_local_port);
1607 
1608 	res = yt921x_reg_read(priv, YT921X_MIRROR, &val);
1609 	if (res)
1610 		return res;
1611 
1612 	/* other mirror tasks & different dst port -> conflict */
1613 	if ((val & ~srcs & (YT921X_MIRROR_EGR_PORTS_M |
1614 			    YT921X_MIRROR_IGR_PORTS_M)) &&
1615 	    (val & YT921X_MIRROR_PORT_M) != dst) {
1616 		NL_SET_ERR_MSG_MOD(extack,
1617 				   "Sniffer port is already configured, delete existing rules & retry");
1618 		return -EBUSY;
1619 	}
1620 
1621 	ctrl = val & ~YT921X_MIRROR_PORT_M;
1622 	ctrl |= srcs;
1623 	ctrl |= dst;
1624 
1625 	if (ctrl == val)
1626 		return 0;
1627 
1628 	return yt921x_reg_write(priv, YT921X_MIRROR, ctrl);
1629 }
1630 
1631 void
1632 yt921x_dsa_port_mirror_del(struct dsa_switch *ds, int port,
1633 			   struct dsa_mall_mirror_tc_entry *mirror)
1634 {
1635 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
1636 	struct device *dev = yt921x_priv_to_device(priv);
1637 	int res;
1638 
1639 	mutex_lock(&priv->reg_lock);
1640 	res = yt921x_mirror_del(priv, port, mirror->ingress);
1641 	mutex_unlock(&priv->reg_lock);
1642 
1643 	if (res)
1644 		dev_err(dev, "Failed to %s port %d: %i\n", "unmirror",
1645 			port, res);
1646 }
1647 
1648 int
1649 yt921x_dsa_port_mirror_add(struct dsa_switch *ds, int port,
1650 			   struct dsa_mall_mirror_tc_entry *mirror,
1651 			   bool ingress, struct netlink_ext_ack *extack)
1652 {
1653 	struct yt921x_priv *priv = dsa_to_yt921x_priv(ds);
1654 	int res;
1655 
1656 	mutex_lock(&priv->reg_lock);
1657 	res = yt921x_mirror_add(priv, port, ingress,
1658 				mirror->to_local_port, extack);
1659 	mutex_unlock(&priv->reg_lock);
1660 
1661 	return res;
1662 }
1663 
1664 int yt921x_chip_setup_tc(struct yt921x_priv *priv)
1665 {
1666 	unsigned int op_ns;
1667 	u32 ctrl;
1668 	int res;
1669 
1670 	op_ns = 8 * priv->cycle_ns;
1671 
1672 	ctrl = max(priv->meter_slot_ns / op_ns, YT921X_METER_SLOT_MIN);
1673 	res = yt921x_reg_write(priv, YT921X_METER_SLOT, ctrl);
1674 	if (res)
1675 		return res;
1676 	priv->meter_slot_ns = ctrl * op_ns;
1677 
1678 	ctrl = max(priv->port_shape_slot_ns / op_ns,
1679 		   YT921X_PORT_SHAPE_SLOT_MIN);
1680 	res = yt921x_reg_write(priv, YT921X_PORT_SHAPE_SLOT, ctrl);
1681 	if (res)
1682 		return res;
1683 	priv->port_shape_slot_ns = ctrl * op_ns;
1684 
1685 	return 0;
1686 }
1687 
1688 int yt921x_chip_setup_acl(struct yt921x_priv *priv)
1689 {
1690 	u32 ctrl;
1691 	int res;
1692 
1693 	ctrl = YT921X_ACL_PERMIT_UNMATCH_PORTS_M;
1694 	res = yt921x_reg_write(priv, YT921X_ACL_PERMIT_UNMATCH, ctrl);
1695 	if (res)
1696 		return res;
1697 
1698 	res = yt921x_reg_write(priv, YT921X_ACL_PORT, 0);
1699 	if (res)
1700 		return res;
1701 
1702 	for (unsigned int o = 0; o < ARRAY_SIZE(yt921x_udf_maps); o++) {
1703 		ctrl = YT921X_UDF_CTRL_UDF_OFFSET(yt921x_udf_maps[o].offset) |
1704 		       YT921X_UDF_CTRL_UDF_TYPE(yt921x_udf_maps[o].type);
1705 		res = yt921x_reg_write(priv, YT921X_UDFn_CTRL(o), ctrl);
1706 		if (res)
1707 			return res;
1708 	}
1709 
1710 	return 0;
1711 }
1712