ocelot_vcap.c 29.5 KB
Newer Older
1 2 3 4 5 6 7 8
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Microsemi Ocelot Switch driver
 * Copyright (c) 2019 Microsemi Corporation
 */

#include <linux/iopoll.h>
#include <linux/proc_fs.h>

9
#include <soc/mscc/ocelot_vcap.h>
10
#include "ocelot_police.h"
11
#include "ocelot_vcap.h"
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

#define OCELOT_POLICER_DISCARD 0x17f
#define ENTRY_WIDTH 32

enum vcap_sel {
	VCAP_SEL_ENTRY = 0x1,
	VCAP_SEL_ACTION = 0x2,
	VCAP_SEL_COUNTER = 0x4,
	VCAP_SEL_ALL = 0x7,
};

enum vcap_cmd {
	VCAP_CMD_WRITE = 0, /* Copy from Cache to TCAM */
	VCAP_CMD_READ = 1, /* Copy from TCAM to Cache */
	VCAP_CMD_MOVE_UP = 2, /* Move <count> up */
	VCAP_CMD_MOVE_DOWN = 3, /* Move <count> down */
	VCAP_CMD_INITIALIZE = 4, /* Write all (from cache) */
};

#define VCAP_ENTRY_WIDTH 12 /* Max entry width (32bit words) */
#define VCAP_COUNTER_WIDTH 4 /* Max counter width (32bit words) */

struct vcap_data {
	u32 entry[VCAP_ENTRY_WIDTH]; /* ENTRY_DAT */
	u32 mask[VCAP_ENTRY_WIDTH]; /* MASK_DAT */
	u32 action[VCAP_ENTRY_WIDTH]; /* ACTION_DAT */
	u32 counter[VCAP_COUNTER_WIDTH]; /* CNT_DAT */
	u32 tg; /* TG_DAT */
	u32 type; /* Action type */
	u32 tg_sw; /* Current type-group */
	u32 cnt; /* Current counter */
	u32 key_offset; /* Current entry offset */
	u32 action_offset; /* Current action offset */
	u32 counter_offset; /* Current counter offset */
	u32 tg_value; /* Current type-group value */
	u32 tg_mask; /* Current type-group mask */
48
};
49

50 51
static u32 vcap_read_update_ctrl(struct ocelot *ocelot,
				 const struct vcap_props *vcap)
52
{
53
	return ocelot_target_read(ocelot, vcap->target, VCAP_CORE_UPDATE_CTRL);
54 55
}

56 57
static void vcap_cmd(struct ocelot *ocelot, const struct vcap_props *vcap,
		     u16 ix, int cmd, int sel)
58
{
59 60 61
	u32 value = (VCAP_CORE_UPDATE_CTRL_UPDATE_CMD(cmd) |
		     VCAP_CORE_UPDATE_CTRL_UPDATE_ADDR(ix) |
		     VCAP_CORE_UPDATE_CTRL_UPDATE_SHOT);
62

63
	if ((sel & VCAP_SEL_ENTRY) && ix >= vcap->entry_count)
64 65 66
		return;

	if (!(sel & VCAP_SEL_ENTRY))
67
		value |= VCAP_CORE_UPDATE_CTRL_UPDATE_ENTRY_DIS;
68 69

	if (!(sel & VCAP_SEL_ACTION))
70
		value |= VCAP_CORE_UPDATE_CTRL_UPDATE_ACTION_DIS;
71 72

	if (!(sel & VCAP_SEL_COUNTER))
73 74 75
		value |= VCAP_CORE_UPDATE_CTRL_UPDATE_CNT_DIS;

	ocelot_target_write(ocelot, vcap->target, value, VCAP_CORE_UPDATE_CTRL);
76

77 78 79
	read_poll_timeout(vcap_read_update_ctrl, value,
			  (value & VCAP_CORE_UPDATE_CTRL_UPDATE_SHOT) == 0,
			  10, 100000, false, ocelot, vcap);
80 81 82
}

/* Convert from 0-based row to VCAP entry row and run command */
83 84
static void vcap_row_cmd(struct ocelot *ocelot, const struct vcap_props *vcap,
			 u32 row, int cmd, int sel)
85
{
86
	vcap_cmd(ocelot, vcap, vcap->entry_count - row - 1, cmd, sel);
87 88
}

89 90 91
static void vcap_entry2cache(struct ocelot *ocelot,
			     const struct vcap_props *vcap,
			     struct vcap_data *data)
92
{
93 94
	u32 entry_words, i;

95
	entry_words = DIV_ROUND_UP(vcap->entry_width, ENTRY_WIDTH);
96

97
	for (i = 0; i < entry_words; i++) {
98 99 100 101
		ocelot_target_write_rix(ocelot, vcap->target, data->entry[i],
					VCAP_CACHE_ENTRY_DAT, i);
		ocelot_target_write_rix(ocelot, vcap->target, ~data->mask[i],
					VCAP_CACHE_MASK_DAT, i);
102
	}
103
	ocelot_target_write(ocelot, vcap->target, data->tg, VCAP_CACHE_TG_DAT);
104 105
}

106 107 108
static void vcap_cache2entry(struct ocelot *ocelot,
			     const struct vcap_props *vcap,
			     struct vcap_data *data)
