ocelot_vcap.c 32.7 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 182 183 184 185 186 187 188 189 190 191 192 193 194
	switch (data->tg_sw) {
	case VCAP_TG_FULL:
		count = 1;
		break;
	case VCAP_TG_HALF:
		count = 2;
		break;
	case VCAP_TG_QUARTER:
		count = 4;
		break;
	default:
		return;
	}

	col = (ix % count);
195 196
	cnt = (vcap->sw_count / count);
	base = (vcap->sw_count - col * cnt - cnt);
197 198 199 200 201 202 203 204 205 206
	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);
207 208
	data->key_offset = (base * vcap->entry_width) / vcap->sw_count;
	data->counter_offset = (cnt * col * vcap->counter_width);
209
	i = data->type;
210 211 212 213
	width = vcap->action_table[i].width;
	cnt = vcap->action_table[i].count;
	data->action_offset = (((cnt * col * width) / count) +
			      vcap->action_type_width);
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243
}

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;
}

244 245
static void vcap_key_field_set(struct vcap_data *data, u32 offset, u32 width,
			       u32 value, u32 mask)
246 247 248 249 250
{
	vcap_data_set(data->entry, offset + data->key_offset, width, value);
	vcap_data_set(data->mask, offset + data->key_offset, width, mask);
}

251 252
static void vcap_key_set(const struct vcap_props *vcap, struct vcap_data *data,
			 int field, u32 value, u32 mask)
253
{
254 255
	u32 offset = vcap->keys[field].offset;
	u32 length = vcap->keys[field].length;
256 257 258 259

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

260 261
static void vcap_key_bytes_set(const struct vcap_props *vcap,
			       struct vcap_data *data, int field,
262
			       u8 *val, u8 *msk)
263
{
264 265
	u32 offset = vcap->keys[field].offset;
	u32 count  = vcap->keys[field].length;
266 267
	u32 i, j, n = 0, value = 0, mask = 0;

268 269
	WARN_ON(count % 8);

270 271 272
	/* 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.
	 */
273 274 275
	offset += count;
	count /= 8;

276 277 278 279 280 281 282
	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;
283
			vcap_key_field_set(data, offset, n, value, mask);
284 285 286 287 288 289 290
			n = 0;
			value = 0;
			mask = 0;
		}
	}
}

291 292
static void vcap_key_l4_port_set(const struct vcap_props *vcap,
				 struct vcap_data *data, int field,
293 294
				 struct ocelot_vcap_udp_tcp *port)
{
295 296
	u32 offset = vcap->keys[field].offset;
	u32 length = vcap->keys[field].length;
297 298 299 300

	WARN_ON(length != 16);

	vcap_key_field_set(data, offset, length, port->value, port->mask);
301 302
}

303 304
static void vcap_key_bit_set(const struct vcap_props *vcap,
			     struct vcap_data *data, int field,
305 306
			     enum ocelot_vcap_bit val)
{
307 308
	u32 value = (val == OCELOT_VCAP_BIT_1 ? 1 : 0);
	u32 msk = (val == OCELOT_VCAP_BIT_ANY ? 0 : 1);
309 310
	u32 offset = vcap->keys[field].offset;
	u32 length = vcap->keys[field].length;
311

312
	WARN_ON(length != 1);
313

314
	vcap_key_field_set(data, offset, length, value, msk);
315 316
}

317 318
static void vcap_action_set(const struct vcap_props *vcap,
			    struct vcap_data *data, int field, u32 value)
319
{
320 321
	int offset = vcap->actions[field].offset;
	int length = vcap->actions[field].length;
322 323 324 325

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

327
static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data,
328
			   struct ocelot_vcap_filter *filter)
329
{
330 331
	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];

332 333
	switch (filter->action) {
	case OCELOT_VCAP_ACTION_DROP:
334 335 336 337
		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,
338
				OCELOT_POLICER_DISCARD);
339 340
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
341
		break;
342
	case OCELOT_VCAP_ACTION_TRAP:
