1 // SPDX-License-Identifier: GPL-2.0+
2 
3 #include "lan966x_main.h"
4 #include "lan966x_vcap_ag_api.h"
5 #include "vcap_api.h"
6 #include "vcap_api_client.h"
7 
8 #define STREAMSIZE (64 * 4)
9 
10 #define LAN966X_IS2_LOOKUPS 2
11 
12 enum vcap_is2_port_sel_ipv6 {
13 	VCAP_IS2_PS_IPV6_TCPUDP_OTHER,
14 	VCAP_IS2_PS_IPV6_STD,
15 	VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER,
16 	VCAP_IS2_PS_IPV6_MAC_ETYPE,
17 };
18 
19 static struct lan966x_vcap_inst {
20 	enum vcap_type vtype; /* type of vcap */
21 	int tgt_inst; /* hardware instance number */
22 	int lookups; /* number of lookups in this vcap type */
23 	int first_cid; /* first chain id in this vcap */
24 	int last_cid; /* last chain id in this vcap */
25 	int count; /* number of available addresses */
26 } lan966x_vcap_inst_cfg[] = {
27 	{
28 		.vtype = VCAP_TYPE_IS2, /* IS2-0 */
29 		.tgt_inst = 2,
30 		.lookups = LAN966X_IS2_LOOKUPS,
31 		.first_cid = LAN966X_VCAP_CID_IS2_L0,
32 		.last_cid = LAN966X_VCAP_CID_IS2_MAX,
33 		.count = 256,
34 	},
35 };
36 
37 struct lan966x_vcap_cmd_cb {
38 	struct lan966x *lan966x;
39 	u32 instance;
40 };
41 
42 static u32 lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb *cb)
43 {
44 	return lan_rd(cb->lan966x, VCAP_UPDATE_CTRL(cb->instance));
45 }
46 
47 static void lan966x_vcap_wait_update(struct lan966x *lan966x, int instance)
48 {
49 	const struct lan966x_vcap_cmd_cb cb = { .lan966x = lan966x,
50 						.instance = instance };
51 	u32 val;
52 
53 	readx_poll_timeout(lan966x_vcap_read_update_ctrl, &cb, val,
54 			   (val & VCAP_UPDATE_CTRL_UPDATE_SHOT) == 0, 10,
55 			   100000);
56 }
57 
58 static void __lan966x_vcap_range_init(struct lan966x *lan966x,
59 				      struct vcap_admin *admin,
60 				      u32 addr,
61 				      u32 count)
62 {
63 	lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
64 	       VCAP_MV_CFG_MV_SIZE_SET(count - 1),
65 	       lan966x, VCAP_MV_CFG(admin->tgt_inst));
66 
67 	lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
68 	       VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
69 	       VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
70 	       VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
71 	       VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
72 	       VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(true) |
73 	       VCAP_UPDATE_CTRL_UPDATE_SHOT_SET(1),
74 	       lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
75 
76 	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
77 }
78 
79 static int lan966x_vcap_cid_to_lookup(int cid)
80 {
81 	if (cid >= LAN966X_VCAP_CID_IS2_L1 &&
82 	    cid < LAN966X_VCAP_CID_IS2_MAX)
83 		return 1;
84 
85 	return 0;
86 }
87 
88 static int
89 lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup,
90 				  struct vcap_keyset_list *keysetlist,
91 				  u16 l3_proto)
92 {
93 	struct lan966x_port *port = netdev_priv(dev);
94 	struct lan966x *lan966x = port->lan966x;
95 	bool found = false;
96 	u32 val;
97 
98 	/* Check if the port keyset selection is enabled */
99 	val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port));
100 	if (!ANA_VCAP_S2_CFG_ENA_GET(val))
101 		return -ENOENT;
102 
103 	/* Collect all keysets for the port in a list */
104 	if (l3_proto == ETH_P_ALL)
105 		vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
106 
107 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_SNAP) {
108 		if (ANA_VCAP_S2_CFG_SNAP_DIS_GET(val) & (BIT(0) << lookup))
109 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_LLC);
110 		else
111 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_SNAP);
112 
113 		found = true;
114 	}
115 
116 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_CFM) {
117 		if (ANA_VCAP_S2_CFG_OAM_DIS_GET(val) & (BIT(0) << lookup))
118 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
119 		else
120 			vcap_keyset_list_add(keysetlist, VCAP_KFS_OAM);
121 
122 		found = true;
123 	}
124 
125 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
126 		if (ANA_VCAP_S2_CFG_ARP_DIS_GET(val) & (BIT(0) << lookup))
127 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
128 		else
129 			vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
130 
131 		found = true;
132 	}
133 
134 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
135 		if (ANA_VCAP_S2_CFG_IP_OTHER_DIS_GET(val) & (BIT(0) << lookup))
136 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
137 		else
138 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
139 
140 		if (ANA_VCAP_S2_CFG_IP_TCPUDP_DIS_GET(val) & (BIT(0) << lookup))
141 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
142 		else
143 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
144 
145 		found = true;
146 	}
147 
148 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
149 		switch (ANA_VCAP_S2_CFG_IP6_CFG_GET(val) & (0x3 << lookup)) {
150 		case VCAP_IS2_PS_IPV6_TCPUDP_OTHER:
151 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_OTHER);
152 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_TCP_UDP);
153 			break;
154 		case VCAP_IS2_PS_IPV6_STD:
155 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
156 			break;
157 		case VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER:
158 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
159 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
160 			break;
161 		case VCAP_IS2_PS_IPV6_MAC_ETYPE:
162 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
163 			break;
164 		}
165 
166 		found = true;
167 	}
168 
169 	if (!found)
170 		vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
171 
172 	return 0;
173 }
174 
175 static enum vcap_keyfield_set
176 lan966x_vcap_validate_keyset(struct net_device *dev,
177 			     struct vcap_admin *admin,
178 			     struct vcap_rule *rule,
179 			     struct vcap_keyset_list *kslist,
180 			     u16 l3_proto)
181 {
182 	struct vcap_keyset_list keysetlist = {};
183 	enum vcap_keyfield_set keysets[10] = {};
184 	int lookup;
185 	int err;
186 
187 	if (!kslist || kslist->cnt == 0)
188 		return VCAP_KFS_NO_VALUE;
189 
190 	lookup = lan966x_vcap_cid_to_lookup(rule->vcap_chain_id);
191 	keysetlist.max = ARRAY_SIZE(keysets);
192 	keysetlist.keysets = keysets;
193 	err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist,
194 						l3_proto);
195 	if (err)
196 		return VCAP_KFS_NO_VALUE;
197 
198 	/* Check if there is a match and return the match */
199 	for (int i = 0; i < kslist->cnt; ++i)
200 		for (int j = 0; j < keysetlist.cnt; ++j)
201 			if (kslist->keysets[i] == keysets[j])
202 				return kslist->keysets[i];
203 
204 	return VCAP_KFS_NO_VALUE;
205 }
206 
207 static bool lan966x_vcap_is_first_chain(struct vcap_rule *rule)
208 {
209 	return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 &&
210 		rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1);
211 }
212 
213 static void lan966x_vcap_add_default_fields(struct net_device *dev,
214 					    struct vcap_admin *admin,
215 					    struct vcap_rule *rule)
216 {
217 	struct lan966x_port *port = netdev_priv(dev);
218 	u32 value, mask;
219 
220 	if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
221 				  &value, &mask))
222 		vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
223 				      ~BIT(port->chip_port));
224 
225 	if (lan966x_vcap_is_first_chain(rule))
226 		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
227 				      VCAP_BIT_1);
228 	else
229 		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
230 				      VCAP_BIT_0);
231 }
232 
233 static void lan966x_vcap_cache_erase(struct vcap_admin *admin)
234 {
235 	memset(admin->cache.keystream, 0, STREAMSIZE);
236 	memset(admin->cache.maskstream, 0, STREAMSIZE);
237 	memset(admin->cache.actionstream, 0, STREAMSIZE);
238 	memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
239 }
240 
241 static void lan966x_vcap_cache_write(struct net_device *dev,
242 				     struct vcap_admin *admin,
243 				     enum vcap_selection sel,
244 				     u32 start,
245 				     u32 count)
246 {
247 	struct lan966x_port *port = netdev_priv(dev);
248 	struct lan966x *lan966x = port->lan966x;
249 	u32 *keystr, *mskstr, *actstr;
250 
251 	keystr = &admin->cache.keystream[start];
252 	mskstr = &admin->cache.maskstream[start];
253 	actstr = &admin->cache.actionstream[start];
254 
255 	switch (sel) {
256 	case VCAP_SEL_ENTRY:
257 		for (int i = 0; i < count; ++i) {
258 			lan_wr(keystr[i] & mskstr[i], lan966x,
259 			       VCAP_ENTRY_DAT(admin->tgt_inst, i));
260 			lan_wr(~mskstr[i], lan966x,
261 			       VCAP_MASK_DAT(admin->tgt_inst, i));
262 		}
263 		break;
264 	case VCAP_SEL_ACTION:
265 		for (int i = 0; i < count; ++i)
266 			lan_wr(actstr[i], lan966x,
267 			       VCAP_ACTION_DAT(admin->tgt_inst, i));
268 		break;
269 	case VCAP_SEL_COUNTER:
270 		admin->cache.sticky = admin->cache.counter > 0;
271 		lan_wr(admin->cache.counter, lan966x,
272 		       VCAP_CNT_DAT(admin->tgt_inst, 0));
273 		break;
274 	default:
275 		break;
276 	}
277 }
278 
279 static void lan966x_vcap_cache_read(struct net_device *dev,
280 				    struct vcap_admin *admin,
281 				    enum vcap_selection sel,
282 				    u32 start,
283 				    u32 count)
284 {
285 	struct lan966x_port *port = netdev_priv(dev);
286 	struct lan966x *lan966x = port->lan966x;
287 	int instance = admin->tgt_inst;
288 	u32 *keystr, *mskstr, *actstr;
289 
290 	keystr = &admin->cache.keystream[start];
291 	mskstr = &admin->cache.maskstream[start];
292 	actstr = &admin->cache.actionstream[start];
293 
294 	if (sel & VCAP_SEL_ENTRY) {
295 		for (int i = 0; i < count; ++i) {
296 			keystr[i] =
297 				lan_rd(lan966x, VCAP_ENTRY_DAT(instance, i));
298 			mskstr[i] =
299 				~lan_rd(lan966x, VCAP_MASK_DAT(instance, i));
300 		}
301 	}
302 
303 	if (sel & VCAP_SEL_ACTION)
304 		for (int i = 0; i < count; ++i)
305 			actstr[i] =
306 				lan_rd(lan966x, VCAP_ACTION_DAT(instance, i));
307 
308 	if (sel & VCAP_SEL_COUNTER) {
309 		admin->cache.counter =
310 			lan_rd(lan966x, VCAP_CNT_DAT(instance, 0));
311 		admin->cache.sticky = admin->cache.counter > 0;
312 	}
313 }
314 
315 static void lan966x_vcap_range_init(struct net_device *dev,
316 				    struct vcap_admin *admin,
317 				    u32 addr,
318 				    u32 count)
319 {
320 	struct lan966x_port *port = netdev_priv(dev);
321 	struct lan966x *lan966x = port->lan966x;
322 
323 	__lan966x_vcap_range_init(lan966x, admin, addr, count);
324 }
325 
326 static void lan966x_vcap_update(struct net_device *dev,
327 				struct vcap_admin *admin,
328 				enum vcap_command cmd,
329 				enum vcap_selection sel,
330 				u32 addr)
331 {
332 	struct lan966x_port *port = netdev_priv(dev);
333 	struct lan966x *lan966x = port->lan966x;
334 	bool clear;
335 
336 	clear = (cmd == VCAP_CMD_INITIALIZE);
337 
338 	lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
339 	       VCAP_MV_CFG_MV_SIZE_SET(0),
340 	       lan966x, VCAP_MV_CFG(admin->tgt_inst));
341 
342 	lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
343 	       VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
344 	       VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
345 	       VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
346 	       VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
347 	       VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(clear) |
348 	       VCAP_UPDATE_CTRL_UPDATE_SHOT,
349 	       lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
350 
351 	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
352 }
353 
354 static void lan966x_vcap_move(struct net_device *dev,
355 			      struct vcap_admin *admin,
356 			      u32 addr, int offset, int count)
357 {
358 	struct lan966x_port *port = netdev_priv(dev);
359 	struct lan966x *lan966x = port->lan966x;
360 	enum vcap_command cmd;
361 	u16 mv_num_pos;
362 	u16 mv_size;
363 
364 	mv_size = count - 1;
365 	if (offset > 0) {
366 		mv_num_pos = offset - 1;
367 		cmd = VCAP_CMD_MOVE_DOWN;
368 	} else {
369 		mv_num_pos = -offset - 1;
370 		cmd = VCAP_CMD_MOVE_UP;
371 	}
372 
373 	lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(mv_num_pos) |
374 	       VCAP_MV_CFG_MV_SIZE_SET(mv_size),
375 	       lan966x, VCAP_MV_CFG(admin->tgt_inst));
376 
377 	lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
378 	       VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
379 	       VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
380 	       VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
381 	       VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
382 	       VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(false) |
383 	       VCAP_UPDATE_CTRL_UPDATE_SHOT,
384 	       lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
385 
386 	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
387 }
388 
389 static int lan966x_vcap_port_info(struct net_device *dev,
390 				  struct vcap_admin *admin,
391 				  struct vcap_output_print *out)
392 {
393 	return 0;
394 }
395 
396 static int lan966x_vcap_enable(struct net_device *dev,
397 			       struct vcap_admin *admin,
398 			       bool enable)
399 {
400 	struct lan966x_port *port = netdev_priv(dev);
401 	struct lan966x *lan966x = port->lan966x;
402 
403 	lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(enable),
404 		ANA_VCAP_S2_CFG_ENA,
405 		lan966x, ANA_VCAP_S2_CFG(port->chip_port));
406 
407 	return 0;
408 }
409 
410 static struct vcap_operations lan966x_vcap_ops = {
411 	.validate_keyset = lan966x_vcap_validate_keyset,
412 	.add_default_fields = lan966x_vcap_add_default_fields,
413 	.cache_erase = lan966x_vcap_cache_erase,
414 	.cache_write = lan966x_vcap_cache_write,
415 	.cache_read = lan966x_vcap_cache_read,
416 	.init = lan966x_vcap_range_init,
417 	.update = lan966x_vcap_update,
418 	.move = lan966x_vcap_move,
419 	.port_info = lan966x_vcap_port_info,
420 	.enable = lan966x_vcap_enable,
421 };
422 
423 static void lan966x_vcap_admin_free(struct vcap_admin *admin)
424 {
425 	if (!admin)
426 		return;
427 
428 	kfree(admin->cache.keystream);
429 	kfree(admin->cache.maskstream);
430 	kfree(admin->cache.actionstream);
431 	mutex_destroy(&admin->lock);
432 	kfree(admin);
433 }
434 
435 static struct vcap_admin *
436 lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl,
437 			 const struct lan966x_vcap_inst *cfg)
438 {
439 	struct vcap_admin *admin;
440 
441 	admin = kzalloc(sizeof(*admin), GFP_KERNEL);
442 	if (!admin)
443 		return ERR_PTR(-ENOMEM);
444 
445 	mutex_init(&admin->lock);
446 	INIT_LIST_HEAD(&admin->list);
447 	INIT_LIST_HEAD(&admin->rules);
448 	INIT_LIST_HEAD(&admin->enabled);
449 
450 	admin->vtype = cfg->vtype;
451 	admin->vinst = 0;
452 	admin->w32be = true;
453 	admin->tgt_inst = cfg->tgt_inst;
454 
455 	admin->lookups = cfg->lookups;
456 	admin->lookups_per_instance = cfg->lookups;
457 
458 	admin->first_cid = cfg->first_cid;
459 	admin->last_cid = cfg->last_cid;
460 
461 	admin->cache.keystream = kzalloc(STREAMSIZE, GFP_KERNEL);
462 	admin->cache.maskstream = kzalloc(STREAMSIZE, GFP_KERNEL);
463 	admin->cache.actionstream = kzalloc(STREAMSIZE, GFP_KERNEL);
464 	if (!admin->cache.keystream ||
465 	    !admin->cache.maskstream ||
466 	    !admin->cache.actionstream) {
467 		lan966x_vcap_admin_free(admin);
468 		return ERR_PTR(-ENOMEM);
469 	}
470 
471 	return admin;
472 }
473 
474 static void lan966x_vcap_block_init(struct lan966x *lan966x,
475 				    struct vcap_admin *admin,
476 				    struct lan966x_vcap_inst *cfg)
477 {
478 	admin->first_valid_addr = 0;
479 	admin->last_used_addr = cfg->count;
480 	admin->last_valid_addr = cfg->count - 1;
481 
482 	lan_wr(VCAP_CORE_IDX_CORE_IDX_SET(0),
483 	       lan966x, VCAP_CORE_IDX(admin->tgt_inst));
484 	lan_wr(VCAP_CORE_MAP_CORE_MAP_SET(1),
485 	       lan966x, VCAP_CORE_MAP(admin->tgt_inst));
486 
487 	__lan966x_vcap_range_init(lan966x, admin, admin->first_valid_addr,
488 				  admin->last_valid_addr -
489 					admin->first_valid_addr);
490 }
491 
492 static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,
493 					      struct vcap_admin *admin)
494 {
495 	for (int p = 0; p < lan966x->num_phys_ports; ++p)
496 		lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p));
497 }
498 
499 int lan966x_vcap_init(struct lan966x *lan966x)
500 {
501 	struct lan966x_vcap_inst *cfg;
502 	struct vcap_control *ctrl;
503 	struct vcap_admin *admin;
504 
505 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
506 	if (!ctrl)
507 		return -ENOMEM;
508 
509 	ctrl->vcaps = lan966x_vcaps;
510 	ctrl->stats = &lan966x_vcap_stats;
511 	ctrl->ops = &lan966x_vcap_ops;
512 
513 	INIT_LIST_HEAD(&ctrl->list);
514 	for (int i = 0; i < ARRAY_SIZE(lan966x_vcap_inst_cfg); ++i) {
515 		cfg = &lan966x_vcap_inst_cfg[i];
516 
517 		admin = lan966x_vcap_admin_alloc(lan966x, ctrl, cfg);
518 		if (IS_ERR(admin))
519 			return PTR_ERR(admin);
520 
521 		lan966x_vcap_block_init(lan966x, admin, cfg);
522 		lan966x_vcap_port_key_deselection(lan966x, admin);
523 
524 		list_add_tail(&admin->list, &ctrl->list);
525 	}
526 
527 	lan966x->vcap_ctrl = ctrl;
528 
529 	return 0;
530 }
531 
532 void lan966x_vcap_deinit(struct lan966x *lan966x)
533 {
534 	struct vcap_admin *admin, *admin_next;
535 	struct vcap_control *ctrl;
536 
537 	ctrl = lan966x->vcap_ctrl;
538 	if (!ctrl)
539 		return;
540 
541 	list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) {
542 		lan966x_vcap_port_key_deselection(lan966x, admin);
543 		vcap_del_rules(ctrl, admin);
544 		list_del(&admin->list);
545 		lan966x_vcap_admin_free(admin);
546 	}
547 
548 	kfree(ctrl);
549 }
550