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