1 /*- 2 * Copyright (c) 2007-2016 Solarflare Communications Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * The views and conclusions contained in the software and documentation are 27 * those of the authors and should not be interpreted as representing official 28 * policies, either expressed or implied, of the FreeBSD Project. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include "efx.h" 35 #include "efx_impl.h" 36 37 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD 38 39 #if EFSYS_OPT_FILTER 40 41 #define EFE_SPEC(eftp, index) ((eftp)->eft_entry[(index)].efe_spec) 42 43 static efx_filter_spec_t * 44 ef10_filter_entry_spec( 45 __in const ef10_filter_table_t *eftp, 46 __in unsigned int index) 47 { 48 return ((efx_filter_spec_t *)(EFE_SPEC(eftp, index) & 49 ~(uintptr_t)EFX_EF10_FILTER_FLAGS)); 50 } 51 52 static boolean_t 53 ef10_filter_entry_is_busy( 54 __in const ef10_filter_table_t *eftp, 55 __in unsigned int index) 56 { 57 if (EFE_SPEC(eftp, index) & EFX_EF10_FILTER_FLAG_BUSY) 58 return (B_TRUE); 59 else 60 return (B_FALSE); 61 } 62 63 static boolean_t 64 ef10_filter_entry_is_auto_old( 65 __in const ef10_filter_table_t *eftp, 66 __in unsigned int index) 67 { 68 if (EFE_SPEC(eftp, index) & EFX_EF10_FILTER_FLAG_AUTO_OLD) 69 return (B_TRUE); 70 else 71 return (B_FALSE); 72 } 73 74 static void 75 ef10_filter_set_entry( 76 __inout ef10_filter_table_t *eftp, 77 __in unsigned int index, 78 __in_opt const efx_filter_spec_t *efsp) 79 { 80 EFE_SPEC(eftp, index) = (uintptr_t)efsp; 81 } 82 83 static void 84 ef10_filter_set_entry_busy( 85 __inout ef10_filter_table_t *eftp, 86 __in unsigned int index) 87 { 88 EFE_SPEC(eftp, index) |= (uintptr_t)EFX_EF10_FILTER_FLAG_BUSY; 89 } 90 91 static void 92 ef10_filter_set_entry_not_busy( 93 __inout ef10_filter_table_t *eftp, 94 __in unsigned int index) 95 { 96 EFE_SPEC(eftp, index) &= ~(uintptr_t)EFX_EF10_FILTER_FLAG_BUSY; 97 } 98 99 static void 100 ef10_filter_set_entry_auto_old( 101 __inout ef10_filter_table_t *eftp, 102 __in unsigned int index) 103 { 104 EFSYS_ASSERT(ef10_filter_entry_spec(eftp, index) != NULL); 105 EFE_SPEC(eftp, index) |= (uintptr_t)EFX_EF10_FILTER_FLAG_AUTO_OLD; 106 } 107 108 static void 109 ef10_filter_set_entry_not_auto_old( 110 __inout ef10_filter_table_t *eftp, 111 __in unsigned int index) 112 { 113 EFE_SPEC(eftp, index) &= ~(uintptr_t)EFX_EF10_FILTER_FLAG_AUTO_OLD; 114 EFSYS_ASSERT(ef10_filter_entry_spec(eftp, index) != NULL); 115 } 116 117 __checkReturn efx_rc_t 118 ef10_filter_init( 119 __in efx_nic_t *enp) 120 { 121 efx_rc_t rc; 122 ef10_filter_table_t *eftp; 123 124 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 125 enp->en_family == EFX_FAMILY_MEDFORD); 126 127 #define MATCH_MASK(match) (EFX_MASK32(match) << EFX_LOW_BIT(match)) 128 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_HOST == 129 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_SRC_IP)); 130 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_HOST == 131 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_DST_IP)); 132 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_MAC == 133 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_SRC_MAC)); 134 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_PORT == 135 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_SRC_PORT)); 136 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_MAC == 137 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_DST_MAC)); 138 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_PORT == 139 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_DST_PORT)); 140 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_ETHER_TYPE == 141 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_ETHER_TYPE)); 142 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_INNER_VID == 143 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_INNER_VLAN)); 144 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_OUTER_VID == 145 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_OUTER_VLAN)); 146 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO == 147 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_IP_PROTO)); 148 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_UNKNOWN_MCAST_DST == 149 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_MCAST_DST)); 150 EFX_STATIC_ASSERT((uint32_t)EFX_FILTER_MATCH_UNKNOWN_UCAST_DST == 151 MATCH_MASK(MC_CMD_FILTER_OP_IN_MATCH_UNKNOWN_UCAST_DST)); 152 #undef MATCH_MASK 153 154 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (ef10_filter_table_t), eftp); 155 156 if (!eftp) { 157 rc = ENOMEM; 158 goto fail1; 159 } 160 161 enp->en_filter.ef_ef10_filter_table = eftp; 162 163 return (0); 164 165 fail1: 166 EFSYS_PROBE1(fail1, efx_rc_t, rc); 167 168 return (rc); 169 } 170 171 void 172 ef10_filter_fini( 173 __in efx_nic_t *enp) 174 { 175 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 176 enp->en_family == EFX_FAMILY_MEDFORD); 177 178 if (enp->en_filter.ef_ef10_filter_table != NULL) { 179 EFSYS_KMEM_FREE(enp->en_esip, sizeof (ef10_filter_table_t), 180 enp->en_filter.ef_ef10_filter_table); 181 } 182 } 183 184 static __checkReturn efx_rc_t 185 efx_mcdi_filter_op_add( 186 __in efx_nic_t *enp, 187 __in efx_filter_spec_t *spec, 188 __in unsigned int filter_op, 189 __inout ef10_filter_handle_t *handle) 190 { 191 efx_mcdi_req_t req; 192 uint8_t payload[MAX(MC_CMD_FILTER_OP_IN_LEN, 193 MC_CMD_FILTER_OP_OUT_LEN)]; 194 efx_rc_t rc; 195 196 memset(payload, 0, sizeof (payload)); 197 req.emr_cmd = MC_CMD_FILTER_OP; 198 req.emr_in_buf = payload; 199 req.emr_in_length = MC_CMD_FILTER_OP_IN_LEN; 200 req.emr_out_buf = payload; 201 req.emr_out_length = MC_CMD_FILTER_OP_OUT_LEN; 202 203 switch (filter_op) { 204 case MC_CMD_FILTER_OP_IN_OP_REPLACE: 205 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_HANDLE_LO, 206 handle->efh_lo); 207 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_HANDLE_HI, 208 handle->efh_hi); 209 /* Fall through */ 210 case MC_CMD_FILTER_OP_IN_OP_INSERT: 211 case MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE: 212 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_OP, filter_op); 213 break; 214 default: 215 EFSYS_ASSERT(0); 216 rc = EINVAL; 217 goto fail1; 218 } 219 220 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_PORT_ID, 221 EVB_PORT_ID_ASSIGNED); 222 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_MATCH_FIELDS, 223 spec->efs_match_flags); 224 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_RX_DEST, 225 MC_CMD_FILTER_OP_IN_RX_DEST_HOST); 226 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_RX_QUEUE, 227 spec->efs_dmaq_id); 228 if (spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) { 229 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_RX_CONTEXT, 230 spec->efs_rss_context); 231 } 232 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_RX_MODE, 233 spec->efs_flags & EFX_FILTER_FLAG_RX_RSS ? 234 MC_CMD_FILTER_OP_IN_RX_MODE_RSS : 235 MC_CMD_FILTER_OP_IN_RX_MODE_SIMPLE); 236 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_TX_DEST, 237 MC_CMD_FILTER_OP_IN_TX_DEST_DEFAULT); 238 239 if (filter_op != MC_CMD_FILTER_OP_IN_OP_REPLACE) { 240 /* 241 * NOTE: Unlike most MCDI requests, the filter fields 242 * are presented in network (big endian) byte order. 243 */ 244 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_IN_SRC_MAC), 245 spec->efs_rem_mac, EFX_MAC_ADDR_LEN); 246 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_IN_DST_MAC), 247 spec->efs_loc_mac, EFX_MAC_ADDR_LEN); 248 249 MCDI_IN_SET_WORD(req, FILTER_OP_IN_SRC_PORT, 250 __CPU_TO_BE_16(spec->efs_rem_port)); 251 MCDI_IN_SET_WORD(req, FILTER_OP_IN_DST_PORT, 252 __CPU_TO_BE_16(spec->efs_loc_port)); 253 254 MCDI_IN_SET_WORD(req, FILTER_OP_IN_ETHER_TYPE, 255 __CPU_TO_BE_16(spec->efs_ether_type)); 256 257 MCDI_IN_SET_WORD(req, FILTER_OP_IN_INNER_VLAN, 258 __CPU_TO_BE_16(spec->efs_inner_vid)); 259 MCDI_IN_SET_WORD(req, FILTER_OP_IN_OUTER_VLAN, 260 __CPU_TO_BE_16(spec->efs_outer_vid)); 261 262 /* IP protocol (in low byte, high byte is zero) */ 263 MCDI_IN_SET_BYTE(req, FILTER_OP_IN_IP_PROTO, 264 spec->efs_ip_proto); 265 266 EFX_STATIC_ASSERT(sizeof (spec->efs_rem_host) == 267 MC_CMD_FILTER_OP_IN_SRC_IP_LEN); 268 EFX_STATIC_ASSERT(sizeof (spec->efs_loc_host) == 269 MC_CMD_FILTER_OP_IN_DST_IP_LEN); 270 271 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_IN_SRC_IP), 272 &spec->efs_rem_host.eo_byte[0], 273 MC_CMD_FILTER_OP_IN_SRC_IP_LEN); 274 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_IN_DST_IP), 275 &spec->efs_loc_host.eo_byte[0], 276 MC_CMD_FILTER_OP_IN_DST_IP_LEN); 277 } 278 279 efx_mcdi_execute(enp, &req); 280 281 if (req.emr_rc != 0) { 282 rc = req.emr_rc; 283 goto fail2; 284 } 285 286 if (req.emr_out_length_used < MC_CMD_FILTER_OP_OUT_LEN) { 287 rc = EMSGSIZE; 288 goto fail3; 289 } 290 291 handle->efh_lo = MCDI_OUT_DWORD(req, FILTER_OP_OUT_HANDLE_LO); 292 handle->efh_hi = MCDI_OUT_DWORD(req, FILTER_OP_OUT_HANDLE_HI); 293 294 return (0); 295 296 fail3: 297 EFSYS_PROBE(fail3); 298 fail2: 299 EFSYS_PROBE(fail2); 300 fail1: 301 EFSYS_PROBE1(fail1, efx_rc_t, rc); 302 303 return (rc); 304 305 } 306 307 static __checkReturn efx_rc_t 308 efx_mcdi_filter_op_delete( 309 __in efx_nic_t *enp, 310 __in unsigned int filter_op, 311 __inout ef10_filter_handle_t *handle) 312 { 313 efx_mcdi_req_t req; 314 uint8_t payload[MAX(MC_CMD_FILTER_OP_IN_LEN, 315 MC_CMD_FILTER_OP_OUT_LEN)]; 316 efx_rc_t rc; 317 318 memset(payload, 0, sizeof (payload)); 319 req.emr_cmd = MC_CMD_FILTER_OP; 320 req.emr_in_buf = payload; 321 req.emr_in_length = MC_CMD_FILTER_OP_IN_LEN; 322 req.emr_out_buf = payload; 323 req.emr_out_length = MC_CMD_FILTER_OP_OUT_LEN; 324 325 switch (filter_op) { 326 case MC_CMD_FILTER_OP_IN_OP_REMOVE: 327 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_OP, 328 MC_CMD_FILTER_OP_IN_OP_REMOVE); 329 break; 330 case MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE: 331 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_OP, 332 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE); 333 break; 334 default: 335 EFSYS_ASSERT(0); 336 rc = EINVAL; 337 goto fail1; 338 } 339 340 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_HANDLE_LO, handle->efh_lo); 341 MCDI_IN_SET_DWORD(req, FILTER_OP_IN_HANDLE_HI, handle->efh_hi); 342 343 efx_mcdi_execute_quiet(enp, &req); 344 345 if (req.emr_rc != 0) { 346 rc = req.emr_rc; 347 goto fail2; 348 } 349 350 if (req.emr_out_length_used < MC_CMD_FILTER_OP_OUT_LEN) { 351 rc = EMSGSIZE; 352 goto fail3; 353 } 354 355 return (0); 356 357 fail3: 358 EFSYS_PROBE(fail3); 359 360 fail2: 361 EFSYS_PROBE(fail2); 362 fail1: 363 EFSYS_PROBE1(fail1, efx_rc_t, rc); 364 365 return (rc); 366 } 367 368 static __checkReturn boolean_t 369 ef10_filter_equal( 370 __in const efx_filter_spec_t *left, 371 __in const efx_filter_spec_t *right) 372 { 373 /* FIXME: Consider rx vs tx filters (look at efs_flags) */ 374 if (left->efs_match_flags != right->efs_match_flags) 375 return (B_FALSE); 376 if (!EFX_OWORD_IS_EQUAL(left->efs_rem_host, right->efs_rem_host)) 377 return (B_FALSE); 378 if (!EFX_OWORD_IS_EQUAL(left->efs_loc_host, right->efs_loc_host)) 379 return (B_FALSE); 380 if (memcmp(left->efs_rem_mac, right->efs_rem_mac, EFX_MAC_ADDR_LEN)) 381 return (B_FALSE); 382 if (memcmp(left->efs_loc_mac, right->efs_loc_mac, EFX_MAC_ADDR_LEN)) 383 return (B_FALSE); 384 if (left->efs_rem_port != right->efs_rem_port) 385 return (B_FALSE); 386 if (left->efs_loc_port != right->efs_loc_port) 387 return (B_FALSE); 388 if (left->efs_inner_vid != right->efs_inner_vid) 389 return (B_FALSE); 390 if (left->efs_outer_vid != right->efs_outer_vid) 391 return (B_FALSE); 392 if (left->efs_ether_type != right->efs_ether_type) 393 return (B_FALSE); 394 if (left->efs_ip_proto != right->efs_ip_proto) 395 return (B_FALSE); 396 397 return (B_TRUE); 398 399 } 400 401 static __checkReturn boolean_t 402 ef10_filter_same_dest( 403 __in const efx_filter_spec_t *left, 404 __in const efx_filter_spec_t *right) 405 { 406 if ((left->efs_flags & EFX_FILTER_FLAG_RX_RSS) && 407 (right->efs_flags & EFX_FILTER_FLAG_RX_RSS)) { 408 if (left->efs_rss_context == right->efs_rss_context) 409 return (B_TRUE); 410 } else if ((~(left->efs_flags) & EFX_FILTER_FLAG_RX_RSS) && 411 (~(right->efs_flags) & EFX_FILTER_FLAG_RX_RSS)) { 412 if (left->efs_dmaq_id == right->efs_dmaq_id) 413 return (B_TRUE); 414 } 415 return (B_FALSE); 416 } 417 418 static __checkReturn uint32_t 419 ef10_filter_hash( 420 __in efx_filter_spec_t *spec) 421 { 422 EFX_STATIC_ASSERT((sizeof (efx_filter_spec_t) % sizeof (uint32_t)) 423 == 0); 424 EFX_STATIC_ASSERT((EFX_FIELD_OFFSET(efx_filter_spec_t, efs_outer_vid) % 425 sizeof (uint32_t)) == 0); 426 427 /* 428 * As the area of the efx_filter_spec_t we need to hash is DWORD 429 * aligned and an exact number of DWORDs in size we can use the 430 * optimised efx_hash_dwords() rather than efx_hash_bytes() 431 */ 432 return (efx_hash_dwords((const uint32_t *)&spec->efs_outer_vid, 433 (sizeof (efx_filter_spec_t) - 434 EFX_FIELD_OFFSET(efx_filter_spec_t, efs_outer_vid)) / 435 sizeof (uint32_t), 0)); 436 } 437 438 /* 439 * Decide whether a filter should be exclusive or else should allow 440 * delivery to additional recipients. Currently we decide that 441 * filters for specific local unicast MAC and IP addresses are 442 * exclusive. 443 */ 444 static __checkReturn boolean_t 445 ef10_filter_is_exclusive( 446 __in efx_filter_spec_t *spec) 447 { 448 if ((spec->efs_match_flags & EFX_FILTER_MATCH_LOC_MAC) && 449 !EFX_MAC_ADDR_IS_MULTICAST(spec->efs_loc_mac)) 450 return (B_TRUE); 451 452 if ((spec->efs_match_flags & 453 (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) == 454 (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) { 455 if ((spec->efs_ether_type == EFX_ETHER_TYPE_IPV4) && 456 ((spec->efs_loc_host.eo_u8[0] & 0xf) != 0xe)) 457 return (B_TRUE); 458 if ((spec->efs_ether_type == EFX_ETHER_TYPE_IPV6) && 459 (spec->efs_loc_host.eo_u8[0] != 0xff)) 460 return (B_TRUE); 461 } 462 463 return (B_FALSE); 464 } 465 466 __checkReturn efx_rc_t 467 ef10_filter_restore( 468 __in efx_nic_t *enp) 469 { 470 int tbl_id; 471 efx_filter_spec_t *spec; 472 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 473 boolean_t restoring; 474 efsys_lock_state_t state; 475 efx_rc_t rc; 476 477 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 478 enp->en_family == EFX_FAMILY_MEDFORD); 479 480 for (tbl_id = 0; tbl_id < EFX_EF10_FILTER_TBL_ROWS; tbl_id++) { 481 482 EFSYS_LOCK(enp->en_eslp, state); 483 484 spec = ef10_filter_entry_spec(eftp, tbl_id); 485 if (spec == NULL) { 486 restoring = B_FALSE; 487 } else if (ef10_filter_entry_is_busy(eftp, tbl_id)) { 488 /* Ignore busy entries. */ 489 restoring = B_FALSE; 490 } else { 491 ef10_filter_set_entry_busy(eftp, tbl_id); 492 restoring = B_TRUE; 493 } 494 495 EFSYS_UNLOCK(enp->en_eslp, state); 496 497 if (restoring == B_FALSE) 498 continue; 499 500 if (ef10_filter_is_exclusive(spec)) { 501 rc = efx_mcdi_filter_op_add(enp, spec, 502 MC_CMD_FILTER_OP_IN_OP_INSERT, 503 &eftp->eft_entry[tbl_id].efe_handle); 504 } else { 505 rc = efx_mcdi_filter_op_add(enp, spec, 506 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE, 507 &eftp->eft_entry[tbl_id].efe_handle); 508 } 509 510 if (rc != 0) 511 goto fail1; 512 513 EFSYS_LOCK(enp->en_eslp, state); 514 515 ef10_filter_set_entry_not_busy(eftp, tbl_id); 516 517 EFSYS_UNLOCK(enp->en_eslp, state); 518 } 519 520 return (0); 521 522 fail1: 523 EFSYS_PROBE1(fail1, efx_rc_t, rc); 524 525 return (rc); 526 } 527 528 /* 529 * An arbitrary search limit for the software hash table. As per the linux net 530 * driver. 531 */ 532 #define EF10_FILTER_SEARCH_LIMIT 200 533 534 static __checkReturn efx_rc_t 535 ef10_filter_add_internal( 536 __in efx_nic_t *enp, 537 __inout efx_filter_spec_t *spec, 538 __in boolean_t may_replace, 539 __out_opt uint32_t *filter_id) 540 { 541 efx_rc_t rc; 542 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 543 efx_filter_spec_t *saved_spec; 544 uint32_t hash; 545 unsigned int depth; 546 int ins_index; 547 boolean_t replacing = B_FALSE; 548 unsigned int i; 549 efsys_lock_state_t state; 550 boolean_t locked = B_FALSE; 551 552 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 553 enp->en_family == EFX_FAMILY_MEDFORD); 554 555 #if EFSYS_OPT_RX_SCALE 556 spec->efs_rss_context = enp->en_rss_context; 557 #endif 558 559 hash = ef10_filter_hash(spec); 560 561 /* 562 * FIXME: Add support for inserting filters of different priorities 563 * and removing lower priority multicast filters (bug 42378) 564 */ 565 566 /* 567 * Find any existing filters with the same match tuple or 568 * else a free slot to insert at. If any of them are busy, 569 * we have to wait and retry. 570 */ 571 for (;;) { 572 ins_index = -1; 573 depth = 1; 574 EFSYS_LOCK(enp->en_eslp, state); 575 locked = B_TRUE; 576 577 for (;;) { 578 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); 579 saved_spec = ef10_filter_entry_spec(eftp, i); 580 581 if (!saved_spec) { 582 if (ins_index < 0) { 583 ins_index = i; 584 } 585 } else if (ef10_filter_equal(spec, saved_spec)) { 586 if (ef10_filter_entry_is_busy(eftp, i)) 587 break; 588 if (saved_spec->efs_priority 589 == EFX_FILTER_PRI_AUTO) { 590 ins_index = i; 591 goto found; 592 } else if (ef10_filter_is_exclusive(spec)) { 593 if (may_replace) { 594 ins_index = i; 595 goto found; 596 } else { 597 rc = EEXIST; 598 goto fail1; 599 } 600 } 601 602 /* Leave existing */ 603 } 604 605 /* 606 * Once we reach the maximum search depth, use 607 * the first suitable slot or return EBUSY if 608 * there was none. 609 */ 610 if (depth == EF10_FILTER_SEARCH_LIMIT) { 611 if (ins_index < 0) { 612 rc = EBUSY; 613 goto fail2; 614 } 615 goto found; 616 } 617 depth++; 618 } 619 EFSYS_UNLOCK(enp->en_eslp, state); 620 locked = B_FALSE; 621 } 622 623 found: 624 /* 625 * Create a software table entry if necessary, and mark it 626 * busy. We might yet fail to insert, but any attempt to 627 * insert a conflicting filter while we're waiting for the 628 * firmware must find the busy entry. 629 */ 630 saved_spec = ef10_filter_entry_spec(eftp, ins_index); 631 if (saved_spec) { 632 if (saved_spec->efs_priority == EFX_FILTER_PRI_AUTO) { 633 /* This is a filter we are refreshing */ 634 ef10_filter_set_entry_not_auto_old(eftp, ins_index); 635 goto out_unlock; 636 637 } 638 replacing = B_TRUE; 639 } else { 640 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), saved_spec); 641 if (!saved_spec) { 642 rc = ENOMEM; 643 goto fail3; 644 } 645 *saved_spec = *spec; 646 ef10_filter_set_entry(eftp, ins_index, saved_spec); 647 } 648 ef10_filter_set_entry_busy(eftp, ins_index); 649 650 EFSYS_UNLOCK(enp->en_eslp, state); 651 locked = B_FALSE; 652 653 /* 654 * On replacing the filter handle may change after after a successful 655 * replace operation. 656 */ 657 if (replacing) { 658 rc = efx_mcdi_filter_op_add(enp, spec, 659 MC_CMD_FILTER_OP_IN_OP_REPLACE, 660 &eftp->eft_entry[ins_index].efe_handle); 661 } else if (ef10_filter_is_exclusive(spec)) { 662 rc = efx_mcdi_filter_op_add(enp, spec, 663 MC_CMD_FILTER_OP_IN_OP_INSERT, 664 &eftp->eft_entry[ins_index].efe_handle); 665 } else { 666 rc = efx_mcdi_filter_op_add(enp, spec, 667 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE, 668 &eftp->eft_entry[ins_index].efe_handle); 669 } 670 671 if (rc != 0) 672 goto fail4; 673 674 EFSYS_LOCK(enp->en_eslp, state); 675 locked = B_TRUE; 676 677 if (replacing) { 678 /* Update the fields that may differ */ 679 saved_spec->efs_priority = spec->efs_priority; 680 saved_spec->efs_flags = spec->efs_flags; 681 saved_spec->efs_rss_context = spec->efs_rss_context; 682 saved_spec->efs_dmaq_id = spec->efs_dmaq_id; 683 } 684 685 ef10_filter_set_entry_not_busy(eftp, ins_index); 686 687 out_unlock: 688 689 EFSYS_UNLOCK(enp->en_eslp, state); 690 locked = B_FALSE; 691 692 if (filter_id) 693 *filter_id = ins_index; 694 695 return (0); 696 697 fail4: 698 EFSYS_PROBE(fail4); 699 700 if (!replacing) { 701 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), saved_spec); 702 saved_spec = NULL; 703 } 704 ef10_filter_set_entry_not_busy(eftp, ins_index); 705 ef10_filter_set_entry(eftp, ins_index, NULL); 706 707 fail3: 708 EFSYS_PROBE(fail3); 709 710 fail2: 711 EFSYS_PROBE(fail2); 712 713 fail1: 714 EFSYS_PROBE1(fail1, efx_rc_t, rc); 715 716 if (locked) 717 EFSYS_UNLOCK(enp->en_eslp, state); 718 719 return (rc); 720 } 721 722 __checkReturn efx_rc_t 723 ef10_filter_add( 724 __in efx_nic_t *enp, 725 __inout efx_filter_spec_t *spec, 726 __in boolean_t may_replace) 727 { 728 efx_rc_t rc; 729 730 rc = ef10_filter_add_internal(enp, spec, may_replace, NULL); 731 if (rc != 0) 732 goto fail1; 733 734 return (0); 735 736 fail1: 737 EFSYS_PROBE1(fail1, efx_rc_t, rc); 738 739 return (rc); 740 } 741 742 743 static __checkReturn efx_rc_t 744 ef10_filter_delete_internal( 745 __in efx_nic_t *enp, 746 __in uint32_t filter_id) 747 { 748 efx_rc_t rc; 749 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 750 efx_filter_spec_t *spec; 751 efsys_lock_state_t state; 752 uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS; 753 754 /* 755 * Find the software table entry and mark it busy. Don't 756 * remove it yet; any attempt to update while we're waiting 757 * for the firmware must find the busy entry. 758 * 759 * FIXME: What if the busy flag is never cleared? 760 */ 761 EFSYS_LOCK(enp->en_eslp, state); 762 while (ef10_filter_entry_is_busy(table, filter_idx)) { 763 EFSYS_UNLOCK(enp->en_eslp, state); 764 EFSYS_SPIN(1); 765 EFSYS_LOCK(enp->en_eslp, state); 766 } 767 if ((spec = ef10_filter_entry_spec(table, filter_idx)) != NULL) { 768 ef10_filter_set_entry_busy(table, filter_idx); 769 } 770 EFSYS_UNLOCK(enp->en_eslp, state); 771 772 if (spec == NULL) { 773 rc = ENOENT; 774 goto fail1; 775 } 776 777 /* 778 * Try to remove the hardware filter. This may fail if the MC has 779 * rebooted (which frees all hardware filter resources). 780 */ 781 if (ef10_filter_is_exclusive(spec)) { 782 rc = efx_mcdi_filter_op_delete(enp, 783 MC_CMD_FILTER_OP_IN_OP_REMOVE, 784 &table->eft_entry[filter_idx].efe_handle); 785 } else { 786 rc = efx_mcdi_filter_op_delete(enp, 787 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE, 788 &table->eft_entry[filter_idx].efe_handle); 789 } 790 791 /* Free the software table entry */ 792 EFSYS_LOCK(enp->en_eslp, state); 793 ef10_filter_set_entry_not_busy(table, filter_idx); 794 ef10_filter_set_entry(table, filter_idx, NULL); 795 EFSYS_UNLOCK(enp->en_eslp, state); 796 797 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec); 798 799 /* Check result of hardware filter removal */ 800 if (rc != 0) 801 goto fail2; 802 803 return (0); 804 805 fail2: 806 EFSYS_PROBE(fail2); 807 808 fail1: 809 EFSYS_PROBE1(fail1, efx_rc_t, rc); 810 811 return (rc); 812 } 813 814 __checkReturn efx_rc_t 815 ef10_filter_delete( 816 __in efx_nic_t *enp, 817 __inout efx_filter_spec_t *spec) 818 { 819 efx_rc_t rc; 820 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 821 efx_filter_spec_t *saved_spec; 822 unsigned int hash; 823 unsigned int depth; 824 unsigned int i; 825 efsys_lock_state_t state; 826 boolean_t locked = B_FALSE; 827 828 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 829 enp->en_family == EFX_FAMILY_MEDFORD); 830 831 hash = ef10_filter_hash(spec); 832 833 EFSYS_LOCK(enp->en_eslp, state); 834 locked = B_TRUE; 835 836 depth = 1; 837 for (;;) { 838 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); 839 saved_spec = ef10_filter_entry_spec(table, i); 840 if (saved_spec && ef10_filter_equal(spec, saved_spec) && 841 ef10_filter_same_dest(spec, saved_spec)) { 842 break; 843 } 844 if (depth == EF10_FILTER_SEARCH_LIMIT) { 845 rc = ENOENT; 846 goto fail1; 847 } 848 depth++; 849 } 850 851 EFSYS_UNLOCK(enp->en_eslp, state); 852 locked = B_FALSE; 853 854 rc = ef10_filter_delete_internal(enp, i); 855 if (rc != 0) 856 goto fail2; 857 858 return (0); 859 860 fail2: 861 EFSYS_PROBE(fail2); 862 863 fail1: 864 EFSYS_PROBE1(fail1, efx_rc_t, rc); 865 866 if (locked) 867 EFSYS_UNLOCK(enp->en_eslp, state); 868 869 return (rc); 870 } 871 872 static __checkReturn efx_rc_t 873 efx_mcdi_get_parser_disp_info( 874 __in efx_nic_t *enp, 875 __out_ecount(buffer_length) uint32_t *buffer, 876 __in size_t buffer_length, 877 __out size_t *list_lengthp) 878 { 879 efx_mcdi_req_t req; 880 uint8_t payload[MAX(MC_CMD_GET_PARSER_DISP_INFO_IN_LEN, 881 MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX)]; 882 size_t matches_count; 883 size_t list_size; 884 efx_rc_t rc; 885 886 (void) memset(payload, 0, sizeof (payload)); 887 req.emr_cmd = MC_CMD_GET_PARSER_DISP_INFO; 888 req.emr_in_buf = payload; 889 req.emr_in_length = MC_CMD_GET_PARSER_DISP_INFO_IN_LEN; 890 req.emr_out_buf = payload; 891 req.emr_out_length = MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX; 892 893 MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, 894 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_RX_MATCHES); 895 896 efx_mcdi_execute(enp, &req); 897 898 if (req.emr_rc != 0) { 899 rc = req.emr_rc; 900 goto fail1; 901 } 902 903 matches_count = MCDI_OUT_DWORD(req, 904 GET_PARSER_DISP_INFO_OUT_NUM_SUPPORTED_MATCHES); 905 906 if (req.emr_out_length_used < 907 MC_CMD_GET_PARSER_DISP_INFO_OUT_LEN(matches_count)) { 908 rc = EMSGSIZE; 909 goto fail2; 910 } 911 912 *list_lengthp = matches_count; 913 914 if (buffer_length < matches_count) { 915 rc = ENOSPC; 916 goto fail3; 917 } 918 919 /* 920 * Check that the elements in the list in the MCDI response are the size 921 * we expect, so we can just copy them directly. Any conversion of the 922 * flags is handled by the caller. 923 */ 924 EFX_STATIC_ASSERT(sizeof (uint32_t) == 925 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN); 926 927 list_size = matches_count * 928 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN; 929 memcpy(buffer, 930 MCDI_OUT2(req, uint32_t, 931 GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES), 932 list_size); 933 934 return (0); 935 936 fail3: 937 EFSYS_PROBE(fail3); 938 fail2: 939 EFSYS_PROBE(fail2); 940 fail1: 941 EFSYS_PROBE1(fail1, efx_rc_t, rc); 942 943 return (rc); 944 } 945 946 __checkReturn efx_rc_t 947 ef10_filter_supported_filters( 948 __in efx_nic_t *enp, 949 __out_ecount(buffer_length) uint32_t *buffer, 950 __in size_t buffer_length, 951 __out size_t *list_lengthp) 952 { 953 954 size_t mcdi_list_length; 955 size_t list_length; 956 uint32_t i; 957 efx_rc_t rc; 958 uint32_t all_filter_flags = 959 (EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_LOC_HOST | 960 EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_REM_PORT | 961 EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | 962 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | 963 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | 964 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | 965 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); 966 967 rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, 968 &mcdi_list_length); 969 if (rc != 0) { 970 if (rc == ENOSPC) { 971 /* Pass through mcdi_list_length for the list length */ 972 *list_lengthp = mcdi_list_length; 973 } 974 goto fail1; 975 } 976 977 /* 978 * The static assertions in ef10_filter_init() ensure that the values of 979 * the EFX_FILTER_MATCH flags match those used by MCDI, so they don't 980 * need to be converted. 981 * 982 * In case support is added to MCDI for additional flags, remove any 983 * matches from the list which include flags we don't support. The order 984 * of the matches is preserved as they are ordered from highest to 985 * lowest priority. 986 */ 987 EFSYS_ASSERT(mcdi_list_length <= buffer_length); 988 list_length = 0; 989 for (i = 0; i < mcdi_list_length; i++) { 990 if ((buffer[i] & ~all_filter_flags) == 0) { 991 buffer[list_length] = buffer[i]; 992 list_length++; 993 } 994 } 995 996 *list_lengthp = list_length; 997 998 return (0); 999 1000 fail1: 1001 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1002 1003 return (rc); 1004 } 1005 1006 static __checkReturn efx_rc_t 1007 ef10_filter_insert_unicast( 1008 __in efx_nic_t *enp, 1009 __in_ecount(6) uint8_t const *addr, 1010 __in efx_filter_flags_t filter_flags) 1011 { 1012 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1013 efx_filter_spec_t spec; 1014 efx_rc_t rc; 1015 1016 /* Insert the filter for the local station address */ 1017 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1018 filter_flags, 1019 eftp->eft_default_rxq); 1020 efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC, addr); 1021 1022 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1023 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); 1024 if (rc != 0) 1025 goto fail1; 1026 1027 eftp->eft_unicst_filter_count++; 1028 EFSYS_ASSERT(eftp->eft_unicst_filter_count <= 1029 EFX_EF10_FILTER_UNICAST_FILTERS_MAX); 1030 1031 return (0); 1032 1033 fail1: 1034 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1035 return (rc); 1036 } 1037 1038 static __checkReturn efx_rc_t 1039 ef10_filter_insert_all_unicast( 1040 __in efx_nic_t *enp, 1041 __in efx_filter_flags_t filter_flags) 1042 { 1043 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1044 efx_filter_spec_t spec; 1045 efx_rc_t rc; 1046 1047 /* Insert the unknown unicast filter */ 1048 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1049 filter_flags, 1050 eftp->eft_default_rxq); 1051 efx_filter_spec_set_uc_def(&spec); 1052 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1053 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); 1054 if (rc != 0) 1055 goto fail1; 1056 1057 eftp->eft_unicst_filter_count++; 1058 EFSYS_ASSERT(eftp->eft_unicst_filter_count <= 1059 EFX_EF10_FILTER_UNICAST_FILTERS_MAX); 1060 1061 return (0); 1062 1063 fail1: 1064 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1065 return (rc); 1066 } 1067 1068 static __checkReturn efx_rc_t 1069 ef10_filter_insert_multicast_list( 1070 __in efx_nic_t *enp, 1071 __in boolean_t mulcst, 1072 __in boolean_t brdcst, 1073 __in_ecount(6*count) uint8_t const *addrs, 1074 __in uint32_t count, 1075 __in efx_filter_flags_t filter_flags, 1076 __in boolean_t rollback) 1077 { 1078 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1079 efx_filter_spec_t spec; 1080 uint8_t addr[6]; 1081 uint32_t i; 1082 uint32_t filter_index; 1083 uint32_t filter_count; 1084 efx_rc_t rc; 1085 1086 if (mulcst == B_FALSE) 1087 count = 0; 1088 1089 if (count + (brdcst ? 1 : 0) > 1090 EFX_ARRAY_SIZE(eftp->eft_mulcst_filter_indexes)) { 1091 /* Too many MAC addresses */ 1092 rc = EINVAL; 1093 goto fail1; 1094 } 1095 1096 /* Insert/renew multicast address list filters */ 1097 filter_count = 0; 1098 for (i = 0; i < count; i++) { 1099 efx_filter_spec_init_rx(&spec, 1100 EFX_FILTER_PRI_AUTO, 1101 filter_flags, 1102 eftp->eft_default_rxq); 1103 1104 efx_filter_spec_set_eth_local(&spec, 1105 EFX_FILTER_SPEC_VID_UNSPEC, 1106 &addrs[i * EFX_MAC_ADDR_LEN]); 1107 1108 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1109 &filter_index); 1110 1111 if (rc == 0) { 1112 eftp->eft_mulcst_filter_indexes[filter_count] = 1113 filter_index; 1114 filter_count++; 1115 } else if (rollback == B_TRUE) { 1116 /* Only stop upon failure if told to rollback */ 1117 goto rollback; 1118 } 1119 1120 } 1121 1122 if (brdcst == B_TRUE) { 1123 /* Insert/renew broadcast address filter */ 1124 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1125 filter_flags, 1126 eftp->eft_default_rxq); 1127 1128 EFX_MAC_BROADCAST_ADDR_SET(addr); 1129 efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC, 1130 addr); 1131 1132 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1133 &filter_index); 1134 1135 if (rc == 0) { 1136 eftp->eft_mulcst_filter_indexes[filter_count] = 1137 filter_index; 1138 filter_count++; 1139 } else if (rollback == B_TRUE) { 1140 /* Only stop upon failure if told to rollback */ 1141 goto rollback; 1142 } 1143 } 1144 1145 eftp->eft_mulcst_filter_count = filter_count; 1146 eftp->eft_using_all_mulcst = B_FALSE; 1147 1148 return (0); 1149 1150 rollback: 1151 /* Remove any filters we have inserted */ 1152 i = filter_count; 1153 while (i--) { 1154 (void) ef10_filter_delete_internal(enp, 1155 eftp->eft_mulcst_filter_indexes[i]); 1156 } 1157 eftp->eft_mulcst_filter_count = 0; 1158 1159 fail1: 1160 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1161 1162 return (rc); 1163 } 1164 1165 static __checkReturn efx_rc_t 1166 ef10_filter_insert_all_multicast( 1167 __in efx_nic_t *enp, 1168 __in efx_filter_flags_t filter_flags) 1169 { 1170 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1171 efx_filter_spec_t spec; 1172 efx_rc_t rc; 1173 1174 /* Insert the unknown multicast filter */ 1175 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1176 filter_flags, 1177 eftp->eft_default_rxq); 1178 efx_filter_spec_set_mc_def(&spec); 1179 1180 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1181 &eftp->eft_mulcst_filter_indexes[0]); 1182 if (rc != 0) 1183 goto fail1; 1184 1185 eftp->eft_mulcst_filter_count = 1; 1186 eftp->eft_using_all_mulcst = B_TRUE; 1187 1188 /* 1189 * FIXME: If brdcst == B_FALSE, add a filter to drop broadcast traffic. 1190 */ 1191 1192 return (0); 1193 1194 fail1: 1195 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1196 1197 return (rc); 1198 } 1199 1200 static void 1201 ef10_filter_remove_old( 1202 __in efx_nic_t *enp) 1203 { 1204 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1205 uint32_t i; 1206 1207 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) { 1208 if (ef10_filter_entry_is_auto_old(table, i)) { 1209 (void) ef10_filter_delete_internal(enp, i); 1210 } 1211 } 1212 } 1213 1214 1215 static __checkReturn efx_rc_t 1216 ef10_filter_get_workarounds( 1217 __in efx_nic_t *enp) 1218 { 1219 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1220 uint32_t implemented = 0; 1221 uint32_t enabled = 0; 1222 efx_rc_t rc; 1223 1224 rc = efx_mcdi_get_workarounds(enp, &implemented, &enabled); 1225 if (rc == 0) { 1226 /* Check if chained multicast filter support is enabled */ 1227 if (implemented & enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807) 1228 encp->enc_bug26807_workaround = B_TRUE; 1229 else 1230 encp->enc_bug26807_workaround = B_FALSE; 1231 } else if (rc == ENOTSUP) { 1232 /* 1233 * Firmware is too old to support GET_WORKAROUNDS, and support 1234 * for this workaround was implemented later. 1235 */ 1236 encp->enc_bug26807_workaround = B_FALSE; 1237 } else { 1238 goto fail1; 1239 } 1240 1241 return (0); 1242 1243 fail1: 1244 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1245 1246 return (rc); 1247 1248 } 1249 1250 1251 /* 1252 * Reconfigure all filters. 1253 * If all_unicst and/or all mulcst filters cannot be applied then 1254 * return ENOTSUP (Note the filters for the specified addresses are 1255 * still applied in this case). 1256 */ 1257 __checkReturn efx_rc_t 1258 ef10_filter_reconfigure( 1259 __in efx_nic_t *enp, 1260 __in_ecount(6) uint8_t const *mac_addr, 1261 __in boolean_t all_unicst, 1262 __in boolean_t mulcst, 1263 __in boolean_t all_mulcst, 1264 __in boolean_t brdcst, 1265 __in_ecount(6*count) uint8_t const *addrs, 1266 __in uint32_t count) 1267 { 1268 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1269 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1270 efx_filter_flags_t filter_flags; 1271 unsigned int i; 1272 efx_rc_t all_unicst_rc = 0; 1273 efx_rc_t all_mulcst_rc = 0; 1274 efx_rc_t rc; 1275 1276 if (table->eft_default_rxq == NULL) { 1277 /* 1278 * Filters direct traffic to the default RXQ, and so cannot be 1279 * inserted until it is available. Any currently configured 1280 * filters must be removed (ignore errors in case the MC 1281 * has rebooted, which removes hardware filters). 1282 */ 1283 for (i = 0; i < table->eft_unicst_filter_count; i++) { 1284 (void) ef10_filter_delete_internal(enp, 1285 table->eft_unicst_filter_indexes[i]); 1286 } 1287 table->eft_unicst_filter_count = 0; 1288 1289 for (i = 0; i < table->eft_mulcst_filter_count; i++) { 1290 (void) ef10_filter_delete_internal(enp, 1291 table->eft_mulcst_filter_indexes[i]); 1292 } 1293 table->eft_mulcst_filter_count = 0; 1294 1295 return (0); 1296 } 1297 1298 if (table->eft_using_rss) 1299 filter_flags = EFX_FILTER_FLAG_RX_RSS; 1300 else 1301 filter_flags = 0; 1302 1303 /* Mark old filters which may need to be removed */ 1304 for (i = 0; i < table->eft_unicst_filter_count; i++) { 1305 ef10_filter_set_entry_auto_old(table, 1306 table->eft_unicst_filter_indexes[i]); 1307 } 1308 for (i = 0; i < table->eft_mulcst_filter_count; i++) { 1309 ef10_filter_set_entry_auto_old(table, 1310 table->eft_mulcst_filter_indexes[i]); 1311 } 1312 1313 /* 1314 * Insert or renew unicast filters. 1315 * 1316 * Frimware does not perform chaining on unicast filters. As traffic is 1317 * therefore only delivered to the first matching filter, we should 1318 * always insert the specific filter for our MAC address, to try and 1319 * ensure we get that traffic. 1320 * 1321 * (If the filter for our MAC address has already been inserted by 1322 * another function, we won't receive traffic sent to us, even if we 1323 * insert a unicast mismatch filter. To prevent traffic stealing, this 1324 * therefore relies on the privilege model only allowing functions to 1325 * insert filters for their own MAC address unless explicitly given 1326 * additional privileges by the user. This also means that, even on a 1327 * priviliged function, inserting a unicast mismatch filter may not 1328 * catch all traffic in multi PCI function scenarios.) 1329 */ 1330 table->eft_unicst_filter_count = 0; 1331 rc = ef10_filter_insert_unicast(enp, mac_addr, filter_flags); 1332 if (all_unicst || (rc != 0)) { 1333 all_unicst_rc = ef10_filter_insert_all_unicast(enp, 1334 filter_flags); 1335 if ((rc != 0) && (all_unicst_rc != 0)) 1336 goto fail1; 1337 } 1338 1339 /* 1340 * WORKAROUND_BUG26807 controls firmware support for chained multicast 1341 * filters, and can only be enabled or disabled when the hardware filter 1342 * table is empty. 1343 * 1344 * Chained multicast filters require support from the datapath firmware, 1345 * and may not be available (e.g. low-latency variants or old Huntington 1346 * firmware). 1347 * 1348 * Firmware will reset (FLR) functions which have inserted filters in 1349 * the hardware filter table when the workaround is enabled/disabled. 1350 * Functions without any hardware filters are not reset. 1351 * 1352 * Re-check if the workaround is enabled after adding unicast hardware 1353 * filters. This ensures that encp->enc_bug26807_workaround matches the 1354 * firmware state, and that later changes to enable/disable the 1355 * workaround will result in this function seeing a reset (FLR). 1356 * 1357 * In common-code drivers, we only support multiple PCI function 1358 * scenarios with firmware that supports multicast chaining, so we can 1359 * assume it is enabled for such cases and hence simplify the filter 1360 * insertion logic. Firmware that does not support multicast chaining 1361 * does not support multiple PCI function configurations either, so 1362 * filter insertion is much simpler and the same strategies can still be 1363 * used. 1364 */ 1365 if ((rc = ef10_filter_get_workarounds(enp)) != 0) 1366 goto fail2; 1367 1368 if ((table->eft_using_all_mulcst != all_mulcst) && 1369 (encp->enc_bug26807_workaround == B_TRUE)) { 1370 /* 1371 * Multicast filter chaining is enabled, so traffic that matches 1372 * more than one multicast filter will be replicated and 1373 * delivered to multiple recipients. To avoid this duplicate 1374 * delivery, remove old multicast filters before inserting new 1375 * multicast filters. 1376 */ 1377 ef10_filter_remove_old(enp); 1378 } 1379 1380 /* Insert or renew multicast filters */ 1381 if (all_mulcst == B_TRUE) { 1382 /* 1383 * Insert the all multicast filter. If that fails, try to insert 1384 * all of our multicast filters (but without rollback on 1385 * failure). 1386 */ 1387 all_mulcst_rc = ef10_filter_insert_all_multicast(enp, 1388 filter_flags); 1389 if (all_mulcst_rc != 0) { 1390 rc = ef10_filter_insert_multicast_list(enp, B_TRUE, 1391 brdcst, addrs, count, filter_flags, B_FALSE); 1392 if (rc != 0) 1393 goto fail3; 1394 } 1395 } else { 1396 /* 1397 * Insert filters for multicast addresses. 1398 * If any insertion fails, then rollback and try to insert the 1399 * all multicast filter instead. 1400 * If that also fails, try to insert all of the multicast 1401 * filters (but without rollback on failure). 1402 */ 1403 rc = ef10_filter_insert_multicast_list(enp, mulcst, brdcst, 1404 addrs, count, filter_flags, B_TRUE); 1405 if (rc != 0) { 1406 if ((table->eft_using_all_mulcst == B_FALSE) && 1407 (encp->enc_bug26807_workaround == B_TRUE)) { 1408 /* 1409 * Multicast filter chaining is on, so remove 1410 * old filters before inserting the multicast 1411 * all filter to avoid duplicate delivery caused 1412 * by packets matching multiple filters. 1413 */ 1414 ef10_filter_remove_old(enp); 1415 } 1416 1417 rc = ef10_filter_insert_all_multicast(enp, 1418 filter_flags); 1419 if (rc != 0) { 1420 rc = ef10_filter_insert_multicast_list(enp, 1421 mulcst, brdcst, 1422 addrs, count, filter_flags, B_FALSE); 1423 if (rc != 0) 1424 goto fail4; 1425 } 1426 } 1427 } 1428 1429 /* Remove old filters which were not renewed */ 1430 ef10_filter_remove_old(enp); 1431 1432 /* report if any optional flags were rejected */ 1433 if (((all_unicst != B_FALSE) && (all_unicst_rc != 0)) || 1434 ((all_mulcst != B_FALSE) && (all_mulcst_rc != 0))) { 1435 rc = ENOTSUP; 1436 } 1437 1438 return (rc); 1439 1440 fail4: 1441 EFSYS_PROBE(fail4); 1442 fail3: 1443 EFSYS_PROBE(fail3); 1444 fail2: 1445 EFSYS_PROBE(fail2); 1446 fail1: 1447 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1448 1449 /* Clear auto old flags */ 1450 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) { 1451 if (ef10_filter_entry_is_auto_old(table, i)) { 1452 ef10_filter_set_entry_not_auto_old(table, i); 1453 } 1454 } 1455 1456 return (rc); 1457 } 1458 1459 void 1460 ef10_filter_get_default_rxq( 1461 __in efx_nic_t *enp, 1462 __out efx_rxq_t **erpp, 1463 __out boolean_t *using_rss) 1464 { 1465 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1466 1467 *erpp = table->eft_default_rxq; 1468 *using_rss = table->eft_using_rss; 1469 } 1470 1471 1472 void 1473 ef10_filter_default_rxq_set( 1474 __in efx_nic_t *enp, 1475 __in efx_rxq_t *erp, 1476 __in boolean_t using_rss) 1477 { 1478 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1479 1480 #if EFSYS_OPT_RX_SCALE 1481 EFSYS_ASSERT((using_rss == B_FALSE) || 1482 (enp->en_rss_context != EF10_RSS_CONTEXT_INVALID)); 1483 table->eft_using_rss = using_rss; 1484 #else 1485 EFSYS_ASSERT(using_rss == B_FALSE); 1486 table->eft_using_rss = B_FALSE; 1487 #endif 1488 table->eft_default_rxq = erp; 1489 } 1490 1491 void 1492 ef10_filter_default_rxq_clear( 1493 __in efx_nic_t *enp) 1494 { 1495 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1496 1497 table->eft_default_rxq = NULL; 1498 table->eft_using_rss = B_FALSE; 1499 } 1500 1501 1502 #endif /* EFSYS_OPT_FILTER */ 1503 1504 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */ 1505