/* These protocols have dedicated keysets in IS0 and a TC dissector */ static u16 sparx5_vcap_is0_known_etypes[] = {
ETH_P_ALL,
ETH_P_IP,
ETH_P_IPV6,
};
/* These protocols have dedicated keysets in IS2 and a TC dissector */ static u16 sparx5_vcap_is2_known_etypes[] = {
ETH_P_ALL,
ETH_P_ARP,
ETH_P_IP,
ETH_P_IPV6,
};
/* These protocols have dedicated keysets in ES2 and a TC dissector */ static u16 sparx5_vcap_es2_known_etypes[] = {
ETH_P_ALL,
ETH_P_ARP,
ETH_P_IP,
ETH_P_IPV6,
};
/* Get the keyset name from the sparx5 VCAP model */ staticconstchar *sparx5_vcap_keyset_name(struct net_device *ndev, enum vcap_keyfield_set keyset)
{ struct sparx5_port *port = netdev_priv(ndev);
/* Set the narrow range ingress port mask on a rule */ staticvoid sparx5_vcap_add_ingress_range_port_mask(struct vcap_rule *rule, struct net_device *ndev)
{ struct sparx5_port *port = netdev_priv(ndev);
u32 port_mask;
u32 range;
range = port->portno / BITS_PER_TYPE(u32); /* Port bit set to match-any */
port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32));
vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_SEL, 0, 0xf);
vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_RNG, range, 0xf);
vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, port_mask);
}
/* Set the wide range ingress port mask on a rule */ staticvoid sparx5_vcap_add_wide_port_mask(struct vcap_rule *rule, struct net_device *ndev)
{ struct sparx5_port *port = netdev_priv(ndev); struct vcap_u72_key port_mask;
u32 range;
/* Port bit set to match-any */
memset(port_mask.value, 0, sizeof(port_mask.value));
memset(port_mask.mask, 0xff, sizeof(port_mask.mask));
range = port->portno / BITS_PER_BYTE;
port_mask.mask[range] = ~BIT(port->portno % BITS_PER_BYTE);
vcap_rule_add_key_u72(rule, VCAP_KF_IF_IGR_PORT_MASK, &port_mask);
}
/* Convert ES2 chain id to vcap lookup id */ staticint sparx5_vcap_es2_cid_to_lookup(int cid)
{ int lookup = 0;
if (cid >= SPARX5_VCAP_CID_ES2_L1)
lookup = 1;
return lookup;
}
/* Add ethernet type IS0 keyset to a list */ staticvoid
sparx5_vcap_is0_get_port_etype_keysets(struct vcap_keyset_list *keysetlist,
u32 value)
{ switch (ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value)) { case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_7TUPLE); break; case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_5TUPLE_IP4); break;
}
}
/* Return the list of keysets for the vcap port configuration */ staticint sparx5_vcap_is0_get_port_keysets(struct net_device *ndev, int lookup, struct vcap_keyset_list *keysetlist,
u16 l3_proto)
{ struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; int portno = port->portno;
u32 value;
value = spx5_rd(sparx5, ANA_CL_ADV_CL_CFG(portno, lookup));
/* Collect all keysets for the port in a list */ if (l3_proto == ETH_P_ALL)
sparx5_vcap_is0_get_port_etype_keysets(keysetlist, value);
if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) switch (ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value)) { case VCAP_IS0_PS_ETYPE_DEFAULT:
sparx5_vcap_is0_get_port_etype_keysets(keysetlist,
value); break; case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
vcap_keyset_list_add(keysetlist,
VCAP_KFS_NORMAL_7TUPLE); break; case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
vcap_keyset_list_add(keysetlist,
VCAP_KFS_NORMAL_5TUPLE_IP4); break;
}
if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) switch (ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value)) { case VCAP_IS0_PS_ETYPE_DEFAULT:
sparx5_vcap_is0_get_port_etype_keysets(keysetlist,
value); break; case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE:
vcap_keyset_list_add(keysetlist,
VCAP_KFS_NORMAL_7TUPLE); break; case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4:
vcap_keyset_list_add(keysetlist,
VCAP_KFS_NORMAL_5TUPLE_IP4); break;
}
/* Return the list of keysets for the vcap port configuration */ staticint sparx5_vcap_is2_get_port_keysets(struct net_device *ndev, int lookup, struct vcap_keyset_list *keysetlist,
u16 l3_proto)
{ struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; int portno = port->portno;
u32 value;
value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
/* Collect all keysets for the port in a list */ if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) { switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) { case VCAP_IS2_PS_ARP_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_IS2_PS_ARP_ARP:
vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP); break;
}
}
if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) { switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); break; case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break;
}
switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); break; case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break;
}
}
if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break; case VCAP_IS2_PS_IPV6_UC_IP6_STD:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); break; case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); break;
}
switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) { case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break; case VCAP_IS2_PS_IPV6_MC_IP6_STD:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); break; case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); break; case VCAP_IS2_PS_IPV6_MC_IP6_VID: /* Not used */ break;
}
}
/* Return the keysets for the vcap port IP4 traffic class configuration */ staticvoid
sparx5_vcap_es2_get_port_ipv4_keysets(struct vcap_keyset_list *keysetlist,
u32 value)
{ switch (EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_GET(value)) { case VCAP_ES2_PS_IPV4_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_ES2_PS_IPV4_IP_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break; case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_VID:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); break; case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); break; case VCAP_ES2_PS_IPV4_IP4_VID: /* Not used */ break; case VCAP_ES2_PS_IPV4_IP4_OTHER:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); break;
}
}
/* Return the list of keysets for the vcap port configuration */ staticint sparx5_vcap_es0_get_port_keysets(struct net_device *ndev, struct vcap_keyset_list *keysetlist,
u16 l3_proto)
{ struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; int portno = port->portno;
u32 value;
value = spx5_rd(sparx5, REW_RTAG_ETAG_CTRL(portno));
/* Collect all keysets for the port in a list */ switch (REW_RTAG_ETAG_CTRL_ES0_ISDX_KEY_ENA_GET(value)) { case VCAP_ES0_PS_NORMAL_SELECTION: case VCAP_ES0_PS_FORCE_ISDX_LOOKUPS:
vcap_keyset_list_add(keysetlist, VCAP_KFS_ISDX); break; default: break;
} return0;
}
/* Return the list of keysets for the vcap port configuration */ staticint sparx5_vcap_es2_get_port_keysets(struct net_device *ndev, int lookup, struct vcap_keyset_list *keysetlist,
u16 l3_proto)
{ struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; int portno = port->portno;
u32 value;
value = spx5_rd(sparx5, EACL_VCAP_ES2_KEY_SEL(portno, lookup));
/* Collect all keysets for the port in a list */ if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) { switch (EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_GET(value)) { case VCAP_ES2_PS_ARP_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_ES2_PS_ARP_ARP:
vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP); break;
}
}
if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP)
sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist, value);
if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { switch (EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_GET(value)) { case VCAP_ES2_PS_IPV6_MAC_ETYPE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); break; case VCAP_ES2_PS_IPV6_IP_7TUPLE:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break; case VCAP_ES2_PS_IPV6_IP_7TUPLE_VID:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); break; case VCAP_ES2_PS_IPV6_IP_7TUPLE_STD:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE);
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); break; case VCAP_ES2_PS_IPV6_IP6_VID: /* Not used */ break; case VCAP_ES2_PS_IPV6_IP6_STD:
vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); break; case VCAP_ES2_PS_IPV6_IP4_DOWNGRADE:
sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist,
value); break;
}
}
/* Get the port keyset for the vcap lookup */ int sparx5_vcap_get_port_keyset(struct net_device *ndev, struct vcap_admin *admin, int cid,
u16 l3_proto, struct vcap_keyset_list *kslist)
{ int lookup, err = -EINVAL; struct sparx5_port *port;
/* Check if the ethertype is supported by the vcap port classification */ bool sparx5_vcap_is_known_etype(struct vcap_admin *admin, u16 etype)
{ const u16 *known_etypes; int size, idx;
switch (admin->vtype) { case VCAP_TYPE_IS0:
known_etypes = sparx5_vcap_is0_known_etypes;
size = ARRAY_SIZE(sparx5_vcap_is0_known_etypes); break; case VCAP_TYPE_IS2:
known_etypes = sparx5_vcap_is2_known_etypes;
size = ARRAY_SIZE(sparx5_vcap_is2_known_etypes); break; case VCAP_TYPE_ES0: returntrue; case VCAP_TYPE_ES2:
known_etypes = sparx5_vcap_es2_known_etypes;
size = ARRAY_SIZE(sparx5_vcap_es2_known_etypes); break; default: returnfalse;
} for (idx = 0; idx < size; ++idx) if (known_etypes[idx] == etype) returntrue; returnfalse;
}
/* API callback used for validating a field keyset (check the port keysets) */ staticenum vcap_keyfield_set
sparx5_vcap_validate_keyset(struct net_device *ndev, struct vcap_admin *admin, struct vcap_rule *rule, struct vcap_keyset_list *kslist,
u16 l3_proto)
{ struct vcap_keyset_list keysetlist = {}; enum vcap_keyfield_set keysets[10] = {}; struct sparx5_port *port; int idx, jdx, lookup;
if (!kslist || kslist->cnt == 0) return VCAP_KFS_NO_VALUE;
/* Get a list of currently configured keysets in the lookups */ switch (admin->vtype) { case VCAP_TYPE_IS0:
lookup = sparx5_vcap_is0_cid_to_lookup(rule->vcap_chain_id);
sparx5_vcap_is0_get_port_keysets(ndev, lookup, &keysetlist,
l3_proto); break; case VCAP_TYPE_IS2:
lookup = sparx5_vcap_is2_cid_to_lookup(rule->vcap_chain_id);
sparx5_vcap_is2_get_port_keysets(ndev, lookup, &keysetlist,
l3_proto); break; case VCAP_TYPE_ES0:
sparx5_vcap_es0_get_port_keysets(ndev, &keysetlist, l3_proto); break; case VCAP_TYPE_ES2:
lookup = sparx5_vcap_es2_cid_to_lookup(rule->vcap_chain_id);
sparx5_vcap_es2_get_port_keysets(ndev, lookup, &keysetlist,
l3_proto); break; default:
port = netdev_priv(ndev);
sparx5_vcap_type_err(port->sparx5, admin, __func__); break;
}
/* Check if there is a match and return the match */ for (idx = 0; idx < kslist->cnt; ++idx) for (jdx = 0; jdx < keysetlist.cnt; ++jdx) if (kslist->keysets[idx] == keysets[jdx]) return kslist->keysets[idx];
pr_err("%s:%d: %s not supported in port key selection\n",
__func__, __LINE__,
sparx5_vcap_keyset_name(ndev, kslist->keysets[0]));
vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO, port->portno, ~0); /* Match untagged frames if there was no VLAN key */
vcap_rule_add_key_u32(rule, VCAP_KF_8021Q_TPID, SPX5_TPID_SEL_UNTAGGED,
~0);
}
/* Add egress port mask matching the net device */
field = vcap_lookup_keyfield(rule, VCAP_KF_IF_EGR_PORT_MASK); if (field)
sparx5_vcap_add_egress_range_port_mask(rule, ndev);
/* Add key that selects the first/second lookup */
is_first = sparx5_vcap_es2_is_first_chain(rule);
if (is_first)
vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
VCAP_BIT_1); else
vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
VCAP_BIT_0);
}
/* API callback used for adding default fields to a rule */ staticvoid sparx5_vcap_add_default_fields(struct net_device *ndev, struct vcap_admin *admin, struct vcap_rule *rule)
{ struct sparx5_port *port;
/* add the lookup bit */ switch (admin->vtype) { case VCAP_TYPE_IS0: case VCAP_TYPE_IS2:
sparx5_vcap_ingress_add_default_fields(ndev, admin, rule); break; case VCAP_TYPE_ES0:
sparx5_vcap_es0_add_default_fields(ndev, admin, rule); break; case VCAP_TYPE_ES2:
sparx5_vcap_es2_add_default_fields(ndev, admin, rule); break; default:
port = netdev_priv(ndev);
sparx5_vcap_type_err(port->sparx5, admin, __func__); break;
}
}
/* API callback used for erasing the vcap cache area (not the register area) */ staticvoid sparx5_vcap_cache_erase(struct vcap_admin *admin)
{
memset(admin->cache.keystream, 0, STREAMSIZE);
memset(admin->cache.maskstream, 0, STREAMSIZE);
memset(admin->cache.actionstream, 0, STREAMSIZE);
memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
}
/* API callback used for moving a block of rules in the VCAP */ staticvoid sparx5_vcap_move(struct net_device *ndev, struct vcap_admin *admin,
u32 addr, int offset, int count)
{ struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; enum vcap_command cmd;
u16 mv_num_pos;
u16 mv_size;
static u32 sparx5_vcap_es2_keyset_to_ipv4_ps(enum vcap_keyfield_set keyset)
{ switch (keyset) { case VCAP_KFS_MAC_ETYPE: return VCAP_ES2_PS_IPV4_MAC_ETYPE; case VCAP_KFS_IP_7TUPLE: return VCAP_ES2_PS_IPV4_IP_7TUPLE; case VCAP_KFS_IP4_TCP_UDP: return VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER; case VCAP_KFS_IP4_OTHER: return VCAP_ES2_PS_IPV4_IP4_OTHER; default: return VCAP_ES2_PS_IPV4_MAC_ETYPE;
}
}
static u32 sparx5_vcap_es2_keyset_to_ipv6_ps(enum vcap_keyfield_set keyset)
{ switch (keyset) { case VCAP_KFS_MAC_ETYPE: return VCAP_ES2_PS_IPV6_MAC_ETYPE; case VCAP_KFS_IP4_TCP_UDP: case VCAP_KFS_IP4_OTHER: return VCAP_ES2_PS_IPV6_IP4_DOWNGRADE; case VCAP_KFS_IP_7TUPLE: return VCAP_ES2_PS_IPV6_IP_7TUPLE; case VCAP_KFS_IP6_STD: return VCAP_ES2_PS_IPV6_IP6_STD; default: return VCAP_ES2_PS_IPV6_MAC_ETYPE;
}
}
staticvoid sparx5_vcap_es2_set_port_keyset(struct net_device *ndev, int lookup, enum vcap_keyfield_set keyset, int l3_proto)
{ struct sparx5_port *port = netdev_priv(ndev); struct sparx5 *sparx5 = port->sparx5; int portno = port->portno;
u32 value;
switch (l3_proto) { case ETH_P_IP:
value = sparx5_vcap_es2_keyset_to_ipv4_ps(keyset);
spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(value),
EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL,
sparx5,
EACL_VCAP_ES2_KEY_SEL(portno, lookup)); break; case ETH_P_IPV6:
value = sparx5_vcap_es2_keyset_to_ipv6_ps(keyset);
spx5_rmw(EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(value),
EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL,
sparx5,
EACL_VCAP_ES2_KEY_SEL(portno, lookup)); break; case ETH_P_ARP:
value = sparx5_vcap_es2_keyset_to_arp_ps(keyset);
spx5_rmw(EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(value),
EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL,
sparx5,
EACL_VCAP_ES2_KEY_SEL(portno, lookup)); break;
}
}
/* Change the port keyset for the lookup and protocol */ void sparx5_vcap_set_port_keyset(struct net_device *ndev, struct vcap_admin *admin, int cid,
u16 l3_proto, enum vcap_keyfield_set keyset, struct vcap_keyset_list *orig)
{ struct sparx5_port *port; int lookup;
switch (admin->vtype) { case VCAP_TYPE_IS0:
lookup = sparx5_vcap_is0_cid_to_lookup(cid); if (orig)
sparx5_vcap_is0_get_port_keysets(ndev, lookup, orig,
l3_proto);
sparx5_vcap_is0_set_port_keyset(ndev, lookup, keyset, l3_proto); break; case VCAP_TYPE_IS2:
lookup = sparx5_vcap_is2_cid_to_lookup(cid); if (orig)
sparx5_vcap_is2_get_port_keysets(ndev, lookup, orig,
l3_proto);
sparx5_vcap_is2_set_port_keyset(ndev, lookup, keyset, l3_proto); break; case VCAP_TYPE_ES0: break; case VCAP_TYPE_ES2:
lookup = sparx5_vcap_es2_cid_to_lookup(cid); if (orig)
sparx5_vcap_es2_get_port_keysets(ndev, lookup, orig,
l3_proto);
sparx5_vcap_es2_set_port_keyset(ndev, lookup, keyset, l3_proto); break; default:
port = netdev_priv(ndev);
sparx5_vcap_type_err(port->sparx5, admin, __func__); break;
}
}
/* Enable IS0 lookups per port and set the keyset generation */ staticvoid sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5, struct vcap_admin *admin)
{ conststruct sparx5_consts *consts = sparx5->data->consts; int portno, lookup;
u32 keysel;
/* Enable IS2 lookups per port and set the keyset generation */ staticvoid sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5, struct vcap_admin *admin)
{ conststruct sparx5_consts *consts = sparx5->data->consts; int portno, lookup;
u32 keysel;
keysel = VCAP_IS2_KEYSEL(true, VCAP_IS2_PS_NONETH_MAC_ETYPE,
VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER,
VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER,
VCAP_IS2_PS_IPV6_MC_IP_7TUPLE,
VCAP_IS2_PS_IPV6_UC_IP_7TUPLE,
VCAP_IS2_PS_ARP_ARP); for (lookup = 0; lookup < admin->lookups; ++lookup) { for (portno = 0; portno < consts->n_ports; ++portno) {
spx5_wr(keysel, sparx5,
ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup));
}
} /* IS2 lookups are in bit 0:3 */ for (portno = 0; portno < consts->n_ports; ++portno)
spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0xf),
ANA_ACL_VCAP_S2_CFG_SEC_ENA,
sparx5,
ANA_ACL_VCAP_S2_CFG(portno));
}
/* Enable ES0 lookups per port and set the keyset generation */ staticvoid sparx5_vcap_es0_port_key_selection(struct sparx5 *sparx5, struct vcap_admin *admin)
{ conststruct sparx5_consts *consts = sparx5->data->consts; int portno;
u32 keysel;
/* Enable ES2 lookups per port and set the keyset generation */ staticvoid sparx5_vcap_es2_port_key_selection(struct sparx5 *sparx5, struct vcap_admin *admin)
{ conststruct sparx5_consts *consts = sparx5->data->consts; int portno, lookup;
u32 keysel;
/* Allocate a vcap instance with a rule list and a cache area */ staticstruct vcap_admin *
sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl, conststruct sparx5_vcap_inst *cfg)
{ struct vcap_admin *admin;
/* Do block allocations and provide addresses for VCAP instances */ staticvoid sparx5_vcap_block_alloc(struct sparx5 *sparx5, struct vcap_admin *admin, conststruct sparx5_vcap_inst *cfg)
{ int idx, cores;
/* Allocate a vcap control and vcap instances and configure the system */ int sparx5_vcap_init(struct sparx5 *sparx5)
{ conststruct sparx5_consts *consts = sparx5->data->consts; conststruct sparx5_vcap_inst *cfg; struct vcap_control *ctrl; struct vcap_admin *admin; struct dentry *dir; int err = 0, idx;
/* Create a VCAP control instance that owns the platform specific VCAP *modelwithVCAPinstancesandinformationaboutkeysets,keys, *actionsetsandactions *-CreateadministrativestateforeachavailableVCAP *-Listsofrules *-Addressinformation *-InitializeVCAPblocks *-Configureportkeysets
*/
ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM;
sparx5->vcap_ctrl = ctrl; /* select the sparx5 VCAP model */
ctrl->vcaps = consts->vcaps;
ctrl->stats = consts->vcap_stats; /* Setup callbacks to allow the API to use the VCAP HW */
ctrl->ops = &sparx5_vcap_ops;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.