343 344 345 346 347 348
		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);
349
		break;
350
	case OCELOT_VCAP_ACTION_POLICE:
351 352 353 354
		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,
355
				filter->pol_ix);
356 357
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_QU_NUM, 0);
		vcap_action_set(vcap, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0);
358
		break;
359 360 361 362
	}
}

static void is2_entry_set(struct ocelot *ocelot, int ix,
363
			  struct ocelot_vcap_filter *filter)
364
{
365
	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
366
	struct ocelot_vcap_key_vlan *tag = &filter->vlan;
367
	u32 val, msk, type, type_mask = 0xf, i, count;
368 369
	struct ocelot_vcap_u64 payload;
	struct vcap_data data;
370 371
	int row = (ix / 2);

372 373 374
	memset(&payload, 0, sizeof(payload));
	memset(&data, 0, sizeof(data));

375
	/* Read row */
376 377 378
	vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_READ, VCAP_SEL_ALL);
	vcap_cache2entry(ocelot, vcap, &data);
	vcap_cache2action(ocelot, vcap, &data);
379 380

	data.tg_sw = VCAP_TG_HALF;
381
	vcap_data_offset_get(vcap, &data, ix);
382
	data.tg = (data.tg & ~data.tg_mask);
383
	if (filter->prio != 0)
384 385 386 387
		data.tg |= data.tg_value;

	data.type = IS2_ACTION_TYPE_NORMAL;

388 389
	vcap_key_set(vcap, &data, VCAP_IS2_HK_PAG, 0, 0);
	vcap_key_set(vcap, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0,
390
		     ~filter->ingress_port_mask);
391 392
	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,
393
			 OCELOT_VCAP_BIT_ANY);
394 395 396 397
	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,
398
		     tag->vid.value, tag->vid.mask);
399
	vcap_key_set(vcap, &data, VCAP_IS2_HK_PCP,
400
		     tag->pcp.value[0], tag->pcp.mask[0]);
401
	vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_DEI, tag->dei);
402

403 404 405
	switch (filter->key_type) {
	case OCELOT_VCAP_KEY_ETYPE: {
		struct ocelot_vcap_key_etype *etype = &filter->key.etype;
406 407

		type = IS2_TYPE_ETYPE;
408
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_DMAC,
409
				   etype->dmac.value, etype->dmac.mask);
410
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_SMAC,
411
				   etype->smac.value, etype->smac.mask);
412
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_ETYPE,
413 414
				   etype->etype.value, etype->etype.mask);
		/* Clear unused bits */
415
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0,
416
			     0, 0);
417
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1,
418
			     0, 0);
419
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2,
420
			     0, 0);
421
		vcap_key_bytes_set(vcap, &data,
422 423
				   VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0,
				   etype->data.value, etype->data.mask);
424 425
		break;
	}
426 427
	case OCELOT_VCAP_KEY_LLC: {
		struct ocelot_vcap_key_llc *llc = &filter->key.llc;
428 429

		type = IS2_TYPE_LLC;
430
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_DMAC,
431
				   llc->dmac.value, llc->dmac.mask);
432
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_SMAC,
433
				   llc->smac.value, llc->smac.mask);
434 435 436 437
		for (i = 0; i < 4; i++) {
			payload.value[i] = llc->llc.value[i];
			payload.mask[i] = llc->llc.mask[i];
		}
438
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_LLC_L2_LLC,
439
				   payload.value, payload.mask);
440 441
		break;
	}
442 443
	case OCELOT_VCAP_KEY_SNAP: {
		struct ocelot_vcap_key_snap *snap = &filter->key.snap;
444 445

		type = IS2_TYPE_SNAP;
446
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_DMAC,
447
				   snap->dmac.value, snap->dmac.mask);
448
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L2_SMAC,
449
				   snap->smac.value, snap->smac.mask);
450
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_SNAP_L2_SNAP,
451 452
				   filter->key.snap.snap.value,
				   filter->key.snap.snap.mask);
