1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip Sparx5 Switch driver VCAP implementation
3  *
4  * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
5  *
6  * The Sparx5 Chip Register Model can be browsed at this location:
7  * https://github.com/microchip-ung/sparx-5_reginfo
8  */
9 
10 #include <linux/types.h>
11 #include <linux/list.h>
12 
13 #include "vcap_api.h"
14 #include "vcap_api_client.h"
15 #include "sparx5_main_regs.h"
16 #include "sparx5_main.h"
17 #include "sparx5_vcap_impl.h"
18 #include "sparx5_vcap_ag_api.h"
19 
20 #define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */
21 #define STREAMSIZE (64 * 4)  /* bytes in the VCAP cache area */
22 
23 #define SPARX5_IS2_LOOKUPS 4
24 #define VCAP_IS2_KEYSEL(_ena, _noneth, _v4_mc, _v4_uc, _v6_mc, _v6_uc, _arp) \
25 	(ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(_ena) | \
26 	 ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(_noneth) | \
27 	 ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(_v4_mc) | \
28 	 ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(_v4_uc) | \
29 	 ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(_v6_mc) | \
30 	 ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \
31 	 ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp))
32 
33 /* IS2 port keyset selection control */
34 
35 /* IS2 non-ethernet traffic type keyset generation */
36 enum vcap_is2_port_sel_noneth {
37 	VCAP_IS2_PS_NONETH_MAC_ETYPE,
38 	VCAP_IS2_PS_NONETH_CUSTOM_1,
39 	VCAP_IS2_PS_NONETH_CUSTOM_2,
40 	VCAP_IS2_PS_NONETH_NO_LOOKUP
41 };
42 
43 /* IS2 IPv4 unicast traffic type keyset generation */
44 enum vcap_is2_port_sel_ipv4_uc {
45 	VCAP_IS2_PS_IPV4_UC_MAC_ETYPE,
46 	VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
47 	VCAP_IS2_PS_IPV4_UC_IP_7TUPLE,
48 };
49 
50 /* IS2 IPv4 multicast traffic type keyset generation */
51 enum vcap_is2_port_sel_ipv4_mc {
52 	VCAP_IS2_PS_IPV4_MC_MAC_ETYPE,
53 	VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
54 	VCAP_IS2_PS_IPV4_MC_IP_7TUPLE,
55 	VCAP_IS2_PS_IPV4_MC_IP4_VID,
56 };
57 
58 /* IS2 IPv6 unicast traffic type keyset generation */
59 enum vcap_is2_port_sel_ipv6_uc {
60 	VCAP_IS2_PS_IPV6_UC_MAC_ETYPE,
61 	VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
62 	VCAP_IS2_PS_IPV6_UC_IP6_STD,
63 	VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER,
64 };
65 
66 /* IS2 IPv6 multicast traffic type keyset generation */
67 enum vcap_is2_port_sel_ipv6_mc {
68 	VCAP_IS2_PS_IPV6_MC_MAC_ETYPE,
69 	VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
70 	VCAP_IS2_PS_IPV6_MC_IP6_VID,
71 	VCAP_IS2_PS_IPV6_MC_IP6_STD,
72 	VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER,
73 };
74 
75 /* IS2 ARP traffic type keyset generation */
76 enum vcap_is2_port_sel_arp {
77 	VCAP_IS2_PS_ARP_MAC_ETYPE,
78 	VCAP_IS2_PS_ARP_ARP,
79 };
80 
81 static struct sparx5_vcap_inst {
82 	enum vcap_type vtype; /* type of vcap */
83 	int vinst; /* instance number within the same type */
84 	int lookups; /* number of lookups in this vcap type */
85 	int lookups_per_instance; /* number of lookups in this instance */
86 	int first_cid; /* first chain id in this vcap */
87 	int last_cid; /* last chain id in this vcap */
88 	int count; /* number of available addresses, not in super vcap */
89 	int map_id; /* id in the super vcap block mapping (if applicable) */
90 	int blockno; /* starting block in super vcap (if applicable) */
91 	int blocks; /* number of blocks in super vcap (if applicable) */
92 } sparx5_vcap_inst_cfg[] = {
93 	{
94 		.vtype = VCAP_TYPE_IS2, /* IS2-0 */
95 		.vinst = 0,
96 		.map_id = 4,
97 		.lookups = SPARX5_IS2_LOOKUPS,
98 		.lookups_per_instance = SPARX5_IS2_LOOKUPS / 2,
99 		.first_cid = SPARX5_VCAP_CID_IS2_L0,
100 		.last_cid = SPARX5_VCAP_CID_IS2_L2 - 1,
101 		.blockno = 0, /* Maps block 0-1 */
102 		.blocks = 2,
103 	},
104 	{
105 		.vtype = VCAP_TYPE_IS2, /* IS2-1 */
106 		.vinst = 1,
107 		.map_id = 5,
108 		.lookups = SPARX5_IS2_LOOKUPS,
109 		.lookups_per_instance = SPARX5_IS2_LOOKUPS / 2,
110 		.first_cid = SPARX5_VCAP_CID_IS2_L2,
111 		.last_cid = SPARX5_VCAP_CID_IS2_MAX,
112 		.blockno = 2, /* Maps block 2-3 */
113 		.blocks = 2,
114 	},
115 };
116 
117 /* Await the super VCAP completion of the current operation */
118 static void sparx5_vcap_wait_super_update(struct sparx5 *sparx5)
119 {
120 	u32 value;
121 
122 	read_poll_timeout(spx5_rd, value,
123 			  !VCAP_SUPER_CTRL_UPDATE_SHOT_GET(value), 500, 10000,
124 			  false, sparx5, VCAP_SUPER_CTRL);
125 }
126 
127 /* Initializing a VCAP address range: only IS2 for now */
128 static void _sparx5_vcap_range_init(struct sparx5 *sparx5,
129 				    struct vcap_admin *admin,
130 				    u32 addr, u32 count)
131 {
132 	u32 size = count - 1;
133 
134 	spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) |
135 		VCAP_SUPER_CFG_MV_SIZE_SET(size),
136 		sparx5, VCAP_SUPER_CFG);
137 	spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
138 		VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) |
139 		VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) |
140 		VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) |
141 		VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) |
142 		VCAP_SUPER_CTRL_CLEAR_CACHE_SET(true) |
143 		VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
144 		sparx5, VCAP_SUPER_CTRL);
145 	sparx5_vcap_wait_super_update(sparx5);
146 }
147 
148 /* Initializing VCAP rule data area */
149 static void sparx5_vcap_block_init(struct sparx5 *sparx5,
150 				   struct vcap_admin *admin)
151 {
152 	_sparx5_vcap_range_init(sparx5, admin, admin->first_valid_addr,
153 				admin->last_valid_addr -
154 					admin->first_valid_addr);
155 }
156 
157 /* Get the keyset name from the sparx5 VCAP model */
158 static const char *sparx5_vcap_keyset_name(struct net_device *ndev,
159 					   enum vcap_keyfield_set keyset)
160 {
161 	struct sparx5_port *port = netdev_priv(ndev);
162 
163 	return vcap_keyset_name(port->sparx5->vcap_ctrl, keyset);
164 }
165 
166 /* Check if this is the first lookup of IS2 */
167 static bool sparx5_vcap_is2_is_first_chain(struct vcap_rule *rule)
168 {
169 	return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L0 &&
170 		rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L1) ||
171 		((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L2 &&
172 		  rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L3));
173 }
174 
175 /* Set the narrow range ingress port mask on a rule */
176 static void sparx5_vcap_add_range_port_mask(struct vcap_rule *rule,
177 					    struct net_device *ndev)
178 {
179 	struct sparx5_port *port = netdev_priv(ndev);
180 	u32 port_mask;
181 	u32 range;
182 
183 	range = port->portno / BITS_PER_TYPE(u32);
184 	/* Port bit set to match-any */
185 	port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32));
186 	vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_SEL, 0, 0xf);
187 	vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_RNG, range, 0xf);
188 	vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, port_mask);
189 }
190 
191 /* Set the wide range ingress port mask on a rule */
192 static void sparx5_vcap_add_wide_port_mask(struct vcap_rule *rule,
193 					   struct net_device *ndev)
194 {
195 	struct sparx5_port *port = netdev_priv(ndev);
196 	struct vcap_u72_key port_mask;
197 	u32 range;
198 
199 	/* Port bit set to match-any */
200 	memset(port_mask.value, 0, sizeof(port_mask.value));
201 	memset(port_mask.mask, 0xff, sizeof(port_mask.mask));
202 	range = port->portno / BITS_PER_BYTE;
203 	port_mask.mask[range] = ~BIT(port->portno % BITS_PER_BYTE);
204 	vcap_rule_add_key_u72(rule, VCAP_KF_IF_IGR_PORT_MASK, &port_mask);
205 }
206 
207 /* Convert chain id to vcap lookup id */
208 static int sparx5_vcap_cid_to_lookup(int cid)
209 {
210 	int lookup = 0;
211 
212 	/* For now only handle IS2 */
213 	if (cid >= SPARX5_VCAP_CID_IS2_L1 && cid < SPARX5_VCAP_CID_IS2_L2)
214 		lookup = 1;
215 	else if (cid >= SPARX5_VCAP_CID_IS2_L2 && cid < SPARX5_VCAP_CID_IS2_L3)
216 		lookup = 2;
217 	else if (cid >= SPARX5_VCAP_CID_IS2_L3 && cid < SPARX5_VCAP_CID_IS2_MAX)
218 		lookup = 3;
219 
220 	return lookup;
221 }
222 
223 /* Return the list of keysets for the vcap port configuration */
224 static int sparx5_vcap_is2_get_port_keysets(struct net_device *ndev,
225 					    int lookup,
226 					    struct vcap_keyset_list *keysetlist,
227 					    u16 l3_proto)
228 {
229 	struct sparx5_port *port = netdev_priv(ndev);
230 	struct sparx5 *sparx5 = port->sparx5;
231 	int portno = port->portno;
232 	u32 value;
233 
234 	/* Check if the port keyset selection is enabled */
235 	value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
236 	if (!ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_GET(value))
237 		return -ENOENT;
238 
239 	/* Collect all keysets for the port in a list */
240 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
241 		switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) {
242 		case VCAP_IS2_PS_ARP_MAC_ETYPE:
243 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
244 			break;
245 		case VCAP_IS2_PS_ARP_ARP:
246 			vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
247 			break;
248 		}
249 	}
250 
251 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
252 		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) {
253 		case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE:
254 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
255 			break;
256 		case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER:
257 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
258 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
259 			break;
260 		case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE:
261 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
262 			break;
263 		}
264 
265 		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) {
266 		case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE:
267 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
268 			break;
269 		case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER:
270 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
271 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
272 			break;
273 		case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE:
274 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
275 			break;
276 		}
277 	}
278 
279 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
280 		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) {
281 		case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE:
282 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
283 			break;
284 		case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE:
285 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
286 			break;
287 		case VCAP_IS2_PS_IPV6_UC_IP6_STD:
288 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
289 			break;
290 		case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER:
291 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
292 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
293 			break;
294 		}
295 
296 		switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) {
297 		case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE:
298 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
299 			break;
300 		case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE:
301 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
302 			break;
303 		case VCAP_IS2_PS_IPV6_MC_IP6_STD:
304 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
305 			break;
306 		case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER:
307 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
308 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
309 			break;
310 		case VCAP_IS2_PS_IPV6_MC_IP6_VID:
311 			/* Not used */
312 			break;
313 		}
314 	}
315 
316 	if (l3_proto != ETH_P_ARP && l3_proto != ETH_P_IP &&
317 	    l3_proto != ETH_P_IPV6) {
318 		switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) {
319 		case VCAP_IS2_PS_NONETH_MAC_ETYPE:
320 			/* IS2 non-classified frames generate MAC_ETYPE */
321 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
322 			break;
323 		}
324 	}
325 	return 0;
326 }
327 
328 /* API callback used for validating a field keyset (check the port keysets) */
329 static enum vcap_keyfield_set
330 sparx5_vcap_validate_keyset(struct net_device *ndev,
331 			    struct vcap_admin *admin,
332 			    struct vcap_rule *rule,
333 			    struct vcap_keyset_list *kslist,
334 			    u16 l3_proto)
335 {
336 	struct vcap_keyset_list keysetlist = {};
337 	enum vcap_keyfield_set keysets[10] = {};
338 	int idx, jdx, lookup;
339 
340 	if (!kslist || kslist->cnt == 0)
341 		return VCAP_KFS_NO_VALUE;
342 
343 	/* Get a list of currently configured keysets in the lookups */
344 	lookup = sparx5_vcap_cid_to_lookup(rule->vcap_chain_id);
345 	keysetlist.max = ARRAY_SIZE(keysets);
346 	keysetlist.keysets = keysets;
347 	sparx5_vcap_is2_get_port_keysets(ndev, lookup, &keysetlist, l3_proto);
348 
349 	/* Check if there is a match and return the match */
350 	for (idx = 0; idx < kslist->cnt; ++idx)
351 		for (jdx = 0; jdx < keysetlist.cnt; ++jdx)
352 			if (kslist->keysets[idx] == keysets[jdx])
353 				return kslist->keysets[idx];
354 
355 	pr_err("%s:%d: %s not supported in port key selection\n",
356 	       __func__, __LINE__,
357 	       sparx5_vcap_keyset_name(ndev, kslist->keysets[0]));
358 
359 	return -ENOENT;
360 }
361 
362 /* API callback used for adding default fields to a rule */
363 static void sparx5_vcap_add_default_fields(struct net_device *ndev,
364 					   struct vcap_admin *admin,
365 					   struct vcap_rule *rule)
366 {
367 	const struct vcap_field *field;
368 
369 	field = vcap_lookup_keyfield(rule, VCAP_KF_IF_IGR_PORT_MASK);
370 	if (field && field->width == SPX5_PORTS)
371 		sparx5_vcap_add_wide_port_mask(rule, ndev);
372 	else if (field && field->width == BITS_PER_TYPE(u32))
373 		sparx5_vcap_add_range_port_mask(rule, ndev);
374 	else
375 		pr_err("%s:%d: %s: could not add an ingress port mask for: %s\n",
376 		       __func__, __LINE__, netdev_name(ndev),
377 		       sparx5_vcap_keyset_name(ndev, rule->keyset));
378 	/* add the lookup bit */
379 	if (sparx5_vcap_is2_is_first_chain(rule))
380 		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_1);
381 	else
382 		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, VCAP_BIT_0);
383 }
384 
385 /* API callback used for erasing the vcap cache area (not the register area) */
386 static void sparx5_vcap_cache_erase(struct vcap_admin *admin)
387 {
388 	memset(admin->cache.keystream, 0, STREAMSIZE);
389 	memset(admin->cache.maskstream, 0, STREAMSIZE);
390 	memset(admin->cache.actionstream, 0, STREAMSIZE);
391 	memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
392 }
393 
394 /* API callback used for writing to the VCAP cache */
395 static void sparx5_vcap_cache_write(struct net_device *ndev,
396 				    struct vcap_admin *admin,
397 				    enum vcap_selection sel,
398 				    u32 start,
399 				    u32 count)
400 {
401 	struct sparx5_port *port = netdev_priv(ndev);
402 	struct sparx5 *sparx5 = port->sparx5;
403 	u32 *keystr, *mskstr, *actstr;
404 	int idx;
405 
406 	keystr = &admin->cache.keystream[start];
407 	mskstr = &admin->cache.maskstream[start];
408 	actstr = &admin->cache.actionstream[start];
409 	switch (sel) {
410 	case VCAP_SEL_ENTRY:
411 		for (idx = 0; idx < count; ++idx) {
412 			/* Avoid 'match-off' by setting value & mask */
413 			spx5_wr(keystr[idx] & mskstr[idx], sparx5,
414 				VCAP_SUPER_VCAP_ENTRY_DAT(idx));
415 			spx5_wr(~mskstr[idx], sparx5,
416 				VCAP_SUPER_VCAP_MASK_DAT(idx));
417 		}
418 		break;
419 	case VCAP_SEL_ACTION:
420 		for (idx = 0; idx < count; ++idx)
421 			spx5_wr(actstr[idx], sparx5,
422 				VCAP_SUPER_VCAP_ACTION_DAT(idx));
423 		break;
424 	case VCAP_SEL_ALL:
425 		pr_err("%s:%d: cannot write all streams at once\n",
426 		       __func__, __LINE__);
427 		break;
428 	default:
429 		break;
430 	}
431 }
432 
433 /* API callback used for reading from the VCAP into the VCAP cache */
434 static void sparx5_vcap_cache_read(struct net_device *ndev,
435 				   struct vcap_admin *admin,
436 				   enum vcap_selection sel, u32 start,
437 				   u32 count)
438 {
439 	/* this will be added later */
440 }
441 
442 /* API callback used for initializing a VCAP address range */
443 static void sparx5_vcap_range_init(struct net_device *ndev,
444 				   struct vcap_admin *admin, u32 addr,
445 				   u32 count)
446 {
447 	struct sparx5_port *port = netdev_priv(ndev);
448 	struct sparx5 *sparx5 = port->sparx5;
449 
450 	_sparx5_vcap_range_init(sparx5, admin, addr, count);
451 }
452 
453 /* API callback used for updating the VCAP cache */
454 static void sparx5_vcap_update(struct net_device *ndev,
455 			       struct vcap_admin *admin, enum vcap_command cmd,
456 			       enum vcap_selection sel, u32 addr)
457 {
458 	struct sparx5_port *port = netdev_priv(ndev);
459 	struct sparx5 *sparx5 = port->sparx5;
460 	bool clear;
461 
462 	clear = (cmd == VCAP_CMD_INITIALIZE);
463 	spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) |
464 		VCAP_SUPER_CFG_MV_SIZE_SET(0), sparx5, VCAP_SUPER_CFG);
465 	spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd) |
466 		VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
467 		VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
468 		VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
469 		VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) |
470 		VCAP_SUPER_CTRL_CLEAR_CACHE_SET(clear) |
471 		VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true),
472 		sparx5, VCAP_SUPER_CTRL);
473 	sparx5_vcap_wait_super_update(sparx5);
474 }
475 
476 /* API callback used for moving a block of rules in the VCAP */
477 static void sparx5_vcap_move(struct net_device *ndev, struct vcap_admin *admin,
478 			     u32 addr, int offset, int count)
479 {
480 	/* this will be added later */
481 }
482 
483 /* Provide port information via a callback interface */
484 static int sparx5_port_info(struct net_device *ndev, enum vcap_type vtype,
485 			    int (*pf)(void *out, int arg, const char *fmt, ...),
486 			    void *out, int arg)
487 {
488 	/* this will be added later */
489 	return 0;
490 }
491 
492 /* Enable all lookups in the VCAP instance */
493 static int sparx5_vcap_enable(struct net_device *ndev,
494 			      struct vcap_admin *admin,
495 			      bool enable)
496 {
497 	struct sparx5_port *port = netdev_priv(ndev);
498 	struct sparx5 *sparx5;
499 	int portno;
500 
501 	sparx5 = port->sparx5;
502 	portno = port->portno;
503 
504 	/* For now we only consider IS2 */
505 	if (enable)
506 		spx5_wr(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0xf), sparx5,
507 			ANA_ACL_VCAP_S2_CFG(portno));
508 	else
509 		spx5_wr(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0), sparx5,
510 			ANA_ACL_VCAP_S2_CFG(portno));
511 	return 0;
512 }
513 
514 /* API callback operations: only IS2 is supported for now */
515 static struct vcap_operations sparx5_vcap_ops = {
516 	.validate_keyset = sparx5_vcap_validate_keyset,
517 	.add_default_fields = sparx5_vcap_add_default_fields,
518 	.cache_erase = sparx5_vcap_cache_erase,
519 	.cache_write = sparx5_vcap_cache_write,
520 	.cache_read = sparx5_vcap_cache_read,
521 	.init = sparx5_vcap_range_init,
522 	.update = sparx5_vcap_update,
523 	.move = sparx5_vcap_move,
524 	.port_info = sparx5_port_info,
525 	.enable = sparx5_vcap_enable,
526 };
527 
528 /* Enable lookups per port and set the keyset generation: only IS2 for now */
529 static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5,
530 					   struct vcap_admin *admin)
531 {
532 	int portno, lookup;
533 	u32 keysel;
534 
535 	/* all traffic types generate the MAC_ETYPE keyset for now in all
536 	 * lookups on all ports
537 	 */
538 	keysel = VCAP_IS2_KEYSEL(true, VCAP_IS2_PS_NONETH_MAC_ETYPE,
539 				 VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
540 				 VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
541 				 VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
542 				 VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
543 				 VCAP_IS2_PS_ARP_MAC_ETYPE);
544 	for (lookup = 0; lookup < admin->lookups; ++lookup) {
545 		for (portno = 0; portno < SPX5_PORTS; ++portno) {
546 			spx5_wr(keysel, sparx5,
547 				ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
548 		}
549 	}
550 }
551 
552 /* Disable lookups per port and set the keyset generation: only IS2 for now */
553 static void sparx5_vcap_port_key_deselection(struct sparx5 *sparx5,
554 					     struct vcap_admin *admin)
555 {
556 	int portno;
557 
558 	for (portno = 0; portno < SPX5_PORTS; ++portno)
559 		spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0),
560 			 ANA_ACL_VCAP_S2_CFG_SEC_ENA,
561 			 sparx5,
562 			 ANA_ACL_VCAP_S2_CFG(portno));
563 }
564 
565 static void sparx5_vcap_admin_free(struct vcap_admin *admin)
566 {
567 	if (!admin)
568 		return;
569 	kfree(admin->cache.keystream);
570 	kfree(admin->cache.maskstream);
571 	kfree(admin->cache.actionstream);
572 	kfree(admin);
573 }
574 
575 /* Allocate a vcap instance with a rule list and a cache area */
576 static struct vcap_admin *
577 sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl,
578 			const struct sparx5_vcap_inst *cfg)
579 {
580 	struct vcap_admin *admin;
581 
582 	admin = kzalloc(sizeof(*admin), GFP_KERNEL);
583 	if (!admin)
584 		return ERR_PTR(-ENOMEM);
585 	INIT_LIST_HEAD(&admin->list);
586 	INIT_LIST_HEAD(&admin->rules);
587 	INIT_LIST_HEAD(&admin->enabled);
588 	admin->vtype = cfg->vtype;
589 	admin->vinst = cfg->vinst;
590 	admin->lookups = cfg->lookups;
591 	admin->lookups_per_instance = cfg->lookups_per_instance;
592 	admin->first_cid = cfg->first_cid;
593 	admin->last_cid = cfg->last_cid;
594 	admin->cache.keystream =
595 		kzalloc(STREAMSIZE, GFP_KERNEL);
596 	admin->cache.maskstream =
597 		kzalloc(STREAMSIZE, GFP_KERNEL);
598 	admin->cache.actionstream =
599 		kzalloc(STREAMSIZE, GFP_KERNEL);
600 	if (!admin->cache.keystream || !admin->cache.maskstream ||
601 	    !admin->cache.actionstream) {
602 		sparx5_vcap_admin_free(admin);
603 		return ERR_PTR(-ENOMEM);
604 	}
605 	return admin;
606 }
607 
608 /* Do block allocations and provide addresses for VCAP instances */
609 static void sparx5_vcap_block_alloc(struct sparx5 *sparx5,
610 				    struct vcap_admin *admin,
611 				    const struct sparx5_vcap_inst *cfg)
612 {
613 	int idx;
614 
615 	/* Super VCAP block mapping and address configuration. Block 0
616 	 * is assigned addresses 0 through 3071, block 1 is assigned
617 	 * addresses 3072 though 6143, and so on.
618 	 */
619 	for (idx = cfg->blockno; idx < cfg->blockno + cfg->blocks; ++idx) {
620 		spx5_wr(VCAP_SUPER_IDX_CORE_IDX_SET(idx), sparx5,
621 			VCAP_SUPER_IDX);
622 		spx5_wr(VCAP_SUPER_MAP_CORE_MAP_SET(cfg->map_id), sparx5,
623 			VCAP_SUPER_MAP);
624 	}
625 	admin->first_valid_addr = cfg->blockno * SUPER_VCAP_BLK_SIZE;
626 	admin->last_used_addr = admin->first_valid_addr +
627 		cfg->blocks * SUPER_VCAP_BLK_SIZE;
628 	admin->last_valid_addr = admin->last_used_addr - 1;
629 }
630 
631 /* Allocate a vcap control and vcap instances and configure the system */
632 int sparx5_vcap_init(struct sparx5 *sparx5)
633 {
634 	const struct sparx5_vcap_inst *cfg;
635 	struct vcap_control *ctrl;
636 	struct vcap_admin *admin;
637 	int err = 0, idx;
638 
639 	/* Create a VCAP control instance that owns the platform specific VCAP
640 	 * model with VCAP instances and information about keysets, keys,
641 	 * actionsets and actions
642 	 * - Create administrative state for each available VCAP
643 	 *   - Lists of rules
644 	 *   - Address information
645 	 *   - Initialize VCAP blocks
646 	 *   - Configure port keysets
647 	 */
648 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
649 	if (!ctrl)
650 		return -ENOMEM;
651 
652 	sparx5->vcap_ctrl = ctrl;
653 	/* select the sparx5 VCAP model */
654 	ctrl->vcaps = sparx5_vcaps;
655 	ctrl->stats = &sparx5_vcap_stats;
656 	/* Setup callbacks to allow the API to use the VCAP HW */
657 	ctrl->ops = &sparx5_vcap_ops;
658 
659 	INIT_LIST_HEAD(&ctrl->list);
660 	for (idx = 0; idx < ARRAY_SIZE(sparx5_vcap_inst_cfg); ++idx) {
661 		cfg = &sparx5_vcap_inst_cfg[idx];
662 		admin = sparx5_vcap_admin_alloc(sparx5, ctrl, cfg);
663 		if (IS_ERR(admin)) {
664 			err = PTR_ERR(admin);
665 			pr_err("%s:%d: vcap allocation failed: %d\n",
666 			       __func__, __LINE__, err);
667 			return err;
668 		}
669 		sparx5_vcap_block_alloc(sparx5, admin, cfg);
670 		sparx5_vcap_block_init(sparx5, admin);
671 		if (cfg->vinst == 0)
672 			sparx5_vcap_port_key_selection(sparx5, admin);
673 		list_add_tail(&admin->list, &ctrl->list);
674 	}
675 
676 	return err;
677 }
678 
679 void sparx5_vcap_destroy(struct sparx5 *sparx5)
680 {
681 	struct vcap_control *ctrl = sparx5->vcap_ctrl;
682 	struct vcap_admin *admin, *admin_next;
683 
684 	if (!ctrl)
685 		return;
686 
687 	list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) {
688 		sparx5_vcap_port_key_deselection(sparx5, admin);
689 		vcap_del_rules(ctrl, admin);
690 		list_del(&admin->list);
691 		sparx5_vcap_admin_free(admin);
692 	}
693 	kfree(ctrl);
694 }
695