109
{
110 111
	u32 entry_words, i;

112
	entry_words = DIV_ROUND_UP(vcap->entry_width, ENTRY_WIDTH);
113

114
	for (i = 0; i < entry_words; i++) {
115 116
		data->entry[i] = ocelot_target_read_rix(ocelot, vcap->target,
							VCAP_CACHE_ENTRY_DAT, i);
117
		// Invert mask
118 119
		data->mask[i] = ~ocelot_target_read_rix(ocelot, vcap->target,
							VCAP_CACHE_MASK_DAT, i);
120
	}
121
	data->tg = ocelot_target_read(ocelot, vcap->target, VCAP_CACHE_TG_DAT);
122 123
}

124 125 126
static void vcap_action2cache(struct ocelot *ocelot,
			      const struct vcap_props *vcap,
			      struct vcap_data *data)
127
{
128 129
	u32 action_words, mask;
	int i, width;
130 131

	/* Encode action type */
132
	width = vcap->action_type_width;
133 134 135 136 137
	if (width) {
		mask = GENMASK(width, 0);
		data->action[0] = ((data->action[0] & ~mask) | data->type);
	}

138
	action_words = DIV_ROUND_UP(vcap->action_width, ENTRY_WIDTH);
139

140
	for (i = 0; i < action_words; i++)
141 142
		ocelot_target_write_rix(ocelot, vcap->target, data->action[i],
					VCAP_CACHE_ACTION_DAT, i);
143

144 145 146
	for (i = 0; i < vcap->counter_words; i++)
		ocelot_target_write_rix(ocelot, vcap->target, data->counter[i],
					VCAP_CACHE_CNT_DAT, i);
147 148
}

149 150 151
static void vcap_cache2action(struct ocelot *ocelot,
			      const struct vcap_props *vcap,
			      struct vcap_data *data)
152
{
153 154
	u32 action_words;
	int i, width;
155

156
	action_words = DIV_ROUND_UP(vcap->action_width, ENTRY_WIDTH);
157

158
	for (i = 0; i < action_words; i++)
159 160 161
		data->action[i] = ocelot_target_read_rix(ocelot, vcap->target,
							 VCAP_CACHE_ACTION_DAT,
							 i);
162

163 164 165 166
	for (i = 0; i < vcap->counter_words; i++)
		data->counter[i] = ocelot_target_read_rix(ocelot, vcap->target,
							  VCAP_CACHE_CNT_DAT,
							  i);
167 168

	/* Extract action type */
169
	width = vcap->action_type_width;
170 171 172 173
	data->type = (width ? (data->action[0] & GENMASK(width, 0)) : 0);
}

/* Calculate offsets for entry */
174 175
static void vcap_data_offset_get(const struct vcap_props *vcap,
				 struct vcap_data *data, int ix)
176
{
177
	int i, col, offset, count, cnt, base;
178
	u32 width = vcap->tg_width;
179 180 181

	count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4);
	col = (ix % 2);
182 183
	cnt = (vcap->sw_count / count);
	base = (vcap->sw_count - col * cnt - cnt);
184 185 186 187 188 189 190 191 192 193
	data->tg_value = 0;
	data->tg_mask = 0;
	for (i = 0; i < cnt; i++) {
		offset = ((base + i) * width);
		data->tg_value |= (data->tg_sw << offset);
		data->tg_mask |= GENMASK(offset + width - 1, offset);
	}

	/* Calculate key/action/counter offsets */
	col = (count - col - 1);
194 195
	data->key_offset = (base * vcap->entry_width) / vcap->sw_count;
	data->counter_offset = (cnt * col * vcap->counter_width);
196
	i = data->type;
197 198 199 200
	width = vcap->action_table[i].width;
	cnt = vcap->action_table[i].count;
	data->action_offset = (((cnt * col * width) / count) +
			      vcap->action_type_width);
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
}

static void vcap_data_set(u32 *data, u32 offset, u32 len, u32 value)
{
	u32 i, v, m;

	for (i = 0; i < len; i++, offset++) {
		v = data[offset / ENTRY_WIDTH];
		m = (1 << (offset % ENTRY_WIDTH));
		if (value & (1 << i))
			v |= m;
		else
			v &= ~m;
		data[offset / ENTRY_WIDTH] = v;
	}
}

static u32 vcap_data_get(u32 *data, u32 offset, u32 len)
{
	u32 i, v, m, value = 0;

	for (i = 0; i < len; i++, offset++) {
		v = data[offset / ENTRY_WIDTH];
		m = (1 << (offset % ENTRY_WIDTH));
		if (v & m)
			value |= (1 << i);
	}
	return value;
}

231 232
static void vcap_key_field_set(struct vcap_data *data, u32 offset, u32 width,
			       u32 value, u32 mask)
233 234 235 236 237
{
	vcap_data_set(data->entry, offset + data->key_offset, width, value);
	vcap_data_set(data->mask, offset + data->key_offset, width, mask);
}

238 239
static void vcap_key_set(const struct vcap_props *vcap, struct vcap_data *data,
			 int field, u32 value, u32 mask)
240
{
241 242
	u32 offset = vcap->keys[field].offset;
	u32 length = vcap->keys[field].length;
243 244 245 246

	vcap_key_field_set(data, offset, length, value, mask);
}