453 454
		break;
	}
455 456
	case OCELOT_VCAP_KEY_ARP: {
		struct ocelot_vcap_key_arp *arp = &filter->key.arp;
457 458

		type = IS2_TYPE_ARP;
459
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_MAC_ARP_SMAC,
460
				   arp->smac.value, arp->smac.mask);
461
		vcap_key_bit_set(vcap, &data,
462 463
				 VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK,
				 arp->ethernet);
464
		vcap_key_bit_set(vcap, &data,
465 466
				 VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK,
				 arp->ip);
467
		vcap_key_bit_set(vcap, &data,
468 469
				 VCAP_IS2_HK_MAC_ARP_LEN_OK,
				 arp->length);
470
		vcap_key_bit_set(vcap, &data,
471 472
				 VCAP_IS2_HK_MAC_ARP_TARGET_MATCH,
				 arp->dmac_match);
473
		vcap_key_bit_set(vcap, &data,
474 475
				 VCAP_IS2_HK_MAC_ARP_SENDER_MATCH,
				 arp->smac_match);
476
		vcap_key_bit_set(vcap, &data,
477 478
				 VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN,
				 arp->unknown);
479 480 481 482 483 484

		/* 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));
485
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ARP_OPCODE,
486
			     val, msk);
487
		vcap_key_bytes_set(vcap, &data,
488 489
				   VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP,
				   arp->dip.value.addr, arp->dip.mask.addr);
490
		vcap_key_bytes_set(vcap, &data,
491 492
				   VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP,
				   arp->sip.value.addr, arp->sip.mask.addr);
493
		vcap_key_set(vcap, &data, VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP,
494
			     0, 0);
495 496
		break;
	}
497 498
	case OCELOT_VCAP_KEY_IPV4:
	case OCELOT_VCAP_KEY_IPV6: {
499 500 501
		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;
502 503
		struct ocelot_vcap_key_ipv4 *ipv4 = NULL;
		struct ocelot_vcap_key_ipv6 *ipv6 = NULL;
504 505 506 507 508
		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;

509 510
		if (filter->key_type == OCELOT_VCAP_KEY_IPV4) {
			ipv4 = &filter->key.ipv4;
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
			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 {
531
			ipv6 = &filter->key.ipv6;
532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
			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;
		}

562
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_IP4,
563
				 ipv4 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0);
564
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L3_FRAGMENT,
565
				 fragment);
566 567
		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,
568
				 options);
569
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_IP4_L3_TTL_GT0,
570
				 ttl);
571
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L3_TOS,
572
				   ds.value, ds.mask);
573
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L3_IP4_DIP,
574
				   dip.value.addr, dip.mask.addr);
575
		vcap_key_bytes_set(vcap, &data, VCAP_IS2_HK_L3_IP4_SIP,
576
				   sip.value.addr, sip.mask.addr);
577
		vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_DIP_EQ_SIP,
578
				 sip_eq_dip);
579 580 581 582 583 584 585
		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);
586 587
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_TCP, tcp);
			vcap_key_l4_port_set(vcap, &data,
588
					     VCAP_IS2_HK_L4_DPORT, dport);
589
			vcap_key_l4_port_set(vcap, &data,
590
					     VCAP_IS2_HK_L4_SPORT, sport);
591 592
			vcap_key_set(vcap, &data, VCAP_IS2_HK_L4_RNG, 0, 0);
			vcap_key_bit_set(vcap, &data,
593
					 VCAP_IS2_HK_L4_SPORT_EQ_DPORT,
594
					 sport_eq_dport);
595
			vcap_key_bit_set(vcap, &data,
596 597
					 VCAP_IS2_HK_L4_SEQUENCE_EQ0,
					 seq_zero);
598
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_FIN,
599
					 tcp_fin);
600
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_SYN,
601
					 tcp_syn);
602
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_RST,
603
					 tcp_rst);
604
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_PSH,
605
					 tcp_psh);
606
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_ACK,
607
					 tcp_ack);
608
			vcap_key_bit_set(vcap, &data, VCAP_IS2_HK_L4_URG,
609
					 tcp_urg);
610
			vcap_key_set(vcap, &data, VCAP_IS2_HK_L4_1588_DOM,
611
				     0, 0);
612
			vcap_key_set(vcap, &data, VCAP_IS2_HK_L4_1588_VER,
613
				     0, 0);
614 615 616 617 618 619 620 621 622 623 624 625
		} 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];
				}
			}
626
			vcap_key_bytes_set(vcap, &data,
627 628
					   VCAP_IS2_HK_IP4_L3_PROTO,
					   proto.value, proto.mask);
629
			vcap_key_bytes_set(vcap, &data,
630 631
					   VCAP_IS2_HK_L3_PAYLOAD,
					   payload.value, payload.mask);
632 633 634
		}
		break;
	}
635
	case OCELOT_VCAP_KEY_ANY:
636 637 638
	default:
		type = 0;
		type_mask = 0;
639
		count = vcap->entry_width / 2;
640 641 642
		/* Iterate over the non-common part of the key and
		 * clear entry data
		 */
