Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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
 20static 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
 57struct lan966x_vcap_cmd_cb {
 58	struct lan966x *lan966x;
 59	u32 instance;
 60};
 61
 62static 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
 67static 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
 78static 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
 99static 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
113static 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 */
123static int
124lan966x_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
183static int
184lan966x_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
267static enum vcap_keyfield_set
268lan966x_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
316static 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
322static 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
338static 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
357static 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
365static 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
388static 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 */
400static 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
415static 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
430static 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
471static 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
510static 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
521static 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
549static 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
584static 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
596static 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
608static struct vcap_admin *
609lan966x_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
648static 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
666static 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
708int 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
767void 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}