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