643
		for (i = vcap->keys[VCAP_IS2_HK_L2_DMAC].offset;
644 645
		     i < count; i += ENTRY_WIDTH) {
			vcap_key_field_set(&data, i, min(32u, count - i), 0, 0);
646 647 648 649
		}
		break;
	}

650
	vcap_key_set(vcap, &data, VCAP_IS2_TYPE, type, type_mask);
651
	is2_action_set(ocelot, &data, filter);
652
	vcap_data_set(data.counter, data.counter_offset,
653
		      vcap->counter_width, filter->stats.pkts);
654 655

	/* Write row */
656 657 658
	vcap_entry2cache(ocelot, vcap, &data);
	vcap_action2cache(ocelot, vcap, &data);
	vcap_row_cmd(ocelot, vcap, row, VCAP_CMD_WRITE, VCAP_SEL_ALL);
659 660
}

661 662
static void
vcap_entry_get(struct ocelot *ocelot, struct ocelot_vcap_filter *filter, int ix)
663
{
664
	const struct vcap_props *vcap = &ocelot->vcap[VCAP_IS2];
665
	struct vcap_data data;
666
	int row, count;
667 668 669
	u32 cnt;

	data.tg_sw = VCAP_TG_HALF;
670 671 672 673 674
	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);
675
	cnt = vcap_data_get(data.counter, data.counter_offset,
676
			    vcap->counter_width);
677

678
	filter->stats.pkts = cnt;
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 711 712 713 714 715 716 717 718 719 720 721 722 723
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++;
}

724 725 726
static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot,
					    struct ocelot_vcap_block *block,
					    struct ocelot_vcap_filter *filter)
727
{
728
	struct ocelot_vcap_filter *tmp;
729 730
	struct list_head *pos, *n;

731
	if (filter->action == OCELOT_VCAP_ACTION_POLICE) {
732
		block->pol_lpr--;
733 734
		filter->pol_ix = block->pol_lpr;
		ocelot_vcap_policer_add(ocelot, filter->pol_ix, &filter->pol);
735 736
	}

737 738 739
	block->count++;

	if (list_empty(&block->rules)) {
740
		list_add(&filter->list, &block->rules);
741 742 743 744
		return;
	}

	list_for_each_safe(pos, n, &block->rules) {
745 746
		tmp = list_entry(pos, struct ocelot_vcap_filter, list);
		if (filter->prio < tmp->prio)
747 748
			break;
	}
749
	list_add(&filter->list, pos->prev);
750 751
}

752 753
static int ocelot_vcap_block_get_filter_index(struct ocelot_vcap_block *block,
					      struct ocelot_vcap_filter *filter)
754
{
755
	struct ocelot_vcap_filter *tmp;
756
	int index = 0;
757 758

	list_for_each_entry(tmp, &block->rules, list) {
759
		if (filter->id == tmp->id)
760 761
			return index;
		index++;
762
	}
763 764

	return -ENOENT;
765 766
}