247 248
static void vcap_key_bytes_set(const struct vcap_props *vcap,
			       struct vcap_data *data, int field,
249
			       u8 *val, u8 *msk)
250
{
251 252
	u32 offset = vcap->keys[field].offset;
	u32 count  = vcap->keys[field].length;
253 254
	u32 i, j, n = 0, value = 0, mask = 0;

255 256
	WARN_ON(count % 8);

257 258 259
	/* Data wider than 32 bits are split up in chunks of maximum 32 bits.
	 * The 32 LSB of the data are written to the 32 MSB of the TCAM.
	 */
260 261 262
	offset += count;
	count /= 8;

263 264 265 266 267 268 269
	for (i = 0; i < count; i++) {
		j = (count - i - 1);
		value += (val[j] << n);
		mask += (msk[j] << n);
		n += 8;
		if (n == ENTRY_WIDTH || (i + 1) == count) {
			offset -= n;
270
			vcap_key_field_set(data, offset, n, value, mask);
271 272 273 274 275 276 277
			n = 0;
			value = 0;
			mask = 0;
		}
	}
}

278 279
static void vcap_key_l4_port_set(const struct vcap_props *vcap,
				 struct vcap_data *data, int field,
280 281
				 struct ocelot_vcap_udp_tcp *port)
{
282 283
	u32 offset = vcap->keys[field].offset;
	u32 length = vcap->keys[field].length;
284 285 286 287

	WARN_ON(length != 16);

	vcap_key_field_set(data, offset, length, port->value, port->mask);
288 289
}

290 291
static void vcap_key_bit_set(const struct vcap_props *vcap,
			     struct vcap_data *data, int field,
292 293
			     enum ocelot_vcap_bit val)
{
294 295
	u32 value = (val == OCELOT_VCAP_BIT_1 ? 1 : 0);
	u32 msk = (val == OCELOT_VCAP_BIT_ANY ? 0 : 1);
296 297
	u32 offset = vcap->keys[field].offset;
	u32 length = vcap->keys[field].length;
298

299
	WARN_ON(length != 1);
300

301
	vcap_key_field_set(data, offset, length, value, msk);
302 303
}

304 305
static void vcap_action_set(const struct vcap_props *vcap,
			    struct vcap_data *data, int field, u32 value)
306
{
307 308
	int offset = vcap->actions[field].offset;
	int length = vcap->actions[field].length;
309 310 311 312

	vcap_data_set(data->action, offset + data->action_offset, length,
		      value);
}
313

314
static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data,
315
			   struct ocelot_vcap_filter *filter)
316
{
317 318
	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];

319 320
	switch (filter->action) {
	case OCELOT_VCAP_ACTION_DROP:
321 322 323 324
		vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 1);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 1);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX,
325
				OCELOT_POLICER_DISCARD);
326 327
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
328
		break;
329
	case OCELOT_VCAP_ACTION_TRAP:
330 331 332 333 334 335
		vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 1);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 1);
336
		break;
337
	case OCELOT_VCAP_ACTION_POLICE:
338 339 340 341
		vcap_action_set(vcap, data, VCAP_IS2_ACT_PORT_MASK, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_MASK_MODE, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_ENA, 1);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_POLICE_IDX,
342
				filter->pol_ix);
343 344
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
345
		break;
346 347 348 349
	}
}

static void is2_entry_set(struct ocelot *ocelot, int ix,
350
			  struct ocelot_vcap_filter *filter)
351
{
352
	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
353
	struct ocelot_vcap_key_vlan *tag = &filter->vlan;
354
	u32 val, msk, type, type_mask = 0xf, i, count;
355 356
	struct ocelot_vcap_u64 payload;
	struct vcap_data data;
357 358
	int row = (ix / 2);

359 360 361
	memset(&payload, 0, sizeof(payload));
	memset(&data, 0, sizeof(data));

362
	/* Read row */
363 364 365
	vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_READ, VCAP_SEL_ALL);
	vcap_cache2entry(ocelot, vcap, &data);
	vcap_cache2action(ocelot, vcap, &data);
366 367

	data.tg_sw = VCAP_TG_HALF;
368
	vcap_data_offset_get(vcap, &data, ix);
369
	data.tg = (data.tg & ~data.tg_mask);
370
	if (filter->prio != 0)
371 372 373 374
		data.tg |= data.tg_value;

	data.type = IS2_ACTION_TYPE_NORMAL;

375 376
	vcap_key_set(vcap, &data, VCAP_IS2_HK_PAG, 0, 0);
	vcap_key_set(vcap, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0,
377
		     ~filter->ingress_port_mask);
378 379
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_ANY);
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_HOST_MATCH,
380
			 OCELOT_VCAP_BIT_ANY);
381 382 383 384
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L2_MC, filter->dmac_mc);
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L2_BC, filter->dmac_bc);
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_VLAN_TAGGED, tag->tagged);
	vcap_key_set(vcap, &data, VCAP_IS2_HK_VID,
385
		     tag->vid.value, tag->vid.mask);
386
	vcap_key_set(vcap, &data, VCAP_IS2_HK_PCP,
387
		     tag->pcp.value[0], tag->pcp.mask[0]);
