xref: /linux/drivers/net/ethernet/microchip/lan966x/lan966x_vcap_impl.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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 #include "vcap_api_debugfs.h"
8 
9 #define STREAMSIZE (64 * 4)
10 
11 #define LAN966X_IS1_LOOKUPS 3
12 #define LAN966X_IS2_LOOKUPS 2
13 #define LAN966X_ES0_LOOKUPS 1
14 
15 #define LAN966X_STAT_ESDX_GRN_BYTES 0x300
16 #define LAN966X_STAT_ESDX_GRN_PKTS 0x301
17 #define LAN966X_STAT_ESDX_YEL_BYTES 0x302
18 #define LAN966X_STAT_ESDX_YEL_PKTS 0x303
19 
20 static struct lan966x_vcap_inst {
21 	enum vcap_type vtype; /* type of vcap */
22 	int tgt_inst; /* hardware instance number */
23 	int lookups; /* number of lookups in this vcap type */
24 	int first_cid; /* first chain id in this vcap */
25 	int last_cid; /* last chain id in this vcap */
26 	int count; /* number of available addresses */
27 	bool ingress; /* is vcap in the ingress path */
28 } lan966x_vcap_inst_cfg[] = {
29 	{
30 		.vtype = VCAP_TYPE_ES0,
31 		.tgt_inst = 0,
32 		.lookups = LAN966X_ES0_LOOKUPS,
33 		.first_cid = LAN966X_VCAP_CID_ES0_L0,
34 		.last_cid = LAN966X_VCAP_CID_ES0_MAX,
35 		.count = 64,
36 	},
37 	{
38 		.vtype = VCAP_TYPE_IS1, /* IS1-0 */
39 		.tgt_inst = 1,
40 		.lookups = LAN966X_IS1_LOOKUPS,
41 		.first_cid = LAN966X_VCAP_CID_IS1_L0,
42 		.last_cid = LAN966X_VCAP_CID_IS1_MAX,
43 		.count = 768,
44 		.ingress = true,
45 	},
46 	{
47 		.vtype = VCAP_TYPE_IS2, /* IS2-0 */
48 		.tgt_inst = 2,
49 		.lookups = LAN966X_IS2_LOOKUPS,
50 		.first_cid = LAN966X_VCAP_CID_IS2_L0,
51 		.last_cid = LAN966X_VCAP_CID_IS2_MAX,
52 		.count = 256,
53 		.ingress = true,
54 	},
55 };
56 
57 struct lan966x_vcap_cmd_cb {
58 	struct lan966x *lan966x;
59 	u32 instance;
60 };
61 
lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb * cb)62 static u32 lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb *cb)
63 {
64 	return lan_rd(cb->lan966x, VCAP_UPDATE_CTRL(cb->instance));
65 }
66 
lan966x_vcap_wait_update(struct lan966x * lan966x,int instance)67 static void lan966x_vcap_wait_update(struct lan966x *lan966x, int instance)
68 {
69 	const struct lan966x_vcap_cmd_cb cb = { .lan966x = lan966x,
70 						.instance = instance };
71 	u32 val;
72 
73 	readx_poll_timeout(lan966x_vcap_read_update_ctrl, &cb, val,
74 			   (val & VCAP_UPDATE_CTRL_UPDATE_SHOT) == 0, 10,
75 			   100000);
76 }
77 
__lan966x_vcap_range_init(struct lan966x * lan966x,struct vcap_admin * admin,u32 addr,u32 count)78 static void __lan966x_vcap_range_init(struct lan966x *lan966x,
79 				      struct vcap_admin *admin,
80 				      u32 addr,
81 				      u32 count)
82 {
83 	lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
84 	       VCAP_MV_CFG_MV_SIZE_SET(count - 1),
85 	       lan966x, VCAP_MV_CFG(admin->tgt_inst));
86 
87 	lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
88 	       VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
89 	       VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
90 	       VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
91 	       VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
92 	       VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(true) |
93 	       VCAP_UPDATE_CTRL_UPDATE_SHOT_SET(1),
94 	       lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
95 
96 	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
97 }
98 
lan966x_vcap_is1_cid_to_lookup(int cid)99 static int lan966x_vcap_is1_cid_to_lookup(int cid)
100 {
101 	int lookup = 0;
102 
103 	if (cid >= LAN966X_VCAP_CID_IS1_L1 &&
104 	    cid < LAN966X_VCAP_CID_IS1_L2)
105 		lookup = 1;
106 	else if (cid >= LAN966X_VCAP_CID_IS1_L2 &&
107 		 cid < LAN966X_VCAP_CID_IS1_MAX)
108 		lookup = 2;
109 
110 	return lookup;
111 }
112 
lan966x_vcap_is2_cid_to_lookup(int cid)113 static int lan966x_vcap_is2_cid_to_lookup(int cid)
114 {
115 	if (cid >= LAN966X_VCAP_CID_IS2_L1 &&
116 	    cid < LAN966X_VCAP_CID_IS2_MAX)
117 		return 1;
118 
119 	return 0;
120 }
121 
122 /* Return the list of keysets for the vcap port configuration */
123 static int
lan966x_vcap_is1_get_port_keysets(struct net_device * ndev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)124 lan966x_vcap_is1_get_port_keysets(struct net_device *ndev, int lookup,
125 				  struct vcap_keyset_list *keysetlist,
126 				  u16 l3_proto)
127 {
128 	struct lan966x_port *port = netdev_priv(ndev);
129 	struct lan966x *lan966x = port->lan966x;
130 	u32 val;
131 
132 	val = lan_rd(lan966x, ANA_VCAP_S1_CFG(port->chip_port, lookup));
133 
134 	/* Collect all keysets for the port in a list */
135 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
136 		switch (ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(val)) {
137 		case VCAP_IS1_PS_IPV4_7TUPLE:
138 			vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
139 			break;
140 		case VCAP_IS1_PS_IPV4_5TUPLE_IP4:
141 			vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4);
142 			break;
143 		case VCAP_IS1_PS_IPV4_NORMAL:
144 			vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
145 			break;
146 		}
147 	}
148 
149 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
150 		switch (ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(val)) {
151 		case VCAP_IS1_PS_IPV6_NORMAL:
152 		case VCAP_IS1_PS_IPV6_NORMAL_IP6:
153 			vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
154 			vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_IP6);
155 			break;
156 		case VCAP_IS1_PS_IPV6_5TUPLE_IP6:
157 			vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP6);
158 			break;
159 		case VCAP_IS1_PS_IPV6_7TUPLE:
160 			vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
161 			break;
162 		case VCAP_IS1_PS_IPV6_5TUPLE_IP4:
163 			vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4);
164 			break;
165 		case VCAP_IS1_PS_IPV6_DMAC_VID:
166 			vcap_keyset_list_add(keysetlist, VCAP_KFS_DMAC_VID);
167 			break;
168 		}
169 	}
170 
171 	switch (ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(val)) {
172 	case VCAP_IS1_PS_OTHER_7TUPLE:
173 		vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
174 		break;
175 	case VCAP_IS1_PS_OTHER_NORMAL:
176 		vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
177 		break;
178 	}
179 
180 	return 0;
181 }
182 
183 static int
lan966x_vcap_is2_get_port_keysets(struct net_device * dev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)184 lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup,
185 				  struct vcap_keyset_list *keysetlist,
186 				  u16 l3_proto)
187 {
188 	struct lan966x_port *port = netdev_priv(dev);
189 	struct lan966x *lan966x = port->lan966x;
190 	bool found = false;
191 	u32 val;
192 
193 	val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port));
194 
195 	/* Collect all keysets for the port in a list */
196 	if (l3_proto == ETH_P_ALL)
197 		vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
198 
199 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_SNAP) {
200 		if (ANA_VCAP_S2_CFG_SNAP_DIS_GET(val) & (BIT(0) << lookup))
201 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_LLC);
202 		else
203 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_SNAP);
204 
205 		found = true;
206 	}
207 
208 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_CFM) {
209 		if (ANA_VCAP_S2_CFG_OAM_DIS_GET(val) & (BIT(0) << lookup))
210 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
211 		else
212 			vcap_keyset_list_add(keysetlist, VCAP_KFS_OAM);
213 
214 		found = true;
215 	}
216 
217 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
218 		if (ANA_VCAP_S2_CFG_ARP_DIS_GET(val) & (BIT(0) << lookup))
219 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
220 		else
221 			vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
222 
223 		found = true;
224 	}
225 
226 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
227 		if (ANA_VCAP_S2_CFG_IP_OTHER_DIS_GET(val) & (BIT(0) << lookup))
228 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
229 		else
230 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
231 
232 		if (ANA_VCAP_S2_CFG_IP_TCPUDP_DIS_GET(val) & (BIT(0) << lookup))
233 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
234 		else
235 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
236 
237 		found = true;
238 	}
239 
240 	if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
241 		switch (ANA_VCAP_S2_CFG_IP6_CFG_GET(val) & (0x3 << lookup)) {
242 		case VCAP_IS2_PS_IPV6_TCPUDP_OTHER:
243 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_OTHER);
244 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_TCP_UDP);
245 			break;
246 		case VCAP_IS2_PS_IPV6_STD:
247 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
248 			break;
249 		case VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER:
250 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
251 			vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
252 			break;
253 		case VCAP_IS2_PS_IPV6_MAC_ETYPE:
254 			vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
255 			break;
256 		}
257 
258 		found = true;
259 	}
260 
261 	if (!found)
262 		vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
263 
264 	return 0;
265 }
266 
267 static enum vcap_keyfield_set
lan966x_vcap_validate_keyset(struct net_device * dev,struct vcap_admin * admin,struct vcap_rule * rule,struct vcap_keyset_list * kslist,u16 l3_proto)268 lan966x_vcap_validate_keyset(struct net_device *dev,
269 			     struct vcap_admin *admin,
270 			     struct vcap_rule *rule,
271 			     struct vcap_keyset_list *kslist,
272 			     u16 l3_proto)
273 {
274 	struct vcap_keyset_list keysetlist = {};
275 	enum vcap_keyfield_set keysets[10] = {};
276 	int lookup;
277 	int err;
278 
279 	if (!kslist || kslist->cnt == 0)
280 		return VCAP_KFS_NO_VALUE;
281 
282 	keysetlist.max = ARRAY_SIZE(keysets);
283 	keysetlist.keysets = keysets;
284 
285 	switch (admin->vtype) {
286 	case VCAP_TYPE_IS1:
287 		lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id);
288 		err = lan966x_vcap_is1_get_port_keysets(dev, lookup, &keysetlist,
289 							l3_proto);
290 		break;
291 	case VCAP_TYPE_IS2:
292 		lookup = lan966x_vcap_is2_cid_to_lookup(rule->vcap_chain_id);
293 		err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist,
294 							l3_proto);
295 		break;
296 	case VCAP_TYPE_ES0:
297 		return kslist->keysets[0];
298 	default:
299 		pr_err("vcap type: %s not supported\n",
300 		       lan966x_vcaps[admin->vtype].name);
301 		return VCAP_KFS_NO_VALUE;
302 	}
303 
304 	if (err)
305 		return VCAP_KFS_NO_VALUE;
306 
307 	/* Check if there is a match and return the match */
308 	for (int i = 0; i < kslist->cnt; ++i)
309 		for (int j = 0; j < keysetlist.cnt; ++j)
310 			if (kslist->keysets[i] == keysets[j])
311 				return kslist->keysets[i];
312 
313 	return VCAP_KFS_NO_VALUE;
314 }
315 
lan966x_vcap_is2_is_first_chain(struct vcap_rule * rule)316 static bool lan966x_vcap_is2_is_first_chain(struct vcap_rule *rule)
317 {
318 	return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 &&
319 		rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1);
320 }
321 
lan966x_vcap_is1_add_default_fields(struct lan966x_port * port,struct vcap_admin * admin,struct vcap_rule * rule)322 static void lan966x_vcap_is1_add_default_fields(struct lan966x_port *port,
323 						struct vcap_admin *admin,
324 						struct vcap_rule *rule)
325 {
326 	u32 value, mask;
327 	u32 lookup;
328 
329 	if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
330 				  &value, &mask))
331 		vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
332 				      ~BIT(port->chip_port));
333 
334 	lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id);
335 	vcap_rule_add_key_u32(rule, VCAP_KF_LOOKUP_INDEX, lookup, 0x3);
336 }
337 
lan966x_vcap_is2_add_default_fields(struct lan966x_port * port,struct vcap_admin * admin,struct vcap_rule * rule)338 static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port,
339 						struct vcap_admin *admin,
340 						struct vcap_rule *rule)
341 {
342 	u32 value, mask;
343 
344 	if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
345 				  &value, &mask))
346 		vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
347 				      ~BIT(port->chip_port));
348 
349 	if (lan966x_vcap_is2_is_first_chain(rule))
350 		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
351 				      VCAP_BIT_1);
352 	else
353 		vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
354 				      VCAP_BIT_0);
355 }
356 
lan966x_vcap_es0_add_default_fields(struct lan966x_port * port,struct vcap_admin * admin,struct vcap_rule * rule)357 static void lan966x_vcap_es0_add_default_fields(struct lan966x_port *port,
358 						struct vcap_admin *admin,
359 						struct vcap_rule *rule)
360 {
361 	vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO,
362 			      port->chip_port, GENMASK(4, 0));
363 }
364 
lan966x_vcap_add_default_fields(struct net_device * dev,struct vcap_admin * admin,struct vcap_rule * rule)365 static void lan966x_vcap_add_default_fields(struct net_device *dev,
366 					    struct vcap_admin *admin,
367 					    struct vcap_rule *rule)
368 {
369 	struct lan966x_port *port = netdev_priv(dev);
370 
371 	switch (admin->vtype) {
372 	case VCAP_TYPE_IS1:
373 		lan966x_vcap_is1_add_default_fields(port, admin, rule);
374 		break;
375 	case VCAP_TYPE_IS2:
376 		lan966x_vcap_is2_add_default_fields(port, admin, rule);
377 		break;
378 	case VCAP_TYPE_ES0:
379 		lan966x_vcap_es0_add_default_fields(port, admin, rule);
380 		break;
381 	default:
382 		pr_err("vcap type: %s not supported\n",
383 		       lan966x_vcaps[admin->vtype].name);
384 		break;
385 	}
386 }
387 
lan966x_vcap_cache_erase(struct vcap_admin * admin)388 static void lan966x_vcap_cache_erase(struct vcap_admin *admin)
389 {
390 	memset(admin->cache.keystream, 0, STREAMSIZE);
391 	memset(admin->cache.maskstream, 0, STREAMSIZE);
392 	memset(admin->cache.actionstream, 0, STREAMSIZE);
393 	memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
394 }
395 
396 /* The ESDX counter is only used/incremented if the frame has been classified
397  * with an ISDX > 0 (e.g by a rule in IS0).  This is not mentioned in the
398  * datasheet.
399  */
lan966x_es0_read_esdx_counter(struct lan966x * lan966x,struct vcap_admin * admin,u32 id)400 static void lan966x_es0_read_esdx_counter(struct lan966x *lan966x,
401 					  struct vcap_admin *admin, u32 id)
402 {
403 	u32 counter;
404 
405 	id = id & 0xff; /* counter limit */
406 	mutex_lock(&lan966x->stats_lock);
407 	lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
408 	counter = lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)) +
409 		  lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
410 	mutex_unlock(&lan966x->stats_lock);
411 	if (counter)
412 		admin->cache.counter = counter;
413 }
414 
lan966x_es0_write_esdx_counter(struct lan966x * lan966x,struct vcap_admin * admin,u32 id)415 static void lan966x_es0_write_esdx_counter(struct lan966x *lan966x,
416 					   struct vcap_admin *admin, u32 id)
417 {
418 	id = id & 0xff; /* counter limit */
419 
420 	mutex_lock(&lan966x->stats_lock);
421 	lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
422 	lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_BYTES));
423 	lan_wr(admin->cache.counter, lan966x,
424 	       SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS));
425 	lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_BYTES));
426 	lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
427 	mutex_unlock(&lan966x->stats_lock);
428 }
429 
lan966x_vcap_cache_write(struct net_device * dev,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)430 static void lan966x_vcap_cache_write(struct net_device *dev,
431 				     struct vcap_admin *admin,
432 				     enum vcap_selection sel,
433 				     u32 start,
434 				     u32 count)
435 {
436 	struct lan966x_port *port = netdev_priv(dev);
437 	struct lan966x *lan966x = port->lan966x;
438 	u32 *keystr, *mskstr, *actstr;
439 
440 	keystr = &admin->cache.keystream[start];
441 	mskstr = &admin->cache.maskstream[start];
442 	actstr = &admin->cache.actionstream[start];
443 
444 	switch (sel) {
445 	case VCAP_SEL_ENTRY:
446 		for (int i = 0; i < count; ++i) {
447 			lan_wr(keystr[i] & mskstr[i], lan966x,
448 			       VCAP_ENTRY_DAT(admin->tgt_inst, i));
449 			lan_wr(~mskstr[i], lan966x,
450 			       VCAP_MASK_DAT(admin->tgt_inst, i));
451 		}
452 		break;
453 	case VCAP_SEL_ACTION:
454 		for (int i = 0; i < count; ++i)
455 			lan_wr(actstr[i], lan966x,
456 			       VCAP_ACTION_DAT(admin->tgt_inst, i));
457 		break;
458 	case VCAP_SEL_COUNTER:
459 		admin->cache.sticky = admin->cache.counter > 0;
460 		lan_wr(admin->cache.counter, lan966x,
461 		       VCAP_CNT_DAT(admin->tgt_inst, 0));
462 
463 		if (admin->vtype == VCAP_TYPE_ES0)
464 			lan966x_es0_write_esdx_counter(lan966x, admin, start);
465 		break;
466 	default:
467 		break;
468 	}
469 }
470 
lan966x_vcap_cache_read(struct net_device * dev,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)471 static void lan966x_vcap_cache_read(struct net_device *dev,
472 				    struct vcap_admin *admin,
473 				    enum vcap_selection sel,
474 				    u32 start,
475 				    u32 count)
476 {
477 	struct lan966x_port *port = netdev_priv(dev);
478 	struct lan966x *lan966x = port->lan966x;
479 	int instance = admin->tgt_inst;
480 	u32 *keystr, *mskstr, *actstr;
481 
482 	keystr = &admin->cache.keystream[start];
483 	mskstr = &admin->cache.maskstream[start];
484 	actstr = &admin->cache.actionstream[start];
485 
486 	if (sel & VCAP_SEL_ENTRY) {
487 		for (int i = 0; i < count; ++i) {
488 			keystr[i] =
489 				lan_rd(lan966x, VCAP_ENTRY_DAT(instance, i));
490 			mskstr[i] =
491 				~lan_rd(lan966x, VCAP_MASK_DAT(instance, i));
492 		}
493 	}
494 
495 	if (sel & VCAP_SEL_ACTION)
496 		for (int i = 0; i < count; ++i)
497 			actstr[i] =
498 				lan_rd(lan966x, VCAP_ACTION_DAT(instance, i));
499 
500 	if (sel & VCAP_SEL_COUNTER) {
501 		admin->cache.counter =
502 			lan_rd(lan966x, VCAP_CNT_DAT(instance, 0));
503 		admin->cache.sticky = admin->cache.counter > 0;
504 
505 		if (admin->vtype == VCAP_TYPE_ES0)
506 			lan966x_es0_read_esdx_counter(lan966x, admin, start);
507 	}
508 }
509 
lan966x_vcap_range_init(struct net_device * dev,struct vcap_admin * admin,u32 addr,u32 count)510 static void lan966x_vcap_range_init(struct net_device *dev,
511 				    struct vcap_admin *admin,
512 				    u32 addr,
513 				    u32 count)
514 {
515 	struct lan966x_port *port = netdev_priv(dev);
516 	struct lan966x *lan966x = port->lan966x;
517 
518 	__lan966x_vcap_range_init(lan966x, admin, addr, count);
519 }
520 
lan966x_vcap_update(struct net_device * dev,struct vcap_admin * admin,enum vcap_command cmd,enum vcap_selection sel,u32 addr)521 static void lan966x_vcap_update(struct net_device *dev,
522 				struct vcap_admin *admin,
523 				enum vcap_command cmd,
524 				enum vcap_selection sel,
525 				u32 addr)
526 {
527 	struct lan966x_port *port = netdev_priv(dev);
528 	struct lan966x *lan966x = port->lan966x;
529 	bool clear;
530 
531 	clear = (cmd == VCAP_CMD_INITIALIZE);
532 
533 	lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
534 	       VCAP_MV_CFG_MV_SIZE_SET(0),
535 	       lan966x, VCAP_MV_CFG(admin->tgt_inst));
536 
537 	lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
538 	       VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
539 	       VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
540 	       VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
541 	       VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
542 	       VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(clear) |
543 	       VCAP_UPDATE_CTRL_UPDATE_SHOT,
544 	       lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
545 
546 	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
547 }
548 
lan966x_vcap_move(struct net_device * dev,struct vcap_admin * admin,u32 addr,int offset,int count)549 static void lan966x_vcap_move(struct net_device *dev,
550 			      struct vcap_admin *admin,
551 			      u32 addr, int offset, int count)
552 {
553 	struct lan966x_port *port = netdev_priv(dev);
554 	struct lan966x *lan966x = port->lan966x;
555 	enum vcap_command cmd;
556 	u16 mv_num_pos;
557 	u16 mv_size;
558 
559 	mv_size = count - 1;
560 	if (offset > 0) {
561 		mv_num_pos = offset - 1;
562 		cmd = VCAP_CMD_MOVE_DOWN;
563 	} else {
564 		mv_num_pos = -offset - 1;
565 		cmd = VCAP_CMD_MOVE_UP;
566 	}
567 
568 	lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(mv_num_pos) |
569 	       VCAP_MV_CFG_MV_SIZE_SET(mv_size),
570 	       lan966x, VCAP_MV_CFG(admin->tgt_inst));
571 
572 	lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
573 	       VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
574 	       VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
575 	       VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
576 	       VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
577 	       VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(false) |
578 	       VCAP_UPDATE_CTRL_UPDATE_SHOT,
579 	       lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
580 
581 	lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
582 }
583 
584 static const struct vcap_operations lan966x_vcap_ops = {
585 	.validate_keyset = lan966x_vcap_validate_keyset,
586 	.add_default_fields = lan966x_vcap_add_default_fields,
587 	.cache_erase = lan966x_vcap_cache_erase,
588 	.cache_write = lan966x_vcap_cache_write,
589 	.cache_read = lan966x_vcap_cache_read,
590 	.init = lan966x_vcap_range_init,
591 	.update = lan966x_vcap_update,
592 	.move = lan966x_vcap_move,
593 	.port_info = lan966x_vcap_port_info,
594 };
595 
lan966x_vcap_admin_free(struct vcap_admin * admin)596 static void lan966x_vcap_admin_free(struct vcap_admin *admin)
597 {
598 	if (!admin)
599 		return;
600 
601 	kfree(admin->cache.keystream);
602 	kfree(admin->cache.maskstream);
603 	kfree(admin->cache.actionstream);
604 	mutex_destroy(&admin->lock);
605 	kfree(admin);
606 }
607 
608 static struct vcap_admin *
lan966x_vcap_admin_alloc(struct lan966x * lan966x,struct vcap_control * ctrl,const struct lan966x_vcap_inst * cfg)609 lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl,
610 			 const struct lan966x_vcap_inst *cfg)
611 {
612 	struct vcap_admin *admin;
613 
614 	admin = kzalloc(sizeof(*admin), GFP_KERNEL);
615 	if (!admin)
616 		return ERR_PTR(-ENOMEM);
617 
618 	mutex_init(&admin->lock);
619 	INIT_LIST_HEAD(&admin->list);
620 	INIT_LIST_HEAD(&admin->rules);
621 	INIT_LIST_HEAD(&admin->enabled);
622 
623 	admin->vtype = cfg->vtype;
624 	admin->vinst = 0;
625 	admin->ingress = cfg->ingress;
626 	admin->w32be = true;
627 	admin->tgt_inst = cfg->tgt_inst;
628 
629 	admin->lookups = cfg->lookups;
630 	admin->lookups_per_instance = cfg->lookups;
631 
632 	admin->first_cid = cfg->first_cid;
633 	admin->last_cid = cfg->last_cid;
634 
635 	admin->cache.keystream = kzalloc(STREAMSIZE, GFP_KERNEL);
636 	admin->cache.maskstream = kzalloc(STREAMSIZE, GFP_KERNEL);
637 	admin->cache.actionstream = kzalloc(STREAMSIZE, GFP_KERNEL);
638 	if (!admin->cache.keystream ||
639 	    !admin->cache.maskstream ||
640 	    !admin->cache.actionstream) {
641 		lan966x_vcap_admin_free(admin);
642 		return ERR_PTR(-ENOMEM);
643 	}
644 
645 	return admin;
646 }
647 
lan966x_vcap_block_init(struct lan966x * lan966x,struct vcap_admin * admin,struct lan966x_vcap_inst * cfg)648 static void lan966x_vcap_block_init(struct lan966x *lan966x,
649 				    struct vcap_admin *admin,
650 				    struct lan966x_vcap_inst *cfg)
651 {
652 	admin->first_valid_addr = 0;
653 	admin->last_used_addr = cfg->count;
654 	admin->last_valid_addr = cfg->count - 1;
655 
656 	lan_wr(VCAP_CORE_IDX_CORE_IDX_SET(0),
657 	       lan966x, VCAP_CORE_IDX(admin->tgt_inst));
658 	lan_wr(VCAP_CORE_MAP_CORE_MAP_SET(1),
659 	       lan966x, VCAP_CORE_MAP(admin->tgt_inst));
660 
661 	__lan966x_vcap_range_init(lan966x, admin, admin->first_valid_addr,
662 				  admin->last_valid_addr -
663 					admin->first_valid_addr);
664 }
665 
lan966x_vcap_port_key_deselection(struct lan966x * lan966x,struct vcap_admin * admin)666 static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,
667 					      struct vcap_admin *admin)
668 {
669 	u32 val;
670 
671 	switch (admin->vtype) {
672 	case VCAP_TYPE_IS1:
673 		val = ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(VCAP_IS1_PS_IPV6_5TUPLE_IP6) |
674 		      ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(VCAP_IS1_PS_IPV4_5TUPLE_IP4) |
675 		      ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(VCAP_IS1_PS_OTHER_NORMAL);
676 
677 		for (int p = 0; p < lan966x->num_phys_ports; ++p) {
678 			if (!lan966x->ports[p])
679 				continue;
680 
681 			for (int l = 0; l < LAN966X_IS1_LOOKUPS; ++l)
682 				lan_wr(val, lan966x, ANA_VCAP_S1_CFG(p, l));
683 
684 			lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
685 				ANA_VCAP_CFG_S1_ENA, lan966x,
686 				ANA_VCAP_CFG(p));
687 		}
688 
689 		break;
690 	case VCAP_TYPE_IS2:
691 		for (int p = 0; p < lan966x->num_phys_ports; ++p)
692 			lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p));
693 
694 		break;
695 	case VCAP_TYPE_ES0:
696 		for (int p = 0; p < lan966x->num_phys_ports; ++p)
697 			lan_rmw(REW_PORT_CFG_ES0_EN_SET(false),
698 				REW_PORT_CFG_ES0_EN, lan966x,
699 				REW_PORT_CFG(p));
700 		break;
701 	default:
702 		pr_err("vcap type: %s not supported\n",
703 		       lan966x_vcaps[admin->vtype].name);
704 		break;
705 	}
706 }
707 
lan966x_vcap_init(struct lan966x * lan966x)708 int lan966x_vcap_init(struct lan966x *lan966x)
709 {
710 	struct lan966x_vcap_inst *cfg;
711 	struct vcap_control *ctrl;
712 	struct vcap_admin *admin;
713 	struct dentry *dir;
714 
715 	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
716 	if (!ctrl)
717 		return -ENOMEM;
718 
719 	ctrl->vcaps = lan966x_vcaps;
720 	ctrl->stats = &lan966x_vcap_stats;
721 	ctrl->ops = &lan966x_vcap_ops;
722 
723 	INIT_LIST_HEAD(&ctrl->list);
724 	for (int i = 0; i < ARRAY_SIZE(lan966x_vcap_inst_cfg); ++i) {
725 		cfg = &lan966x_vcap_inst_cfg[i];
726 
727 		admin = lan966x_vcap_admin_alloc(lan966x, ctrl, cfg);
728 		if (IS_ERR(admin))
729 			return PTR_ERR(admin);
730 
731 		lan966x_vcap_block_init(lan966x, admin, cfg);
732 		lan966x_vcap_port_key_deselection(lan966x, admin);
733 
734 		list_add_tail(&admin->list, &ctrl->list);
735 	}
736 
737 	dir = vcap_debugfs(lan966x->dev, lan966x->debugfs_root, ctrl);
738 	for (int p = 0; p < lan966x->num_phys_ports; ++p) {
739 		if (lan966x->ports[p]) {
740 			vcap_port_debugfs(lan966x->dev, dir, ctrl,
741 					  lan966x->ports[p]->dev);
742 
743 			lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(true),
744 				ANA_VCAP_S2_CFG_ENA, lan966x,
745 				ANA_VCAP_S2_CFG(lan966x->ports[p]->chip_port));
746 
747 			lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
748 				ANA_VCAP_CFG_S1_ENA, lan966x,
749 				ANA_VCAP_CFG(lan966x->ports[p]->chip_port));
750 
751 			lan_rmw(REW_PORT_CFG_ES0_EN_SET(true),
752 				REW_PORT_CFG_ES0_EN, lan966x,
753 				REW_PORT_CFG(lan966x->ports[p]->chip_port));
754 		}
755 	}
756 
757 	/* Statistics: Use ESDX from ES0 if hit, otherwise no counting */
758 	lan_rmw(REW_STAT_CFG_STAT_MODE_SET(1),
759 		REW_STAT_CFG_STAT_MODE, lan966x,
760 		REW_STAT_CFG);
761 
762 	lan966x->vcap_ctrl = ctrl;
763 
764 	return 0;
765 }
766 
lan966x_vcap_deinit(struct lan966x * lan966x)767 void lan966x_vcap_deinit(struct lan966x *lan966x)
768 {
769 	struct vcap_admin *admin, *admin_next;
770 	struct vcap_control *ctrl;
771 
772 	ctrl = lan966x->vcap_ctrl;
773 	if (!ctrl)
774 		return;
775 
776 	list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) {
777 		lan966x_vcap_port_key_deselection(lan966x, admin);
778 		vcap_del_rules(ctrl, admin);
779 		list_del(&admin->list);
780 		lan966x_vcap_admin_free(admin);
781 	}
782 
783 	kfree(ctrl);
784 }
785