767 768 769
static struct ocelot_vcap_filter*
ocelot_vcap_block_find_filter(struct ocelot_vcap_block *block,
			      int index)
770
{
771
	struct ocelot_vcap_filter *tmp;
772 773 774 775 776 777 778 779 780 781 782
	int i = 0;

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

	return NULL;
}

783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
/* 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);
}

814 815
static bool
ocelot_vcap_is_problematic_mac_etype(struct ocelot_vcap_filter *filter)
816
{
817 818
	u16 proto, mask;

819
	if (filter->key_type != OCELOT_VCAP_KEY_ETYPE)
820
		return false;
821

822 823
	proto = ntohs(*(__be16 *)filter->key.etype.etype.value);
	mask = ntohs(*(__be16 *)filter->key.etype.etype.mask);
824 825 826

	/* ETH_P_ALL match, so all protocols below are included */
	if (mask == 0)
827
		return true;
828
	if (proto == ETH_P_ARP)
829
		return true;
830 831 832 833 834
	if (proto == ETH_P_IP)
		return true;
	if (proto == ETH_P_IPV6)
		return true;

835 836 837
	return false;
}

838 839
static bool
ocelot_vcap_is_problematic_non_mac_etype(struct ocelot_vcap_filter *filter)
840
{
841
	if (filter->key_type == OCELOT_VCAP_KEY_SNAP)
842
		return true;
843
	if (filter->key_type == OCELOT_VCAP_KEY_ARP)
844
		return true;
845
	if (filter->key_type == OCELOT_VCAP_KEY_IPV4)
846
		return true;
847
	if (filter->key_type == OCELOT_VCAP_KEY_IPV6)
848 849 850 851
		return true;
	return false;
}

852 853 854
static bool
ocelot_exclusive_mac_etype_filter_rules(struct ocelot *ocelot,
					struct ocelot_vcap_filter *filter)
855
{
856 857
	struct ocelot_vcap_block *block = &ocelot->block;
	struct ocelot_vcap_filter *tmp;
858 859 860
	unsigned long port;
	int i;

861
	if (ocelot_vcap_is_problematic_mac_etype(filter)) {
862 863
		/* Search for any non-MAC_ETYPE rules on the port */
		for (i = 0; i < block->count; i++) {
864 865 866
			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))
867 868 869
				return false;
		}

870
		for_each_set_bit(port, &filter->ingress_port_mask,
871 872
				 ocelot->num_phys_ports)
			ocelot_match_all_as_mac_etype(ocelot, port, true);
873
	} else if (ocelot_vcap_is_problematic_non_mac_etype(filter)) {
874 875
		/* Search for any MAC_ETYPE rules on the port */
		for (i = 0; i < block->count; i++) {
876 877 878
			tmp = ocelot_vcap_block_find_filter(block, i);
			if (tmp->ingress_port_mask & filter->ingress_port_mask &&
			    ocelot_vcap_is_problematic_mac_etype(tmp))
879 880 881
				return false;
		}

882
		for_each_set_bit(port, &filter->ingress_port_mask,
883 884 885 886 887 888 889
				 ocelot->num_phys_ports)
			ocelot_match_all_as_mac_etype(ocelot, port, false);
	}

	return true;
}

890 891 892
int ocelot_vcap_filter_add(struct ocelot *ocelot,
			   struct ocelot_vcap_filter *filter,
			   struct netlink_ext_ack *extack)
