1 /* 2 * Broadcom Starfighter 2 DSA switch CFP support 3 * 4 * Copyright (C) 2016, Broadcom 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12 #include <linux/list.h> 13 #include <linux/ethtool.h> 14 #include <linux/if_ether.h> 15 #include <linux/in.h> 16 #include <linux/netdevice.h> 17 #include <net/dsa.h> 18 #include <linux/bitmap.h> 19 20 #include "bcm_sf2.h" 21 #include "bcm_sf2_regs.h" 22 23 struct cfp_rule { 24 int port; 25 struct ethtool_rx_flow_spec fs; 26 struct list_head next; 27 }; 28 29 struct cfp_udf_slice_layout { 30 u8 slices[UDFS_PER_SLICE]; 31 u32 mask_value; 32 u32 base_offset; 33 }; 34 35 struct cfp_udf_layout { 36 struct cfp_udf_slice_layout udfs[UDF_NUM_SLICES]; 37 }; 38 39 static const u8 zero_slice[UDFS_PER_SLICE] = { }; 40 41 /* UDF slices layout for a TCPv4/UDPv4 specification */ 42 static const struct cfp_udf_layout udf_tcpip4_layout = { 43 .udfs = { 44 [1] = { 45 .slices = { 46 /* End of L2, byte offset 12, src IP[0:15] */ 47 CFG_UDF_EOL2 | 6, 48 /* End of L2, byte offset 14, src IP[16:31] */ 49 CFG_UDF_EOL2 | 7, 50 /* End of L2, byte offset 16, dst IP[0:15] */ 51 CFG_UDF_EOL2 | 8, 52 /* End of L2, byte offset 18, dst IP[16:31] */ 53 CFG_UDF_EOL2 | 9, 54 /* End of L3, byte offset 0, src port */ 55 CFG_UDF_EOL3 | 0, 56 /* End of L3, byte offset 2, dst port */ 57 CFG_UDF_EOL3 | 1, 58 0, 0, 0 59 }, 60 .mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG, 61 .base_offset = CORE_UDF_0_A_0_8_PORT_0 + UDF_SLICE_OFFSET, 62 }, 63 }, 64 }; 65 66 /* UDF slices layout for a TCPv6/UDPv6 specification */ 67 static const struct cfp_udf_layout udf_tcpip6_layout = { 68 .udfs = { 69 [0] = { 70 .slices = { 71 /* End of L2, byte offset 8, src IP[0:15] */ 72 CFG_UDF_EOL2 | 4, 73 /* End of L2, byte offset 10, src IP[16:31] */ 74 CFG_UDF_EOL2 | 5, 75 /* End of L2, byte offset 12, src IP[32:47] */ 76 CFG_UDF_EOL2 | 6, 77 /* End of L2, byte offset 14, src IP[48:63] */ 78 CFG_UDF_EOL2 | 7, 79 /* End of L2, byte offset 16, src IP[64:79] */ 80 CFG_UDF_EOL2 | 8, 81 /* End of L2, byte offset 18, src IP[80:95] */ 82 CFG_UDF_EOL2 | 9, 83 /* End of L2, byte offset 20, src IP[96:111] */ 84 CFG_UDF_EOL2 | 10, 85 /* End of L2, byte offset 22, src IP[112:127] */ 86 CFG_UDF_EOL2 | 11, 87 /* End of L3, byte offset 0, src port */ 88 CFG_UDF_EOL3 | 0, 89 }, 90 .mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG, 91 .base_offset = CORE_UDF_0_B_0_8_PORT_0, 92 }, 93 [3] = { 94 .slices = { 95 /* End of L2, byte offset 24, dst IP[0:15] */ 96 CFG_UDF_EOL2 | 12, 97 /* End of L2, byte offset 26, dst IP[16:31] */ 98 CFG_UDF_EOL2 | 13, 99 /* End of L2, byte offset 28, dst IP[32:47] */ 100 CFG_UDF_EOL2 | 14, 101 /* End of L2, byte offset 30, dst IP[48:63] */ 102 CFG_UDF_EOL2 | 15, 103 /* End of L2, byte offset 32, dst IP[64:79] */ 104 CFG_UDF_EOL2 | 16, 105 /* End of L2, byte offset 34, dst IP[80:95] */ 106 CFG_UDF_EOL2 | 17, 107 /* End of L2, byte offset 36, dst IP[96:111] */ 108 CFG_UDF_EOL2 | 18, 109 /* End of L2, byte offset 38, dst IP[112:127] */ 110 CFG_UDF_EOL2 | 19, 111 /* End of L3, byte offset 2, dst port */ 112 CFG_UDF_EOL3 | 1, 113 }, 114 .mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG, 115 .base_offset = CORE_UDF_0_D_0_11_PORT_0, 116 }, 117 }, 118 }; 119 120 static inline unsigned int bcm_sf2_get_num_udf_slices(const u8 *layout) 121 { 122 unsigned int i, count = 0; 123 124 for (i = 0; i < UDFS_PER_SLICE; i++) { 125 if (layout[i] != 0) 126 count++; 127 } 128 129 return count; 130 } 131 132 static inline u32 udf_upper_bits(unsigned int num_udf) 133 { 134 return GENMASK(num_udf - 1, 0) >> (UDFS_PER_SLICE - 1); 135 } 136 137 static inline u32 udf_lower_bits(unsigned int num_udf) 138 { 139 return (u8)GENMASK(num_udf - 1, 0); 140 } 141 142 static unsigned int bcm_sf2_get_slice_number(const struct cfp_udf_layout *l, 143 unsigned int start) 144 { 145 const struct cfp_udf_slice_layout *slice_layout; 146 unsigned int slice_idx; 147 148 for (slice_idx = start; slice_idx < UDF_NUM_SLICES; slice_idx++) { 149 slice_layout = &l->udfs[slice_idx]; 150 if (memcmp(slice_layout->slices, zero_slice, 151 sizeof(zero_slice))) 152 break; 153 } 154 155 return slice_idx; 156 } 157 158 static void bcm_sf2_cfp_udf_set(struct bcm_sf2_priv *priv, 159 const struct cfp_udf_layout *layout, 160 unsigned int slice_num) 161 { 162 u32 offset = layout->udfs[slice_num].base_offset; 163 unsigned int i; 164 165 for (i = 0; i < UDFS_PER_SLICE; i++) 166 core_writel(priv, layout->udfs[slice_num].slices[i], 167 offset + i * 4); 168 } 169 170 static int bcm_sf2_cfp_op(struct bcm_sf2_priv *priv, unsigned int op) 171 { 172 unsigned int timeout = 1000; 173 u32 reg; 174 175 reg = core_readl(priv, CORE_CFP_ACC); 176 reg &= ~(OP_SEL_MASK | RAM_SEL_MASK); 177 reg |= OP_STR_DONE | op; 178 core_writel(priv, reg, CORE_CFP_ACC); 179 180 do { 181 reg = core_readl(priv, CORE_CFP_ACC); 182 if (!(reg & OP_STR_DONE)) 183 break; 184 185 cpu_relax(); 186 } while (timeout--); 187 188 if (!timeout) 189 return -ETIMEDOUT; 190 191 return 0; 192 } 193 194 static inline void bcm_sf2_cfp_rule_addr_set(struct bcm_sf2_priv *priv, 195 unsigned int addr) 196 { 197 u32 reg; 198 199 WARN_ON(addr >= priv->num_cfp_rules); 200 201 reg = core_readl(priv, CORE_CFP_ACC); 202 reg &= ~(XCESS_ADDR_MASK << XCESS_ADDR_SHIFT); 203 reg |= addr << XCESS_ADDR_SHIFT; 204 core_writel(priv, reg, CORE_CFP_ACC); 205 } 206 207 static inline unsigned int bcm_sf2_cfp_rule_size(struct bcm_sf2_priv *priv) 208 { 209 /* Entry #0 is reserved */ 210 return priv->num_cfp_rules - 1; 211 } 212 213 static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv, 214 unsigned int rule_index, 215 unsigned int port_num, 216 unsigned int queue_num, 217 bool fwd_map_change) 218 { 219 int ret; 220 u32 reg; 221 222 /* Replace ARL derived destination with DST_MAP derived, define 223 * which port and queue this should be forwarded to. 224 */ 225 if (fwd_map_change) 226 reg = CHANGE_FWRD_MAP_IB_REP_ARL | 227 BIT(port_num + DST_MAP_IB_SHIFT) | 228 CHANGE_TC | queue_num << NEW_TC_SHIFT; 229 else 230 reg = 0; 231 232 core_writel(priv, reg, CORE_ACT_POL_DATA0); 233 234 /* Set classification ID that needs to be put in Broadcom tag */ 235 core_writel(priv, rule_index << CHAIN_ID_SHIFT, CORE_ACT_POL_DATA1); 236 237 core_writel(priv, 0, CORE_ACT_POL_DATA2); 238 239 /* Configure policer RAM now */ 240 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | ACT_POL_RAM); 241 if (ret) { 242 pr_err("Policer entry at %d failed\n", rule_index); 243 return ret; 244 } 245 246 /* Disable the policer */ 247 core_writel(priv, POLICER_MODE_DISABLE, CORE_RATE_METER0); 248 249 /* Now the rate meter */ 250 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | RATE_METER_RAM); 251 if (ret) { 252 pr_err("Meter entry at %d failed\n", rule_index); 253 return ret; 254 } 255 256 return 0; 257 } 258 259 static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv, 260 struct ethtool_tcpip4_spec *v4_spec, 261 unsigned int slice_num, 262 bool mask) 263 { 264 u32 reg, offset; 265 266 /* C-Tag [31:24] 267 * UDF_n_A8 [23:8] 268 * UDF_n_A7 [7:0] 269 */ 270 reg = 0; 271 if (mask) 272 offset = CORE_CFP_MASK_PORT(4); 273 else 274 offset = CORE_CFP_DATA_PORT(4); 275 core_writel(priv, reg, offset); 276 277 /* UDF_n_A7 [31:24] 278 * UDF_n_A6 [23:8] 279 * UDF_n_A5 [7:0] 280 */ 281 reg = be16_to_cpu(v4_spec->pdst) >> 8; 282 if (mask) 283 offset = CORE_CFP_MASK_PORT(3); 284 else 285 offset = CORE_CFP_DATA_PORT(3); 286 core_writel(priv, reg, offset); 287 288 /* UDF_n_A5 [31:24] 289 * UDF_n_A4 [23:8] 290 * UDF_n_A3 [7:0] 291 */ 292 reg = (be16_to_cpu(v4_spec->pdst) & 0xff) << 24 | 293 (u32)be16_to_cpu(v4_spec->psrc) << 8 | 294 (be32_to_cpu(v4_spec->ip4dst) & 0x0000ff00) >> 8; 295 if (mask) 296 offset = CORE_CFP_MASK_PORT(2); 297 else 298 offset = CORE_CFP_DATA_PORT(2); 299 core_writel(priv, reg, offset); 300 301 /* UDF_n_A3 [31:24] 302 * UDF_n_A2 [23:8] 303 * UDF_n_A1 [7:0] 304 */ 305 reg = (u32)(be32_to_cpu(v4_spec->ip4dst) & 0xff) << 24 | 306 (u32)(be32_to_cpu(v4_spec->ip4dst) >> 16) << 8 | 307 (be32_to_cpu(v4_spec->ip4src) & 0x0000ff00) >> 8; 308 if (mask) 309 offset = CORE_CFP_MASK_PORT(1); 310 else 311 offset = CORE_CFP_DATA_PORT(1); 312 core_writel(priv, reg, offset); 313 314 /* UDF_n_A1 [31:24] 315 * UDF_n_A0 [23:8] 316 * Reserved [7:4] 317 * Slice ID [3:2] 318 * Slice valid [1:0] 319 */ 320 reg = (u32)(be32_to_cpu(v4_spec->ip4src) & 0xff) << 24 | 321 (u32)(be32_to_cpu(v4_spec->ip4src) >> 16) << 8 | 322 SLICE_NUM(slice_num) | SLICE_VALID; 323 if (mask) 324 offset = CORE_CFP_MASK_PORT(0); 325 else 326 offset = CORE_CFP_DATA_PORT(0); 327 core_writel(priv, reg, offset); 328 } 329 330 static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port, 331 unsigned int port_num, 332 unsigned int queue_num, 333 struct ethtool_rx_flow_spec *fs) 334 { 335 struct ethtool_tcpip4_spec *v4_spec, *v4_m_spec; 336 const struct cfp_udf_layout *layout; 337 unsigned int slice_num, rule_index; 338 u8 ip_proto, ip_frag; 339 u8 num_udf; 340 u32 reg; 341 int ret; 342 343 switch (fs->flow_type & ~FLOW_EXT) { 344 case TCP_V4_FLOW: 345 ip_proto = IPPROTO_TCP; 346 v4_spec = &fs->h_u.tcp_ip4_spec; 347 v4_m_spec = &fs->m_u.tcp_ip4_spec; 348 break; 349 case UDP_V4_FLOW: 350 ip_proto = IPPROTO_UDP; 351 v4_spec = &fs->h_u.udp_ip4_spec; 352 v4_m_spec = &fs->m_u.udp_ip4_spec; 353 break; 354 default: 355 return -EINVAL; 356 } 357 358 ip_frag = be32_to_cpu(fs->m_ext.data[0]); 359 360 /* Locate the first rule available */ 361 if (fs->location == RX_CLS_LOC_ANY) 362 rule_index = find_first_zero_bit(priv->cfp.used, 363 priv->num_cfp_rules); 364 else 365 rule_index = fs->location; 366 367 if (rule_index > bcm_sf2_cfp_rule_size(priv)) 368 return -ENOSPC; 369 370 layout = &udf_tcpip4_layout; 371 /* We only use one UDF slice for now */ 372 slice_num = bcm_sf2_get_slice_number(layout, 0); 373 if (slice_num == UDF_NUM_SLICES) 374 return -EINVAL; 375 376 num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices); 377 378 /* Apply the UDF layout for this filter */ 379 bcm_sf2_cfp_udf_set(priv, layout, slice_num); 380 381 /* Apply to all packets received through this port */ 382 core_writel(priv, BIT(port), CORE_CFP_DATA_PORT(7)); 383 384 /* Source port map match */ 385 core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7)); 386 387 /* S-Tag status [31:30] 388 * C-Tag status [29:28] 389 * L2 framing [27:26] 390 * L3 framing [25:24] 391 * IP ToS [23:16] 392 * IP proto [15:08] 393 * IP Fragm [7] 394 * Non 1st frag [6] 395 * IP Authen [5] 396 * TTL range [4:3] 397 * PPPoE session [2] 398 * Reserved [1] 399 * UDF_Valid[8] [0] 400 */ 401 core_writel(priv, v4_spec->tos << IPTOS_SHIFT | 402 ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT | 403 udf_upper_bits(num_udf), 404 CORE_CFP_DATA_PORT(6)); 405 406 /* Mask with the specific layout for IPv4 packets */ 407 core_writel(priv, layout->udfs[slice_num].mask_value | 408 udf_upper_bits(num_udf), CORE_CFP_MASK_PORT(6)); 409 410 /* UDF_Valid[7:0] [31:24] 411 * S-Tag [23:8] 412 * C-Tag [7:0] 413 */ 414 core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_DATA_PORT(5)); 415 416 /* Mask all but valid UDFs */ 417 core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5)); 418 419 /* Program the match and the mask */ 420 bcm_sf2_cfp_slice_ipv4(priv, v4_spec, slice_num, false); 421 bcm_sf2_cfp_slice_ipv4(priv, v4_m_spec, SLICE_NUM_MASK, true); 422 423 /* Insert into TCAM now */ 424 bcm_sf2_cfp_rule_addr_set(priv, rule_index); 425 426 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); 427 if (ret) { 428 pr_err("TCAM entry at addr %d failed\n", rule_index); 429 return ret; 430 } 431 432 /* Insert into Action and policer RAMs now */ 433 ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port_num, 434 queue_num, true); 435 if (ret) 436 return ret; 437 438 /* Turn on CFP for this rule now */ 439 reg = core_readl(priv, CORE_CFP_CTL_REG); 440 reg |= BIT(port); 441 core_writel(priv, reg, CORE_CFP_CTL_REG); 442 443 /* Flag the rule as being used and return it */ 444 set_bit(rule_index, priv->cfp.used); 445 set_bit(rule_index, priv->cfp.unique); 446 fs->location = rule_index; 447 448 return 0; 449 } 450 451 static void bcm_sf2_cfp_slice_ipv6(struct bcm_sf2_priv *priv, 452 const __be32 *ip6_addr, const __be16 port, 453 unsigned int slice_num, 454 bool mask) 455 { 456 u32 reg, tmp, val, offset; 457 458 /* C-Tag [31:24] 459 * UDF_n_B8 [23:8] (port) 460 * UDF_n_B7 (upper) [7:0] (addr[15:8]) 461 */ 462 reg = be32_to_cpu(ip6_addr[3]); 463 val = (u32)be16_to_cpu(port) << 8 | ((reg >> 8) & 0xff); 464 if (mask) 465 offset = CORE_CFP_MASK_PORT(4); 466 else 467 offset = CORE_CFP_DATA_PORT(4); 468 core_writel(priv, val, offset); 469 470 /* UDF_n_B7 (lower) [31:24] (addr[7:0]) 471 * UDF_n_B6 [23:8] (addr[31:16]) 472 * UDF_n_B5 (upper) [7:0] (addr[47:40]) 473 */ 474 tmp = be32_to_cpu(ip6_addr[2]); 475 val = (u32)(reg & 0xff) << 24 | (u32)(reg >> 16) << 8 | 476 ((tmp >> 8) & 0xff); 477 if (mask) 478 offset = CORE_CFP_MASK_PORT(3); 479 else 480 offset = CORE_CFP_DATA_PORT(3); 481 core_writel(priv, val, offset); 482 483 /* UDF_n_B5 (lower) [31:24] (addr[39:32]) 484 * UDF_n_B4 [23:8] (addr[63:48]) 485 * UDF_n_B3 (upper) [7:0] (addr[79:72]) 486 */ 487 reg = be32_to_cpu(ip6_addr[1]); 488 val = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 | 489 ((reg >> 8) & 0xff); 490 if (mask) 491 offset = CORE_CFP_MASK_PORT(2); 492 else 493 offset = CORE_CFP_DATA_PORT(2); 494 core_writel(priv, val, offset); 495 496 /* UDF_n_B3 (lower) [31:24] (addr[71:64]) 497 * UDF_n_B2 [23:8] (addr[95:80]) 498 * UDF_n_B1 (upper) [7:0] (addr[111:104]) 499 */ 500 tmp = be32_to_cpu(ip6_addr[0]); 501 val = (u32)(reg & 0xff) << 24 | (u32)(reg >> 16) << 8 | 502 ((tmp >> 8) & 0xff); 503 if (mask) 504 offset = CORE_CFP_MASK_PORT(1); 505 else 506 offset = CORE_CFP_DATA_PORT(1); 507 core_writel(priv, val, offset); 508 509 /* UDF_n_B1 (lower) [31:24] (addr[103:96]) 510 * UDF_n_B0 [23:8] (addr[127:112]) 511 * Reserved [7:4] 512 * Slice ID [3:2] 513 * Slice valid [1:0] 514 */ 515 reg = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 | 516 SLICE_NUM(slice_num) | SLICE_VALID; 517 if (mask) 518 offset = CORE_CFP_MASK_PORT(0); 519 else 520 offset = CORE_CFP_DATA_PORT(0); 521 core_writel(priv, reg, offset); 522 } 523 524 static struct cfp_rule *bcm_sf2_cfp_rule_find(struct bcm_sf2_priv *priv, 525 int port, u32 location) 526 { 527 struct cfp_rule *rule = NULL; 528 529 list_for_each_entry(rule, &priv->cfp.rules_list, next) { 530 if (rule->port == port && rule->fs.location == location) 531 break; 532 } 533 534 return rule; 535 } 536 537 static int bcm_sf2_cfp_rule_cmp(struct bcm_sf2_priv *priv, int port, 538 struct ethtool_rx_flow_spec *fs) 539 { 540 struct cfp_rule *rule = NULL; 541 size_t fs_size = 0; 542 int ret = 1; 543 544 if (list_empty(&priv->cfp.rules_list)) 545 return ret; 546 547 list_for_each_entry(rule, &priv->cfp.rules_list, next) { 548 ret = 1; 549 if (rule->port != port) 550 continue; 551 552 if (rule->fs.flow_type != fs->flow_type || 553 rule->fs.ring_cookie != fs->ring_cookie || 554 rule->fs.m_ext.data[0] != fs->m_ext.data[0]) 555 continue; 556 557 switch (fs->flow_type & ~FLOW_EXT) { 558 case TCP_V6_FLOW: 559 case UDP_V6_FLOW: 560 fs_size = sizeof(struct ethtool_tcpip6_spec); 561 break; 562 case TCP_V4_FLOW: 563 case UDP_V4_FLOW: 564 fs_size = sizeof(struct ethtool_tcpip4_spec); 565 break; 566 default: 567 continue; 568 } 569 570 ret = memcmp(&rule->fs.h_u, &fs->h_u, fs_size); 571 ret |= memcmp(&rule->fs.m_u, &fs->m_u, fs_size); 572 if (ret == 0) 573 break; 574 } 575 576 return ret; 577 } 578 579 static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port, 580 unsigned int port_num, 581 unsigned int queue_num, 582 struct ethtool_rx_flow_spec *fs) 583 { 584 struct ethtool_tcpip6_spec *v6_spec, *v6_m_spec; 585 unsigned int slice_num, rule_index[2]; 586 const struct cfp_udf_layout *layout; 587 u8 ip_proto, ip_frag; 588 int ret = 0; 589 u8 num_udf; 590 u32 reg; 591 592 switch (fs->flow_type & ~FLOW_EXT) { 593 case TCP_V6_FLOW: 594 ip_proto = IPPROTO_TCP; 595 v6_spec = &fs->h_u.tcp_ip6_spec; 596 v6_m_spec = &fs->m_u.tcp_ip6_spec; 597 break; 598 case UDP_V6_FLOW: 599 ip_proto = IPPROTO_UDP; 600 v6_spec = &fs->h_u.udp_ip6_spec; 601 v6_m_spec = &fs->m_u.udp_ip6_spec; 602 break; 603 default: 604 return -EINVAL; 605 } 606 607 ip_frag = be32_to_cpu(fs->m_ext.data[0]); 608 609 layout = &udf_tcpip6_layout; 610 slice_num = bcm_sf2_get_slice_number(layout, 0); 611 if (slice_num == UDF_NUM_SLICES) 612 return -EINVAL; 613 614 num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices); 615 616 /* Negotiate two indexes, one for the second half which we are chained 617 * from, which is what we will return to user-space, and a second one 618 * which is used to store its first half. That first half does not 619 * allow any choice of placement, so it just needs to find the next 620 * available bit. We return the second half as fs->location because 621 * that helps with the rule lookup later on since the second half is 622 * chained from its first half, we can easily identify IPv6 CFP rules 623 * by looking whether they carry a CHAIN_ID. 624 * 625 * We also want the second half to have a lower rule_index than its 626 * first half because the HW search is by incrementing addresses. 627 */ 628 if (fs->location == RX_CLS_LOC_ANY) 629 rule_index[1] = find_first_zero_bit(priv->cfp.used, 630 priv->num_cfp_rules); 631 else 632 rule_index[1] = fs->location; 633 if (rule_index[1] > bcm_sf2_cfp_rule_size(priv)) 634 return -ENOSPC; 635 636 /* Flag it as used (cleared on error path) such that we can immediately 637 * obtain a second one to chain from. 638 */ 639 set_bit(rule_index[1], priv->cfp.used); 640 641 rule_index[0] = find_first_zero_bit(priv->cfp.used, 642 priv->num_cfp_rules); 643 if (rule_index[0] > bcm_sf2_cfp_rule_size(priv)) { 644 ret = -ENOSPC; 645 goto out_err; 646 } 647 648 /* Apply the UDF layout for this filter */ 649 bcm_sf2_cfp_udf_set(priv, layout, slice_num); 650 651 /* Apply to all packets received through this port */ 652 core_writel(priv, BIT(port), CORE_CFP_DATA_PORT(7)); 653 654 /* Source port map match */ 655 core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7)); 656 657 /* S-Tag status [31:30] 658 * C-Tag status [29:28] 659 * L2 framing [27:26] 660 * L3 framing [25:24] 661 * IP ToS [23:16] 662 * IP proto [15:08] 663 * IP Fragm [7] 664 * Non 1st frag [6] 665 * IP Authen [5] 666 * TTL range [4:3] 667 * PPPoE session [2] 668 * Reserved [1] 669 * UDF_Valid[8] [0] 670 */ 671 reg = 1 << L3_FRAMING_SHIFT | ip_proto << IPPROTO_SHIFT | 672 ip_frag << IP_FRAG_SHIFT | udf_upper_bits(num_udf); 673 core_writel(priv, reg, CORE_CFP_DATA_PORT(6)); 674 675 /* Mask with the specific layout for IPv6 packets including 676 * UDF_Valid[8] 677 */ 678 reg = layout->udfs[slice_num].mask_value | udf_upper_bits(num_udf); 679 core_writel(priv, reg, CORE_CFP_MASK_PORT(6)); 680 681 /* UDF_Valid[7:0] [31:24] 682 * S-Tag [23:8] 683 * C-Tag [7:0] 684 */ 685 core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_DATA_PORT(5)); 686 687 /* Mask all but valid UDFs */ 688 core_writel(priv, udf_lower_bits(num_udf) << 24, CORE_CFP_MASK_PORT(5)); 689 690 /* Slice the IPv6 source address and port */ 691 bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6src, v6_spec->psrc, 692 slice_num, false); 693 bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6src, v6_m_spec->psrc, 694 SLICE_NUM_MASK, true); 695 696 /* Insert into TCAM now because we need to insert a second rule */ 697 bcm_sf2_cfp_rule_addr_set(priv, rule_index[0]); 698 699 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); 700 if (ret) { 701 pr_err("TCAM entry at addr %d failed\n", rule_index[0]); 702 goto out_err; 703 } 704 705 /* Insert into Action and policer RAMs now */ 706 ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port_num, 707 queue_num, false); 708 if (ret) 709 goto out_err; 710 711 /* Now deal with the second slice to chain this rule */ 712 slice_num = bcm_sf2_get_slice_number(layout, slice_num + 1); 713 if (slice_num == UDF_NUM_SLICES) { 714 ret = -EINVAL; 715 goto out_err; 716 } 717 718 num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices); 719 720 /* Apply the UDF layout for this filter */ 721 bcm_sf2_cfp_udf_set(priv, layout, slice_num); 722 723 /* Chained rule, source port match is coming from the rule we are 724 * chained from. 725 */ 726 core_writel(priv, 0, CORE_CFP_DATA_PORT(7)); 727 core_writel(priv, 0, CORE_CFP_MASK_PORT(7)); 728 729 /* 730 * CHAIN ID [31:24] chain to previous slice 731 * Reserved [23:20] 732 * UDF_Valid[11:8] [19:16] 733 * UDF_Valid[7:0] [15:8] 734 * UDF_n_D11 [7:0] 735 */ 736 reg = rule_index[0] << 24 | udf_upper_bits(num_udf) << 16 | 737 udf_lower_bits(num_udf) << 8; 738 core_writel(priv, reg, CORE_CFP_DATA_PORT(6)); 739 740 /* Mask all except chain ID, UDF Valid[8] and UDF Valid[7:0] */ 741 reg = XCESS_ADDR_MASK << 24 | udf_upper_bits(num_udf) << 16 | 742 udf_lower_bits(num_udf) << 8; 743 core_writel(priv, reg, CORE_CFP_MASK_PORT(6)); 744 745 /* Don't care */ 746 core_writel(priv, 0, CORE_CFP_DATA_PORT(5)); 747 748 /* Mask all */ 749 core_writel(priv, 0, CORE_CFP_MASK_PORT(5)); 750 751 bcm_sf2_cfp_slice_ipv6(priv, v6_spec->ip6dst, v6_spec->pdst, slice_num, 752 false); 753 bcm_sf2_cfp_slice_ipv6(priv, v6_m_spec->ip6dst, v6_m_spec->pdst, 754 SLICE_NUM_MASK, true); 755 756 /* Insert into TCAM now */ 757 bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]); 758 759 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); 760 if (ret) { 761 pr_err("TCAM entry at addr %d failed\n", rule_index[1]); 762 goto out_err; 763 } 764 765 /* Insert into Action and policer RAMs now, set chain ID to 766 * the one we are chained to 767 */ 768 ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port_num, 769 queue_num, true); 770 if (ret) 771 goto out_err; 772 773 /* Turn on CFP for this rule now */ 774 reg = core_readl(priv, CORE_CFP_CTL_REG); 775 reg |= BIT(port); 776 core_writel(priv, reg, CORE_CFP_CTL_REG); 777 778 /* Flag the second half rule as being used now, return it as the 779 * location, and flag it as unique while dumping rules 780 */ 781 set_bit(rule_index[0], priv->cfp.used); 782 set_bit(rule_index[1], priv->cfp.unique); 783 fs->location = rule_index[1]; 784 785 return ret; 786 787 out_err: 788 clear_bit(rule_index[1], priv->cfp.used); 789 return ret; 790 } 791 792 static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port, 793 struct ethtool_rx_flow_spec *fs) 794 { 795 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 796 s8 cpu_port = ds->ports[port].cpu_dp->index; 797 __u64 ring_cookie = fs->ring_cookie; 798 unsigned int queue_num, port_num; 799 int ret; 800 801 /* This rule is a Wake-on-LAN filter and we must specifically 802 * target the CPU port in order for it to be working. 803 */ 804 if (ring_cookie == RX_CLS_FLOW_WAKE) 805 ring_cookie = cpu_port * SF2_NUM_EGRESS_QUEUES; 806 807 /* We do not support discarding packets, check that the 808 * destination port is enabled and that we are within the 809 * number of ports supported by the switch 810 */ 811 port_num = ring_cookie / SF2_NUM_EGRESS_QUEUES; 812 813 if (ring_cookie == RX_CLS_FLOW_DISC || 814 !(dsa_is_user_port(ds, port_num) || 815 dsa_is_cpu_port(ds, port_num)) || 816 port_num >= priv->hw_params.num_ports) 817 return -EINVAL; 818 /* 819 * We have a small oddity where Port 6 just does not have a 820 * valid bit here (so we substract by one). 821 */ 822 queue_num = ring_cookie % SF2_NUM_EGRESS_QUEUES; 823 if (port_num >= 7) 824 port_num -= 1; 825 826 switch (fs->flow_type & ~FLOW_EXT) { 827 case TCP_V4_FLOW: 828 case UDP_V4_FLOW: 829 ret = bcm_sf2_cfp_ipv4_rule_set(priv, port, port_num, 830 queue_num, fs); 831 break; 832 case TCP_V6_FLOW: 833 case UDP_V6_FLOW: 834 ret = bcm_sf2_cfp_ipv6_rule_set(priv, port, port_num, 835 queue_num, fs); 836 break; 837 default: 838 ret = -EINVAL; 839 break; 840 } 841 842 return ret; 843 } 844 845 static int bcm_sf2_cfp_rule_set(struct dsa_switch *ds, int port, 846 struct ethtool_rx_flow_spec *fs) 847 { 848 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 849 struct cfp_rule *rule = NULL; 850 int ret = -EINVAL; 851 852 /* Check for unsupported extensions */ 853 if ((fs->flow_type & FLOW_EXT) && (fs->m_ext.vlan_etype || 854 fs->m_ext.data[1])) 855 return -EINVAL; 856 857 if (fs->location != RX_CLS_LOC_ANY && 858 test_bit(fs->location, priv->cfp.used)) 859 return -EBUSY; 860 861 if (fs->location != RX_CLS_LOC_ANY && 862 fs->location > bcm_sf2_cfp_rule_size(priv)) 863 return -EINVAL; 864 865 ret = bcm_sf2_cfp_rule_cmp(priv, port, fs); 866 if (ret == 0) 867 return -EEXIST; 868 869 rule = kzalloc(sizeof(*rule), GFP_KERNEL); 870 if (!rule) 871 return -ENOMEM; 872 873 ret = bcm_sf2_cfp_rule_insert(ds, port, fs); 874 if (ret) { 875 kfree(rule); 876 return ret; 877 } 878 879 rule->port = port; 880 memcpy(&rule->fs, fs, sizeof(*fs)); 881 list_add_tail(&rule->next, &priv->cfp.rules_list); 882 883 return ret; 884 } 885 886 static int bcm_sf2_cfp_rule_del_one(struct bcm_sf2_priv *priv, int port, 887 u32 loc, u32 *next_loc) 888 { 889 int ret; 890 u32 reg; 891 892 /* Indicate which rule we want to read */ 893 bcm_sf2_cfp_rule_addr_set(priv, loc); 894 895 ret = bcm_sf2_cfp_op(priv, OP_SEL_READ | TCAM_SEL); 896 if (ret) 897 return ret; 898 899 /* Check if this is possibly an IPv6 rule that would 900 * indicate we need to delete its companion rule 901 * as well 902 */ 903 reg = core_readl(priv, CORE_CFP_DATA_PORT(6)); 904 if (next_loc) 905 *next_loc = (reg >> 24) & CHAIN_ID_MASK; 906 907 /* Clear its valid bits */ 908 reg = core_readl(priv, CORE_CFP_DATA_PORT(0)); 909 reg &= ~SLICE_VALID; 910 core_writel(priv, reg, CORE_CFP_DATA_PORT(0)); 911 912 /* Write back this entry into the TCAM now */ 913 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL); 914 if (ret) 915 return ret; 916 917 clear_bit(loc, priv->cfp.used); 918 clear_bit(loc, priv->cfp.unique); 919 920 return 0; 921 } 922 923 static int bcm_sf2_cfp_rule_remove(struct bcm_sf2_priv *priv, int port, 924 u32 loc) 925 { 926 u32 next_loc = 0; 927 int ret; 928 929 ret = bcm_sf2_cfp_rule_del_one(priv, port, loc, &next_loc); 930 if (ret) 931 return ret; 932 933 /* If this was an IPv6 rule, delete is companion rule too */ 934 if (next_loc) 935 ret = bcm_sf2_cfp_rule_del_one(priv, port, next_loc, NULL); 936 937 return ret; 938 } 939 940 static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, int port, u32 loc) 941 { 942 struct cfp_rule *rule; 943 int ret; 944 945 /* Refuse deleting unused rules, and those that are not unique since 946 * that could leave IPv6 rules with one of the chained rule in the 947 * table. 948 */ 949 if (!test_bit(loc, priv->cfp.unique) || loc == 0) 950 return -EINVAL; 951 952 rule = bcm_sf2_cfp_rule_find(priv, port, loc); 953 if (!rule) 954 return -EINVAL; 955 956 ret = bcm_sf2_cfp_rule_remove(priv, port, loc); 957 958 list_del(&rule->next); 959 kfree(rule); 960 961 return ret; 962 } 963 964 static void bcm_sf2_invert_masks(struct ethtool_rx_flow_spec *flow) 965 { 966 unsigned int i; 967 968 for (i = 0; i < sizeof(flow->m_u); i++) 969 flow->m_u.hdata[i] ^= 0xff; 970 971 flow->m_ext.vlan_etype ^= cpu_to_be16(~0); 972 flow->m_ext.vlan_tci ^= cpu_to_be16(~0); 973 flow->m_ext.data[0] ^= cpu_to_be32(~0); 974 flow->m_ext.data[1] ^= cpu_to_be32(~0); 975 } 976 977 static int bcm_sf2_cfp_rule_get(struct bcm_sf2_priv *priv, int port, 978 struct ethtool_rxnfc *nfc) 979 { 980 struct cfp_rule *rule; 981 982 rule = bcm_sf2_cfp_rule_find(priv, port, nfc->fs.location); 983 if (!rule) 984 return -EINVAL; 985 986 memcpy(&nfc->fs, &rule->fs, sizeof(rule->fs)); 987 988 bcm_sf2_invert_masks(&nfc->fs); 989 990 /* Put the TCAM size here */ 991 nfc->data = bcm_sf2_cfp_rule_size(priv); 992 993 return 0; 994 } 995 996 /* We implement the search doing a TCAM search operation */ 997 static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv, 998 int port, struct ethtool_rxnfc *nfc, 999 u32 *rule_locs) 1000 { 1001 unsigned int index = 1, rules_cnt = 0; 1002 1003 for_each_set_bit_from(index, priv->cfp.unique, priv->num_cfp_rules) { 1004 rule_locs[rules_cnt] = index; 1005 rules_cnt++; 1006 } 1007 1008 /* Put the TCAM size here */ 1009 nfc->data = bcm_sf2_cfp_rule_size(priv); 1010 nfc->rule_cnt = rules_cnt; 1011 1012 return 0; 1013 } 1014 1015 int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port, 1016 struct ethtool_rxnfc *nfc, u32 *rule_locs) 1017 { 1018 struct net_device *p = ds->ports[port].cpu_dp->master; 1019 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 1020 int ret = 0; 1021 1022 mutex_lock(&priv->cfp.lock); 1023 1024 switch (nfc->cmd) { 1025 case ETHTOOL_GRXCLSRLCNT: 1026 /* Subtract the default, unusable rule */ 1027 nfc->rule_cnt = bitmap_weight(priv->cfp.unique, 1028 priv->num_cfp_rules) - 1; 1029 /* We support specifying rule locations */ 1030 nfc->data |= RX_CLS_LOC_SPECIAL; 1031 break; 1032 case ETHTOOL_GRXCLSRULE: 1033 ret = bcm_sf2_cfp_rule_get(priv, port, nfc); 1034 break; 1035 case ETHTOOL_GRXCLSRLALL: 1036 ret = bcm_sf2_cfp_rule_get_all(priv, port, nfc, rule_locs); 1037 break; 1038 default: 1039 ret = -EOPNOTSUPP; 1040 break; 1041 } 1042 1043 mutex_unlock(&priv->cfp.lock); 1044 1045 if (ret) 1046 return ret; 1047 1048 /* Pass up the commands to the attached master network device */ 1049 if (p->ethtool_ops->get_rxnfc) { 1050 ret = p->ethtool_ops->get_rxnfc(p, nfc, rule_locs); 1051 if (ret == -EOPNOTSUPP) 1052 ret = 0; 1053 } 1054 1055 return ret; 1056 } 1057 1058 int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port, 1059 struct ethtool_rxnfc *nfc) 1060 { 1061 struct net_device *p = ds->ports[port].cpu_dp->master; 1062 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 1063 int ret = 0; 1064 1065 mutex_lock(&priv->cfp.lock); 1066 1067 switch (nfc->cmd) { 1068 case ETHTOOL_SRXCLSRLINS: 1069 ret = bcm_sf2_cfp_rule_set(ds, port, &nfc->fs); 1070 break; 1071 1072 case ETHTOOL_SRXCLSRLDEL: 1073 ret = bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location); 1074 break; 1075 default: 1076 ret = -EOPNOTSUPP; 1077 break; 1078 } 1079 1080 mutex_unlock(&priv->cfp.lock); 1081 1082 if (ret) 1083 return ret; 1084 1085 /* Pass up the commands to the attached master network device. 1086 * This can fail, so rollback the operation if we need to. 1087 */ 1088 if (p->ethtool_ops->set_rxnfc) { 1089 ret = p->ethtool_ops->set_rxnfc(p, nfc); 1090 if (ret && ret != -EOPNOTSUPP) { 1091 mutex_lock(&priv->cfp.lock); 1092 bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location); 1093 mutex_unlock(&priv->cfp.lock); 1094 } else { 1095 ret = 0; 1096 } 1097 } 1098 1099 return ret; 1100 } 1101 1102 int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv) 1103 { 1104 unsigned int timeout = 1000; 1105 u32 reg; 1106 1107 reg = core_readl(priv, CORE_CFP_ACC); 1108 reg |= TCAM_RESET; 1109 core_writel(priv, reg, CORE_CFP_ACC); 1110 1111 do { 1112 reg = core_readl(priv, CORE_CFP_ACC); 1113 if (!(reg & TCAM_RESET)) 1114 break; 1115 1116 cpu_relax(); 1117 } while (timeout--); 1118 1119 if (!timeout) 1120 return -ETIMEDOUT; 1121 1122 return 0; 1123 } 1124 1125 void bcm_sf2_cfp_exit(struct dsa_switch *ds) 1126 { 1127 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 1128 struct cfp_rule *rule, *n; 1129 1130 if (list_empty(&priv->cfp.rules_list)) 1131 return; 1132 1133 list_for_each_entry_safe_reverse(rule, n, &priv->cfp.rules_list, next) 1134 bcm_sf2_cfp_rule_del(priv, rule->port, rule->fs.location); 1135 } 1136 1137 int bcm_sf2_cfp_resume(struct dsa_switch *ds) 1138 { 1139 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 1140 struct cfp_rule *rule; 1141 int ret = 0; 1142 u32 reg; 1143 1144 if (list_empty(&priv->cfp.rules_list)) 1145 return ret; 1146 1147 reg = core_readl(priv, CORE_CFP_CTL_REG); 1148 reg &= ~CFP_EN_MAP_MASK; 1149 core_writel(priv, reg, CORE_CFP_CTL_REG); 1150 1151 ret = bcm_sf2_cfp_rst(priv); 1152 if (ret) 1153 return ret; 1154 1155 list_for_each_entry(rule, &priv->cfp.rules_list, next) { 1156 ret = bcm_sf2_cfp_rule_remove(priv, rule->port, 1157 rule->fs.location); 1158 if (ret) { 1159 dev_err(ds->dev, "failed to remove rule\n"); 1160 return ret; 1161 } 1162 1163 ret = bcm_sf2_cfp_rule_insert(ds, rule->port, &rule->fs); 1164 if (ret) { 1165 dev_err(ds->dev, "failed to restore rule\n"); 1166 return ret; 1167 } 1168 } 1169 1170 return ret; 1171 } 1172