From a56d7a345dd67995ba415a26a0164a72780f2d02 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:06 +0200 Subject: net: mscc: ocelot: simplify tc-flower offload structures The ocelot tc-flower offload binds a second flow block callback (apart from the one for matchall) just because it uses a different block private structure (ocelot_port_private for matchall, ocelot_port_block for flower). But ocelot_port_block just appears to be boilerplate, and doesn't help with anything in particular at all, it's just useless glue between the (global!) struct ocelot_acl_block *block pointer, and a per-netdevice struct ocelot_port_private *priv. So let's just simplify that, and make struct ocelot_port_private be the private structure for the block offload. This makes us able to use the same flow callback as in the case of matchall. This also reveals that the struct ocelot_acl_block *block is used rather strangely, as mentioned above: it is defined globally, allocated at probe time, and freed at unbind time. So just move the structure to the main ocelot structure, which gives further opportunity for simplification. Also get rid of backpointers from struct ocelot_acl_block and struct ocelot_ace_rule back to struct ocelot, by reworking the function prototypes, where necessary, to use a more DSA-friendly "struct ocelot *ocelot, int port" format. And finally, remove the debugging prints that were added during development, since they provide no useful information at this point. Signed-off-by: Vladimir Oltean Tested-by: Horatiu Vultur Reviewed-by: Allan W. Nielsen Signed-off-by: David S. Miller --- include/soc/mscc/ocelot.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 068f96b1a83e..74e7c63adad4 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -406,6 +406,11 @@ struct ocelot_ops { int (*reset)(struct ocelot *ocelot); }; +struct ocelot_acl_block { + struct list_head rules; + int count; +}; + struct ocelot_port { struct ocelot *ocelot; @@ -455,6 +460,8 @@ struct ocelot { struct list_head multicast; + struct ocelot_acl_block acl_block; + /* Workqueue to check statistics for overflow with its lock */ struct mutex stats_lock; u64 *stats; -- cgit v1.2.3 From e0632940bc4c986f2dc9c8ee6aba65c14e30c762 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:10 +0200 Subject: net: mscc: ocelot: don't rely on preprocessor for vcap key/action packing The IGR_PORT_MASK key width is different between the 11-port VSC7514 and the 6-port VSC9959 switches. And since IGR_PORT_MASK is one of the first fields of a VCAP key entry, it means that all further field offset/length pairs are shifted between the 2. The ocelot driver performs packing of VCAP half keys with the help of some preprocessor macros: - A set of macros for defining the HKO (Half Key Offset) and HKL (Half Key Length) of each possible key field. The offset of each field is defined as the sum between the offset and the sum of the previous field. - A set of accessors on top of vcap_key_set for shorter (aka less typing) access to the HKO and HKL of each key field. Since the field offsets and lengths are different between switches, defining them through the preprocessor isn't going to fly. So introduce a structure holding (offset, length) pairs and instantiate it in ocelot_board.c for VSC7514. In a future patch, a similar structure will be instantiated in felix_vsc9959.c for NXP LS1028A. The accessors also need to go. They are based on macro name concatenation, which is horrible to understand and follow. Signed-off-by: Vladimir Oltean Tested-by: Horatiu Vultur Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot_ace.c | 315 +++++++++++++++--------- drivers/net/ethernet/mscc/ocelot_board.c | 102 ++++++++ drivers/net/ethernet/mscc/ocelot_vcap.h | 403 ------------------------------- include/soc/mscc/ocelot.h | 3 + include/soc/mscc/ocelot_vcap.h | 184 ++++++++++++++ 5 files changed, 484 insertions(+), 523 deletions(-) delete mode 100644 drivers/net/ethernet/mscc/ocelot_vcap.h create mode 100644 include/soc/mscc/ocelot_vcap.h (limited to 'include') diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c index ec86d29d8be4..9922033a2aaf 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.c +++ b/drivers/net/ethernet/mscc/ocelot_ace.c @@ -6,8 +6,8 @@ #include #include +#include #include "ocelot_ace.h" -#include "ocelot_vcap.h" #include "ocelot_s2.h" #define OCELOT_POLICER_DISCARD 0x17f @@ -47,7 +47,7 @@ static const struct vcap_props vcap_is2 = { .action_type_width = 1, .action_table = { { - .width = (IS2_AO_ACL_ID + IS2_AL_ACL_ID), + .width = 49, .count = 2 }, { @@ -243,22 +243,39 @@ static u32 vcap_data_get(u32 *data, u32 offset, u32 len) return value; } -static void vcap_key_set(struct vcap_data *data, u32 offset, u32 width, - u32 value, u32 mask) +static void vcap_key_field_set(struct vcap_data *data, u32 offset, u32 width, + u32 value, u32 mask) { vcap_data_set(data->entry, offset + data->key_offset, width, value); vcap_data_set(data->mask, offset + data->key_offset, width, mask); } -static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val, - u8 *msk, u32 count) +static void vcap_key_set(struct ocelot *ocelot, struct vcap_data *data, + enum vcap_is2_half_key_field field, + u32 value, u32 mask) +{ + u32 offset = ocelot->vcap_is2_keys[field].offset; + u32 length = ocelot->vcap_is2_keys[field].length; + + vcap_key_field_set(data, offset, length, value, mask); +} + +static void vcap_key_bytes_set(struct ocelot *ocelot, struct vcap_data *data, + enum vcap_is2_half_key_field field, + u8 *val, u8 *msk) { + u32 offset = ocelot->vcap_is2_keys[field].offset; + u32 count = ocelot->vcap_is2_keys[field].length; u32 i, j, n = 0, value = 0, mask = 0; + WARN_ON(count % 8); + /* 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. */ - offset += (count * 8); + offset += count; + count /= 8; + for (i = 0; i < count; i++) { j = (count - i - 1); value += (val[j] << n); @@ -266,7 +283,7 @@ static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val, n += 8; if (n == ENTRY_WIDTH || (i + 1) == count) { offset -= n; - vcap_key_set(data, offset, n, value, mask); + vcap_key_field_set(data, offset, n, value, mask); n = 0; value = 0; mask = 0; @@ -274,55 +291,62 @@ static void vcap_key_bytes_set(struct vcap_data *data, u32 offset, u8 *val, } } -static void vcap_key_l4_port_set(struct vcap_data *data, u32 offset, +static void vcap_key_l4_port_set(struct ocelot *ocelot, struct vcap_data *data, + enum vcap_is2_half_key_field field, struct ocelot_vcap_udp_tcp *port) { - vcap_key_set(data, offset, 16, port->value, port->mask); + u32 offset = ocelot->vcap_is2_keys[field].offset; + u32 length = ocelot->vcap_is2_keys[field].length; + + WARN_ON(length != 16); + + vcap_key_field_set(data, offset, length, port->value, port->mask); } -static void vcap_key_bit_set(struct vcap_data *data, u32 offset, +static void vcap_key_bit_set(struct ocelot *ocelot, struct vcap_data *data, + enum vcap_is2_half_key_field field, enum ocelot_vcap_bit val) { - vcap_key_set(data, offset, 1, val == OCELOT_VCAP_BIT_1 ? 1 : 0, - val == OCELOT_VCAP_BIT_ANY ? 0 : 1); -} + u32 offset = ocelot->vcap_is2_keys[field].offset; + u32 length = ocelot->vcap_is2_keys[field].length; + u32 value = (val == OCELOT_VCAP_BIT_1 ? 1 : 0); + u32 msk = (val == OCELOT_VCAP_BIT_ANY ? 0 : 1); -#define VCAP_KEY_SET(fld, val, msk) \ - vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, val, msk) -#define VCAP_KEY_ANY_SET(fld) \ - vcap_key_set(&data, IS2_HKO_##fld, IS2_HKL_##fld, 0, 0) -#define VCAP_KEY_BIT_SET(fld, val) vcap_key_bit_set(&data, IS2_HKO_##fld, val) -#define VCAP_KEY_BYTES_SET(fld, val, msk) \ - vcap_key_bytes_set(&data, IS2_HKO_##fld, val, msk, IS2_HKL_##fld / 8) + WARN_ON(length != 1); -static void vcap_action_set(struct vcap_data *data, u32 offset, u32 width, - u32 value) -{ - vcap_data_set(data->action, offset + data->action_offset, width, value); + vcap_key_field_set(data, offset, length, value, msk); } -#define VCAP_ACT_SET(fld, val) \ - vcap_action_set(data, IS2_AO_##fld, IS2_AL_##fld, val) +static void vcap_action_set(struct ocelot *ocelot, struct vcap_data *data, + enum vcap_is2_action_field field, u32 value) +{ + int offset = ocelot->vcap_is2_actions[field].offset; + int length = ocelot->vcap_is2_actions[field].length; + + vcap_data_set(data->action, offset + data->action_offset, length, + value); +} -static void is2_action_set(struct vcap_data *data, +static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data, enum ocelot_ace_action action) { switch (action) { case OCELOT_ACL_ACTION_DROP: - VCAP_ACT_SET(PORT_MASK, 0x0); - VCAP_ACT_SET(MASK_MODE, 0x1); - VCAP_ACT_SET(POLICE_ENA, 0x1); - VCAP_ACT_SET(POLICE_IDX, OCELOT_POLICER_DISCARD); - VCAP_ACT_SET(CPU_QU_NUM, 0x0); - VCAP_ACT_SET(CPU_COPY_ENA, 0x0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 1); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_ENA, 1); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_IDX, + OCELOT_POLICER_DISCARD); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 0); break; case OCELOT_ACL_ACTION_TRAP: - VCAP_ACT_SET(PORT_MASK, 0x0); - VCAP_ACT_SET(MASK_MODE, 0x1); - VCAP_ACT_SET(POLICE_ENA, 0x0); - VCAP_ACT_SET(POLICE_IDX, 0x0); - VCAP_ACT_SET(CPU_QU_NUM, 0x0); - VCAP_ACT_SET(CPU_COPY_ENA, 0x1); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_PORT_MASK, 0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_MASK_MODE, 1); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_ENA, 0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_POLICE_IDX, 0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_QU_NUM, 0); + vcap_action_set(ocelot, data, VCAP_IS2_ACT_CPU_COPY_ENA, 1); break; } } @@ -352,53 +376,69 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, data.type = IS2_ACTION_TYPE_NORMAL; - VCAP_KEY_ANY_SET(PAG); - VCAP_KEY_SET(IGR_PORT_MASK, 0, ~ace->ingress_port_mask); - VCAP_KEY_BIT_SET(FIRST, OCELOT_VCAP_BIT_1); - VCAP_KEY_BIT_SET(HOST_MATCH, OCELOT_VCAP_BIT_ANY); - VCAP_KEY_BIT_SET(L2_MC, ace->dmac_mc); - VCAP_KEY_BIT_SET(L2_BC, ace->dmac_bc); - VCAP_KEY_BIT_SET(VLAN_TAGGED, tag->tagged); - VCAP_KEY_SET(VID, tag->vid.value, tag->vid.mask); - VCAP_KEY_SET(PCP, tag->pcp.value[0], tag->pcp.mask[0]); - VCAP_KEY_BIT_SET(DEI, tag->dei); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_PAG, 0, 0); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_IGR_PORT_MASK, 0, + ~ace->ingress_port_mask); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_FIRST, OCELOT_VCAP_BIT_1); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_HOST_MATCH, + OCELOT_VCAP_BIT_ANY); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L2_MC, ace->dmac_mc); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L2_BC, ace->dmac_bc); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_VLAN_TAGGED, tag->tagged); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_VID, + tag->vid.value, tag->vid.mask); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_PCP, + tag->pcp.value[0], tag->pcp.mask[0]); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_DEI, tag->dei); switch (ace->type) { case OCELOT_ACE_TYPE_ETYPE: { struct ocelot_ace_frame_etype *etype = &ace->frame.etype; type = IS2_TYPE_ETYPE; - VCAP_KEY_BYTES_SET(L2_DMAC, etype->dmac.value, - etype->dmac.mask); - VCAP_KEY_BYTES_SET(L2_SMAC, etype->smac.value, - etype->smac.mask); - VCAP_KEY_BYTES_SET(MAC_ETYPE_ETYPE, etype->etype.value, - etype->etype.mask); - VCAP_KEY_ANY_SET(MAC_ETYPE_L2_PAYLOAD); // Clear unused bits - vcap_key_bytes_set(&data, IS2_HKO_MAC_ETYPE_L2_PAYLOAD, - etype->data.value, etype->data.mask, 2); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_DMAC, + etype->dmac.value, etype->dmac.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_SMAC, + etype->smac.value, etype->smac.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_ETYPE, + etype->etype.value, etype->etype.mask); + /* Clear unused bits */ + vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0, + 0, 0); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1, + 0, 0); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2, + 0, 0); + vcap_key_bytes_set(ocelot, &data, + VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0, + etype->data.value, etype->data.mask); break; } case OCELOT_ACE_TYPE_LLC: { struct ocelot_ace_frame_llc *llc = &ace->frame.llc; type = IS2_TYPE_LLC; - VCAP_KEY_BYTES_SET(L2_DMAC, llc->dmac.value, llc->dmac.mask); - VCAP_KEY_BYTES_SET(L2_SMAC, llc->smac.value, llc->smac.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_DMAC, + llc->dmac.value, llc->dmac.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_SMAC, + llc->smac.value, llc->smac.mask); for (i = 0; i < 4; i++) { payload.value[i] = llc->llc.value[i]; payload.mask[i] = llc->llc.mask[i]; } - VCAP_KEY_BYTES_SET(MAC_LLC_L2_LLC, payload.value, payload.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_LLC_L2_LLC, + payload.value, payload.mask); break; } case OCELOT_ACE_TYPE_SNAP: { struct ocelot_ace_frame_snap *snap = &ace->frame.snap; type = IS2_TYPE_SNAP; - VCAP_KEY_BYTES_SET(L2_DMAC, snap->dmac.value, snap->dmac.mask); - VCAP_KEY_BYTES_SET(L2_SMAC, snap->smac.value, snap->smac.mask); - VCAP_KEY_BYTES_SET(MAC_SNAP_L2_SNAP, + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_DMAC, + snap->dmac.value, snap->dmac.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L2_SMAC, + snap->smac.value, snap->smac.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_SNAP_L2_SNAP, ace->frame.snap.snap.value, ace->frame.snap.snap.mask); break; @@ -407,26 +447,42 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, struct ocelot_ace_frame_arp *arp = &ace->frame.arp; type = IS2_TYPE_ARP; - VCAP_KEY_BYTES_SET(MAC_ARP_L2_SMAC, arp->smac.value, - arp->smac.mask); - VCAP_KEY_BIT_SET(MAC_ARP_ARP_ADDR_SPACE_OK, arp->ethernet); - VCAP_KEY_BIT_SET(MAC_ARP_ARP_PROTO_SPACE_OK, arp->ip); - VCAP_KEY_BIT_SET(MAC_ARP_ARP_LEN_OK, arp->length); - VCAP_KEY_BIT_SET(MAC_ARP_ARP_TGT_MATCH, arp->dmac_match); - VCAP_KEY_BIT_SET(MAC_ARP_ARP_SENDER_MATCH, arp->smac_match); - VCAP_KEY_BIT_SET(MAC_ARP_ARP_OPCODE_UNKNOWN, arp->unknown); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_MAC_ARP_SMAC, + arp->smac.value, arp->smac.mask); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK, + arp->ethernet); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK, + arp->ip); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_LEN_OK, + arp->length); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_TARGET_MATCH, + arp->dmac_match); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_SENDER_MATCH, + arp->smac_match); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN, + arp->unknown); /* 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)); - VCAP_KEY_SET(MAC_ARP_ARP_OPCODE, val, msk); - vcap_key_bytes_set(&data, IS2_HKO_MAC_ARP_L3_IP4_DIP, - arp->dip.value.addr, arp->dip.mask.addr, 4); - vcap_key_bytes_set(&data, IS2_HKO_MAC_ARP_L3_IP4_SIP, - arp->sip.value.addr, arp->sip.mask.addr, 4); - VCAP_KEY_ANY_SET(MAC_ARP_DIP_EQ_SIP); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ARP_OPCODE, + val, msk); + vcap_key_bytes_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP, + arp->dip.value.addr, arp->dip.mask.addr); + vcap_key_bytes_set(ocelot, &data, + VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP, + arp->sip.value.addr, arp->sip.mask.addr); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP, + 0, 0); break; } case OCELOT_ACE_TYPE_IPV4: @@ -494,18 +550,23 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, seq_zero = ipv6->seq_zero; } - VCAP_KEY_BIT_SET(IP4, + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_IP4, ipv4 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); - VCAP_KEY_BIT_SET(L3_FRAGMENT, fragment); - VCAP_KEY_ANY_SET(L3_FRAG_OFS_GT0); - VCAP_KEY_BIT_SET(L3_OPTIONS, options); - VCAP_KEY_BIT_SET(L3_TTL_GT0, ttl); - VCAP_KEY_BYTES_SET(L3_TOS, ds.value, ds.mask); - vcap_key_bytes_set(&data, IS2_HKO_L3_IP4_DIP, dip.value.addr, - dip.mask.addr, 4); - vcap_key_bytes_set(&data, IS2_HKO_L3_IP4_SIP, sip.value.addr, - sip.mask.addr, 4); - VCAP_KEY_BIT_SET(DIP_EQ_SIP, sip_eq_dip); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L3_FRAGMENT, + fragment); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_L3_FRAG_OFS_GT0, 0, 0); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L3_OPTIONS, + options); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_IP4_L3_TTL_GT0, + ttl); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L3_TOS, + ds.value, ds.mask); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L3_IP4_DIP, + dip.value.addr, dip.mask.addr); + vcap_key_bytes_set(ocelot, &data, VCAP_IS2_HK_L3_IP4_SIP, + sip.value.addr, sip.mask.addr); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_DIP_EQ_SIP, + sip_eq_dip); val = proto.value[0]; msk = proto.mask[0]; type = IS2_TYPE_IP_UDP_TCP; @@ -513,25 +574,34 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, /* UDP/TCP protocol match */ tcp = (val == 6 ? OCELOT_VCAP_BIT_1 : OCELOT_VCAP_BIT_0); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_TCP, tcp); - vcap_key_l4_port_set(&data, - IS2_HKO_IP4_TCP_UDP_L4_DPORT, - dport); - vcap_key_l4_port_set(&data, - IS2_HKO_IP4_TCP_UDP_L4_SPORT, - sport); - VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_RNG); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_SPORT_EQ_DPORT, + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_TCP, tcp); + vcap_key_l4_port_set(ocelot, &data, + VCAP_IS2_HK_L4_DPORT, dport); + vcap_key_l4_port_set(ocelot, &data, + VCAP_IS2_HK_L4_SPORT, sport); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_L4_RNG, 0, 0); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_L4_SPORT_EQ_DPORT, sport_eq_dport); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_SEQUENCE_EQ0, seq_zero); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_FIN, tcp_fin); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_SYN, tcp_syn); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_RST, tcp_rst); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_PSH, tcp_psh); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_ACK, tcp_ack); - VCAP_KEY_BIT_SET(IP4_TCP_UDP_L4_URG, tcp_urg); - VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_DOM); - VCAP_KEY_ANY_SET(IP4_TCP_UDP_L4_1588_VER); + vcap_key_bit_set(ocelot, &data, + VCAP_IS2_HK_L4_SEQUENCE_EQ0, + seq_zero); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_FIN, + tcp_fin); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_SYN, + tcp_syn); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_RST, + tcp_rst); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_PSH, + tcp_psh); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_ACK, + tcp_ack); + vcap_key_bit_set(ocelot, &data, VCAP_IS2_HK_L4_URG, + tcp_urg); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_L4_1588_DOM, + 0, 0); + vcap_key_set(ocelot, &data, VCAP_IS2_HK_L4_1588_VER, + 0, 0); } else { if (msk == 0) { /* Any IP protocol match */ @@ -544,10 +614,12 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, payload.mask[i] = ip_data->mask[i]; } } - VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PROTO, proto.value, - proto.mask); - VCAP_KEY_BYTES_SET(IP4_OTHER_L3_PAYLOAD, payload.value, - payload.mask); + vcap_key_bytes_set(ocelot, &data, + VCAP_IS2_HK_IP4_L3_PROTO, + proto.value, proto.mask); + vcap_key_bytes_set(ocelot, &data, + VCAP_IS2_HK_L3_PAYLOAD, + payload.value, payload.mask); } break; } @@ -556,18 +628,20 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, type = 0; type_mask = 0; count = (vcap_is2.entry_width / 2); - for (i = (IS2_HKO_PCP + IS2_HKL_PCP); i < count; - i += ENTRY_WIDTH) { - /* Clear entry data */ - vcap_key_set(&data, i, min(32u, count - i), 0, 0); + /* Iterate over the non-common part of the key and + * clear entry data + */ + for (i = ocelot->vcap_is2_keys[VCAP_IS2_HK_L2_DMAC].offset; + i < count; i += ENTRY_WIDTH) { + vcap_key_field_set(&data, i, min(32u, count - i), 0, 0); } break; } - VCAP_KEY_SET(TYPE, type, type_mask); - is2_action_set(&data, ace->action); - vcap_data_set(data.counter, data.counter_offset, vcap_is2.counter_width, - ace->stats.pkts); + vcap_key_set(ocelot, &data, VCAP_IS2_TYPE, type, type_mask); + is2_action_set(ocelot, &data, ace->action); + vcap_data_set(data.counter, data.counter_offset, + vcap_is2.counter_width, ace->stats.pkts); /* Write row */ vcap_entry2cache(ocelot, &data); @@ -734,6 +808,7 @@ int ocelot_ace_init(struct ocelot *ocelot) struct vcap_data data; memset(&data, 0, sizeof(data)); + vcap_entry2cache(ocelot, &data); ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG); vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY); diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index 1135a18019c7..c236936dbde7 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -14,6 +14,7 @@ #include #include +#include #include "ocelot.h" #define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0)) @@ -262,6 +263,104 @@ static const struct ocelot_ops ocelot_ops = { .reset = ocelot_reset, }; +static const struct vcap_field vsc7514_vcap_is2_keys[] = { + /* Common: 46 bits */ + [VCAP_IS2_TYPE] = { 0, 4}, + [VCAP_IS2_HK_FIRST] = { 4, 1}, + [VCAP_IS2_HK_PAG] = { 5, 8}, + [VCAP_IS2_HK_IGR_PORT_MASK] = { 13, 12}, + [VCAP_IS2_HK_RSV2] = { 25, 1}, + [VCAP_IS2_HK_HOST_MATCH] = { 26, 1}, + [VCAP_IS2_HK_L2_MC] = { 27, 1}, + [VCAP_IS2_HK_L2_BC] = { 28, 1}, + [VCAP_IS2_HK_VLAN_TAGGED] = { 29, 1}, + [VCAP_IS2_HK_VID] = { 30, 12}, + [VCAP_IS2_HK_DEI] = { 42, 1}, + [VCAP_IS2_HK_PCP] = { 43, 3}, + /* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */ + [VCAP_IS2_HK_L2_DMAC] = { 46, 48}, + [VCAP_IS2_HK_L2_SMAC] = { 94, 48}, + /* MAC_ETYPE (TYPE=000) */ + [VCAP_IS2_HK_MAC_ETYPE_ETYPE] = {142, 16}, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0] = {158, 16}, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1] = {174, 8}, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2] = {182, 3}, + /* MAC_LLC (TYPE=001) */ + [VCAP_IS2_HK_MAC_LLC_L2_LLC] = {142, 40}, + /* MAC_SNAP (TYPE=010) */ + [VCAP_IS2_HK_MAC_SNAP_L2_SNAP] = {142, 40}, + /* MAC_ARP (TYPE=011) */ + [VCAP_IS2_HK_MAC_ARP_SMAC] = { 46, 48}, + [VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK] = { 94, 1}, + [VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK] = { 95, 1}, + [VCAP_IS2_HK_MAC_ARP_LEN_OK] = { 96, 1}, + [VCAP_IS2_HK_MAC_ARP_TARGET_MATCH] = { 97, 1}, + [VCAP_IS2_HK_MAC_ARP_SENDER_MATCH] = { 98, 1}, + [VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN] = { 99, 1}, + [VCAP_IS2_HK_MAC_ARP_OPCODE] = {100, 2}, + [VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP] = {102, 32}, + [VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP] = {134, 32}, + [VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP] = {166, 1}, + /* IP4_TCP_UDP / IP4_OTHER common */ + [VCAP_IS2_HK_IP4] = { 46, 1}, + [VCAP_IS2_HK_L3_FRAGMENT] = { 47, 1}, + [VCAP_IS2_HK_L3_FRAG_OFS_GT0] = { 48, 1}, + [VCAP_IS2_HK_L3_OPTIONS] = { 49, 1}, + [VCAP_IS2_HK_IP4_L3_TTL_GT0] = { 50, 1}, + [VCAP_IS2_HK_L3_TOS] = { 51, 8}, + [VCAP_IS2_HK_L3_IP4_DIP] = { 59, 32}, + [VCAP_IS2_HK_L3_IP4_SIP] = { 91, 32}, + [VCAP_IS2_HK_DIP_EQ_SIP] = {123, 1}, + /* IP4_TCP_UDP (TYPE=100) */ + [VCAP_IS2_HK_TCP] = {124, 1}, + [VCAP_IS2_HK_L4_SPORT] = {125, 16}, + [VCAP_IS2_HK_L4_DPORT] = {141, 16}, + [VCAP_IS2_HK_L4_RNG] = {157, 8}, + [VCAP_IS2_HK_L4_SPORT_EQ_DPORT] = {165, 1}, + [VCAP_IS2_HK_L4_SEQUENCE_EQ0] = {166, 1}, + [VCAP_IS2_HK_L4_URG] = {167, 1}, + [VCAP_IS2_HK_L4_ACK] = {168, 1}, + [VCAP_IS2_HK_L4_PSH] = {169, 1}, + [VCAP_IS2_HK_L4_RST] = {170, 1}, + [VCAP_IS2_HK_L4_SYN] = {171, 1}, + [VCAP_IS2_HK_L4_FIN] = {172, 1}, + [VCAP_IS2_HK_L4_1588_DOM] = {173, 8}, + [VCAP_IS2_HK_L4_1588_VER] = {181, 4}, + /* IP4_OTHER (TYPE=101) */ + [VCAP_IS2_HK_IP4_L3_PROTO] = {124, 8}, + [VCAP_IS2_HK_L3_PAYLOAD] = {132, 56}, + /* IP6_STD (TYPE=110) */ + [VCAP_IS2_HK_IP6_L3_TTL_GT0] = { 46, 1}, + [VCAP_IS2_HK_L3_IP6_SIP] = { 47, 128}, + [VCAP_IS2_HK_IP6_L3_PROTO] = {175, 8}, + /* OAM (TYPE=111) */ + [VCAP_IS2_HK_OAM_MEL_FLAGS] = {142, 7}, + [VCAP_IS2_HK_OAM_VER] = {149, 5}, + [VCAP_IS2_HK_OAM_OPCODE] = {154, 8}, + [VCAP_IS2_HK_OAM_FLAGS] = {162, 8}, + [VCAP_IS2_HK_OAM_MEPID] = {170, 16}, + [VCAP_IS2_HK_OAM_CCM_CNTS_EQ0] = {186, 1}, + [VCAP_IS2_HK_OAM_IS_Y1731] = {187, 1}, +}; + +static const struct vcap_field vsc7514_vcap_is2_actions[] = { + [VCAP_IS2_ACT_HIT_ME_ONCE] = { 0, 1}, + [VCAP_IS2_ACT_CPU_COPY_ENA] = { 1, 1}, + [VCAP_IS2_ACT_CPU_QU_NUM] = { 2, 3}, + [VCAP_IS2_ACT_MASK_MODE] = { 5, 2}, + [VCAP_IS2_ACT_MIRROR_ENA] = { 7, 1}, + [VCAP_IS2_ACT_LRN_DIS] = { 8, 1}, + [VCAP_IS2_ACT_POLICE_ENA] = { 9, 1}, + [VCAP_IS2_ACT_POLICE_IDX] = { 10, 9}, + [VCAP_IS2_ACT_POLICE_VCAP_ONLY] = { 19, 1}, + [VCAP_IS2_ACT_PORT_MASK] = { 20, 11}, + [VCAP_IS2_ACT_REW_OP] = { 31, 9}, + [VCAP_IS2_ACT_SMAC_REPLACE_ENA] = { 40, 1}, + [VCAP_IS2_ACT_RSV] = { 41, 2}, + [VCAP_IS2_ACT_ACL_ID] = { 43, 6}, + [VCAP_IS2_ACT_HIT_CNT] = { 49, 32}, +}; + static int mscc_ocelot_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -362,6 +461,9 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ocelot->ports = devm_kcalloc(&pdev->dev, ocelot->num_phys_ports, sizeof(struct ocelot_port *), GFP_KERNEL); + ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys; + ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions; + ocelot_init(ocelot); ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports, OCELOT_TAG_PREFIX_NONE, OCELOT_TAG_PREFIX_NONE); diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.h b/drivers/net/ethernet/mscc/ocelot_vcap.h deleted file mode 100644 index e22eac1da783..000000000000 --- a/drivers/net/ethernet/mscc/ocelot_vcap.h +++ /dev/null @@ -1,403 +0,0 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR MIT) - * Microsemi Ocelot Switch driver - * Copyright (c) 2019 Microsemi Corporation - */ - -#ifndef _OCELOT_VCAP_H_ -#define _OCELOT_VCAP_H_ - -/* ================================================================= - * VCAP Common - * ================================================================= - */ - -/* VCAP Type-Group values */ -#define VCAP_TG_NONE 0 /* Entry is invalid */ -#define VCAP_TG_FULL 1 /* Full entry */ -#define VCAP_TG_HALF 2 /* Half entry */ -#define VCAP_TG_QUARTER 3 /* Quarter entry */ - -/* ================================================================= - * VCAP IS2 - * ================================================================= - */ - -#define VCAP_IS2_CNT 64 -#define VCAP_IS2_ENTRY_WIDTH 376 -#define VCAP_IS2_ACTION_WIDTH 99 -#define VCAP_PORT_CNT 11 - -/* IS2 half key types */ -#define IS2_TYPE_ETYPE 0 -#define IS2_TYPE_LLC 1 -#define IS2_TYPE_SNAP 2 -#define IS2_TYPE_ARP 3 -#define IS2_TYPE_IP_UDP_TCP 4 -#define IS2_TYPE_IP_OTHER 5 -#define IS2_TYPE_IPV6 6 -#define IS2_TYPE_OAM 7 -#define IS2_TYPE_SMAC_SIP6 8 -#define IS2_TYPE_ANY 100 /* Pseudo type */ - -/* IS2 half key type mask for matching any IP */ -#define IS2_TYPE_MASK_IP_ANY 0xe - -/* IS2 action types */ -#define IS2_ACTION_TYPE_NORMAL 0 -#define IS2_ACTION_TYPE_SMAC_SIP 1 - -/* IS2 MASK_MODE values */ -#define IS2_ACT_MASK_MODE_NONE 0 -#define IS2_ACT_MASK_MODE_FILTER 1 -#define IS2_ACT_MASK_MODE_POLICY 2 -#define IS2_ACT_MASK_MODE_REDIR 3 - -/* IS2 REW_OP values */ -#define IS2_ACT_REW_OP_NONE 0 -#define IS2_ACT_REW_OP_PTP_ONE 2 -#define IS2_ACT_REW_OP_PTP_TWO 3 -#define IS2_ACT_REW_OP_SPECIAL 8 -#define IS2_ACT_REW_OP_PTP_ORG 9 -#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_1 (IS2_ACT_REW_OP_PTP_ONE | (1 << 3)) -#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_2 (IS2_ACT_REW_OP_PTP_ONE | (2 << 3)) -#define IS2_ACT_REW_OP_PTP_ONE_ADD_DELAY (IS2_ACT_REW_OP_PTP_ONE | (1 << 5)) -#define IS2_ACT_REW_OP_PTP_ONE_ADD_SUB BIT(7) - -#define VCAP_PORT_WIDTH 4 - -/* IS2 quarter key - SMAC_SIP4 */ -#define IS2_QKO_IGR_PORT 0 -#define IS2_QKL_IGR_PORT VCAP_PORT_WIDTH -#define IS2_QKO_L2_SMAC (IS2_QKO_IGR_PORT + IS2_QKL_IGR_PORT) -#define IS2_QKL_L2_SMAC 48 -#define IS2_QKO_L3_IP4_SIP (IS2_QKO_L2_SMAC + IS2_QKL_L2_SMAC) -#define IS2_QKL_L3_IP4_SIP 32 - -/* IS2 half key - common */ -#define IS2_HKO_TYPE 0 -#define IS2_HKL_TYPE 4 -#define IS2_HKO_FIRST (IS2_HKO_TYPE + IS2_HKL_TYPE) -#define IS2_HKL_FIRST 1 -#define IS2_HKO_PAG (IS2_HKO_FIRST + IS2_HKL_FIRST) -#define IS2_HKL_PAG 8 -#define IS2_HKO_IGR_PORT_MASK (IS2_HKO_PAG + IS2_HKL_PAG) -#define IS2_HKL_IGR_PORT_MASK (VCAP_PORT_CNT + 1) -#define IS2_HKO_SERVICE_FRM (IS2_HKO_IGR_PORT_MASK + IS2_HKL_IGR_PORT_MASK) -#define IS2_HKL_SERVICE_FRM 1 -#define IS2_HKO_HOST_MATCH (IS2_HKO_SERVICE_FRM + IS2_HKL_SERVICE_FRM) -#define IS2_HKL_HOST_MATCH 1 -#define IS2_HKO_L2_MC (IS2_HKO_HOST_MATCH + IS2_HKL_HOST_MATCH) -#define IS2_HKL_L2_MC 1 -#define IS2_HKO_L2_BC (IS2_HKO_L2_MC + IS2_HKL_L2_MC) -#define IS2_HKL_L2_BC 1 -#define IS2_HKO_VLAN_TAGGED (IS2_HKO_L2_BC + IS2_HKL_L2_BC) -#define IS2_HKL_VLAN_TAGGED 1 -#define IS2_HKO_VID (IS2_HKO_VLAN_TAGGED + IS2_HKL_VLAN_TAGGED) -#define IS2_HKL_VID 12 -#define IS2_HKO_DEI (IS2_HKO_VID + IS2_HKL_VID) -#define IS2_HKL_DEI 1 -#define IS2_HKO_PCP (IS2_HKO_DEI + IS2_HKL_DEI) -#define IS2_HKL_PCP 3 - -/* IS2 half key - MAC_ETYPE/MAC_LLC/MAC_SNAP/OAM common */ -#define IS2_HKO_L2_DMAC (IS2_HKO_PCP + IS2_HKL_PCP) -#define IS2_HKL_L2_DMAC 48 -#define IS2_HKO_L2_SMAC (IS2_HKO_L2_DMAC + IS2_HKL_L2_DMAC) -#define IS2_HKL_L2_SMAC 48 - -/* IS2 half key - MAC_ETYPE */ -#define IS2_HKO_MAC_ETYPE_ETYPE (IS2_HKO_L2_SMAC + IS2_HKL_L2_SMAC) -#define IS2_HKL_MAC_ETYPE_ETYPE 16 -#define IS2_HKO_MAC_ETYPE_L2_PAYLOAD \ - (IS2_HKO_MAC_ETYPE_ETYPE + IS2_HKL_MAC_ETYPE_ETYPE) -#define IS2_HKL_MAC_ETYPE_L2_PAYLOAD 27 - -/* IS2 half key - MAC_LLC */ -#define IS2_HKO_MAC_LLC_L2_LLC IS2_HKO_MAC_ETYPE_ETYPE -#define IS2_HKL_MAC_LLC_L2_LLC 40 - -/* IS2 half key - MAC_SNAP */ -#define IS2_HKO_MAC_SNAP_L2_SNAP IS2_HKO_MAC_ETYPE_ETYPE -#define IS2_HKL_MAC_SNAP_L2_SNAP 40 - -/* IS2 half key - ARP */ -#define IS2_HKO_MAC_ARP_L2_SMAC IS2_HKO_L2_DMAC -#define IS2_HKL_MAC_ARP_L2_SMAC 48 -#define IS2_HKO_MAC_ARP_ARP_ADDR_SPACE_OK \ - (IS2_HKO_MAC_ARP_L2_SMAC + IS2_HKL_MAC_ARP_L2_SMAC) -#define IS2_HKL_MAC_ARP_ARP_ADDR_SPACE_OK 1 -#define IS2_HKO_MAC_ARP_ARP_PROTO_SPACE_OK \ - (IS2_HKO_MAC_ARP_ARP_ADDR_SPACE_OK + IS2_HKL_MAC_ARP_ARP_ADDR_SPACE_OK) -#define IS2_HKL_MAC_ARP_ARP_PROTO_SPACE_OK 1 -#define IS2_HKO_MAC_ARP_ARP_LEN_OK \ - (IS2_HKO_MAC_ARP_ARP_PROTO_SPACE_OK + \ - IS2_HKL_MAC_ARP_ARP_PROTO_SPACE_OK) -#define IS2_HKL_MAC_ARP_ARP_LEN_OK 1 -#define IS2_HKO_MAC_ARP_ARP_TGT_MATCH \ - (IS2_HKO_MAC_ARP_ARP_LEN_OK + IS2_HKL_MAC_ARP_ARP_LEN_OK) -#define IS2_HKL_MAC_ARP_ARP_TGT_MATCH 1 -#define IS2_HKO_MAC_ARP_ARP_SENDER_MATCH \ - (IS2_HKO_MAC_ARP_ARP_TGT_MATCH + IS2_HKL_MAC_ARP_ARP_TGT_MATCH) -#define IS2_HKL_MAC_ARP_ARP_SENDER_MATCH 1 -#define IS2_HKO_MAC_ARP_ARP_OPCODE_UNKNOWN \ - (IS2_HKO_MAC_ARP_ARP_SENDER_MATCH + IS2_HKL_MAC_ARP_ARP_SENDER_MATCH) -#define IS2_HKL_MAC_ARP_ARP_OPCODE_UNKNOWN 1 -#define IS2_HKO_MAC_ARP_ARP_OPCODE \ - (IS2_HKO_MAC_ARP_ARP_OPCODE_UNKNOWN + \ - IS2_HKL_MAC_ARP_ARP_OPCODE_UNKNOWN) -#define IS2_HKL_MAC_ARP_ARP_OPCODE 2 -#define IS2_HKO_MAC_ARP_L3_IP4_DIP \ - (IS2_HKO_MAC_ARP_ARP_OPCODE + IS2_HKL_MAC_ARP_ARP_OPCODE) -#define IS2_HKL_MAC_ARP_L3_IP4_DIP 32 -#define IS2_HKO_MAC_ARP_L3_IP4_SIP \ - (IS2_HKO_MAC_ARP_L3_IP4_DIP + IS2_HKL_MAC_ARP_L3_IP4_DIP) -#define IS2_HKL_MAC_ARP_L3_IP4_SIP 32 -#define IS2_HKO_MAC_ARP_DIP_EQ_SIP \ - (IS2_HKO_MAC_ARP_L3_IP4_SIP + IS2_HKL_MAC_ARP_L3_IP4_SIP) -#define IS2_HKL_MAC_ARP_DIP_EQ_SIP 1 - -/* IS2 half key - IP4_TCP_UDP/IP4_OTHER common */ -#define IS2_HKO_IP4 IS2_HKO_L2_DMAC -#define IS2_HKL_IP4 1 -#define IS2_HKO_L3_FRAGMENT (IS2_HKO_IP4 + IS2_HKL_IP4) -#define IS2_HKL_L3_FRAGMENT 1 -#define IS2_HKO_L3_FRAG_OFS_GT0 (IS2_HKO_L3_FRAGMENT + IS2_HKL_L3_FRAGMENT) -#define IS2_HKL_L3_FRAG_OFS_GT0 1 -#define IS2_HKO_L3_OPTIONS (IS2_HKO_L3_FRAG_OFS_GT0 + IS2_HKL_L3_FRAG_OFS_GT0) -#define IS2_HKL_L3_OPTIONS 1 -#define IS2_HKO_L3_TTL_GT0 (IS2_HKO_L3_OPTIONS + IS2_HKL_L3_OPTIONS) -#define IS2_HKL_L3_TTL_GT0 1 -#define IS2_HKO_L3_TOS (IS2_HKO_L3_TTL_GT0 + IS2_HKL_L3_TTL_GT0) -#define IS2_HKL_L3_TOS 8 -#define IS2_HKO_L3_IP4_DIP (IS2_HKO_L3_TOS + IS2_HKL_L3_TOS) -#define IS2_HKL_L3_IP4_DIP 32 -#define IS2_HKO_L3_IP4_SIP (IS2_HKO_L3_IP4_DIP + IS2_HKL_L3_IP4_DIP) -#define IS2_HKL_L3_IP4_SIP 32 -#define IS2_HKO_DIP_EQ_SIP (IS2_HKO_L3_IP4_SIP + IS2_HKL_L3_IP4_SIP) -#define IS2_HKL_DIP_EQ_SIP 1 - -/* IS2 half key - IP4_TCP_UDP */ -#define IS2_HKO_IP4_TCP_UDP_TCP (IS2_HKO_DIP_EQ_SIP + IS2_HKL_DIP_EQ_SIP) -#define IS2_HKL_IP4_TCP_UDP_TCP 1 -#define IS2_HKO_IP4_TCP_UDP_L4_DPORT \ - (IS2_HKO_IP4_TCP_UDP_TCP + IS2_HKL_IP4_TCP_UDP_TCP) -#define IS2_HKL_IP4_TCP_UDP_L4_DPORT 16 -#define IS2_HKO_IP4_TCP_UDP_L4_SPORT \ - (IS2_HKO_IP4_TCP_UDP_L4_DPORT + IS2_HKL_IP4_TCP_UDP_L4_DPORT) -#define IS2_HKL_IP4_TCP_UDP_L4_SPORT 16 -#define IS2_HKO_IP4_TCP_UDP_L4_RNG \ - (IS2_HKO_IP4_TCP_UDP_L4_SPORT + IS2_HKL_IP4_TCP_UDP_L4_SPORT) -#define IS2_HKL_IP4_TCP_UDP_L4_RNG 8 -#define IS2_HKO_IP4_TCP_UDP_SPORT_EQ_DPORT \ - (IS2_HKO_IP4_TCP_UDP_L4_RNG + IS2_HKL_IP4_TCP_UDP_L4_RNG) -#define IS2_HKL_IP4_TCP_UDP_SPORT_EQ_DPORT 1 -#define IS2_HKO_IP4_TCP_UDP_SEQUENCE_EQ0 \ - (IS2_HKO_IP4_TCP_UDP_SPORT_EQ_DPORT + \ - IS2_HKL_IP4_TCP_UDP_SPORT_EQ_DPORT) -#define IS2_HKL_IP4_TCP_UDP_SEQUENCE_EQ0 1 -#define IS2_HKO_IP4_TCP_UDP_L4_FIN \ - (IS2_HKO_IP4_TCP_UDP_SEQUENCE_EQ0 + IS2_HKL_IP4_TCP_UDP_SEQUENCE_EQ0) -#define IS2_HKL_IP4_TCP_UDP_L4_FIN 1 -#define IS2_HKO_IP4_TCP_UDP_L4_SYN \ - (IS2_HKO_IP4_TCP_UDP_L4_FIN + IS2_HKL_IP4_TCP_UDP_L4_FIN) -#define IS2_HKL_IP4_TCP_UDP_L4_SYN 1 -#define IS2_HKO_IP4_TCP_UDP_L4_RST \ - (IS2_HKO_IP4_TCP_UDP_L4_SYN + IS2_HKL_IP4_TCP_UDP_L4_SYN) -#define IS2_HKL_IP4_TCP_UDP_L4_RST 1 -#define IS2_HKO_IP4_TCP_UDP_L4_PSH \ - (IS2_HKO_IP4_TCP_UDP_L4_RST + IS2_HKL_IP4_TCP_UDP_L4_RST) -#define IS2_HKL_IP4_TCP_UDP_L4_PSH 1 -#define IS2_HKO_IP4_TCP_UDP_L4_ACK \ - (IS2_HKO_IP4_TCP_UDP_L4_PSH + IS2_HKL_IP4_TCP_UDP_L4_PSH) -#define IS2_HKL_IP4_TCP_UDP_L4_ACK 1 -#define IS2_HKO_IP4_TCP_UDP_L4_URG \ - (IS2_HKO_IP4_TCP_UDP_L4_ACK + IS2_HKL_IP4_TCP_UDP_L4_ACK) -#define IS2_HKL_IP4_TCP_UDP_L4_URG 1 -#define IS2_HKO_IP4_TCP_UDP_L4_1588_DOM \ - (IS2_HKO_IP4_TCP_UDP_L4_URG + IS2_HKL_IP4_TCP_UDP_L4_URG) -#define IS2_HKL_IP4_TCP_UDP_L4_1588_DOM 8 -#define IS2_HKO_IP4_TCP_UDP_L4_1588_VER \ - (IS2_HKO_IP4_TCP_UDP_L4_1588_DOM + IS2_HKL_IP4_TCP_UDP_L4_1588_DOM) -#define IS2_HKL_IP4_TCP_UDP_L4_1588_VER 4 - -/* IS2 half key - IP4_OTHER */ -#define IS2_HKO_IP4_OTHER_L3_PROTO IS2_HKO_IP4_TCP_UDP_TCP -#define IS2_HKL_IP4_OTHER_L3_PROTO 8 -#define IS2_HKO_IP4_OTHER_L3_PAYLOAD \ - (IS2_HKO_IP4_OTHER_L3_PROTO + IS2_HKL_IP4_OTHER_L3_PROTO) -#define IS2_HKL_IP4_OTHER_L3_PAYLOAD 56 - -/* IS2 half key - IP6_STD */ -#define IS2_HKO_IP6_STD_L3_TTL_GT0 IS2_HKO_L2_DMAC -#define IS2_HKL_IP6_STD_L3_TTL_GT0 1 -#define IS2_HKO_IP6_STD_L3_IP6_SIP \ - (IS2_HKO_IP6_STD_L3_TTL_GT0 + IS2_HKL_IP6_STD_L3_TTL_GT0) -#define IS2_HKL_IP6_STD_L3_IP6_SIP 128 -#define IS2_HKO_IP6_STD_L3_PROTO \ - (IS2_HKO_IP6_STD_L3_IP6_SIP + IS2_HKL_IP6_STD_L3_IP6_SIP) -#define IS2_HKL_IP6_STD_L3_PROTO 8 - -/* IS2 half key - OAM */ -#define IS2_HKO_OAM_OAM_MEL_FLAGS IS2_HKO_MAC_ETYPE_ETYPE -#define IS2_HKL_OAM_OAM_MEL_FLAGS 7 -#define IS2_HKO_OAM_OAM_VER \ - (IS2_HKO_OAM_OAM_MEL_FLAGS + IS2_HKL_OAM_OAM_MEL_FLAGS) -#define IS2_HKL_OAM_OAM_VER 5 -#define IS2_HKO_OAM_OAM_OPCODE (IS2_HKO_OAM_OAM_VER + IS2_HKL_OAM_OAM_VER) -#define IS2_HKL_OAM_OAM_OPCODE 8 -#define IS2_HKO_OAM_OAM_FLAGS (IS2_HKO_OAM_OAM_OPCODE + IS2_HKL_OAM_OAM_OPCODE) -#define IS2_HKL_OAM_OAM_FLAGS 8 -#define IS2_HKO_OAM_OAM_MEPID (IS2_HKO_OAM_OAM_FLAGS + IS2_HKL_OAM_OAM_FLAGS) -#define IS2_HKL_OAM_OAM_MEPID 16 -#define IS2_HKO_OAM_OAM_CCM_CNTS_EQ0 \ - (IS2_HKO_OAM_OAM_MEPID + IS2_HKL_OAM_OAM_MEPID) -#define IS2_HKL_OAM_OAM_CCM_CNTS_EQ0 1 - -/* IS2 half key - SMAC_SIP6 */ -#define IS2_HKO_SMAC_SIP6_IGR_PORT IS2_HKL_TYPE -#define IS2_HKL_SMAC_SIP6_IGR_PORT VCAP_PORT_WIDTH -#define IS2_HKO_SMAC_SIP6_L2_SMAC \ - (IS2_HKO_SMAC_SIP6_IGR_PORT + IS2_HKL_SMAC_SIP6_IGR_PORT) -#define IS2_HKL_SMAC_SIP6_L2_SMAC 48 -#define IS2_HKO_SMAC_SIP6_L3_IP6_SIP \ - (IS2_HKO_SMAC_SIP6_L2_SMAC + IS2_HKL_SMAC_SIP6_L2_SMAC) -#define IS2_HKL_SMAC_SIP6_L3_IP6_SIP 128 - -/* IS2 full key - common */ -#define IS2_FKO_TYPE 0 -#define IS2_FKL_TYPE 2 -#define IS2_FKO_FIRST (IS2_FKO_TYPE + IS2_FKL_TYPE) -#define IS2_FKL_FIRST 1 -#define IS2_FKO_PAG (IS2_FKO_FIRST + IS2_FKL_FIRST) -#define IS2_FKL_PAG 8 -#define IS2_FKO_IGR_PORT_MASK (IS2_FKO_PAG + IS2_FKL_PAG) -#define IS2_FKL_IGR_PORT_MASK (VCAP_PORT_CNT + 1) -#define IS2_FKO_SERVICE_FRM (IS2_FKO_IGR_PORT_MASK + IS2_FKL_IGR_PORT_MASK) -#define IS2_FKL_SERVICE_FRM 1 -#define IS2_FKO_HOST_MATCH (IS2_FKO_SERVICE_FRM + IS2_FKL_SERVICE_FRM) -#define IS2_FKL_HOST_MATCH 1 -#define IS2_FKO_L2_MC (IS2_FKO_HOST_MATCH + IS2_FKL_HOST_MATCH) -#define IS2_FKL_L2_MC 1 -#define IS2_FKO_L2_BC (IS2_FKO_L2_MC + IS2_FKL_L2_MC) -#define IS2_FKL_L2_BC 1 -#define IS2_FKO_VLAN_TAGGED (IS2_FKO_L2_BC + IS2_FKL_L2_BC) -#define IS2_FKL_VLAN_TAGGED 1 -#define IS2_FKO_VID (IS2_FKO_VLAN_TAGGED + IS2_FKL_VLAN_TAGGED) -#define IS2_FKL_VID 12 -#define IS2_FKO_DEI (IS2_FKO_VID + IS2_FKL_VID) -#define IS2_FKL_DEI 1 -#define IS2_FKO_PCP (IS2_FKO_DEI + IS2_FKL_DEI) -#define IS2_FKL_PCP 3 - -/* IS2 full key - IP6_TCP_UDP/IP6_OTHER common */ -#define IS2_FKO_L3_TTL_GT0 (IS2_FKO_PCP + IS2_FKL_PCP) -#define IS2_FKL_L3_TTL_GT0 1 -#define IS2_FKO_L3_TOS (IS2_FKO_L3_TTL_GT0 + IS2_FKL_L3_TTL_GT0) -#define IS2_FKL_L3_TOS 8 -#define IS2_FKO_L3_IP6_DIP (IS2_FKO_L3_TOS + IS2_FKL_L3_TOS) -#define IS2_FKL_L3_IP6_DIP 128 -#define IS2_FKO_L3_IP6_SIP (IS2_FKO_L3_IP6_DIP + IS2_FKL_L3_IP6_DIP) -#define IS2_FKL_L3_IP6_SIP 128 -#define IS2_FKO_DIP_EQ_SIP (IS2_FKO_L3_IP6_SIP + IS2_FKL_L3_IP6_SIP) -#define IS2_FKL_DIP_EQ_SIP 1 - -/* IS2 full key - IP6_TCP_UDP */ -#define IS2_FKO_IP6_TCP_UDP_TCP (IS2_FKO_DIP_EQ_SIP + IS2_FKL_DIP_EQ_SIP) -#define IS2_FKL_IP6_TCP_UDP_TCP 1 -#define IS2_FKO_IP6_TCP_UDP_L4_DPORT \ - (IS2_FKO_IP6_TCP_UDP_TCP + IS2_FKL_IP6_TCP_UDP_TCP) -#define IS2_FKL_IP6_TCP_UDP_L4_DPORT 16 -#define IS2_FKO_IP6_TCP_UDP_L4_SPORT \ - (IS2_FKO_IP6_TCP_UDP_L4_DPORT + IS2_FKL_IP6_TCP_UDP_L4_DPORT) -#define IS2_FKL_IP6_TCP_UDP_L4_SPORT 16 -#define IS2_FKO_IP6_TCP_UDP_L4_RNG \ - (IS2_FKO_IP6_TCP_UDP_L4_SPORT + IS2_FKL_IP6_TCP_UDP_L4_SPORT) -#define IS2_FKL_IP6_TCP_UDP_L4_RNG 8 -#define IS2_FKO_IP6_TCP_UDP_SPORT_EQ_DPORT \ - (IS2_FKO_IP6_TCP_UDP_L4_RNG + IS2_FKL_IP6_TCP_UDP_L4_RNG) -#define IS2_FKL_IP6_TCP_UDP_SPORT_EQ_DPORT 1 -#define IS2_FKO_IP6_TCP_UDP_SEQUENCE_EQ0 \ - (IS2_FKO_IP6_TCP_UDP_SPORT_EQ_DPORT + \ - IS2_FKL_IP6_TCP_UDP_SPORT_EQ_DPORT) -#define IS2_FKL_IP6_TCP_UDP_SEQUENCE_EQ0 1 -#define IS2_FKO_IP6_TCP_UDP_L4_FIN \ - (IS2_FKO_IP6_TCP_UDP_SEQUENCE_EQ0 + IS2_FKL_IP6_TCP_UDP_SEQUENCE_EQ0) -#define IS2_FKL_IP6_TCP_UDP_L4_FIN 1 -#define IS2_FKO_IP6_TCP_UDP_L4_SYN \ - (IS2_FKO_IP6_TCP_UDP_L4_FIN + IS2_FKL_IP6_TCP_UDP_L4_FIN) -#define IS2_FKL_IP6_TCP_UDP_L4_SYN 1 -#define IS2_FKO_IP6_TCP_UDP_L4_RST \ - (IS2_FKO_IP6_TCP_UDP_L4_SYN + IS2_FKL_IP6_TCP_UDP_L4_SYN) -#define IS2_FKL_IP6_TCP_UDP_L4_RST 1 -#define IS2_FKO_IP6_TCP_UDP_L4_PSH \ - (IS2_FKO_IP6_TCP_UDP_L4_RST + IS2_FKL_IP6_TCP_UDP_L4_RST) -#define IS2_FKL_IP6_TCP_UDP_L4_PSH 1 -#define IS2_FKO_IP6_TCP_UDP_L4_ACK \ - (IS2_FKO_IP6_TCP_UDP_L4_PSH + IS2_FKL_IP6_TCP_UDP_L4_PSH) -#define IS2_FKL_IP6_TCP_UDP_L4_ACK 1 -#define IS2_FKO_IP6_TCP_UDP_L4_URG \ - (IS2_FKO_IP6_TCP_UDP_L4_ACK + IS2_FKL_IP6_TCP_UDP_L4_ACK) -#define IS2_FKL_IP6_TCP_UDP_L4_URG 1 -#define IS2_FKO_IP6_TCP_UDP_L4_1588_DOM \ - (IS2_FKO_IP6_TCP_UDP_L4_URG + IS2_FKL_IP6_TCP_UDP_L4_URG) -#define IS2_FKL_IP6_TCP_UDP_L4_1588_DOM 8 -#define IS2_FKO_IP6_TCP_UDP_L4_1588_VER \ - (IS2_FKO_IP6_TCP_UDP_L4_1588_DOM + IS2_FKL_IP6_TCP_UDP_L4_1588_DOM) -#define IS2_FKL_IP6_TCP_UDP_L4_1588_VER 4 - -/* IS2 full key - IP6_OTHER */ -#define IS2_FKO_IP6_OTHER_L3_PROTO IS2_FKO_IP6_TCP_UDP_TCP -#define IS2_FKL_IP6_OTHER_L3_PROTO 8 -#define IS2_FKO_IP6_OTHER_L3_PAYLOAD \ - (IS2_FKO_IP6_OTHER_L3_PROTO + IS2_FKL_IP6_OTHER_L3_PROTO) -#define IS2_FKL_IP6_OTHER_L3_PAYLOAD 56 - -/* IS2 full key - CUSTOM */ -#define IS2_FKO_CUSTOM_CUSTOM_TYPE IS2_FKO_L3_TTL_GT0 -#define IS2_FKL_CUSTOM_CUSTOM_TYPE 1 -#define IS2_FKO_CUSTOM_CUSTOM \ - (IS2_FKO_CUSTOM_CUSTOM_TYPE + IS2_FKL_CUSTOM_CUSTOM_TYPE) -#define IS2_FKL_CUSTOM_CUSTOM 320 - -/* IS2 action - BASE_TYPE */ -#define IS2_AO_HIT_ME_ONCE 0 -#define IS2_AL_HIT_ME_ONCE 1 -#define IS2_AO_CPU_COPY_ENA (IS2_AO_HIT_ME_ONCE + IS2_AL_HIT_ME_ONCE) -#define IS2_AL_CPU_COPY_ENA 1 -#define IS2_AO_CPU_QU_NUM (IS2_AO_CPU_COPY_ENA + IS2_AL_CPU_COPY_ENA) -#define IS2_AL_CPU_QU_NUM 3 -#define IS2_AO_MASK_MODE (IS2_AO_CPU_QU_NUM + IS2_AL_CPU_QU_NUM) -#define IS2_AL_MASK_MODE 2 -#define IS2_AO_MIRROR_ENA (IS2_AO_MASK_MODE + IS2_AL_MASK_MODE) -#define IS2_AL_MIRROR_ENA 1 -#define IS2_AO_LRN_DIS (IS2_AO_MIRROR_ENA + IS2_AL_MIRROR_ENA) -#define IS2_AL_LRN_DIS 1 -#define IS2_AO_POLICE_ENA (IS2_AO_LRN_DIS + IS2_AL_LRN_DIS) -#define IS2_AL_POLICE_ENA 1 -#define IS2_AO_POLICE_IDX (IS2_AO_POLICE_ENA + IS2_AL_POLICE_ENA) -#define IS2_AL_POLICE_IDX 9 -#define IS2_AO_POLICE_VCAP_ONLY (IS2_AO_POLICE_IDX + IS2_AL_POLICE_IDX) -#define IS2_AL_POLICE_VCAP_ONLY 1 -#define IS2_AO_PORT_MASK (IS2_AO_POLICE_VCAP_ONLY + IS2_AL_POLICE_VCAP_ONLY) -#define IS2_AL_PORT_MASK VCAP_PORT_CNT -#define IS2_AO_REW_OP (IS2_AO_PORT_MASK + IS2_AL_PORT_MASK) -#define IS2_AL_REW_OP 9 -#define IS2_AO_LM_CNT_DIS (IS2_AO_REW_OP + IS2_AL_REW_OP) -#define IS2_AL_LM_CNT_DIS 1 -#define IS2_AO_ISDX_ENA \ - (IS2_AO_LM_CNT_DIS + IS2_AL_LM_CNT_DIS + 1) /* Reserved bit */ -#define IS2_AL_ISDX_ENA 1 -#define IS2_AO_ACL_ID (IS2_AO_ISDX_ENA + IS2_AL_ISDX_ENA) -#define IS2_AL_ACL_ID 6 - -/* IS2 action - SMAC_SIP */ -#define IS2_AO_SMAC_SIP_CPU_COPY_ENA 0 -#define IS2_AL_SMAC_SIP_CPU_COPY_ENA 1 -#define IS2_AO_SMAC_SIP_CPU_QU_NUM 1 -#define IS2_AL_SMAC_SIP_CPU_QU_NUM 3 -#define IS2_AO_SMAC_SIP_FWD_KILL_ENA 4 -#define IS2_AL_SMAC_SIP_FWD_KILL_ENA 1 -#define IS2_AO_SMAC_SIP_HOST_MATCH 5 -#define IS2_AL_SMAC_SIP_HOST_MATCH 1 - -#endif /* _OCELOT_VCAP_H_ */ diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 74e7c63adad4..3da8285d4cd8 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -462,6 +462,9 @@ struct ocelot { struct ocelot_acl_block acl_block; + const struct vcap_field *vcap_is2_keys; + const struct vcap_field *vcap_is2_actions; + /* Workqueue to check statistics for overflow with its lock */ struct mutex stats_lock; u64 *stats; diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h new file mode 100644 index 000000000000..0783f0ffc813 --- /dev/null +++ b/include/soc/mscc/ocelot_vcap.h @@ -0,0 +1,184 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR MIT) + * Microsemi Ocelot Switch driver + * Copyright (c) 2019 Microsemi Corporation + */ + +#ifndef _OCELOT_VCAP_H_ +#define _OCELOT_VCAP_H_ + +/* ================================================================= + * VCAP Common + * ================================================================= + */ + +/* VCAP Type-Group values */ +#define VCAP_TG_NONE 0 /* Entry is invalid */ +#define VCAP_TG_FULL 1 /* Full entry */ +#define VCAP_TG_HALF 2 /* Half entry */ +#define VCAP_TG_QUARTER 3 /* Quarter entry */ + +/* ================================================================= + * VCAP IS2 + * ================================================================= + */ + +#define VCAP_IS2_CNT 64 +#define VCAP_IS2_ENTRY_WIDTH 376 +#define VCAP_IS2_ACTION_WIDTH 99 +#define VCAP_PORT_CNT 11 + +/* IS2 half key types */ +#define IS2_TYPE_ETYPE 0 +#define IS2_TYPE_LLC 1 +#define IS2_TYPE_SNAP 2 +#define IS2_TYPE_ARP 3 +#define IS2_TYPE_IP_UDP_TCP 4 +#define IS2_TYPE_IP_OTHER 5 +#define IS2_TYPE_IPV6 6 +#define IS2_TYPE_OAM 7 +#define IS2_TYPE_SMAC_SIP6 8 +#define IS2_TYPE_ANY 100 /* Pseudo type */ + +/* IS2 half key type mask for matching any IP */ +#define IS2_TYPE_MASK_IP_ANY 0xe + +/* IS2 action types */ +#define IS2_ACTION_TYPE_NORMAL 0 +#define IS2_ACTION_TYPE_SMAC_SIP 1 + +/* IS2 MASK_MODE values */ +#define IS2_ACT_MASK_MODE_NONE 0 +#define IS2_ACT_MASK_MODE_FILTER 1 +#define IS2_ACT_MASK_MODE_POLICY 2 +#define IS2_ACT_MASK_MODE_REDIR 3 + +/* IS2 REW_OP values */ +#define IS2_ACT_REW_OP_NONE 0 +#define IS2_ACT_REW_OP_PTP_ONE 2 +#define IS2_ACT_REW_OP_PTP_TWO 3 +#define IS2_ACT_REW_OP_SPECIAL 8 +#define IS2_ACT_REW_OP_PTP_ORG 9 +#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_1 (IS2_ACT_REW_OP_PTP_ONE | (1 << 3)) +#define IS2_ACT_REW_OP_PTP_ONE_SUB_DELAY_2 (IS2_ACT_REW_OP_PTP_ONE | (2 << 3)) +#define IS2_ACT_REW_OP_PTP_ONE_ADD_DELAY (IS2_ACT_REW_OP_PTP_ONE | (1 << 5)) +#define IS2_ACT_REW_OP_PTP_ONE_ADD_SUB BIT(7) + +#define VCAP_PORT_WIDTH 4 + +/* IS2 quarter key - SMAC_SIP4 */ +#define IS2_QKO_IGR_PORT 0 +#define IS2_QKL_IGR_PORT VCAP_PORT_WIDTH +#define IS2_QKO_L2_SMAC (IS2_QKO_IGR_PORT + IS2_QKL_IGR_PORT) +#define IS2_QKL_L2_SMAC 48 +#define IS2_QKO_L3_IP4_SIP (IS2_QKO_L2_SMAC + IS2_QKL_L2_SMAC) +#define IS2_QKL_L3_IP4_SIP 32 + +enum vcap_is2_half_key_field { + /* Common */ + VCAP_IS2_TYPE, + VCAP_IS2_HK_FIRST, + VCAP_IS2_HK_PAG, + VCAP_IS2_HK_RSV1, + VCAP_IS2_HK_IGR_PORT_MASK, + VCAP_IS2_HK_RSV2, + VCAP_IS2_HK_HOST_MATCH, + VCAP_IS2_HK_L2_MC, + VCAP_IS2_HK_L2_BC, + VCAP_IS2_HK_VLAN_TAGGED, + VCAP_IS2_HK_VID, + VCAP_IS2_HK_DEI, + VCAP_IS2_HK_PCP, + /* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */ + VCAP_IS2_HK_L2_DMAC, + VCAP_IS2_HK_L2_SMAC, + /* MAC_ETYPE (TYPE=000) */ + VCAP_IS2_HK_MAC_ETYPE_ETYPE, + VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0, + VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1, + VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2, + /* MAC_LLC (TYPE=001) */ + VCAP_IS2_HK_MAC_LLC_DMAC, + VCAP_IS2_HK_MAC_LLC_SMAC, + VCAP_IS2_HK_MAC_LLC_L2_LLC, + /* MAC_SNAP (TYPE=010) */ + VCAP_IS2_HK_MAC_SNAP_SMAC, + VCAP_IS2_HK_MAC_SNAP_DMAC, + VCAP_IS2_HK_MAC_SNAP_L2_SNAP, + /* MAC_ARP (TYPE=011) */ + VCAP_IS2_HK_MAC_ARP_SMAC, + VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK, + VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK, + VCAP_IS2_HK_MAC_ARP_LEN_OK, + VCAP_IS2_HK_MAC_ARP_TARGET_MATCH, + VCAP_IS2_HK_MAC_ARP_SENDER_MATCH, + VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN, + VCAP_IS2_HK_MAC_ARP_OPCODE, + VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP, + VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP, + VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP, + /* IP4_TCP_UDP / IP4_OTHER common */ + VCAP_IS2_HK_IP4, + VCAP_IS2_HK_L3_FRAGMENT, + VCAP_IS2_HK_L3_FRAG_OFS_GT0, + VCAP_IS2_HK_L3_OPTIONS, + VCAP_IS2_HK_IP4_L3_TTL_GT0, + VCAP_IS2_HK_L3_TOS, + VCAP_IS2_HK_L3_IP4_DIP, + VCAP_IS2_HK_L3_IP4_SIP, + VCAP_IS2_HK_DIP_EQ_SIP, + /* IP4_TCP_UDP (TYPE=100) */ + VCAP_IS2_HK_TCP, + VCAP_IS2_HK_L4_SPORT, + VCAP_IS2_HK_L4_DPORT, + VCAP_IS2_HK_L4_RNG, + VCAP_IS2_HK_L4_SPORT_EQ_DPORT, + VCAP_IS2_HK_L4_SEQUENCE_EQ0, + VCAP_IS2_HK_L4_URG, + VCAP_IS2_HK_L4_ACK, + VCAP_IS2_HK_L4_PSH, + VCAP_IS2_HK_L4_RST, + VCAP_IS2_HK_L4_SYN, + VCAP_IS2_HK_L4_FIN, + VCAP_IS2_HK_L4_1588_DOM, + VCAP_IS2_HK_L4_1588_VER, + /* IP4_OTHER (TYPE=101) */ + VCAP_IS2_HK_IP4_L3_PROTO, + VCAP_IS2_HK_L3_PAYLOAD, + /* IP6_STD (TYPE=110) */ + VCAP_IS2_HK_IP6_L3_TTL_GT0, + VCAP_IS2_HK_IP6_L3_PROTO, + VCAP_IS2_HK_L3_IP6_SIP, + /* OAM (TYPE=111) */ + VCAP_IS2_HK_OAM_MEL_FLAGS, + VCAP_IS2_HK_OAM_VER, + VCAP_IS2_HK_OAM_OPCODE, + VCAP_IS2_HK_OAM_FLAGS, + VCAP_IS2_HK_OAM_MEPID, + VCAP_IS2_HK_OAM_CCM_CNTS_EQ0, + VCAP_IS2_HK_OAM_IS_Y1731, +}; + +struct vcap_field { + int offset; + int length; +}; + +enum vcap_is2_action_field { + VCAP_IS2_ACT_HIT_ME_ONCE, + VCAP_IS2_ACT_CPU_COPY_ENA, + VCAP_IS2_ACT_CPU_QU_NUM, + VCAP_IS2_ACT_MASK_MODE, + VCAP_IS2_ACT_MIRROR_ENA, + VCAP_IS2_ACT_LRN_DIS, + VCAP_IS2_ACT_POLICE_ENA, + VCAP_IS2_ACT_POLICE_IDX, + VCAP_IS2_ACT_POLICE_VCAP_ONLY, + VCAP_IS2_ACT_PORT_MASK, + VCAP_IS2_ACT_REW_OP, + VCAP_IS2_ACT_SMAC_REPLACE_ENA, + VCAP_IS2_ACT_RSV, + VCAP_IS2_ACT_ACL_ID, + VCAP_IS2_ACT_HIT_CNT, +}; + +#endif /* _OCELOT_VCAP_H_ */ -- cgit v1.2.3 From 1ba8f6561a3ba3a4ac4becadb691667645fe73d2 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:11 +0200 Subject: net: mscc: ocelot: remove port_pcs_init indirection for VSC7514 The Felix driver is now using its own PHYLINK instance, not calling into ocelot_adjust_link. So the port_pcs_init function pointer is an unnecessary indirection. Remove it. Signed-off-by: Vladimir Oltean Tested-by: Horatiu Vultur Reviewed-by: Allan W. Nielsen Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 19 +++++++++++++++++-- drivers/net/ethernet/mscc/ocelot_board.c | 24 ------------------------ include/soc/mscc/ocelot.h | 3 --- 3 files changed, 17 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index fe5a0ff4ee2f..ac4cf34d3af5 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -442,8 +442,23 @@ void ocelot_adjust_link(struct ocelot *ocelot, int port, ocelot_port_writel(ocelot_port, DEV_MAC_MODE_CFG_FDX_ENA | mode, DEV_MAC_MODE_CFG); - if (ocelot->ops->pcs_init) - ocelot->ops->pcs_init(ocelot, port); + /* Disable HDX fast control */ + ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS, + DEV_PORT_MISC); + + /* SGMII only for now */ + ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA, + PCS1G_MODE_CFG); + ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG); + + /* Enable PCS */ + ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG); + + /* No aneg on SGMII */ + ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG); + + /* No loopback */ + ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG); /* Enable MAC module */ ocelot_port_writel(ocelot_port, DEV_MAC_ENA_CFG_RX_ENA | diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index c236936dbde7..c9257a828d91 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -212,29 +212,6 @@ static const struct of_device_id mscc_ocelot_match[] = { }; MODULE_DEVICE_TABLE(of, mscc_ocelot_match); -static void ocelot_port_pcs_init(struct ocelot *ocelot, int port) -{ - struct ocelot_port *ocelot_port = ocelot->ports[port]; - - /* Disable HDX fast control */ - ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS, - DEV_PORT_MISC); - - /* SGMII only for now */ - ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA, - PCS1G_MODE_CFG); - ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG); - - /* Enable PCS */ - ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG); - - /* No aneg on SGMII */ - ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG); - - /* No loopback */ - ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG); -} - static int ocelot_reset(struct ocelot *ocelot) { int retries = 100; @@ -259,7 +236,6 @@ static int ocelot_reset(struct ocelot *ocelot) } static const struct ocelot_ops ocelot_ops = { - .pcs_init = ocelot_port_pcs_init, .reset = ocelot_reset, }; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 3da8285d4cd8..45630bee8ed2 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -402,7 +402,6 @@ enum ocelot_tag_prefix { struct ocelot; struct ocelot_ops { - void (*pcs_init)(struct ocelot *ocelot, int port); int (*reset)(struct ocelot *ocelot); }; @@ -479,8 +478,6 @@ struct ocelot { struct mutex ptp_lock; /* Protects the PTP clock */ spinlock_t ptp_clock_lock; - - void (*port_pcs_init)(struct ocelot_port *port); }; #define ocelot_read_ix(ocelot, reg, gi, ri) __ocelot_read_ix(ocelot, reg, reg##_GSZ * (gi) + reg##_RSZ * (ri)) -- cgit v1.2.3 From 8551cdeb2ad1711e3ae85799ad9cc41c0bc64e0b Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:12 +0200 Subject: net: mscc: ocelot: parameterize the vcap_is2 properties Remove the definitions for the VCAP IS2 table from ocelot_ace.c, since it is specific to VSC7514. The VSC9959 VCAP IS2 table supports more rules (1024 instead of 64) and has a different width for the action (89 bits instead of 99). Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot_ace.c | 134 +++++++++++++------------------ drivers/net/ethernet/mscc/ocelot_board.c | 30 +++++++ include/soc/mscc/ocelot.h | 1 + include/soc/mscc/ocelot_vcap.h | 37 +++++++-- 4 files changed, 114 insertions(+), 88 deletions(-) (limited to 'include') diff --git a/drivers/net/ethernet/mscc/ocelot_ace.c b/drivers/net/ethernet/mscc/ocelot_ace.c index 9922033a2aaf..906b54025b17 100644 --- a/drivers/net/ethernet/mscc/ocelot_ace.c +++ b/drivers/net/ethernet/mscc/ocelot_ace.c @@ -11,53 +11,7 @@ #include "ocelot_s2.h" #define OCELOT_POLICER_DISCARD 0x17f - -struct vcap_props { - const char *name; /* Symbolic name */ - u16 tg_width; /* Type-group width (in bits) */ - u16 sw_count; /* Sub word count */ - u16 entry_count; /* Entry count */ - u16 entry_words; /* Number of entry words */ - u16 entry_width; /* Entry width (in bits) */ - u16 action_count; /* Action count */ - u16 action_words; /* Number of action words */ - u16 action_width; /* Action width (in bits) */ - u16 action_type_width; /* Action type width (in bits) */ - struct { - u16 width; /* Action type width (in bits) */ - u16 count; /* Action type sub word count */ - } action_table[2]; - u16 counter_words; /* Number of counter words */ - u16 counter_width; /* Counter width (in bits) */ -}; - #define ENTRY_WIDTH 32 -#define BITS_TO_32BIT(x) (1 + (((x) - 1) / ENTRY_WIDTH)) - -static const struct vcap_props vcap_is2 = { - .name = "IS2", - .tg_width = 2, - .sw_count = 4, - .entry_count = VCAP_IS2_CNT, - .entry_words = BITS_TO_32BIT(VCAP_IS2_ENTRY_WIDTH), - .entry_width = VCAP_IS2_ENTRY_WIDTH, - .action_count = (VCAP_IS2_CNT + VCAP_PORT_CNT + 2), - .action_words = BITS_TO_32BIT(VCAP_IS2_ACTION_WIDTH), - .action_width = (VCAP_IS2_ACTION_WIDTH), - .action_type_width = 1, - .action_table = { - { - .width = 49, - .count = 2 - }, - { - .width = 6, - .count = 4 - }, - }, - .counter_words = BITS_TO_32BIT(4 * ENTRY_WIDTH), - .counter_width = ENTRY_WIDTH, -}; enum vcap_sel { VCAP_SEL_ENTRY = 0x1, @@ -100,11 +54,13 @@ static u32 vcap_s2_read_update_ctrl(struct ocelot *ocelot) static void vcap_cmd(struct ocelot *ocelot, u16 ix, int cmd, int sel) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 value = (S2_CORE_UPDATE_CTRL_UPDATE_CMD(cmd) | S2_CORE_UPDATE_CTRL_UPDATE_ADDR(ix) | S2_CORE_UPDATE_CTRL_UPDATE_SHOT); - if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2.entry_count) + if ((sel & VCAP_SEL_ENTRY) && ix >= vcap_is2->entry_count) return; if (!(sel & VCAP_SEL_ENTRY)) @@ -125,14 +81,19 @@ static void vcap_cmd(struct ocelot *ocelot, u16 ix, int cmd, int sel) /* Convert from 0-based row to VCAP entry row and run command */ static void vcap_row_cmd(struct ocelot *ocelot, u32 row, int cmd, int sel) { - vcap_cmd(ocelot, vcap_is2.entry_count - row - 1, cmd, sel); + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + + vcap_cmd(ocelot, vcap_is2->entry_count - row - 1, cmd, sel); } static void vcap_entry2cache(struct ocelot *ocelot, struct vcap_data *data) { - u32 i; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 entry_words, i; + + entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.entry_words; i++) { + for (i = 0; i < entry_words; i++) { ocelot_write_rix(ocelot, data->entry[i], S2_CACHE_ENTRY_DAT, i); ocelot_write_rix(ocelot, ~data->mask[i], S2_CACHE_MASK_DAT, i); } @@ -141,9 +102,12 @@ static void vcap_entry2cache(struct ocelot *ocelot, struct vcap_data *data) static void vcap_cache2entry(struct ocelot *ocelot, struct vcap_data *data) { - u32 i; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 entry_words, i; + + entry_words = DIV_ROUND_UP(vcap_is2->entry_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.entry_words; i++) { + for (i = 0; i < entry_words; i++) { data->entry[i] = ocelot_read_rix(ocelot, S2_CACHE_ENTRY_DAT, i); // Invert mask data->mask[i] = ~ocelot_read_rix(ocelot, S2_CACHE_MASK_DAT, i); @@ -153,49 +117,56 @@ static void vcap_cache2entry(struct ocelot *ocelot, struct vcap_data *data) static void vcap_action2cache(struct ocelot *ocelot, struct vcap_data *data) { - u32 i, width, mask; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 action_words, i, width, mask; /* Encode action type */ - width = vcap_is2.action_type_width; + width = vcap_is2->action_type_width; if (width) { mask = GENMASK(width, 0); data->action[0] = ((data->action[0] & ~mask) | data->type); } - for (i = 0; i < vcap_is2.action_words; i++) - ocelot_write_rix(ocelot, data->action[i], - S2_CACHE_ACTION_DAT, i); + action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.counter_words; i++) - ocelot_write_rix(ocelot, data->counter[i], - S2_CACHE_CNT_DAT, i); + for (i = 0; i < action_words; i++) + ocelot_write_rix(ocelot, data->action[i], S2_CACHE_ACTION_DAT, + i); + + for (i = 0; i < vcap_is2->counter_words; i++) + ocelot_write_rix(ocelot, data->counter[i], S2_CACHE_CNT_DAT, i); } static void vcap_cache2action(struct ocelot *ocelot, struct vcap_data *data) { - u32 i, width; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 action_words, i, width; + + action_words = DIV_ROUND_UP(vcap_is2->action_width, ENTRY_WIDTH); - for (i = 0; i < vcap_is2.action_words; i++) + for (i = 0; i < action_words; i++) data->action[i] = ocelot_read_rix(ocelot, S2_CACHE_ACTION_DAT, i); - for (i = 0; i < vcap_is2.counter_words; i++) + for (i = 0; i < vcap_is2->counter_words; i++) data->counter[i] = ocelot_read_rix(ocelot, S2_CACHE_CNT_DAT, i); /* Extract action type */ - width = vcap_is2.action_type_width; + width = vcap_is2->action_type_width; data->type = (width ? (data->action[0] & GENMASK(width, 0)) : 0); } /* Calculate offsets for entry */ -static void is2_data_get(struct vcap_data *data, int ix) +static void is2_data_get(struct ocelot *ocelot, struct vcap_data *data, int ix) { - u32 i, col, offset, count, cnt, base, width = vcap_is2.tg_width; + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; + u32 i, col, offset, count, cnt, base; + u32 width = vcap_is2->tg_width; count = (data->tg_sw == VCAP_TG_HALF ? 2 : 4); col = (ix % 2); - cnt = (vcap_is2.sw_count / count); - base = (vcap_is2.sw_count - col * cnt - cnt); + cnt = (vcap_is2->sw_count / count); + base = (vcap_is2->sw_count - col * cnt - cnt); data->tg_value = 0; data->tg_mask = 0; for (i = 0; i < cnt; i++) { @@ -206,13 +177,13 @@ static void is2_data_get(struct vcap_data *data, int ix) /* Calculate key/action/counter offsets */ col = (count - col - 1); - data->key_offset = (base * vcap_is2.entry_width) / vcap_is2.sw_count; - data->counter_offset = (cnt * col * vcap_is2.counter_width); + data->key_offset = (base * vcap_is2->entry_width) / vcap_is2->sw_count; + data->counter_offset = (cnt * col * vcap_is2->counter_width); i = data->type; - width = vcap_is2.action_table[i].width; - cnt = vcap_is2.action_table[i].count; + width = vcap_is2->action_table[i].width; + cnt = vcap_is2->action_table[i].count; data->action_offset = - (((cnt * col * width) / count) + vcap_is2.action_type_width); + (((cnt * col * width) / count) + vcap_is2->action_type_width); } static void vcap_data_set(u32 *data, u32 offset, u32 len, u32 value) @@ -354,6 +325,7 @@ static void is2_action_set(struct ocelot *ocelot, struct vcap_data *data, static void is2_entry_set(struct ocelot *ocelot, int ix, struct ocelot_ace_rule *ace) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; u32 val, msk, type, type_mask = 0xf, i, count; struct ocelot_ace_vlan *tag = &ace->vlan; struct ocelot_vcap_u64 payload; @@ -369,7 +341,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, vcap_cache2action(ocelot, &data); data.tg_sw = VCAP_TG_HALF; - is2_data_get(&data, ix); + is2_data_get(ocelot, &data, ix); data.tg = (data.tg & ~data.tg_mask); if (ace->prio != 0) data.tg |= data.tg_value; @@ -627,7 +599,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, default: type = 0; type_mask = 0; - count = (vcap_is2.entry_width / 2); + count = vcap_is2->entry_width / 2; /* Iterate over the non-common part of the key and * clear entry data */ @@ -641,7 +613,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, vcap_key_set(ocelot, &data, VCAP_IS2_TYPE, type, type_mask); is2_action_set(ocelot, &data, ace->action); vcap_data_set(data.counter, data.counter_offset, - vcap_is2.counter_width, ace->stats.pkts); + vcap_is2->counter_width, ace->stats.pkts); /* Write row */ vcap_entry2cache(ocelot, &data); @@ -652,6 +624,7 @@ static void is2_entry_set(struct ocelot *ocelot, int ix, static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule, int ix) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; struct vcap_data data; int row = (ix / 2); u32 cnt; @@ -659,9 +632,9 @@ static void is2_entry_get(struct ocelot *ocelot, struct ocelot_ace_rule *rule, vcap_row_cmd(ocelot, row, VCAP_CMD_READ, VCAP_SEL_COUNTER); vcap_cache2action(ocelot, &data); data.tg_sw = VCAP_TG_HALF; - is2_data_get(&data, ix); + is2_data_get(ocelot, &data, ix); cnt = vcap_data_get(data.counter, data.counter_offset, - vcap_is2.counter_width); + vcap_is2->counter_width); rule->stats.pkts = cnt; } @@ -805,16 +778,17 @@ int ocelot_ace_rule_stats_update(struct ocelot *ocelot, int ocelot_ace_init(struct ocelot *ocelot) { + const struct vcap_props *vcap_is2 = &ocelot->vcap[VCAP_IS2]; struct vcap_data data; memset(&data, 0, sizeof(data)); vcap_entry2cache(ocelot, &data); - ocelot_write(ocelot, vcap_is2.entry_count, S2_CORE_MV_CFG); + ocelot_write(ocelot, vcap_is2->entry_count, S2_CORE_MV_CFG); vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ENTRY); vcap_action2cache(ocelot, &data); - ocelot_write(ocelot, vcap_is2.action_count, S2_CORE_MV_CFG); + ocelot_write(ocelot, vcap_is2->action_count, S2_CORE_MV_CFG); vcap_cmd(ocelot, 0, VCAP_CMD_INITIALIZE, VCAP_SEL_ACTION | VCAP_SEL_COUNTER); diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index c9257a828d91..c343ca5276ef 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -18,6 +18,10 @@ #include "ocelot.h" #define IFH_EXTRACT_BITFIELD64(x, o, w) (((x) >> (o)) & GENMASK_ULL((w) - 1, 0)) +#define VSC7514_VCAP_IS2_CNT 64 +#define VSC7514_VCAP_IS2_ENTRY_WIDTH 376 +#define VSC7514_VCAP_IS2_ACTION_WIDTH 99 +#define VSC7514_VCAP_PORT_CNT 11 static int ocelot_parse_ifh(u32 *_ifh, struct frame_info *info) { @@ -337,6 +341,31 @@ static const struct vcap_field vsc7514_vcap_is2_actions[] = { [VCAP_IS2_ACT_HIT_CNT] = { 49, 32}, }; +static const struct vcap_props vsc7514_vcap_props[] = { + [VCAP_IS2] = { + .tg_width = 2, + .sw_count = 4, + .entry_count = VSC7514_VCAP_IS2_CNT, + .entry_width = VSC7514_VCAP_IS2_ENTRY_WIDTH, + .action_count = VSC7514_VCAP_IS2_CNT + + VSC7514_VCAP_PORT_CNT + 2, + .action_width = 99, + .action_type_width = 1, + .action_table = { + [IS2_ACTION_TYPE_NORMAL] = { + .width = 49, + .count = 2 + }, + [IS2_ACTION_TYPE_SMAC_SIP] = { + .width = 6, + .count = 4 + }, + }, + .counter_words = 4, + .counter_width = 32, + }, +}; + static int mscc_ocelot_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -439,6 +468,7 @@ static int mscc_ocelot_probe(struct platform_device *pdev) ocelot->vcap_is2_keys = vsc7514_vcap_is2_keys; ocelot->vcap_is2_actions = vsc7514_vcap_is2_actions; + ocelot->vcap = vsc7514_vcap_props; ocelot_init(ocelot); ocelot_set_cpu_port(ocelot, ocelot->num_phys_ports, diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 45630bee8ed2..30270571fb71 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -463,6 +463,7 @@ struct ocelot { const struct vcap_field *vcap_is2_keys; const struct vcap_field *vcap_is2_actions; + const struct vcap_props *vcap; /* Workqueue to check statistics for overflow with its lock */ struct mutex stats_lock; diff --git a/include/soc/mscc/ocelot_vcap.h b/include/soc/mscc/ocelot_vcap.h index 0783f0ffc813..5748373ab4d3 100644 --- a/include/soc/mscc/ocelot_vcap.h +++ b/include/soc/mscc/ocelot_vcap.h @@ -11,6 +11,30 @@ * ================================================================= */ +enum { + /* VCAP_IS1, */ + VCAP_IS2, + /* VCAP_ES0, */ +}; + +struct vcap_props { + u16 tg_width; /* Type-group width (in bits) */ + u16 sw_count; /* Sub word count */ + u16 entry_count; /* Entry count */ + u16 entry_words; /* Number of entry words */ + u16 entry_width; /* Entry width (in bits) */ + u16 action_count; /* Action count */ + u16 action_words; /* Number of action words */ + u16 action_width; /* Action width (in bits) */ + u16 action_type_width; /* Action type width (in bits) */ + struct { + u16 width; /* Action type width (in bits) */ + u16 count; /* Action type sub word count */ + } action_table[2]; + u16 counter_words; /* Number of counter words */ + u16 counter_width; /* Counter width (in bits) */ +}; + /* VCAP Type-Group values */ #define VCAP_TG_NONE 0 /* Entry is invalid */ #define VCAP_TG_FULL 1 /* Full entry */ @@ -22,11 +46,6 @@ * ================================================================= */ -#define VCAP_IS2_CNT 64 -#define VCAP_IS2_ENTRY_WIDTH 376 -#define VCAP_IS2_ACTION_WIDTH 99 -#define VCAP_PORT_CNT 11 - /* IS2 half key types */ #define IS2_TYPE_ETYPE 0 #define IS2_TYPE_LLC 1 @@ -42,9 +61,11 @@ /* IS2 half key type mask for matching any IP */ #define IS2_TYPE_MASK_IP_ANY 0xe -/* IS2 action types */ -#define IS2_ACTION_TYPE_NORMAL 0 -#define IS2_ACTION_TYPE_SMAC_SIP 1 +enum { + IS2_ACTION_TYPE_NORMAL, + IS2_ACTION_TYPE_SMAC_SIP, + IS2_ACTION_TYPE_MAX, +}; /* IS2 MASK_MODE values */ #define IS2_ACT_MASK_MODE_NONE 0 -- cgit v1.2.3 From ed11bb1f9657e95e8b79a9a49211986bde96005a Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:13 +0200 Subject: net: dsa: Add bypass operations for the flower classifier-action filter Due to the immense variety of classification keys and actions available for tc-flower, as well as due to potentially very different DSA switch capabilities, it doesn't make a lot of sense for the DSA mid layer to even attempt to interpret these. So just pass them on to the underlying switch driver. DSA implements just the standard boilerplate for binding and unbinding flow blocks to ports, since nobody wants to deal with that. Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- include/net/dsa.h | 6 ++++++ net/dsa/slave.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) (limited to 'include') diff --git a/include/net/dsa.h b/include/net/dsa.h index 7d3d84f0ef42..beeb81a532e3 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -540,6 +540,12 @@ struct dsa_switch_ops { /* * TC integration */ + int (*cls_flower_add)(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress); + int (*cls_flower_del)(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress); + int (*cls_flower_stats)(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress); int (*port_mirror_add)(struct dsa_switch *ds, int port, struct dsa_mall_mirror_tc_entry *mirror, bool ingress); diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 088c886e609e..79d9b4384d7b 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -946,6 +946,64 @@ static int dsa_slave_setup_tc_cls_matchall(struct net_device *dev, } } +static int dsa_slave_add_cls_flower(struct net_device *dev, + struct flow_cls_offload *cls, + bool ingress) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + int port = dp->index; + + if (!ds->ops->cls_flower_add) + return -EOPNOTSUPP; + + return ds->ops->cls_flower_add(ds, port, cls, ingress); +} + +static int dsa_slave_del_cls_flower(struct net_device *dev, + struct flow_cls_offload *cls, + bool ingress) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + int port = dp->index; + + if (!ds->ops->cls_flower_del) + return -EOPNOTSUPP; + + return ds->ops->cls_flower_del(ds, port, cls, ingress); +} + +static int dsa_slave_stats_cls_flower(struct net_device *dev, + struct flow_cls_offload *cls, + bool ingress) +{ + struct dsa_port *dp = dsa_slave_to_port(dev); + struct dsa_switch *ds = dp->ds; + int port = dp->index; + + if (!ds->ops->cls_flower_stats) + return -EOPNOTSUPP; + + return ds->ops->cls_flower_stats(ds, port, cls, ingress); +} + +static int dsa_slave_setup_tc_cls_flower(struct net_device *dev, + struct flow_cls_offload *cls, + bool ingress) +{ + switch (cls->command) { + case FLOW_CLS_REPLACE: + return dsa_slave_add_cls_flower(dev, cls, ingress); + case FLOW_CLS_DESTROY: + return dsa_slave_del_cls_flower(dev, cls, ingress); + case FLOW_CLS_STATS: + return dsa_slave_stats_cls_flower(dev, cls, ingress); + default: + return -EOPNOTSUPP; + } +} + static int dsa_slave_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv, bool ingress) { @@ -957,6 +1015,8 @@ static int dsa_slave_setup_tc_block_cb(enum tc_setup_type type, void *type_data, switch (type) { case TC_SETUP_CLSMATCHALL: return dsa_slave_setup_tc_cls_matchall(dev, type_data, ingress); + case TC_SETUP_CLSFLOWER: + return dsa_slave_setup_tc_cls_flower(dev, type_data, ingress); default: return -EOPNOTSUPP; } -- cgit v1.2.3 From 07d985eef07348345870f1062797852cb4489b83 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sat, 29 Feb 2020 16:31:14 +0200 Subject: net: dsa: felix: Wire up the ocelot cls_flower methods Export the cls_flower methods from the ocelot driver and hook them up to the DSA passthrough layer. Tables for the VCAP IS2 parameters, as well as half key packing (field offsets and lengths) need to be defined for the VSC9959 core, as they are different from Ocelot, mainly due to the different port count. Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 31 ++++++++ drivers/net/dsa/ocelot/felix.h | 3 + drivers/net/dsa/ocelot/felix_vsc9959.c | 131 +++++++++++++++++++++++++++++++++ include/soc/mscc/ocelot.h | 6 ++ 4 files changed, 171 insertions(+) (limited to 'include') diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 7e66821b05b4..c0acd7dc7f48 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -2,6 +2,7 @@ /* Copyright 2019 NXP Semiconductors */ #include +#include #include #include #include @@ -401,6 +402,9 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports) ocelot->stats_layout = felix->info->stats_layout; ocelot->num_stats = felix->info->num_stats; ocelot->shared_queue_sz = felix->info->shared_queue_sz; + ocelot->vcap_is2_keys = felix->info->vcap_is2_keys; + ocelot->vcap_is2_actions= felix->info->vcap_is2_actions; + ocelot->vcap = felix->info->vcap; ocelot->ops = felix->info->ops; port_phy_modes = kcalloc(num_phys_ports, sizeof(phy_interface_t), @@ -595,6 +599,30 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port, return false; } +static int felix_cls_flower_add(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_cls_flower_replace(ocelot, port, cls, ingress); +} + +static int felix_cls_flower_del(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_cls_flower_destroy(ocelot, port, cls, ingress); +} + +static int felix_cls_flower_stats(struct dsa_switch *ds, int port, + struct flow_cls_offload *cls, bool ingress) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_cls_flower_stats(ocelot, port, cls, ingress); +} + static const struct dsa_switch_ops felix_switch_ops = { .get_tag_protocol = felix_get_tag_protocol, .setup = felix_setup, @@ -626,6 +654,9 @@ static const struct dsa_switch_ops felix_switch_ops = { .port_hwtstamp_set = felix_hwtstamp_set, .port_rxtstamp = felix_rxtstamp, .port_txtstamp = felix_txtstamp, + .cls_flower_add = felix_cls_flower_add, + .cls_flower_del = felix_cls_flower_del, + .cls_flower_stats = felix_cls_flower_stats, }; static struct felix_info *felix_instance_tbl[] = { diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 3a7580015b62..82d46f260041 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -18,6 +18,9 @@ struct felix_info { const struct ocelot_stat_layout *stats_layout; unsigned int num_stats; int num_ports; + struct vcap_field *vcap_is2_keys; + struct vcap_field *vcap_is2_actions; + const struct vcap_props *vcap; int switch_pci_bar; int imdio_pci_bar; int (*mdio_bus_alloc)(struct ocelot *ocelot); diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index 93800e81cdd4..b4078f3c5c38 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -3,12 +3,17 @@ * Copyright 2018-2019 NXP Semiconductors */ #include +#include #include #include #include #include #include "felix.h" +#define VSC9959_VCAP_IS2_CNT 1024 +#define VSC9959_VCAP_IS2_ENTRY_WIDTH 376 +#define VSC9959_VCAP_PORT_CNT 6 + /* TODO: should find a better place for these */ #define USXGMII_BMCR_RESET BIT(15) #define USXGMII_BMCR_AN_EN BIT(12) @@ -547,6 +552,129 @@ static const struct ocelot_stat_layout vsc9959_stats_layout[] = { { .offset = 0x111, .name = "drop_green_prio_7", }, }; +struct vcap_field vsc9959_vcap_is2_keys[] = { + /* Common: 41 bits */ + [VCAP_IS2_TYPE] = { 0, 4}, + [VCAP_IS2_HK_FIRST] = { 4, 1}, + [VCAP_IS2_HK_PAG] = { 5, 8}, + [VCAP_IS2_HK_IGR_PORT_MASK] = { 13, 7}, + [VCAP_IS2_HK_RSV2] = { 20, 1}, + [VCAP_IS2_HK_HOST_MATCH] = { 21, 1}, + [VCAP_IS2_HK_L2_MC] = { 22, 1}, + [VCAP_IS2_HK_L2_BC] = { 23, 1}, + [VCAP_IS2_HK_VLAN_TAGGED] = { 24, 1}, + [VCAP_IS2_HK_VID] = { 25, 12}, + [VCAP_IS2_HK_DEI] = { 37, 1}, + [VCAP_IS2_HK_PCP] = { 38, 3}, + /* MAC_ETYPE / MAC_LLC / MAC_SNAP / OAM common */ + [VCAP_IS2_HK_L2_DMAC] = { 41, 48}, + [VCAP_IS2_HK_L2_SMAC] = { 89, 48}, + /* MAC_ETYPE (TYPE=000) */ + [VCAP_IS2_HK_MAC_ETYPE_ETYPE] = {137, 16}, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD0] = {153, 16}, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD1] = {169, 8}, + [VCAP_IS2_HK_MAC_ETYPE_L2_PAYLOAD2] = {177, 3}, + /* MAC_LLC (TYPE=001) */ + [VCAP_IS2_HK_MAC_LLC_L2_LLC] = {137, 40}, + /* MAC_SNAP (TYPE=010) */ + [VCAP_IS2_HK_MAC_SNAP_L2_SNAP] = {137, 40}, + /* MAC_ARP (TYPE=011) */ + [VCAP_IS2_HK_MAC_ARP_SMAC] = { 41, 48}, + [VCAP_IS2_HK_MAC_ARP_ADDR_SPACE_OK] = { 89, 1}, + [VCAP_IS2_HK_MAC_ARP_PROTO_SPACE_OK] = { 90, 1}, + [VCAP_IS2_HK_MAC_ARP_LEN_OK] = { 91, 1}, + [VCAP_IS2_HK_MAC_ARP_TARGET_MATCH] = { 92, 1}, + [VCAP_IS2_HK_MAC_ARP_SENDER_MATCH] = { 93, 1}, + [VCAP_IS2_HK_MAC_ARP_OPCODE_UNKNOWN] = { 94, 1}, + [VCAP_IS2_HK_MAC_ARP_OPCODE] = { 95, 2}, + [VCAP_IS2_HK_MAC_ARP_L3_IP4_DIP] = { 97, 32}, + [VCAP_IS2_HK_MAC_ARP_L3_IP4_SIP] = {129, 32}, + [VCAP_IS2_HK_MAC_ARP_DIP_EQ_SIP] = {161, 1}, + /* IP4_TCP_UDP / IP4_OTHER common */ + [VCAP_IS2_HK_IP4] = { 41, 1}, + [VCAP_IS2_HK_L3_FRAGMENT] = { 42, 1}, + [VCAP_IS2_HK_L3_FRAG_OFS_GT0] = { 43, 1}, + [VCAP_IS2_HK_L3_OPTIONS] = { 44, 1}, + [VCAP_IS2_HK_IP4_L3_TTL_GT0] = { 45, 1}, + [VCAP_IS2_HK_L3_TOS] = { 46, 8}, + [VCAP_IS2_HK_L3_IP4_DIP] = { 54, 32}, + [VCAP_IS2_HK_L3_IP4_SIP] = { 86, 32}, + [VCAP_IS2_HK_DIP_EQ_SIP] = {118, 1}, + /* IP4_TCP_UDP (TYPE=100) */ + [VCAP_IS2_HK_TCP] = {119, 1}, + [VCAP_IS2_HK_L4_SPORT] = {120, 16}, + [VCAP_IS2_HK_L4_DPORT] = {136, 16}, + [VCAP_IS2_HK_L4_RNG] = {152, 8}, + [VCAP_IS2_HK_L4_SPORT_EQ_DPORT] = {160, 1}, + [VCAP_IS2_HK_L4_SEQUENCE_EQ0] = {161, 1}, + [VCAP_IS2_HK_L4_URG] = {162, 1}, + [VCAP_IS2_HK_L4_ACK] = {163, 1}, + [VCAP_IS2_HK_L4_PSH] = {164, 1}, + [VCAP_IS2_HK_L4_RST] = {165, 1}, + [VCAP_IS2_HK_L4_SYN] = {166, 1}, + [VCAP_IS2_HK_L4_FIN] = {167, 1}, + [VCAP_IS2_HK_L4_1588_DOM] = {168, 8}, + [VCAP_IS2_HK_L4_1588_VER] = {176, 4}, + /* IP4_OTHER (TYPE=101) */ + [VCAP_IS2_HK_IP4_L3_PROTO] = {119, 8}, + [VCAP_IS2_HK_L3_PAYLOAD] = {127, 56}, + /* IP6_STD (TYPE=110) */ + [VCAP_IS2_HK_IP6_L3_TTL_GT0] = { 41, 1}, + [VCAP_IS2_HK_L3_IP6_SIP] = { 42, 128}, + [VCAP_IS2_HK_IP6_L3_PROTO] = {170, 8}, + /* OAM (TYPE=111) */ + [VCAP_IS2_HK_OAM_MEL_FLAGS] = {137, 7}, + [VCAP_IS2_HK_OAM_VER] = {144, 5}, + [VCAP_IS2_HK_OAM_OPCODE] = {149, 8}, + [VCAP_IS2_HK_OAM_FLAGS] = {157, 8}, + [VCAP_IS2_HK_OAM_MEPID] = {165, 16}, + [VCAP_IS2_HK_OAM_CCM_CNTS_EQ0] = {181, 1}, + [VCAP_IS2_HK_OAM_IS_Y1731] = {182, 1}, +}; + +struct vcap_field vsc9959_vcap_is2_actions[] = { + [VCAP_IS2_ACT_HIT_ME_ONCE] = { 0, 1}, + [VCAP_IS2_ACT_CPU_COPY_ENA] = { 1, 1}, + [VCAP_IS2_ACT_CPU_QU_NUM] = { 2, 3}, + [VCAP_IS2_ACT_MASK_MODE] = { 5, 2}, + [VCAP_IS2_ACT_MIRROR_ENA] = { 7, 1}, + [VCAP_IS2_ACT_LRN_DIS] = { 8, 1}, + [VCAP_IS2_ACT_POLICE_ENA] = { 9, 1}, + [VCAP_IS2_ACT_POLICE_IDX] = { 10, 9}, + [VCAP_IS2_ACT_POLICE_VCAP_ONLY] = { 19, 1}, + [VCAP_IS2_ACT_PORT_MASK] = { 20, 11}, + [VCAP_IS2_ACT_REW_OP] = { 31, 9}, + [VCAP_IS2_ACT_SMAC_REPLACE_ENA] = { 40, 1}, + [VCAP_IS2_ACT_RSV] = { 41, 2}, + [VCAP_IS2_ACT_ACL_ID] = { 43, 6}, + [VCAP_IS2_ACT_HIT_CNT] = { 49, 32}, +}; + +static const struct vcap_props vsc9959_vcap_props[] = { + [VCAP_IS2] = { + .tg_width = 2, + .sw_count = 4, + .entry_count = VSC9959_VCAP_IS2_CNT, + .entry_width = VSC9959_VCAP_IS2_ENTRY_WIDTH, + .action_count = VSC9959_VCAP_IS2_CNT + + VSC9959_VCAP_PORT_CNT + 2, + .action_width = 89, + .action_type_width = 1, + .action_table = { + [IS2_ACTION_TYPE_NORMAL] = { + .width = 44, + .count = 2 + }, + [IS2_ACTION_TYPE_SMAC_SIP] = { + .width = 6, + .count = 4 + }, + }, + .counter_words = 4, + .counter_width = 32, + }, +}; + #define VSC9959_INIT_TIMEOUT 50000 #define VSC9959_GCB_RST_SLEEP 100 #define VSC9959_SYS_RAMINIT_SLEEP 80 @@ -1088,6 +1216,9 @@ struct felix_info felix_info_vsc9959 = { .ops = &vsc9959_ops, .stats_layout = vsc9959_stats_layout, .num_stats = ARRAY_SIZE(vsc9959_stats_layout), + .vcap_is2_keys = vsc9959_vcap_is2_keys, + .vcap_is2_actions = vsc9959_vcap_is2_actions, + .vcap = vsc9959_vcap_props, .shared_queue_sz = 128 * 1024, .num_ports = 6, .switch_pci_bar = 4, diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 30270571fb71..5b037f976245 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -549,5 +549,11 @@ int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts); int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port, struct sk_buff *skb); void ocelot_get_txtstamp(struct ocelot *ocelot); +int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, + struct flow_cls_offload *f, bool ingress); +int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, + struct flow_cls_offload *f, bool ingress); +int ocelot_cls_flower_stats(struct ocelot *ocelot, int port, + struct flow_cls_offload *f, bool ingress); #endif -- cgit v1.2.3