388
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_DEI, tag->dei);
389

390 391 392
	switch (filter->key_type) {
	case OCELOT_VCAP_KEY_ETYPE: {
		struct ocelot_vcap_key_etype *etype = &filter->key.etype;
393 394

		type = IS2_TYPE_ETYPE;
395
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_DMAC,
396
				   etype->dmac.value, etype->dmac.mask);
397
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_SMAC,
398
				   etype->smac.value, etype->smac.mask);
399
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_ETYPE,
400 401
				   etype->etype.value, etype->etype.mask);
		/* Clear unused bits */
402
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0,
403
			     0, 0);
404
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1,
405
			     0, 0);
406
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2,
407
			     0, 0);
408
		vcap_key_bytes_set(vcap, &data,
409 410
				   VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0,
				   etype->data.value, etype->data.mask);
411 412
		break;
	}
413 414
	case OCELOT_VCAP_KEY_LLC: {
		struct ocelot_vcap_key_llc *llc = &filter->key.llc;
415 416

		type = IS2_TYPE_LLC;
417
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_DMAC,
418
				   llc->dmac.value, llc->dmac.mask);
419
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_SMAC,
420
				   llc->smac.value, llc->smac.mask);
421 422 423 424
		for (i = 0; i < 4; i++) {
			payload.value[i] = llc->llc.value[i];
			payload.mask[i] = llc->llc.mask[i];
		}
425
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_LLC_L2_LLC,
426
				   payload.value, payload.mask);
427 428
		break;
	}
429 430
	case OCELOT_VCAP_KEY_SNAP: {
		struct ocelot_vcap_key_snap *snap = &filter->key.snap;
431 432

		type = IS2_TYPE_SNAP;
433
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_DMAC,
434
				   snap->dmac.value, snap->dmac.mask);
435
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_SMAC,
436
				   snap->smac.value, snap->smac.mask);
437
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_SNAP_L2_SNAP,
438 439
				   filter->key.snap.snap.value,
				   filter->key.snap.snap.mask);
440 441
		break;
	}
442 443
	case OCELOT_VCAP_KEY_ARP: {
		struct ocelot_vcap_key_arp *arp = &filter->key.arp;
444 445

		type = IS2_TYPE_ARP;
446
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_ARP_SMAC,
447
				   arp->smac.value, arp->smac.mask);
448
		vcap_key_bit_set(vcap, &data,
449 450
				 VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK,
				 arp->ethernet);
451
		vcap_key_bit_set(vcap, &data,
452 453
				 VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK,
				 arp->ip);
454
		vcap_key_bit_set(vcap, &data,
455 456
				 VCAP_IS2_HK_MAC_ARP_LEN_OK,
				 arp->length);
457
		vcap_key_bit_set(vcap, &data,
458 459
				 VCAP_IS2_HK_MAC_ARP_TARGET_MATCH,
				 arp->dmac_match);
460
		vcap_key_bit_set(vcap, &data,
461 462
				 VCAP_IS2_HK_MAC_ARP_SENDER_MATCH,
				 arp->smac_match);
463
		vcap_key_bit_set(vcap, &data,
464 465
				 VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN,
				 arp->unknown);
466 467 468 469 470 471

		/* OPCODE is inverse, bit 0 is reply flag, bit 1 is RARP flag */
		val = ((arp->req == OCELOT_VCAP_BIT_0 ? 1 : 0) |
		       (arp->arp == OCELOT_VCAP_BIT_0 ? 2 : 0));
		msk = ((arp->req == OCELOT_VCAP_BIT_ANY ? 0 : 1) |
		       (arp->arp == OCELOT_VCAP_BIT_ANY ? 0 : 2));
472
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ARP_OPCODE,
473
			     val, msk);
474
		vcap_key_bytes_set(vcap, &data,
475 476
				   VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP,
				   arp->dip.value.addr, arp->dip.mask.addr);
477
		vcap_key_bytes_set(vcap, &data,
478 479
				   VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP,
				   arp->sip.value.addr, arp->sip.mask.addr);
480
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP,
481
			     0, 0);
482 483
		break;
	}
