1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
3 * Copyright (c) 2019 Microsemi Corporation
6 #include <linux/iopoll.h>
7 #include <linux/proc_fs.h>
9 #include <soc/mscc/ocelot_vcap.h>
10 #include "ocelot_police.h"
11 #include "ocelot_vcap.h"
13 #define ENTRY_WIDTH 32
17 VCAP_SEL_ACTION
= 0x2,
18 VCAP_SEL_COUNTER
= 0x4,
23 VCAP_CMD_WRITE
= 0, /* Copy from Cache to TCAM */
24 VCAP_CMD_READ
= 1, /* Copy from TCAM to Cache */
25 VCAP_CMD_MOVE_UP
= 2, /* Move <count> up */
26 VCAP_CMD_MOVE_DOWN
= 3, /* Move <count> down */
27 VCAP_CMD_INITIALIZE
= 4, /* Write all (from cache) */
30 #define VCAP_ENTRY_WIDTH 12 /* Max entry width (32bit words) */
31 #define VCAP_COUNTER_WIDTH 4 /* Max counter width (32bit words) */
34 u32 entry
[VCAP_ENTRY_WIDTH
]; /* ENTRY_DAT */
35 u32 mask
[VCAP_ENTRY_WIDTH
]; /* MASK_DAT */
36 u32 action
[VCAP_ENTRY_WIDTH
]; /* ACTION_DAT */
37 u32 counter
[VCAP_COUNTER_WIDTH
]; /* CNT_DAT */
39 u32 type
; /* Action type */
40 u32 tg_sw
; /* Current type-group */
41 u32 cnt
; /* Current counter */
42 u32 key_offset
; /* Current entry offset */
43 u32 action_offset
; /* Current action offset */
44 u32 counter_offset
; /* Current counter offset */
45 u32 tg_value
; /* Current type-group value */
46 u32 tg_mask
; /* Current type-group mask */
49 static u32
vcap_read_update_ctrl(struct ocelot
*ocelot
,
50 const struct vcap_props
*vcap
)
52 return ocelot_target_read(ocelot
, vcap
->target
, VCAP_CORE_UPDATE_CTRL
);
55 static void vcap_cmd(struct ocelot
*ocelot
, const struct vcap_props
*vcap
,
56 u16 ix
, int cmd
, int sel
)
58 u32 value
= (VCAP_CORE_UPDATE_CTRL_UPDATE_CMD(cmd
) |
59 VCAP_CORE_UPDATE_CTRL_UPDATE_ADDR(ix
) |
60 VCAP_CORE_UPDATE_CTRL_UPDATE_SHOT
);
62 if ((sel
& VCAP_SEL_ENTRY
) && ix
>= vcap
->entry_count
)
65 if (!(sel
& VCAP_SEL_ENTRY
))
66 value
|= VCAP_CORE_UPDATE_CTRL_UPDATE_ENTRY_DIS
;
68 if (!(sel
& VCAP_SEL_ACTION
))
69 value
|= VCAP_CORE_UPDATE_CTRL_UPDATE_ACTION_DIS
;
71 if (!(sel
& VCAP_SEL_COUNTER
))
72 value
|= VCAP_CORE_UPDATE_CTRL_UPDATE_CNT_DIS
;
74 ocelot_target_write(ocelot
, vcap
->target
, value
, VCAP_CORE_UPDATE_CTRL
);
76 read_poll_timeout(vcap_read_update_ctrl
, value
,
77 (value
& VCAP_CORE_UPDATE_CTRL_UPDATE_SHOT
) == 0,
78 10, 100000, false, ocelot
, vcap
);
81 /* Convert from 0-based row to VCAP entry row and run command */
82 static void vcap_row_cmd(struct ocelot
*ocelot
, const struct vcap_props
*vcap
,
83 u32 row
, int cmd
, int sel
)
85 vcap_cmd(ocelot
, vcap
, vcap
->entry_count
- row
- 1, cmd
, sel
);
88 static void vcap_entry2cache(struct ocelot
*ocelot
,
89 const struct vcap_props
*vcap
,
90 struct vcap_data
*data
)
94 entry_words
= DIV_ROUND_UP(vcap
->entry_width
, ENTRY_WIDTH
);
96 for (i
= 0; i
< entry_words
; i
++) {
97 ocelot_target_write_rix(ocelot
, vcap
->target
, data
->entry
[i
],
98 VCAP_CACHE_ENTRY_DAT
, i
);
99 ocelot_target_write_rix(ocelot
, vcap
->target
, ~data
->mask
[i
],
100 VCAP_CACHE_MASK_DAT
, i
);
102 ocelot_target_write(ocelot
, vcap
->target
, data
->tg
, VCAP_CACHE_TG_DAT
);
105 static void vcap_cache2entry(struct ocelot
*ocelot
,
106 const struct vcap_props
*vcap
,
107 struct vcap_data
*data
)
111 entry_words
= DIV_ROUND_UP(vcap
->entry_width
, ENTRY_WIDTH
);
113 for (i
= 0; i
< entry_words
; i
++) {
114 data
->entry
[i
] = ocelot_target_read_rix(ocelot
, vcap
->target
,
115 VCAP_CACHE_ENTRY_DAT
, i
);
117 data
->mask
[i
] = ~ocelot_target_read_rix(ocelot
, vcap
->target
,
118 VCAP_CACHE_MASK_DAT
, i
);
120 data
->tg
= ocelot_target_read(ocelot
, vcap
->target
, VCAP_CACHE_TG_DAT
);
123 static void vcap_action2cache(struct ocelot
*ocelot
,
124 const struct vcap_props
*vcap
,
125 struct vcap_data
*data
)
127 u32 action_words
, mask
;
130 /* Encode action type */
131 width
= vcap
->action_type_width
;
133 mask
= GENMASK(width
, 0);
134 data
->action
[0] = ((data
->action
[0] & ~mask
) | data
->type
);
137 action_words
= DIV_ROUND_UP(vcap
->action_width
, ENTRY_WIDTH
);
139 for (i
= 0; i
< action_words
; i
++)
140 ocelot_target_write_rix(ocelot
, vcap
->target
, data
->action
[i
],
141 VCAP_CACHE_ACTION_DAT
, i
);
143 for (i
= 0; i
< vcap
->counter_words
; i
++)
144 ocelot_target_write_rix(ocelot
, vcap
->target
, data
->counter
[i
],
145 VCAP_CACHE_CNT_DAT
, i
);
148 static void vcap_cache2action(struct ocelot
*ocelot
,
149 const struct vcap_props
*vcap
,
150 struct vcap_data
*data
)
155 action_words
= DIV_ROUND_UP(vcap
->action_width
, ENTRY_WIDTH
);
157 for (i
= 0; i
< action_words
; i
++)
158 data
->action
[i
] = ocelot_target_read_rix(ocelot
, vcap
->target
,
159 VCAP_CACHE_ACTION_DAT
,
162 for (i
= 0; i
< vcap
->counter_words
; i
++)
163 data
->counter
[i
] = ocelot_target_read_rix(ocelot
, vcap
->target
,
167 /* Extract action type */
168 width
= vcap
->action_type_width
;
169 data
->type
= (width
? (data
->action
[0] & GENMASK(width
, 0)) : 0);
172 /* Calculate offsets for entry */
173 static void vcap_data_offset_get(const struct vcap_props
*vcap
,
174 struct vcap_data
*data
, int ix
)
176 int num_subwords_per_entry
, num_subwords_per_action
;
177 int i
, col
, offset
, num_entries_per_row
, base
;
178 u32 width
= vcap
->tg_width
;
180 switch (data
->tg_sw
) {
182 num_entries_per_row
= 1;
185 num_entries_per_row
= 2;
187 case VCAP_TG_QUARTER
:
188 num_entries_per_row
= 4;
194 col
= (ix
% num_entries_per_row
);
195 num_subwords_per_entry
= (vcap
->sw_count
/ num_entries_per_row
);
196 base
= (vcap
->sw_count
- col
* num_subwords_per_entry
-
197 num_subwords_per_entry
);
200 for (i
= 0; i
< num_subwords_per_entry
; i
++) {
201 offset
= ((base
+ i
) * width
);
202 data
->tg_value
|= (data
->tg_sw
<< offset
);
203 data
->tg_mask
|= GENMASK(offset
+ width
- 1, offset
);
206 /* Calculate key/action/counter offsets */
207 col
= (num_entries_per_row
- col
- 1);
208 data
->key_offset
= (base
* vcap
->entry_width
) / vcap
->sw_count
;
209 data
->counter_offset
= (num_subwords_per_entry
* col
*
210 vcap
->counter_width
);
212 width
= vcap
->action_table
[i
].width
;
213 num_subwords_per_action
= vcap
->action_table
[i
].count
;
214 data
->action_offset
= ((num_subwords_per_action
* col
* width
) /
215 num_entries_per_row
);
216 data
->action_offset
+= vcap
->action_type_width
;
219 static void vcap_data_set(u32
*data
, u32 offset
, u32 len
, u32 value
)
223 for (i
= 0; i
< len
; i
++, offset
++) {
224 v
= data
[offset
/ ENTRY_WIDTH
];
225 m
= (1 << (offset
% ENTRY_WIDTH
));
226 if (value
& (1 << i
))
230 data
[offset
/ ENTRY_WIDTH
] = v
;
234 static u32
vcap_data_get(u32
*data
, u32 offset
, u32 len
)
236 u32 i
, v
, m
, value
= 0;
238 for (i
= 0; i
< len
; i
++, offset
++) {
239 v
= data
[offset
/ ENTRY_WIDTH
];
240 m
= (1 << (offset
% ENTRY_WIDTH
));
247 static void vcap_key_field_set(struct vcap_data
*data
, u32 offset
, u32 width
,
250 vcap_data_set(data
->entry
, offset
+ data
->key_offset
, width
, value
);
251 vcap_data_set(data
->mask
, offset
+ data
->key_offset
, width
, mask
);
254 static void vcap_key_set(const struct vcap_props
*vcap
, struct vcap_data
*data
,
255 int field
, u32 value
, u32 mask
)
257 u32 offset
= vcap
->keys
[field
].offset
;
258 u32 length
= vcap
->keys
[field
].length
;
260 vcap_key_field_set(data
, offset
, length
, value
, mask
);
263 static void vcap_key_bytes_set(const struct vcap_props
*vcap
,
264 struct vcap_data
*data
, int field
,
267 u32 offset
= vcap
->keys
[field
].offset
;
268 u32 count
= vcap
->keys
[field
].length
;
269 u32 i
, j
, n
= 0, value
= 0, mask
= 0;
273 /* Data wider than 32 bits are split up in chunks of maximum 32 bits.
274 * The 32 LSB of the data are written to the 32 MSB of the TCAM.
279 for (i
= 0; i
< count
; i
++) {
281 value
+= (val
[j
] << n
);
282 mask
+= (msk
[j
] << n
);
284 if (n
== ENTRY_WIDTH
|| (i
+ 1) == count
) {
286 vcap_key_field_set(data
, offset
, n
, value
, mask
);
294 static void vcap_key_l4_port_set(const struct vcap_props
*vcap
,
295 struct vcap_data
*data
, int field
,
296 struct ocelot_vcap_udp_tcp
*port
)
298 u32 offset
= vcap
->keys
[field
].offset
;
299 u32 length
= vcap
->keys
[field
].length
;
301 WARN_ON(length
!= 16);
303 vcap_key_field_set(data
, offset
, length
, port
->value
, port
->mask
);
306 static void vcap_key_bit_set(const struct vcap_props
*vcap
,
307 struct vcap_data
*data
, int field
,
308 enum ocelot_vcap_bit val
)
310 u32 value
= (val
== OCELOT_VCAP_BIT_1
? 1 : 0);
311 u32 msk
= (val
== OCELOT_VCAP_BIT_ANY
? 0 : 1);
312 u32 offset
= vcap
->keys
[field
].offset
;
313 u32 length
= vcap
->keys
[field
].length
;
315 WARN_ON(length
!= 1);
317 vcap_key_field_set(data
, offset
, length
, value
, msk
);
320 static void vcap_action_set(const struct vcap_props
*vcap
,
321 struct vcap_data
*data
, int field
, u32 value
)
323 int offset
= vcap
->actions
[field
].offset
;
324 int length
= vcap
->actions
[field
].length
;
326 vcap_data_set(data
->action
, offset
+ data
->action_offset
, length
,
330 static void is2_action_set(struct ocelot
*ocelot
, struct vcap_data
*data
,
331 struct ocelot_vcap_filter
*filter
)
333 const struct vcap_props
*vcap
= &ocelot
->vcap
[VCAP_IS2
];
334 struct ocelot_vcap_action
*a
= &filter
->action
;
336 vcap_action_set(vcap
, data
, VCAP_IS2_ACT_MASK_MODE
, a
->mask_mode
);
337 vcap_action_set(vcap
, data
, VCAP_IS2_ACT_PORT_MASK
, a
->port_mask
);
338 vcap_action_set(vcap
, data
, VCAP_IS2_ACT_POLICE_ENA
, a
->police_ena
);
339 vcap_action_set(vcap
, data
, VCAP_IS2_ACT_POLICE_IDX
, a
->pol_ix
);
340 vcap_action_set(vcap
, data
, VCAP_IS2_ACT_CPU_QU_NUM
, a
->cpu_qu_num
);
341 vcap_action_set(vcap
, data
, VCAP_IS2_ACT_CPU_COPY_ENA
, a
->cpu_copy_ena
);
344 static void is2_entry_set(struct ocelot
*ocelot
, int ix
,
345 struct ocelot_vcap_filter
*filter
)
347 const struct vcap_props
*vcap
= &ocelot
->vcap
[VCAP_IS2
];
348 struct ocelot_vcap_key_vlan
*tag
= &filter
->vlan
;
349 u32 val
, msk
, type
, type_mask
= 0xf, i
, count
;
350 struct ocelot_vcap_u64 payload
;
351 struct vcap_data data
;
354 memset(&payload
, 0, sizeof(payload
));
355 memset(&data
, 0, sizeof(data
));
358 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_READ
, VCAP_SEL_ALL
);
359 vcap_cache2entry(ocelot
, vcap
, &data
);
360 vcap_cache2action(ocelot
, vcap
, &data
);
362 data
.tg_sw
= VCAP_TG_HALF
;
363 vcap_data_offset_get(vcap
, &data
, ix
);
364 data
.tg
= (data
.tg
& ~data
.tg_mask
);
365 if (filter
->prio
!= 0)
366 data
.tg
|= data
.tg_value
;
368 data
.type
= IS2_ACTION_TYPE_NORMAL
;
370 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_PAG
, filter
->pag
, 0xff);
371 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_FIRST
,
372 (filter
->lookup
== 0) ? OCELOT_VCAP_BIT_1
:
374 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_IGR_PORT_MASK
, 0,
375 ~filter
->ingress_port_mask
);
376 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_FIRST
, OCELOT_VCAP_BIT_ANY
);
377 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_HOST_MATCH
,
378 OCELOT_VCAP_BIT_ANY
);
379 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L2_MC
, filter
->dmac_mc
);
380 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L2_BC
, filter
->dmac_bc
);
381 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_VLAN_TAGGED
, tag
->tagged
);
382 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_VID
,
383 tag
->vid
.value
, tag
->vid
.mask
);
384 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_PCP
,
385 tag
->pcp
.value
[0], tag
->pcp
.mask
[0]);
386 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_DEI
, tag
->dei
);
388 switch (filter
->key_type
) {
389 case OCELOT_VCAP_KEY_ETYPE
: {
390 struct ocelot_vcap_key_etype
*etype
= &filter
->key
.etype
;
392 type
= IS2_TYPE_ETYPE
;
393 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L2_DMAC
,
394 etype
->dmac
.value
, etype
->dmac
.mask
);
395 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L2_SMAC
,
396 etype
->smac
.value
, etype
->smac
.mask
);
397 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_MAC_ETYPE_ETYPE
,
398 etype
->etype
.value
, etype
->etype
.mask
);
399 /* Clear unused bits */
400 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0
,
402 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1
,
404 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2
,
406 vcap_key_bytes_set(vcap
, &data
,
407 VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0
,
408 etype
->data
.value
, etype
->data
.mask
);
411 case OCELOT_VCAP_KEY_LLC
: {
412 struct ocelot_vcap_key_llc
*llc
= &filter
->key
.llc
;
415 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L2_DMAC
,
416 llc
->dmac
.value
, llc
->dmac
.mask
);
417 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L2_SMAC
,
418 llc
->smac
.value
, llc
->smac
.mask
);
419 for (i
= 0; i
< 4; i
++) {
420 payload
.value
[i
] = llc
->llc
.value
[i
];
421 payload
.mask
[i
] = llc
->llc
.mask
[i
];
423 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_MAC_LLC_L2_LLC
,
424 payload
.value
, payload
.mask
);
427 case OCELOT_VCAP_KEY_SNAP
: {
428 struct ocelot_vcap_key_snap
*snap
= &filter
->key
.snap
;
430 type
= IS2_TYPE_SNAP
;
431 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L2_DMAC
,
432 snap
->dmac
.value
, snap
->dmac
.mask
);
433 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L2_SMAC
,
434 snap
->smac
.value
, snap
->smac
.mask
);
435 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_MAC_SNAP_L2_SNAP
,
436 filter
->key
.snap
.snap
.value
,
437 filter
->key
.snap
.snap
.mask
);
440 case OCELOT_VCAP_KEY_ARP
: {
441 struct ocelot_vcap_key_arp
*arp
= &filter
->key
.arp
;
444 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_MAC_ARP_SMAC
,
445 arp
->smac
.value
, arp
->smac
.mask
);
446 vcap_key_bit_set(vcap
, &data
,
447 VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK
,
449 vcap_key_bit_set(vcap
, &data
,
450 VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK
,
452 vcap_key_bit_set(vcap
, &data
,
453 VCAP_IS2_HK_MAC_ARP_LEN_OK
,
455 vcap_key_bit_set(vcap
, &data
,
456 VCAP_IS2_HK_MAC_ARP_TARGET_MATCH
,
458 vcap_key_bit_set(vcap
, &data
,
459 VCAP_IS2_HK_MAC_ARP_SENDER_MATCH
,
461 vcap_key_bit_set(vcap
, &data
,
462 VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN
,
465 /* OPCODE is inverse, bit 0 is reply flag, bit 1 is RARP flag */
466 val
= ((arp
->req
== OCELOT_VCAP_BIT_0
? 1 : 0) |
467 (arp
->arp
== OCELOT_VCAP_BIT_0
? 2 : 0));
468 msk
= ((arp
->req
== OCELOT_VCAP_BIT_ANY
? 0 : 1) |
469 (arp
->arp
== OCELOT_VCAP_BIT_ANY
? 0 : 2));
470 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_MAC_ARP_OPCODE
,
472 vcap_key_bytes_set(vcap
, &data
,
473 VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP
,
474 arp
->dip
.value
.addr
, arp
->dip
.mask
.addr
);
475 vcap_key_bytes_set(vcap
, &data
,
476 VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP
,
477 arp
->sip
.value
.addr
, arp
->sip
.mask
.addr
);
478 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP
,
482 case OCELOT_VCAP_KEY_IPV4
:
483 case OCELOT_VCAP_KEY_IPV6
: {
484 enum ocelot_vcap_bit sip_eq_dip
, sport_eq_dport
, seq_zero
, tcp
;
485 enum ocelot_vcap_bit ttl
, fragment
, options
, tcp_ack
, tcp_urg
;
486 enum ocelot_vcap_bit tcp_fin
, tcp_syn
, tcp_rst
, tcp_psh
;
487 struct ocelot_vcap_key_ipv4
*ipv4
= NULL
;
488 struct ocelot_vcap_key_ipv6
*ipv6
= NULL
;
489 struct ocelot_vcap_udp_tcp
*sport
, *dport
;
490 struct ocelot_vcap_ipv4 sip
, dip
;
491 struct ocelot_vcap_u8 proto
, ds
;
492 struct ocelot_vcap_u48
*ip_data
;
494 if (filter
->key_type
== OCELOT_VCAP_KEY_IPV4
) {
495 ipv4
= &filter
->key
.ipv4
;
497 fragment
= ipv4
->fragment
;
498 options
= ipv4
->options
;
501 ip_data
= &ipv4
->data
;
504 sport
= &ipv4
->sport
;
505 dport
= &ipv4
->dport
;
506 tcp_fin
= ipv4
->tcp_fin
;
507 tcp_syn
= ipv4
->tcp_syn
;
508 tcp_rst
= ipv4
->tcp_rst
;
509 tcp_psh
= ipv4
->tcp_psh
;
510 tcp_ack
= ipv4
->tcp_ack
;
511 tcp_urg
= ipv4
->tcp_urg
;
512 sip_eq_dip
= ipv4
->sip_eq_dip
;
513 sport_eq_dport
= ipv4
->sport_eq_dport
;
514 seq_zero
= ipv4
->seq_zero
;
516 ipv6
= &filter
->key
.ipv6
;
518 fragment
= OCELOT_VCAP_BIT_ANY
;
519 options
= OCELOT_VCAP_BIT_ANY
;
522 ip_data
= &ipv6
->data
;
523 for (i
= 0; i
< 8; i
++) {
524 val
= ipv6
->sip
.value
[i
+ 8];
525 msk
= ipv6
->sip
.mask
[i
+ 8];
527 dip
.value
.addr
[i
] = val
;
528 dip
.mask
.addr
[i
] = msk
;
530 sip
.value
.addr
[i
- 4] = val
;
531 sip
.mask
.addr
[i
- 4] = msk
;
534 sport
= &ipv6
->sport
;
535 dport
= &ipv6
->dport
;
536 tcp_fin
= ipv6
->tcp_fin
;
537 tcp_syn
= ipv6
->tcp_syn
;
538 tcp_rst
= ipv6
->tcp_rst
;
539 tcp_psh
= ipv6
->tcp_psh
;
540 tcp_ack
= ipv6
->tcp_ack
;
541 tcp_urg
= ipv6
->tcp_urg
;
542 sip_eq_dip
= ipv6
->sip_eq_dip
;
543 sport_eq_dport
= ipv6
->sport_eq_dport
;
544 seq_zero
= ipv6
->seq_zero
;
547 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_IP4
,
548 ipv4
? OCELOT_VCAP_BIT_1
: OCELOT_VCAP_BIT_0
);
549 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L3_FRAGMENT
,
551 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_L3_FRAG_OFS_GT0
, 0, 0);
552 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L3_OPTIONS
,
554 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_IP4_L3_TTL_GT0
,
556 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L3_TOS
,
558 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L3_IP4_DIP
,
559 dip
.value
.addr
, dip
.mask
.addr
);
560 vcap_key_bytes_set(vcap
, &data
, VCAP_IS2_HK_L3_IP4_SIP
,
561 sip
.value
.addr
, sip
.mask
.addr
);
562 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_DIP_EQ_SIP
,
564 val
= proto
.value
[0];
566 type
= IS2_TYPE_IP_UDP_TCP
;
567 if (msk
== 0xff && (val
== 6 || val
== 17)) {
568 /* UDP/TCP protocol match */
570 OCELOT_VCAP_BIT_1
: OCELOT_VCAP_BIT_0
);
571 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_TCP
, tcp
);
572 vcap_key_l4_port_set(vcap
, &data
,
573 VCAP_IS2_HK_L4_DPORT
, dport
);
574 vcap_key_l4_port_set(vcap
, &data
,
575 VCAP_IS2_HK_L4_SPORT
, sport
);
576 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_L4_RNG
, 0, 0);
577 vcap_key_bit_set(vcap
, &data
,
578 VCAP_IS2_HK_L4_SPORT_EQ_DPORT
,
580 vcap_key_bit_set(vcap
, &data
,
581 VCAP_IS2_HK_L4_SEQUENCE_EQ0
,
583 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L4_FIN
,
585 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L4_SYN
,
587 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L4_RST
,
589 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L4_PSH
,
591 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L4_ACK
,
593 vcap_key_bit_set(vcap
, &data
, VCAP_IS2_HK_L4_URG
,
595 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_L4_1588_DOM
,
597 vcap_key_set(vcap
, &data
, VCAP_IS2_HK_L4_1588_VER
,
601 /* Any IP protocol match */
602 type_mask
= IS2_TYPE_MASK_IP_ANY
;
604 /* Non-UDP/TCP protocol match */
605 type
= IS2_TYPE_IP_OTHER
;
606 for (i
= 0; i
< 6; i
++) {
607 payload
.value
[i
] = ip_data
->value
[i
];
608 payload
.mask
[i
] = ip_data
->mask
[i
];
611 vcap_key_bytes_set(vcap
, &data
,
612 VCAP_IS2_HK_IP4_L3_PROTO
,
613 proto
.value
, proto
.mask
);
614 vcap_key_bytes_set(vcap
, &data
,
615 VCAP_IS2_HK_L3_PAYLOAD
,
616 payload
.value
, payload
.mask
);
620 case OCELOT_VCAP_KEY_ANY
:
624 count
= vcap
->entry_width
/ 2;
625 /* Iterate over the non-common part of the key and
628 for (i
= vcap
->keys
[VCAP_IS2_HK_L2_DMAC
].offset
;
629 i
< count
; i
+= ENTRY_WIDTH
) {
630 vcap_key_field_set(&data
, i
, min(32u, count
- i
), 0, 0);
635 vcap_key_set(vcap
, &data
, VCAP_IS2_TYPE
, type
, type_mask
);
636 is2_action_set(ocelot
, &data
, filter
);
637 vcap_data_set(data
.counter
, data
.counter_offset
,
638 vcap
->counter_width
, filter
->stats
.pkts
);
641 vcap_entry2cache(ocelot
, vcap
, &data
);
642 vcap_action2cache(ocelot
, vcap
, &data
);
643 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_WRITE
, VCAP_SEL_ALL
);
646 static void is1_action_set(struct ocelot
*ocelot
, struct vcap_data
*data
,
647 const struct ocelot_vcap_filter
*filter
)
649 const struct vcap_props
*vcap
= &ocelot
->vcap
[VCAP_IS1
];
650 const struct ocelot_vcap_action
*a
= &filter
->action
;
652 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_VID_REPLACE_ENA
,
654 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_VID_ADD_VAL
, a
->vid
);
655 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_VLAN_POP_CNT_ENA
,
656 a
->vlan_pop_cnt_ena
);
657 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_VLAN_POP_CNT
,
659 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_PCP_DEI_ENA
, a
->pcp_dei_ena
);
660 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_PCP_VAL
, a
->pcp
);
661 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_DEI_VAL
, a
->dei
);
662 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_QOS_ENA
, a
->qos_ena
);
663 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_QOS_VAL
, a
->qos_val
);
664 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_PAG_OVERRIDE_MASK
,
665 a
->pag_override_mask
);
666 vcap_action_set(vcap
, data
, VCAP_IS1_ACT_PAG_VAL
, a
->pag_val
);
669 static void is1_entry_set(struct ocelot
*ocelot
, int ix
,
670 struct ocelot_vcap_filter
*filter
)
672 const struct vcap_props
*vcap
= &ocelot
->vcap
[VCAP_IS1
];
673 struct ocelot_vcap_key_vlan
*tag
= &filter
->vlan
;
674 struct ocelot_vcap_u64 payload
;
675 struct vcap_data data
;
679 memset(&payload
, 0, sizeof(payload
));
680 memset(&data
, 0, sizeof(data
));
683 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_READ
, VCAP_SEL_ALL
);
684 vcap_cache2entry(ocelot
, vcap
, &data
);
685 vcap_cache2action(ocelot
, vcap
, &data
);
687 data
.tg_sw
= VCAP_TG_HALF
;
688 data
.type
= IS1_ACTION_TYPE_NORMAL
;
689 vcap_data_offset_get(vcap
, &data
, ix
);
690 data
.tg
= (data
.tg
& ~data
.tg_mask
);
691 if (filter
->prio
!= 0)
692 data
.tg
|= data
.tg_value
;
694 vcap_key_set(vcap
, &data
, VCAP_IS1_HK_LOOKUP
, filter
->lookup
, 0x3);
695 vcap_key_set(vcap
, &data
, VCAP_IS1_HK_IGR_PORT_MASK
, 0,
696 ~filter
->ingress_port_mask
);
697 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_L2_MC
, filter
->dmac_mc
);
698 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_L2_BC
, filter
->dmac_bc
);
699 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_VLAN_TAGGED
, tag
->tagged
);
700 vcap_key_set(vcap
, &data
, VCAP_IS1_HK_VID
,
701 tag
->vid
.value
, tag
->vid
.mask
);
702 vcap_key_set(vcap
, &data
, VCAP_IS1_HK_PCP
,
703 tag
->pcp
.value
[0], tag
->pcp
.mask
[0]);
704 type
= IS1_TYPE_S1_NORMAL
;
706 switch (filter
->key_type
) {
707 case OCELOT_VCAP_KEY_ETYPE
: {
708 struct ocelot_vcap_key_etype
*etype
= &filter
->key
.etype
;
710 vcap_key_bytes_set(vcap
, &data
, VCAP_IS1_HK_L2_SMAC
,
711 etype
->smac
.value
, etype
->smac
.mask
);
712 vcap_key_bytes_set(vcap
, &data
, VCAP_IS1_HK_ETYPE
,
713 etype
->etype
.value
, etype
->etype
.mask
);
716 case OCELOT_VCAP_KEY_IPV4
: {
717 struct ocelot_vcap_key_ipv4
*ipv4
= &filter
->key
.ipv4
;
718 struct ocelot_vcap_udp_tcp
*sport
= &ipv4
->sport
;
719 struct ocelot_vcap_udp_tcp
*dport
= &ipv4
->dport
;
720 enum ocelot_vcap_bit tcp_udp
= OCELOT_VCAP_BIT_0
;
721 struct ocelot_vcap_u8 proto
= ipv4
->proto
;
722 struct ocelot_vcap_ipv4 sip
= ipv4
->sip
;
725 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_IP_SNAP
,
727 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_IP4
,
729 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_ETYPE_LEN
,
731 vcap_key_bytes_set(vcap
, &data
, VCAP_IS1_HK_L3_IP4_SIP
,
732 sip
.value
.addr
, sip
.mask
.addr
);
734 val
= proto
.value
[0];
737 if ((val
== NEXTHDR_TCP
|| val
== NEXTHDR_UDP
) && msk
== 0xff)
738 tcp_udp
= OCELOT_VCAP_BIT_1
;
739 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_TCP_UDP
, tcp_udp
);
742 enum ocelot_vcap_bit tcp
= OCELOT_VCAP_BIT_0
;
744 if (val
== NEXTHDR_TCP
)
745 tcp
= OCELOT_VCAP_BIT_1
;
747 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_TCP
, tcp
);
748 vcap_key_l4_port_set(vcap
, &data
, VCAP_IS1_HK_L4_SPORT
,
750 /* Overloaded field */
751 vcap_key_l4_port_set(vcap
, &data
, VCAP_IS1_HK_ETYPE
,
754 /* IPv4 "other" frame */
755 struct ocelot_vcap_u16 etype
= {0};
757 /* Overloaded field */
758 etype
.value
[0] = proto
.value
[0];
759 etype
.mask
[0] = proto
.mask
[0];
761 vcap_key_bytes_set(vcap
, &data
, VCAP_IS1_HK_ETYPE
,
762 etype
.value
, etype
.mask
);
769 vcap_key_bit_set(vcap
, &data
, VCAP_IS1_HK_TYPE
,
770 type
? OCELOT_VCAP_BIT_1
: OCELOT_VCAP_BIT_0
);
772 is1_action_set(ocelot
, &data
, filter
);
773 vcap_data_set(data
.counter
, data
.counter_offset
,
774 vcap
->counter_width
, filter
->stats
.pkts
);
777 vcap_entry2cache(ocelot
, vcap
, &data
);
778 vcap_action2cache(ocelot
, vcap
, &data
);
779 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_WRITE
, VCAP_SEL_ALL
);
782 static void es0_action_set(struct ocelot
*ocelot
, struct vcap_data
*data
,
783 const struct ocelot_vcap_filter
*filter
)
785 const struct vcap_props
*vcap
= &ocelot
->vcap
[VCAP_ES0
];
786 const struct ocelot_vcap_action
*a
= &filter
->action
;
788 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_PUSH_OUTER_TAG
,
790 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_PUSH_INNER_TAG
,
792 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_TAG_A_TPID_SEL
,
794 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_TAG_A_VID_SEL
,
796 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_TAG_A_PCP_SEL
,
798 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_VID_A_VAL
, a
->vid_a_val
);
799 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_PCP_A_VAL
, a
->pcp_a_val
);
800 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_TAG_B_TPID_SEL
,
802 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_TAG_B_VID_SEL
,
804 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_TAG_B_PCP_SEL
,
806 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_VID_B_VAL
, a
->vid_b_val
);
807 vcap_action_set(vcap
, data
, VCAP_ES0_ACT_PCP_B_VAL
, a
->pcp_b_val
);
810 static void es0_entry_set(struct ocelot
*ocelot
, int ix
,
811 struct ocelot_vcap_filter
*filter
)
813 const struct vcap_props
*vcap
= &ocelot
->vcap
[VCAP_ES0
];
814 struct ocelot_vcap_key_vlan
*tag
= &filter
->vlan
;
815 struct ocelot_vcap_u64 payload
;
816 struct vcap_data data
;
819 memset(&payload
, 0, sizeof(payload
));
820 memset(&data
, 0, sizeof(data
));
823 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_READ
, VCAP_SEL_ALL
);
824 vcap_cache2entry(ocelot
, vcap
, &data
);
825 vcap_cache2action(ocelot
, vcap
, &data
);
827 data
.tg_sw
= VCAP_TG_FULL
;
828 data
.type
= ES0_ACTION_TYPE_NORMAL
;
829 vcap_data_offset_get(vcap
, &data
, ix
);
830 data
.tg
= (data
.tg
& ~data
.tg_mask
);
831 if (filter
->prio
!= 0)
832 data
.tg
|= data
.tg_value
;
834 vcap_key_set(vcap
, &data
, VCAP_ES0_IGR_PORT
, filter
->ingress_port
.value
,
835 filter
->ingress_port
.mask
);
836 vcap_key_set(vcap
, &data
, VCAP_ES0_EGR_PORT
, filter
->egress_port
.value
,
837 filter
->egress_port
.mask
);
838 vcap_key_bit_set(vcap
, &data
, VCAP_ES0_L2_MC
, filter
->dmac_mc
);
839 vcap_key_bit_set(vcap
, &data
, VCAP_ES0_L2_BC
, filter
->dmac_bc
);
840 vcap_key_set(vcap
, &data
, VCAP_ES0_VID
,
841 tag
->vid
.value
, tag
->vid
.mask
);
842 vcap_key_set(vcap
, &data
, VCAP_ES0_PCP
,
843 tag
->pcp
.value
[0], tag
->pcp
.mask
[0]);
845 es0_action_set(ocelot
, &data
, filter
);
846 vcap_data_set(data
.counter
, data
.counter_offset
,
847 vcap
->counter_width
, filter
->stats
.pkts
);
850 vcap_entry2cache(ocelot
, vcap
, &data
);
851 vcap_action2cache(ocelot
, vcap
, &data
);
852 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_WRITE
, VCAP_SEL_ALL
);
855 static void vcap_entry_get(struct ocelot
*ocelot
, int ix
,
856 struct ocelot_vcap_filter
*filter
)
858 const struct vcap_props
*vcap
= &ocelot
->vcap
[filter
->block_id
];
859 struct vcap_data data
;
863 if (filter
->block_id
== VCAP_ES0
)
864 data
.tg_sw
= VCAP_TG_FULL
;
866 data
.tg_sw
= VCAP_TG_HALF
;
868 count
= (1 << (data
.tg_sw
- 1));
870 vcap_row_cmd(ocelot
, vcap
, row
, VCAP_CMD_READ
, VCAP_SEL_COUNTER
);
871 vcap_cache2action(ocelot
, vcap
, &data
);
872 vcap_data_offset_get(vcap
, &data
, ix
);
873 cnt
= vcap_data_get(data
.counter
, data
.counter_offset
,
874 vcap
->counter_width
);
876 filter
->stats
.pkts
= cnt
;
879 static void vcap_entry_set(struct ocelot
*ocelot
, int ix
,
880 struct ocelot_vcap_filter
*filter
)
882 if (filter
->block_id
== VCAP_IS1
)
883 return is1_entry_set(ocelot
, ix
, filter
);
884 if (filter
->block_id
== VCAP_IS2
)
885 return is2_entry_set(ocelot
, ix
, filter
);
886 if (filter
->block_id
== VCAP_ES0
)
887 return es0_entry_set(ocelot
, ix
, filter
);
890 static int ocelot_vcap_policer_add(struct ocelot
*ocelot
, u32 pol_ix
,
891 struct ocelot_policer
*pol
)
893 struct qos_policer_conf pp
= { 0 };
898 pp
.mode
= MSCC_QOS_RATE_MODE_DATA
;
902 return qos_policer_conf_set(ocelot
, 0, pol_ix
, &pp
);
905 static void ocelot_vcap_policer_del(struct ocelot
*ocelot
,
906 struct ocelot_vcap_block
*block
,
909 struct ocelot_vcap_filter
*filter
;
910 struct qos_policer_conf pp
= {0};
913 if (pol_ix
< block
->pol_lpr
)
916 list_for_each_entry(filter
, &block
->rules
, list
) {
918 if (filter
->block_id
== VCAP_IS2
&&
919 filter
->action
.police_ena
&&
920 filter
->action
.pol_ix
< pol_ix
) {
921 filter
->action
.pol_ix
+= 1;
922 ocelot_vcap_policer_add(ocelot
, filter
->action
.pol_ix
,
923 &filter
->action
.pol
);
924 is2_entry_set(ocelot
, index
, filter
);
928 pp
.mode
= MSCC_QOS_RATE_MODE_DISABLED
;
929 qos_policer_conf_set(ocelot
, 0, pol_ix
, &pp
);
934 static void ocelot_vcap_filter_add_to_block(struct ocelot
*ocelot
,
935 struct ocelot_vcap_block
*block
,
936 struct ocelot_vcap_filter
*filter
)
938 struct ocelot_vcap_filter
*tmp
;
939 struct list_head
*pos
, *n
;
941 if (filter
->block_id
== VCAP_IS2
&& filter
->action
.police_ena
) {
943 filter
->action
.pol_ix
= block
->pol_lpr
;
944 ocelot_vcap_policer_add(ocelot
, filter
->action
.pol_ix
,
945 &filter
->action
.pol
);
950 if (list_empty(&block
->rules
)) {
951 list_add(&filter
->list
, &block
->rules
);
955 list_for_each_safe(pos
, n
, &block
->rules
) {
956 tmp
= list_entry(pos
, struct ocelot_vcap_filter
, list
);
957 if (filter
->prio
< tmp
->prio
)
960 list_add(&filter
->list
, pos
->prev
);
963 static bool ocelot_vcap_filter_equal(const struct ocelot_vcap_filter
*a
,
964 const struct ocelot_vcap_filter
*b
)
966 return !memcmp(&a
->id
, &b
->id
, sizeof(struct ocelot_vcap_id
));
969 static int ocelot_vcap_block_get_filter_index(struct ocelot_vcap_block
*block
,
970 struct ocelot_vcap_filter
*filter
)
972 struct ocelot_vcap_filter
*tmp
;
975 list_for_each_entry(tmp
, &block
->rules
, list
) {
976 if (ocelot_vcap_filter_equal(filter
, tmp
))
984 static struct ocelot_vcap_filter
*
985 ocelot_vcap_block_find_filter_by_index(struct ocelot_vcap_block
*block
,
988 struct ocelot_vcap_filter
*tmp
;
991 list_for_each_entry(tmp
, &block
->rules
, list
) {
1000 struct ocelot_vcap_filter
*
1001 ocelot_vcap_block_find_filter_by_id(struct ocelot_vcap_block
*block
,
1002 unsigned long cookie
, bool tc_offload
)
1004 struct ocelot_vcap_filter
*filter
;
1006 list_for_each_entry(filter
, &block
->rules
, list
)
1007 if (filter
->id
.tc_offload
== tc_offload
&&
1008 filter
->id
.cookie
== cookie
)
1013 EXPORT_SYMBOL(ocelot_vcap_block_find_filter_by_id
);
1015 /* If @on=false, then SNAP, ARP, IP and OAM frames will not match on keys based
1016 * on destination and source MAC addresses, but only on higher-level protocol
1017 * information. The only frame types to match on keys containing MAC addresses
1018 * in this case are non-SNAP, non-ARP, non-IP and non-OAM frames.
1020 * If @on=true, then the above frame types (SNAP, ARP, IP and OAM) will match
1021 * on MAC_ETYPE keys such as destination and source MAC on this ingress port.
1022 * However the setting has the side effect of making these frames not matching
1023 * on any _other_ keys than MAC_ETYPE ones.
1025 static void ocelot_match_all_as_mac_etype(struct ocelot
*ocelot
, int port
,
1026 int lookup
, bool on
)
1031 val
= ANA_PORT_VCAP_S2_CFG_S2_SNAP_DIS(BIT(lookup
)) |
1032 ANA_PORT_VCAP_S2_CFG_S2_ARP_DIS(BIT(lookup
)) |
1033 ANA_PORT_VCAP_S2_CFG_S2_IP_TCPUDP_DIS(BIT(lookup
)) |
1034 ANA_PORT_VCAP_S2_CFG_S2_IP_OTHER_DIS(BIT(lookup
)) |
1035 ANA_PORT_VCAP_S2_CFG_S2_OAM_DIS(BIT(lookup
));
1037 ocelot_rmw_gix(ocelot
, val
,
1038 ANA_PORT_VCAP_S2_CFG_S2_SNAP_DIS(BIT(lookup
)) |
1039 ANA_PORT_VCAP_S2_CFG_S2_ARP_DIS(BIT(lookup
)) |
1040 ANA_PORT_VCAP_S2_CFG_S2_IP_TCPUDP_DIS(BIT(lookup
)) |
1041 ANA_PORT_VCAP_S2_CFG_S2_IP_OTHER_DIS(BIT(lookup
)) |
1042 ANA_PORT_VCAP_S2_CFG_S2_OAM_DIS(BIT(lookup
)),
1043 ANA_PORT_VCAP_S2_CFG
, port
);
1047 ocelot_vcap_is_problematic_mac_etype(struct ocelot_vcap_filter
*filter
)
1051 if (filter
->key_type
!= OCELOT_VCAP_KEY_ETYPE
)
1054 proto
= ntohs(*(__be16
*)filter
->key
.etype
.etype
.value
);
1055 mask
= ntohs(*(__be16
*)filter
->key
.etype
.etype
.mask
);
1057 /* ETH_P_ALL match, so all protocols below are included */
1060 if (proto
== ETH_P_ARP
)
1062 if (proto
== ETH_P_IP
)
1064 if (proto
== ETH_P_IPV6
)
1071 ocelot_vcap_is_problematic_non_mac_etype(struct ocelot_vcap_filter
*filter
)
1073 if (filter
->key_type
== OCELOT_VCAP_KEY_SNAP
)
1075 if (filter
->key_type
== OCELOT_VCAP_KEY_ARP
)
1077 if (filter
->key_type
== OCELOT_VCAP_KEY_IPV4
)
1079 if (filter
->key_type
== OCELOT_VCAP_KEY_IPV6
)
1085 ocelot_exclusive_mac_etype_filter_rules(struct ocelot
*ocelot
,
1086 struct ocelot_vcap_filter
*filter
)
1088 struct ocelot_vcap_block
*block
= &ocelot
->block
[filter
->block_id
];
1089 struct ocelot_vcap_filter
*tmp
;
1093 /* We only have the S2_IP_TCPUDP_DIS set of knobs for VCAP IS2 */
1094 if (filter
->block_id
!= VCAP_IS2
)
1097 if (ocelot_vcap_is_problematic_mac_etype(filter
)) {
1098 /* Search for any non-MAC_ETYPE rules on the port */
1099 for (i
= 0; i
< block
->count
; i
++) {
1100 tmp
= ocelot_vcap_block_find_filter_by_index(block
, i
);
1101 if (tmp
->ingress_port_mask
& filter
->ingress_port_mask
&&
1102 tmp
->lookup
== filter
->lookup
&&
1103 ocelot_vcap_is_problematic_non_mac_etype(tmp
))
1107 for_each_set_bit(port
, &filter
->ingress_port_mask
,
1108 ocelot
->num_phys_ports
)
1109 ocelot_match_all_as_mac_etype(ocelot
, port
,
1110 filter
->lookup
, true);
1111 } else if (ocelot_vcap_is_problematic_non_mac_etype(filter
)) {
1112 /* Search for any MAC_ETYPE rules on the port */
1113 for (i
= 0; i
< block
->count
; i
++) {
1114 tmp
= ocelot_vcap_block_find_filter_by_index(block
, i
);
1115 if (tmp
->ingress_port_mask
& filter
->ingress_port_mask
&&
1116 tmp
->lookup
== filter
->lookup
&&
1117 ocelot_vcap_is_problematic_mac_etype(tmp
))
1121 for_each_set_bit(port
, &filter
->ingress_port_mask
,
1122 ocelot
->num_phys_ports
)
1123 ocelot_match_all_as_mac_etype(ocelot
, port
,
1124 filter
->lookup
, false);
1130 int ocelot_vcap_filter_add(struct ocelot
*ocelot
,
1131 struct ocelot_vcap_filter
*filter
,
1132 struct netlink_ext_ack
*extack
)
1134 struct ocelot_vcap_block
*block
= &ocelot
->block
[filter
->block_id
];
1137 if (!ocelot_exclusive_mac_etype_filter_rules(ocelot
, filter
)) {
1138 NL_SET_ERR_MSG_MOD(extack
,
1139 "Cannot mix MAC_ETYPE with non-MAC_ETYPE rules, use the other IS2 lookup");
1143 /* Add filter to the linked list */
1144 ocelot_vcap_filter_add_to_block(ocelot
, block
, filter
);
1146 /* Get the index of the inserted filter */
1147 index
= ocelot_vcap_block_get_filter_index(block
, filter
);
1151 /* Move down the rules to make place for the new filter */
1152 for (i
= block
->count
- 1; i
> index
; i
--) {
1153 struct ocelot_vcap_filter
*tmp
;
1155 tmp
= ocelot_vcap_block_find_filter_by_index(block
, i
);
1156 vcap_entry_set(ocelot
, i
, tmp
);
1159 /* Now insert the new filter */
1160 vcap_entry_set(ocelot
, index
, filter
);
1163 EXPORT_SYMBOL(ocelot_vcap_filter_add
);
1165 static void ocelot_vcap_block_remove_filter(struct ocelot
*ocelot
,
1166 struct ocelot_vcap_block
*block
,
1167 struct ocelot_vcap_filter
*filter
)
1169 struct ocelot_vcap_filter
*tmp
;
1170 struct list_head
*pos
, *q
;
1172 list_for_each_safe(pos
, q
, &block
->rules
) {
1173 tmp
= list_entry(pos
, struct ocelot_vcap_filter
, list
);
1174 if (ocelot_vcap_filter_equal(filter
, tmp
)) {
1175 if (tmp
->block_id
== VCAP_IS2
&&
1176 tmp
->action
.police_ena
)
1177 ocelot_vcap_policer_del(ocelot
, block
,
1178 tmp
->action
.pol_ix
);
1188 int ocelot_vcap_filter_del(struct ocelot
*ocelot
,
1189 struct ocelot_vcap_filter
*filter
)
1191 struct ocelot_vcap_block
*block
= &ocelot
->block
[filter
->block_id
];
1192 struct ocelot_vcap_filter del_filter
;
1195 memset(&del_filter
, 0, sizeof(del_filter
));
1197 /* Gets index of the filter */
1198 index
= ocelot_vcap_block_get_filter_index(block
, filter
);
1203 ocelot_vcap_block_remove_filter(ocelot
, block
, filter
);
1205 /* Move up all the blocks over the deleted filter */
1206 for (i
= index
; i
< block
->count
; i
++) {
1207 struct ocelot_vcap_filter
*tmp
;
1209 tmp
= ocelot_vcap_block_find_filter_by_index(block
, i
);
1210 vcap_entry_set(ocelot
, i
, tmp
);
1213 /* Now delete the last filter, because it is duplicated */
1214 vcap_entry_set(ocelot
, block
->count
, &del_filter
);
1218 EXPORT_SYMBOL(ocelot_vcap_filter_del
);
1220 int ocelot_vcap_filter_stats_update(struct ocelot
*ocelot
,
1221 struct ocelot_vcap_filter
*filter
)
1223 struct ocelot_vcap_block
*block
= &ocelot
->block
[filter
->block_id
];
1224 struct ocelot_vcap_filter tmp
;
1227 index
= ocelot_vcap_block_get_filter_index(block
, filter
);
1231 vcap_entry_get(ocelot
, index
, filter
);
1233 /* After we get the result we need to clear the counters */
1236 vcap_entry_set(ocelot
, index
, &tmp
);
1241 static void ocelot_vcap_init_one(struct ocelot
*ocelot
,
1242 const struct vcap_props
*vcap
)
1244 struct vcap_data data
;
1246 memset(&data
, 0, sizeof(data
));
1248 vcap_entry2cache(ocelot
, vcap
, &data
);
1249 ocelot_target_write(ocelot
, vcap
->target
, vcap
->entry_count
,
1251 vcap_cmd(ocelot
, vcap
, 0, VCAP_CMD_INITIALIZE
, VCAP_SEL_ENTRY
);
1253 vcap_action2cache(ocelot
, vcap
, &data
);
1254 ocelot_target_write(ocelot
, vcap
->target
, vcap
->action_count
,
1256 vcap_cmd(ocelot
, vcap
, 0, VCAP_CMD_INITIALIZE
,
1257 VCAP_SEL_ACTION
| VCAP_SEL_COUNTER
);
1260 static void ocelot_vcap_detect_constants(struct ocelot
*ocelot
,
1261 struct vcap_props
*vcap
)
1263 int counter_memory_width
;
1264 int num_default_actions
;
1267 version
= ocelot_target_read(ocelot
, vcap
->target
,
1268 VCAP_CONST_VCAP_VER
);
1269 /* Only version 0 VCAP supported for now */
1270 if (WARN_ON(version
!= 0))
1273 /* Width in bits of type-group field */
1274 vcap
->tg_width
= ocelot_target_read(ocelot
, vcap
->target
,
1275 VCAP_CONST_ENTRY_TG_WIDTH
);
1276 /* Number of subwords per TCAM row */
1277 vcap
->sw_count
= ocelot_target_read(ocelot
, vcap
->target
,
1278 VCAP_CONST_ENTRY_SWCNT
);
1279 /* Number of rows in TCAM. There can be this many full keys, or double
1280 * this number half keys, or 4 times this number quarter keys.
1282 vcap
->entry_count
= ocelot_target_read(ocelot
, vcap
->target
,
1283 VCAP_CONST_ENTRY_CNT
);
1284 /* Assuming there are 4 subwords per TCAM row, their layout in the
1285 * actual TCAM (not in the cache) would be:
1287 * | SW 3 | TG 3 | SW 2 | TG 2 | SW 1 | TG 1 | SW 0 | TG 0 |
1289 * (where SW=subword and TG=Type-Group).
1291 * What VCAP_CONST_ENTRY_CNT is giving us is the width of one full TCAM
1292 * row. But when software accesses the TCAM through the cache
1293 * registers, the Type-Group values are written through another set of
1294 * registers VCAP_TG_DAT, and therefore, it appears as though the 4
1295 * subwords are contiguous in the cache memory.
1296 * Important mention: regardless of the number of key entries per row
1297 * (and therefore of key size: 1 full key or 2 half keys or 4 quarter
1298 * keys), software always has to configure 4 Type-Group values. For
1299 * example, in the case of 1 full key, the driver needs to set all 4
1300 * Type-Group to be full key.
1302 * For this reason, we need to fix up the value that the hardware is
1303 * giving us. We don't actually care about the width of the entry in
1304 * the TCAM. What we care about is the width of the entry in the cache
1305 * registers, which is how we get to interact with it. And since the
1306 * VCAP_ENTRY_DAT cache registers access only the subwords and not the
1307 * Type-Groups, this means we need to subtract the width of the
1308 * Type-Groups when packing and unpacking key entry data in a TCAM row.
1310 vcap
->entry_width
= ocelot_target_read(ocelot
, vcap
->target
,
1311 VCAP_CONST_ENTRY_WIDTH
);
1312 vcap
->entry_width
-= vcap
->tg_width
* vcap
->sw_count
;
1313 num_default_actions
= ocelot_target_read(ocelot
, vcap
->target
,
1314 VCAP_CONST_ACTION_DEF_CNT
);
1315 vcap
->action_count
= vcap
->entry_count
+ num_default_actions
;
1316 vcap
->action_width
= ocelot_target_read(ocelot
, vcap
->target
,
1317 VCAP_CONST_ACTION_WIDTH
);
1318 /* The width of the counter memory, this is the complete width of all
1319 * counter-fields associated with one full-word entry. There is one
1320 * counter per entry sub-word (see CAP_CORE::ENTRY_SWCNT for number of
1323 vcap
->counter_words
= vcap
->sw_count
;
1324 counter_memory_width
= ocelot_target_read(ocelot
, vcap
->target
,
1325 VCAP_CONST_CNT_WIDTH
);
1326 vcap
->counter_width
= counter_memory_width
/ vcap
->counter_words
;
1329 int ocelot_vcap_init(struct ocelot
*ocelot
)
1333 /* Create a policer that will drop the frames for the cpu.
1334 * This policer will be used as action in the acl rules to drop
1337 ocelot_write_gix(ocelot
, 0x299, ANA_POL_MODE_CFG
,
1338 OCELOT_POLICER_DISCARD
);
1339 ocelot_write_gix(ocelot
, 0x1, ANA_POL_PIR_CFG
,
1340 OCELOT_POLICER_DISCARD
);
1341 ocelot_write_gix(ocelot
, 0x3fffff, ANA_POL_PIR_STATE
,
1342 OCELOT_POLICER_DISCARD
);
1343 ocelot_write_gix(ocelot
, 0x0, ANA_POL_CIR_CFG
,
1344 OCELOT_POLICER_DISCARD
);
1345 ocelot_write_gix(ocelot
, 0x3fffff, ANA_POL_CIR_STATE
,
1346 OCELOT_POLICER_DISCARD
);
1348 for (i
= 0; i
< OCELOT_NUM_VCAP_BLOCKS
; i
++) {
1349 struct ocelot_vcap_block
*block
= &ocelot
->block
[i
];
1350 struct vcap_props
*vcap
= &ocelot
->vcap
[i
];
1352 INIT_LIST_HEAD(&block
->rules
);
1353 block
->pol_lpr
= OCELOT_POLICER_DISCARD
- 1;
1355 ocelot_vcap_detect_constants(ocelot
, vcap
);
1356 ocelot_vcap_init_one(ocelot
, vcap
);
1359 INIT_LIST_HEAD(&ocelot
->dummy_rules
);