1b0531225SHoratiu Vultur // SPDX-License-Identifier: GPL-2.0+
2b0531225SHoratiu Vultur
3b0531225SHoratiu Vultur #include "lan966x_main.h"
439bedc16SHoratiu Vultur #include "lan966x_vcap_ag_api.h"
5b0531225SHoratiu Vultur #include "vcap_api.h"
63643abd6SHoratiu Vultur #include "vcap_api_client.h"
794281484SHoratiu Vultur #include "vcap_api_debugfs.h"
83643abd6SHoratiu Vultur
93643abd6SHoratiu Vultur #define STREAMSIZE (64 * 4)
103643abd6SHoratiu Vultur
11*a4d9b3ecSHoratiu Vultur #define LAN966X_IS1_LOOKUPS 3
123643abd6SHoratiu Vultur #define LAN966X_IS2_LOOKUPS 2
133643abd6SHoratiu Vultur #define LAN966X_ES0_LOOKUPS 1
143643abd6SHoratiu Vultur
153643abd6SHoratiu Vultur #define LAN966X_STAT_ESDX_GRN_BYTES 0x300
163643abd6SHoratiu Vultur #define LAN966X_STAT_ESDX_GRN_PKTS 0x301
173643abd6SHoratiu Vultur #define LAN966X_STAT_ESDX_YEL_BYTES 0x302
183643abd6SHoratiu Vultur #define LAN966X_STAT_ESDX_YEL_PKTS 0x303
193643abd6SHoratiu Vultur
203643abd6SHoratiu Vultur static struct lan966x_vcap_inst {
21e7e3f514SSteen Hegelund enum vcap_type vtype; /* type of vcap */
223643abd6SHoratiu Vultur int tgt_inst; /* hardware instance number */
233643abd6SHoratiu Vultur int lookups; /* number of lookups in this vcap type */
24*a4d9b3ecSHoratiu Vultur int first_cid; /* first chain id in this vcap */
25*a4d9b3ecSHoratiu Vultur int last_cid; /* last chain id in this vcap */
26*a4d9b3ecSHoratiu Vultur int count; /* number of available addresses */
27*a4d9b3ecSHoratiu Vultur bool ingress; /* is vcap in the ingress path */
28*a4d9b3ecSHoratiu Vultur } lan966x_vcap_inst_cfg[] = {
29*a4d9b3ecSHoratiu Vultur {
30*a4d9b3ecSHoratiu Vultur .vtype = VCAP_TYPE_ES0,
31*a4d9b3ecSHoratiu Vultur .tgt_inst = 0,
32*a4d9b3ecSHoratiu Vultur .lookups = LAN966X_ES0_LOOKUPS,
333643abd6SHoratiu Vultur .first_cid = LAN966X_VCAP_CID_ES0_L0,
343643abd6SHoratiu Vultur .last_cid = LAN966X_VCAP_CID_ES0_MAX,
353643abd6SHoratiu Vultur .count = 64,
363643abd6SHoratiu Vultur },
373643abd6SHoratiu Vultur {
383643abd6SHoratiu Vultur .vtype = VCAP_TYPE_IS1, /* IS1-0 */
39e7e3f514SSteen Hegelund .tgt_inst = 1,
403643abd6SHoratiu Vultur .lookups = LAN966X_IS1_LOOKUPS,
413643abd6SHoratiu Vultur .first_cid = LAN966X_VCAP_CID_IS1_L0,
423643abd6SHoratiu Vultur .last_cid = LAN966X_VCAP_CID_IS1_MAX,
433643abd6SHoratiu Vultur .count = 768,
443643abd6SHoratiu Vultur .ingress = true,
453643abd6SHoratiu Vultur },
463643abd6SHoratiu Vultur {
473643abd6SHoratiu Vultur .vtype = VCAP_TYPE_IS2, /* IS2-0 */
483643abd6SHoratiu Vultur .tgt_inst = 2,
493643abd6SHoratiu Vultur .lookups = LAN966X_IS2_LOOKUPS,
503643abd6SHoratiu Vultur .first_cid = LAN966X_VCAP_CID_IS2_L0,
513643abd6SHoratiu Vultur .last_cid = LAN966X_VCAP_CID_IS2_MAX,
523643abd6SHoratiu Vultur .count = 256,
533643abd6SHoratiu Vultur .ingress = true,
543643abd6SHoratiu Vultur },
553643abd6SHoratiu Vultur };
563643abd6SHoratiu Vultur
573643abd6SHoratiu Vultur struct lan966x_vcap_cmd_cb {
583643abd6SHoratiu Vultur struct lan966x *lan966x;
593643abd6SHoratiu Vultur u32 instance;
603643abd6SHoratiu Vultur };
613643abd6SHoratiu Vultur
lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb * cb)623643abd6SHoratiu Vultur static u32 lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb *cb)
633643abd6SHoratiu Vultur {
643643abd6SHoratiu Vultur return lan_rd(cb->lan966x, VCAP_UPDATE_CTRL(cb->instance));
653643abd6SHoratiu Vultur }
663643abd6SHoratiu Vultur
lan966x_vcap_wait_update(struct lan966x * lan966x,int instance)673643abd6SHoratiu Vultur static void lan966x_vcap_wait_update(struct lan966x *lan966x, int instance)
683643abd6SHoratiu Vultur {
693643abd6SHoratiu Vultur const struct lan966x_vcap_cmd_cb cb = { .lan966x = lan966x,
703643abd6SHoratiu Vultur .instance = instance };
713643abd6SHoratiu Vultur u32 val;
723643abd6SHoratiu Vultur
733643abd6SHoratiu Vultur readx_poll_timeout(lan966x_vcap_read_update_ctrl, &cb, val,
743643abd6SHoratiu Vultur (val & VCAP_UPDATE_CTRL_UPDATE_SHOT) == 0, 10,
753643abd6SHoratiu Vultur 100000);
763643abd6SHoratiu Vultur }
773643abd6SHoratiu Vultur
__lan966x_vcap_range_init(struct lan966x * lan966x,struct vcap_admin * admin,u32 addr,u32 count)783643abd6SHoratiu Vultur static void __lan966x_vcap_range_init(struct lan966x *lan966x,
793643abd6SHoratiu Vultur struct vcap_admin *admin,
803643abd6SHoratiu Vultur u32 addr,
813643abd6SHoratiu Vultur u32 count)
823643abd6SHoratiu Vultur {
833643abd6SHoratiu Vultur lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
843643abd6SHoratiu Vultur VCAP_MV_CFG_MV_SIZE_SET(count - 1),
85*a4d9b3ecSHoratiu Vultur lan966x, VCAP_MV_CFG(admin->tgt_inst));
86*a4d9b3ecSHoratiu Vultur
87*a4d9b3ecSHoratiu Vultur lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) |
88*a4d9b3ecSHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
89*a4d9b3ecSHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
90*a4d9b3ecSHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
91*a4d9b3ecSHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
92*a4d9b3ecSHoratiu Vultur VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(true) |
93*a4d9b3ecSHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_SHOT_SET(1),
94*a4d9b3ecSHoratiu Vultur lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
95*a4d9b3ecSHoratiu Vultur
96*a4d9b3ecSHoratiu Vultur lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
97*a4d9b3ecSHoratiu Vultur }
98*a4d9b3ecSHoratiu Vultur
lan966x_vcap_is1_cid_to_lookup(int cid)99*a4d9b3ecSHoratiu Vultur static int lan966x_vcap_is1_cid_to_lookup(int cid)
1004426b78cSHoratiu Vultur {
1014426b78cSHoratiu Vultur int lookup = 0;
1024426b78cSHoratiu Vultur
1034426b78cSHoratiu Vultur if (cid >= LAN966X_VCAP_CID_IS1_L1 &&
1044426b78cSHoratiu Vultur cid < LAN966X_VCAP_CID_IS1_L2)
1054426b78cSHoratiu Vultur lookup = 1;
1064426b78cSHoratiu Vultur else if (cid >= LAN966X_VCAP_CID_IS1_L2 &&
1074426b78cSHoratiu Vultur cid < LAN966X_VCAP_CID_IS1_MAX)
108*a4d9b3ecSHoratiu Vultur lookup = 2;
109*a4d9b3ecSHoratiu Vultur
110*a4d9b3ecSHoratiu Vultur return lookup;
111*a4d9b3ecSHoratiu Vultur }
112*a4d9b3ecSHoratiu Vultur
lan966x_vcap_is2_cid_to_lookup(int cid)113*a4d9b3ecSHoratiu Vultur static int lan966x_vcap_is2_cid_to_lookup(int cid)
114*a4d9b3ecSHoratiu Vultur {
115*a4d9b3ecSHoratiu Vultur if (cid >= LAN966X_VCAP_CID_IS2_L1 &&
116*a4d9b3ecSHoratiu Vultur cid < LAN966X_VCAP_CID_IS2_MAX)
117*a4d9b3ecSHoratiu Vultur return 1;
118*a4d9b3ecSHoratiu Vultur
119*a4d9b3ecSHoratiu Vultur return 0;
120*a4d9b3ecSHoratiu Vultur }
121*a4d9b3ecSHoratiu Vultur
122*a4d9b3ecSHoratiu Vultur /* Return the list of keysets for the vcap port configuration */
123*a4d9b3ecSHoratiu Vultur static int
lan966x_vcap_is1_get_port_keysets(struct net_device * ndev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)124*a4d9b3ecSHoratiu Vultur lan966x_vcap_is1_get_port_keysets(struct net_device *ndev, int lookup,
125*a4d9b3ecSHoratiu Vultur struct vcap_keyset_list *keysetlist,
126*a4d9b3ecSHoratiu Vultur u16 l3_proto)
127*a4d9b3ecSHoratiu Vultur {
128*a4d9b3ecSHoratiu Vultur struct lan966x_port *port = netdev_priv(ndev);
129*a4d9b3ecSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
130*a4d9b3ecSHoratiu Vultur u32 val;
131*a4d9b3ecSHoratiu Vultur
132*a4d9b3ecSHoratiu Vultur val = lan_rd(lan966x, ANA_VCAP_S1_CFG(port->chip_port, lookup));
133*a4d9b3ecSHoratiu Vultur
134*a4d9b3ecSHoratiu Vultur /* Collect all keysets for the port in a list */
135*a4d9b3ecSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
136*a4d9b3ecSHoratiu Vultur switch (ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(val)) {
137*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV4_7TUPLE:
138*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
139*a4d9b3ecSHoratiu Vultur break;
140*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV4_5TUPLE_IP4:
141*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4);
142*a4d9b3ecSHoratiu Vultur break;
143*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV4_NORMAL:
144*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
145*a4d9b3ecSHoratiu Vultur break;
146*a4d9b3ecSHoratiu Vultur }
147*a4d9b3ecSHoratiu Vultur }
148*a4d9b3ecSHoratiu Vultur
149*a4d9b3ecSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
150*a4d9b3ecSHoratiu Vultur switch (ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(val)) {
151*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV6_NORMAL:
152*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV6_NORMAL_IP6:
153*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
154*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_IP6);
155*a4d9b3ecSHoratiu Vultur break;
156*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV6_5TUPLE_IP6:
157*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP6);
158*a4d9b3ecSHoratiu Vultur break;
159*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV6_7TUPLE:
160*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
161*a4d9b3ecSHoratiu Vultur break;
162*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV6_5TUPLE_IP4:
163*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4);
164*a4d9b3ecSHoratiu Vultur break;
165*a4d9b3ecSHoratiu Vultur case VCAP_IS1_PS_IPV6_DMAC_VID:
166*a4d9b3ecSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_DMAC_VID);
167*a4d9b3ecSHoratiu Vultur break;
168*a4d9b3ecSHoratiu Vultur }
1694426b78cSHoratiu Vultur }
1704426b78cSHoratiu Vultur
1714426b78cSHoratiu Vultur switch (ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(val)) {
1724426b78cSHoratiu Vultur case VCAP_IS1_PS_OTHER_7TUPLE:
1734426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE);
1744426b78cSHoratiu Vultur break;
1754426b78cSHoratiu Vultur case VCAP_IS1_PS_OTHER_NORMAL:
1764426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL);
1774426b78cSHoratiu Vultur break;
1784426b78cSHoratiu Vultur }
1794426b78cSHoratiu Vultur
1804426b78cSHoratiu Vultur return 0;
1814426b78cSHoratiu Vultur }
1824426b78cSHoratiu Vultur
1834426b78cSHoratiu Vultur static int
lan966x_vcap_is2_get_port_keysets(struct net_device * dev,int lookup,struct vcap_keyset_list * keysetlist,u16 l3_proto)1844426b78cSHoratiu Vultur lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup,
1854426b78cSHoratiu Vultur struct vcap_keyset_list *keysetlist,
1864426b78cSHoratiu Vultur u16 l3_proto)
1874426b78cSHoratiu Vultur {
1884426b78cSHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
1894426b78cSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
1904426b78cSHoratiu Vultur bool found = false;
1914426b78cSHoratiu Vultur u32 val;
1924426b78cSHoratiu Vultur
1934426b78cSHoratiu Vultur val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port));
1944426b78cSHoratiu Vultur
1954426b78cSHoratiu Vultur /* Collect all keysets for the port in a list */
1964426b78cSHoratiu Vultur if (l3_proto == ETH_P_ALL)
1974426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
1984426b78cSHoratiu Vultur
1994426b78cSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_SNAP) {
2004426b78cSHoratiu Vultur if (ANA_VCAP_S2_CFG_SNAP_DIS_GET(val) & (BIT(0) << lookup))
2014426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_LLC);
2024426b78cSHoratiu Vultur else
2034426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_SNAP);
2044426b78cSHoratiu Vultur
2054426b78cSHoratiu Vultur found = true;
2064426b78cSHoratiu Vultur }
2074426b78cSHoratiu Vultur
2084426b78cSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_CFM) {
2094426b78cSHoratiu Vultur if (ANA_VCAP_S2_CFG_OAM_DIS_GET(val) & (BIT(0) << lookup))
2104426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
2114426b78cSHoratiu Vultur else
2124426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_OAM);
2134426b78cSHoratiu Vultur
2144426b78cSHoratiu Vultur found = true;
2154426b78cSHoratiu Vultur }
2164426b78cSHoratiu Vultur
2174426b78cSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) {
2184426b78cSHoratiu Vultur if (ANA_VCAP_S2_CFG_ARP_DIS_GET(val) & (BIT(0) << lookup))
2194426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
2204426b78cSHoratiu Vultur else
2214426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP);
2224426b78cSHoratiu Vultur
2234426b78cSHoratiu Vultur found = true;
2244426b78cSHoratiu Vultur }
2254426b78cSHoratiu Vultur
2264426b78cSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) {
2274426b78cSHoratiu Vultur if (ANA_VCAP_S2_CFG_IP_OTHER_DIS_GET(val) & (BIT(0) << lookup))
2284426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
2294426b78cSHoratiu Vultur else
2304426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
2314426b78cSHoratiu Vultur
2324426b78cSHoratiu Vultur if (ANA_VCAP_S2_CFG_IP_TCPUDP_DIS_GET(val) & (BIT(0) << lookup))
2334426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
2344426b78cSHoratiu Vultur else
2354426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
2364426b78cSHoratiu Vultur
2374426b78cSHoratiu Vultur found = true;
2384426b78cSHoratiu Vultur }
2394426b78cSHoratiu Vultur
2404426b78cSHoratiu Vultur if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) {
2414426b78cSHoratiu Vultur switch (ANA_VCAP_S2_CFG_IP6_CFG_GET(val) & (0x3 << lookup)) {
2424426b78cSHoratiu Vultur case VCAP_IS2_PS_IPV6_TCPUDP_OTHER:
2434426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_OTHER);
2444426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_TCP_UDP);
2454426b78cSHoratiu Vultur break;
2464426b78cSHoratiu Vultur case VCAP_IS2_PS_IPV6_STD:
2474426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD);
2484426b78cSHoratiu Vultur break;
2494426b78cSHoratiu Vultur case VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER:
2504426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER);
2514426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP);
2524426b78cSHoratiu Vultur break;
2534426b78cSHoratiu Vultur case VCAP_IS2_PS_IPV6_MAC_ETYPE:
2544426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
2554426b78cSHoratiu Vultur break;
2564426b78cSHoratiu Vultur }
2574426b78cSHoratiu Vultur
2584426b78cSHoratiu Vultur found = true;
2594426b78cSHoratiu Vultur }
2604426b78cSHoratiu Vultur
2614426b78cSHoratiu Vultur if (!found)
2624426b78cSHoratiu Vultur vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE);
2634426b78cSHoratiu Vultur
2644426b78cSHoratiu Vultur return 0;
2654426b78cSHoratiu Vultur }
2664426b78cSHoratiu Vultur
2674426b78cSHoratiu Vultur static enum vcap_keyfield_set
lan966x_vcap_validate_keyset(struct net_device * dev,struct vcap_admin * admin,struct vcap_rule * rule,struct vcap_keyset_list * kslist,u16 l3_proto)2684426b78cSHoratiu Vultur lan966x_vcap_validate_keyset(struct net_device *dev,
2694426b78cSHoratiu Vultur struct vcap_admin *admin,
270*a4d9b3ecSHoratiu Vultur struct vcap_rule *rule,
271*a4d9b3ecSHoratiu Vultur struct vcap_keyset_list *kslist,
272*a4d9b3ecSHoratiu Vultur u16 l3_proto)
273*a4d9b3ecSHoratiu Vultur {
274*a4d9b3ecSHoratiu Vultur struct vcap_keyset_list keysetlist = {};
275*a4d9b3ecSHoratiu Vultur enum vcap_keyfield_set keysets[10] = {};
276*a4d9b3ecSHoratiu Vultur int lookup;
277*a4d9b3ecSHoratiu Vultur int err;
278*a4d9b3ecSHoratiu Vultur
2794426b78cSHoratiu Vultur if (!kslist || kslist->cnt == 0)
2804426b78cSHoratiu Vultur return VCAP_KFS_NO_VALUE;
281*a4d9b3ecSHoratiu Vultur
282*a4d9b3ecSHoratiu Vultur keysetlist.max = ARRAY_SIZE(keysets);
283*a4d9b3ecSHoratiu Vultur keysetlist.keysets = keysets;
284*a4d9b3ecSHoratiu Vultur
285*a4d9b3ecSHoratiu Vultur switch (admin->vtype) {
286*a4d9b3ecSHoratiu Vultur case VCAP_TYPE_IS1:
287*a4d9b3ecSHoratiu Vultur lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id);
2884426b78cSHoratiu Vultur err = lan966x_vcap_is1_get_port_keysets(dev, lookup, &keysetlist,
2894426b78cSHoratiu Vultur l3_proto);
2904426b78cSHoratiu Vultur break;
2914426b78cSHoratiu Vultur case VCAP_TYPE_IS2:
2924426b78cSHoratiu Vultur lookup = lan966x_vcap_is2_cid_to_lookup(rule->vcap_chain_id);
2934426b78cSHoratiu Vultur err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist,
2944426b78cSHoratiu Vultur l3_proto);
2954426b78cSHoratiu Vultur break;
2964426b78cSHoratiu Vultur case VCAP_TYPE_ES0:
2974426b78cSHoratiu Vultur return kslist->keysets[0];
2984426b78cSHoratiu Vultur default:
2994426b78cSHoratiu Vultur pr_err("vcap type: %s not supported\n",
300*a4d9b3ecSHoratiu Vultur lan966x_vcaps[admin->vtype].name);
3014426b78cSHoratiu Vultur return VCAP_KFS_NO_VALUE;
3024426b78cSHoratiu Vultur }
3034426b78cSHoratiu Vultur
3044426b78cSHoratiu Vultur if (err)
3054426b78cSHoratiu Vultur return VCAP_KFS_NO_VALUE;
306*a4d9b3ecSHoratiu Vultur
3074426b78cSHoratiu Vultur /* Check if there is a match and return the match */
3084426b78cSHoratiu Vultur for (int i = 0; i < kslist->cnt; ++i)
3094426b78cSHoratiu Vultur for (int j = 0; j < keysetlist.cnt; ++j)
310*a4d9b3ecSHoratiu Vultur if (kslist->keysets[i] == keysets[j])
311*a4d9b3ecSHoratiu Vultur return kslist->keysets[i];
312*a4d9b3ecSHoratiu Vultur
313*a4d9b3ecSHoratiu Vultur return VCAP_KFS_NO_VALUE;
314*a4d9b3ecSHoratiu Vultur }
315*a4d9b3ecSHoratiu Vultur
lan966x_vcap_is2_is_first_chain(struct vcap_rule * rule)316*a4d9b3ecSHoratiu Vultur static bool lan966x_vcap_is2_is_first_chain(struct vcap_rule *rule)
317*a4d9b3ecSHoratiu Vultur {
318*a4d9b3ecSHoratiu Vultur return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 &&
319*a4d9b3ecSHoratiu Vultur rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1);
320*a4d9b3ecSHoratiu Vultur }
321*a4d9b3ecSHoratiu Vultur
lan966x_vcap_is1_add_default_fields(struct lan966x_port * port,struct vcap_admin * admin,struct vcap_rule * rule)322*a4d9b3ecSHoratiu Vultur static void lan966x_vcap_is1_add_default_fields(struct lan966x_port *port,
323*a4d9b3ecSHoratiu Vultur struct vcap_admin *admin,
324*a4d9b3ecSHoratiu Vultur struct vcap_rule *rule)
325*a4d9b3ecSHoratiu Vultur {
32672df3489SHoratiu Vultur u32 value, mask;
3274426b78cSHoratiu Vultur u32 lookup;
32872df3489SHoratiu Vultur
32972df3489SHoratiu Vultur if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
3304426b78cSHoratiu Vultur &value, &mask))
3314426b78cSHoratiu Vultur vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
3324426b78cSHoratiu Vultur ~BIT(port->chip_port));
333*a4d9b3ecSHoratiu Vultur
3344426b78cSHoratiu Vultur lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id);
3354426b78cSHoratiu Vultur vcap_rule_add_key_u32(rule, VCAP_KF_LOOKUP_INDEX, lookup, 0x3);
3364426b78cSHoratiu Vultur }
3374426b78cSHoratiu Vultur
lan966x_vcap_is2_add_default_fields(struct lan966x_port * port,struct vcap_admin * admin,struct vcap_rule * rule)3384426b78cSHoratiu Vultur static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port,
3394426b78cSHoratiu Vultur struct vcap_admin *admin,
3404426b78cSHoratiu Vultur struct vcap_rule *rule)
341*a4d9b3ecSHoratiu Vultur {
342*a4d9b3ecSHoratiu Vultur u32 value, mask;
343*a4d9b3ecSHoratiu Vultur
344*a4d9b3ecSHoratiu Vultur if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK,
345*a4d9b3ecSHoratiu Vultur &value, &mask))
346*a4d9b3ecSHoratiu Vultur vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0,
347*a4d9b3ecSHoratiu Vultur ~BIT(port->chip_port));
348*a4d9b3ecSHoratiu Vultur
349*a4d9b3ecSHoratiu Vultur if (lan966x_vcap_is2_is_first_chain(rule))
350*a4d9b3ecSHoratiu Vultur vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
351*a4d9b3ecSHoratiu Vultur VCAP_BIT_1);
352*a4d9b3ecSHoratiu Vultur else
353*a4d9b3ecSHoratiu Vultur vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS,
354*a4d9b3ecSHoratiu Vultur VCAP_BIT_0);
355*a4d9b3ecSHoratiu Vultur }
356*a4d9b3ecSHoratiu Vultur
lan966x_vcap_es0_add_default_fields(struct lan966x_port * port,struct vcap_admin * admin,struct vcap_rule * rule)357*a4d9b3ecSHoratiu Vultur static void lan966x_vcap_es0_add_default_fields(struct lan966x_port *port,
358*a4d9b3ecSHoratiu Vultur struct vcap_admin *admin,
359*a4d9b3ecSHoratiu Vultur struct vcap_rule *rule)
360*a4d9b3ecSHoratiu Vultur {
3614426b78cSHoratiu Vultur vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_NO,
3624426b78cSHoratiu Vultur port->chip_port, GENMASK(4, 0));
3634426b78cSHoratiu Vultur }
3644426b78cSHoratiu Vultur
lan966x_vcap_add_default_fields(struct net_device * dev,struct vcap_admin * admin,struct vcap_rule * rule)3654426b78cSHoratiu Vultur static void lan966x_vcap_add_default_fields(struct net_device *dev,
3664426b78cSHoratiu Vultur struct vcap_admin *admin,
3674426b78cSHoratiu Vultur struct vcap_rule *rule)
3684426b78cSHoratiu Vultur {
3694426b78cSHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
3704426b78cSHoratiu Vultur
3714426b78cSHoratiu Vultur switch (admin->vtype) {
3724426b78cSHoratiu Vultur case VCAP_TYPE_IS1:
3734426b78cSHoratiu Vultur lan966x_vcap_is1_add_default_fields(port, admin, rule);
3744426b78cSHoratiu Vultur break;
3754426b78cSHoratiu Vultur case VCAP_TYPE_IS2:
3764426b78cSHoratiu Vultur lan966x_vcap_is2_add_default_fields(port, admin, rule);
3774426b78cSHoratiu Vultur break;
3784426b78cSHoratiu Vultur case VCAP_TYPE_ES0:
3794426b78cSHoratiu Vultur lan966x_vcap_es0_add_default_fields(port, admin, rule);
3804426b78cSHoratiu Vultur break;
3814426b78cSHoratiu Vultur default:
3824426b78cSHoratiu Vultur pr_err("vcap type: %s not supported\n",
3834426b78cSHoratiu Vultur lan966x_vcaps[admin->vtype].name);
3844426b78cSHoratiu Vultur break;
3854426b78cSHoratiu Vultur }
3864426b78cSHoratiu Vultur }
3874426b78cSHoratiu Vultur
lan966x_vcap_cache_erase(struct vcap_admin * admin)3884426b78cSHoratiu Vultur static void lan966x_vcap_cache_erase(struct vcap_admin *admin)
3894426b78cSHoratiu Vultur {
3904426b78cSHoratiu Vultur memset(admin->cache.keystream, 0, STREAMSIZE);
3914426b78cSHoratiu Vultur memset(admin->cache.maskstream, 0, STREAMSIZE);
3924426b78cSHoratiu Vultur memset(admin->cache.actionstream, 0, STREAMSIZE);
3934426b78cSHoratiu Vultur memset(&admin->cache.counter, 0, sizeof(admin->cache.counter));
3944426b78cSHoratiu Vultur }
3954426b78cSHoratiu Vultur
3964426b78cSHoratiu Vultur /* The ESDX counter is only used/incremented if the frame has been classified
3974426b78cSHoratiu Vultur * with an ISDX > 0 (e.g by a rule in IS0). This is not mentioned in the
3984426b78cSHoratiu Vultur * datasheet.
3994426b78cSHoratiu Vultur */
lan966x_es0_read_esdx_counter(struct lan966x * lan966x,struct vcap_admin * admin,u32 id)4004426b78cSHoratiu Vultur static void lan966x_es0_read_esdx_counter(struct lan966x *lan966x,
4014426b78cSHoratiu Vultur struct vcap_admin *admin, u32 id)
4024426b78cSHoratiu Vultur {
4034426b78cSHoratiu Vultur u32 counter;
4044426b78cSHoratiu Vultur
4054426b78cSHoratiu Vultur id = id & 0xff; /* counter limit */
4064426b78cSHoratiu Vultur mutex_lock(&lan966x->stats_lock);
4074426b78cSHoratiu Vultur lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
4084426b78cSHoratiu Vultur counter = lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS)) +
4094426b78cSHoratiu Vultur lan_rd(lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
4104426b78cSHoratiu Vultur mutex_unlock(&lan966x->stats_lock);
4114426b78cSHoratiu Vultur if (counter)
4124426b78cSHoratiu Vultur admin->cache.counter = counter;
4134426b78cSHoratiu Vultur }
4144426b78cSHoratiu Vultur
lan966x_es0_write_esdx_counter(struct lan966x * lan966x,struct vcap_admin * admin,u32 id)4154426b78cSHoratiu Vultur static void lan966x_es0_write_esdx_counter(struct lan966x *lan966x,
4164426b78cSHoratiu Vultur struct vcap_admin *admin, u32 id)
4174426b78cSHoratiu Vultur {
4184426b78cSHoratiu Vultur id = id & 0xff; /* counter limit */
4194426b78cSHoratiu Vultur
4204426b78cSHoratiu Vultur mutex_lock(&lan966x->stats_lock);
4214426b78cSHoratiu Vultur lan_wr(SYS_STAT_CFG_STAT_VIEW_SET(id), lan966x, SYS_STAT_CFG);
4224426b78cSHoratiu Vultur lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_GRN_BYTES));
4234426b78cSHoratiu Vultur lan_wr(admin->cache.counter, lan966x,
4244426b78cSHoratiu Vultur SYS_CNT(LAN966X_STAT_ESDX_GRN_PKTS));
4254426b78cSHoratiu Vultur lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_BYTES));
4264426b78cSHoratiu Vultur lan_wr(0, lan966x, SYS_CNT(LAN966X_STAT_ESDX_YEL_PKTS));
4274426b78cSHoratiu Vultur mutex_unlock(&lan966x->stats_lock);
4284426b78cSHoratiu Vultur }
4294426b78cSHoratiu Vultur
lan966x_vcap_cache_write(struct net_device * dev,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)4304426b78cSHoratiu Vultur static void lan966x_vcap_cache_write(struct net_device *dev,
4314426b78cSHoratiu Vultur struct vcap_admin *admin,
4324426b78cSHoratiu Vultur enum vcap_selection sel,
4334426b78cSHoratiu Vultur u32 start,
4344426b78cSHoratiu Vultur u32 count)
4354426b78cSHoratiu Vultur {
4364426b78cSHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
4374426b78cSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
4384426b78cSHoratiu Vultur u32 *keystr, *mskstr, *actstr;
4394426b78cSHoratiu Vultur
4404426b78cSHoratiu Vultur keystr = &admin->cache.keystream[start];
4414426b78cSHoratiu Vultur mskstr = &admin->cache.maskstream[start];
4424426b78cSHoratiu Vultur actstr = &admin->cache.actionstream[start];
4434426b78cSHoratiu Vultur
4444426b78cSHoratiu Vultur switch (sel) {
4454426b78cSHoratiu Vultur case VCAP_SEL_ENTRY:
4464426b78cSHoratiu Vultur for (int i = 0; i < count; ++i) {
4474426b78cSHoratiu Vultur lan_wr(keystr[i] & mskstr[i], lan966x,
4484426b78cSHoratiu Vultur VCAP_ENTRY_DAT(admin->tgt_inst, i));
4494426b78cSHoratiu Vultur lan_wr(~mskstr[i], lan966x,
4504426b78cSHoratiu Vultur VCAP_MASK_DAT(admin->tgt_inst, i));
4514426b78cSHoratiu Vultur }
4524426b78cSHoratiu Vultur break;
4534426b78cSHoratiu Vultur case VCAP_SEL_ACTION:
4544426b78cSHoratiu Vultur for (int i = 0; i < count; ++i)
4554426b78cSHoratiu Vultur lan_wr(actstr[i], lan966x,
4564426b78cSHoratiu Vultur VCAP_ACTION_DAT(admin->tgt_inst, i));
4574426b78cSHoratiu Vultur break;
4584426b78cSHoratiu Vultur case VCAP_SEL_COUNTER:
4594426b78cSHoratiu Vultur admin->cache.sticky = admin->cache.counter > 0;
4604426b78cSHoratiu Vultur lan_wr(admin->cache.counter, lan966x,
4614426b78cSHoratiu Vultur VCAP_CNT_DAT(admin->tgt_inst, 0));
4624426b78cSHoratiu Vultur
4634426b78cSHoratiu Vultur if (admin->vtype == VCAP_TYPE_ES0)
4644426b78cSHoratiu Vultur lan966x_es0_write_esdx_counter(lan966x, admin, start);
4654426b78cSHoratiu Vultur break;
4664426b78cSHoratiu Vultur default:
4674426b78cSHoratiu Vultur break;
4684426b78cSHoratiu Vultur }
4694426b78cSHoratiu Vultur }
4704426b78cSHoratiu Vultur
lan966x_vcap_cache_read(struct net_device * dev,struct vcap_admin * admin,enum vcap_selection sel,u32 start,u32 count)4714426b78cSHoratiu Vultur static void lan966x_vcap_cache_read(struct net_device *dev,
4724426b78cSHoratiu Vultur struct vcap_admin *admin,
4734426b78cSHoratiu Vultur enum vcap_selection sel,
4744426b78cSHoratiu Vultur u32 start,
4754426b78cSHoratiu Vultur u32 count)
4764426b78cSHoratiu Vultur {
4774426b78cSHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
4784426b78cSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
4794426b78cSHoratiu Vultur int instance = admin->tgt_inst;
4804426b78cSHoratiu Vultur u32 *keystr, *mskstr, *actstr;
4814426b78cSHoratiu Vultur
4824426b78cSHoratiu Vultur keystr = &admin->cache.keystream[start];
4834426b78cSHoratiu Vultur mskstr = &admin->cache.maskstream[start];
4844426b78cSHoratiu Vultur actstr = &admin->cache.actionstream[start];
4854426b78cSHoratiu Vultur
4864426b78cSHoratiu Vultur if (sel & VCAP_SEL_ENTRY) {
4874426b78cSHoratiu Vultur for (int i = 0; i < count; ++i) {
4884426b78cSHoratiu Vultur keystr[i] =
4894426b78cSHoratiu Vultur lan_rd(lan966x, VCAP_ENTRY_DAT(instance, i));
4904426b78cSHoratiu Vultur mskstr[i] =
4914426b78cSHoratiu Vultur ~lan_rd(lan966x, VCAP_MASK_DAT(instance, i));
4924426b78cSHoratiu Vultur }
4934426b78cSHoratiu Vultur }
4944426b78cSHoratiu Vultur
4954426b78cSHoratiu Vultur if (sel & VCAP_SEL_ACTION)
4964426b78cSHoratiu Vultur for (int i = 0; i < count; ++i)
4974426b78cSHoratiu Vultur actstr[i] =
4984426b78cSHoratiu Vultur lan_rd(lan966x, VCAP_ACTION_DAT(instance, i));
4994426b78cSHoratiu Vultur
5004426b78cSHoratiu Vultur if (sel & VCAP_SEL_COUNTER) {
5014426b78cSHoratiu Vultur admin->cache.counter =
5024426b78cSHoratiu Vultur lan_rd(lan966x, VCAP_CNT_DAT(instance, 0));
5034426b78cSHoratiu Vultur admin->cache.sticky = admin->cache.counter > 0;
5044426b78cSHoratiu Vultur
5054426b78cSHoratiu Vultur if (admin->vtype == VCAP_TYPE_ES0)
5064426b78cSHoratiu Vultur lan966x_es0_read_esdx_counter(lan966x, admin, start);
5074426b78cSHoratiu Vultur }
5084426b78cSHoratiu Vultur }
5094426b78cSHoratiu Vultur
lan966x_vcap_range_init(struct net_device * dev,struct vcap_admin * admin,u32 addr,u32 count)5104426b78cSHoratiu Vultur static void lan966x_vcap_range_init(struct net_device *dev,
5114426b78cSHoratiu Vultur struct vcap_admin *admin,
5124426b78cSHoratiu Vultur u32 addr,
5134426b78cSHoratiu Vultur u32 count)
5144426b78cSHoratiu Vultur {
5154426b78cSHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
5164426b78cSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
5174426b78cSHoratiu Vultur
5184426b78cSHoratiu Vultur __lan966x_vcap_range_init(lan966x, admin, addr, count);
5194426b78cSHoratiu Vultur }
5204426b78cSHoratiu Vultur
lan966x_vcap_update(struct net_device * dev,struct vcap_admin * admin,enum vcap_command cmd,enum vcap_selection sel,u32 addr)5214426b78cSHoratiu Vultur static void lan966x_vcap_update(struct net_device *dev,
5224426b78cSHoratiu Vultur struct vcap_admin *admin,
5234426b78cSHoratiu Vultur enum vcap_command cmd,
5244426b78cSHoratiu Vultur enum vcap_selection sel,
5254426b78cSHoratiu Vultur u32 addr)
5264426b78cSHoratiu Vultur {
5274426b78cSHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
5284426b78cSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
5293643abd6SHoratiu Vultur bool clear;
5303643abd6SHoratiu Vultur
5313643abd6SHoratiu Vultur clear = (cmd == VCAP_CMD_INITIALIZE);
5323643abd6SHoratiu Vultur
5333643abd6SHoratiu Vultur lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) |
5343643abd6SHoratiu Vultur VCAP_MV_CFG_MV_SIZE_SET(0),
5353643abd6SHoratiu Vultur lan966x, VCAP_MV_CFG(admin->tgt_inst));
5363643abd6SHoratiu Vultur
5373643abd6SHoratiu Vultur lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
5383643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) |
5393643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) |
5403643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) |
5413643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
5423643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(clear) |
5433643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_SHOT,
5443643abd6SHoratiu Vultur lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
5453643abd6SHoratiu Vultur
5463643abd6SHoratiu Vultur lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
5473643abd6SHoratiu Vultur }
5483643abd6SHoratiu Vultur
lan966x_vcap_move(struct net_device * dev,struct vcap_admin * admin,u32 addr,int offset,int count)5493643abd6SHoratiu Vultur static void lan966x_vcap_move(struct net_device *dev,
5503643abd6SHoratiu Vultur struct vcap_admin *admin,
5513643abd6SHoratiu Vultur u32 addr, int offset, int count)
5523643abd6SHoratiu Vultur {
5533643abd6SHoratiu Vultur struct lan966x_port *port = netdev_priv(dev);
5544426b78cSHoratiu Vultur struct lan966x *lan966x = port->lan966x;
5554426b78cSHoratiu Vultur enum vcap_command cmd;
5563643abd6SHoratiu Vultur u16 mv_num_pos;
5573643abd6SHoratiu Vultur u16 mv_size;
558e7e3f514SSteen Hegelund
5594426b78cSHoratiu Vultur mv_size = count - 1;
5604426b78cSHoratiu Vultur if (offset > 0) {
5614426b78cSHoratiu Vultur mv_num_pos = offset - 1;
5623643abd6SHoratiu Vultur cmd = VCAP_CMD_MOVE_DOWN;
5633643abd6SHoratiu Vultur } else {
5644426b78cSHoratiu Vultur mv_num_pos = -offset - 1;
5653643abd6SHoratiu Vultur cmd = VCAP_CMD_MOVE_UP;
5663643abd6SHoratiu Vultur }
5674426b78cSHoratiu Vultur
5683643abd6SHoratiu Vultur lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(mv_num_pos) |
5693643abd6SHoratiu Vultur VCAP_MV_CFG_MV_SIZE_SET(mv_size),
5703643abd6SHoratiu Vultur lan966x, VCAP_MV_CFG(admin->tgt_inst));
5713643abd6SHoratiu Vultur
5723643abd6SHoratiu Vultur lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) |
5733643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) |
5743643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) |
5753643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) |
5763643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) |
5773643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(false) |
5783643abd6SHoratiu Vultur VCAP_UPDATE_CTRL_UPDATE_SHOT,
5793643abd6SHoratiu Vultur lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst));
5803643abd6SHoratiu Vultur
5813643abd6SHoratiu Vultur lan966x_vcap_wait_update(lan966x, admin->tgt_inst);
5823643abd6SHoratiu Vultur }
5833643abd6SHoratiu Vultur
5843643abd6SHoratiu Vultur static struct vcap_operations lan966x_vcap_ops = {
5853643abd6SHoratiu Vultur .validate_keyset = lan966x_vcap_validate_keyset,
5863643abd6SHoratiu Vultur .add_default_fields = lan966x_vcap_add_default_fields,
5873643abd6SHoratiu Vultur .cache_erase = lan966x_vcap_cache_erase,
5883643abd6SHoratiu Vultur .cache_write = lan966x_vcap_cache_write,
5893643abd6SHoratiu Vultur .cache_read = lan966x_vcap_cache_read,
5903643abd6SHoratiu Vultur .init = lan966x_vcap_range_init,
5913643abd6SHoratiu Vultur .update = lan966x_vcap_update,
5923643abd6SHoratiu Vultur .move = lan966x_vcap_move,
5933643abd6SHoratiu Vultur .port_info = lan966x_vcap_port_info,
5943643abd6SHoratiu Vultur };
5953643abd6SHoratiu Vultur
lan966x_vcap_admin_free(struct vcap_admin * admin)5963643abd6SHoratiu Vultur static void lan966x_vcap_admin_free(struct vcap_admin *admin)
5973643abd6SHoratiu Vultur {
598b0531225SHoratiu Vultur if (!admin)
5994426b78cSHoratiu Vultur return;
6004426b78cSHoratiu Vultur
6014426b78cSHoratiu Vultur kfree(admin->cache.keystream);
602*a4d9b3ecSHoratiu Vultur kfree(admin->cache.maskstream);
603*a4d9b3ecSHoratiu Vultur kfree(admin->cache.actionstream);
604*a4d9b3ecSHoratiu Vultur mutex_destroy(&admin->lock);
605*a4d9b3ecSHoratiu Vultur kfree(admin);
606*a4d9b3ecSHoratiu Vultur }
607*a4d9b3ecSHoratiu Vultur
608*a4d9b3ecSHoratiu Vultur static struct vcap_admin *
lan966x_vcap_admin_alloc(struct lan966x * lan966x,struct vcap_control * ctrl,const struct lan966x_vcap_inst * cfg)609*a4d9b3ecSHoratiu Vultur lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl,
610*a4d9b3ecSHoratiu Vultur const struct lan966x_vcap_inst *cfg)
611*a4d9b3ecSHoratiu Vultur {
612*a4d9b3ecSHoratiu Vultur struct vcap_admin *admin;
613*a4d9b3ecSHoratiu Vultur
614*a4d9b3ecSHoratiu Vultur admin = kzalloc(sizeof(*admin), GFP_KERNEL);
615*a4d9b3ecSHoratiu Vultur if (!admin)
616*a4d9b3ecSHoratiu Vultur return ERR_PTR(-ENOMEM);
617*a4d9b3ecSHoratiu Vultur
618*a4d9b3ecSHoratiu Vultur mutex_init(&admin->lock);
619*a4d9b3ecSHoratiu Vultur INIT_LIST_HEAD(&admin->list);
620*a4d9b3ecSHoratiu Vultur INIT_LIST_HEAD(&admin->rules);
621*a4d9b3ecSHoratiu Vultur INIT_LIST_HEAD(&admin->enabled);
622*a4d9b3ecSHoratiu Vultur
623*a4d9b3ecSHoratiu Vultur admin->vtype = cfg->vtype;
6244426b78cSHoratiu Vultur admin->vinst = 0;
6254426b78cSHoratiu Vultur admin->ingress = cfg->ingress;
626*a4d9b3ecSHoratiu Vultur admin->w32be = true;
627*a4d9b3ecSHoratiu Vultur admin->tgt_inst = cfg->tgt_inst;
628*a4d9b3ecSHoratiu Vultur
629*a4d9b3ecSHoratiu Vultur admin->lookups = cfg->lookups;
630*a4d9b3ecSHoratiu Vultur admin->lookups_per_instance = cfg->lookups;
631*a4d9b3ecSHoratiu Vultur
632*a4d9b3ecSHoratiu Vultur admin->first_cid = cfg->first_cid;
6334426b78cSHoratiu Vultur admin->last_cid = cfg->last_cid;
6344426b78cSHoratiu Vultur
635b0531225SHoratiu Vultur admin->cache.keystream = kzalloc(STREAMSIZE, GFP_KERNEL);
636b0531225SHoratiu Vultur admin->cache.maskstream = kzalloc(STREAMSIZE, GFP_KERNEL);
6373643abd6SHoratiu Vultur admin->cache.actionstream = kzalloc(STREAMSIZE, GFP_KERNEL);
638b0531225SHoratiu Vultur if (!admin->cache.keystream ||
6393643abd6SHoratiu Vultur !admin->cache.maskstream ||
64094281484SHoratiu Vultur !admin->cache.actionstream) {
641b0531225SHoratiu Vultur lan966x_vcap_admin_free(admin);
642b0531225SHoratiu Vultur return ERR_PTR(-ENOMEM);
643b0531225SHoratiu Vultur }
644b0531225SHoratiu Vultur
645b0531225SHoratiu Vultur return admin;
64639bedc16SHoratiu Vultur }
64739bedc16SHoratiu Vultur
lan966x_vcap_block_init(struct lan966x * lan966x,struct vcap_admin * admin,struct lan966x_vcap_inst * cfg)6484426b78cSHoratiu Vultur static void lan966x_vcap_block_init(struct lan966x *lan966x,
64939bedc16SHoratiu Vultur struct vcap_admin *admin,
6503643abd6SHoratiu Vultur struct lan966x_vcap_inst *cfg)
6513643abd6SHoratiu Vultur {
6523643abd6SHoratiu Vultur admin->first_valid_addr = 0;
6533643abd6SHoratiu Vultur admin->last_used_addr = cfg->count;
6543643abd6SHoratiu Vultur admin->last_valid_addr = cfg->count - 1;
6553643abd6SHoratiu Vultur
6563643abd6SHoratiu Vultur lan_wr(VCAP_CORE_IDX_CORE_IDX_SET(0),
6573643abd6SHoratiu Vultur lan966x, VCAP_CORE_IDX(admin->tgt_inst));
6583643abd6SHoratiu Vultur lan_wr(VCAP_CORE_MAP_CORE_MAP_SET(1),
6594426b78cSHoratiu Vultur lan966x, VCAP_CORE_MAP(admin->tgt_inst));
6604426b78cSHoratiu Vultur
6613643abd6SHoratiu Vultur __lan966x_vcap_range_init(lan966x, admin, admin->first_valid_addr,
6623643abd6SHoratiu Vultur admin->last_valid_addr -
6633643abd6SHoratiu Vultur admin->first_valid_addr);
66494281484SHoratiu Vultur }
66594281484SHoratiu Vultur
lan966x_vcap_port_key_deselection(struct lan966x * lan966x,struct vcap_admin * admin)66694281484SHoratiu Vultur static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x,
66794281484SHoratiu Vultur struct vcap_admin *admin)
66894281484SHoratiu Vultur {
66994281484SHoratiu Vultur u32 val;
67001ef75a2SSteen Hegelund
67101ef75a2SSteen Hegelund switch (admin->vtype) {
67201ef75a2SSteen Hegelund case VCAP_TYPE_IS1:
673*a4d9b3ecSHoratiu Vultur val = ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(VCAP_IS1_PS_IPV6_5TUPLE_IP6) |
674*a4d9b3ecSHoratiu Vultur ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(VCAP_IS1_PS_IPV4_5TUPLE_IP4) |
675*a4d9b3ecSHoratiu Vultur ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(VCAP_IS1_PS_OTHER_NORMAL);
676*a4d9b3ecSHoratiu Vultur
67794281484SHoratiu Vultur for (int p = 0; p < lan966x->num_phys_ports; ++p) {
67894281484SHoratiu Vultur if (!lan966x->ports[p])
67901ef75a2SSteen Hegelund continue;
680b0531225SHoratiu Vultur
681b0531225SHoratiu Vultur for (int l = 0; l < LAN966X_IS1_LOOKUPS; ++l)
682b0531225SHoratiu Vultur lan_wr(val, lan966x, ANA_VCAP_S1_CFG(p, l));
683b0531225SHoratiu Vultur
684b0531225SHoratiu Vultur lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
685b0531225SHoratiu Vultur ANA_VCAP_CFG_S1_ENA, lan966x,
686b0531225SHoratiu Vultur ANA_VCAP_CFG(p));
6873643abd6SHoratiu Vultur }
688b0531225SHoratiu Vultur
689b0531225SHoratiu Vultur break;
690b0531225SHoratiu Vultur case VCAP_TYPE_IS2:
691b0531225SHoratiu Vultur for (int p = 0; p < lan966x->num_phys_ports; ++p)
692b0531225SHoratiu Vultur lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p));
693b0531225SHoratiu Vultur
6943643abd6SHoratiu Vultur break;
6954426b78cSHoratiu Vultur case VCAP_TYPE_ES0:
6963643abd6SHoratiu Vultur for (int p = 0; p < lan966x->num_phys_ports; ++p)
6973643abd6SHoratiu Vultur lan_rmw(REW_PORT_CFG_ES0_EN_SET(false),
6983643abd6SHoratiu Vultur REW_PORT_CFG_ES0_EN, lan966x,
6993643abd6SHoratiu Vultur REW_PORT_CFG(p));
7003643abd6SHoratiu Vultur break;
701b0531225SHoratiu Vultur default:
702b0531225SHoratiu Vultur pr_err("vcap type: %s not supported\n",
703 lan966x_vcaps[admin->vtype].name);
704 break;
705 }
706 }
707
lan966x_vcap_init(struct lan966x * lan966x)708 int lan966x_vcap_init(struct lan966x *lan966x)
709 {
710 struct lan966x_vcap_inst *cfg;
711 struct vcap_control *ctrl;
712 struct vcap_admin *admin;
713 struct dentry *dir;
714
715 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
716 if (!ctrl)
717 return -ENOMEM;
718
719 ctrl->vcaps = lan966x_vcaps;
720 ctrl->stats = &lan966x_vcap_stats;
721 ctrl->ops = &lan966x_vcap_ops;
722
723 INIT_LIST_HEAD(&ctrl->list);
724 for (int i = 0; i < ARRAY_SIZE(lan966x_vcap_inst_cfg); ++i) {
725 cfg = &lan966x_vcap_inst_cfg[i];
726
727 admin = lan966x_vcap_admin_alloc(lan966x, ctrl, cfg);
728 if (IS_ERR(admin))
729 return PTR_ERR(admin);
730
731 lan966x_vcap_block_init(lan966x, admin, cfg);
732 lan966x_vcap_port_key_deselection(lan966x, admin);
733
734 list_add_tail(&admin->list, &ctrl->list);
735 }
736
737 dir = vcap_debugfs(lan966x->dev, lan966x->debugfs_root, ctrl);
738 for (int p = 0; p < lan966x->num_phys_ports; ++p) {
739 if (lan966x->ports[p]) {
740 vcap_port_debugfs(lan966x->dev, dir, ctrl,
741 lan966x->ports[p]->dev);
742
743 lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(true),
744 ANA_VCAP_S2_CFG_ENA, lan966x,
745 ANA_VCAP_S2_CFG(lan966x->ports[p]->chip_port));
746
747 lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true),
748 ANA_VCAP_CFG_S1_ENA, lan966x,
749 ANA_VCAP_CFG(lan966x->ports[p]->chip_port));
750
751 lan_rmw(REW_PORT_CFG_ES0_EN_SET(true),
752 REW_PORT_CFG_ES0_EN, lan966x,
753 REW_PORT_CFG(lan966x->ports[p]->chip_port));
754 }
755 }
756
757 /* Statistics: Use ESDX from ES0 if hit, otherwise no counting */
758 lan_rmw(REW_STAT_CFG_STAT_MODE_SET(1),
759 REW_STAT_CFG_STAT_MODE, lan966x,
760 REW_STAT_CFG);
761
762 lan966x->vcap_ctrl = ctrl;
763
764 return 0;
765 }
766
lan966x_vcap_deinit(struct lan966x * lan966x)767 void lan966x_vcap_deinit(struct lan966x *lan966x)
768 {
769 struct vcap_admin *admin, *admin_next;
770 struct vcap_control *ctrl;
771
772 ctrl = lan966x->vcap_ctrl;
773 if (!ctrl)
774 return;
775
776 list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) {
777 lan966x_vcap_port_key_deselection(lan966x, admin);
778 vcap_del_rules(ctrl, admin);
779 list_del(&admin->list);
780 lan966x_vcap_admin_free(admin);
781 }
782
783 kfree(ctrl);
784 }
785