1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2015 - 2024 Beijing WangXun Technology Co., Ltd. */ 3 4 #include <linux/string.h> 5 #include <linux/types.h> 6 #include <linux/pci.h> 7 8 #include "../libwx/wx_type.h" 9 #include "../libwx/wx_lib.h" 10 #include "../libwx/wx_hw.h" 11 #include "txgbe_type.h" 12 #include "txgbe_fdir.h" 13 14 /* These defines allow us to quickly generate all of the necessary instructions 15 * in the function below by simply calling out TXGBE_COMPUTE_SIG_HASH_ITERATION 16 * for values 0 through 15 17 */ 18 #define TXGBE_ATR_COMMON_HASH_KEY \ 19 (TXGBE_ATR_BUCKET_HASH_KEY & TXGBE_ATR_SIGNATURE_HASH_KEY) 20 #define TXGBE_COMPUTE_SIG_HASH_ITERATION(_n) \ 21 do { \ 22 u32 n = (_n); \ 23 if (TXGBE_ATR_COMMON_HASH_KEY & (0x01 << n)) \ 24 common_hash ^= lo_hash_dword >> n; \ 25 else if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ 26 bucket_hash ^= lo_hash_dword >> n; \ 27 else if (TXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << n)) \ 28 sig_hash ^= lo_hash_dword << (16 - n); \ 29 if (TXGBE_ATR_COMMON_HASH_KEY & (0x01 << (n + 16))) \ 30 common_hash ^= hi_hash_dword >> n; \ 31 else if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ 32 bucket_hash ^= hi_hash_dword >> n; \ 33 else if (TXGBE_ATR_SIGNATURE_HASH_KEY & (0x01 << (n + 16))) \ 34 sig_hash ^= hi_hash_dword << (16 - n); \ 35 } while (0) 36 37 /** 38 * txgbe_atr_compute_sig_hash - Compute the signature hash 39 * @input: input bitstream to compute the hash on 40 * @common: compressed common input dword 41 * @hash: pointer to the computed hash 42 * 43 * This function is almost identical to the function above but contains 44 * several optimizations such as unwinding all of the loops, letting the 45 * compiler work out all of the conditional ifs since the keys are static 46 * defines, and computing two keys at once since the hashed dword stream 47 * will be the same for both keys. 48 **/ 49 static void txgbe_atr_compute_sig_hash(union txgbe_atr_hash_dword input, 50 union txgbe_atr_hash_dword common, 51 u32 *hash) 52 { 53 u32 sig_hash = 0, bucket_hash = 0, common_hash = 0; 54 u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; 55 u32 i; 56 57 /* record the flow_vm_vlan bits as they are a key part to the hash */ 58 flow_vm_vlan = ntohl(input.dword); 59 60 /* generate common hash dword */ 61 hi_hash_dword = ntohl(common.dword); 62 63 /* low dword is word swapped version of common */ 64 lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); 65 66 /* apply flow ID/VM pool/VLAN ID bits to hash words */ 67 hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); 68 69 /* Process bits 0 and 16 */ 70 TXGBE_COMPUTE_SIG_HASH_ITERATION(0); 71 72 /* apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to 73 * delay this because bit 0 of the stream should not be processed 74 * so we do not add the VLAN until after bit 0 was processed 75 */ 76 lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); 77 78 /* Process remaining 30 bit of the key */ 79 for (i = 1; i <= 15; i++) 80 TXGBE_COMPUTE_SIG_HASH_ITERATION(i); 81 82 /* combine common_hash result with signature and bucket hashes */ 83 bucket_hash ^= common_hash; 84 bucket_hash &= TXGBE_ATR_HASH_MASK; 85 86 sig_hash ^= common_hash << 16; 87 sig_hash &= TXGBE_ATR_HASH_MASK << 16; 88 89 /* return completed signature hash */ 90 *hash = sig_hash ^ bucket_hash; 91 } 92 93 #define TXGBE_COMPUTE_BKT_HASH_ITERATION(_n) \ 94 do { \ 95 u32 n = (_n); \ 96 if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << n)) \ 97 bucket_hash ^= lo_hash_dword >> n; \ 98 if (TXGBE_ATR_BUCKET_HASH_KEY & (0x01 << (n + 16))) \ 99 bucket_hash ^= hi_hash_dword >> n; \ 100 } while (0) 101 102 /** 103 * txgbe_atr_compute_perfect_hash - Compute the perfect filter hash 104 * @input: input bitstream to compute the hash on 105 * @input_mask: mask for the input bitstream 106 * 107 * This function serves two main purposes. First it applies the input_mask 108 * to the atr_input resulting in a cleaned up atr_input data stream. 109 * Secondly it computes the hash and stores it in the bkt_hash field at 110 * the end of the input byte stream. This way it will be available for 111 * future use without needing to recompute the hash. 112 **/ 113 void txgbe_atr_compute_perfect_hash(union txgbe_atr_input *input, 114 union txgbe_atr_input *input_mask) 115 { 116 u32 hi_hash_dword, lo_hash_dword, flow_vm_vlan; 117 u32 bucket_hash = 0; 118 __be32 hi_dword = 0; 119 u32 i = 0; 120 121 /* Apply masks to input data */ 122 for (i = 0; i < 11; i++) 123 input->dword_stream[i] &= input_mask->dword_stream[i]; 124 125 /* record the flow_vm_vlan bits as they are a key part to the hash */ 126 flow_vm_vlan = ntohl(input->dword_stream[0]); 127 128 /* generate common hash dword */ 129 for (i = 1; i <= 10; i++) 130 hi_dword ^= input->dword_stream[i]; 131 hi_hash_dword = ntohl(hi_dword); 132 133 /* low dword is word swapped version of common */ 134 lo_hash_dword = (hi_hash_dword >> 16) | (hi_hash_dword << 16); 135 136 /* apply flow ID/VM pool/VLAN ID bits to hash words */ 137 hi_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan >> 16); 138 139 /* Process bits 0 and 16 */ 140 TXGBE_COMPUTE_BKT_HASH_ITERATION(0); 141 142 /* apply flow ID/VM pool/VLAN ID bits to lo hash dword, we had to 143 * delay this because bit 0 of the stream should not be processed 144 * so we do not add the VLAN until after bit 0 was processed 145 */ 146 lo_hash_dword ^= flow_vm_vlan ^ (flow_vm_vlan << 16); 147 148 /* Process remaining 30 bit of the key */ 149 for (i = 1; i <= 15; i++) 150 TXGBE_COMPUTE_BKT_HASH_ITERATION(i); 151 152 /* Limit hash to 13 bits since max bucket count is 8K. 153 * Store result at the end of the input stream. 154 */ 155 input->formatted.bkt_hash = (__force __be16)(bucket_hash & 0x1FFF); 156 } 157 158 static int txgbe_fdir_check_cmd_complete(struct wx *wx) 159 { 160 u32 val; 161 162 return read_poll_timeout_atomic(rd32, val, 163 !(val & TXGBE_RDB_FDIR_CMD_CMD_MASK), 164 10, 100, false, 165 wx, TXGBE_RDB_FDIR_CMD); 166 } 167 168 /** 169 * txgbe_fdir_add_signature_filter - Adds a signature hash filter 170 * @wx: pointer to hardware structure 171 * @input: unique input dword 172 * @common: compressed common input dword 173 * @queue: queue index to direct traffic to 174 * 175 * @return: 0 on success and negative on failure 176 **/ 177 static int txgbe_fdir_add_signature_filter(struct wx *wx, 178 union txgbe_atr_hash_dword input, 179 union txgbe_atr_hash_dword common, 180 u8 queue) 181 { 182 u32 fdirhashcmd, fdircmd; 183 u8 flow_type; 184 int err; 185 186 /* Get the flow_type in order to program FDIRCMD properly 187 * lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 188 * fifth is FDIRCMD.TUNNEL_FILTER 189 */ 190 flow_type = input.formatted.flow_type; 191 switch (flow_type) { 192 case TXGBE_ATR_FLOW_TYPE_TCPV4: 193 case TXGBE_ATR_FLOW_TYPE_UDPV4: 194 case TXGBE_ATR_FLOW_TYPE_SCTPV4: 195 case TXGBE_ATR_FLOW_TYPE_TCPV6: 196 case TXGBE_ATR_FLOW_TYPE_UDPV6: 197 case TXGBE_ATR_FLOW_TYPE_SCTPV6: 198 break; 199 default: 200 wx_err(wx, "Error on flow type input\n"); 201 return -EINVAL; 202 } 203 204 /* configure FDIRCMD register */ 205 fdircmd = TXGBE_RDB_FDIR_CMD_CMD_ADD_FLOW | 206 TXGBE_RDB_FDIR_CMD_FILTER_UPDATE | 207 TXGBE_RDB_FDIR_CMD_LAST | TXGBE_RDB_FDIR_CMD_QUEUE_EN; 208 fdircmd |= TXGBE_RDB_FDIR_CMD_FLOW_TYPE(flow_type); 209 fdircmd |= TXGBE_RDB_FDIR_CMD_RX_QUEUE(queue); 210 211 txgbe_atr_compute_sig_hash(input, common, &fdirhashcmd); 212 fdirhashcmd |= TXGBE_RDB_FDIR_HASH_BUCKET_VALID; 213 wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhashcmd); 214 wr32(wx, TXGBE_RDB_FDIR_CMD, fdircmd); 215 216 wx_dbg(wx, "Tx Queue=%x hash=%x\n", queue, (u32)fdirhashcmd); 217 218 err = txgbe_fdir_check_cmd_complete(wx); 219 if (err) 220 wx_err(wx, "Flow Director command did not complete!\n"); 221 222 return err; 223 } 224 225 void txgbe_atr(struct wx_ring *ring, struct wx_tx_buffer *first, u8 ptype) 226 { 227 union txgbe_atr_hash_dword common = { .dword = 0 }; 228 union txgbe_atr_hash_dword input = { .dword = 0 }; 229 struct wx_q_vector *q_vector = ring->q_vector; 230 struct wx_dec_ptype dptype; 231 union network_header { 232 struct ipv6hdr *ipv6; 233 struct iphdr *ipv4; 234 void *raw; 235 } hdr; 236 struct tcphdr *th; 237 238 /* if ring doesn't have a interrupt vector, cannot perform ATR */ 239 if (!q_vector) 240 return; 241 242 ring->atr_count++; 243 dptype = wx_decode_ptype(ptype); 244 if (dptype.etype) { 245 if (WX_PTYPE_TYPL4(ptype) != WX_PTYPE_TYP_TCP) 246 return; 247 hdr.raw = (void *)skb_inner_network_header(first->skb); 248 th = inner_tcp_hdr(first->skb); 249 } else { 250 if (WX_PTYPE_PKT(ptype) != WX_PTYPE_PKT_IP || 251 WX_PTYPE_TYPL4(ptype) != WX_PTYPE_TYP_TCP) 252 return; 253 hdr.raw = (void *)skb_network_header(first->skb); 254 th = tcp_hdr(first->skb); 255 } 256 257 /* skip this packet since it is invalid or the socket is closing */ 258 if (!th || th->fin) 259 return; 260 261 /* sample on all syn packets or once every atr sample count */ 262 if (!th->syn && ring->atr_count < ring->atr_sample_rate) 263 return; 264 265 /* reset sample count */ 266 ring->atr_count = 0; 267 268 /* src and dst are inverted, think how the receiver sees them 269 * 270 * The input is broken into two sections, a non-compressed section 271 * containing vm_pool, vlan_id, and flow_type. The rest of the data 272 * is XORed together and stored in the compressed dword. 273 */ 274 input.formatted.vlan_id = htons((u16)ptype); 275 276 /* since src port and flex bytes occupy the same word XOR them together 277 * and write the value to source port portion of compressed dword 278 */ 279 if (first->tx_flags & WX_TX_FLAGS_SW_VLAN) 280 common.port.src ^= th->dest ^ first->skb->protocol; 281 else if (first->tx_flags & WX_TX_FLAGS_HW_VLAN) 282 common.port.src ^= th->dest ^ first->skb->vlan_proto; 283 else 284 common.port.src ^= th->dest ^ first->protocol; 285 common.port.dst ^= th->source; 286 287 if (WX_PTYPE_PKT_IPV6 & WX_PTYPE_PKT(ptype)) { 288 input.formatted.flow_type = TXGBE_ATR_FLOW_TYPE_TCPV6; 289 common.ip ^= hdr.ipv6->saddr.s6_addr32[0] ^ 290 hdr.ipv6->saddr.s6_addr32[1] ^ 291 hdr.ipv6->saddr.s6_addr32[2] ^ 292 hdr.ipv6->saddr.s6_addr32[3] ^ 293 hdr.ipv6->daddr.s6_addr32[0] ^ 294 hdr.ipv6->daddr.s6_addr32[1] ^ 295 hdr.ipv6->daddr.s6_addr32[2] ^ 296 hdr.ipv6->daddr.s6_addr32[3]; 297 } else { 298 input.formatted.flow_type = TXGBE_ATR_FLOW_TYPE_TCPV4; 299 common.ip ^= hdr.ipv4->saddr ^ hdr.ipv4->daddr; 300 } 301 302 /* This assumes the Rx queue and Tx queue are bound to the same CPU */ 303 txgbe_fdir_add_signature_filter(q_vector->wx, input, common, 304 ring->queue_index); 305 } 306 307 int txgbe_fdir_set_input_mask(struct wx *wx, union txgbe_atr_input *input_mask) 308 { 309 u32 fdirm = 0, fdirtcpm = 0, flex = 0; 310 int index, offset; 311 312 /* Program the relevant mask registers. If src/dst_port or src/dst_addr 313 * are zero, then assume a full mask for that field. Also assume that 314 * a VLAN of 0 is unspecified, so mask that out as well. L4type 315 * cannot be masked out in this implementation. 316 * 317 * This also assumes IPv4 only. IPv6 masking isn't supported at this 318 * point in time. 319 */ 320 321 /* verify bucket hash is cleared on hash generation */ 322 if (input_mask->formatted.bkt_hash) 323 wx_dbg(wx, "bucket hash should always be 0 in mask\n"); 324 325 /* Program FDIRM and verify partial masks */ 326 switch (input_mask->formatted.vm_pool & 0x7F) { 327 case 0x0: 328 fdirm |= TXGBE_RDB_FDIR_OTHER_MSK_POOL; 329 break; 330 case 0x7F: 331 break; 332 default: 333 wx_err(wx, "Error on vm pool mask\n"); 334 return -EINVAL; 335 } 336 337 switch (input_mask->formatted.flow_type & TXGBE_ATR_L4TYPE_MASK) { 338 case 0x0: 339 fdirm |= TXGBE_RDB_FDIR_OTHER_MSK_L4P; 340 if (input_mask->formatted.dst_port || 341 input_mask->formatted.src_port) { 342 wx_err(wx, "Error on src/dst port mask\n"); 343 return -EINVAL; 344 } 345 break; 346 case TXGBE_ATR_L4TYPE_MASK: 347 break; 348 default: 349 wx_err(wx, "Error on flow type mask\n"); 350 return -EINVAL; 351 } 352 353 /* Now mask VM pool and destination IPv6 - bits 5 and 2 */ 354 wr32(wx, TXGBE_RDB_FDIR_OTHER_MSK, fdirm); 355 356 index = VMDQ_P(0) / 4; 357 offset = VMDQ_P(0) % 4; 358 flex = rd32(wx, TXGBE_RDB_FDIR_FLEX_CFG(index)); 359 flex &= ~(TXGBE_RDB_FDIR_FLEX_CFG_FIELD0 << (offset * 8)); 360 flex |= (TXGBE_RDB_FDIR_FLEX_CFG_BASE_MAC | 361 TXGBE_RDB_FDIR_FLEX_CFG_OFST(0x6)) << (offset * 8); 362 363 switch ((__force u16)input_mask->formatted.flex_bytes & 0xFFFF) { 364 case 0x0000: 365 /* Mask Flex Bytes */ 366 flex |= TXGBE_RDB_FDIR_FLEX_CFG_MSK << (offset * 8); 367 break; 368 case 0xFFFF: 369 break; 370 default: 371 wx_err(wx, "Error on flexible byte mask\n"); 372 return -EINVAL; 373 } 374 wr32(wx, TXGBE_RDB_FDIR_FLEX_CFG(index), flex); 375 376 /* store the TCP/UDP port masks, bit reversed from port layout */ 377 fdirtcpm = ntohs(input_mask->formatted.dst_port); 378 fdirtcpm <<= TXGBE_RDB_FDIR_PORT_DESTINATION_SHIFT; 379 fdirtcpm |= ntohs(input_mask->formatted.src_port); 380 381 /* write both the same so that UDP and TCP use the same mask */ 382 wr32(wx, TXGBE_RDB_FDIR_TCP_MSK, ~fdirtcpm); 383 wr32(wx, TXGBE_RDB_FDIR_UDP_MSK, ~fdirtcpm); 384 wr32(wx, TXGBE_RDB_FDIR_SCTP_MSK, ~fdirtcpm); 385 386 /* store source and destination IP masks (little-enian) */ 387 wr32(wx, TXGBE_RDB_FDIR_SA4_MSK, 388 ntohl(~input_mask->formatted.src_ip[0])); 389 wr32(wx, TXGBE_RDB_FDIR_DA4_MSK, 390 ntohl(~input_mask->formatted.dst_ip[0])); 391 392 return 0; 393 } 394 395 int txgbe_fdir_write_perfect_filter(struct wx *wx, 396 union txgbe_atr_input *input, 397 u16 soft_id, u8 queue) 398 { 399 u32 fdirport, fdirvlan, fdirhash, fdircmd; 400 int err = 0; 401 402 /* currently IPv6 is not supported, must be programmed with 0 */ 403 wr32(wx, TXGBE_RDB_FDIR_IP6(2), ntohl(input->formatted.src_ip[0])); 404 wr32(wx, TXGBE_RDB_FDIR_IP6(1), ntohl(input->formatted.src_ip[1])); 405 wr32(wx, TXGBE_RDB_FDIR_IP6(0), ntohl(input->formatted.src_ip[2])); 406 407 /* record the source address (little-endian) */ 408 wr32(wx, TXGBE_RDB_FDIR_SA, ntohl(input->formatted.src_ip[0])); 409 410 /* record the first 32 bits of the destination address 411 * (little-endian) 412 */ 413 wr32(wx, TXGBE_RDB_FDIR_DA, ntohl(input->formatted.dst_ip[0])); 414 415 /* record source and destination port (little-endian)*/ 416 fdirport = ntohs(input->formatted.dst_port); 417 fdirport <<= TXGBE_RDB_FDIR_PORT_DESTINATION_SHIFT; 418 fdirport |= ntohs(input->formatted.src_port); 419 wr32(wx, TXGBE_RDB_FDIR_PORT, fdirport); 420 421 /* record packet type and flex_bytes (little-endian) */ 422 fdirvlan = ntohs(input->formatted.flex_bytes); 423 fdirvlan <<= TXGBE_RDB_FDIR_FLEX_FLEX_SHIFT; 424 fdirvlan |= ntohs(input->formatted.vlan_id); 425 wr32(wx, TXGBE_RDB_FDIR_FLEX, fdirvlan); 426 427 /* configure FDIRHASH register */ 428 fdirhash = (__force u32)input->formatted.bkt_hash | 429 TXGBE_RDB_FDIR_HASH_BUCKET_VALID | 430 TXGBE_RDB_FDIR_HASH_SIG_SW_INDEX(soft_id); 431 wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhash); 432 433 /* flush all previous writes to make certain registers are 434 * programmed prior to issuing the command 435 */ 436 WX_WRITE_FLUSH(wx); 437 438 /* configure FDIRCMD register */ 439 fdircmd = TXGBE_RDB_FDIR_CMD_CMD_ADD_FLOW | 440 TXGBE_RDB_FDIR_CMD_FILTER_UPDATE | 441 TXGBE_RDB_FDIR_CMD_LAST | TXGBE_RDB_FDIR_CMD_QUEUE_EN; 442 if (queue == TXGBE_RDB_FDIR_DROP_QUEUE) 443 fdircmd |= TXGBE_RDB_FDIR_CMD_DROP; 444 fdircmd |= TXGBE_RDB_FDIR_CMD_FLOW_TYPE(input->formatted.flow_type); 445 fdircmd |= TXGBE_RDB_FDIR_CMD_RX_QUEUE(queue); 446 fdircmd |= TXGBE_RDB_FDIR_CMD_VT_POOL(input->formatted.vm_pool); 447 448 wr32(wx, TXGBE_RDB_FDIR_CMD, fdircmd); 449 err = txgbe_fdir_check_cmd_complete(wx); 450 if (err) 451 wx_err(wx, "Flow Director command did not complete!\n"); 452 453 return err; 454 } 455 456 int txgbe_fdir_erase_perfect_filter(struct wx *wx, 457 union txgbe_atr_input *input, 458 u16 soft_id) 459 { 460 u32 fdirhash, fdircmd; 461 int err = 0; 462 463 /* configure FDIRHASH register */ 464 fdirhash = (__force u32)input->formatted.bkt_hash; 465 fdirhash |= TXGBE_RDB_FDIR_HASH_SIG_SW_INDEX(soft_id); 466 wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhash); 467 468 /* flush hash to HW */ 469 WX_WRITE_FLUSH(wx); 470 471 /* Query if filter is present */ 472 wr32(wx, TXGBE_RDB_FDIR_CMD, TXGBE_RDB_FDIR_CMD_CMD_QUERY_REM_FILT); 473 474 err = txgbe_fdir_check_cmd_complete(wx); 475 if (err) { 476 wx_err(wx, "Flow Director command did not complete!\n"); 477 return err; 478 } 479 480 fdircmd = rd32(wx, TXGBE_RDB_FDIR_CMD); 481 /* if filter exists in hardware then remove it */ 482 if (fdircmd & TXGBE_RDB_FDIR_CMD_FILTER_VALID) { 483 wr32(wx, TXGBE_RDB_FDIR_HASH, fdirhash); 484 WX_WRITE_FLUSH(wx); 485 wr32(wx, TXGBE_RDB_FDIR_CMD, 486 TXGBE_RDB_FDIR_CMD_CMD_REMOVE_FLOW); 487 } 488 489 return 0; 490 } 491 492 /** 493 * txgbe_fdir_enable - Initialize Flow Director control registers 494 * @wx: pointer to hardware structure 495 * @fdirctrl: value to write to flow director control register 496 **/ 497 static void txgbe_fdir_enable(struct wx *wx, u32 fdirctrl) 498 { 499 u32 val; 500 int ret; 501 502 /* Prime the keys for hashing */ 503 wr32(wx, TXGBE_RDB_FDIR_HKEY, TXGBE_ATR_BUCKET_HASH_KEY); 504 wr32(wx, TXGBE_RDB_FDIR_SKEY, TXGBE_ATR_SIGNATURE_HASH_KEY); 505 506 wr32(wx, TXGBE_RDB_FDIR_CTL, fdirctrl); 507 WX_WRITE_FLUSH(wx); 508 ret = read_poll_timeout(rd32, val, val & TXGBE_RDB_FDIR_CTL_INIT_DONE, 509 1000, 10000, false, wx, TXGBE_RDB_FDIR_CTL); 510 511 if (ret < 0) 512 wx_dbg(wx, "Flow Director poll time exceeded!\n"); 513 } 514 515 /** 516 * txgbe_init_fdir_signature -Initialize Flow Director sig filters 517 * @wx: pointer to hardware structure 518 **/ 519 static void txgbe_init_fdir_signature(struct wx *wx) 520 { 521 u32 fdirctrl = TXGBE_FDIR_PBALLOC_64K; 522 int index = VMDQ_P(0) / 4; 523 int offset = VMDQ_P(0) % 4; 524 u32 flex = 0; 525 526 flex = rd32(wx, TXGBE_RDB_FDIR_FLEX_CFG(index)); 527 flex &= ~(TXGBE_RDB_FDIR_FLEX_CFG_FIELD0 << (offset * 8)); 528 529 flex |= (TXGBE_RDB_FDIR_FLEX_CFG_BASE_MAC | 530 TXGBE_RDB_FDIR_FLEX_CFG_OFST(0x6)) << (offset * 8); 531 wr32(wx, TXGBE_RDB_FDIR_FLEX_CFG(index), flex); 532 533 /* Continue setup of fdirctrl register bits: 534 * Move the flexible bytes to use the ethertype - shift 6 words 535 * Set the maximum length per hash bucket to 0xA filters 536 * Send interrupt when 64 filters are left 537 */ 538 fdirctrl |= TXGBE_RDB_FDIR_CTL_HASH_BITS(0xF) | 539 TXGBE_RDB_FDIR_CTL_MAX_LENGTH(0xA) | 540 TXGBE_RDB_FDIR_CTL_FULL_THRESH(4); 541 542 /* write hashes and fdirctrl register, poll for completion */ 543 txgbe_fdir_enable(wx, fdirctrl); 544 } 545 546 /** 547 * txgbe_init_fdir_perfect - Initialize Flow Director perfect filters 548 * @wx: pointer to hardware structure 549 **/ 550 static void txgbe_init_fdir_perfect(struct wx *wx) 551 { 552 u32 fdirctrl = TXGBE_FDIR_PBALLOC_64K; 553 554 /* Continue setup of fdirctrl register bits: 555 * Turn perfect match filtering on 556 * Report hash in RSS field of Rx wb descriptor 557 * Initialize the drop queue 558 * Move the flexible bytes to use the ethertype - shift 6 words 559 * Set the maximum length per hash bucket to 0xA filters 560 * Send interrupt when 64 (0x4 * 16) filters are left 561 */ 562 fdirctrl |= TXGBE_RDB_FDIR_CTL_PERFECT_MATCH | 563 TXGBE_RDB_FDIR_CTL_DROP_Q(TXGBE_RDB_FDIR_DROP_QUEUE) | 564 TXGBE_RDB_FDIR_CTL_HASH_BITS(0xF) | 565 TXGBE_RDB_FDIR_CTL_MAX_LENGTH(0xA) | 566 TXGBE_RDB_FDIR_CTL_FULL_THRESH(4); 567 568 /* write hashes and fdirctrl register, poll for completion */ 569 txgbe_fdir_enable(wx, fdirctrl); 570 } 571 572 static void txgbe_fdir_filter_restore(struct wx *wx) 573 { 574 struct txgbe_fdir_filter *filter; 575 struct txgbe *txgbe = wx->priv; 576 struct hlist_node *node; 577 u8 queue = 0; 578 int ret = 0; 579 580 spin_lock(&txgbe->fdir_perfect_lock); 581 582 if (!hlist_empty(&txgbe->fdir_filter_list)) 583 ret = txgbe_fdir_set_input_mask(wx, &txgbe->fdir_mask); 584 585 if (ret) 586 goto unlock; 587 588 hlist_for_each_entry_safe(filter, node, 589 &txgbe->fdir_filter_list, fdir_node) { 590 if (filter->action == TXGBE_RDB_FDIR_DROP_QUEUE) { 591 queue = TXGBE_RDB_FDIR_DROP_QUEUE; 592 } else { 593 u32 ring = ethtool_get_flow_spec_ring(filter->action); 594 595 if (ring >= wx->num_rx_queues) { 596 wx_err(wx, "FDIR restore failed, ring:%u\n", 597 ring); 598 continue; 599 } 600 601 /* Map the ring onto the absolute queue index */ 602 queue = wx->rx_ring[ring]->reg_idx; 603 } 604 605 ret = txgbe_fdir_write_perfect_filter(wx, 606 &filter->filter, 607 filter->sw_idx, 608 queue); 609 if (ret) 610 wx_err(wx, "FDIR restore failed, index:%u\n", 611 filter->sw_idx); 612 } 613 614 unlock: 615 spin_unlock(&txgbe->fdir_perfect_lock); 616 } 617 618 void txgbe_configure_fdir(struct wx *wx) 619 { 620 wx_disable_sec_rx_path(wx); 621 622 if (test_bit(WX_FLAG_FDIR_HASH, wx->flags)) { 623 txgbe_init_fdir_signature(wx); 624 } else if (test_bit(WX_FLAG_FDIR_PERFECT, wx->flags)) { 625 txgbe_init_fdir_perfect(wx); 626 txgbe_fdir_filter_restore(wx); 627 } 628 629 wx_enable_sec_rx_path(wx); 630 } 631 632 void txgbe_fdir_filter_exit(struct wx *wx) 633 { 634 struct txgbe_fdir_filter *filter; 635 struct txgbe *txgbe = wx->priv; 636 struct hlist_node *node; 637 638 spin_lock(&txgbe->fdir_perfect_lock); 639 640 hlist_for_each_entry_safe(filter, node, 641 &txgbe->fdir_filter_list, fdir_node) { 642 hlist_del(&filter->fdir_node); 643 kfree(filter); 644 } 645 txgbe->fdir_filter_count = 0; 646 647 spin_unlock(&txgbe->fdir_perfect_lock); 648 } 649