484 485
	case OCELOT_VCAP_KEY_IPV4:
	case OCELOT_VCAP_KEY_IPV6: {
486 487 488
		enum ocelot_vcap_bit sip_eq_dip, sport_eq_dport, seq_zero, tcp;
		enum ocelot_vcap_bit ttl, fragment, options, tcp_ack, tcp_urg;
		enum ocelot_vcap_bit tcp_fin, tcp_syn, tcp_rst, tcp_psh;
489 490
		struct ocelot_vcap_key_ipv4 *ipv4 = NULL;
		struct ocelot_vcap_key_ipv6 *ipv6 = NULL;
491 492 493 494 495
		struct ocelot_vcap_udp_tcp *sport, *dport;
		struct ocelot_vcap_ipv4 sip, dip;
		struct ocelot_vcap_u8 proto, ds;
		struct ocelot_vcap_u48 *ip_data;

496 497
		if (filter->key_type == OCELOT_VCAP_KEY_IPV4) {
			ipv4 = &filter->key.ipv4;
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
			ttl = ipv4->ttl;
			fragment = ipv4->fragment;
			options = ipv4->options;
			proto = ipv4->proto;
			ds = ipv4->ds;
			ip_data = &ipv4->data;
			sip = ipv4->sip;
			dip = ipv4->dip;
			sport = &ipv4->sport;
			dport = &ipv4->dport;
			tcp_fin = ipv4->tcp_fin;
			tcp_syn = ipv4->tcp_syn;
			tcp_rst = ipv4->tcp_rst;
			tcp_psh = ipv4->tcp_psh;
			tcp_ack = ipv4->tcp_ack;
			tcp_urg = ipv4->tcp_urg;
			sip_eq_dip = ipv4->sip_eq_dip;
			sport_eq_dport = ipv4->sport_eq_dport;
			seq_zero = ipv4->seq_zero;
		} else {
518
			ipv6 = &filter->key.ipv6;
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
			ttl = ipv6->ttl;
			fragment = OCELOT_VCAP_BIT_ANY;
			options = OCELOT_VCAP_BIT_ANY;
			proto = ipv6->proto;
			ds = ipv6->ds;
			ip_data = &ipv6->data;
			for (i = 0; i < 8; i++) {
				val = ipv6->sip.value[i + 8];
				msk = ipv6->sip.mask[i + 8];
				if (i < 4) {
					dip.value.addr[i] = val;
					dip.mask.addr[i] = msk;
				} else {
					sip.value.addr[i - 4] = val;
					sip.mask.addr[i - 4] = msk;
				}
			}
			sport = &ipv6->sport;
			dport = &ipv6->dport;
			tcp_fin = ipv6->tcp_fin;
			tcp_syn = ipv6->tcp_syn;
			tcp_rst = ipv6->tcp_rst;
			tcp_psh = ipv6->tcp_psh;
			tcp_ack = ipv6->tcp_ack;
			tcp_urg = ipv6->tcp_urg;
			sip_eq_dip = ipv6->sip_eq_dip;
			sport_eq_dport = ipv6->sport_eq_dport;
			seq_zero = ipv6->seq_zero;
		}

549
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_IP4,
550
				 ipv4 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0);
551
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L3_FRAGMENT,
552
				 fragment);
553 554
		vcap_key_set(vcap, &data, VCAP_IS2_HK_L3_FRAG_OFS_GT0, 0, 0);
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L3_OPTIONS,
555
				 options);
556
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_IP4_L3_TTL_GT0,
557
				 ttl);
558
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L3_TOS,
559
				   ds.value, ds.mask);
560
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L3_IP4_DIP,
561
				   dip.value.addr, dip.mask.addr);
562
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L3_IP4_SIP,
563
				   sip.value.addr, sip.mask.addr);
564
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_DIP_EQ_SIP,
565
				 sip_eq_dip);
566 567 568 569 570 571 572
		val = proto.value[0];
		msk = proto.mask[0];
		type = IS2_TYPE_IP_UDP_TCP;
		if (msk == 0xff && (val == 6 || val == 17)) {
			/* UDP/TCP protocol match */
			tcp = (val == 6 ?
			       OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0);
573 574
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_TCP, tcp);
			vcap_key_l4_port_set(vcap, &data,
575
					     VCAP_IS2_HK_L4_DPORT, dport);
576
			vcap_key_l4_port_set(vcap, &data,
577
					     VCAP_IS2_HK_L4_SPORT, sport);
578 579
			vcap_key_set(vcap, &data, VCAP_IS2_HK_L4_RNG, 0, 0);
			vcap_key_bit_set(vcap, &data,
580
					 VCAP_IS2_HK_L4_SPORT_EQ_DPORT,
581
					 sport_eq_dport);
582
			vcap_key_bit_set(vcap, &data,
583 584
					 VCAP_IS2_HK_L4_SEQUENCE_EQ0,
					 seq_zero);
585
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_FIN,
586
					 tcp_fin);
587
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_SYN,
588
					 tcp_syn);
589
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_RST,
590
					 tcp_rst);
591
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_PSH,
592
					 tcp_psh);
593
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_ACK,
594
					 tcp_ack);
595
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_URG,
596
					 tcp_urg);
597
			vcap_key_set(vcap, &data, VCAP_IS2_HK_L4_1588_DOM,
598
				     0, 0);
599
			vcap_key_set(vcap, &data, VCAP_IS2_HK_L4_1588_VER,
600
				     0, 0);
601 602 603 604 605 606 607 608 609 610 611 612
		} else {
			if (msk == 0) {
				/* Any IP protocol match */
				type_mask = IS2_TYPE_MASK_IP_ANY;
			} else {
				/* Non-UDP/TCP protocol match */
				type = IS2_TYPE_IP_OTHER;
				for (i = 0; i < 6; i++) {
					payload.value[i] = ip_data->value[i];
					payload.mask[i] = ip_data->mask[i];
				}
			}
613
			vcap_key_bytes_set(vcap, &data,
614 615
					   VCAP_IS2_HK_IP4_L3_PROTO,
					   proto.value, proto.mask);
616
			vcap_key_bytes_set(vcap, &data,
617 618
					   VCAP_IS2_HK_L3_PAYLOAD,
					   payload.value, payload.mask);
619 620 621
		}
		break;
	}
622
	case OCELOT_VCAP_KEY_ANY:
