1 // SPDX-License-Identifier: GPL-2.0+ 2 3 #include "lan966x_main.h" 4 #include "lan966x_vcap_ag_api.h" 5 #include "vcap_api.h" 6 #include "vcap_api_client.h" 7 #include "vcap_api_debugfs.h" 8 9 #define STREAMSIZE (64 * 4) 10 11 #define LAN966X_IS1_LOOKUPS 3 12 #define LAN966X_IS2_LOOKUPS 2 13 14 static struct lan966x_vcap_inst { 15 enum vcap_type vtype; /* type of vcap */ 16 int tgt_inst; /* hardware instance number */ 17 int lookups; /* number of lookups in this vcap type */ 18 int first_cid; /* first chain id in this vcap */ 19 int last_cid; /* last chain id in this vcap */ 20 int count; /* number of available addresses */ 21 bool ingress; /* is vcap in the ingress path */ 22 } lan966x_vcap_inst_cfg[] = { 23 { 24 .vtype = VCAP_TYPE_IS1, /* IS1-0 */ 25 .tgt_inst = 1, 26 .lookups = LAN966X_IS1_LOOKUPS, 27 .first_cid = LAN966X_VCAP_CID_IS1_L0, 28 .last_cid = LAN966X_VCAP_CID_IS1_MAX, 29 .count = 768, 30 .ingress = true, 31 }, 32 { 33 .vtype = VCAP_TYPE_IS2, /* IS2-0 */ 34 .tgt_inst = 2, 35 .lookups = LAN966X_IS2_LOOKUPS, 36 .first_cid = LAN966X_VCAP_CID_IS2_L0, 37 .last_cid = LAN966X_VCAP_CID_IS2_MAX, 38 .count = 256, 39 .ingress = true, 40 }, 41 }; 42 43 struct lan966x_vcap_cmd_cb { 44 struct lan966x *lan966x; 45 u32 instance; 46 }; 47 48 static u32 lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb *cb) 49 { 50 return lan_rd(cb->lan966x, VCAP_UPDATE_CTRL(cb->instance)); 51 } 52 53 static void lan966x_vcap_wait_update(struct lan966x *lan966x, int instance) 54 { 55 const struct lan966x_vcap_cmd_cb cb = { .lan966x = lan966x, 56 .instance = instance }; 57 u32 val; 58 59 readx_poll_timeout(lan966x_vcap_read_update_ctrl, &cb, val, 60 (val & VCAP_UPDATE_CTRL_UPDATE_SHOT) == 0, 10, 61 100000); 62 } 63 64 static void __lan966x_vcap_range_init(struct lan966x *lan966x, 65 struct vcap_admin *admin, 66 u32 addr, 67 u32 count) 68 { 69 lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) | 70 VCAP_MV_CFG_MV_SIZE_SET(count - 1), 71 lan966x, VCAP_MV_CFG(admin->tgt_inst)); 72 73 lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) | 74 VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) | 75 VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) | 76 VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) | 77 VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) | 78 VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(true) | 79 VCAP_UPDATE_CTRL_UPDATE_SHOT_SET(1), 80 lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst)); 81 82 lan966x_vcap_wait_update(lan966x, admin->tgt_inst); 83 } 84 85 static int lan966x_vcap_is1_cid_to_lookup(int cid) 86 { 87 int lookup = 0; 88 89 if (cid >= LAN966X_VCAP_CID_IS1_L1 && 90 cid < LAN966X_VCAP_CID_IS1_L2) 91 lookup = 1; 92 else if (cid >= LAN966X_VCAP_CID_IS1_L2 && 93 cid < LAN966X_VCAP_CID_IS1_MAX) 94 lookup = 2; 95 96 return lookup; 97 } 98 99 static int lan966x_vcap_is2_cid_to_lookup(int cid) 100 { 101 if (cid >= LAN966X_VCAP_CID_IS2_L1 && 102 cid < LAN966X_VCAP_CID_IS2_MAX) 103 return 1; 104 105 return 0; 106 } 107 108 /* Return the list of keysets for the vcap port configuration */ 109 static int 110 lan966x_vcap_is1_get_port_keysets(struct net_device *ndev, int lookup, 111 struct vcap_keyset_list *keysetlist, 112 u16 l3_proto) 113 { 114 struct lan966x_port *port = netdev_priv(ndev); 115 struct lan966x *lan966x = port->lan966x; 116 u32 val; 117 118 val = lan_rd(lan966x, ANA_VCAP_S1_CFG(port->chip_port, lookup)); 119 120 /* Collect all keysets for the port in a list */ 121 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) { 122 switch (ANA_VCAP_S1_CFG_KEY_IP4_CFG_GET(val)) { 123 case VCAP_IS1_PS_IPV4_7TUPLE: 124 vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE); 125 break; 126 case VCAP_IS1_PS_IPV4_5TUPLE_IP4: 127 vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4); 128 break; 129 case VCAP_IS1_PS_IPV4_NORMAL: 130 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL); 131 break; 132 } 133 } 134 135 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { 136 switch (ANA_VCAP_S1_CFG_KEY_IP6_CFG_GET(val)) { 137 case VCAP_IS1_PS_IPV6_NORMAL: 138 case VCAP_IS1_PS_IPV6_NORMAL_IP6: 139 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL); 140 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL_IP6); 141 break; 142 case VCAP_IS1_PS_IPV6_5TUPLE_IP6: 143 vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP6); 144 break; 145 case VCAP_IS1_PS_IPV6_7TUPLE: 146 vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE); 147 break; 148 case VCAP_IS1_PS_IPV6_5TUPLE_IP4: 149 vcap_keyset_list_add(keysetlist, VCAP_KFS_5TUPLE_IP4); 150 break; 151 case VCAP_IS1_PS_IPV6_DMAC_VID: 152 vcap_keyset_list_add(keysetlist, VCAP_KFS_DMAC_VID); 153 break; 154 } 155 } 156 157 switch (ANA_VCAP_S1_CFG_KEY_OTHER_CFG_GET(val)) { 158 case VCAP_IS1_PS_OTHER_7TUPLE: 159 vcap_keyset_list_add(keysetlist, VCAP_KFS_7TUPLE); 160 break; 161 case VCAP_IS1_PS_OTHER_NORMAL: 162 vcap_keyset_list_add(keysetlist, VCAP_KFS_NORMAL); 163 break; 164 } 165 166 return 0; 167 } 168 169 static int 170 lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup, 171 struct vcap_keyset_list *keysetlist, 172 u16 l3_proto) 173 { 174 struct lan966x_port *port = netdev_priv(dev); 175 struct lan966x *lan966x = port->lan966x; 176 bool found = false; 177 u32 val; 178 179 val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port)); 180 181 /* Collect all keysets for the port in a list */ 182 if (l3_proto == ETH_P_ALL) 183 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 184 185 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_SNAP) { 186 if (ANA_VCAP_S2_CFG_SNAP_DIS_GET(val) & (BIT(0) << lookup)) 187 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_LLC); 188 else 189 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_SNAP); 190 191 found = true; 192 } 193 194 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_CFM) { 195 if (ANA_VCAP_S2_CFG_OAM_DIS_GET(val) & (BIT(0) << lookup)) 196 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 197 else 198 vcap_keyset_list_add(keysetlist, VCAP_KFS_OAM); 199 200 found = true; 201 } 202 203 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) { 204 if (ANA_VCAP_S2_CFG_ARP_DIS_GET(val) & (BIT(0) << lookup)) 205 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 206 else 207 vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP); 208 209 found = true; 210 } 211 212 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) { 213 if (ANA_VCAP_S2_CFG_IP_OTHER_DIS_GET(val) & (BIT(0) << lookup)) 214 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 215 else 216 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 217 218 if (ANA_VCAP_S2_CFG_IP_TCPUDP_DIS_GET(val) & (BIT(0) << lookup)) 219 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 220 else 221 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 222 223 found = true; 224 } 225 226 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { 227 switch (ANA_VCAP_S2_CFG_IP6_CFG_GET(val) & (0x3 << lookup)) { 228 case VCAP_IS2_PS_IPV6_TCPUDP_OTHER: 229 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_OTHER); 230 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_TCP_UDP); 231 break; 232 case VCAP_IS2_PS_IPV6_STD: 233 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); 234 break; 235 case VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER: 236 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 237 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 238 break; 239 case VCAP_IS2_PS_IPV6_MAC_ETYPE: 240 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 241 break; 242 } 243 244 found = true; 245 } 246 247 if (!found) 248 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 249 250 return 0; 251 } 252 253 static enum vcap_keyfield_set 254 lan966x_vcap_validate_keyset(struct net_device *dev, 255 struct vcap_admin *admin, 256 struct vcap_rule *rule, 257 struct vcap_keyset_list *kslist, 258 u16 l3_proto) 259 { 260 struct vcap_keyset_list keysetlist = {}; 261 enum vcap_keyfield_set keysets[10] = {}; 262 int lookup; 263 int err; 264 265 if (!kslist || kslist->cnt == 0) 266 return VCAP_KFS_NO_VALUE; 267 268 keysetlist.max = ARRAY_SIZE(keysets); 269 keysetlist.keysets = keysets; 270 271 switch (admin->vtype) { 272 case VCAP_TYPE_IS1: 273 lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id); 274 err = lan966x_vcap_is1_get_port_keysets(dev, lookup, &keysetlist, 275 l3_proto); 276 break; 277 case VCAP_TYPE_IS2: 278 lookup = lan966x_vcap_is2_cid_to_lookup(rule->vcap_chain_id); 279 err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist, 280 l3_proto); 281 break; 282 default: 283 pr_err("vcap type: %s not supported\n", 284 lan966x_vcaps[admin->vtype].name); 285 return VCAP_KFS_NO_VALUE; 286 } 287 288 if (err) 289 return VCAP_KFS_NO_VALUE; 290 291 /* Check if there is a match and return the match */ 292 for (int i = 0; i < kslist->cnt; ++i) 293 for (int j = 0; j < keysetlist.cnt; ++j) 294 if (kslist->keysets[i] == keysets[j]) 295 return kslist->keysets[i]; 296 297 return VCAP_KFS_NO_VALUE; 298 } 299 300 static bool lan966x_vcap_is2_is_first_chain(struct vcap_rule *rule) 301 { 302 return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 && 303 rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1); 304 } 305 306 static void lan966x_vcap_is1_add_default_fields(struct lan966x_port *port, 307 struct vcap_admin *admin, 308 struct vcap_rule *rule) 309 { 310 u32 value, mask; 311 u32 lookup; 312 313 if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 314 &value, &mask)) 315 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, 316 ~BIT(port->chip_port)); 317 318 lookup = lan966x_vcap_is1_cid_to_lookup(rule->vcap_chain_id); 319 vcap_rule_add_key_u32(rule, VCAP_KF_LOOKUP_INDEX, lookup, 0x3); 320 } 321 322 static void lan966x_vcap_is2_add_default_fields(struct lan966x_port *port, 323 struct vcap_admin *admin, 324 struct vcap_rule *rule) 325 { 326 u32 value, mask; 327 328 if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 329 &value, &mask)) 330 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, 331 ~BIT(port->chip_port)); 332 333 if (lan966x_vcap_is2_is_first_chain(rule)) 334 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 335 VCAP_BIT_1); 336 else 337 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 338 VCAP_BIT_0); 339 } 340 341 static void lan966x_vcap_add_default_fields(struct net_device *dev, 342 struct vcap_admin *admin, 343 struct vcap_rule *rule) 344 { 345 struct lan966x_port *port = netdev_priv(dev); 346 347 switch (admin->vtype) { 348 case VCAP_TYPE_IS1: 349 lan966x_vcap_is1_add_default_fields(port, admin, rule); 350 break; 351 case VCAP_TYPE_IS2: 352 lan966x_vcap_is2_add_default_fields(port, admin, rule); 353 break; 354 default: 355 pr_err("vcap type: %s not supported\n", 356 lan966x_vcaps[admin->vtype].name); 357 break; 358 } 359 } 360 361 static void lan966x_vcap_cache_erase(struct vcap_admin *admin) 362 { 363 memset(admin->cache.keystream, 0, STREAMSIZE); 364 memset(admin->cache.maskstream, 0, STREAMSIZE); 365 memset(admin->cache.actionstream, 0, STREAMSIZE); 366 memset(&admin->cache.counter, 0, sizeof(admin->cache.counter)); 367 } 368 369 static void lan966x_vcap_cache_write(struct net_device *dev, 370 struct vcap_admin *admin, 371 enum vcap_selection sel, 372 u32 start, 373 u32 count) 374 { 375 struct lan966x_port *port = netdev_priv(dev); 376 struct lan966x *lan966x = port->lan966x; 377 u32 *keystr, *mskstr, *actstr; 378 379 keystr = &admin->cache.keystream[start]; 380 mskstr = &admin->cache.maskstream[start]; 381 actstr = &admin->cache.actionstream[start]; 382 383 switch (sel) { 384 case VCAP_SEL_ENTRY: 385 for (int i = 0; i < count; ++i) { 386 lan_wr(keystr[i] & mskstr[i], lan966x, 387 VCAP_ENTRY_DAT(admin->tgt_inst, i)); 388 lan_wr(~mskstr[i], lan966x, 389 VCAP_MASK_DAT(admin->tgt_inst, i)); 390 } 391 break; 392 case VCAP_SEL_ACTION: 393 for (int i = 0; i < count; ++i) 394 lan_wr(actstr[i], lan966x, 395 VCAP_ACTION_DAT(admin->tgt_inst, i)); 396 break; 397 case VCAP_SEL_COUNTER: 398 admin->cache.sticky = admin->cache.counter > 0; 399 lan_wr(admin->cache.counter, lan966x, 400 VCAP_CNT_DAT(admin->tgt_inst, 0)); 401 break; 402 default: 403 break; 404 } 405 } 406 407 static void lan966x_vcap_cache_read(struct net_device *dev, 408 struct vcap_admin *admin, 409 enum vcap_selection sel, 410 u32 start, 411 u32 count) 412 { 413 struct lan966x_port *port = netdev_priv(dev); 414 struct lan966x *lan966x = port->lan966x; 415 int instance = admin->tgt_inst; 416 u32 *keystr, *mskstr, *actstr; 417 418 keystr = &admin->cache.keystream[start]; 419 mskstr = &admin->cache.maskstream[start]; 420 actstr = &admin->cache.actionstream[start]; 421 422 if (sel & VCAP_SEL_ENTRY) { 423 for (int i = 0; i < count; ++i) { 424 keystr[i] = 425 lan_rd(lan966x, VCAP_ENTRY_DAT(instance, i)); 426 mskstr[i] = 427 ~lan_rd(lan966x, VCAP_MASK_DAT(instance, i)); 428 } 429 } 430 431 if (sel & VCAP_SEL_ACTION) 432 for (int i = 0; i < count; ++i) 433 actstr[i] = 434 lan_rd(lan966x, VCAP_ACTION_DAT(instance, i)); 435 436 if (sel & VCAP_SEL_COUNTER) { 437 admin->cache.counter = 438 lan_rd(lan966x, VCAP_CNT_DAT(instance, 0)); 439 admin->cache.sticky = admin->cache.counter > 0; 440 } 441 } 442 443 static void lan966x_vcap_range_init(struct net_device *dev, 444 struct vcap_admin *admin, 445 u32 addr, 446 u32 count) 447 { 448 struct lan966x_port *port = netdev_priv(dev); 449 struct lan966x *lan966x = port->lan966x; 450 451 __lan966x_vcap_range_init(lan966x, admin, addr, count); 452 } 453 454 static void lan966x_vcap_update(struct net_device *dev, 455 struct vcap_admin *admin, 456 enum vcap_command cmd, 457 enum vcap_selection sel, 458 u32 addr) 459 { 460 struct lan966x_port *port = netdev_priv(dev); 461 struct lan966x *lan966x = port->lan966x; 462 bool clear; 463 464 clear = (cmd == VCAP_CMD_INITIALIZE); 465 466 lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) | 467 VCAP_MV_CFG_MV_SIZE_SET(0), 468 lan966x, VCAP_MV_CFG(admin->tgt_inst)); 469 470 lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) | 471 VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) | 472 VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) | 473 VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) | 474 VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) | 475 VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(clear) | 476 VCAP_UPDATE_CTRL_UPDATE_SHOT, 477 lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst)); 478 479 lan966x_vcap_wait_update(lan966x, admin->tgt_inst); 480 } 481 482 static void lan966x_vcap_move(struct net_device *dev, 483 struct vcap_admin *admin, 484 u32 addr, int offset, int count) 485 { 486 struct lan966x_port *port = netdev_priv(dev); 487 struct lan966x *lan966x = port->lan966x; 488 enum vcap_command cmd; 489 u16 mv_num_pos; 490 u16 mv_size; 491 492 mv_size = count - 1; 493 if (offset > 0) { 494 mv_num_pos = offset - 1; 495 cmd = VCAP_CMD_MOVE_DOWN; 496 } else { 497 mv_num_pos = -offset - 1; 498 cmd = VCAP_CMD_MOVE_UP; 499 } 500 501 lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(mv_num_pos) | 502 VCAP_MV_CFG_MV_SIZE_SET(mv_size), 503 lan966x, VCAP_MV_CFG(admin->tgt_inst)); 504 505 lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) | 506 VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) | 507 VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) | 508 VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) | 509 VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) | 510 VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(false) | 511 VCAP_UPDATE_CTRL_UPDATE_SHOT, 512 lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst)); 513 514 lan966x_vcap_wait_update(lan966x, admin->tgt_inst); 515 } 516 517 static struct vcap_operations lan966x_vcap_ops = { 518 .validate_keyset = lan966x_vcap_validate_keyset, 519 .add_default_fields = lan966x_vcap_add_default_fields, 520 .cache_erase = lan966x_vcap_cache_erase, 521 .cache_write = lan966x_vcap_cache_write, 522 .cache_read = lan966x_vcap_cache_read, 523 .init = lan966x_vcap_range_init, 524 .update = lan966x_vcap_update, 525 .move = lan966x_vcap_move, 526 .port_info = lan966x_vcap_port_info, 527 }; 528 529 static void lan966x_vcap_admin_free(struct vcap_admin *admin) 530 { 531 if (!admin) 532 return; 533 534 kfree(admin->cache.keystream); 535 kfree(admin->cache.maskstream); 536 kfree(admin->cache.actionstream); 537 mutex_destroy(&admin->lock); 538 kfree(admin); 539 } 540 541 static struct vcap_admin * 542 lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl, 543 const struct lan966x_vcap_inst *cfg) 544 { 545 struct vcap_admin *admin; 546 547 admin = kzalloc(sizeof(*admin), GFP_KERNEL); 548 if (!admin) 549 return ERR_PTR(-ENOMEM); 550 551 mutex_init(&admin->lock); 552 INIT_LIST_HEAD(&admin->list); 553 INIT_LIST_HEAD(&admin->rules); 554 INIT_LIST_HEAD(&admin->enabled); 555 556 admin->vtype = cfg->vtype; 557 admin->vinst = 0; 558 admin->ingress = cfg->ingress; 559 admin->w32be = true; 560 admin->tgt_inst = cfg->tgt_inst; 561 562 admin->lookups = cfg->lookups; 563 admin->lookups_per_instance = cfg->lookups; 564 565 admin->first_cid = cfg->first_cid; 566 admin->last_cid = cfg->last_cid; 567 568 admin->cache.keystream = kzalloc(STREAMSIZE, GFP_KERNEL); 569 admin->cache.maskstream = kzalloc(STREAMSIZE, GFP_KERNEL); 570 admin->cache.actionstream = kzalloc(STREAMSIZE, GFP_KERNEL); 571 if (!admin->cache.keystream || 572 !admin->cache.maskstream || 573 !admin->cache.actionstream) { 574 lan966x_vcap_admin_free(admin); 575 return ERR_PTR(-ENOMEM); 576 } 577 578 return admin; 579 } 580 581 static void lan966x_vcap_block_init(struct lan966x *lan966x, 582 struct vcap_admin *admin, 583 struct lan966x_vcap_inst *cfg) 584 { 585 admin->first_valid_addr = 0; 586 admin->last_used_addr = cfg->count; 587 admin->last_valid_addr = cfg->count - 1; 588 589 lan_wr(VCAP_CORE_IDX_CORE_IDX_SET(0), 590 lan966x, VCAP_CORE_IDX(admin->tgt_inst)); 591 lan_wr(VCAP_CORE_MAP_CORE_MAP_SET(1), 592 lan966x, VCAP_CORE_MAP(admin->tgt_inst)); 593 594 __lan966x_vcap_range_init(lan966x, admin, admin->first_valid_addr, 595 admin->last_valid_addr - 596 admin->first_valid_addr); 597 } 598 599 static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x, 600 struct vcap_admin *admin) 601 { 602 u32 val; 603 604 switch (admin->vtype) { 605 case VCAP_TYPE_IS1: 606 val = ANA_VCAP_S1_CFG_KEY_IP6_CFG_SET(VCAP_IS1_PS_IPV6_5TUPLE_IP6) | 607 ANA_VCAP_S1_CFG_KEY_IP4_CFG_SET(VCAP_IS1_PS_IPV4_5TUPLE_IP4) | 608 ANA_VCAP_S1_CFG_KEY_OTHER_CFG_SET(VCAP_IS1_PS_OTHER_NORMAL); 609 610 for (int p = 0; p < lan966x->num_phys_ports; ++p) { 611 if (!lan966x->ports[p]) 612 continue; 613 614 for (int l = 0; l < LAN966X_IS1_LOOKUPS; ++l) 615 lan_wr(val, lan966x, ANA_VCAP_S1_CFG(p, l)); 616 617 lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true), 618 ANA_VCAP_CFG_S1_ENA, lan966x, 619 ANA_VCAP_CFG(p)); 620 } 621 622 break; 623 case VCAP_TYPE_IS2: 624 for (int p = 0; p < lan966x->num_phys_ports; ++p) 625 lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p)); 626 627 break; 628 default: 629 pr_err("vcap type: %s not supported\n", 630 lan966x_vcaps[admin->vtype].name); 631 break; 632 } 633 } 634 635 int lan966x_vcap_init(struct lan966x *lan966x) 636 { 637 struct lan966x_vcap_inst *cfg; 638 struct vcap_control *ctrl; 639 struct vcap_admin *admin; 640 struct dentry *dir; 641 642 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 643 if (!ctrl) 644 return -ENOMEM; 645 646 ctrl->vcaps = lan966x_vcaps; 647 ctrl->stats = &lan966x_vcap_stats; 648 ctrl->ops = &lan966x_vcap_ops; 649 650 INIT_LIST_HEAD(&ctrl->list); 651 for (int i = 0; i < ARRAY_SIZE(lan966x_vcap_inst_cfg); ++i) { 652 cfg = &lan966x_vcap_inst_cfg[i]; 653 654 admin = lan966x_vcap_admin_alloc(lan966x, ctrl, cfg); 655 if (IS_ERR(admin)) 656 return PTR_ERR(admin); 657 658 lan966x_vcap_block_init(lan966x, admin, cfg); 659 lan966x_vcap_port_key_deselection(lan966x, admin); 660 661 list_add_tail(&admin->list, &ctrl->list); 662 } 663 664 dir = vcap_debugfs(lan966x->dev, lan966x->debugfs_root, ctrl); 665 for (int p = 0; p < lan966x->num_phys_ports; ++p) { 666 if (lan966x->ports[p]) { 667 vcap_port_debugfs(lan966x->dev, dir, ctrl, 668 lan966x->ports[p]->dev); 669 670 lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(true), 671 ANA_VCAP_S2_CFG_ENA, lan966x, 672 ANA_VCAP_S2_CFG(lan966x->ports[p]->chip_port)); 673 674 lan_rmw(ANA_VCAP_CFG_S1_ENA_SET(true), 675 ANA_VCAP_CFG_S1_ENA, lan966x, 676 ANA_VCAP_CFG(lan966x->ports[p]->chip_port)); 677 } 678 } 679 680 lan966x->vcap_ctrl = ctrl; 681 682 return 0; 683 } 684 685 void lan966x_vcap_deinit(struct lan966x *lan966x) 686 { 687 struct vcap_admin *admin, *admin_next; 688 struct vcap_control *ctrl; 689 690 ctrl = lan966x->vcap_ctrl; 691 if (!ctrl) 692 return; 693 694 list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) { 695 lan966x_vcap_port_key_deselection(lan966x, admin); 696 vcap_del_rules(ctrl, admin); 697 list_del(&admin->list); 698 lan966x_vcap_admin_free(admin); 699 } 700 701 kfree(ctrl); 702 } 703