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