1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Microchip Sparx5 Switch driver VCAP implementation 3 * 4 * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries. 5 * 6 * The Sparx5 Chip Register Model can be browsed at this location: 7 * https://github.com/microchip-ung/sparx-5_reginfo 8 */ 9 10 #include "vcap_api_debugfs.h" 11 #include "sparx5_main_regs.h" 12 #include "sparx5_main.h" 13 #include "sparx5_vcap_impl.h" 14 #include "sparx5_vcap_ag_api.h" 15 #include "sparx5_vcap_debugfs.h" 16 17 #define SUPER_VCAP_BLK_SIZE 3072 /* addresses per Super VCAP block */ 18 #define STREAMSIZE (64 * 4) /* bytes in the VCAP cache area */ 19 20 #define SPARX5_IS2_LOOKUPS 4 21 #define VCAP_IS2_KEYSEL(_ena, _noneth, _v4_mc, _v4_uc, _v6_mc, _v6_uc, _arp) \ 22 (ANA_ACL_VCAP_S2_KEY_SEL_KEY_SEL_ENA_SET(_ena) | \ 23 ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_SET(_noneth) | \ 24 ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_SET(_v4_mc) | \ 25 ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_SET(_v4_uc) | \ 26 ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_SET(_v6_mc) | \ 27 ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_SET(_v6_uc) | \ 28 ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_SET(_arp)) 29 30 #define SPARX5_IS0_LOOKUPS 6 31 #define VCAP_IS0_KEYSEL(_ena, _etype, _ipv4, _ipv6, _mpls_uc, _mpls_mc, _mlbs) \ 32 (ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(_ena) | \ 33 ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_SET(_etype) | \ 34 ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_SET(_ipv4) | \ 35 ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_SET(_ipv6) | \ 36 ANA_CL_ADV_CL_CFG_MPLS_UC_CLM_KEY_SEL_SET(_mpls_uc) | \ 37 ANA_CL_ADV_CL_CFG_MPLS_MC_CLM_KEY_SEL_SET(_mpls_mc) | \ 38 ANA_CL_ADV_CL_CFG_MLBS_CLM_KEY_SEL_SET(_mlbs)) 39 40 #define SPARX5_ES2_LOOKUPS 2 41 #define VCAP_ES2_KEYSEL(_ena, _arp, _ipv4, _ipv6) \ 42 (EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(_ena) | \ 43 EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_SET(_arp) | \ 44 EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_SET(_ipv4) | \ 45 EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_SET(_ipv6)) 46 47 static struct sparx5_vcap_inst { 48 enum vcap_type vtype; /* type of vcap */ 49 int vinst; /* instance number within the same type */ 50 int lookups; /* number of lookups in this vcap type */ 51 int lookups_per_instance; /* number of lookups in this instance */ 52 int first_cid; /* first chain id in this vcap */ 53 int last_cid; /* last chain id in this vcap */ 54 int count; /* number of available addresses, not in super vcap */ 55 int map_id; /* id in the super vcap block mapping (if applicable) */ 56 int blockno; /* starting block in super vcap (if applicable) */ 57 int blocks; /* number of blocks in super vcap (if applicable) */ 58 bool ingress; /* is vcap in the ingress path */ 59 } sparx5_vcap_inst_cfg[] = { 60 { 61 .vtype = VCAP_TYPE_IS0, /* CLM-0 */ 62 .vinst = 0, 63 .map_id = 1, 64 .lookups = SPARX5_IS0_LOOKUPS, 65 .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3, 66 .first_cid = SPARX5_VCAP_CID_IS0_L0, 67 .last_cid = SPARX5_VCAP_CID_IS0_L2 - 1, 68 .blockno = 8, /* Maps block 8-9 */ 69 .blocks = 2, 70 .ingress = true, 71 }, 72 { 73 .vtype = VCAP_TYPE_IS0, /* CLM-1 */ 74 .vinst = 1, 75 .map_id = 2, 76 .lookups = SPARX5_IS0_LOOKUPS, 77 .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3, 78 .first_cid = SPARX5_VCAP_CID_IS0_L2, 79 .last_cid = SPARX5_VCAP_CID_IS0_L4 - 1, 80 .blockno = 6, /* Maps block 6-7 */ 81 .blocks = 2, 82 .ingress = true, 83 }, 84 { 85 .vtype = VCAP_TYPE_IS0, /* CLM-2 */ 86 .vinst = 2, 87 .map_id = 3, 88 .lookups = SPARX5_IS0_LOOKUPS, 89 .lookups_per_instance = SPARX5_IS0_LOOKUPS / 3, 90 .first_cid = SPARX5_VCAP_CID_IS0_L4, 91 .last_cid = SPARX5_VCAP_CID_IS0_MAX, 92 .blockno = 4, /* Maps block 4-5 */ 93 .blocks = 2, 94 .ingress = true, 95 }, 96 { 97 .vtype = VCAP_TYPE_IS2, /* IS2-0 */ 98 .vinst = 0, 99 .map_id = 4, 100 .lookups = SPARX5_IS2_LOOKUPS, 101 .lookups_per_instance = SPARX5_IS2_LOOKUPS / 2, 102 .first_cid = SPARX5_VCAP_CID_IS2_L0, 103 .last_cid = SPARX5_VCAP_CID_IS2_L2 - 1, 104 .blockno = 0, /* Maps block 0-1 */ 105 .blocks = 2, 106 .ingress = true, 107 }, 108 { 109 .vtype = VCAP_TYPE_IS2, /* IS2-1 */ 110 .vinst = 1, 111 .map_id = 5, 112 .lookups = SPARX5_IS2_LOOKUPS, 113 .lookups_per_instance = SPARX5_IS2_LOOKUPS / 2, 114 .first_cid = SPARX5_VCAP_CID_IS2_L2, 115 .last_cid = SPARX5_VCAP_CID_IS2_MAX, 116 .blockno = 2, /* Maps block 2-3 */ 117 .blocks = 2, 118 .ingress = true, 119 }, 120 { 121 .vtype = VCAP_TYPE_ES2, 122 .lookups = SPARX5_ES2_LOOKUPS, 123 .lookups_per_instance = SPARX5_ES2_LOOKUPS, 124 .first_cid = SPARX5_VCAP_CID_ES2_L0, 125 .last_cid = SPARX5_VCAP_CID_ES2_MAX, 126 .count = 12288, /* Addresses according to datasheet */ 127 .ingress = false, 128 }, 129 }; 130 131 /* These protocols have dedicated keysets in IS0 and a TC dissector */ 132 static u16 sparx5_vcap_is0_known_etypes[] = { 133 ETH_P_ALL, 134 ETH_P_IP, 135 ETH_P_IPV6, 136 }; 137 138 /* These protocols have dedicated keysets in IS2 and a TC dissector */ 139 static u16 sparx5_vcap_is2_known_etypes[] = { 140 ETH_P_ALL, 141 ETH_P_ARP, 142 ETH_P_IP, 143 ETH_P_IPV6, 144 }; 145 146 /* These protocols have dedicated keysets in ES2 and a TC dissector */ 147 static u16 sparx5_vcap_es2_known_etypes[] = { 148 ETH_P_ALL, 149 ETH_P_ARP, 150 ETH_P_IP, 151 ETH_P_IPV6, 152 }; 153 154 static void sparx5_vcap_type_err(struct sparx5 *sparx5, 155 struct vcap_admin *admin, 156 const char *fname) 157 { 158 pr_err("%s: vcap type: %s not supported\n", 159 fname, sparx5_vcaps[admin->vtype].name); 160 } 161 162 /* Await the super VCAP completion of the current operation */ 163 static void sparx5_vcap_wait_super_update(struct sparx5 *sparx5) 164 { 165 u32 value; 166 167 read_poll_timeout(spx5_rd, value, 168 !VCAP_SUPER_CTRL_UPDATE_SHOT_GET(value), 500, 10000, 169 false, sparx5, VCAP_SUPER_CTRL); 170 } 171 172 /* Await the ES2 VCAP completion of the current operation */ 173 static void sparx5_vcap_wait_es2_update(struct sparx5 *sparx5) 174 { 175 u32 value; 176 177 read_poll_timeout(spx5_rd, value, 178 !VCAP_ES2_CTRL_UPDATE_SHOT_GET(value), 500, 10000, 179 false, sparx5, VCAP_ES2_CTRL); 180 } 181 182 /* Initializing a VCAP address range */ 183 static void _sparx5_vcap_range_init(struct sparx5 *sparx5, 184 struct vcap_admin *admin, 185 u32 addr, u32 count) 186 { 187 u32 size = count - 1; 188 189 switch (admin->vtype) { 190 case VCAP_TYPE_IS0: 191 case VCAP_TYPE_IS2: 192 spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) | 193 VCAP_SUPER_CFG_MV_SIZE_SET(size), 194 sparx5, VCAP_SUPER_CFG); 195 spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) | 196 VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) | 197 VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) | 198 VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) | 199 VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) | 200 VCAP_SUPER_CTRL_CLEAR_CACHE_SET(true) | 201 VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true), 202 sparx5, VCAP_SUPER_CTRL); 203 sparx5_vcap_wait_super_update(sparx5); 204 break; 205 case VCAP_TYPE_ES2: 206 spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(0) | 207 VCAP_ES2_CFG_MV_SIZE_SET(size), 208 sparx5, VCAP_ES2_CFG); 209 spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) | 210 VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET(0) | 211 VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET(0) | 212 VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET(0) | 213 VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr) | 214 VCAP_ES2_CTRL_CLEAR_CACHE_SET(true) | 215 VCAP_ES2_CTRL_UPDATE_SHOT_SET(true), 216 sparx5, VCAP_ES2_CTRL); 217 sparx5_vcap_wait_es2_update(sparx5); 218 break; 219 default: 220 sparx5_vcap_type_err(sparx5, admin, __func__); 221 break; 222 } 223 } 224 225 /* Initializing VCAP rule data area */ 226 static void sparx5_vcap_block_init(struct sparx5 *sparx5, 227 struct vcap_admin *admin) 228 { 229 _sparx5_vcap_range_init(sparx5, admin, admin->first_valid_addr, 230 admin->last_valid_addr - 231 admin->first_valid_addr); 232 } 233 234 /* Get the keyset name from the sparx5 VCAP model */ 235 static const char *sparx5_vcap_keyset_name(struct net_device *ndev, 236 enum vcap_keyfield_set keyset) 237 { 238 struct sparx5_port *port = netdev_priv(ndev); 239 240 return vcap_keyset_name(port->sparx5->vcap_ctrl, keyset); 241 } 242 243 /* Check if this is the first lookup of IS0 */ 244 static bool sparx5_vcap_is0_is_first_chain(struct vcap_rule *rule) 245 { 246 return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L0 && 247 rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L1) || 248 ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L2 && 249 rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L3)) || 250 ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS0_L4 && 251 rule->vcap_chain_id < SPARX5_VCAP_CID_IS0_L5)); 252 } 253 254 /* Check if this is the first lookup of IS2 */ 255 static bool sparx5_vcap_is2_is_first_chain(struct vcap_rule *rule) 256 { 257 return (rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L0 && 258 rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L1) || 259 ((rule->vcap_chain_id >= SPARX5_VCAP_CID_IS2_L2 && 260 rule->vcap_chain_id < SPARX5_VCAP_CID_IS2_L3)); 261 } 262 263 static bool sparx5_vcap_es2_is_first_chain(struct vcap_rule *rule) 264 { 265 return (rule->vcap_chain_id >= SPARX5_VCAP_CID_ES2_L0 && 266 rule->vcap_chain_id < SPARX5_VCAP_CID_ES2_L1); 267 } 268 269 /* Set the narrow range ingress port mask on a rule */ 270 static void sparx5_vcap_add_ingress_range_port_mask(struct vcap_rule *rule, 271 struct net_device *ndev) 272 { 273 struct sparx5_port *port = netdev_priv(ndev); 274 u32 port_mask; 275 u32 range; 276 277 range = port->portno / BITS_PER_TYPE(u32); 278 /* Port bit set to match-any */ 279 port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32)); 280 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_SEL, 0, 0xf); 281 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK_RNG, range, 0xf); 282 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, port_mask); 283 } 284 285 /* Set the wide range ingress port mask on a rule */ 286 static void sparx5_vcap_add_wide_port_mask(struct vcap_rule *rule, 287 struct net_device *ndev) 288 { 289 struct sparx5_port *port = netdev_priv(ndev); 290 struct vcap_u72_key port_mask; 291 u32 range; 292 293 /* Port bit set to match-any */ 294 memset(port_mask.value, 0, sizeof(port_mask.value)); 295 memset(port_mask.mask, 0xff, sizeof(port_mask.mask)); 296 range = port->portno / BITS_PER_BYTE; 297 port_mask.mask[range] = ~BIT(port->portno % BITS_PER_BYTE); 298 vcap_rule_add_key_u72(rule, VCAP_KF_IF_IGR_PORT_MASK, &port_mask); 299 } 300 301 static void sparx5_vcap_add_egress_range_port_mask(struct vcap_rule *rule, 302 struct net_device *ndev) 303 { 304 struct sparx5_port *port = netdev_priv(ndev); 305 u32 port_mask; 306 u32 range; 307 308 /* Mask range selects: 309 * 0-2: Physical/Logical egress port number 0-31, 32–63, 64. 310 * 3-5: Virtual Interface Number 0-31, 32-63, 64. 311 * 6: CPU queue Number 0-7. 312 * 313 * Use physical/logical port ranges (0-2) 314 */ 315 range = port->portno / BITS_PER_TYPE(u32); 316 /* Port bit set to match-any */ 317 port_mask = ~BIT(port->portno % BITS_PER_TYPE(u32)); 318 vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_MASK_RNG, range, 0xf); 319 vcap_rule_add_key_u32(rule, VCAP_KF_IF_EGR_PORT_MASK, 0, port_mask); 320 } 321 322 /* Convert IS0 chain id to vcap lookup id */ 323 static int sparx5_vcap_is0_cid_to_lookup(int cid) 324 { 325 int lookup = 0; 326 327 if (cid >= SPARX5_VCAP_CID_IS0_L1 && cid < SPARX5_VCAP_CID_IS0_L2) 328 lookup = 1; 329 else if (cid >= SPARX5_VCAP_CID_IS0_L2 && cid < SPARX5_VCAP_CID_IS0_L3) 330 lookup = 2; 331 else if (cid >= SPARX5_VCAP_CID_IS0_L3 && cid < SPARX5_VCAP_CID_IS0_L4) 332 lookup = 3; 333 else if (cid >= SPARX5_VCAP_CID_IS0_L4 && cid < SPARX5_VCAP_CID_IS0_L5) 334 lookup = 4; 335 else if (cid >= SPARX5_VCAP_CID_IS0_L5 && cid < SPARX5_VCAP_CID_IS0_MAX) 336 lookup = 5; 337 338 return lookup; 339 } 340 341 /* Convert IS2 chain id to vcap lookup id */ 342 static int sparx5_vcap_is2_cid_to_lookup(int cid) 343 { 344 int lookup = 0; 345 346 if (cid >= SPARX5_VCAP_CID_IS2_L1 && cid < SPARX5_VCAP_CID_IS2_L2) 347 lookup = 1; 348 else if (cid >= SPARX5_VCAP_CID_IS2_L2 && cid < SPARX5_VCAP_CID_IS2_L3) 349 lookup = 2; 350 else if (cid >= SPARX5_VCAP_CID_IS2_L3 && cid < SPARX5_VCAP_CID_IS2_MAX) 351 lookup = 3; 352 353 return lookup; 354 } 355 356 /* Convert ES2 chain id to vcap lookup id */ 357 static int sparx5_vcap_es2_cid_to_lookup(int cid) 358 { 359 int lookup = 0; 360 361 if (cid >= SPARX5_VCAP_CID_ES2_L1) 362 lookup = 1; 363 364 return lookup; 365 } 366 367 /* Add ethernet type IS0 keyset to a list */ 368 static void 369 sparx5_vcap_is0_get_port_etype_keysets(struct vcap_keyset_list *keysetlist, 370 u32 value) 371 { 372 switch (ANA_CL_ADV_CL_CFG_ETYPE_CLM_KEY_SEL_GET(value)) { 373 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE: 374 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_7TUPLE); 375 break; 376 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4: 377 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_5TUPLE_IP4); 378 break; 379 } 380 } 381 382 /* Return the list of keysets for the vcap port configuration */ 383 static int sparx5_vcap_is0_get_port_keysets(struct net_device *ndev, 384 int lookup, 385 struct vcap_keyset_list *keysetlist, 386 u16 l3_proto) 387 { 388 struct sparx5_port *port = netdev_priv(ndev); 389 struct sparx5 *sparx5 = port->sparx5; 390 int portno = port->portno; 391 u32 value; 392 393 value = spx5_rd(sparx5, ANA_CL_ADV_CL_CFG(portno, lookup)); 394 395 /* Collect all keysets for the port in a list */ 396 if (l3_proto == ETH_P_ALL) 397 sparx5_vcap_is0_get_port_etype_keysets(keysetlist, value); 398 399 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) 400 switch (ANA_CL_ADV_CL_CFG_IP4_CLM_KEY_SEL_GET(value)) { 401 case VCAP_IS0_PS_ETYPE_DEFAULT: 402 sparx5_vcap_is0_get_port_etype_keysets(keysetlist, 403 value); 404 break; 405 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE: 406 vcap_keyset_list_add(keysetlist, 407 VCAP_KFS_NORMAL_7TUPLE); 408 break; 409 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4: 410 vcap_keyset_list_add(keysetlist, 411 VCAP_KFS_NORMAL_5TUPLE_IP4); 412 break; 413 } 414 415 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) 416 switch (ANA_CL_ADV_CL_CFG_IP6_CLM_KEY_SEL_GET(value)) { 417 case VCAP_IS0_PS_ETYPE_DEFAULT: 418 sparx5_vcap_is0_get_port_etype_keysets(keysetlist, 419 value); 420 break; 421 case VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE: 422 vcap_keyset_list_add(keysetlist, 423 VCAP_KFS_NORMAL_7TUPLE); 424 break; 425 case VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4: 426 vcap_keyset_list_add(keysetlist, 427 VCAP_KFS_NORMAL_5TUPLE_IP4); 428 break; 429 } 430 431 if (l3_proto != ETH_P_IP && l3_proto != ETH_P_IPV6) 432 sparx5_vcap_is0_get_port_etype_keysets(keysetlist, value); 433 return 0; 434 } 435 436 /* Return the list of keysets for the vcap port configuration */ 437 static int sparx5_vcap_is2_get_port_keysets(struct net_device *ndev, 438 int lookup, 439 struct vcap_keyset_list *keysetlist, 440 u16 l3_proto) 441 { 442 struct sparx5_port *port = netdev_priv(ndev); 443 struct sparx5 *sparx5 = port->sparx5; 444 int portno = port->portno; 445 u32 value; 446 447 value = spx5_rd(sparx5, ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); 448 449 /* Collect all keysets for the port in a list */ 450 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) { 451 switch (ANA_ACL_VCAP_S2_KEY_SEL_ARP_KEY_SEL_GET(value)) { 452 case VCAP_IS2_PS_ARP_MAC_ETYPE: 453 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 454 break; 455 case VCAP_IS2_PS_ARP_ARP: 456 vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP); 457 break; 458 } 459 } 460 461 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) { 462 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_UC_KEY_SEL_GET(value)) { 463 case VCAP_IS2_PS_IPV4_UC_MAC_ETYPE: 464 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 465 break; 466 case VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER: 467 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 468 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 469 break; 470 case VCAP_IS2_PS_IPV4_UC_IP_7TUPLE: 471 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 472 break; 473 } 474 475 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP4_MC_KEY_SEL_GET(value)) { 476 case VCAP_IS2_PS_IPV4_MC_MAC_ETYPE: 477 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 478 break; 479 case VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER: 480 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 481 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 482 break; 483 case VCAP_IS2_PS_IPV4_MC_IP_7TUPLE: 484 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 485 break; 486 } 487 } 488 489 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { 490 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_UC_KEY_SEL_GET(value)) { 491 case VCAP_IS2_PS_IPV6_UC_MAC_ETYPE: 492 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 493 break; 494 case VCAP_IS2_PS_IPV6_UC_IP_7TUPLE: 495 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 496 break; 497 case VCAP_IS2_PS_IPV6_UC_IP6_STD: 498 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); 499 break; 500 case VCAP_IS2_PS_IPV6_UC_IP4_TCP_UDP_OTHER: 501 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 502 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 503 break; 504 } 505 506 switch (ANA_ACL_VCAP_S2_KEY_SEL_IP6_MC_KEY_SEL_GET(value)) { 507 case VCAP_IS2_PS_IPV6_MC_MAC_ETYPE: 508 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 509 break; 510 case VCAP_IS2_PS_IPV6_MC_IP_7TUPLE: 511 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 512 break; 513 case VCAP_IS2_PS_IPV6_MC_IP6_STD: 514 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); 515 break; 516 case VCAP_IS2_PS_IPV6_MC_IP4_TCP_UDP_OTHER: 517 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 518 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 519 break; 520 case VCAP_IS2_PS_IPV6_MC_IP6_VID: 521 /* Not used */ 522 break; 523 } 524 } 525 526 if (l3_proto != ETH_P_ARP && l3_proto != ETH_P_IP && 527 l3_proto != ETH_P_IPV6) { 528 switch (ANA_ACL_VCAP_S2_KEY_SEL_NON_ETH_KEY_SEL_GET(value)) { 529 case VCAP_IS2_PS_NONETH_MAC_ETYPE: 530 /* IS2 non-classified frames generate MAC_ETYPE */ 531 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 532 break; 533 } 534 } 535 return 0; 536 } 537 538 /* Return the keysets for the vcap port IP4 traffic class configuration */ 539 static void 540 sparx5_vcap_es2_get_port_ipv4_keysets(struct vcap_keyset_list *keysetlist, 541 u32 value) 542 { 543 switch (EACL_VCAP_ES2_KEY_SEL_IP4_KEY_SEL_GET(value)) { 544 case VCAP_ES2_PS_IPV4_MAC_ETYPE: 545 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 546 break; 547 case VCAP_ES2_PS_IPV4_IP_7TUPLE: 548 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 549 break; 550 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_VID: 551 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 552 break; 553 case VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER: 554 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 555 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 556 break; 557 case VCAP_ES2_PS_IPV4_IP4_VID: 558 /* Not used */ 559 break; 560 case VCAP_ES2_PS_IPV4_IP4_OTHER: 561 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 562 break; 563 } 564 } 565 566 /* Return the list of keysets for the vcap port configuration */ 567 static int sparx5_vcap_es2_get_port_keysets(struct net_device *ndev, 568 int lookup, 569 struct vcap_keyset_list *keysetlist, 570 u16 l3_proto) 571 { 572 struct sparx5_port *port = netdev_priv(ndev); 573 struct sparx5 *sparx5 = port->sparx5; 574 int portno = port->portno; 575 u32 value; 576 577 value = spx5_rd(sparx5, EACL_VCAP_ES2_KEY_SEL(portno, lookup)); 578 579 /* Collect all keysets for the port in a list */ 580 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) { 581 switch (EACL_VCAP_ES2_KEY_SEL_ARP_KEY_SEL_GET(value)) { 582 case VCAP_ES2_PS_ARP_MAC_ETYPE: 583 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 584 break; 585 case VCAP_ES2_PS_ARP_ARP: 586 vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP); 587 break; 588 } 589 } 590 591 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) 592 sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist, value); 593 594 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { 595 switch (EACL_VCAP_ES2_KEY_SEL_IP6_KEY_SEL_GET(value)) { 596 case VCAP_ES2_PS_IPV6_MAC_ETYPE: 597 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 598 break; 599 case VCAP_ES2_PS_IPV6_IP_7TUPLE: 600 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 601 break; 602 case VCAP_ES2_PS_IPV6_IP_7TUPLE_VID: 603 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 604 break; 605 case VCAP_ES2_PS_IPV6_IP_7TUPLE_STD: 606 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP_7TUPLE); 607 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); 608 break; 609 case VCAP_ES2_PS_IPV6_IP6_VID: 610 /* Not used */ 611 break; 612 case VCAP_ES2_PS_IPV6_IP6_STD: 613 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); 614 break; 615 case VCAP_ES2_PS_IPV6_IP4_DOWNGRADE: 616 sparx5_vcap_es2_get_port_ipv4_keysets(keysetlist, 617 value); 618 break; 619 } 620 } 621 622 if (l3_proto != ETH_P_ARP && l3_proto != ETH_P_IP && 623 l3_proto != ETH_P_IPV6) { 624 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 625 } 626 return 0; 627 } 628 629 /* Get the port keyset for the vcap lookup */ 630 int sparx5_vcap_get_port_keyset(struct net_device *ndev, 631 struct vcap_admin *admin, 632 int cid, 633 u16 l3_proto, 634 struct vcap_keyset_list *kslist) 635 { 636 int lookup, err = -EINVAL; 637 struct sparx5_port *port; 638 639 switch (admin->vtype) { 640 case VCAP_TYPE_IS0: 641 lookup = sparx5_vcap_is0_cid_to_lookup(cid); 642 err = sparx5_vcap_is0_get_port_keysets(ndev, lookup, kslist, 643 l3_proto); 644 break; 645 case VCAP_TYPE_IS2: 646 lookup = sparx5_vcap_is2_cid_to_lookup(cid); 647 err = sparx5_vcap_is2_get_port_keysets(ndev, lookup, kslist, 648 l3_proto); 649 break; 650 case VCAP_TYPE_ES2: 651 lookup = sparx5_vcap_es2_cid_to_lookup(cid); 652 err = sparx5_vcap_es2_get_port_keysets(ndev, lookup, kslist, 653 l3_proto); 654 break; 655 default: 656 port = netdev_priv(ndev); 657 sparx5_vcap_type_err(port->sparx5, admin, __func__); 658 break; 659 } 660 return err; 661 } 662 663 /* Check if the ethertype is supported by the vcap port classification */ 664 bool sparx5_vcap_is_known_etype(struct vcap_admin *admin, u16 etype) 665 { 666 const u16 *known_etypes; 667 int size, idx; 668 669 switch (admin->vtype) { 670 case VCAP_TYPE_IS0: 671 known_etypes = sparx5_vcap_is0_known_etypes; 672 size = ARRAY_SIZE(sparx5_vcap_is0_known_etypes); 673 break; 674 case VCAP_TYPE_IS2: 675 known_etypes = sparx5_vcap_is2_known_etypes; 676 size = ARRAY_SIZE(sparx5_vcap_is2_known_etypes); 677 break; 678 case VCAP_TYPE_ES2: 679 known_etypes = sparx5_vcap_es2_known_etypes; 680 size = ARRAY_SIZE(sparx5_vcap_es2_known_etypes); 681 break; 682 default: 683 return false; 684 } 685 for (idx = 0; idx < size; ++idx) 686 if (known_etypes[idx] == etype) 687 return true; 688 return false; 689 } 690 691 /* API callback used for validating a field keyset (check the port keysets) */ 692 static enum vcap_keyfield_set 693 sparx5_vcap_validate_keyset(struct net_device *ndev, 694 struct vcap_admin *admin, 695 struct vcap_rule *rule, 696 struct vcap_keyset_list *kslist, 697 u16 l3_proto) 698 { 699 struct vcap_keyset_list keysetlist = {}; 700 enum vcap_keyfield_set keysets[10] = {}; 701 struct sparx5_port *port; 702 int idx, jdx, lookup; 703 704 if (!kslist || kslist->cnt == 0) 705 return VCAP_KFS_NO_VALUE; 706 707 keysetlist.max = ARRAY_SIZE(keysets); 708 keysetlist.keysets = keysets; 709 710 /* Get a list of currently configured keysets in the lookups */ 711 switch (admin->vtype) { 712 case VCAP_TYPE_IS0: 713 lookup = sparx5_vcap_is0_cid_to_lookup(rule->vcap_chain_id); 714 sparx5_vcap_is0_get_port_keysets(ndev, lookup, &keysetlist, 715 l3_proto); 716 break; 717 case VCAP_TYPE_IS2: 718 lookup = sparx5_vcap_is2_cid_to_lookup(rule->vcap_chain_id); 719 sparx5_vcap_is2_get_port_keysets(ndev, lookup, &keysetlist, 720 l3_proto); 721 break; 722 case VCAP_TYPE_ES2: 723 lookup = sparx5_vcap_es2_cid_to_lookup(rule->vcap_chain_id); 724 sparx5_vcap_es2_get_port_keysets(ndev, lookup, &keysetlist, 725 l3_proto); 726 break; 727 default: 728 port = netdev_priv(ndev); 729 sparx5_vcap_type_err(port->sparx5, admin, __func__); 730 break; 731 } 732 733 /* Check if there is a match and return the match */ 734 for (idx = 0; idx < kslist->cnt; ++idx) 735 for (jdx = 0; jdx < keysetlist.cnt; ++jdx) 736 if (kslist->keysets[idx] == keysets[jdx]) 737 return kslist->keysets[idx]; 738 739 pr_err("%s:%d: %s not supported in port key selection\n", 740 __func__, __LINE__, 741 sparx5_vcap_keyset_name(ndev, kslist->keysets[0])); 742 743 return -ENOENT; 744 } 745 746 static void sparx5_vcap_ingress_add_default_fields(struct net_device *ndev, 747 struct vcap_admin *admin, 748 struct vcap_rule *rule) 749 { 750 const struct vcap_field *field; 751 bool is_first; 752 753 /* Add ingress port mask matching the net device */ 754 field = vcap_lookup_keyfield(rule, VCAP_KF_IF_IGR_PORT_MASK); 755 if (field && field->width == SPX5_PORTS) 756 sparx5_vcap_add_wide_port_mask(rule, ndev); 757 else if (field && field->width == BITS_PER_TYPE(u32)) 758 sparx5_vcap_add_ingress_range_port_mask(rule, ndev); 759 else 760 pr_err("%s:%d: %s: could not add an ingress port mask for: %s\n", 761 __func__, __LINE__, netdev_name(ndev), 762 sparx5_vcap_keyset_name(ndev, rule->keyset)); 763 764 if (admin->vtype == VCAP_TYPE_IS0) 765 is_first = sparx5_vcap_is0_is_first_chain(rule); 766 else 767 is_first = sparx5_vcap_is2_is_first_chain(rule); 768 769 /* Add key that selects the first/second lookup */ 770 if (is_first) 771 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 772 VCAP_BIT_1); 773 else 774 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 775 VCAP_BIT_0); 776 } 777 778 static void sparx5_vcap_es2_add_default_fields(struct net_device *ndev, 779 struct vcap_admin *admin, 780 struct vcap_rule *rule) 781 { 782 const struct vcap_field *field; 783 bool is_first; 784 785 /* Add egress port mask matching the net device */ 786 field = vcap_lookup_keyfield(rule, VCAP_KF_IF_EGR_PORT_MASK); 787 if (field) 788 sparx5_vcap_add_egress_range_port_mask(rule, ndev); 789 790 /* Add key that selects the first/second lookup */ 791 is_first = sparx5_vcap_es2_is_first_chain(rule); 792 793 if (is_first) 794 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 795 VCAP_BIT_1); 796 else 797 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 798 VCAP_BIT_0); 799 } 800 801 /* API callback used for adding default fields to a rule */ 802 static void sparx5_vcap_add_default_fields(struct net_device *ndev, 803 struct vcap_admin *admin, 804 struct vcap_rule *rule) 805 { 806 struct sparx5_port *port; 807 808 /* add the lookup bit */ 809 switch (admin->vtype) { 810 case VCAP_TYPE_IS0: 811 case VCAP_TYPE_IS2: 812 sparx5_vcap_ingress_add_default_fields(ndev, admin, rule); 813 break; 814 case VCAP_TYPE_ES2: 815 sparx5_vcap_es2_add_default_fields(ndev, admin, rule); 816 break; 817 default: 818 port = netdev_priv(ndev); 819 sparx5_vcap_type_err(port->sparx5, admin, __func__); 820 break; 821 } 822 } 823 824 /* API callback used for erasing the vcap cache area (not the register area) */ 825 static void sparx5_vcap_cache_erase(struct vcap_admin *admin) 826 { 827 memset(admin->cache.keystream, 0, STREAMSIZE); 828 memset(admin->cache.maskstream, 0, STREAMSIZE); 829 memset(admin->cache.actionstream, 0, STREAMSIZE); 830 memset(&admin->cache.counter, 0, sizeof(admin->cache.counter)); 831 } 832 833 static void sparx5_vcap_is0_cache_write(struct sparx5 *sparx5, 834 struct vcap_admin *admin, 835 enum vcap_selection sel, 836 u32 start, 837 u32 count) 838 { 839 u32 *keystr, *mskstr, *actstr; 840 int idx; 841 842 keystr = &admin->cache.keystream[start]; 843 mskstr = &admin->cache.maskstream[start]; 844 actstr = &admin->cache.actionstream[start]; 845 846 switch (sel) { 847 case VCAP_SEL_ENTRY: 848 for (idx = 0; idx < count; ++idx) { 849 /* Avoid 'match-off' by setting value & mask */ 850 spx5_wr(keystr[idx] & mskstr[idx], sparx5, 851 VCAP_SUPER_VCAP_ENTRY_DAT(idx)); 852 spx5_wr(~mskstr[idx], sparx5, 853 VCAP_SUPER_VCAP_MASK_DAT(idx)); 854 } 855 break; 856 case VCAP_SEL_ACTION: 857 for (idx = 0; idx < count; ++idx) 858 spx5_wr(actstr[idx], sparx5, 859 VCAP_SUPER_VCAP_ACTION_DAT(idx)); 860 break; 861 case VCAP_SEL_ALL: 862 pr_err("%s:%d: cannot write all streams at once\n", 863 __func__, __LINE__); 864 break; 865 default: 866 break; 867 } 868 869 if (sel & VCAP_SEL_COUNTER) 870 spx5_wr(admin->cache.counter, sparx5, 871 VCAP_SUPER_VCAP_CNT_DAT(0)); 872 } 873 874 static void sparx5_vcap_is2_cache_write(struct sparx5 *sparx5, 875 struct vcap_admin *admin, 876 enum vcap_selection sel, 877 u32 start, 878 u32 count) 879 { 880 u32 *keystr, *mskstr, *actstr; 881 int idx; 882 883 keystr = &admin->cache.keystream[start]; 884 mskstr = &admin->cache.maskstream[start]; 885 actstr = &admin->cache.actionstream[start]; 886 887 switch (sel) { 888 case VCAP_SEL_ENTRY: 889 for (idx = 0; idx < count; ++idx) { 890 /* Avoid 'match-off' by setting value & mask */ 891 spx5_wr(keystr[idx] & mskstr[idx], sparx5, 892 VCAP_SUPER_VCAP_ENTRY_DAT(idx)); 893 spx5_wr(~mskstr[idx], sparx5, 894 VCAP_SUPER_VCAP_MASK_DAT(idx)); 895 } 896 break; 897 case VCAP_SEL_ACTION: 898 for (idx = 0; idx < count; ++idx) 899 spx5_wr(actstr[idx], sparx5, 900 VCAP_SUPER_VCAP_ACTION_DAT(idx)); 901 break; 902 case VCAP_SEL_ALL: 903 pr_err("%s:%d: cannot write all streams at once\n", 904 __func__, __LINE__); 905 break; 906 default: 907 break; 908 } 909 if (sel & VCAP_SEL_COUNTER) { 910 start = start & 0xfff; /* counter limit */ 911 if (admin->vinst == 0) 912 spx5_wr(admin->cache.counter, sparx5, 913 ANA_ACL_CNT_A(start)); 914 else 915 spx5_wr(admin->cache.counter, sparx5, 916 ANA_ACL_CNT_B(start)); 917 spx5_wr(admin->cache.sticky, sparx5, 918 VCAP_SUPER_VCAP_CNT_DAT(0)); 919 } 920 } 921 922 static void sparx5_vcap_es2_cache_write(struct sparx5 *sparx5, 923 struct vcap_admin *admin, 924 enum vcap_selection sel, 925 u32 start, 926 u32 count) 927 { 928 u32 *keystr, *mskstr, *actstr; 929 int idx; 930 931 keystr = &admin->cache.keystream[start]; 932 mskstr = &admin->cache.maskstream[start]; 933 actstr = &admin->cache.actionstream[start]; 934 935 switch (sel) { 936 case VCAP_SEL_ENTRY: 937 for (idx = 0; idx < count; ++idx) { 938 /* Avoid 'match-off' by setting value & mask */ 939 spx5_wr(keystr[idx] & mskstr[idx], sparx5, 940 VCAP_ES2_VCAP_ENTRY_DAT(idx)); 941 spx5_wr(~mskstr[idx], sparx5, 942 VCAP_ES2_VCAP_MASK_DAT(idx)); 943 } 944 break; 945 case VCAP_SEL_ACTION: 946 for (idx = 0; idx < count; ++idx) 947 spx5_wr(actstr[idx], sparx5, 948 VCAP_ES2_VCAP_ACTION_DAT(idx)); 949 break; 950 case VCAP_SEL_ALL: 951 pr_err("%s:%d: cannot write all streams at once\n", 952 __func__, __LINE__); 953 break; 954 default: 955 break; 956 } 957 if (sel & VCAP_SEL_COUNTER) { 958 start = start & 0x7ff; /* counter limit */ 959 spx5_wr(admin->cache.counter, sparx5, EACL_ES2_CNT(start)); 960 spx5_wr(admin->cache.sticky, sparx5, VCAP_ES2_VCAP_CNT_DAT(0)); 961 } 962 } 963 964 /* API callback used for writing to the VCAP cache */ 965 static void sparx5_vcap_cache_write(struct net_device *ndev, 966 struct vcap_admin *admin, 967 enum vcap_selection sel, 968 u32 start, 969 u32 count) 970 { 971 struct sparx5_port *port = netdev_priv(ndev); 972 struct sparx5 *sparx5 = port->sparx5; 973 974 switch (admin->vtype) { 975 case VCAP_TYPE_IS0: 976 sparx5_vcap_is0_cache_write(sparx5, admin, sel, start, count); 977 break; 978 case VCAP_TYPE_IS2: 979 sparx5_vcap_is2_cache_write(sparx5, admin, sel, start, count); 980 break; 981 case VCAP_TYPE_ES2: 982 sparx5_vcap_es2_cache_write(sparx5, admin, sel, start, count); 983 break; 984 default: 985 sparx5_vcap_type_err(sparx5, admin, __func__); 986 break; 987 } 988 } 989 990 static void sparx5_vcap_is0_cache_read(struct sparx5 *sparx5, 991 struct vcap_admin *admin, 992 enum vcap_selection sel, 993 u32 start, 994 u32 count) 995 { 996 u32 *keystr, *mskstr, *actstr; 997 int idx; 998 999 keystr = &admin->cache.keystream[start]; 1000 mskstr = &admin->cache.maskstream[start]; 1001 actstr = &admin->cache.actionstream[start]; 1002 1003 if (sel & VCAP_SEL_ENTRY) { 1004 for (idx = 0; idx < count; ++idx) { 1005 keystr[idx] = spx5_rd(sparx5, 1006 VCAP_SUPER_VCAP_ENTRY_DAT(idx)); 1007 mskstr[idx] = ~spx5_rd(sparx5, 1008 VCAP_SUPER_VCAP_MASK_DAT(idx)); 1009 } 1010 } 1011 1012 if (sel & VCAP_SEL_ACTION) 1013 for (idx = 0; idx < count; ++idx) 1014 actstr[idx] = spx5_rd(sparx5, 1015 VCAP_SUPER_VCAP_ACTION_DAT(idx)); 1016 1017 if (sel & VCAP_SEL_COUNTER) { 1018 admin->cache.counter = 1019 spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0)); 1020 admin->cache.sticky = 1021 spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0)); 1022 } 1023 } 1024 1025 static void sparx5_vcap_is2_cache_read(struct sparx5 *sparx5, 1026 struct vcap_admin *admin, 1027 enum vcap_selection sel, 1028 u32 start, 1029 u32 count) 1030 { 1031 u32 *keystr, *mskstr, *actstr; 1032 int idx; 1033 1034 keystr = &admin->cache.keystream[start]; 1035 mskstr = &admin->cache.maskstream[start]; 1036 actstr = &admin->cache.actionstream[start]; 1037 1038 if (sel & VCAP_SEL_ENTRY) { 1039 for (idx = 0; idx < count; ++idx) { 1040 keystr[idx] = spx5_rd(sparx5, 1041 VCAP_SUPER_VCAP_ENTRY_DAT(idx)); 1042 mskstr[idx] = ~spx5_rd(sparx5, 1043 VCAP_SUPER_VCAP_MASK_DAT(idx)); 1044 } 1045 } 1046 1047 if (sel & VCAP_SEL_ACTION) 1048 for (idx = 0; idx < count; ++idx) 1049 actstr[idx] = spx5_rd(sparx5, 1050 VCAP_SUPER_VCAP_ACTION_DAT(idx)); 1051 1052 if (sel & VCAP_SEL_COUNTER) { 1053 start = start & 0xfff; /* counter limit */ 1054 if (admin->vinst == 0) 1055 admin->cache.counter = 1056 spx5_rd(sparx5, ANA_ACL_CNT_A(start)); 1057 else 1058 admin->cache.counter = 1059 spx5_rd(sparx5, ANA_ACL_CNT_B(start)); 1060 admin->cache.sticky = 1061 spx5_rd(sparx5, VCAP_SUPER_VCAP_CNT_DAT(0)); 1062 } 1063 } 1064 1065 static void sparx5_vcap_es2_cache_read(struct sparx5 *sparx5, 1066 struct vcap_admin *admin, 1067 enum vcap_selection sel, 1068 u32 start, 1069 u32 count) 1070 { 1071 u32 *keystr, *mskstr, *actstr; 1072 int idx; 1073 1074 keystr = &admin->cache.keystream[start]; 1075 mskstr = &admin->cache.maskstream[start]; 1076 actstr = &admin->cache.actionstream[start]; 1077 1078 if (sel & VCAP_SEL_ENTRY) { 1079 for (idx = 0; idx < count; ++idx) { 1080 keystr[idx] = 1081 spx5_rd(sparx5, VCAP_ES2_VCAP_ENTRY_DAT(idx)); 1082 mskstr[idx] = 1083 ~spx5_rd(sparx5, VCAP_ES2_VCAP_MASK_DAT(idx)); 1084 } 1085 } 1086 1087 if (sel & VCAP_SEL_ACTION) 1088 for (idx = 0; idx < count; ++idx) 1089 actstr[idx] = 1090 spx5_rd(sparx5, VCAP_ES2_VCAP_ACTION_DAT(idx)); 1091 1092 if (sel & VCAP_SEL_COUNTER) { 1093 start = start & 0x7ff; /* counter limit */ 1094 admin->cache.counter = 1095 spx5_rd(sparx5, EACL_ES2_CNT(start)); 1096 admin->cache.sticky = 1097 spx5_rd(sparx5, VCAP_ES2_VCAP_CNT_DAT(0)); 1098 } 1099 } 1100 1101 /* API callback used for reading from the VCAP into the VCAP cache */ 1102 static void sparx5_vcap_cache_read(struct net_device *ndev, 1103 struct vcap_admin *admin, 1104 enum vcap_selection sel, 1105 u32 start, 1106 u32 count) 1107 { 1108 struct sparx5_port *port = netdev_priv(ndev); 1109 struct sparx5 *sparx5 = port->sparx5; 1110 1111 switch (admin->vtype) { 1112 case VCAP_TYPE_IS0: 1113 sparx5_vcap_is0_cache_read(sparx5, admin, sel, start, count); 1114 break; 1115 case VCAP_TYPE_IS2: 1116 sparx5_vcap_is2_cache_read(sparx5, admin, sel, start, count); 1117 break; 1118 case VCAP_TYPE_ES2: 1119 sparx5_vcap_es2_cache_read(sparx5, admin, sel, start, count); 1120 break; 1121 default: 1122 sparx5_vcap_type_err(sparx5, admin, __func__); 1123 break; 1124 } 1125 } 1126 1127 /* API callback used for initializing a VCAP address range */ 1128 static void sparx5_vcap_range_init(struct net_device *ndev, 1129 struct vcap_admin *admin, u32 addr, 1130 u32 count) 1131 { 1132 struct sparx5_port *port = netdev_priv(ndev); 1133 struct sparx5 *sparx5 = port->sparx5; 1134 1135 _sparx5_vcap_range_init(sparx5, admin, addr, count); 1136 } 1137 1138 static void sparx5_vcap_super_update(struct sparx5 *sparx5, 1139 enum vcap_command cmd, 1140 enum vcap_selection sel, u32 addr) 1141 { 1142 bool clear = (cmd == VCAP_CMD_INITIALIZE); 1143 1144 spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(0) | 1145 VCAP_SUPER_CFG_MV_SIZE_SET(0), sparx5, VCAP_SUPER_CFG); 1146 spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd) | 1147 VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) | 1148 VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) | 1149 VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) | 1150 VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) | 1151 VCAP_SUPER_CTRL_CLEAR_CACHE_SET(clear) | 1152 VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true), 1153 sparx5, VCAP_SUPER_CTRL); 1154 sparx5_vcap_wait_super_update(sparx5); 1155 } 1156 1157 static void sparx5_vcap_es2_update(struct sparx5 *sparx5, 1158 enum vcap_command cmd, 1159 enum vcap_selection sel, u32 addr) 1160 { 1161 bool clear = (cmd == VCAP_CMD_INITIALIZE); 1162 1163 spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(0) | 1164 VCAP_ES2_CFG_MV_SIZE_SET(0), sparx5, VCAP_ES2_CFG); 1165 spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(cmd) | 1166 VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) | 1167 VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) | 1168 VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) | 1169 VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr) | 1170 VCAP_ES2_CTRL_CLEAR_CACHE_SET(clear) | 1171 VCAP_ES2_CTRL_UPDATE_SHOT_SET(true), 1172 sparx5, VCAP_ES2_CTRL); 1173 sparx5_vcap_wait_es2_update(sparx5); 1174 } 1175 1176 /* API callback used for updating the VCAP cache */ 1177 static void sparx5_vcap_update(struct net_device *ndev, 1178 struct vcap_admin *admin, enum vcap_command cmd, 1179 enum vcap_selection sel, u32 addr) 1180 { 1181 struct sparx5_port *port = netdev_priv(ndev); 1182 struct sparx5 *sparx5 = port->sparx5; 1183 1184 switch (admin->vtype) { 1185 case VCAP_TYPE_IS0: 1186 case VCAP_TYPE_IS2: 1187 sparx5_vcap_super_update(sparx5, cmd, sel, addr); 1188 break; 1189 case VCAP_TYPE_ES2: 1190 sparx5_vcap_es2_update(sparx5, cmd, sel, addr); 1191 break; 1192 default: 1193 sparx5_vcap_type_err(sparx5, admin, __func__); 1194 break; 1195 } 1196 } 1197 1198 static void sparx5_vcap_super_move(struct sparx5 *sparx5, 1199 u32 addr, 1200 enum vcap_command cmd, 1201 u16 mv_num_pos, 1202 u16 mv_size) 1203 { 1204 spx5_wr(VCAP_SUPER_CFG_MV_NUM_POS_SET(mv_num_pos) | 1205 VCAP_SUPER_CFG_MV_SIZE_SET(mv_size), 1206 sparx5, VCAP_SUPER_CFG); 1207 spx5_wr(VCAP_SUPER_CTRL_UPDATE_CMD_SET(cmd) | 1208 VCAP_SUPER_CTRL_UPDATE_ENTRY_DIS_SET(0) | 1209 VCAP_SUPER_CTRL_UPDATE_ACTION_DIS_SET(0) | 1210 VCAP_SUPER_CTRL_UPDATE_CNT_DIS_SET(0) | 1211 VCAP_SUPER_CTRL_UPDATE_ADDR_SET(addr) | 1212 VCAP_SUPER_CTRL_CLEAR_CACHE_SET(false) | 1213 VCAP_SUPER_CTRL_UPDATE_SHOT_SET(true), 1214 sparx5, VCAP_SUPER_CTRL); 1215 sparx5_vcap_wait_super_update(sparx5); 1216 } 1217 1218 static void sparx5_vcap_es2_move(struct sparx5 *sparx5, 1219 u32 addr, 1220 enum vcap_command cmd, 1221 u16 mv_num_pos, 1222 u16 mv_size) 1223 { 1224 spx5_wr(VCAP_ES2_CFG_MV_NUM_POS_SET(mv_num_pos) | 1225 VCAP_ES2_CFG_MV_SIZE_SET(mv_size), 1226 sparx5, VCAP_ES2_CFG); 1227 spx5_wr(VCAP_ES2_CTRL_UPDATE_CMD_SET(cmd) | 1228 VCAP_ES2_CTRL_UPDATE_ENTRY_DIS_SET(0) | 1229 VCAP_ES2_CTRL_UPDATE_ACTION_DIS_SET(0) | 1230 VCAP_ES2_CTRL_UPDATE_CNT_DIS_SET(0) | 1231 VCAP_ES2_CTRL_UPDATE_ADDR_SET(addr) | 1232 VCAP_ES2_CTRL_CLEAR_CACHE_SET(false) | 1233 VCAP_ES2_CTRL_UPDATE_SHOT_SET(true), 1234 sparx5, VCAP_ES2_CTRL); 1235 sparx5_vcap_wait_es2_update(sparx5); 1236 } 1237 1238 /* API callback used for moving a block of rules in the VCAP */ 1239 static void sparx5_vcap_move(struct net_device *ndev, struct vcap_admin *admin, 1240 u32 addr, int offset, int count) 1241 { 1242 struct sparx5_port *port = netdev_priv(ndev); 1243 struct sparx5 *sparx5 = port->sparx5; 1244 enum vcap_command cmd; 1245 u16 mv_num_pos; 1246 u16 mv_size; 1247 1248 mv_size = count - 1; 1249 if (offset > 0) { 1250 mv_num_pos = offset - 1; 1251 cmd = VCAP_CMD_MOVE_DOWN; 1252 } else { 1253 mv_num_pos = -offset - 1; 1254 cmd = VCAP_CMD_MOVE_UP; 1255 } 1256 1257 switch (admin->vtype) { 1258 case VCAP_TYPE_IS0: 1259 case VCAP_TYPE_IS2: 1260 sparx5_vcap_super_move(sparx5, addr, cmd, mv_num_pos, mv_size); 1261 break; 1262 case VCAP_TYPE_ES2: 1263 sparx5_vcap_es2_move(sparx5, addr, cmd, mv_num_pos, mv_size); 1264 break; 1265 default: 1266 sparx5_vcap_type_err(sparx5, admin, __func__); 1267 break; 1268 } 1269 } 1270 1271 static struct vcap_operations sparx5_vcap_ops = { 1272 .validate_keyset = sparx5_vcap_validate_keyset, 1273 .add_default_fields = sparx5_vcap_add_default_fields, 1274 .cache_erase = sparx5_vcap_cache_erase, 1275 .cache_write = sparx5_vcap_cache_write, 1276 .cache_read = sparx5_vcap_cache_read, 1277 .init = sparx5_vcap_range_init, 1278 .update = sparx5_vcap_update, 1279 .move = sparx5_vcap_move, 1280 .port_info = sparx5_port_info, 1281 }; 1282 1283 /* Enable IS0 lookups per port and set the keyset generation */ 1284 static void sparx5_vcap_is0_port_key_selection(struct sparx5 *sparx5, 1285 struct vcap_admin *admin) 1286 { 1287 int portno, lookup; 1288 u32 keysel; 1289 1290 keysel = VCAP_IS0_KEYSEL(false, 1291 VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE, 1292 VCAP_IS0_PS_ETYPE_NORMAL_5TUPLE_IP4, 1293 VCAP_IS0_PS_ETYPE_NORMAL_7TUPLE, 1294 VCAP_IS0_PS_MPLS_FOLLOW_ETYPE, 1295 VCAP_IS0_PS_MPLS_FOLLOW_ETYPE, 1296 VCAP_IS0_PS_MLBS_FOLLOW_ETYPE); 1297 for (lookup = 0; lookup < admin->lookups; ++lookup) { 1298 for (portno = 0; portno < SPX5_PORTS; ++portno) { 1299 spx5_wr(keysel, sparx5, 1300 ANA_CL_ADV_CL_CFG(portno, lookup)); 1301 spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA, 1302 ANA_CL_ADV_CL_CFG_LOOKUP_ENA, 1303 sparx5, 1304 ANA_CL_ADV_CL_CFG(portno, lookup)); 1305 } 1306 } 1307 } 1308 1309 /* Enable IS2 lookups per port and set the keyset generation */ 1310 static void sparx5_vcap_is2_port_key_selection(struct sparx5 *sparx5, 1311 struct vcap_admin *admin) 1312 { 1313 int portno, lookup; 1314 u32 keysel; 1315 1316 keysel = VCAP_IS2_KEYSEL(true, VCAP_IS2_PS_NONETH_MAC_ETYPE, 1317 VCAP_IS2_PS_IPV4_MC_IP4_TCP_UDP_OTHER, 1318 VCAP_IS2_PS_IPV4_UC_IP4_TCP_UDP_OTHER, 1319 VCAP_IS2_PS_IPV6_MC_IP_7TUPLE, 1320 VCAP_IS2_PS_IPV6_UC_IP_7TUPLE, 1321 VCAP_IS2_PS_ARP_ARP); 1322 for (lookup = 0; lookup < admin->lookups; ++lookup) { 1323 for (portno = 0; portno < SPX5_PORTS; ++portno) { 1324 spx5_wr(keysel, sparx5, 1325 ANA_ACL_VCAP_S2_KEY_SEL(portno, lookup)); 1326 } 1327 } 1328 /* IS2 lookups are in bit 0:3 */ 1329 for (portno = 0; portno < SPX5_PORTS; ++portno) 1330 spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0xf), 1331 ANA_ACL_VCAP_S2_CFG_SEC_ENA, 1332 sparx5, 1333 ANA_ACL_VCAP_S2_CFG(portno)); 1334 } 1335 1336 /* Enable ES2 lookups per port and set the keyset generation */ 1337 static void sparx5_vcap_es2_port_key_selection(struct sparx5 *sparx5, 1338 struct vcap_admin *admin) 1339 { 1340 int portno, lookup; 1341 u32 keysel; 1342 1343 keysel = VCAP_ES2_KEYSEL(true, VCAP_ES2_PS_ARP_MAC_ETYPE, 1344 VCAP_ES2_PS_IPV4_IP4_TCP_UDP_OTHER, 1345 VCAP_ES2_PS_IPV6_IP_7TUPLE); 1346 for (lookup = 0; lookup < admin->lookups; ++lookup) 1347 for (portno = 0; portno < SPX5_PORTS; ++portno) 1348 spx5_wr(keysel, sparx5, 1349 EACL_VCAP_ES2_KEY_SEL(portno, lookup)); 1350 } 1351 1352 /* Enable lookups per port and set the keyset generation */ 1353 static void sparx5_vcap_port_key_selection(struct sparx5 *sparx5, 1354 struct vcap_admin *admin) 1355 { 1356 switch (admin->vtype) { 1357 case VCAP_TYPE_IS0: 1358 sparx5_vcap_is0_port_key_selection(sparx5, admin); 1359 break; 1360 case VCAP_TYPE_IS2: 1361 sparx5_vcap_is2_port_key_selection(sparx5, admin); 1362 break; 1363 case VCAP_TYPE_ES2: 1364 sparx5_vcap_es2_port_key_selection(sparx5, admin); 1365 break; 1366 default: 1367 sparx5_vcap_type_err(sparx5, admin, __func__); 1368 break; 1369 } 1370 } 1371 1372 /* Disable lookups per port */ 1373 static void sparx5_vcap_port_key_deselection(struct sparx5 *sparx5, 1374 struct vcap_admin *admin) 1375 { 1376 int portno, lookup; 1377 1378 switch (admin->vtype) { 1379 case VCAP_TYPE_IS0: 1380 for (lookup = 0; lookup < admin->lookups; ++lookup) 1381 for (portno = 0; portno < SPX5_PORTS; ++portno) 1382 spx5_rmw(ANA_CL_ADV_CL_CFG_LOOKUP_ENA_SET(0), 1383 ANA_CL_ADV_CL_CFG_LOOKUP_ENA, 1384 sparx5, 1385 ANA_CL_ADV_CL_CFG(portno, lookup)); 1386 break; 1387 case VCAP_TYPE_IS2: 1388 for (portno = 0; portno < SPX5_PORTS; ++portno) 1389 spx5_rmw(ANA_ACL_VCAP_S2_CFG_SEC_ENA_SET(0), 1390 ANA_ACL_VCAP_S2_CFG_SEC_ENA, 1391 sparx5, 1392 ANA_ACL_VCAP_S2_CFG(portno)); 1393 break; 1394 case VCAP_TYPE_ES2: 1395 for (lookup = 0; lookup < admin->lookups; ++lookup) 1396 for (portno = 0; portno < SPX5_PORTS; ++portno) 1397 spx5_rmw(EACL_VCAP_ES2_KEY_SEL_KEY_ENA_SET(0), 1398 EACL_VCAP_ES2_KEY_SEL_KEY_ENA, 1399 sparx5, 1400 EACL_VCAP_ES2_KEY_SEL(portno, lookup)); 1401 break; 1402 default: 1403 sparx5_vcap_type_err(sparx5, admin, __func__); 1404 break; 1405 } 1406 } 1407 1408 static void sparx5_vcap_admin_free(struct vcap_admin *admin) 1409 { 1410 if (!admin) 1411 return; 1412 mutex_destroy(&admin->lock); 1413 kfree(admin->cache.keystream); 1414 kfree(admin->cache.maskstream); 1415 kfree(admin->cache.actionstream); 1416 kfree(admin); 1417 } 1418 1419 /* Allocate a vcap instance with a rule list and a cache area */ 1420 static struct vcap_admin * 1421 sparx5_vcap_admin_alloc(struct sparx5 *sparx5, struct vcap_control *ctrl, 1422 const struct sparx5_vcap_inst *cfg) 1423 { 1424 struct vcap_admin *admin; 1425 1426 admin = kzalloc(sizeof(*admin), GFP_KERNEL); 1427 if (!admin) 1428 return ERR_PTR(-ENOMEM); 1429 INIT_LIST_HEAD(&admin->list); 1430 INIT_LIST_HEAD(&admin->rules); 1431 INIT_LIST_HEAD(&admin->enabled); 1432 mutex_init(&admin->lock); 1433 admin->vtype = cfg->vtype; 1434 admin->vinst = cfg->vinst; 1435 admin->ingress = cfg->ingress; 1436 admin->lookups = cfg->lookups; 1437 admin->lookups_per_instance = cfg->lookups_per_instance; 1438 admin->first_cid = cfg->first_cid; 1439 admin->last_cid = cfg->last_cid; 1440 admin->cache.keystream = 1441 kzalloc(STREAMSIZE, GFP_KERNEL); 1442 admin->cache.maskstream = 1443 kzalloc(STREAMSIZE, GFP_KERNEL); 1444 admin->cache.actionstream = 1445 kzalloc(STREAMSIZE, GFP_KERNEL); 1446 if (!admin->cache.keystream || !admin->cache.maskstream || 1447 !admin->cache.actionstream) { 1448 sparx5_vcap_admin_free(admin); 1449 return ERR_PTR(-ENOMEM); 1450 } 1451 return admin; 1452 } 1453 1454 /* Do block allocations and provide addresses for VCAP instances */ 1455 static void sparx5_vcap_block_alloc(struct sparx5 *sparx5, 1456 struct vcap_admin *admin, 1457 const struct sparx5_vcap_inst *cfg) 1458 { 1459 int idx, cores; 1460 1461 switch (admin->vtype) { 1462 case VCAP_TYPE_IS0: 1463 case VCAP_TYPE_IS2: 1464 /* Super VCAP block mapping and address configuration. Block 0 1465 * is assigned addresses 0 through 3071, block 1 is assigned 1466 * addresses 3072 though 6143, and so on. 1467 */ 1468 for (idx = cfg->blockno; idx < cfg->blockno + cfg->blocks; 1469 ++idx) { 1470 spx5_wr(VCAP_SUPER_IDX_CORE_IDX_SET(idx), sparx5, 1471 VCAP_SUPER_IDX); 1472 spx5_wr(VCAP_SUPER_MAP_CORE_MAP_SET(cfg->map_id), 1473 sparx5, VCAP_SUPER_MAP); 1474 } 1475 admin->first_valid_addr = cfg->blockno * SUPER_VCAP_BLK_SIZE; 1476 admin->last_used_addr = admin->first_valid_addr + 1477 cfg->blocks * SUPER_VCAP_BLK_SIZE; 1478 admin->last_valid_addr = admin->last_used_addr - 1; 1479 break; 1480 case VCAP_TYPE_ES2: 1481 admin->first_valid_addr = 0; 1482 admin->last_used_addr = cfg->count; 1483 admin->last_valid_addr = cfg->count - 1; 1484 cores = spx5_rd(sparx5, VCAP_ES2_CORE_CNT); 1485 for (idx = 0; idx < cores; ++idx) { 1486 spx5_wr(VCAP_ES2_IDX_CORE_IDX_SET(idx), sparx5, 1487 VCAP_ES2_IDX); 1488 spx5_wr(VCAP_ES2_MAP_CORE_MAP_SET(1), sparx5, 1489 VCAP_ES2_MAP); 1490 } 1491 break; 1492 default: 1493 sparx5_vcap_type_err(sparx5, admin, __func__); 1494 break; 1495 } 1496 } 1497 1498 /* Allocate a vcap control and vcap instances and configure the system */ 1499 int sparx5_vcap_init(struct sparx5 *sparx5) 1500 { 1501 const struct sparx5_vcap_inst *cfg; 1502 struct vcap_control *ctrl; 1503 struct vcap_admin *admin; 1504 struct dentry *dir; 1505 int err = 0, idx; 1506 1507 /* Create a VCAP control instance that owns the platform specific VCAP 1508 * model with VCAP instances and information about keysets, keys, 1509 * actionsets and actions 1510 * - Create administrative state for each available VCAP 1511 * - Lists of rules 1512 * - Address information 1513 * - Initialize VCAP blocks 1514 * - Configure port keysets 1515 */ 1516 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 1517 if (!ctrl) 1518 return -ENOMEM; 1519 1520 sparx5->vcap_ctrl = ctrl; 1521 /* select the sparx5 VCAP model */ 1522 ctrl->vcaps = sparx5_vcaps; 1523 ctrl->stats = &sparx5_vcap_stats; 1524 /* Setup callbacks to allow the API to use the VCAP HW */ 1525 ctrl->ops = &sparx5_vcap_ops; 1526 1527 INIT_LIST_HEAD(&ctrl->list); 1528 for (idx = 0; idx < ARRAY_SIZE(sparx5_vcap_inst_cfg); ++idx) { 1529 cfg = &sparx5_vcap_inst_cfg[idx]; 1530 admin = sparx5_vcap_admin_alloc(sparx5, ctrl, cfg); 1531 if (IS_ERR(admin)) { 1532 err = PTR_ERR(admin); 1533 pr_err("%s:%d: vcap allocation failed: %d\n", 1534 __func__, __LINE__, err); 1535 return err; 1536 } 1537 sparx5_vcap_block_alloc(sparx5, admin, cfg); 1538 sparx5_vcap_block_init(sparx5, admin); 1539 if (cfg->vinst == 0) 1540 sparx5_vcap_port_key_selection(sparx5, admin); 1541 list_add_tail(&admin->list, &ctrl->list); 1542 } 1543 dir = vcap_debugfs(sparx5->dev, sparx5->debugfs_root, ctrl); 1544 for (idx = 0; idx < SPX5_PORTS; ++idx) 1545 if (sparx5->ports[idx]) 1546 vcap_port_debugfs(sparx5->dev, dir, ctrl, 1547 sparx5->ports[idx]->ndev); 1548 1549 return err; 1550 } 1551 1552 void sparx5_vcap_destroy(struct sparx5 *sparx5) 1553 { 1554 struct vcap_control *ctrl = sparx5->vcap_ctrl; 1555 struct vcap_admin *admin, *admin_next; 1556 1557 if (!ctrl) 1558 return; 1559 1560 list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) { 1561 sparx5_vcap_port_key_deselection(sparx5, admin); 1562 vcap_del_rules(ctrl, admin); 1563 list_del(&admin->list); 1564 sparx5_vcap_admin_free(admin); 1565 } 1566 kfree(ctrl); 1567 } 1568