623 624 625
	default:
		type = 0;
		type_mask = 0;
626
		count = vcap->entry_width / 2;
627 628 629
		/* Iterate over the non-common part of the key and
		 * clear entry data
		 */
630
		for (i = vcap->keys[VCAP_IS2_HK_L2_DMAC].offset;
631 632
		     i < count; i += ENTRY_WIDTH) {
			vcap_key_field_set(&data, i, min(32u, count - i), 0, 0);
633 634 635 636
		}
		break;
	}

637
	vcap_key_set(vcap, &data, VCAP_IS2_TYPE, type, type_mask);
638
	is2_action_set(ocelot, &data, filter);
639
	vcap_data_set(data.counter, data.counter_offset,
640
		      vcap->counter_width, filter->stats.pkts);
641 642

	/* Write row */
643 644 645
	vcap_entry2cache(ocelot, vcap, &data);
	vcap_action2cache(ocelot, vcap, &data);
	vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_WRITE, VCAP_SEL_ALL);
646 647
}

648 649
static void
vcap_entry_get(struct ocelot *ocelot, struct ocelot_vcap_filter *filter, int ix)
650
{
651
	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
652
	struct vcap_data data;
653
	int row, count;
654 655 656
	u32 cnt;

	data.tg_sw = VCAP_TG_HALF;
657 658 659 660 661
	count = (1 << (data.tg_sw - 1));
	row = (ix / count);
	vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_READ, VCAP_SEL_COUNTER);
	vcap_cache2action(ocelot, vcap, &data);
	vcap_data_offset_get(vcap, &data, ix);
662
	cnt = vcap_data_get(data.counter, data.counter_offset,
663
			    vcap->counter_width);
664

665
	filter->stats.pkts = cnt;
666 667
}

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
static int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
				   struct ocelot_policer *pol)
{
	struct qos_policer_conf pp = { 0 };

	if (!pol)
		return -EINVAL;

	pp.mode = MSCC_QOS_RATE_MODE_DATA;
	pp.pir = pol->rate;
	pp.pbs = pol->burst;

	return qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
}

static void ocelot_vcap_policer_del(struct ocelot *ocelot,
				    struct ocelot_vcap_block *block,
				    u32 pol_ix)
{
	struct ocelot_vcap_filter *filter;
	struct qos_policer_conf pp = {0};
	int index = -1;

	if (pol_ix < block->pol_lpr)
		return;

	list_for_each_entry(filter, &block->rules, list) {
		index++;
		if (filter->action == OCELOT_VCAP_ACTION_POLICE &&
		    filter->pol_ix < pol_ix) {
			filter->pol_ix += 1;
			ocelot_vcap_policer_add(ocelot, filter->pol_ix,
						&filter->pol);
			is2_entry_set(ocelot, index, filter);
		}
	}

	pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
	qos_policer_conf_set(ocelot, 0, pol_ix, &pp);

	block->pol_lpr++;
}

711 712 713
static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot,
					    struct ocelot_vcap_block *block,
					    struct ocelot_vcap_filter *filter)
714
{
715
	struct ocelot_vcap_filter *tmp;
716 717
	struct list_head *pos, *n;

718
	if (filter->action == OCELOT_VCAP_ACTION_POLICE) {
719
		block->pol_lpr--;
720 721
		filter->pol_ix = block->pol_lpr;
		ocelot_vcap_policer_add(ocelot, filter->pol_ix, &filter->pol);
722 723
	}

724 725 726
	block->count++;

	if (list_empty(&block->rules)) {
727
		list_add(&filter->list, &block->rules);
728 729 730 731
		return;
	}

	list_for_each_safe(pos, n, &block->rules) {
732 733
		tmp = list_entry(pos, struct ocelot_vcap_filter, list);
		if (filter->prio < tmp->prio)
734 735
			break;
	}
736
	list_add(&filter->list, pos->prev);
737 738
}

739 740
static int ocelot_vcap_block_get_filter_index(struct ocelot_vcap_block *block,
					      struct ocelot_vcap_filter *filter)
741
{
742
	struct ocelot_vcap_filter *tmp;
743
	int index = 0;
744 745

	list_for_each_entry(tmp, &block->rules, list) {
746
		if (filter->id == tmp->id)
747 748
			return index;
		index++;
749
	}
750 751

	return -ENOENT;
752 753
}

754 755 756
static struct ocelot_vcap_filter*
ocelot_vcap_block_find_filter(struct ocelot_vcap_block *block,
			      int index)
757
{
758
	struct ocelot_vcap_filter *tmp;
759 760 761 762 763 764 765 766 767 768 769
	int i = 0;

	list_for_each_entry(tmp, &block->rules, list) {
		if (i == index)
			return tmp;
		++i;
	}

	return NULL;
}

770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
/* If @on=false, then SNAP, ARP, IP and OAM frames will not match on keys based
 * on destination and source MAC addresses, but only on higher-level protocol
 * information. The only frame types to match on keys containing MAC addresses
 * in this case are non-SNAP, non-ARP, non-IP and non-OAM frames.
 *
 * If @on=true, then the above frame types (SNAP, ARP, IP and OAM) will match
 * on MAC_ETYPE keys such as destination and source MAC on this ingress port.
 * However the setting has the side effect of making these frames not matching
 * on any _other_ keys than MAC_ETYPE ones.
 */
