xref: /openbmc/linux/drivers/net/dsa/bcm_sf2_cfp.c (revision 2fa49589)
1 /*
2  * Broadcom Starfighter 2 DSA switch CFP support
3  *
4  * Copyright (C) 2016, Broadcom
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #include <linux/list.h>
13 #include <linux/ethtool.h>
14 #include <linux/if_ether.h>
15 #include <linux/in.h>
16 #include <linux/netdevice.h>
17 #include <net/dsa.h>
18 #include <linux/bitmap.h>
19 
20 #include "bcm_sf2.h"
21 #include "bcm_sf2_regs.h"
22 
23 struct cfp_rule {
24 	int port;
25 	struct ethtool_rx_flow_spec fs;
26 	struct list_head next;
27 };
28 
29 struct cfp_udf_slice_layout {
30 	u8 slices[UDFS_PER_SLICE];
31 	u32 mask_value;
32 	u32 base_offset;
33 };
34 
35 struct cfp_udf_layout {
36 	struct cfp_udf_slice_layout udfs[UDF_NUM_SLICES];
37 };
38 
39 static const u8 zero_slice[UDFS_PER_SLICE] = { };
40 
41 /* UDF slices layout for a TCPv4/UDPv4 specification */
42 static const struct cfp_udf_layout udf_tcpip4_layout = {
43 	.udfs = {
44 		[1] = {
45 			.slices = {
46 				/* End of L2, byte offset 12, src IP[0:15] */
47 				CFG_UDF_EOL2 | 6,
48 				/* End of L2, byte offset 14, src IP[16:31] */
49 				CFG_UDF_EOL2 | 7,
50 				/* End of L2, byte offset 16, dst IP[0:15] */
51 				CFG_UDF_EOL2 | 8,
52 				/* End of L2, byte offset 18, dst IP[16:31] */
53 				CFG_UDF_EOL2 | 9,
54 				/* End of L3, byte offset 0, src port */
55 				CFG_UDF_EOL3 | 0,
56 				/* End of L3, byte offset 2, dst port */
57 				CFG_UDF_EOL3 | 1,
58 				0, 0, 0
59 			},
60 			.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
61 			.base_offset = CORE_UDF_0_A_0_8_PORT_0 + UDF_SLICE_OFFSET,
62 		},
63 	},
64 };
65 
66 /* UDF slices layout for a TCPv6/UDPv6 specification */
67 static const struct cfp_udf_layout udf_tcpip6_layout = {
68 	.udfs = {
69 		[0] = {
70 			.slices = {
71 				/* End of L2, byte offset 8, src IP[0:15] */
72 				CFG_UDF_EOL2 | 4,
73 				/* End of L2, byte offset 10, src IP[16:31] */
74 				CFG_UDF_EOL2 | 5,
75 				/* End of L2, byte offset 12, src IP[32:47] */
76 				CFG_UDF_EOL2 | 6,
77 				/* End of L2, byte offset 14, src IP[48:63] */
78 				CFG_UDF_EOL2 | 7,
79 				/* End of L2, byte offset 16, src IP[64:79] */
80 				CFG_UDF_EOL2 | 8,
81 				/* End of L2, byte offset 18, src IP[80:95] */
82 				CFG_UDF_EOL2 | 9,
83 				/* End of L2, byte offset 20, src IP[96:111] */
84 				CFG_UDF_EOL2 | 10,
85 				/* End of L2, byte offset 22, src IP[112:127] */
86 				CFG_UDF_EOL2 | 11,
87 				/* End of L3, byte offset 0, src port */
88 				CFG_UDF_EOL3 | 0,
89 			},
90 			.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
91 			.base_offset = CORE_UDF_0_B_0_8_PORT_0,
92 		},
93 		[3] = {
94 			.slices = {
95 				/* End of L2, byte offset 24, dst IP[0:15] */
96 				CFG_UDF_EOL2 | 12,
97 				/* End of L2, byte offset 26, dst IP[16:31] */
98 				CFG_UDF_EOL2 | 13,
99 				/* End of L2, byte offset 28, dst IP[32:47] */
100 				CFG_UDF_EOL2 | 14,
101 				/* End of L2, byte offset 30, dst IP[48:63] */
102 				CFG_UDF_EOL2 | 15,
103 				/* End of L2, byte offset 32, dst IP[64:79] */
104 				CFG_UDF_EOL2 | 16,
105 				/* End of L2, byte offset 34, dst IP[80:95] */
106 				CFG_UDF_EOL2 | 17,
107 				/* End of L2, byte offset 36, dst IP[96:111] */
108 				CFG_UDF_EOL2 | 18,
109 				/* End of L2, byte offset 38, dst IP[112:127] */
110 				CFG_UDF_EOL2 | 19,
111 				/* End of L3, byte offset 2, dst port */
112 				CFG_UDF_EOL3 | 1,
113 			},
114 			.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
115 			.base_offset = CORE_UDF_0_D_0_11_PORT_0,
116 		},
117 	},
118 };
119 
120 static inline unsigned int bcm_sf2_get_num_udf_slices(const u8 *layout)
121 {
122 	unsigned int i, count = 0;
123 
124 	for (i = 0; i < UDFS_PER_SLICE; i++) {
125 		if (layout[i] != 0)
126 			count++;
127 	}
128 
129 	return count;
130 }
131 
132 static inline u32 udf_upper_bits(unsigned int num_udf)
133 {
134 	return GENMASK(num_udf - 1, 0) >> (UDFS_PER_SLICE - 1);
135 }
136 
137 static inline u32 udf_lower_bits(unsigned int num_udf)
138 {
139 	return (u8)GENMASK(num_udf - 1, 0);
140 }
141 
142 static unsigned int bcm_sf2_get_slice_number(const struct cfp_udf_layout *l,
143 					     unsigned int start)
144 {
145 	const struct cfp_udf_slice_layout *slice_layout;
146 	unsigned int slice_idx;
147 
148 	for (slice_idx = start; slice_idx < UDF_NUM_SLICES; slice_idx++) {
149 		slice_layout = &l->udfs[slice_idx];
150 		if (memcmp(slice_layout->slices, zero_slice,
151 			   sizeof(zero_slice)))
152 			break;
153 	}
154 
155 	return slice_idx;
156 }
157 
158 static void bcm_sf2_cfp_udf_set(struct bcm_sf2_priv *priv,
159 				const struct cfp_udf_layout *layout,
160 				unsigned int slice_num)
161 {
162 	u32 offset = layout->udfs[slice_num].base_offset;
163 	unsigned int i;
164 
165 	for (i = 0; i < UDFS_PER_SLICE; i++)
166 		core_writel(priv, layout->udfs[slice_num].slices[i],
167 			    offset + i * 4);
168 }
169 
170 static int bcm_sf2_cfp_op(struct bcm_sf2_priv *priv, unsigned int op)
171 {
172 	unsigned int timeout = 1000;
173 	u32 reg;
174 
175 	reg = core_readl(priv, CORE_CFP_ACC);
176 	reg &= ~(OP_SEL_MASK | RAM_SEL_MASK);
177 	reg |= OP_STR_DONE | op;
178 	core_writel(priv, reg, CORE_CFP_ACC);
179 
180 	do {
181 		reg = core_readl(priv, CORE_CFP_ACC);
182 		if (!(reg & OP_STR_DONE))
183 			break;
184 
185 		cpu_relax();
186 	} while (timeout--);
187 
188 	if (!timeout)
189 		return -ETIMEDOUT;
190 
191 	return 0;
192 }
193 
194 static inline void bcm_sf2_cfp_rule_addr_set(struct bcm_sf2_priv *priv,
195 					     unsigned int addr)
196 {
197 	u32 reg;
198 
199 	WARN_ON(addr >= priv->num_cfp_rules);
200 
201 	reg = core_readl(priv, CORE_CFP_ACC);
202 	reg &= ~(XCESS_ADDR_MASK << XCESS_ADDR_SHIFT);
203 	reg |= addr << XCESS_ADDR_SHIFT;
204 	core_writel(priv, reg, CORE_CFP_ACC);
205 }
206 
207 static inline unsigned int bcm_sf2_cfp_rule_size(struct bcm_sf2_priv *priv)
208 {
209 	/* Entry #0 is reserved */
210 	return priv->num_cfp_rules - 1;
211 }
212 
213 static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
214 				   unsigned int rule_index,
215 				   unsigned int port_num,
216 				   unsigned int queue_num,
217 				   bool fwd_map_change)
218 {
219 	int ret;
220 	u32 reg;
221 
222 	/* Replace ARL derived destination with DST_MAP derived, define
223 	 * which port and queue this should be forwarded to.
224 	 */
225 	if (fwd_map_change)
226 		reg = CHANGE_FWRD_MAP_IB_REP_ARL |
227 		      BIT(port_num + DST_MAP_IB_SHIFT) |
228 		      CHANGE_TC | queue_num << NEW_TC_SHIFT;
229 	else
230 		reg = 0;
231 
232 	core_writel(priv, reg, CORE_ACT_POL_DATA0);
233 
234 	/* Set classification ID that needs to be put in Broadcom tag */
235 	core_writel(priv, rule_index << CHAIN_ID_SHIFT, CORE_ACT_POL_DATA1);
236 
237 	core_writel(priv, 0, CORE_ACT_POL_DATA2);
238 
239 	/* Configure policer RAM now */
240 	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | ACT_POL_RAM);
241 	if (ret) {
242 		pr_err("Policer entry at %d failed\n", rule_index);
243 		return ret;
244 	}
245 
246 	/* Disable the policer */
247 	core_writel(priv, POLICER_MODE_DISABLE, CORE_RATE_METER0);
248 
249 	/* Now the rate meter */
250 	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | RATE_METER_RAM);
251 	if (ret) {
252 		pr_err("Meter entry at %d failed\n", rule_index);
253 		return ret;
254 	}
255 
256 	return 0;
257 }
258 
259 static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
260 				   struct ethtool_tcpip4_spec *v4_spec,
261 				   unsigned int slice_num,
262 				   bool mask)
263 {
264 	u32 reg, offset;
265 
266 	/* C-Tag		[31:24]
267 	 * UDF_n_A8		[23:8]
268 	 * UDF_n_A7		[7:0]
269 	 */
270 	reg = 0;
271 	if (mask)
272 		offset = CORE_CFP_MASK_PORT(4);
273 	else
274 		offset = CORE_CFP_DATA_PORT(4);
275 	core_writel(priv, reg, offset);
276 
277 	/* UDF_n_A7		[31:24]
278 	 * UDF_n_A6		[23:8]
279 	 * UDF_n_A5		[7:0]
280 	 */
281 	reg = be16_to_cpu(v4_spec->pdst) >> 8;
282 	if (mask)
283 		offset = CORE_CFP_MASK_PORT(3);
284 	else
285 		offset = CORE_CFP_DATA_PORT(3);
286 	core_writel(priv, reg, offset);
287 
288 	/* UDF_n_A5		[31:24]
289 	 * UDF_n_A4		[23:8]
290 	 * UDF_n_A3		[7:0]
291 	 */
292 	reg = (be16_to_cpu(v4_spec->pdst) & 0xff) << 24 |
293 	      (u32)be16_to_cpu(v4_spec->psrc) << 8 |
294 	      (be32_to_cpu(v4_spec->ip4dst) & 0x0000ff00) >> 8;
295 	if (mask)
296 		offset = CORE_CFP_MASK_PORT(2);
297 	else
298 		offset = CORE_CFP_DATA_PORT(2);
299 	core_writel(priv, reg, offset);
300 
301 	/* UDF_n_A3		[31:24]
302 	 * UDF_n_A2		[23:8]
303 	 * UDF_n_A1		[7:0]
304 	 */
305 	reg = (u32)(be32_to_cpu(v4_spec->ip4dst) & 0xff) << 24 |
306 	      (u32)(be32_to_cpu(v4_spec->ip4dst) >> 16) << 8 |
307 	      (be32_to_cpu(v4_spec->ip4src) & 0x0000ff00) >> 8;
308 	if (mask)
309 		offset = CORE_CFP_MASK_PORT(1);
310 	else
311 		offset = CORE_CFP_DATA_PORT(1);
312 	core_writel(priv, reg, offset);
313 
314 	/* UDF_n_A1		[31:24]
315 	 * UDF_n_A0		[23:8]
316 	 * Reserved		[7:4]
317 	 * Slice ID		[3:2]
318 	 * Slice valid		[1:0]
319 	 */
320 	reg = (u32)(be32_to_cpu(v4_spec->ip4src) & 0xff) << 24 |
321 	      (u32)(be32_to_cpu(v4_spec->ip4src) >> 16) << 8 |
322 	      SLICE_NUM(slice_num) | SLICE_VALID;
323 	if (mask)
324 		offset = CORE_CFP_MASK_PORT(0);
325 	else
326 		offset = CORE_CFP_DATA_PORT(0);
327 	core_writel(priv, reg, offset);
328 }
329 
330 static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
331 				     unsigned int port_num,
332 				     unsigned int queue_num,
333 				     struct ethtool_rx_flow_spec *fs)
334 {
335 	struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec;
336 	const struct cfp_udf_layout *layout;
337 	unsigned int slice_num, rule_index;
338 	u8 ip_proto, ip_frag;
339 	u8 num_udf;
340 	u32 reg;
341 	int ret;
342 
343 	switch (fs->flow_type & ~FLOW_EXT) {
344 	case TCP_V4_FLOW:
345 		ip_proto = IPPROTO_TCP;
346 		v4_spec = &fs->h_u.tcp_ip4_spec;
347 		v4_m_spec = &fs->m_u.tcp_ip4_spec;
348 		break;
349 	case UDP_V4_FLOW:
350 		ip_proto = IPPROTO_UDP;
351 		v4_spec = &fs->h_u.udp_ip4_spec;
352 		v4_m_spec = &fs->m_u.udp_ip4_spec;
353 		break;
354 	default:
355 		return -EINVAL;
356 	}
357 
358 	ip_frag = be32_to_cpu(fs->m_ext.data[0]);
359 
360 	/* Locate the first rule available */
361 	if (fs->location == RX_CLS_LOC_ANY)
362 		rule_index = find_first_zero_bit(priv->cfp.used,
363 						 priv->num_cfp_rules);
364 	else
365 		rule_index = fs->location;
366 
367 	if (rule_index > bcm_sf2_cfp_rule_size(priv))
368 		return -ENOSPC;
369 
370 	layout = &udf_tcpip4_layout;
371 	/* We only use one UDF slice for now */
372 	slice_num = bcm_sf2_get_slice_number(layout, 0);
373 	if (slice_num == UDF_NUM_SLICES)
374 		return -EINVAL;
375 
376 	num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
377 
378 	/* Apply the UDF layout for this filter */
379 	bcm_sf2_cfp_udf_set(priv, layout, slice_num);
380 
381 	/* Apply to all packets received through this port */
382 	core_writel(priv, BIT(port), CORE_CFP_DATA_PORT(7));
383 
384 	/* Source port map match */
385 	core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7));
386 
387 	/* S-Tag status		[31:30]
388 	 * C-Tag status		[29:28]
389 	 * L2 framing		[27:26]
390 	 * L3 framing		[25:24]
391 	 * IP ToS		[23:16]
392 	 * IP proto		[15:08]
393 	 * IP Fragm		[7]
394 	 * Non 1st frag		[6]
395 	 * IP Authen		[5]
396 	 * TTL range		[4:3]
397 	 * PPPoE session	[2]
398 	 * Reserved		[1]
399 	 * UDF_Valid[8]		[0]
400 	 */
401 	core_writel(priv, v4_spec->tos << IPTOS_SHIFT |
402 		    ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
403 		    udf_upper_bits(num_udf),
404 		    CORE_CFP_DATA_PORT(6));
405 
406 	/* Mask with the specific layout for IPv4 packets */
407 	core_writel(priv, layout->udfs[slice_num].mask_value |
408 		    udf_upper_bits(num_udf), CORE_CFP_MASK_PORT(6));
409 
410 	/* UDF_Valid[7:0]	[31:24]
411 	 * S-Tag		[23:8]
412 	 * C-Tag		[7:0]
413 	 */
414 	core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_DATA_PORT(5));
415 
416 	/* Mask all but valid UDFs */
417 	core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
418 
419 	/* Program the match and the mask */
420 	bcm_sf2_cfp_slice_ipv4(priv, v4_spec, slice_num, false);
421 	bcm_sf2_cfp_slice_ipv4(priv, v4_m_spec, SLICE_NUM_MASK, true);
422 
423 	/* Insert into TCAM now */
424 	bcm_sf2_cfp_rule_addr_set(priv, rule_index);
425 
426 	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
427 	if (ret) {
428 		pr_err("TCAM entry at addr %d failed\n", rule_index);
429 		return ret;
430 	}
431 
432 	/* Insert into Action and policer RAMs now */
433 	ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port_num,
434 				      queue_num, true);
435 	if (ret)
436 		return ret;
437 
438 	/* Turn on CFP for this rule now */
439 	reg = core_readl(priv, CORE_CFP_CTL_REG);
440 	reg |= BIT(port);
441 	core_writel(priv, reg, CORE_CFP_CTL_REG);
442 
443 	/* Flag the rule as being used and return it */
444 	set_bit(rule_index, priv->cfp.used);
445 	set_bit(rule_index, priv->cfp.unique);
446 	fs->location = rule_index;
447 
448 	return 0;
449 }
450 
451 static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv,
452 				   const __be32 *ip6_addr, const __be16 port,
453 				   unsigned int slice_num,
454 				   bool mask)
455 {
456 	u32 reg, tmp, val, offset;
457 
458 	/* C-Tag		[31:24]
459 	 * UDF_n_B8		[23:8]	(port)
460 	 * UDF_n_B7 (upper)	[7:0]	(addr[15:8])
461 	 */
462 	reg = be32_to_cpu(ip6_addr[3]);
463 	val = (u32)be16_to_cpu(port) << 8 | ((reg >> 8) & 0xff);
464 	if (mask)
465 		offset = CORE_CFP_MASK_PORT(4);
466 	else
467 		offset = CORE_CFP_DATA_PORT(4);
468 	core_writel(priv, val, offset);
469 
470 	/* UDF_n_B7 (lower)	[31:24]	(addr[7:0])
471 	 * UDF_n_B6		[23:8] (addr[31:16])
472 	 * UDF_n_B5 (upper)	[7:0] (addr[47:40])
473 	 */
474 	tmp = be32_to_cpu(ip6_addr[2]);
475 	val = (u32)(reg & 0xff) << 24 | (u32)(reg >> 16) << 8 |
476 	      ((tmp >> 8) & 0xff);
477 	if (mask)
478 		offset = CORE_CFP_MASK_PORT(3);
479 	else
480 		offset = CORE_CFP_DATA_PORT(3);
481 	core_writel(priv, val, offset);
482 
483 	/* UDF_n_B5 (lower)	[31:24] (addr[39:32])
484 	 * UDF_n_B4		[23:8] (addr[63:48])
485 	 * UDF_n_B3 (upper)	[7:0] (addr[79:72])
486 	 */
487 	reg = be32_to_cpu(ip6_addr[1]);
488 	val = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 |
489 	      ((reg >> 8) & 0xff);
490 	if (mask)
491 		offset = CORE_CFP_MASK_PORT(2);
492 	else
493 		offset = CORE_CFP_DATA_PORT(2);
494 	core_writel(priv, val, offset);
495 
496 	/* UDF_n_B3 (lower)	[31:24] (addr[71:64])
497 	 * UDF_n_B2		[23:8] (addr[95:80])
498 	 * UDF_n_B1 (upper)	[7:0] (addr[111:104])
499 	 */
500 	tmp = be32_to_cpu(ip6_addr[0]);
501 	val = (u32)(reg & 0xff) << 24 | (u32)(reg >> 16) << 8 |
502 	      ((tmp >> 8) & 0xff);
503 	if (mask)
504 		offset = CORE_CFP_MASK_PORT(1);
505 	else
506 		offset = CORE_CFP_DATA_PORT(1);
507 	core_writel(priv, val, offset);
508 
509 	/* UDF_n_B1 (lower)	[31:24] (addr[103:96])
510 	 * UDF_n_B0		[23:8] (addr[127:112])
511 	 * Reserved		[7:4]
512 	 * Slice ID		[3:2]
513 	 * Slice valid		[1:0]
514 	 */
515 	reg = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 |
516 	       SLICE_NUM(slice_num) | SLICE_VALID;
517 	if (mask)
518 		offset = CORE_CFP_MASK_PORT(0);
519 	else
520 		offset = CORE_CFP_DATA_PORT(0);
521 	core_writel(priv, reg, offset);
522 }
523 
524 static struct cfp_rule *bcm_sf2_cfp_rule_find(struct bcm_sf2_priv *priv,
525 					      int port, u32 location)
526 {
527 	struct cfp_rule *rule = NULL;
528 
529 	list_for_each_entry(rule, &priv->cfp.rules_list, next) {
530 		if (rule->port == port && rule->fs.location == location)
531 			break;
532 	}
533 
534 	return rule;
535 }
536 
537 static int bcm_sf2_cfp_rule_cmp(struct bcm_sf2_priv *priv, int port,
538 				struct ethtool_rx_flow_spec *fs)
539 {
540 	struct cfp_rule *rule = NULL;
541 	size_t fs_size = 0;
542 	int ret = 1;
543 
544 	if (list_empty(&priv->cfp.rules_list))
545 		return ret;
546 
547 	list_for_each_entry(rule, &priv->cfp.rules_list, next) {
548 		ret = 1;
549 		if (rule->port != port)
550 			continue;
551 
552 		if (rule->fs.flow_type != fs->flow_type ||
553 		    rule->fs.ring_cookie != fs->ring_cookie ||
554 		    rule->fs.m_ext.data[0] != fs->m_ext.data[0])
555 			continue;
556 
557 		switch (fs->flow_type & ~FLOW_EXT) {
558 		case TCP_V6_FLOW:
559 		case UDP_V6_FLOW:
560 			fs_size = sizeof(struct ethtool_tcpip6_spec);
561 			break;
562 		case TCP_V4_FLOW:
563 		case UDP_V4_FLOW:
564 			fs_size = sizeof(struct ethtool_tcpip4_spec);
565 			break;
566 		default:
567 			continue;
568 		}
569 
570 		ret = memcmp(&rule->fs.h_u, &fs->h_u, fs_size);
571 		ret |= memcmp(&rule->fs.m_u, &fs->m_u, fs_size);
572 		if (ret == 0)
573 			break;
574 	}
575 
576 	return ret;
577 }
578 
579 static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
580 				     unsigned int port_num,
581 				     unsigned int queue_num,
582 				     struct ethtool_rx_flow_spec *fs)
583 {
584 	struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec;
585 	unsigned int slice_num, rule_index[2];
586 	const struct cfp_udf_layout *layout;
587 	u8 ip_proto, ip_frag;
588 	int ret = 0;
589 	u8 num_udf;
590 	u32 reg;
591 
592 	switch (fs->flow_type & ~FLOW_EXT) {
593 	case TCP_V6_FLOW:
594 		ip_proto = IPPROTO_TCP;
595 		v6_spec = &fs->h_u.tcp_ip6_spec;
596 		v6_m_spec = &fs->m_u.tcp_ip6_spec;
597 		break;
598 	case UDP_V6_FLOW:
599 		ip_proto = IPPROTO_UDP;
600 		v6_spec = &fs->h_u.udp_ip6_spec;
601 		v6_m_spec = &fs->m_u.udp_ip6_spec;
602 		break;
603 	default:
604 		return -EINVAL;
605 	}
606 
607 	ip_frag = be32_to_cpu(fs->m_ext.data[0]);
608 
609 	layout = &udf_tcpip6_layout;
610 	slice_num = bcm_sf2_get_slice_number(layout, 0);
611 	if (slice_num == UDF_NUM_SLICES)
612 		return -EINVAL;
613 
614 	num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
615 
616 	/* Negotiate two indexes, one for the second half which we are chained
617 	 * from, which is what we will return to user-space, and a second one
618 	 * which is used to store its first half. That first half does not
619 	 * allow any choice of placement, so it just needs to find the next
620 	 * available bit. We return the second half as fs->location because
621 	 * that helps with the rule lookup later on since the second half is
622 	 * chained from its first half, we can easily identify IPv6 CFP rules
623 	 * by looking whether they carry a CHAIN_ID.
624 	 *
625 	 * We also want the second half to have a lower rule_index than its
626 	 * first half because the HW search is by incrementing addresses.
627 	 */
628 	if (fs->location == RX_CLS_LOC_ANY)
629 		rule_index[1] = find_first_zero_bit(priv->cfp.used,
630 						    priv->num_cfp_rules);
631 	else
632 		rule_index[1] = fs->location;
633 	if (rule_index[1] > bcm_sf2_cfp_rule_size(priv))
634 		return -ENOSPC;
635 
636 	/* Flag it as used (cleared on error path) such that we can immediately
637 	 * obtain a second one to chain from.
638 	 */
639 	set_bit(rule_index[1], priv->cfp.used);
640 
641 	rule_index[0] = find_first_zero_bit(priv->cfp.used,
642 					    priv->num_cfp_rules);
643 	if (rule_index[0] > bcm_sf2_cfp_rule_size(priv)) {
644 		ret = -ENOSPC;
645 		goto out_err;
646 	}
647 
648 	/* Apply the UDF layout for this filter */
649 	bcm_sf2_cfp_udf_set(priv, layout, slice_num);
650 
651 	/* Apply to all packets received through this port */
652 	core_writel(priv, BIT(port), CORE_CFP_DATA_PORT(7));
653 
654 	/* Source port map match */
655 	core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7));
656 
657 	/* S-Tag status		[31:30]
658 	 * C-Tag status		[29:28]
659 	 * L2 framing		[27:26]
660 	 * L3 framing		[25:24]
661 	 * IP ToS		[23:16]
662 	 * IP proto		[15:08]
663 	 * IP Fragm		[7]
664 	 * Non 1st frag		[6]
665 	 * IP Authen		[5]
666 	 * TTL range		[4:3]
667 	 * PPPoE session	[2]
668 	 * Reserved		[1]
669 	 * UDF_Valid[8]		[0]
670 	 */
671 	reg = 1 << L3_FRAMING_SHIFT | ip_proto << IPPROTO_SHIFT |
672 		ip_frag << IP_FRAG_SHIFT | udf_upper_bits(num_udf);
673 	core_writel(priv, reg, CORE_CFP_DATA_PORT(6));
674 
675 	/* Mask with the specific layout for IPv6 packets including
676 	 * UDF_Valid[8]
677 	 */
678 	reg = layout->udfs[slice_num].mask_value | udf_upper_bits(num_udf);
679 	core_writel(priv, reg, CORE_CFP_MASK_PORT(6));
680 
681 	/* UDF_Valid[7:0]	[31:24]
682 	 * S-Tag		[23:8]
683 	 * C-Tag		[7:0]
684 	 */
685 	core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_DATA_PORT(5));
686 
687 	/* Mask all but valid UDFs */
688 	core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5));
689 
690 	/* Slice the IPv6 source address and port */
691 	bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc,
692 				slice_num, false);
693 	bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6src, v6_m_spec->psrc,
694 				SLICE_NUM_MASK, true);
695 
696 	/* Insert into TCAM now because we need to insert a second rule */
697 	bcm_sf2_cfp_rule_addr_set(priv, rule_index[0]);
698 
699 	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
700 	if (ret) {
701 		pr_err("TCAM entry at addr %d failed\n", rule_index[0]);
702 		goto out_err;
703 	}
704 
705 	/* Insert into Action and policer RAMs now */
706 	ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port_num,
707 				      queue_num, false);
708 	if (ret)
709 		goto out_err;
710 
711 	/* Now deal with the second slice to chain this rule */
712 	slice_num = bcm_sf2_get_slice_number(layout, slice_num + 1);
713 	if (slice_num == UDF_NUM_SLICES) {
714 		ret = -EINVAL;
715 		goto out_err;
716 	}
717 
718 	num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);
719 
720 	/* Apply the UDF layout for this filter */
721 	bcm_sf2_cfp_udf_set(priv, layout, slice_num);
722 
723 	/* Chained rule, source port match is coming from the rule we are
724 	 * chained from.
725 	 */
726 	core_writel(priv, 0, CORE_CFP_DATA_PORT(7));
727 	core_writel(priv, 0, CORE_CFP_MASK_PORT(7));
728 
729 	/*
730 	 * CHAIN ID		[31:24] chain to previous slice
731 	 * Reserved		[23:20]
732 	 * UDF_Valid[11:8]	[19:16]
733 	 * UDF_Valid[7:0]	[15:8]
734 	 * UDF_n_D11		[7:0]
735 	 */
736 	reg = rule_index[0] << 24 | udf_upper_bits(num_udf) << 16 |
737 		udf_lower_bits(num_udf) << 8;
738 	core_writel(priv, reg, CORE_CFP_DATA_PORT(6));
739 
740 	/* Mask all except chain ID, UDF Valid[8] and UDF Valid[7:0] */
741 	reg = XCESS_ADDR_MASK << 24 | udf_upper_bits(num_udf) << 16 |
742 		udf_lower_bits(num_udf) << 8;
743 	core_writel(priv, reg, CORE_CFP_MASK_PORT(6));
744 
745 	/* Don't care */
746 	core_writel(priv, 0, CORE_CFP_DATA_PORT(5));
747 
748 	/* Mask all */
749 	core_writel(priv, 0, CORE_CFP_MASK_PORT(5));
750 
751 	bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num,
752 			       false);
753 	bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6dst, v6_m_spec->pdst,
754 			       SLICE_NUM_MASK, true);
755 
756 	/* Insert into TCAM now */
757 	bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]);
758 
759 	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
760 	if (ret) {
761 		pr_err("TCAM entry at addr %d failed\n", rule_index[1]);
762 		goto out_err;
763 	}
764 
765 	/* Insert into Action and policer RAMs now, set chain ID to
766 	 * the one we are chained to
767 	 */
768 	ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port_num,
769 				      queue_num, true);
770 	if (ret)
771 		goto out_err;
772 
773 	/* Turn on CFP for this rule now */
774 	reg = core_readl(priv, CORE_CFP_CTL_REG);
775 	reg |= BIT(port);
776 	core_writel(priv, reg, CORE_CFP_CTL_REG);
777 
778 	/* Flag the second half rule as being used now, return it as the
779 	 * location, and flag it as unique while dumping rules
780 	 */
781 	set_bit(rule_index[0], priv->cfp.used);
782 	set_bit(rule_index[1], priv->cfp.unique);
783 	fs->location = rule_index[1];
784 
785 	return ret;
786 
787 out_err:
788 	clear_bit(rule_index[1], priv->cfp.used);
789 	return ret;
790 }
791 
792 static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port,
793 				   struct ethtool_rx_flow_spec *fs)
794 {
795 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
796 	s8 cpu_port = ds->ports[port].cpu_dp->index;
797 	__u64 ring_cookie = fs->ring_cookie;
798 	unsigned int queue_num, port_num;
799 	int ret;
800 
801 	/* This rule is a Wake-on-LAN filter and we must specifically
802 	 * target the CPU port in order for it to be working.
803 	 */
804 	if (ring_cookie == RX_CLS_FLOW_WAKE)
805 		ring_cookie = cpu_port * SF2_NUM_EGRESS_QUEUES;
806 
807 	/* We do not support discarding packets, check that the
808 	 * destination port is enabled and that we are within the
809 	 * number of ports supported by the switch
810 	 */
811 	port_num = ring_cookie / SF2_NUM_EGRESS_QUEUES;
812 
813 	if (ring_cookie == RX_CLS_FLOW_DISC ||
814 	    !(dsa_is_user_port(ds, port_num) ||
815 	      dsa_is_cpu_port(ds, port_num)) ||
816 	    port_num >= priv->hw_params.num_ports)
817 		return -EINVAL;
818 	/*
819 	 * We have a small oddity where Port 6 just does not have a
820 	 * valid bit here (so we substract by one).
821 	 */
822 	queue_num = ring_cookie % SF2_NUM_EGRESS_QUEUES;
823 	if (port_num >= 7)
824 		port_num -= 1;
825 
826 	switch (fs->flow_type & ~FLOW_EXT) {
827 	case TCP_V4_FLOW:
828 	case UDP_V4_FLOW:
829 		ret = bcm_sf2_cfp_ipv4_rule_set(priv, port, port_num,
830 						queue_num, fs);
831 		break;
832 	case TCP_V6_FLOW:
833 	case UDP_V6_FLOW:
834 		ret = bcm_sf2_cfp_ipv6_rule_set(priv, port, port_num,
835 						queue_num, fs);
836 		break;
837 	default:
838 		ret = -EINVAL;
839 		break;
840 	}
841 
842 	return ret;
843 }
844 
845 static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port,
846 				struct ethtool_rx_flow_spec *fs)
847 {
848 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
849 	struct cfp_rule *rule = NULL;
850 	int ret = -EINVAL;
851 
852 	/* Check for unsupported extensions */
853 	if ((fs->flow_type & FLOW_EXT) && (fs->m_ext.vlan_etype ||
854 	     fs->m_ext.data[1]))
855 		return -EINVAL;
856 
857 	if (fs->location != RX_CLS_LOC_ANY &&
858 	    test_bit(fs->location, priv->cfp.used))
859 		return -EBUSY;
860 
861 	if (fs->location != RX_CLS_LOC_ANY &&
862 	    fs->location > bcm_sf2_cfp_rule_size(priv))
863 		return -EINVAL;
864 
865 	ret = bcm_sf2_cfp_rule_cmp(priv, port, fs);
866 	if (ret == 0)
867 		return -EEXIST;
868 
869 	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
870 	if (!rule)
871 		return -ENOMEM;
872 
873 	ret = bcm_sf2_cfp_rule_insert(ds, port, fs);
874 	if (ret) {
875 		kfree(rule);
876 		return ret;
877 	}
878 
879 	rule->port = port;
880 	memcpy(&rule->fs, fs, sizeof(*fs));
881 	list_add_tail(&rule->next, &priv->cfp.rules_list);
882 
883 	return ret;
884 }
885 
886 static int bcm_sf2_cfp_rule_del_one(struct bcm_sf2_priv *priv, int port,
887 				    u32 loc, u32 *next_loc)
888 {
889 	int ret;
890 	u32 reg;
891 
892 	/* Indicate which rule we want to read */
893 	bcm_sf2_cfp_rule_addr_set(priv, loc);
894 
895 	ret =  bcm_sf2_cfp_op(priv, OP_SEL_READ | TCAM_SEL);
896 	if (ret)
897 		return ret;
898 
899 	/* Check if this is possibly an IPv6 rule that would
900 	 * indicate we need to delete its companion rule
901 	 * as well
902 	 */
903 	reg = core_readl(priv, CORE_CFP_DATA_PORT(6));
904 	if (next_loc)
905 		*next_loc = (reg >> 24) & CHAIN_ID_MASK;
906 
907 	/* Clear its valid bits */
908 	reg = core_readl(priv, CORE_CFP_DATA_PORT(0));
909 	reg &= ~SLICE_VALID;
910 	core_writel(priv, reg, CORE_CFP_DATA_PORT(0));
911 
912 	/* Write back this entry into the TCAM now */
913 	ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
914 	if (ret)
915 		return ret;
916 
917 	clear_bit(loc, priv->cfp.used);
918 	clear_bit(loc, priv->cfp.unique);
919 
920 	return 0;
921 }
922 
923 static int bcm_sf2_cfp_rule_remove(struct bcm_sf2_priv *priv, int port,
924 				   u32 loc)
925 {
926 	u32 next_loc = 0;
927 	int ret;
928 
929 	ret = bcm_sf2_cfp_rule_del_one(priv, port, loc, &next_loc);
930 	if (ret)
931 		return ret;
932 
933 	/* If this was an IPv6 rule, delete is companion rule too */
934 	if (next_loc)
935 		ret = bcm_sf2_cfp_rule_del_one(priv, port, next_loc, NULL);
936 
937 	return ret;
938 }
939 
940 static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, int port, u32 loc)
941 {
942 	struct cfp_rule *rule;
943 	int ret;
944 
945 	/* Refuse deleting unused rules, and those that are not unique since
946 	 * that could leave IPv6 rules with one of the chained rule in the
947 	 * table.
948 	 */
949 	if (!test_bit(loc, priv->cfp.unique) || loc == 0)
950 		return -EINVAL;
951 
952 	rule = bcm_sf2_cfp_rule_find(priv, port, loc);
953 	if (!rule)
954 		return -EINVAL;
955 
956 	ret = bcm_sf2_cfp_rule_remove(priv, port, loc);
957 
958 	list_del(&rule->next);
959 	kfree(rule);
960 
961 	return ret;
962 }
963 
964 static void bcm_sf2_invert_masks(struct ethtool_rx_flow_spec *flow)
965 {
966 	unsigned int i;
967 
968 	for (i = 0; i < sizeof(flow->m_u); i++)
969 		flow->m_u.hdata[i] ^= 0xff;
970 
971 	flow->m_ext.vlan_etype ^= cpu_to_be16(~0);
972 	flow->m_ext.vlan_tci ^= cpu_to_be16(~0);
973 	flow->m_ext.data[0] ^= cpu_to_be32(~0);
974 	flow->m_ext.data[1] ^= cpu_to_be32(~0);
975 }
976 
977 static int bcm_sf2_cfp_rule_get(struct bcm_sf2_priv *priv, int port,
978 				struct ethtool_rxnfc *nfc)
979 {
980 	struct cfp_rule *rule;
981 
982 	rule = bcm_sf2_cfp_rule_find(priv, port, nfc->fs.location);
983 	if (!rule)
984 		return -EINVAL;
985 
986 	memcpy(&nfc->fs, &rule->fs, sizeof(rule->fs));
987 
988 	bcm_sf2_invert_masks(&nfc->fs);
989 
990 	/* Put the TCAM size here */
991 	nfc->data = bcm_sf2_cfp_rule_size(priv);
992 
993 	return 0;
994 }
995 
996 /* We implement the search doing a TCAM search operation */
997 static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
998 				    int port, struct ethtool_rxnfc *nfc,
999 				    u32 *rule_locs)
1000 {
1001 	unsigned int index = 1, rules_cnt = 0;
1002 
1003 	for_each_set_bit_from(index, priv->cfp.unique, priv->num_cfp_rules) {
1004 		rule_locs[rules_cnt] = index;
1005 		rules_cnt++;
1006 	}
1007 
1008 	/* Put the TCAM size here */
1009 	nfc->data = bcm_sf2_cfp_rule_size(priv);
1010 	nfc->rule_cnt = rules_cnt;
1011 
1012 	return 0;
1013 }
1014 
1015 int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
1016 		      struct ethtool_rxnfc *nfc, u32 *rule_locs)
1017 {
1018 	struct net_device *p = ds->ports[port].cpu_dp->master;
1019 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
1020 	int ret = 0;
1021 
1022 	mutex_lock(&priv->cfp.lock);
1023 
1024 	switch (nfc->cmd) {
1025 	case ETHTOOL_GRXCLSRLCNT:
1026 		/* Subtract the default, unusable rule */
1027 		nfc->rule_cnt = bitmap_weight(priv->cfp.unique,
1028 					      priv->num_cfp_rules) - 1;
1029 		/* We support specifying rule locations */
1030 		nfc->data |= RX_CLS_LOC_SPECIAL;
1031 		break;
1032 	case ETHTOOL_GRXCLSRULE:
1033 		ret = bcm_sf2_cfp_rule_get(priv, port, nfc);
1034 		break;
1035 	case ETHTOOL_GRXCLSRLALL:
1036 		ret = bcm_sf2_cfp_rule_get_all(priv, port, nfc, rule_locs);
1037 		break;
1038 	default:
1039 		ret = -EOPNOTSUPP;
1040 		break;
1041 	}
1042 
1043 	mutex_unlock(&priv->cfp.lock);
1044 
1045 	if (ret)
1046 		return ret;
1047 
1048 	/* Pass up the commands to the attached master network device */
1049 	if (p->ethtool_ops->get_rxnfc) {
1050 		ret = p->ethtool_ops->get_rxnfc(p, nfc, rule_locs);
1051 		if (ret == -EOPNOTSUPP)
1052 			ret = 0;
1053 	}
1054 
1055 	return ret;
1056 }
1057 
1058 int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
1059 		      struct ethtool_rxnfc *nfc)
1060 {
1061 	struct net_device *p = ds->ports[port].cpu_dp->master;
1062 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
1063 	int ret = 0;
1064 
1065 	mutex_lock(&priv->cfp.lock);
1066 
1067 	switch (nfc->cmd) {
1068 	case ETHTOOL_SRXCLSRLINS:
1069 		ret = bcm_sf2_cfp_rule_set(ds, port, &nfc->fs);
1070 		break;
1071 
1072 	case ETHTOOL_SRXCLSRLDEL:
1073 		ret = bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
1074 		break;
1075 	default:
1076 		ret = -EOPNOTSUPP;
1077 		break;
1078 	}
1079 
1080 	mutex_unlock(&priv->cfp.lock);
1081 
1082 	if (ret)
1083 		return ret;
1084 
1085 	/* Pass up the commands to the attached master network device.
1086 	 * This can fail, so rollback the operation if we need to.
1087 	 */
1088 	if (p->ethtool_ops->set_rxnfc) {
1089 		ret = p->ethtool_ops->set_rxnfc(p, nfc);
1090 		if (ret && ret != -EOPNOTSUPP) {
1091 			mutex_lock(&priv->cfp.lock);
1092 			bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
1093 			mutex_unlock(&priv->cfp.lock);
1094 		} else {
1095 			ret = 0;
1096 		}
1097 	}
1098 
1099 	return ret;
1100 }
1101 
1102 int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv)
1103 {
1104 	unsigned int timeout = 1000;
1105 	u32 reg;
1106 
1107 	reg = core_readl(priv, CORE_CFP_ACC);
1108 	reg |= TCAM_RESET;
1109 	core_writel(priv, reg, CORE_CFP_ACC);
1110 
1111 	do {
1112 		reg = core_readl(priv, CORE_CFP_ACC);
1113 		if (!(reg & TCAM_RESET))
1114 			break;
1115 
1116 		cpu_relax();
1117 	} while (timeout--);
1118 
1119 	if (!timeout)
1120 		return -ETIMEDOUT;
1121 
1122 	return 0;
1123 }
1124 
1125 void bcm_sf2_cfp_exit(struct dsa_switch *ds)
1126 {
1127 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
1128 	struct cfp_rule *rule, *n;
1129 
1130 	if (list_empty(&priv->cfp.rules_list))
1131 		return;
1132 
1133 	list_for_each_entry_safe_reverse(rule, n, &priv->cfp.rules_list, next)
1134 		bcm_sf2_cfp_rule_del(priv, rule->port, rule->fs.location);
1135 }
1136 
1137 int bcm_sf2_cfp_resume(struct dsa_switch *ds)
1138 {
1139 	struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
1140 	struct cfp_rule *rule;
1141 	int ret = 0;
1142 	u32 reg;
1143 
1144 	if (list_empty(&priv->cfp.rules_list))
1145 		return ret;
1146 
1147 	reg = core_readl(priv, CORE_CFP_CTL_REG);
1148 	reg &= ~CFP_EN_MAP_MASK;
1149 	core_writel(priv, reg, CORE_CFP_CTL_REG);
1150 
1151 	ret = bcm_sf2_cfp_rst(priv);
1152 	if (ret)
1153 		return ret;
1154 
1155 	list_for_each_entry(rule, &priv->cfp.rules_list, next) {
1156 		ret = bcm_sf2_cfp_rule_remove(priv, rule->port,
1157 					      rule->fs.location);
1158 		if (ret) {
1159 			dev_err(ds->dev, "failed to remove rule\n");
1160 			return ret;
1161 		}
1162 
1163 		ret = bcm_sf2_cfp_rule_insert(ds, rule->port, &rule->fs);
1164 		if (ret) {
1165 			dev_err(ds->dev, "failed to restore rule\n");
1166 			return ret;
1167 		}
1168 	}
1169 
1170 	return ret;
1171 }
1172