1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2026 David Yang 4 */ 5 6 #include "chip.h" 7 #include "smi.h" 8 #include "tc.h" 9 10 static int yt921x_mtu_fetch(struct yt921x_priv *priv, int port) 11 { 12 struct dsa_port *dp = dsa_to_port(&priv->ds, port); 13 14 return dp->user ? READ_ONCE(dp->user->mtu) : ETH_DATA_LEN; 15 } 16 17 /* v * 2^e */ 18 static u64 ldexpu64(u64 v, int e) 19 { 20 return e >= 0 ? v << e : v >> -e; 21 } 22 23 /* slot (ns) * rate (/s) / 10^9 (ns/s) = 2^C * token * 4^unit */ 24 static u32 rate2token(u64 rate, unsigned int slot_ns, int unit, int C) 25 { 26 int e = 2 * unit + C + YT921X_TOKEN_RATE_C; 27 28 return div_u64(ldexpu64(slot_ns * rate, -e), NSEC_PER_SEC); 29 } 30 31 static u64 token2rate(u32 token, unsigned int slot_ns, int unit, int C) 32 { 33 int e = 2 * unit + C + YT921X_TOKEN_RATE_C; 34 35 return div_u64(ldexpu64(mul_u32_u32(NSEC_PER_SEC, token), e), slot_ns); 36 } 37 38 /* burst = 2^C * token * 4^unit */ 39 static u32 burst2token(u64 burst, int unit, int C) 40 { 41 return ldexpu64(burst, -(2 * unit + C)); 42 } 43 44 static u64 token2burst(u32 token, int unit, int C) 45 { 46 return ldexpu64(token, 2 * unit + C); 47 } 48 49 struct yt921x_marker { 50 u32 cir; 51 u32 cbs; 52 u32 ebs; 53 int unit; 54 bool pkt_mode; 55 }; 56 57 #define YT921X_MARKER_PKT_MODE BIT(0) 58 #define YT921X_MARKER_SINGLE_BUCKET BIT(1) 59 60 static int 61 yt921x_marker_tfm(struct yt921x_marker *marker, u64 rate, u64 burst, 62 unsigned int flags, unsigned int slot_ns, u32 cir_max, 63 u32 cbs_max, int unit_max, struct yt921x_priv *priv, int port, 64 struct netlink_ext_ack *extack) 65 { 66 const int C = flags & YT921X_MARKER_PKT_MODE ? YT921X_TOKEN_PKT_C : 67 YT921X_TOKEN_BYTE_C; 68 struct device *dev = yt921x_priv_to_device(priv); 69 struct yt921x_marker m; 70 u64 burst_est; 71 u64 burst_sug; 72 u64 burst_max; 73 u64 rate_max; 74 75 m.unit = unit_max; 76 rate_max = token2rate(cir_max, slot_ns, m.unit, C); 77 burst_max = token2burst(cbs_max, m.unit, C); 78 79 /* Check for unusual values */ 80 if (rate > rate_max || burst > burst_max) { 81 NL_SET_ERR_MSG_MOD(extack, "Unexpected tremendous rate"); 82 return -ERANGE; 83 } 84 85 /* Check for matching burst */ 86 burst_est = div_u64(slot_ns * rate, NSEC_PER_SEC); 87 burst_sug = burst_est; 88 if (flags & YT921X_MARKER_PKT_MODE) 89 burst_sug++; 90 else 91 burst_sug += ETH_HLEN + yt921x_mtu_fetch(priv, port) + 92 ETH_FCS_LEN; 93 if (burst_sug > burst) 94 NL_SET_ERR_MSG_FMT_MOD(extack, 95 "Consider match rate %llu with burst at least %llu", 96 rate, burst_sug); 97 98 /* Select unit */ 99 for (; m.unit > 0; m.unit--) { 100 if (rate > (rate_max >> 2) || burst > (burst_max >> 2)) 101 break; 102 rate_max >>= 2; 103 burst_max >>= 2; 104 } 105 106 /* Calculate information rate and bucket size */ 107 m.cir = rate2token(rate, slot_ns, m.unit, C); 108 if (!m.cir) 109 m.cir = 1; 110 else if (WARN_ON(m.cir > cir_max)) 111 m.cir = cir_max; 112 m.cbs = burst2token(burst, m.unit, C); 113 if (!m.cbs) 114 m.cbs = 1; 115 else if (WARN_ON(m.cbs > cbs_max)) 116 m.cbs = cbs_max; 117 118 /* Cut EBS */ 119 m.ebs = 0; 120 if (!(flags & YT921X_MARKER_SINGLE_BUCKET)) { 121 /* We don't have a chance to adjust rate when MTU is changed */ 122 if (flags & YT921X_MARKER_PKT_MODE) 123 burst_est++; 124 else 125 burst_est += YT921X_FRAME_SIZE_MAX; 126 127 if (burst_est < burst) { 128 u32 pbs = m.cbs; 129 130 m.cbs = burst2token(burst_est, m.unit, C); 131 if (!m.cbs) 132 m.cbs = 1; 133 else if (WARN_ON(m.cbs > cbs_max)) 134 m.cbs = cbs_max; 135 136 if (pbs > m.cbs) 137 m.ebs = pbs - m.cbs; 138 } 139 } 140 141 dev_dbg(dev, 142 "slot %u ns, rate %llu, burst %llu -> unit %d, cir %u, cbs %u, ebs %u\n", 143 slot_ns, rate, burst, m.unit, m.cir, m.cbs, m.ebs); 144 145 m.pkt_mode = flags & YT921X_MARKER_PKT_MODE; 146 *marker = m; 147 return 0; 148 } 149 150 static int 151 yt921x_marker_tfm_police(struct yt921x_marker *marker, 152 const struct flow_action_police *police, 153 unsigned int flags, struct yt921x_priv *priv, int port, 154 struct netlink_ext_ack *extack) 155 { 156 bool pkt_mode = !!police->rate_pkt_ps; 157 u64 burst; 158 u64 rate; 159 160 rate = pkt_mode ? police->rate_pkt_ps : police->rate_bytes_ps; 161 burst = pkt_mode ? police->burst_pkt : police->burst; 162 if (pkt_mode) 163 flags |= YT921X_MARKER_PKT_MODE; 164 165 return yt921x_marker_tfm(marker, rate, burst, flags, 166 priv->meter_slot_ns, YT921X_METER_CIR_MAX, 167 YT921X_METER_CBS_MAX, YT921X_METER_UNIT_MAX, 168 priv, port, extack); 169 } 170 171 static int 172 yt921x_marker_tfm_shape(struct yt921x_marker *marker, u64 rate, u64 burst, 173 unsigned int flags, struct yt921x_priv *priv, int port, 174 struct netlink_ext_ack *extack) 175 { 176 return yt921x_marker_tfm(marker, rate, burst, flags, 177 priv->port_shape_slot_ns, YT921X_SHAPE_CIR_MAX, 178 YT921X_SHAPE_CBS_MAX, YT921X_SHAPE_UNIT_MAX, 179 priv, port, extack); 180 } 181 182 static int 183 yt921x_police_validate(const struct flow_action_police *police, 184 const struct flow_action *action, 185 const struct flow_action_entry *act, 186 struct netlink_ext_ack *extack) 187 { 188 if (police->exceed.act_id != FLOW_ACTION_DROP) { 189 NL_SET_ERR_MSG_MOD(extack, 190 "Offload not supported when exceed action is not drop"); 191 return -EOPNOTSUPP; 192 } 193 194 if (police->notexceed.act_id != FLOW_ACTION_PIPE && 195 police->notexceed.act_id != FLOW_ACTION_ACCEPT) { 196 NL_SET_ERR_MSG_MOD(extack, 197 "Offload not supported when conform action is not pipe or ok"); 198 return -EOPNOTSUPP; 199 } 200 201 if (police->notexceed.act_id == FLOW_ACTION_ACCEPT && action && act && 202 !flow_action_is_last_entry(action, act)) { 203 NL_SET_ERR_MSG_MOD(extack, 204 "Offload not supported when conform action is ok, but action is not last"); 205 return -EOPNOTSUPP; 206 } 207 208 /* mtu defaults to unlimited but we got 2040 here, don't know why */ 209 if (police->peakrate_bytes_ps || police->avrate || police->overhead) { 210 NL_SET_ERR_MSG_MOD(extack, 211 "Offload not supported when peakrate/avrate/overhead is configured"); 212 return -EOPNOTSUPP; 213 } 214 215 return 0; 216 } 217 218 static int 219 yt921x_meter_config(struct yt921x_priv *priv, unsigned int id, 220 const struct yt921x_marker *marker) 221 { 222 u32 ctrls[3]; 223 224 ctrls[0] = 0; 225 ctrls[1] = YT921X_METER_CTRLb_CIR(marker->cir); 226 ctrls[2] = YT921X_METER_CTRLc_UNIT(marker->unit) | 227 YT921X_METER_CTRLc_DROP_R | 228 YT921X_METER_CTRLc_TOKEN_OVERFLOW_EN | 229 YT921X_METER_CTRLc_METER_EN; 230 if (marker->pkt_mode) 231 ctrls[2] |= YT921X_METER_CTRLc_PKT_MODE; 232 update_ctrls_unaligned(&ctrls[0], &ctrls[1], 233 YT921X_METER_CTRLab_EBS_M, 234 YT921X_METER_CTRLab_EBS(marker->ebs)); 235 update_ctrls_unaligned(&ctrls[1], &ctrls[2], 236 YT921X_METER_CTRLbc_CBS_M, 237 YT921X_METER_CTRLbc_CBS(marker->cbs)); 238 239 return yt921x_reg96_write(priv, YT921X_METERn_CTRL(id), ctrls); 240 } 241 242 void yt921x_dsa_port_policer_del(struct dsa_switch *ds, int port) 243 { 244 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 245 struct device *dev = yt921x_priv_to_device(priv); 246 int res; 247 248 mutex_lock(&priv->reg_lock); 249 res = yt921x_reg_write(priv, YT921X_PORTn_METER(port), 0); 250 mutex_unlock(&priv->reg_lock); 251 252 if (res) 253 dev_err(dev, "Failed to %s port %d: %i\n", "delete policer on", 254 port, res); 255 } 256 257 int 258 yt921x_dsa_port_policer_add(struct dsa_switch *ds, int port, 259 const struct flow_action_police *police, 260 struct netlink_ext_ack *extack) 261 { 262 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 263 struct yt921x_marker marker; 264 u32 ctrl; 265 int res; 266 267 res = yt921x_police_validate(police, NULL, NULL, extack); 268 if (res) 269 return res; 270 271 res = yt921x_marker_tfm_police(&marker, police, 0, priv, port, extack); 272 if (res) 273 return res; 274 275 mutex_lock(&priv->reg_lock); 276 res = yt921x_meter_config(priv, port + YT921X_METER_NUM, &marker); 277 if (res) 278 goto end; 279 280 ctrl = YT921X_PORT_METER_ID(port) | YT921X_PORT_METER_EN; 281 res = yt921x_reg_write(priv, YT921X_PORTn_METER(port), ctrl); 282 end: 283 mutex_unlock(&priv->reg_lock); 284 285 return res; 286 } 287 288 static int 289 yt921x_dsa_port_setup_tc_tbf_port(struct dsa_switch *ds, int port, 290 const struct tc_tbf_qopt_offload *qopt) 291 { 292 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 293 struct netlink_ext_ack *extack = qopt->extack; 294 u32 ctrls[2]; 295 int res; 296 297 if (qopt->parent != TC_H_ROOT) 298 return -EOPNOTSUPP; 299 300 switch (qopt->command) { 301 case TC_TBF_STATS: 302 /* Unfortunately the convention for TC_*_STATS is a mess, 303 * neither 0 nor -EOPNOTSUPP is perfect here. 304 */ 305 return -EOPNOTSUPP; 306 case TC_TBF_DESTROY: 307 ctrls[0] = 0; 308 ctrls[1] = 0; 309 break; 310 case TC_TBF_REPLACE: { 311 const struct tc_tbf_qopt_offload_replace_params *p; 312 struct yt921x_marker marker; 313 314 p = &qopt->replace_params; 315 316 res = yt921x_marker_tfm_shape(&marker, p->rate.rate_bytes_ps, 317 p->max_size, 318 YT921X_MARKER_SINGLE_BUCKET, 319 priv, port, extack); 320 if (res) 321 return res; 322 323 ctrls[0] = YT921X_PORT_SHAPE_CTRLa_CIR(marker.cir) | 324 YT921X_PORT_SHAPE_CTRLa_CBS(marker.cbs); 325 ctrls[1] = YT921X_PORT_SHAPE_CTRLb_UNIT(marker.unit) | 326 YT921X_PORT_SHAPE_CTRLb_EN; 327 break; 328 } 329 default: 330 return -EOPNOTSUPP; 331 } 332 333 mutex_lock(&priv->reg_lock); 334 res = yt921x_reg64_write(priv, YT921X_PORTn_SHAPE_CTRL(port), ctrls); 335 mutex_unlock(&priv->reg_lock); 336 337 return res; 338 } 339 340 int 341 yt921x_dsa_port_setup_tc(struct dsa_switch *ds, int port, 342 enum tc_setup_type type, void *type_data) 343 { 344 switch (type) { 345 case TC_SETUP_QDISC_TBF: { 346 const struct tc_tbf_qopt_offload *qopt = type_data; 347 348 return yt921x_dsa_port_setup_tc_tbf_port(ds, port, qopt); 349 } 350 default: 351 return -EOPNOTSUPP; 352 } 353 } 354 355 /* ACL: 48 blocks * 8 entries 356 * 357 * One rule can span multiple entries, but within a block. 358 */ 359 360 static void 361 yt921x_acl_entry_set(struct yt921x_acl_entry *entry, unsigned int offset, 362 u32 flags, bool set) 363 { 364 if (set) 365 entry->key[offset] |= flags; 366 entry->mask[offset] |= flags; 367 } 368 369 static unsigned int 370 yt921x_acl_entries_set_is_fragment(struct yt921x_acl_entry *entries, 371 unsigned int size, bool set) 372 { 373 for (unsigned int i = 0; i < size; i++) 374 switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) { 375 case YT921X_ACL_TYPE_IPV4_DA: 376 case YT921X_ACL_TYPE_IPV4_SA: 377 yt921x_acl_entry_set(&entries[i], 1, 378 YT921X_ACL_BINb_IPV4_FRAG, set); 379 return size; 380 case YT921X_ACL_TYPE_IPV6_DA3: 381 case YT921X_ACL_TYPE_IPV6_SA3: 382 yt921x_acl_entry_set(&entries[i], 1, 383 YT921X_ACL_BINb_IPV6_xA3_FRAG, 384 set); 385 return size; 386 case YT921X_ACL_TYPE_MISC: 387 yt921x_acl_entry_set(&entries[i], 1, 388 YT921X_ACL_BINb_MISC_FRAG, set); 389 return size; 390 case YT921X_ACL_TYPE_L4: 391 yt921x_acl_entry_set(&entries[i], 1, 392 YT921X_ACL_BINb_L4_FRAG, set); 393 return size; 394 } 395 396 if (size >= YT921X_ACL_ENT_PER_BLK) 397 return 0; 398 399 entries[size] = (typeof(*entries)){}; 400 entries[size].key[1] = YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC); 401 yt921x_acl_entry_set(&entries[size], 1, YT921X_ACL_BINb_MISC_FRAG, set); 402 403 return size + 1; 404 } 405 406 static unsigned int 407 yt921x_acl_entries_set_first_frag(struct yt921x_acl_entry *entries, 408 unsigned int size, bool set) 409 { 410 for (unsigned int i = 0; i < size; i++) 411 switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) { 412 case YT921X_ACL_TYPE_IPV6_DA2: 413 case YT921X_ACL_TYPE_IPV6_SA2: 414 yt921x_acl_entry_set(&entries[i], 1, 415 YT921X_ACL_BINb_IPV6_xA2_FIRST_FRAG, 416 set); 417 return size; 418 case YT921X_ACL_TYPE_MISC: 419 yt921x_acl_entry_set(&entries[i], 0, 420 YT921X_ACL_BINa_MISC_FIRST_FRAG, 421 set); 422 return size; 423 } 424 425 if (size >= YT921X_ACL_ENT_PER_BLK) 426 return 0; 427 428 entries[size] = (typeof(*entries)){}; 429 entries[size].key[1] = YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC); 430 yt921x_acl_entry_set(&entries[size], 0, 431 YT921X_ACL_BINa_MISC_FIRST_FRAG, set); 432 433 return size + 1; 434 } 435 436 static unsigned int 437 yt921x_acl_entries_set_l3_type(struct yt921x_acl_entry *entries, 438 unsigned int size, enum yt921x_l3_type type) 439 { 440 for (unsigned int i = 0; i < size; i++) 441 switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) { 442 case YT921X_ACL_TYPE_MAC_DA0: 443 case YT921X_ACL_TYPE_MAC_SA0: 444 entries[i].key[1] |= YT921X_ACL_BINb_MAC_xA0_L3_TYPE(type); 445 entries[i].mask[1] |= YT921X_ACL_BINb_MAC_xA0_L3_TYPE_M; 446 return size; 447 case YT921X_ACL_TYPE_MISC: 448 entries[i].key[0] |= YT921X_ACL_BINa_MISC_L3_TYPE(type); 449 entries[i].mask[0] |= YT921X_ACL_BINa_MISC_L3_TYPE_M; 450 return size; 451 } 452 453 if (size >= YT921X_ACL_ENT_PER_BLK) 454 return 0; 455 456 entries[size] = (typeof(*entries)){}; 457 entries[size].key[0] = YT921X_ACL_BINa_MISC_L3_TYPE(type); 458 entries[size].key[1] = YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC); 459 entries[size].mask[0] = YT921X_ACL_BINa_MISC_L3_TYPE_M; 460 461 return size + 1; 462 } 463 464 static unsigned int 465 yt921x_acl_entries_set_l4_type(struct yt921x_acl_entry *entries, 466 unsigned int size, enum yt921x_l4_type type) 467 { 468 for (unsigned int i = 0; i < size; i++) 469 switch (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1])) { 470 case YT921X_ACL_TYPE_IPV4_DA: 471 case YT921X_ACL_TYPE_IPV4_SA: 472 entries[i].key[1] |= YT921X_ACL_BINb_IPV4_L4_TYPE(type); 473 entries[i].mask[1] |= YT921X_ACL_BINb_IPV4_L4_TYPE_M; 474 return size; 475 case YT921X_ACL_TYPE_IPV6_DA0: 476 case YT921X_ACL_TYPE_IPV6_DA1: 477 case YT921X_ACL_TYPE_IPV6_DA2: 478 case YT921X_ACL_TYPE_IPV6_DA3: 479 case YT921X_ACL_TYPE_IPV6_SA0: 480 case YT921X_ACL_TYPE_IPV6_SA1: 481 case YT921X_ACL_TYPE_IPV6_SA2: 482 case YT921X_ACL_TYPE_IPV6_SA3: 483 entries[i].key[1] |= YT921X_ACL_BINb_IPV6_L4_TYPE(type); 484 entries[i].mask[1] |= YT921X_ACL_BINb_IPV6_L4_TYPE_M; 485 return size; 486 case YT921X_ACL_TYPE_L4: 487 entries[i].key[1] |= YT921X_ACL_BINb_L4_TYPE(type); 488 entries[i].mask[1] |= YT921X_ACL_BINb_L4_TYPE_M; 489 return size; 490 case YT921X_ACL_TYPE_MISC: 491 entries[i].key[1] |= YT921X_ACL_BINb_MISC_L4_TYPE(type); 492 entries[i].mask[1] |= YT921X_ACL_BINb_MISC_L4_TYPE_M; 493 return size; 494 } 495 496 if (size >= YT921X_ACL_ENT_PER_BLK) 497 return 0; 498 499 entries[size] = (typeof(*entries)){}; 500 entries[size].key[1] = YT921X_ACL_BINb_MISC_L4_TYPE(type) | 501 YT921X_ACL_KEYb_TYPE(YT921X_ACL_TYPE_MISC); 502 entries[size].mask[1] = YT921X_ACL_BINb_MISC_L4_TYPE_M; 503 504 return size + 1; 505 } 506 507 static struct yt921x_acl_entry * 508 yt921x_acl_entries_new(struct yt921x_acl_entry *entries, unsigned int *sizep, 509 u32 type) 510 { 511 unsigned int size = *sizep; 512 513 if (size >= YT921X_ACL_ENT_PER_BLK) 514 return NULL; 515 516 entries[size] = (typeof(*entries)){}; 517 entries[size].key[1] = YT921X_ACL_KEYb_TYPE(type); 518 519 (*sizep)++; 520 return &entries[size]; 521 } 522 523 static struct yt921x_acl_entry * 524 yt921x_acl_entries_find(struct yt921x_acl_entry *entries, unsigned int *sizep, 525 u32 type) 526 { 527 for (unsigned int i = 0; i < *sizep; i++) 528 if (FIELD_GET(YT921X_ACL_KEYb_TYPE_M, entries[i].key[1]) == 529 type) 530 return &entries[i]; 531 return yt921x_acl_entries_new(entries, sizep, type); 532 } 533 534 static void 535 yt921x_acl_rule_set_ports(struct yt921x_acl_rule *aclrule, u16 ord, 536 u16 ports_mask) 537 { 538 struct yt921x_acl_entry *entries = aclrule->entries; 539 540 for (unsigned int i = 0; i < hweight8(aclrule->mask); i++) { 541 entries[i].key[1] |= YT921X_ACL_KEYb_SPORTS(ports_mask) | 542 YT921X_ACL_KEYb_ORD(ord); 543 } 544 } 545 546 struct yt921x_udf_entry { 547 unsigned char type; 548 unsigned char offset; 549 u8 key; 550 u8 mask; 551 }; 552 553 struct yt921x_udf_map { 554 unsigned char type; 555 unsigned char offset; 556 }; 557 558 /* UDF windows are preselected - that's enough for now. */ 559 static struct yt921x_udf_map yt921x_udf_maps[] = { 560 {YT921X_UDF_TYPE_L3, 7}, 561 {YT921X_UDF_TYPE_L4, 0}, 562 }; 563 564 struct yt921x_acl_rule_ext { 565 struct yt921x_acl_rule r; 566 567 struct yt921x_marker marker; 568 }; 569 570 static int 571 yt921x_acl_rule_ext_parse_flow_entries(struct yt921x_acl_rule_ext *ruleext, 572 const struct flow_cls_offload *cls) 573 { 574 const struct flow_rule *rule = flow_cls_offload_flow_rule(cls); 575 struct yt921x_acl_entry *entries = ruleext->r.entries; 576 struct netlink_ext_ack *extack = cls->common.extack; 577 struct yt921x_udf_entry udfs[YT921X_UDF_NUM]; 578 const struct flow_dissector *dissector; 579 struct yt921x_acl_entry *entry; 580 unsigned int udfs_cnt = 0; 581 unsigned int size = 0; 582 __be16 n_proto = 0; 583 u8 ip_proto = 0; 584 bool use_dport; 585 bool use_sport; 586 587 /* Incomplete and probably won't, since it supports custom u32 filters. 588 * New adapters are welcome. 589 */ 590 dissector = rule->match.dissector; 591 if (dissector->used_keys & 592 ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) | 593 BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) | 594 BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) | 595 BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) | 596 BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) | 597 BIT_ULL(FLOW_DISSECTOR_KEY_PORTS_RANGE) | 598 BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) | 599 BIT_ULL(FLOW_DISSECTOR_KEY_IP) | 600 BIT_ULL(FLOW_DISSECTOR_KEY_TCP) | 601 BIT_ULL(FLOW_DISSECTOR_KEY_ICMP))) { 602 NL_SET_ERR_MSG_MOD(extack, "Unsupported keys used"); 603 return -EOPNOTSUPP; 604 } 605 606 /* Entries */ 607 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) { 608 struct flow_match_ipv4_addrs match; 609 610 flow_rule_match_ipv4_addrs(rule, &match); 611 612 if (match.mask->dst) { 613 entry = yt921x_acl_entries_new(entries, &size, 614 YT921X_ACL_TYPE_IPV4_DA); 615 if (!entry) 616 goto err; 617 618 entry->key[0] |= ntohl(match.key->dst); 619 entry->mask[0] |= ntohl(match.mask->dst); 620 } 621 622 if (match.mask->src) { 623 entry = yt921x_acl_entries_new(entries, &size, 624 YT921X_ACL_TYPE_IPV4_SA); 625 if (!entry) 626 goto err; 627 628 entry->key[0] |= ntohl(match.key->src); 629 entry->mask[0] |= ntohl(match.mask->src); 630 } 631 } 632 633 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS)) { 634 struct flow_match_ipv6_addrs match; 635 636 flow_rule_match_ipv6_addrs(rule, &match); 637 638 for (unsigned int i = 0; i < 4; i++) { 639 if (!match.mask->dst.s6_addr32[i]) 640 continue; 641 642 entry = yt921x_acl_entries_new(entries, &size, 643 YT921X_ACL_TYPE_IPV6_DA0 + i); 644 if (!entry) 645 goto err; 646 647 entry->key[0] |= ntohl(match.key->dst.s6_addr32[i]); 648 entry->mask[0] |= ntohl(match.mask->dst.s6_addr32[i]); 649 } 650 651 for (unsigned int i = 0; i < 4; i++) { 652 if (!match.mask->src.s6_addr32[i]) 653 continue; 654 655 entry = yt921x_acl_entries_new(entries, &size, 656 YT921X_ACL_TYPE_IPV6_SA0 + i); 657 if (!entry) 658 goto err; 659 660 entry->key[0] |= ntohl(match.key->src.s6_addr32[i]); 661 entry->mask[0] |= ntohl(match.mask->src.s6_addr32[i]); 662 } 663 } 664 665 use_dport = false; 666 use_sport = false; 667 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) { 668 struct flow_match_ports match; 669 670 entry = yt921x_acl_entries_new(entries, &size, 671 YT921X_ACL_TYPE_L4); 672 if (!entry) 673 goto err; 674 675 flow_rule_match_ports(rule, &match); 676 677 use_dport = !!match.mask->dst; 678 use_sport = !!match.mask->src; 679 680 entry->key[0] |= (ntohs(match.key->dst) << 16) | 681 ntohs(match.key->src); 682 entry->mask[0] |= (ntohs(match.mask->dst) << 16) | 683 ntohs(match.mask->src); 684 } 685 686 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS_RANGE)) { 687 struct flow_match_ports_range match; 688 689 entry = yt921x_acl_entries_find(entries, &size, 690 YT921X_ACL_TYPE_L4); 691 if (!entry) 692 goto err; 693 694 flow_rule_match_ports_range(rule, &match); 695 696 if ((use_dport && match.mask->tp.dst) || 697 (use_sport && match.mask->tp.src)) { 698 NL_SET_ERR_MSG_MOD(extack, 699 "Port mask and range are mutually exclusive"); 700 return -EINVAL; 701 } 702 703 if (match.mask->tp.dst) { 704 entry->key[0] |= ntohs(match.key->tp_min.dst) << 16; 705 entry->key[1] |= YT921X_ACL_KEYb_L4_DPORT_RANGE_EN; 706 entry->mask[0] |= ntohs(match.key->tp_max.dst) << 16; 707 } 708 709 if (match.mask->tp.src) { 710 entry->key[0] |= ntohs(match.key->tp_min.src); 711 entry->key[1] |= YT921X_ACL_KEYb_L4_SPORT_RANGE_EN; 712 entry->mask[0] |= ntohs(match.key->tp_max.src); 713 } 714 } 715 716 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { 717 struct flow_match_eth_addrs match; 718 u32 mask; 719 720 flow_rule_match_eth_addrs(rule, &match); 721 722 mask = ethaddr_hi4_to_u32(match.mask->dst); 723 if (mask) { 724 entry = yt921x_acl_entries_new(entries, &size, 725 YT921X_ACL_TYPE_MAC_DA0); 726 if (!entry) 727 goto err; 728 729 entry->key[0] |= ethaddr_hi4_to_u32(match.key->dst); 730 entry->mask[0] |= mask; 731 } 732 733 mask = ethaddr_hi4_to_u32(match.mask->src); 734 if (mask) { 735 entry = yt921x_acl_entries_new(entries, &size, 736 YT921X_ACL_TYPE_MAC_SA0); 737 if (!entry) 738 goto err; 739 740 entry->key[0] |= ethaddr_hi4_to_u32(match.key->src); 741 entry->mask[0] |= mask; 742 } 743 744 mask = (ethaddr_lo2_to_u32(match.mask->dst) << 16) | 745 ethaddr_lo2_to_u32(match.mask->src); 746 if (mask) { 747 entry = yt921x_acl_entries_new(entries, &size, 748 YT921X_ACL_TYPE_MAC_DA1_SA1); 749 if (!entry) 750 goto err; 751 752 entry->key[0] |= (ethaddr_lo2_to_u32(match.key->dst) << 16) | 753 ethaddr_lo2_to_u32(match.key->src); 754 entry->mask[0] |= mask; 755 } 756 } 757 758 /* Entries + Misc */ 759 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) { 760 struct flow_match_basic match; 761 762 flow_rule_match_basic(rule, &match); 763 764 if (match.mask->n_proto) { 765 enum yt921x_l3_type l3type = YT921X_L3_TYPE_OTHER; 766 767 if (match.mask->n_proto == htons(~0)) { 768 n_proto = match.key->n_proto; 769 770 switch (match.key->n_proto) { 771 case htons(ETH_P_IP): 772 l3type = YT921X_L3_TYPE_IPV4; 773 break; 774 case htons(ETH_P_IPV6): 775 l3type = YT921X_L3_TYPE_IPV6; 776 break; 777 case htons(ETH_P_ARP): 778 l3type = YT921X_L3_TYPE_ARP; 779 break; 780 case htons(ETH_P_LLDP): 781 l3type = YT921X_L3_TYPE_LLDP; 782 break; 783 case htons(ETH_P_PAE): 784 l3type = YT921X_L3_TYPE_PAE; 785 break; 786 case htons(ETH_P_CFM): 787 l3type = YT921X_L3_TYPE_ERP; 788 break; 789 } 790 } 791 792 if (l3type != YT921X_L3_TYPE_OTHER) { 793 size = yt921x_acl_entries_set_l3_type(entries, 794 size, 795 l3type); 796 if (!size) 797 goto err; 798 } else { 799 entry = yt921x_acl_entries_new(entries, &size, 800 YT921X_ACL_TYPE_ETHERTYPE); 801 if (!entry) 802 goto err; 803 804 entry->key[0] |= ntohs(match.key->n_proto); 805 entry->mask[0] |= ntohs(match.mask->n_proto); 806 } 807 } 808 809 if (match.mask->ip_proto) { 810 enum yt921x_l4_type l4type = YT921X_L4_TYPE_OTHER; 811 812 if (match.mask->ip_proto == (u8)~0) { 813 ip_proto = match.key->ip_proto; 814 815 switch (match.key->ip_proto) { 816 case IPPROTO_TCP: 817 l4type = YT921X_L4_TYPE_TCP; 818 break; 819 case IPPROTO_UDP: 820 l4type = YT921X_L4_TYPE_UDP; 821 break; 822 case IPPROTO_UDPLITE: 823 l4type = YT921X_L4_TYPE_UDPLITE; 824 break; 825 case IPPROTO_ICMP: 826 l4type = YT921X_L4_TYPE_ICMP; 827 break; 828 case IPPROTO_IGMP: 829 l4type = YT921X_L4_TYPE_IGMP; 830 break; 831 } 832 } 833 834 if (l4type != YT921X_L4_TYPE_OTHER) { 835 size = yt921x_acl_entries_set_l4_type(entries, 836 size, 837 l4type); 838 if (!size) 839 goto err; 840 } else { 841 entry = yt921x_acl_entries_find(entries, &size, 842 YT921X_ACL_TYPE_MISC); 843 if (!entry) 844 goto err; 845 846 entry->key[0] |= YT921X_ACL_BINa_MISC_IP_PROTO(match.key->ip_proto); 847 entry->mask[0] |= YT921X_ACL_BINa_MISC_IP_PROTO(match.mask->ip_proto); 848 } 849 } 850 } 851 852 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { 853 u32 supp_flags = FLOW_DIS_IS_FRAGMENT | FLOW_DIS_FIRST_FRAG; 854 struct flow_match_control match; 855 856 flow_rule_match_control(rule, &match); 857 if (!flow_rule_is_supp_control_flags(supp_flags, 858 match.mask->flags, extack)) 859 return -EOPNOTSUPP; 860 861 if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) { 862 bool set = match.key->flags & FLOW_DIS_IS_FRAGMENT; 863 864 size = yt921x_acl_entries_set_is_fragment(entries, size, 865 set); 866 if (!size) 867 goto err; 868 } 869 if (match.mask->flags & FLOW_DIS_FIRST_FRAG) { 870 bool set = match.key->flags & FLOW_DIS_FIRST_FRAG; 871 872 size = yt921x_acl_entries_set_first_frag(entries, size, 873 set); 874 if (!size) 875 goto err; 876 } 877 } 878 879 /* Misc only */ 880 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) { 881 struct flow_match_ip match; 882 883 flow_rule_match_ip(rule, &match); 884 885 if (match.mask->ttl) { 886 if (n_proto != htons(ETH_P_IP) && 887 n_proto != htons(ETH_P_IPV6)) { 888 NL_SET_ERR_MSG_MOD(extack, 889 "Matching on TTL requires protocol ip or ipv6"); 890 return -EOPNOTSUPP; 891 } 892 893 if (udfs_cnt >= YT921X_UDF_NUM) 894 goto err; 895 896 udfs[udfs_cnt] = (struct yt921x_udf_entry){ 897 .type = YT921X_UDF_TYPE_L3, 898 .offset = n_proto == htons(ETH_P_IP) ? 8 : 7, 899 .key = match.key->ttl, 900 .mask = match.mask->ttl, 901 }; 902 udfs_cnt++; 903 } 904 905 if (match.mask->tos) { 906 entry = yt921x_acl_entries_find(entries, &size, 907 YT921X_ACL_TYPE_MISC); 908 if (!entry) 909 goto err; 910 911 entry->key[0] |= YT921X_ACL_BINa_MISC_TOS(match.key->tos); 912 entry->mask[0] |= YT921X_ACL_BINa_MISC_TOS(match.mask->tos); 913 } 914 } 915 916 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_TCP)) { 917 struct flow_match_tcp match; 918 919 flow_rule_match_tcp(rule, &match); 920 if (match.mask->flags & htons(~0xff)) { 921 NL_SET_ERR_MSG_MOD(extack, "Unsupported TCP flags"); 922 return -EOPNOTSUPP; 923 } 924 925 if (match.mask->flags) { 926 entry = yt921x_acl_entries_find(entries, &size, 927 YT921X_ACL_TYPE_MISC); 928 if (!entry) 929 goto err; 930 931 entry->key[0] |= YT921X_ACL_BINa_MISC_TCP_FLAGS(ntohs(match.key->flags)); 932 entry->mask[0] |= YT921X_ACL_BINa_MISC_TCP_FLAGS(ntohs(match.mask->flags)); 933 } 934 } 935 936 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ICMP)) { 937 struct flow_match_icmp match; 938 939 flow_rule_match_icmp(rule, &match); 940 941 if (match.mask->type || match.mask->code) { 942 if (ip_proto != IPPROTO_ICMP && 943 ip_proto != IPPROTO_ICMPV6) { 944 NL_SET_ERR_MSG_MOD(extack, 945 "Matching on ICMP type/code requires ip_proto icmp or icmpv6"); 946 return -EOPNOTSUPP; 947 } 948 949 if (match.mask->type) { 950 if (udfs_cnt >= YT921X_UDF_NUM) 951 goto err; 952 953 udfs[udfs_cnt] = (struct yt921x_udf_entry){ 954 .type = YT921X_UDF_TYPE_L4, 955 .offset = 0, 956 .key = match.key->type, 957 .mask = match.mask->type, 958 }; 959 udfs_cnt++; 960 } 961 962 if (match.mask->code) { 963 if (udfs_cnt >= YT921X_UDF_NUM) 964 goto err; 965 966 udfs[udfs_cnt] = (struct yt921x_udf_entry){ 967 .type = YT921X_UDF_TYPE_L4, 968 .offset = 1, 969 .key = match.key->code, 970 .mask = match.mask->code, 971 }; 972 udfs_cnt++; 973 } 974 } 975 } 976 977 /* Compile UDFs */ 978 for (unsigned int i = 0; i < udfs_cnt; i++) { 979 unsigned int o; 980 u32 mask; 981 u32 key; 982 983 for (o = 0; o < ARRAY_SIZE(yt921x_udf_maps); o++) 984 if (udfs[i].type == yt921x_udf_maps[o].type && 985 (udfs[i].offset == yt921x_udf_maps[o].offset || 986 udfs[i].offset == yt921x_udf_maps[o].offset + 1)) 987 break; 988 989 if (WARN_ON(o == ARRAY_SIZE(yt921x_udf_maps))) 990 return -EOPNOTSUPP; 991 992 entry = yt921x_acl_entries_find(entries, &size, 993 YT921X_ACL_TYPE_UDF0 + o / 2); 994 if (!entry) 995 goto err; 996 997 key = udfs[i].key; 998 mask = udfs[i].mask; 999 if (udfs[i].offset == yt921x_udf_maps[o].offset) { 1000 key <<= 8; 1001 mask <<= 8; 1002 } 1003 if (!(o % 2)) { 1004 key <<= 16; 1005 mask <<= 16; 1006 } 1007 1008 entry->key[0] |= key; 1009 entry->mask[0] |= mask; 1010 } 1011 1012 if (!size) { 1013 NL_SET_ERR_MSG_MOD(extack, "Empty rule generated, this should not happen"); 1014 return -EOPNOTSUPP; 1015 } 1016 1017 ruleext->r.mask = (1 << size) - 1; 1018 return 0; 1019 1020 err: 1021 NL_SET_ERR_MSG_MOD(extack, "Rule too complex"); 1022 return -EOPNOTSUPP; 1023 } 1024 1025 static int 1026 yt921x_acl_rule_ext_parse_flow_action(struct yt921x_acl_rule_ext *ruleext, 1027 const struct flow_cls_offload *cls, 1028 struct yt921x_priv *priv, int port) 1029 { 1030 const struct flow_rule *rule = flow_cls_offload_flow_rule(cls); 1031 const struct flow_action *flow_action = &rule->action; 1032 struct netlink_ext_ack *extack = cls->common.extack; 1033 enum flow_action_id redir_act = NUM_FLOW_ACTIONS; 1034 const struct flow_action_entry *act; 1035 u32 *action = ruleext->r.action; 1036 bool seen_priority = false; 1037 const char *reason = NULL; 1038 bool seen_police = false; 1039 unsigned int i; 1040 int res; 1041 1042 memset(action, 0, 3 * sizeof(*action)); 1043 flow_action_for_each(i, act, flow_action) 1044 switch (act->id) { 1045 case FLOW_ACTION_ACCEPT: 1046 case FLOW_ACTION_DROP: 1047 case FLOW_ACTION_REDIRECT: 1048 if (redir_act != NUM_FLOW_ACTIONS && 1049 redir_act != act->id) { 1050 reason = "Different redirect actions"; 1051 goto fallback; 1052 } 1053 redir_act = act->id; 1054 1055 switch (act->id) { 1056 case FLOW_ACTION_ACCEPT: 1057 action[2] |= YT921X_ACL_ACTc_FWD_EN | 1058 YT921X_ACL_ACTc_FWD_FWD; 1059 break; 1060 case FLOW_ACTION_DROP: 1061 action[2] |= YT921X_ACL_ACTc_FWD_EN | 1062 YT921X_ACL_ACTc_FWD_REDIR; 1063 break; 1064 case FLOW_ACTION_REDIRECT: { 1065 struct dsa_port *to_dp; 1066 1067 to_dp = dsa_port_from_netdev(act->dev); 1068 if (IS_ERR(to_dp) || to_dp->ds != &priv->ds) { 1069 reason = "Redirect to non-local port"; 1070 goto fallback; 1071 } 1072 1073 action[2] |= YT921X_ACL_ACTc_FWD_EN | 1074 YT921X_ACL_ACTc_FWD_REDIR | 1075 YT921X_ACL_ACTc_FWD_REDIR_DPORTn(to_dp->index); 1076 break; 1077 } 1078 default: 1079 break; 1080 } 1081 break; 1082 case FLOW_ACTION_PRIORITY: 1083 if (seen_priority) { 1084 action[0] &= ~YT921X_ACL_ACTa_PRIO_EN; 1085 action[1] &= ~YT921X_ACL_ACTb_PRIO_M; 1086 1087 reason = "Multiple priority actions"; 1088 goto fallback; 1089 } 1090 seen_priority = true; 1091 1092 if (act->priority >= YT921X_PRIO_NUM) { 1093 NL_SET_ERR_MSG_MOD(extack, 1094 "Priority value is too high"); 1095 return -EOPNOTSUPP; 1096 } 1097 action[0] |= YT921X_ACL_ACTa_PRIO_EN; 1098 action[1] |= YT921X_ACL_ACTb_PRIO(act->priority); 1099 break; 1100 case FLOW_ACTION_POLICE: { 1101 const struct flow_action_police *police = &act->police; 1102 1103 if (seen_police) { 1104 action[0] &= ~YT921X_ACL_ACTa_METER_EN; 1105 1106 reason = "Multiple police actions"; 1107 goto fallback; 1108 } 1109 seen_police = true; 1110 1111 res = yt921x_police_validate(police, flow_action, act, 1112 extack); 1113 if (res) 1114 return res; 1115 1116 res = yt921x_marker_tfm_police(&ruleext->marker, police, 1117 0, priv, port, extack); 1118 if (res) 1119 return res; 1120 1121 action[0] |= YT921X_ACL_ACTa_METER_EN; 1122 break; 1123 } 1124 default: 1125 fallback: 1126 if (cls->common.skip_sw) { 1127 NL_SET_ERR_MSG_FMT_MOD(extack, 1128 "Action not supported when skip_sw: %s", 1129 reason); 1130 return -EOPNOTSUPP; 1131 } 1132 fallthrough; 1133 case FLOW_ACTION_TRAP: 1134 redir_act = FLOW_ACTION_TRAP; 1135 1136 action[2] &= ~YT921X_ACL_ACTc_FWD_REDIR_DPORTS_M & 1137 ~YT921X_ACL_ACTc_FWD_M; 1138 action[2] |= YT921X_ACL_ACTc_FWD_EN | 1139 YT921X_ACL_ACTc_FWD_TRAP; 1140 break; 1141 } 1142 1143 ruleext->r.sw_assisted = !cls->common.skip_sw; 1144 return 0; 1145 } 1146 1147 static int 1148 yt921x_acl_rule_ext_parse_flow(struct yt921x_acl_rule_ext *ruleext, int port, 1149 const struct flow_cls_offload *cls, bool ingress, 1150 struct yt921x_priv *priv) 1151 { 1152 const unsigned int scale = (U16_MAX + 1) / YT921X_ACL_ORD_NUM; 1153 struct netlink_ext_ack *extack = cls->common.extack; 1154 u32 prio = cls->common.prio; 1155 u32 ord; 1156 int res; 1157 1158 if (!ingress) { 1159 NL_SET_ERR_MSG_MOD(extack, "Only ingress is supported"); 1160 return -EOPNOTSUPP; 1161 } 1162 1163 if (cls->common.chain_index) { 1164 NL_SET_ERR_MSG(extack, "Only chain 0 is supported"); 1165 return -EOPNOTSUPP; 1166 } 1167 1168 /* Lower TC priorities take precedence, while larger orders win in 1169 * hardware. Spread the 512 hardware orders over the TC priority range 1170 * as evenly as possible, retaining the relative order: 1171 * 1172 * prio 65535 -> ORD 0 catchall filter 1173 * prio 65408 -> ORD 1 highest mappable TC priority 1174 * ... 1175 * prio 49152 -> ORD 128 default value for the first tc flower rule 1176 * ... 1177 * prio 128 -> ORD 511 1178 * prio 0 (invalid TC priority) 1179 * 1180 * The catchall filter always comes with priority 65535; pin it to ORD 1181 * 0, the lowest hardware order, instead of rejecting it. 1182 * 1183 * Prefer explicit rejects over implicit behaviour changes: reject 1184 * the priorities which do not map onto a hardware order instead of 1185 * silently colliding with a neighbouring one. 1186 */ 1187 if (prio == U16_MAX) { 1188 ord = 0; 1189 } else if (!(prio % scale)) { 1190 ord = YT921X_ACL_ORD_NUM - prio / scale; 1191 } else { 1192 NL_SET_ERR_MSG_FMT_MOD(extack, 1193 "Invalid priority %u, must be a multiple of %u or 65535", 1194 prio, scale); 1195 return -EOPNOTSUPP; 1196 } 1197 1198 res = yt921x_acl_rule_ext_parse_flow_action(ruleext, cls, priv, port); 1199 if (res) 1200 return res; 1201 res = yt921x_acl_rule_ext_parse_flow_entries(ruleext, cls); 1202 if (res) 1203 return res; 1204 1205 yt921x_acl_rule_set_ports(&ruleext->r, ord, BIT(port)); 1206 ruleext->r.tag = cls->cookie; 1207 ruleext->r.type = TC_SETUP_CLSFLOWER; 1208 return 0; 1209 } 1210 1211 /* Ports that _should_ have ACL activated on. ACL_PORT \succeq activated_ports() 1212 */ 1213 static u16 yt921x_acl_activated_ports(const struct yt921x_priv *priv) 1214 { 1215 u16 mask = 0; 1216 1217 for (int port = 0; port < YT921X_PORT_NUM; port++) 1218 if (priv->ports[port].acl_cnt) 1219 mask |= BIT(port); 1220 1221 return mask; 1222 } 1223 1224 static unsigned int 1225 yt921x_acl_find(const struct yt921x_priv *priv, enum tc_setup_type type, 1226 unsigned long tag) 1227 { 1228 for (unsigned int blkid = 0; blkid < YT921X_ACL_BLK_NUM; blkid++) { 1229 const struct yt921x_acl_blk *aclblk = priv->acl_blks[blkid]; 1230 1231 if (!aclblk) 1232 continue; 1233 1234 for (unsigned int i = 0; i < YT921X_ACL_ENT_PER_BLK; i++) 1235 if (aclblk->rules[i] && aclblk->rules[i]->tag == tag && 1236 aclblk->rules[i]->type == type) 1237 return YT921X_ACL_ENT_PER_BLK * blkid + i; 1238 } 1239 1240 return UINT_MAX; 1241 } 1242 1243 static unsigned int 1244 yt921x_acl_reserve(struct yt921x_priv *priv, unsigned int entscnt, 1245 struct netlink_ext_ack *extack) 1246 { 1247 int candidates[YT921X_ACL_ENT_PER_BLK + 1]; 1248 unsigned int acl_used_cnt = 0; 1249 1250 if (WARN_ON(entscnt > YT921X_ACL_ENT_PER_BLK)) 1251 return UINT_MAX; 1252 1253 for (unsigned int i = 0; i < ARRAY_SIZE(candidates); i++) 1254 candidates[i] = -1; 1255 for (unsigned int i = YT921X_ACL_BLK_NUM; i-- > 0;) { 1256 unsigned int blk_used_cnt = hweight8(priv->acl_masks[i]); 1257 1258 candidates[blk_used_cnt] = i; 1259 acl_used_cnt += blk_used_cnt; 1260 } 1261 1262 if (acl_used_cnt >= YT921X_ACL_NUM) { 1263 NL_SET_ERR_MSG_MOD(extack, "ACL entry limit reached"); 1264 return UINT_MAX; 1265 } 1266 if (acl_used_cnt + entscnt <= YT921X_ACL_NUM) 1267 for (unsigned int i = YT921X_ACL_ENT_PER_BLK - entscnt + 1; 1268 i-- > 0;) 1269 if (candidates[i] >= 0) 1270 return YT921X_ACL_ENT_PER_BLK * candidates[i] + 1271 ffz(priv->acl_masks[candidates[i]]); 1272 1273 NL_SET_ERR_MSG_MOD(extack, 1274 "ACL entry allocation failed, simplify your rules or remove existing rules"); 1275 return UINT_MAX; 1276 } 1277 1278 static int 1279 yt921x_acl_commit(struct yt921x_priv *priv, unsigned int entid, u8 entsmask) 1280 { 1281 const struct yt921x_acl_rule *aclrule; 1282 const struct yt921x_acl_blk *aclblk; 1283 unsigned int blkid; 1284 unsigned int binid; 1285 unsigned long mask; 1286 u32 zeros[3] = {}; 1287 unsigned int i; 1288 unsigned int o; 1289 u32 ctrl; 1290 int res; 1291 1292 blkid = entid / YT921X_ACL_ENT_PER_BLK; 1293 binid = entid % YT921X_ACL_ENT_PER_BLK; 1294 aclblk = priv->acl_blks[blkid]; 1295 aclrule = aclblk->rules[binid]; 1296 1297 /* Write actions */ 1298 res = yt921x_reg96_write(priv, YT921X_ACLn_ACT(entid), 1299 aclrule ? aclrule->action : zeros); 1300 if (res) 1301 return res; 1302 1303 /* Select the block */ 1304 ctrl = YT921X_ACL_BLK_CMD_MODIFY | YT921X_ACL_BLK_CMD_BLKID(blkid); 1305 res = yt921x_reg_write(priv, YT921X_ACL_BLK_CMD, ctrl); 1306 if (res) 1307 return res; 1308 1309 /* Write keys and masks */ 1310 ctrl = 0; 1311 for (unsigned int i = 0; i < YT921X_ACL_ENT_PER_BLK; i++) 1312 ctrl |= YT921X_ACL_BLK_KEEP_KEEPn(i); 1313 1314 mask = entsmask; 1315 i = 0; 1316 for_each_set_bit(o, &mask, YT921X_ACL_ENT_PER_BLK) { 1317 res = yt921x_reg64_write(priv, YT921X_ACLn_KEYm(blkid, o), 1318 aclrule ? aclrule->entries[i].key : 1319 zeros); 1320 if (res) 1321 return res; 1322 1323 res = yt921x_reg64_write(priv, YT921X_ACLn_MASKm(blkid, o), 1324 aclrule ? aclrule->entries[i].mask : 1325 zeros); 1326 if (res) 1327 return res; 1328 1329 ctrl &= ~YT921X_ACL_BLK_KEEP_KEEPn(o); 1330 i++; 1331 } 1332 1333 res = yt921x_reg_write(priv, YT921X_ACL_BLK_KEEP, ctrl); 1334 if (res) 1335 return res; 1336 1337 ctrl = 0; 1338 for (unsigned int i = 0; i < YT921X_ACL_ENT_PER_BLK; i++) { 1339 const struct yt921x_acl_rule *other = aclblk->rules[i]; 1340 1341 if (!other) 1342 continue; 1343 1344 mask = other->mask; 1345 for_each_set_bit(o, &mask, YT921X_ACL_ENT_PER_BLK) 1346 ctrl |= YT921X_ACL_ENTRY_ENm(o) | 1347 YT921X_ACL_ENTRY_GRPIDm(o, i); 1348 } 1349 res = yt921x_reg_write(priv, YT921X_ACLn_ENTRY(blkid), ctrl); 1350 if (res) 1351 return res; 1352 1353 /* Commit the block */ 1354 ctrl = YT921X_ACL_BLK_CMD_BLKID(blkid); 1355 res = yt921x_reg_write(priv, YT921X_ACL_BLK_CMD, ctrl); 1356 if (res) 1357 return res; 1358 1359 return 0; 1360 } 1361 1362 static int 1363 yt921x_acl_del(struct yt921x_priv *priv, enum tc_setup_type type, 1364 unsigned long tag) 1365 { 1366 struct yt921x_acl_rule *aclrule; 1367 struct yt921x_acl_blk *aclblk; 1368 bool refresh_en = false; 1369 unsigned int binid; 1370 unsigned int blkid; 1371 unsigned int entid; 1372 unsigned long m; 1373 unsigned int o; 1374 u32 ctrl; 1375 int res; 1376 int ret; 1377 1378 entid = yt921x_acl_find(priv, type, tag); 1379 if (entid == UINT_MAX) 1380 return -ENOENT; 1381 1382 blkid = entid / YT921X_ACL_ENT_PER_BLK; 1383 binid = entid % YT921X_ACL_ENT_PER_BLK; 1384 aclblk = priv->acl_blks[blkid]; 1385 aclrule = aclblk->rules[binid]; 1386 1387 aclblk->rules[binid] = NULL; 1388 ret = yt921x_acl_commit(priv, entid, aclrule->mask); 1389 /* the kernel never rolls back on failure */ 1390 1391 m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, aclrule->entries[0].key[1]); 1392 for_each_set_bit(o, &m, YT921X_PORT_NUM) { 1393 struct yt921x_port *pp = &priv->ports[o]; 1394 1395 if (!WARN_ON(!pp->acl_cnt)) { 1396 pp->acl_cnt--; 1397 if (pp->acl_cnt) 1398 continue; 1399 } 1400 refresh_en = true; 1401 } 1402 if (refresh_en) { 1403 ctrl = yt921x_acl_activated_ports(priv); 1404 res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl); 1405 if (res) 1406 ret = res; 1407 } 1408 1409 if (aclrule->action[0] & YT921X_ACL_ACTa_METER_EN) 1410 clear_bit(FIELD_GET(YT921X_ACL_ACTa_METER_ID_M, 1411 aclrule->action[0]), 1412 priv->meters_map); 1413 priv->acl_masks[blkid] &= ~aclrule->mask; 1414 kvfree(aclrule); 1415 if (!priv->acl_masks[blkid]) { 1416 kvfree(aclblk); 1417 priv->acl_blks[blkid] = NULL; 1418 } 1419 return ret; 1420 } 1421 1422 static int 1423 yt921x_acl_add(struct yt921x_priv *priv, 1424 const struct yt921x_acl_rule_ext *ruleext, 1425 struct netlink_ext_ack *extack) 1426 { 1427 unsigned int entscnt = hweight8(ruleext->r.mask); 1428 struct yt921x_acl_rule *aclrule; 1429 struct yt921x_acl_blk *aclblk; 1430 bool use_trap = false; 1431 unsigned int meterid; 1432 unsigned int binid; 1433 unsigned int blkid; 1434 unsigned int entid; 1435 unsigned long m; 1436 unsigned int o; 1437 u32 ctrl; 1438 int res; 1439 1440 /* Allocate resources */ 1441 entid = yt921x_acl_reserve(priv, entscnt, extack); 1442 if (entid == UINT_MAX) 1443 return -EOPNOTSUPP; 1444 1445 if (!(ruleext->r.action[0] & YT921X_ACL_ACTa_METER_EN)) { 1446 meterid = YT921X_METER_NUM; 1447 } else { 1448 meterid = find_first_zero_bit(priv->meters_map, 1449 YT921X_METER_NUM); 1450 if (meterid < YT921X_METER_NUM) { 1451 res = yt921x_meter_config(priv, meterid, 1452 &ruleext->marker); 1453 if (res) 1454 return res; 1455 } else if (ruleext->r.sw_assisted) { 1456 use_trap = true; 1457 } else { 1458 NL_SET_ERR_MSG_MOD(extack, 1459 "No more meters available"); 1460 return -EOPNOTSUPP; 1461 } 1462 } 1463 1464 /* Prepare acl block ctrlblk */ 1465 blkid = entid / YT921X_ACL_ENT_PER_BLK; 1466 binid = entid % YT921X_ACL_ENT_PER_BLK; 1467 aclblk = priv->acl_blks[blkid]; 1468 if (!aclblk) { 1469 aclblk = kvzalloc_obj(*aclblk); 1470 if (!aclblk) 1471 return -ENOMEM; 1472 priv->acl_blks[blkid] = aclblk; 1473 } 1474 1475 /* Prepare acl rule ctrlblk */ 1476 aclrule = kvmemdup(&ruleext->r, 1477 offsetof(struct yt921x_acl_rule, entries[entscnt]), 1478 GFP_KERNEL); 1479 if (!aclrule) { 1480 res = -ENOMEM; 1481 goto err; 1482 } 1483 1484 /* Replace the placeholder resource IDs */ 1485 aclrule->mask = 0; 1486 m = priv->acl_masks[blkid]; 1487 for_each_clear_bit(o, &m, YT921X_ACL_ENT_PER_BLK) { 1488 aclrule->mask |= BIT(o); 1489 entscnt--; 1490 if (!entscnt) 1491 break; 1492 } 1493 1494 if (use_trap) { 1495 aclrule->action[2] &= ~YT921X_ACL_ACTc_FWD_REDIR_DPORTS_M & 1496 ~YT921X_ACL_ACTc_FWD_M; 1497 aclrule->action[2] |= YT921X_ACL_ACTc_FWD_EN | 1498 YT921X_ACL_ACTc_FWD_TRAP; 1499 } 1500 if (meterid < YT921X_METER_NUM) 1501 aclrule->action[0] |= YT921X_ACL_ACTa_METER_ID(meterid); 1502 else 1503 aclrule->action[0] &= ~YT921X_ACL_ACTa_METER_EN; 1504 1505 /* Activate ACL if needed */ 1506 ctrl = 0; 1507 m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, ruleext->r.entries[0].key[1]); 1508 for_each_set_bit(o, &m, YT921X_PORT_NUM) 1509 if (!priv->ports[o].acl_cnt) 1510 ctrl |= YT921X_ACL_PORT_PORTn(o); 1511 if (ctrl) { 1512 ctrl |= yt921x_acl_activated_ports(priv); 1513 res = yt921x_reg_write(priv, YT921X_ACL_PORT, ctrl); 1514 if (res) 1515 goto err; 1516 } 1517 1518 /* Write rules */ 1519 aclblk->rules[binid] = aclrule; 1520 res = yt921x_acl_commit(priv, entid, aclrule->mask); 1521 if (res) { 1522 aclblk->rules[binid] = NULL; 1523 goto err; 1524 } 1525 1526 /* Bookkeeping */ 1527 m = FIELD_GET(YT921X_ACL_KEYb_SPORTS_M, ruleext->r.entries[0].key[1]); 1528 for_each_set_bit(o, &m, YT921X_PORT_NUM) 1529 priv->ports[o].acl_cnt++; 1530 1531 if (meterid < YT921X_METER_NUM) 1532 set_bit(meterid, priv->meters_map); 1533 priv->acl_masks[blkid] |= aclrule->mask; 1534 return 0; 1535 1536 err: 1537 kvfree(aclrule); 1538 if (!priv->acl_masks[blkid]) { 1539 kvfree(aclblk); 1540 priv->acl_blks[blkid] = NULL; 1541 } 1542 return res; 1543 } 1544 1545 int 1546 yt921x_dsa_cls_flower_del(struct dsa_switch *ds, int port, 1547 struct flow_cls_offload *cls, bool ingress) 1548 { 1549 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 1550 int res; 1551 1552 mutex_lock(&priv->reg_lock); 1553 res = yt921x_acl_del(priv, TC_SETUP_CLSFLOWER, cls->cookie); 1554 mutex_unlock(&priv->reg_lock); 1555 1556 return res; 1557 } 1558 1559 int 1560 yt921x_dsa_cls_flower_add(struct dsa_switch *ds, int port, 1561 struct flow_cls_offload *cls, bool ingress) 1562 { 1563 struct netlink_ext_ack *extack = cls->common.extack; 1564 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 1565 struct yt921x_acl_rule_ext ruleext; 1566 int res; 1567 1568 res = yt921x_acl_rule_ext_parse_flow(&ruleext, port, cls, ingress, 1569 priv); 1570 if (res) 1571 return res; 1572 1573 mutex_lock(&priv->reg_lock); 1574 res = yt921x_acl_add(priv, &ruleext, extack); 1575 mutex_unlock(&priv->reg_lock); 1576 1577 return res; 1578 } 1579 1580 static int 1581 yt921x_mirror_del(struct yt921x_priv *priv, int port, bool ingress) 1582 { 1583 u32 mask; 1584 1585 if (ingress) 1586 mask = YT921X_MIRROR_IGR_PORTn(port); 1587 else 1588 mask = YT921X_MIRROR_EGR_PORTn(port); 1589 return yt921x_reg_clear_bits(priv, YT921X_MIRROR, mask); 1590 } 1591 1592 static int 1593 yt921x_mirror_add(struct yt921x_priv *priv, int port, bool ingress, 1594 int to_local_port, struct netlink_ext_ack *extack) 1595 { 1596 u32 srcs; 1597 u32 ctrl; 1598 u32 val; 1599 u32 dst; 1600 int res; 1601 1602 if (ingress) 1603 srcs = YT921X_MIRROR_IGR_PORTn(port); 1604 else 1605 srcs = YT921X_MIRROR_EGR_PORTn(port); 1606 dst = YT921X_MIRROR_PORT(to_local_port); 1607 1608 res = yt921x_reg_read(priv, YT921X_MIRROR, &val); 1609 if (res) 1610 return res; 1611 1612 /* other mirror tasks & different dst port -> conflict */ 1613 if ((val & ~srcs & (YT921X_MIRROR_EGR_PORTS_M | 1614 YT921X_MIRROR_IGR_PORTS_M)) && 1615 (val & YT921X_MIRROR_PORT_M) != dst) { 1616 NL_SET_ERR_MSG_MOD(extack, 1617 "Sniffer port is already configured, delete existing rules & retry"); 1618 return -EBUSY; 1619 } 1620 1621 ctrl = val & ~YT921X_MIRROR_PORT_M; 1622 ctrl |= srcs; 1623 ctrl |= dst; 1624 1625 if (ctrl == val) 1626 return 0; 1627 1628 return yt921x_reg_write(priv, YT921X_MIRROR, ctrl); 1629 } 1630 1631 void 1632 yt921x_dsa_port_mirror_del(struct dsa_switch *ds, int port, 1633 struct dsa_mall_mirror_tc_entry *mirror) 1634 { 1635 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 1636 struct device *dev = yt921x_priv_to_device(priv); 1637 int res; 1638 1639 mutex_lock(&priv->reg_lock); 1640 res = yt921x_mirror_del(priv, port, mirror->ingress); 1641 mutex_unlock(&priv->reg_lock); 1642 1643 if (res) 1644 dev_err(dev, "Failed to %s port %d: %i\n", "unmirror", 1645 port, res); 1646 } 1647 1648 int 1649 yt921x_dsa_port_mirror_add(struct dsa_switch *ds, int port, 1650 struct dsa_mall_mirror_tc_entry *mirror, 1651 bool ingress, struct netlink_ext_ack *extack) 1652 { 1653 struct yt921x_priv *priv = dsa_to_yt921x_priv(ds); 1654 int res; 1655 1656 mutex_lock(&priv->reg_lock); 1657 res = yt921x_mirror_add(priv, port, ingress, 1658 mirror->to_local_port, extack); 1659 mutex_unlock(&priv->reg_lock); 1660 1661 return res; 1662 } 1663 1664 int yt921x_chip_setup_tc(struct yt921x_priv *priv) 1665 { 1666 unsigned int op_ns; 1667 u32 ctrl; 1668 int res; 1669 1670 op_ns = 8 * priv->cycle_ns; 1671 1672 ctrl = max(priv->meter_slot_ns / op_ns, YT921X_METER_SLOT_MIN); 1673 res = yt921x_reg_write(priv, YT921X_METER_SLOT, ctrl); 1674 if (res) 1675 return res; 1676 priv->meter_slot_ns = ctrl * op_ns; 1677 1678 ctrl = max(priv->port_shape_slot_ns / op_ns, 1679 YT921X_PORT_SHAPE_SLOT_MIN); 1680 res = yt921x_reg_write(priv, YT921X_PORT_SHAPE_SLOT, ctrl); 1681 if (res) 1682 return res; 1683 priv->port_shape_slot_ns = ctrl * op_ns; 1684 1685 return 0; 1686 } 1687 1688 int yt921x_chip_setup_acl(struct yt921x_priv *priv) 1689 { 1690 u32 ctrl; 1691 int res; 1692 1693 ctrl = YT921X_ACL_PERMIT_UNMATCH_PORTS_M; 1694 res = yt921x_reg_write(priv, YT921X_ACL_PERMIT_UNMATCH, ctrl); 1695 if (res) 1696 return res; 1697 1698 res = yt921x_reg_write(priv, YT921X_ACL_PORT, 0); 1699 if (res) 1700 return res; 1701 1702 for (unsigned int o = 0; o < ARRAY_SIZE(yt921x_udf_maps); o++) { 1703 ctrl = YT921X_UDF_CTRL_UDF_OFFSET(yt921x_udf_maps[o].offset) | 1704 YT921X_UDF_CTRL_UDF_TYPE(yt921x_udf_maps[o].type); 1705 res = yt921x_reg_write(priv, YT921X_UDFn_CTRL(o), ctrl); 1706 if (res) 1707 return res; 1708 } 1709 1710 return 0; 1711 } 1712