static void ocelot_match_all_as_mac_etype(struct ocelot *ocelot, int port,
					  bool on)
{
	u32 val = 0;

	if (on)
		val = ANA_PORT_VCAP_S2_CFG_S2_SNAP_DIS(3) |
		      ANA_PORT_VCAP_S2_CFG_S2_ARP_DIS(3) |
		      ANA_PORT_VCAP_S2_CFG_S2_IP_TCPUDP_DIS(3) |
		      ANA_PORT_VCAP_S2_CFG_S2_IP_OTHER_DIS(3) |
		      ANA_PORT_VCAP_S2_CFG_S2_OAM_DIS(3);

	ocelot_rmw_gix(ocelot, val,
		       ANA_PORT_VCAP_S2_CFG_S2_SNAP_DIS_M |
		       ANA_PORT_VCAP_S2_CFG_S2_ARP_DIS_M |
		       ANA_PORT_VCAP_S2_CFG_S2_IP_TCPUDP_DIS_M |
		       ANA_PORT_VCAP_S2_CFG_S2_IP_OTHER_DIS_M |
		       ANA_PORT_VCAP_S2_CFG_S2_OAM_DIS_M,
		       ANA_PORT_VCAP_S2_CFG, port);
}

801 802
static bool
ocelot_vcap_is_problematic_mac_etype(struct ocelot_vcap_filter *filter)
803
{
804 805
	u16 proto, mask;

806
	if (filter->key_type != OCELOT_VCAP_KEY_ETYPE)
807
		return false;
808

809 810
	proto = ntohs(*(__be16 *)filter->key.etype.etype.value);
	mask = ntohs(*(__be16 *)filter->key.etype.etype.mask);
811 812 813

	/* ETH_P_ALL match, so all protocols below are included */
	if (mask == 0)
814
		return true;
815
	if (proto == ETH_P_ARP)
816
		return true;
817 818 819 820 821
	if (proto == ETH_P_IP)
		return true;
	if (proto == ETH_P_IPV6)
		return true;

822 823 824
	return false;
}

825 826
static bool
ocelot_vcap_is_problematic_non_mac_etype(struct ocelot_vcap_filter *filter)
827
{
828
	if (filter->key_type == OCELOT_VCAP_KEY_SNAP)
829
		return true;
830
	if (filter->key_type == OCELOT_VCAP_KEY_ARP)
831
		return true;
832
	if (filter->key_type == OCELOT_VCAP_KEY_IPV4)
833
		return true;
834
	if (filter->key_type == OCELOT_VCAP_KEY_IPV6)
835 836 837 838
		return true;
	return false;
}

839 840 841
static bool
ocelot_exclusive_mac_etype_filter_rules(struct ocelot *ocelot,
					struct ocelot_vcap_filter *filter)
842
{
843 844
	struct ocelot_vcap_block *block = &ocelot->block;
	struct ocelot_vcap_filter *tmp;
845 846 847
	unsigned long port;
	int i;

848
	if (ocelot_vcap_is_problematic_mac_etype(filter)) {
849 850
		/* Search for any non-MAC_ETYPE rules on the port */
		for (i = 0; i < block->count; i++) {
851 852 853
			tmp = ocelot_vcap_block_find_filter(block, i);
			if (tmp->ingress_port_mask & filter->ingress_port_mask &&
			    ocelot_vcap_is_problematic_non_mac_etype(tmp))
854 855 856
				return false;
		}

857
		for_each_set_bit(port, &filter->ingress_port_mask,
858 859
				 ocelot->num_phys_ports)
			ocelot_match_all_as_mac_etype(ocelot, port, true);
860
	} else if (ocelot_vcap_is_problematic_non_mac_etype(filter)) {
861 862
		/* Search for any MAC_ETYPE rules on the port */
		for (i = 0; i < block->count; i++) {
863 864 865
			tmp = ocelot_vcap_block_find_filter(block, i);
			if (tmp->ingress_port_mask & filter->ingress_port_mask &&
			    ocelot_vcap_is_problematic_mac_etype(tmp))
866 867 868
				return false;
		}

869
		for_each_set_bit(port, &filter->ingress_port_mask,
870 871 872 873 874 875 876
				 ocelot->num_phys_ports)
			ocelot_match_all_as_mac_etype(ocelot, port, false);
	}

	return true;
}

877 878 879
int ocelot_vcap_filter_add(struct ocelot *ocelot,
			   struct ocelot_vcap_filter *filter,
			   struct netlink_ext_ack *extack)
880
{
881
	struct ocelot_vcap_block *block = &ocelot->block;
882 883
	int i, index;

884
	if (!ocelot_exclusive_mac_etype_filter_rules(ocelot, filter)) {
885 886 887 888 889
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot mix MAC_ETYPE with non-MAC_ETYPE rules");
		return -EBUSY;
	}

890 891
	/* Add filter to the linked list */
	ocelot_vcap_filter_add_to_block(ocelot, block, filter);
892

893 894
	/* Get the index of the inserted filter */
	index = ocelot_vcap_block_get_filter_index(block, filter);
895 896
	if (index < 0)
		return index;
897

898
	/* Move down the rules to make place for the new filter */
899
	for (i = block->count - 1; i > index; i--) {
900 901 902 903
		struct ocelot_vcap_filter *tmp;

		tmp = ocelot_vcap_block_find_filter(block, i);
		is2_entry_set(ocelot, i, tmp);
904 905
	}

906 907
	/* Now insert the new filter */
	is2_entry_set(ocelot, index, filter);
908 909 910
	return 0;
}