893
{
894
	struct ocelot_vcap_block *block = &ocelot->block;
895 896
	int i, index;

897
	if (!ocelot_exclusive_mac_etype_filter_rules(ocelot, filter)) {
898 899 900 901 902
		NL_SET_ERR_MSG_MOD(extack,
				   "Cannot mix MAC_ETYPE with non-MAC_ETYPE rules");
		return -EBUSY;
	}

903 904
	/* Add filter to the linked list */
	ocelot_vcap_filter_add_to_block(ocelot, block, filter);
905

906 907
	/* Get the index of the inserted filter */
	index = ocelot_vcap_block_get_filter_index(block, filter);
908 909
	if (index < 0)
		return index;
910

911
	/* Move down the rules to make place for the new filter */
912
	for (i = block->count - 1; i > index; i--) {
913 914 915 916
		struct ocelot_vcap_filter *tmp;

		tmp = ocelot_vcap_block_find_filter(block, i);
		is2_entry_set(ocelot, i, tmp);
917 918
	}

919 920
	/* Now insert the new filter */
	is2_entry_set(ocelot, index, filter);
921 922 923
	return 0;
}

924 925 926
static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot,
					    struct ocelot_vcap_block *block,
					    struct ocelot_vcap_filter *filter)
927
{
928
	struct ocelot_vcap_filter *tmp;
929 930 931
	struct list_head *pos, *q;

	list_for_each_safe(pos, q, &block->rules) {
932 933 934
		tmp = list_entry(pos, struct ocelot_vcap_filter, list);
		if (tmp->id == filter->id) {
			if (tmp->action == OCELOT_VCAP_ACTION_POLICE)
935 936
				ocelot_vcap_policer_del(ocelot, block,
							tmp->pol_ix);
937

938 939 940 941 942 943 944 945
			list_del(pos);
			kfree(tmp);
		}
	}

	block->count--;
}

946 947
int ocelot_vcap_filter_del(struct ocelot *ocelot,
			   struct ocelot_vcap_filter *filter)
948
{
949 950
	struct ocelot_vcap_block *block = &ocelot->block;
	struct ocelot_vcap_filter del_filter;
951 952
	int i, index;

953
	memset(&del_filter, 0, sizeof(del_filter));
954

955 956
	/* Gets index of the filter */
	index = ocelot_vcap_block_get_filter_index(block, filter);
957 958
	if (index < 0)
		return index;
959

960 961
	/* Delete filter */
	ocelot_vcap_block_remove_filter(ocelot, block, filter);
962

963
	/* Move up all the blocks over the deleted filter */
964
	for (i = index; i < block->count; i++) {
965 966 967 968
		struct ocelot_vcap_filter *tmp;

		tmp = ocelot_vcap_block_find_filter(block, i);
		is2_entry_set(ocelot, i, tmp);
969 970
	}

971 972
	/* Now delete the last filter, because it is duplicated */
	is2_entry_set(ocelot, block->count, &del_filter);
973 974 975 976

	return 0;
}

977 978
int ocelot_vcap_filter_stats_update(struct ocelot *ocelot,
				    struct ocelot_vcap_filter *filter)
979
{
980 981
	struct ocelot_vcap_block *block = &ocelot->block;
	struct ocelot_vcap_filter *tmp;
982 983
	int index;

984
	index = ocelot_vcap_block_get_filter_index(block, filter);
985 986 987
	if (index < 0)
		return index;

988
	vcap_entry_get(ocelot, filter, index);
989 990

	/* After we get the result we need to clear the counters */
991
	tmp = ocelot_vcap_block_find_filter(block, index);
992
	tmp->stats.pkts = 0;
993
	is2_entry_set(ocelot, index, tmp);
994 995 996 997

	return 0;
}

998 999
static void ocelot_vcap_init_one(struct ocelot *ocelot,
				 const struct vcap_props *vcap)
1000
{
1001
	struct vcap_data data;
1002

1003
	memset(&data, 0, sizeof(data));
1004

1005 1006 1007 1008
	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);
1009

1010 1011 1012 1013
	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,
1014
		 VCAP_SEL_ACTION | VCAP_SEL_COUNTER);
1015 1016
}

1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085
static void ocelot_vcap_detect_constants(struct ocelot *ocelot,
					 struct vcap_props *vcap)
{
	int counter_memory_width;
	int num_default_actions;
	int version;

