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 8 #define STREAMSIZE (64 * 4) 9 10 #define LAN966X_IS2_LOOKUPS 2 11 12 enum vcap_is2_port_sel_ipv6 { 13 VCAP_IS2_PS_IPV6_TCPUDP_OTHER, 14 VCAP_IS2_PS_IPV6_STD, 15 VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER, 16 VCAP_IS2_PS_IPV6_MAC_ETYPE, 17 }; 18 19 static struct lan966x_vcap_inst { 20 enum vcap_type vtype; /* type of vcap */ 21 int tgt_inst; /* hardware instance number */ 22 int lookups; /* number of lookups in this vcap type */ 23 int first_cid; /* first chain id in this vcap */ 24 int last_cid; /* last chain id in this vcap */ 25 int count; /* number of available addresses */ 26 } lan966x_vcap_inst_cfg[] = { 27 { 28 .vtype = VCAP_TYPE_IS2, /* IS2-0 */ 29 .tgt_inst = 2, 30 .lookups = LAN966X_IS2_LOOKUPS, 31 .first_cid = LAN966X_VCAP_CID_IS2_L0, 32 .last_cid = LAN966X_VCAP_CID_IS2_MAX, 33 .count = 256, 34 }, 35 }; 36 37 struct lan966x_vcap_cmd_cb { 38 struct lan966x *lan966x; 39 u32 instance; 40 }; 41 42 static u32 lan966x_vcap_read_update_ctrl(const struct lan966x_vcap_cmd_cb *cb) 43 { 44 return lan_rd(cb->lan966x, VCAP_UPDATE_CTRL(cb->instance)); 45 } 46 47 static void lan966x_vcap_wait_update(struct lan966x *lan966x, int instance) 48 { 49 const struct lan966x_vcap_cmd_cb cb = { .lan966x = lan966x, 50 .instance = instance }; 51 u32 val; 52 53 readx_poll_timeout(lan966x_vcap_read_update_ctrl, &cb, val, 54 (val & VCAP_UPDATE_CTRL_UPDATE_SHOT) == 0, 10, 55 100000); 56 } 57 58 static void __lan966x_vcap_range_init(struct lan966x *lan966x, 59 struct vcap_admin *admin, 60 u32 addr, 61 u32 count) 62 { 63 lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) | 64 VCAP_MV_CFG_MV_SIZE_SET(count - 1), 65 lan966x, VCAP_MV_CFG(admin->tgt_inst)); 66 67 lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(VCAP_CMD_INITIALIZE) | 68 VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) | 69 VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) | 70 VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) | 71 VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) | 72 VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(true) | 73 VCAP_UPDATE_CTRL_UPDATE_SHOT_SET(1), 74 lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst)); 75 76 lan966x_vcap_wait_update(lan966x, admin->tgt_inst); 77 } 78 79 static int lan966x_vcap_cid_to_lookup(int cid) 80 { 81 if (cid >= LAN966X_VCAP_CID_IS2_L1 && 82 cid < LAN966X_VCAP_CID_IS2_MAX) 83 return 1; 84 85 return 0; 86 } 87 88 static int 89 lan966x_vcap_is2_get_port_keysets(struct net_device *dev, int lookup, 90 struct vcap_keyset_list *keysetlist, 91 u16 l3_proto) 92 { 93 struct lan966x_port *port = netdev_priv(dev); 94 struct lan966x *lan966x = port->lan966x; 95 bool found = false; 96 u32 val; 97 98 /* Check if the port keyset selection is enabled */ 99 val = lan_rd(lan966x, ANA_VCAP_S2_CFG(port->chip_port)); 100 if (!ANA_VCAP_S2_CFG_ENA_GET(val)) 101 return -ENOENT; 102 103 /* Collect all keysets for the port in a list */ 104 if (l3_proto == ETH_P_ALL) 105 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 106 107 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_SNAP) { 108 if (ANA_VCAP_S2_CFG_SNAP_DIS_GET(val) & (BIT(0) << lookup)) 109 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_LLC); 110 else 111 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_SNAP); 112 113 found = true; 114 } 115 116 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_CFM) { 117 if (ANA_VCAP_S2_CFG_OAM_DIS_GET(val) & (BIT(0) << lookup)) 118 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 119 else 120 vcap_keyset_list_add(keysetlist, VCAP_KFS_OAM); 121 122 found = true; 123 } 124 125 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_ARP) { 126 if (ANA_VCAP_S2_CFG_ARP_DIS_GET(val) & (BIT(0) << lookup)) 127 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 128 else 129 vcap_keyset_list_add(keysetlist, VCAP_KFS_ARP); 130 131 found = true; 132 } 133 134 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IP) { 135 if (ANA_VCAP_S2_CFG_IP_OTHER_DIS_GET(val) & (BIT(0) << lookup)) 136 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 137 else 138 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 139 140 if (ANA_VCAP_S2_CFG_IP_TCPUDP_DIS_GET(val) & (BIT(0) << lookup)) 141 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 142 else 143 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 144 145 found = true; 146 } 147 148 if (l3_proto == ETH_P_ALL || l3_proto == ETH_P_IPV6) { 149 switch (ANA_VCAP_S2_CFG_IP6_CFG_GET(val) & (0x3 << lookup)) { 150 case VCAP_IS2_PS_IPV6_TCPUDP_OTHER: 151 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_OTHER); 152 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_TCP_UDP); 153 break; 154 case VCAP_IS2_PS_IPV6_STD: 155 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP6_STD); 156 break; 157 case VCAP_IS2_PS_IPV6_IP4_TCPUDP_IP4_OTHER: 158 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_OTHER); 159 vcap_keyset_list_add(keysetlist, VCAP_KFS_IP4_TCP_UDP); 160 break; 161 case VCAP_IS2_PS_IPV6_MAC_ETYPE: 162 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 163 break; 164 } 165 166 found = true; 167 } 168 169 if (!found) 170 vcap_keyset_list_add(keysetlist, VCAP_KFS_MAC_ETYPE); 171 172 return 0; 173 } 174 175 static enum vcap_keyfield_set 176 lan966x_vcap_validate_keyset(struct net_device *dev, 177 struct vcap_admin *admin, 178 struct vcap_rule *rule, 179 struct vcap_keyset_list *kslist, 180 u16 l3_proto) 181 { 182 struct vcap_keyset_list keysetlist = {}; 183 enum vcap_keyfield_set keysets[10] = {}; 184 int lookup; 185 int err; 186 187 if (!kslist || kslist->cnt == 0) 188 return VCAP_KFS_NO_VALUE; 189 190 lookup = lan966x_vcap_cid_to_lookup(rule->vcap_chain_id); 191 keysetlist.max = ARRAY_SIZE(keysets); 192 keysetlist.keysets = keysets; 193 err = lan966x_vcap_is2_get_port_keysets(dev, lookup, &keysetlist, 194 l3_proto); 195 if (err) 196 return VCAP_KFS_NO_VALUE; 197 198 /* Check if there is a match and return the match */ 199 for (int i = 0; i < kslist->cnt; ++i) 200 for (int j = 0; j < keysetlist.cnt; ++j) 201 if (kslist->keysets[i] == keysets[j]) 202 return kslist->keysets[i]; 203 204 return VCAP_KFS_NO_VALUE; 205 } 206 207 static bool lan966x_vcap_is_first_chain(struct vcap_rule *rule) 208 { 209 return (rule->vcap_chain_id >= LAN966X_VCAP_CID_IS2_L0 && 210 rule->vcap_chain_id < LAN966X_VCAP_CID_IS2_L1); 211 } 212 213 static void lan966x_vcap_add_default_fields(struct net_device *dev, 214 struct vcap_admin *admin, 215 struct vcap_rule *rule) 216 { 217 struct lan966x_port *port = netdev_priv(dev); 218 u32 value, mask; 219 220 if (vcap_rule_get_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 221 &value, &mask)) 222 vcap_rule_add_key_u32(rule, VCAP_KF_IF_IGR_PORT_MASK, 0, 223 ~BIT(port->chip_port)); 224 225 if (lan966x_vcap_is_first_chain(rule)) 226 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 227 VCAP_BIT_1); 228 else 229 vcap_rule_add_key_bit(rule, VCAP_KF_LOOKUP_FIRST_IS, 230 VCAP_BIT_0); 231 } 232 233 static void lan966x_vcap_cache_erase(struct vcap_admin *admin) 234 { 235 memset(admin->cache.keystream, 0, STREAMSIZE); 236 memset(admin->cache.maskstream, 0, STREAMSIZE); 237 memset(admin->cache.actionstream, 0, STREAMSIZE); 238 memset(&admin->cache.counter, 0, sizeof(admin->cache.counter)); 239 } 240 241 static void lan966x_vcap_cache_write(struct net_device *dev, 242 struct vcap_admin *admin, 243 enum vcap_selection sel, 244 u32 start, 245 u32 count) 246 { 247 struct lan966x_port *port = netdev_priv(dev); 248 struct lan966x *lan966x = port->lan966x; 249 u32 *keystr, *mskstr, *actstr; 250 251 keystr = &admin->cache.keystream[start]; 252 mskstr = &admin->cache.maskstream[start]; 253 actstr = &admin->cache.actionstream[start]; 254 255 switch (sel) { 256 case VCAP_SEL_ENTRY: 257 for (int i = 0; i < count; ++i) { 258 lan_wr(keystr[i] & mskstr[i], lan966x, 259 VCAP_ENTRY_DAT(admin->tgt_inst, i)); 260 lan_wr(~mskstr[i], lan966x, 261 VCAP_MASK_DAT(admin->tgt_inst, i)); 262 } 263 break; 264 case VCAP_SEL_ACTION: 265 for (int i = 0; i < count; ++i) 266 lan_wr(actstr[i], lan966x, 267 VCAP_ACTION_DAT(admin->tgt_inst, i)); 268 break; 269 case VCAP_SEL_COUNTER: 270 admin->cache.sticky = admin->cache.counter > 0; 271 lan_wr(admin->cache.counter, lan966x, 272 VCAP_CNT_DAT(admin->tgt_inst, 0)); 273 break; 274 default: 275 break; 276 } 277 } 278 279 static void lan966x_vcap_cache_read(struct net_device *dev, 280 struct vcap_admin *admin, 281 enum vcap_selection sel, 282 u32 start, 283 u32 count) 284 { 285 struct lan966x_port *port = netdev_priv(dev); 286 struct lan966x *lan966x = port->lan966x; 287 int instance = admin->tgt_inst; 288 u32 *keystr, *mskstr, *actstr; 289 290 keystr = &admin->cache.keystream[start]; 291 mskstr = &admin->cache.maskstream[start]; 292 actstr = &admin->cache.actionstream[start]; 293 294 if (sel & VCAP_SEL_ENTRY) { 295 for (int i = 0; i < count; ++i) { 296 keystr[i] = 297 lan_rd(lan966x, VCAP_ENTRY_DAT(instance, i)); 298 mskstr[i] = 299 ~lan_rd(lan966x, VCAP_MASK_DAT(instance, i)); 300 } 301 } 302 303 if (sel & VCAP_SEL_ACTION) 304 for (int i = 0; i < count; ++i) 305 actstr[i] = 306 lan_rd(lan966x, VCAP_ACTION_DAT(instance, i)); 307 308 if (sel & VCAP_SEL_COUNTER) { 309 admin->cache.counter = 310 lan_rd(lan966x, VCAP_CNT_DAT(instance, 0)); 311 admin->cache.sticky = admin->cache.counter > 0; 312 } 313 } 314 315 static void lan966x_vcap_range_init(struct net_device *dev, 316 struct vcap_admin *admin, 317 u32 addr, 318 u32 count) 319 { 320 struct lan966x_port *port = netdev_priv(dev); 321 struct lan966x *lan966x = port->lan966x; 322 323 __lan966x_vcap_range_init(lan966x, admin, addr, count); 324 } 325 326 static void lan966x_vcap_update(struct net_device *dev, 327 struct vcap_admin *admin, 328 enum vcap_command cmd, 329 enum vcap_selection sel, 330 u32 addr) 331 { 332 struct lan966x_port *port = netdev_priv(dev); 333 struct lan966x *lan966x = port->lan966x; 334 bool clear; 335 336 clear = (cmd == VCAP_CMD_INITIALIZE); 337 338 lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(0) | 339 VCAP_MV_CFG_MV_SIZE_SET(0), 340 lan966x, VCAP_MV_CFG(admin->tgt_inst)); 341 342 lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) | 343 VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET((VCAP_SEL_ENTRY & sel) == 0) | 344 VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET((VCAP_SEL_ACTION & sel) == 0) | 345 VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET((VCAP_SEL_COUNTER & sel) == 0) | 346 VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) | 347 VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(clear) | 348 VCAP_UPDATE_CTRL_UPDATE_SHOT, 349 lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst)); 350 351 lan966x_vcap_wait_update(lan966x, admin->tgt_inst); 352 } 353 354 static void lan966x_vcap_move(struct net_device *dev, 355 struct vcap_admin *admin, 356 u32 addr, int offset, int count) 357 { 358 struct lan966x_port *port = netdev_priv(dev); 359 struct lan966x *lan966x = port->lan966x; 360 enum vcap_command cmd; 361 u16 mv_num_pos; 362 u16 mv_size; 363 364 mv_size = count - 1; 365 if (offset > 0) { 366 mv_num_pos = offset - 1; 367 cmd = VCAP_CMD_MOVE_DOWN; 368 } else { 369 mv_num_pos = -offset - 1; 370 cmd = VCAP_CMD_MOVE_UP; 371 } 372 373 lan_wr(VCAP_MV_CFG_MV_NUM_POS_SET(mv_num_pos) | 374 VCAP_MV_CFG_MV_SIZE_SET(mv_size), 375 lan966x, VCAP_MV_CFG(admin->tgt_inst)); 376 377 lan_wr(VCAP_UPDATE_CTRL_UPDATE_CMD_SET(cmd) | 378 VCAP_UPDATE_CTRL_UPDATE_ENTRY_DIS_SET(0) | 379 VCAP_UPDATE_CTRL_UPDATE_ACTION_DIS_SET(0) | 380 VCAP_UPDATE_CTRL_UPDATE_CNT_DIS_SET(0) | 381 VCAP_UPDATE_CTRL_UPDATE_ADDR_SET(addr) | 382 VCAP_UPDATE_CTRL_CLEAR_CACHE_SET(false) | 383 VCAP_UPDATE_CTRL_UPDATE_SHOT, 384 lan966x, VCAP_UPDATE_CTRL(admin->tgt_inst)); 385 386 lan966x_vcap_wait_update(lan966x, admin->tgt_inst); 387 } 388 389 static int lan966x_vcap_port_info(struct net_device *dev, 390 struct vcap_admin *admin, 391 struct vcap_output_print *out) 392 { 393 return 0; 394 } 395 396 static int lan966x_vcap_enable(struct net_device *dev, 397 struct vcap_admin *admin, 398 bool enable) 399 { 400 struct lan966x_port *port = netdev_priv(dev); 401 struct lan966x *lan966x = port->lan966x; 402 403 lan_rmw(ANA_VCAP_S2_CFG_ENA_SET(enable), 404 ANA_VCAP_S2_CFG_ENA, 405 lan966x, ANA_VCAP_S2_CFG(port->chip_port)); 406 407 return 0; 408 } 409 410 static struct vcap_operations lan966x_vcap_ops = { 411 .validate_keyset = lan966x_vcap_validate_keyset, 412 .add_default_fields = lan966x_vcap_add_default_fields, 413 .cache_erase = lan966x_vcap_cache_erase, 414 .cache_write = lan966x_vcap_cache_write, 415 .cache_read = lan966x_vcap_cache_read, 416 .init = lan966x_vcap_range_init, 417 .update = lan966x_vcap_update, 418 .move = lan966x_vcap_move, 419 .port_info = lan966x_vcap_port_info, 420 .enable = lan966x_vcap_enable, 421 }; 422 423 static void lan966x_vcap_admin_free(struct vcap_admin *admin) 424 { 425 if (!admin) 426 return; 427 428 kfree(admin->cache.keystream); 429 kfree(admin->cache.maskstream); 430 kfree(admin->cache.actionstream); 431 mutex_destroy(&admin->lock); 432 kfree(admin); 433 } 434 435 static struct vcap_admin * 436 lan966x_vcap_admin_alloc(struct lan966x *lan966x, struct vcap_control *ctrl, 437 const struct lan966x_vcap_inst *cfg) 438 { 439 struct vcap_admin *admin; 440 441 admin = kzalloc(sizeof(*admin), GFP_KERNEL); 442 if (!admin) 443 return ERR_PTR(-ENOMEM); 444 445 mutex_init(&admin->lock); 446 INIT_LIST_HEAD(&admin->list); 447 INIT_LIST_HEAD(&admin->rules); 448 INIT_LIST_HEAD(&admin->enabled); 449 450 admin->vtype = cfg->vtype; 451 admin->vinst = 0; 452 admin->w32be = true; 453 admin->tgt_inst = cfg->tgt_inst; 454 455 admin->lookups = cfg->lookups; 456 admin->lookups_per_instance = cfg->lookups; 457 458 admin->first_cid = cfg->first_cid; 459 admin->last_cid = cfg->last_cid; 460 461 admin->cache.keystream = kzalloc(STREAMSIZE, GFP_KERNEL); 462 admin->cache.maskstream = kzalloc(STREAMSIZE, GFP_KERNEL); 463 admin->cache.actionstream = kzalloc(STREAMSIZE, GFP_KERNEL); 464 if (!admin->cache.keystream || 465 !admin->cache.maskstream || 466 !admin->cache.actionstream) { 467 lan966x_vcap_admin_free(admin); 468 return ERR_PTR(-ENOMEM); 469 } 470 471 return admin; 472 } 473 474 static void lan966x_vcap_block_init(struct lan966x *lan966x, 475 struct vcap_admin *admin, 476 struct lan966x_vcap_inst *cfg) 477 { 478 admin->first_valid_addr = 0; 479 admin->last_used_addr = cfg->count; 480 admin->last_valid_addr = cfg->count - 1; 481 482 lan_wr(VCAP_CORE_IDX_CORE_IDX_SET(0), 483 lan966x, VCAP_CORE_IDX(admin->tgt_inst)); 484 lan_wr(VCAP_CORE_MAP_CORE_MAP_SET(1), 485 lan966x, VCAP_CORE_MAP(admin->tgt_inst)); 486 487 __lan966x_vcap_range_init(lan966x, admin, admin->first_valid_addr, 488 admin->last_valid_addr - 489 admin->first_valid_addr); 490 } 491 492 static void lan966x_vcap_port_key_deselection(struct lan966x *lan966x, 493 struct vcap_admin *admin) 494 { 495 for (int p = 0; p < lan966x->num_phys_ports; ++p) 496 lan_wr(0, lan966x, ANA_VCAP_S2_CFG(p)); 497 } 498 499 int lan966x_vcap_init(struct lan966x *lan966x) 500 { 501 struct lan966x_vcap_inst *cfg; 502 struct vcap_control *ctrl; 503 struct vcap_admin *admin; 504 505 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 506 if (!ctrl) 507 return -ENOMEM; 508 509 ctrl->vcaps = lan966x_vcaps; 510 ctrl->stats = &lan966x_vcap_stats; 511 ctrl->ops = &lan966x_vcap_ops; 512 513 INIT_LIST_HEAD(&ctrl->list); 514 for (int i = 0; i < ARRAY_SIZE(lan966x_vcap_inst_cfg); ++i) { 515 cfg = &lan966x_vcap_inst_cfg[i]; 516 517 admin = lan966x_vcap_admin_alloc(lan966x, ctrl, cfg); 518 if (IS_ERR(admin)) 519 return PTR_ERR(admin); 520 521 lan966x_vcap_block_init(lan966x, admin, cfg); 522 lan966x_vcap_port_key_deselection(lan966x, admin); 523 524 list_add_tail(&admin->list, &ctrl->list); 525 } 526 527 lan966x->vcap_ctrl = ctrl; 528 529 return 0; 530 } 531 532 void lan966x_vcap_deinit(struct lan966x *lan966x) 533 { 534 struct vcap_admin *admin, *admin_next; 535 struct vcap_control *ctrl; 536 537 ctrl = lan966x->vcap_ctrl; 538 if (!ctrl) 539 return; 540 541 list_for_each_entry_safe(admin, admin_next, &ctrl->list, list) { 542 lan966x_vcap_port_key_deselection(lan966x, admin); 543 vcap_del_rules(ctrl, admin); 544 list_del(&admin->list); 545 lan966x_vcap_admin_free(admin); 546 } 547 548 kfree(ctrl); 549 } 550