911 912 913
static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot,
					    struct ocelot_vcap_block *block,
					    struct ocelot_vcap_filter *filter)
914
{
915
	struct ocelot_vcap_filter *tmp;
916 917 918
	struct list_head *pos, *q;

	list_for_each_safe(pos, q, &block->rules) {
919 920 921
		tmp = list_entry(pos, struct ocelot_vcap_filter, list);
		if (tmp->id == filter->id) {
			if (tmp->action == OCELOT_VCAP_ACTION_POLICE)
922 923
				ocelot_vcap_policer_del(ocelot, block,
							tmp->pol_ix);
924

925 926 927 928 929 930 931 932
			list_del(pos);
			kfree(tmp);
		}
	}

	block->count--;
}

933 934
int ocelot_vcap_filter_del(struct ocelot *ocelot,
			   struct ocelot_vcap_filter *filter)
935
{
936 937
	struct ocelot_vcap_block *block = &ocelot->block;
	struct ocelot_vcap_filter del_filter;
938 939
	int i, index;

940
	memset(&del_filter, 0, sizeof(del_filter));
941

942 943
	/* Gets index of the filter */
	index = ocelot_vcap_block_get_filter_index(block, filter);
944 945
	if (index < 0)
		return index;
946

947 948
	/* Delete filter */
	ocelot_vcap_block_remove_filter(ocelot, block, filter);
949

950
	/* Move up all the blocks over the deleted filter */
951
	for (i = index; i < block->count; i++) {
952 953 954 955
		struct ocelot_vcap_filter *tmp;

		tmp = ocelot_vcap_block_find_filter(block, i);
		is2_entry_set(ocelot, i, tmp);
956 957
	}

958 959
	/* Now delete the last filter, because it is duplicated */
	is2_entry_set(ocelot, block->count, &del_filter);
960 961 962 963

	return 0;
}

964 965
int ocelot_vcap_filter_stats_update(struct ocelot *ocelot,
				    struct ocelot_vcap_filter *filter)
966
{
967 968
	struct ocelot_vcap_block *block = &ocelot->block;
	struct ocelot_vcap_filter *tmp;
969 970
	int index;

971
	index = ocelot_vcap_block_get_filter_index(block, filter);
972 973 974
	if (index < 0)
		return index;

975
	vcap_entry_get(ocelot, filter, index);
976 977

	/* After we get the result we need to clear the counters */
978
	tmp = ocelot_vcap_block_find_filter(block, index);
979
	tmp->stats.pkts = 0;
980
	is2_entry_set(ocelot, index, tmp);
981 982 983 984

	return 0;
}

985 986
static void ocelot_vcap_init_one(struct ocelot *ocelot,
				 const struct vcap_props *vcap)
987
{
988
	struct vcap_data data;
989

990
	memset(&data, 0, sizeof(data));
991

992 993 994 995
	vcap_entry2cache(ocelot, vcap, &data);
	ocelot_target_write(ocelot, vcap->target, vcap->entry_count,
			    VCAP_CORE_MV_CFG);
	vcap_cmd(ocelot, vcap, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY);
996

997 998 999 1000
	vcap_action2cache(ocelot, vcap, &data);
	ocelot_target_write(ocelot, vcap->target, vcap->action_count,
			    VCAP_CORE_MV_CFG);
	vcap_cmd(ocelot, vcap, 0, VCAP_CMD_INITIALIZE,
1001
		 VCAP_SEL_ACTION | VCAP_SEL_COUNTER);
1002 1003 1004 1005 1006 1007 1008
}

int ocelot_vcap_init(struct ocelot *ocelot)
{
	struct ocelot_vcap_block *block = &ocelot->block;

	ocelot_vcap_init_one(ocelot, &ocelot->vcap[VCAP_IS2]);
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024

	/* Create a policer that will drop the frames for the cpu.
	 * This policer will be used as action in the acl rules to drop
	 * frames.
	 */
	ocelot_write_gix(ocelot, 0x299, ANA_POL_MODE_CFG,
			 OCELOT_POLICER_DISCARD);
	ocelot_write_gix(ocelot, 0x1, ANA_POL_PIR_CFG,
			 OCELOT_POLICER_DISCARD);
	ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_PIR_STATE,
			 OCELOT_POLICER_DISCARD);
	ocelot_write_gix(ocelot, 0x0, ANA_POL_CIR_CFG,
			 OCELOT_POLICER_DISCARD);
	ocelot_write_gix(ocelot, 0x3fffff, ANA_POL_CIR_STATE,
			 OCELOT_POLICER_DISCARD);

1025 1026
	block->pol_lpr = OCELOT_POLICER_DISCARD - 1;

1027
	INIT_LIST_HEAD(&block->rules);
1028 1029 1030

	return 0;
}