	version = ocelot_target_read(ocelot, vcap->target,
				     VCAP_CONST_VCAP_VER);
	/* Only version 0 VCAP supported for now */
	if (WARN_ON(version != 0))
		return;

	/* Width in bits of type-group field */
	vcap->tg_width = ocelot_target_read(ocelot, vcap->target,
					    VCAP_CONST_ENTRY_TG_WIDTH);
	/* Number of subwords per TCAM row */
	vcap->sw_count = ocelot_target_read(ocelot, vcap->target,
					    VCAP_CONST_ENTRY_SWCNT);
	/* Number of rows in TCAM. There can be this many full keys, or double
	 * this number half keys, or 4 times this number quarter keys.
	 */
	vcap->entry_count = ocelot_target_read(ocelot, vcap->target,
					       VCAP_CONST_ENTRY_CNT);
	/* Assuming there are 4 subwords per TCAM row, their layout in the
	 * actual TCAM (not in the cache) would be:
	 *
	 * |  SW 3  | TG 3 |  SW 2  | TG 2 |  SW 1  | TG 1 |  SW 0  | TG 0 |
	 *
	 * (where SW=subword and TG=Type-Group).
	 *
	 * What VCAP_CONST_ENTRY_CNT is giving us is the width of one full TCAM
	 * row. But when software accesses the TCAM through the cache
	 * registers, the Type-Group values are written through another set of
	 * registers VCAP_TG_DAT, and therefore, it appears as though the 4
	 * subwords are contiguous in the cache memory.
	 * Important mention: regardless of the number of key entries per row
	 * (and therefore of key size: 1 full key or 2 half keys or 4 quarter
	 * keys), software always has to configure 4 Type-Group values. For
	 * example, in the case of 1 full key, the driver needs to set all 4
	 * Type-Group to be full key.
	 *
	 * For this reason, we need to fix up the value that the hardware is
	 * giving us. We don't actually care about the width of the entry in
	 * the TCAM. What we care about is the width of the entry in the cache
	 * registers, which is how we get to interact with it. And since the
	 * VCAP_ENTRY_DAT cache registers access only the subwords and not the
	 * Type-Groups, this means we need to subtract the width of the
	 * Type-Groups when packing and unpacking key entry data in a TCAM row.
	 */
	vcap->entry_width = ocelot_target_read(ocelot, vcap->target,
					       VCAP_CONST_ENTRY_WIDTH);
	vcap->entry_width -= vcap->tg_width * vcap->sw_count;
	num_default_actions = ocelot_target_read(ocelot, vcap->target,
						 VCAP_CONST_ACTION_DEF_CNT);
	vcap->action_count = vcap->entry_count + num_default_actions;
	vcap->action_width = ocelot_target_read(ocelot, vcap->target,
						VCAP_CONST_ACTION_WIDTH);
	/* The width of the counter memory, this is the complete width of all
	 * counter-fields associated with one full-word entry. There is one
	 * counter per entry sub-word (see CAP_CORE::ENTRY_SWCNT for number of
	 * subwords.)
	 */
	vcap->counter_words = vcap->sw_count;
	counter_memory_width = ocelot_target_read(ocelot, vcap->target,
						  VCAP_CONST_CNT_WIDTH);
	vcap->counter_width = counter_memory_width / vcap->counter_words;
}

1086 1087 1088
int ocelot_vcap_init(struct ocelot *ocelot)
{
	struct ocelot_vcap_block *block = &ocelot->block;
1089
	int i;
1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105

	/* 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);

1106 1107 1108 1109 1110 1111 1112
	for (i = 0; i < OCELOT_NUM_VCAP_BLOCKS; i++) {
		struct vcap_props *vcap = &ocelot->vcap[i];

		ocelot_vcap_detect_constants(ocelot, vcap);
		ocelot_vcap_init_one(ocelot, vcap);
	}

1113 1114
	block->pol_lpr = OCELOT_POLICER_DISCARD - 1;

1115
	INIT_LIST_HEAD(&block->rules);
1116 1117 1118

	return 0;
}