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 "ocelot_ace.h"
10 #include "ocelot_vcap.h"
11 #include "ocelot_s2.h"
13 #define OCELOT_POLICER_DISCARD 0x17f
15 static struct ocelot_acl_block
*acl_block
;
18 const char *name
; /* Symbolic name */
19 u16 tg_width
; /* Type-group width (in bits) */
20 u16 sw_count
; /* Sub word count */
21 u16 entry_count
; /* Entry count */
22 u16 entry_words
; /* Number of entry words */
23 u16 entry_width
; /* Entry width (in bits) */
24 u16 action_count
; /* Action count */
25 u16 action_words
; /* Number of action words */
26 u16 action_width
; /* Action width (in bits) */
27 u16 action_type_width
; /* Action type width (in bits) */
29 u16 width
; /* Action type width (in bits) */
30 u16 count
; /* Action type sub word count */
32 u16 counter_words
; /* Number of counter words */
33 u16 counter_width
; /* Counter width (in bits) */
36 #define ENTRY_WIDTH 32
37 #define BITS_TO_32BIT(x) (1 + (((x) - 1) / ENTRY_WIDTH))
39 static const struct vcap_props vcap_is2
= {
43 .entry_count
= VCAP_IS2_CNT
,
44 .entry_words
= BITS_TO_32BIT(VCAP_IS2_ENTRY_WIDTH
),
45 .entry_width
= VCAP_IS2_ENTRY_WIDTH
,
46 .action_count
= (VCAP_IS2_CNT
+ VCAP_PORT_CNT
+ 2),
47 .action_words
= BITS_TO_32BIT(VCAP_IS2_ACTION_WIDTH
),
48 .action_width
= (VCAP_IS2_ACTION_WIDTH
),
49 .action_type_width
= 1,
52 .width
= (IS2_AO_ACL_ID
+ IS2_AL_ACL_ID
),
60 .counter_words
= BITS_TO_32BIT(4 * ENTRY_WIDTH
),
61 .counter_width
= ENTRY_WIDTH
,
66 VCAP_SEL_ACTION
= 0x2,
67 VCAP_SEL_COUNTER
= 0x4,
72 VCAP_CMD_WRITE
= 0, /* Copy from Cache to TCAM */
73 VCAP_CMD_READ
= 1, /* Copy from TCAM to Cache */
74 VCAP_CMD_MOVE_UP
= 2, /* Move <count> up */
75 VCAP_CMD_MOVE_DOWN
= 3, /* Move <count> down */
76 VCAP_CMD_INITIALIZE
= 4, /* Write all (from cache) */
79 #define VCAP_ENTRY_WIDTH 12 /* Max entry width (32bit words) */
80 #define VCAP_COUNTER_WIDTH 4 /* Max counter width (32bit words) */
83 u32 entry
[VCAP_ENTRY_WIDTH
]; /* ENTRY_DAT */
84 u32 mask
[VCAP_ENTRY_WIDTH
]; /* MASK_DAT */
85 u32 action
[VCAP_ENTRY_WIDTH
]; /* ACTION_DAT */
86 u32 counter
[VCAP_COUNTER_WIDTH
]; /* CNT_DAT */
88 u32 type
; /* Action type */
89 u32 tg_sw
; /* Current type-group */
90 u32 cnt
; /* Current counter */
91 u32 key_offset
; /* Current entry offset */
92 u32 action_offset
; /* Current action offset */
93 u32 counter_offset
; /* Current counter offset */
94 u32 tg_value
; /* Current type-group value */
95 u32 tg_mask
; /* Current type-group mask */
98 static u32
vcap_s2_read_update_ctrl(struct ocelot
*oc
)
100 return ocelot_read(oc
, S2_CORE_UPDATE_CTRL
);
103 static void vcap_cmd(struct ocelot
*oc
, u16 ix
, int cmd
, int sel
)
105 u32 value
= (S2_CORE_UPDATE_CTRL_UPDATE_CMD(cmd
) |
106 S2_CORE_UPDATE_CTRL_UPDATE_ADDR(ix
) |
107 S2_CORE_UPDATE_CTRL_UPDATE_SHOT
);
109 if ((sel
& VCAP_SEL_ENTRY
) && ix
>= vcap_is2
.entry_count
)
112 if (!(sel
& VCAP_SEL_ENTRY
))
113 value
|= S2_CORE_UPDATE_CTRL_UPDATE_ENTRY_DIS
;
115 if (!(sel
& VCAP_SEL_ACTION
))
116 value
|= S2_CORE_UPDATE_CTRL_UPDATE_ACTION_DIS
;
118 if (!(sel
& VCAP_SEL_COUNTER
))
119 value
|= S2_CORE_UPDATE_CTRL_UPDATE_CNT_DIS
;
121 ocelot_write(oc
, value
, S2_CORE_UPDATE_CTRL
);
122 readx_poll_timeout(vcap_s2_read_update_ctrl
, oc
, value
,
123 (value
& S2_CORE_UPDATE_CTRL_UPDATE_SHOT
) == 0,
127 /* Convert from 0-based row to VCAP entry row and run command */
128 static void vcap_row_cmd(struct ocelot
*oc
, u32 row
, int cmd
, int sel
)
130 vcap_cmd(oc
, vcap_is2
.entry_count
- row
- 1, cmd
, sel
);
133 static void vcap_entry2cache(struct ocelot
*oc
, struct vcap_data
*data
)
137 for (i
= 0; i
< vcap_is2
.entry_words
; i
++) {
138 ocelot_write_rix(oc
, data
->entry
[i
], S2_CACHE_ENTRY_DAT
, i
);
139 ocelot_write_rix(oc
, ~data
->mask
[i
], S2_CACHE_MASK_DAT
, i
);
141 ocelot_write(oc
, data
->tg
, S2_CACHE_TG_DAT
);
144 static void vcap_cache2entry(struct ocelot
*oc
, struct vcap_data
*data
)
148 for (i
= 0; i
< vcap_is2
.entry_words
; i
++) {
149 data
->entry
[i
] = ocelot_read_rix(oc
, S2_CACHE_ENTRY_DAT
, i
);
151 data
->mask
[i
] = ~ocelot_read_rix(oc
, S2_CACHE_MASK_DAT
, i
);
153 data
->tg
= ocelot_read(oc
, S2_CACHE_TG_DAT
);
156 static void vcap_action2cache(struct ocelot
*oc
, struct vcap_data
*data
)
160 /* Encode action type */
161 width
= vcap_is2
.action_type_width
;
163 mask
= GENMASK(width
, 0);
164 data
->action
[0] = ((data
->action
[0] & ~mask
) | data
->type
);
167 for (i
= 0; i
< vcap_is2
.action_words
; i
++)
168 ocelot_write_rix(oc
, data
->action
[i
], S2_CACHE_ACTION_DAT
, i
);
170 for (i
= 0; i
< vcap_is2
.counter_words
; i
++)
171 ocelot_write_rix(oc
, data
->counter
[i
], S2_CACHE_CNT_DAT
, i
);
174 static void vcap_cache2action(struct ocelot
*oc
, struct vcap_data
*data
)
178 for (i
= 0; i
< vcap_is2
.action_words
; i
++)
179 data
->action
[i
] = ocelot_read_rix(oc
, S2_CACHE_ACTION_DAT
, i
);
181 for (i
= 0; i
< vcap_is2
.counter_words
; i
++)
182 data
->counter
[i
] = ocelot_read_rix(oc
, S2_CACHE_CNT_DAT
, i
);
184 /* Extract action type */
185 width
= vcap_is2
.action_type_width
;
186 data
->type
= (width
? (data
->action
[0] & GENMASK(width
, 0)) : 0);
189 /* Calculate offsets for entry */
190 static void is2_data_get(struct vcap_data
*data
, int ix
)
192 u32 i
, col
, offset
, count
, cnt
, base
, width
= vcap_is2
.tg_width
;
194 count
= (data
->tg_sw
== VCAP_TG_HALF
? 2 : 4);
196 cnt
= (vcap_is2
.sw_count
/ count
);
197 base
= (vcap_is2
.sw_count
- col
* cnt
- cnt
);
200 for (i
= 0; i
< cnt
; 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
= (count
- col
- 1);
208 data
->key_offset
= (base
* vcap_is2
.entry_width
) / vcap_is2
.sw_count
;
209 data
->counter_offset
= (cnt
* col
* vcap_is2
.counter_width
);
211 width
= vcap_is2
.action_table
[i
].width
;
212 cnt
= vcap_is2
.action_table
[i
].count
;
213 data
->action_offset
=
214 (((cnt
* col
* width
) / count
) + vcap_is2
.action_type_width
);
217 static void vcap_data_set(u32
*data
, u32 offset
, u32 len
, u32 value
)
221 for (i
= 0; i
< len
; i
++, offset
++) {
222 v
= data
[offset
/ ENTRY_WIDTH
];
223 m
= (1 << (offset
% ENTRY_WIDTH
));
224 if (value
& (1 << i
))
228 data
[offset
/ ENTRY_WIDTH
] = v
;
232 static u32
vcap_data_get(u32
*data
, u32 offset
, u32 len
)
234 u32 i
, v
, m
, value
= 0;
236 for (i
= 0; i
< len
; i
++, offset
++) {
237 v
= data
[offset
/ ENTRY_WIDTH
];
238 m
= (1 << (offset
% ENTRY_WIDTH
));
245 static void vcap_key_set(struct vcap_data
*data
, u32 offset
, u32 width
,
248 vcap_data_set(data
->entry
, offset
+ data
->key_offset
, width
, value
);
249 vcap_data_set(data
->mask
, offset
+ data
->key_offset
, width
, mask
);
252 static void vcap_key_bytes_set(struct vcap_data
*data
, u32 offset
, u8
*val
,
255 u32 i
, j
, n
= 0, value
= 0, mask
= 0;
257 /* Data wider than 32 bits are split up in chunks of maximum 32 bits.
258 * The 32 LSB of the data are written to the 32 MSB of the TCAM.
260 offset
+= (count
* 8);
261 for (i
= 0; i
< count
; i
++) {
263 value
+= (val
[j
] << n
);
264 mask
+= (msk
[j
] << n
);
266 if (n
== ENTRY_WIDTH
|| (i
+ 1) == count
) {
268 vcap_key_set(data
, offset
, n
, value
, mask
);
276 static void vcap_key_l4_port_set(struct vcap_data
*data
, u32 offset
,
277 struct ocelot_vcap_udp_tcp
*port
)
279 vcap_key_set(data
, offset
, 16, port
->value
, port
->mask
);
282 static void vcap_key_bit_set(struct vcap_data
*data
, u32 offset
,
283 enum ocelot_vcap_bit val
)
285 vcap_key_set(data
, offset
, 1, val
== OCELOT_VCAP_BIT_1
? 1 : 0,
286 val
== OCELOT_VCAP_BIT_ANY
? 0 : 1);
289 #define VCAP_KEY_SET(fld, val, msk) \
290 vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, val, msk)
291 #define VCAP_KEY_ANY_SET(fld) \
292 vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, 0, 0)
293 #define VCAP_KEY_BIT_SET(fld, val) vcap_key_bit_set(&data, IS2_HKO_##fld, val)
294 #define VCAP_KEY_BYTES_SET(fld, val, msk) \
295 vcap_key_bytes_set(&data, IS2_HKO_##fld, val, msk, IS2_HKL_##fld / 8)
297 static void vcap_action_set(struct vcap_data
*data
, u32 offset
, u32 width
,
300 vcap_data_set(data
->action
, offset
+ data
->action_offset
, width
, value
);
303 #define VCAP_ACT_SET(fld, val) \
304 vcap_action_set(data, IS2_AO_##fld, IS2_AL_##fld, val)
306 static void is2_action_set(struct vcap_data
*data
,
307 enum ocelot_ace_action action
)
310 case OCELOT_ACL_ACTION_DROP
:
311 VCAP_ACT_SET(PORT_MASK
, 0x0);
312 VCAP_ACT_SET(MASK_MODE
, 0x1);
313 VCAP_ACT_SET(POLICE_ENA
, 0x1);
314 VCAP_ACT_SET(POLICE_IDX
, OCELOT_POLICER_DISCARD
);
315 VCAP_ACT_SET(CPU_QU_NUM
, 0x0);
316 VCAP_ACT_SET(CPU_COPY_ENA
, 0x0);
318 case OCELOT_ACL_ACTION_TRAP
:
319 VCAP_ACT_SET(PORT_MASK
, 0x0);
320 VCAP_ACT_SET(MASK_MODE
, 0x1);
321 VCAP_ACT_SET(POLICE_ENA
, 0x0);
322 VCAP_ACT_SET(POLICE_IDX
, 0x0);
323 VCAP_ACT_SET(CPU_QU_NUM
, 0x0);
324 VCAP_ACT_SET(CPU_COPY_ENA
, 0x1);
329 static void is2_entry_set(struct ocelot
*ocelot
, int ix
,
330 struct ocelot_ace_rule
*ace
)
332 u32 val
, msk
, type
, type_mask
= 0xf, i
, count
;
333 struct ocelot_ace_vlan
*tag
= &ace
->vlan
;
334 struct ocelot_vcap_u64 payload
;
335 struct vcap_data data
;
338 memset(&payload
, 0, sizeof(payload
));
339 memset(&data
, 0, sizeof(data
));
342 vcap_row_cmd(ocelot
, row
, VCAP_CMD_READ
, VCAP_SEL_ALL
);
343 vcap_cache2entry(ocelot
, &data
);
344 vcap_cache2action(ocelot
, &data
);
346 data
.tg_sw
= VCAP_TG_HALF
;
347 is2_data_get(&data
, ix
);
348 data
.tg
= (data
.tg
& ~data
.tg_mask
);
350 data
.tg
|= data
.tg_value
;
352 data
.type
= IS2_ACTION_TYPE_NORMAL
;
354 VCAP_KEY_ANY_SET(PAG
);
355 VCAP_KEY_SET(IGR_PORT_MASK
, 0, ~BIT(ace
->chip_port
));
356 VCAP_KEY_BIT_SET(FIRST
, OCELOT_VCAP_BIT_1
);
357 VCAP_KEY_BIT_SET(HOST_MATCH
, OCELOT_VCAP_BIT_ANY
);
358 VCAP_KEY_BIT_SET(L2_MC
, ace
->dmac_mc
);
359 VCAP_KEY_BIT_SET(L2_BC
, ace
->dmac_bc
);
360 VCAP_KEY_BIT_SET(VLAN_TAGGED
, tag
->tagged
);
361 VCAP_KEY_SET(VID
, tag
->vid
.value
, tag
->vid
.mask
);
362 VCAP_KEY_SET(PCP
, tag
->pcp
.value
[0], tag
->pcp
.mask
[0]);
363 VCAP_KEY_BIT_SET(DEI
, tag
->dei
);
366 case OCELOT_ACE_TYPE_ETYPE
: {
367 struct ocelot_ace_frame_etype
*etype
= &ace
->frame
.etype
;
369 type
= IS2_TYPE_ETYPE
;
370 VCAP_KEY_BYTES_SET(L2_DMAC
, etype
->dmac
.value
,
372 VCAP_KEY_BYTES_SET(L2_SMAC
, etype
->smac
.value
,
374 VCAP_KEY_BYTES_SET(MAC_ETYPE_ETYPE
, etype
->etype
.value
,
376 VCAP_KEY_ANY_SET(MAC_ETYPE_L2_PAYLOAD
); // Clear unused bits
377 vcap_key_bytes_set(&data
, IS2_HKO_MAC_ETYPE_L2_PAYLOAD
,
378 etype
->data
.value
, etype
->data
.mask
, 2);
381 case OCELOT_ACE_TYPE_LLC
: {
382 struct ocelot_ace_frame_llc
*llc
= &ace
->frame
.llc
;
385 VCAP_KEY_BYTES_SET(L2_DMAC
, llc
->dmac
.value
, llc
->dmac
.mask
);
386 VCAP_KEY_BYTES_SET(L2_SMAC
, llc
->smac
.value
, llc
->smac
.mask
);
387 for (i
= 0; i
< 4; i
++) {
388 payload
.value
[i
] = llc
->llc
.value
[i
];
389 payload
.mask
[i
] = llc
->llc
.mask
[i
];
391 VCAP_KEY_BYTES_SET(MAC_LLC_L2_LLC
, payload
.value
, payload
.mask
);
394 case OCELOT_ACE_TYPE_SNAP
: {
395 struct ocelot_ace_frame_snap
*snap
= &ace
->frame
.snap
;
397 type
= IS2_TYPE_SNAP
;
398 VCAP_KEY_BYTES_SET(L2_DMAC
, snap
->dmac
.value
, snap
->dmac
.mask
);
399 VCAP_KEY_BYTES_SET(L2_SMAC
, snap
->smac
.value
, snap
->smac
.mask
);
400 VCAP_KEY_BYTES_SET(MAC_SNAP_L2_SNAP
,
401 ace
->frame
.snap
.snap
.value
,
402 ace
->frame
.snap
.snap
.mask
);
405 case OCELOT_ACE_TYPE_ARP
: {
406 struct ocelot_ace_frame_arp
*arp
= &ace
->frame
.arp
;
409 VCAP_KEY_BYTES_SET(MAC_ARP_L2_SMAC
, arp
->smac
.value
,
411 VCAP_KEY_BIT_SET(MAC_ARP_ARP_ADDR_SPACE_OK
, arp
->ethernet
);
412 VCAP_KEY_BIT_SET(MAC_ARP_ARP_PROTO_SPACE_OK
, arp
->ip
);
413 VCAP_KEY_BIT_SET(MAC_ARP_ARP_LEN_OK
, arp
->length
);
414 VCAP_KEY_BIT_SET(MAC_ARP_ARP_TGT_MATCH
, arp
->dmac_match
);
415 VCAP_KEY_BIT_SET(MAC_ARP_ARP_SENDER_MATCH
, arp
->smac_match
);
416 VCAP_KEY_BIT_SET(MAC_ARP_ARP_OPCODE_UNKNOWN
, arp
->unknown
);
418 /* OPCODE is inverse, bit 0 is reply flag, bit 1 is RARP flag */
419 val
= ((arp
->req
== OCELOT_VCAP_BIT_0
? 1 : 0) |
420 (arp
->arp
== OCELOT_VCAP_BIT_0
? 2 : 0));
421 msk
= ((arp
->req
== OCELOT_VCAP_BIT_ANY
? 0 : 1) |
422 (arp
->arp
== OCELOT_VCAP_BIT_ANY
? 0 : 2));
423 VCAP_KEY_SET(MAC_ARP_ARP_OPCODE
, val
, msk
);
424 vcap_key_bytes_set(&data
, IS2_HKO_MAC_ARP_L3_IP4_DIP
,
425 arp
->dip
.value
.addr
, arp
->dip
.mask
.addr
, 4);
426 vcap_key_bytes_set(&data
, IS2_HKO_MAC_ARP_L3_IP4_SIP
,
427 arp
->sip
.value
.addr
, arp
->sip
.mask
.addr
, 4);
428 VCAP_KEY_ANY_SET(MAC_ARP_DIP_EQ_SIP
);
431 case OCELOT_ACE_TYPE_IPV4
:
432 case OCELOT_ACE_TYPE_IPV6
: {
433 enum ocelot_vcap_bit sip_eq_dip
, sport_eq_dport
, seq_zero
, tcp
;
434 enum ocelot_vcap_bit ttl
, fragment
, options
, tcp_ack
, tcp_urg
;
435 enum ocelot_vcap_bit tcp_fin
, tcp_syn
, tcp_rst
, tcp_psh
;
436 struct ocelot_ace_frame_ipv4
*ipv4
= NULL
;
437 struct ocelot_ace_frame_ipv6
*ipv6
= NULL
;
438 struct ocelot_vcap_udp_tcp
*sport
, *dport
;
439 struct ocelot_vcap_ipv4 sip
, dip
;
440 struct ocelot_vcap_u8 proto
, ds
;
441 struct ocelot_vcap_u48
*ip_data
;
443 if (ace
->type
== OCELOT_ACE_TYPE_IPV4
) {
444 ipv4
= &ace
->frame
.ipv4
;
446 fragment
= ipv4
->fragment
;
447 options
= ipv4
->options
;
450 ip_data
= &ipv4
->data
;
453 sport
= &ipv4
->sport
;
454 dport
= &ipv4
->dport
;
455 tcp_fin
= ipv4
->tcp_fin
;
456 tcp_syn
= ipv4
->tcp_syn
;
457 tcp_rst
= ipv4
->tcp_rst
;
458 tcp_psh
= ipv4
->tcp_psh
;
459 tcp_ack
= ipv4
->tcp_ack
;
460 tcp_urg
= ipv4
->tcp_urg
;
461 sip_eq_dip
= ipv4
->sip_eq_dip
;
462 sport_eq_dport
= ipv4
->sport_eq_dport
;
463 seq_zero
= ipv4
->seq_zero
;
465 ipv6
= &ace
->frame
.ipv6
;
467 fragment
= OCELOT_VCAP_BIT_ANY
;
468 options
= OCELOT_VCAP_BIT_ANY
;
471 ip_data
= &ipv6
->data
;
472 for (i
= 0; i
< 8; i
++) {
473 val
= ipv6
->sip
.value
[i
+ 8];
474 msk
= ipv6
->sip
.mask
[i
+ 8];
476 dip
.value
.addr
[i
] = val
;
477 dip
.mask
.addr
[i
] = msk
;
479 sip
.value
.addr
[i
- 4] = val
;
480 sip
.mask
.addr
[i
- 4] = msk
;
483 sport
= &ipv6
->sport
;
484 dport
= &ipv6
->dport
;
485 tcp_fin
= ipv6
->tcp_fin
;
486 tcp_syn
= ipv6
->tcp_syn
;
487 tcp_rst
= ipv6
->tcp_rst
;
488 tcp_psh
= ipv6
->tcp_psh
;
489 tcp_ack
= ipv6
->tcp_ack
;
490 tcp_urg
= ipv6
->tcp_urg
;
491 sip_eq_dip
= ipv6
->sip_eq_dip
;
492 sport_eq_dport
= ipv6
->sport_eq_dport
;
493 seq_zero
= ipv6
->seq_zero
;
496 VCAP_KEY_BIT_SET(IP4
,
497 ipv4
? OCELOT_VCAP_BIT_1
: OCELOT_VCAP_BIT_0
);
498 VCAP_KEY_BIT_SET(L3_FRAGMENT
, fragment
);
499 VCAP_KEY_ANY_SET(L3_FRAG_OFS_GT0
);
500 VCAP_KEY_BIT_SET(L3_OPTIONS
, options
);
501 VCAP_KEY_BIT_SET(L3_TTL_GT0
, ttl
);
502 VCAP_KEY_BYTES_SET(L3_TOS
, ds
.value
, ds
.mask
);
503 vcap_key_bytes_set(&data
, IS2_HKO_L3_IP4_DIP
, dip
.value
.addr
,
505 vcap_key_bytes_set(&data
, IS2_HKO_L3_IP4_SIP
, sip
.value
.addr
,
507 VCAP_KEY_BIT_SET(DIP_EQ_SIP
, sip_eq_dip
);
508 val
= proto
.value
[0];
510 type
= IS2_TYPE_IP_UDP_TCP
;
511 if (msk
== 0xff && (val
== 6 || val
== 17)) {
512 /* UDP/TCP protocol match */
514 OCELOT_VCAP_BIT_1
: OCELOT_VCAP_BIT_0
);
515 VCAP_KEY_BIT_SET(IP4_TCP_UDP_TCP
, tcp
);
516 vcap_key_l4_port_set(&data
,
517 IS2_HKO_IP4_TCP_UDP_L4_DPORT
,
519 vcap_key_l4_port_set(&data
,
520 IS2_HKO_IP4_TCP_UDP_L4_SPORT
,
522 VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_RNG
);
523 VCAP_KEY_BIT_SET(IP4_TCP_UDP_SPORT_EQ_DPORT
,
525 VCAP_KEY_BIT_SET(IP4_TCP_UDP_SEQUENCE_EQ0
, seq_zero
);
526 VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_FIN
, tcp_fin
);
527 VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_SYN
, tcp_syn
);
528 VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_RST
, tcp_rst
);
529 VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_PSH
, tcp_psh
);
530 VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_ACK
, tcp_ack
);
531 VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_URG
, tcp_urg
);
532 VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_DOM
);
533 VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_VER
);
536 /* Any IP protocol match */
537 type_mask
= IS2_TYPE_MASK_IP_ANY
;
539 /* Non-UDP/TCP protocol match */
540 type
= IS2_TYPE_IP_OTHER
;
541 for (i
= 0; i
< 6; i
++) {
542 payload
.value
[i
] = ip_data
->value
[i
];
543 payload
.mask
[i
] = ip_data
->mask
[i
];
546 VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PROTO
, proto
.value
,
548 VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PAYLOAD
, payload
.value
,
553 case OCELOT_ACE_TYPE_ANY
:
557 count
= (vcap_is2
.entry_width
/ 2);
558 for (i
= (IS2_HKO_PCP
+ IS2_HKL_PCP
); i
< count
;
560 /* Clear entry data */
561 vcap_key_set(&data
, i
, min(32u, count
- i
), 0, 0);
566 VCAP_KEY_SET(TYPE
, type
, type_mask
);
567 is2_action_set(&data
, ace
->action
);
568 vcap_data_set(data
.counter
, data
.counter_offset
, vcap_is2
.counter_width
,
572 vcap_entry2cache(ocelot
, &data
);
573 vcap_action2cache(ocelot
, &data
);
574 vcap_row_cmd(ocelot
, row
, VCAP_CMD_WRITE
, VCAP_SEL_ALL
);
577 static void is2_entry_get(struct ocelot_ace_rule
*rule
, int ix
)
579 struct ocelot
*op
= rule
->port
->ocelot
;
580 struct vcap_data data
;
584 vcap_row_cmd(op
, row
, VCAP_CMD_READ
, VCAP_SEL_COUNTER
);
585 vcap_cache2action(op
, &data
);
586 data
.tg_sw
= VCAP_TG_HALF
;
587 is2_data_get(&data
, ix
);
588 cnt
= vcap_data_get(data
.counter
, data
.counter_offset
,
589 vcap_is2
.counter_width
);
591 rule
->stats
.pkts
= cnt
;
594 static void ocelot_ace_rule_add(struct ocelot_acl_block
*block
,
595 struct ocelot_ace_rule
*rule
)
597 struct ocelot_ace_rule
*tmp
;
598 struct list_head
*pos
, *n
;
602 if (list_empty(&block
->rules
)) {
603 list_add(&rule
->list
, &block
->rules
);
607 list_for_each_safe(pos
, n
, &block
->rules
) {
608 tmp
= list_entry(pos
, struct ocelot_ace_rule
, list
);
609 if (rule
->prio
< tmp
->prio
)
612 list_add(&rule
->list
, pos
->prev
);
615 static int ocelot_ace_rule_get_index_id(struct ocelot_acl_block
*block
,
616 struct ocelot_ace_rule
*rule
)
618 struct ocelot_ace_rule
*tmp
;
621 list_for_each_entry(tmp
, &block
->rules
, list
) {
623 if (rule
->id
== tmp
->id
)
629 static struct ocelot_ace_rule
*
630 ocelot_ace_rule_get_rule_index(struct ocelot_acl_block
*block
, int index
)
632 struct ocelot_ace_rule
*tmp
;
635 list_for_each_entry(tmp
, &block
->rules
, list
) {
644 int ocelot_ace_rule_offload_add(struct ocelot_ace_rule
*rule
)
646 struct ocelot_ace_rule
*ace
;
649 /* Add rule to the linked list */
650 ocelot_ace_rule_add(acl_block
, rule
);
652 /* Get the index of the inserted rule */
653 index
= ocelot_ace_rule_get_index_id(acl_block
, rule
);
655 /* Move down the rules to make place for the new rule */
656 for (i
= acl_block
->count
- 1; i
> index
; i
--) {
657 ace
= ocelot_ace_rule_get_rule_index(acl_block
, i
);
658 is2_entry_set(rule
->port
->ocelot
, i
, ace
);
661 /* Now insert the new rule */
662 is2_entry_set(rule
->port
->ocelot
, index
, rule
);
666 static void ocelot_ace_rule_del(struct ocelot_acl_block
*block
,
667 struct ocelot_ace_rule
*rule
)
669 struct ocelot_ace_rule
*tmp
;
670 struct list_head
*pos
, *q
;
672 list_for_each_safe(pos
, q
, &block
->rules
) {
673 tmp
= list_entry(pos
, struct ocelot_ace_rule
, list
);
674 if (tmp
->id
== rule
->id
) {
683 int ocelot_ace_rule_offload_del(struct ocelot_ace_rule
*rule
)
685 struct ocelot_ace_rule del_ace
;
686 struct ocelot_ace_rule
*ace
;
689 memset(&del_ace
, 0, sizeof(del_ace
));
691 /* Gets index of the rule */
692 index
= ocelot_ace_rule_get_index_id(acl_block
, rule
);
695 ocelot_ace_rule_del(acl_block
, rule
);
697 /* Move up all the blocks over the deleted rule */
698 for (i
= index
; i
< acl_block
->count
; i
++) {
699 ace
= ocelot_ace_rule_get_rule_index(acl_block
, i
);
700 is2_entry_set(rule
->port
->ocelot
, i
, ace
);
703 /* Now delete the last rule, because it is duplicated */
704 is2_entry_set(rule
->port
->ocelot
, acl_block
->count
, &del_ace
);
709 int ocelot_ace_rule_stats_update(struct ocelot_ace_rule
*rule
)
711 struct ocelot_ace_rule
*tmp
;
714 index
= ocelot_ace_rule_get_index_id(acl_block
, rule
);
715 is2_entry_get(rule
, index
);
717 /* After we get the result we need to clear the counters */
718 tmp
= ocelot_ace_rule_get_rule_index(acl_block
, index
);
720 is2_entry_set(rule
->port
->ocelot
, index
, tmp
);
725 static struct ocelot_acl_block
*ocelot_acl_block_create(struct ocelot
*ocelot
)
727 struct ocelot_acl_block
*block
;
729 block
= kzalloc(sizeof(*block
), GFP_KERNEL
);
733 INIT_LIST_HEAD(&block
->rules
);
735 block
->ocelot
= ocelot
;
740 static void ocelot_acl_block_destroy(struct ocelot_acl_block
*block
)
745 int ocelot_ace_init(struct ocelot
*ocelot
)
747 struct vcap_data data
;
749 memset(&data
, 0, sizeof(data
));
750 vcap_entry2cache(ocelot
, &data
);
751 ocelot_write(ocelot
, vcap_is2
.entry_count
, S2_CORE_MV_CFG
);
752 vcap_cmd(ocelot
, 0, VCAP_CMD_INITIALIZE
, VCAP_SEL_ENTRY
);
754 vcap_action2cache(ocelot
, &data
);
755 ocelot_write(ocelot
, vcap_is2
.action_count
, S2_CORE_MV_CFG
);
756 vcap_cmd(ocelot
, 0, VCAP_CMD_INITIALIZE
,
757 VCAP_SEL_ACTION
| VCAP_SEL_COUNTER
);
759 /* Create a policer that will drop the frames for the cpu.
760 * This policer will be used as action in the acl rules to drop
763 ocelot_write_gix(ocelot
, 0x299, ANA_POL_MODE_CFG
,
764 OCELOT_POLICER_DISCARD
);
765 ocelot_write_gix(ocelot
, 0x1, ANA_POL_PIR_CFG
,
766 OCELOT_POLICER_DISCARD
);
767 ocelot_write_gix(ocelot
, 0x3fffff, ANA_POL_PIR_STATE
,
768 OCELOT_POLICER_DISCARD
);
769 ocelot_write_gix(ocelot
, 0x0, ANA_POL_CIR_CFG
,
770 OCELOT_POLICER_DISCARD
);
771 ocelot_write_gix(ocelot
, 0x3fffff, ANA_POL_CIR_STATE
,
772 OCELOT_POLICER_DISCARD
);
774 acl_block
= ocelot_acl_block_create(ocelot
);
779 void ocelot_ace_deinit(void)
781 ocelot_acl_block_destroy(acl_block
);