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 #include "efx.h" 33 #include "efx_impl.h" 34 35 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 36 37 #if EFSYS_OPT_FILTER 38 39 #define EFE_SPEC(eftp, index) ((eftp)->eft_entry[(index)].efe_spec) 40 41 static efx_filter_spec_t * 42 ef10_filter_entry_spec( 43 __in const ef10_filter_table_t *eftp, 44 __in unsigned int index) 45 { 46 return ((efx_filter_spec_t *)(EFE_SPEC(eftp, index) & 47 ~(uintptr_t)EFX_EF10_FILTER_FLAGS)); 48 } 49 50 static boolean_t 51 ef10_filter_entry_is_busy( 52 __in const ef10_filter_table_t *eftp, 53 __in unsigned int index) 54 { 55 if (EFE_SPEC(eftp, index) & EFX_EF10_FILTER_FLAG_BUSY) 56 return (B_TRUE); 57 else 58 return (B_FALSE); 59 } 60 61 static boolean_t 62 ef10_filter_entry_is_auto_old( 63 __in const ef10_filter_table_t *eftp, 64 __in unsigned int index) 65 { 66 if (EFE_SPEC(eftp, index) & EFX_EF10_FILTER_FLAG_AUTO_OLD) 67 return (B_TRUE); 68 else 69 return (B_FALSE); 70 } 71 72 static void 73 ef10_filter_set_entry( 74 __inout ef10_filter_table_t *eftp, 75 __in unsigned int index, 76 __in_opt const efx_filter_spec_t *efsp) 77 { 78 EFE_SPEC(eftp, index) = (uintptr_t)efsp; 79 } 80 81 static void 82 ef10_filter_set_entry_busy( 83 __inout ef10_filter_table_t *eftp, 84 __in unsigned int index) 85 { 86 EFE_SPEC(eftp, index) |= (uintptr_t)EFX_EF10_FILTER_FLAG_BUSY; 87 } 88 89 static void 90 ef10_filter_set_entry_not_busy( 91 __inout ef10_filter_table_t *eftp, 92 __in unsigned int index) 93 { 94 EFE_SPEC(eftp, index) &= ~(uintptr_t)EFX_EF10_FILTER_FLAG_BUSY; 95 } 96 97 static void 98 ef10_filter_set_entry_auto_old( 99 __inout ef10_filter_table_t *eftp, 100 __in unsigned int index) 101 { 102 EFSYS_ASSERT(ef10_filter_entry_spec(eftp, index) != NULL); 103 EFE_SPEC(eftp, index) |= (uintptr_t)EFX_EF10_FILTER_FLAG_AUTO_OLD; 104 } 105 106 static void 107 ef10_filter_set_entry_not_auto_old( 108 __inout ef10_filter_table_t *eftp, 109 __in unsigned int index) 110 { 111 EFE_SPEC(eftp, index) &= ~(uintptr_t)EFX_EF10_FILTER_FLAG_AUTO_OLD; 112 EFSYS_ASSERT(ef10_filter_entry_spec(eftp, index) != NULL); 113 } 114 115 __checkReturn efx_rc_t 116 ef10_filter_init( 117 __in efx_nic_t *enp) 118 { 119 efx_rc_t rc; 120 ef10_filter_table_t *eftp; 121 122 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 123 enp->en_family == EFX_FAMILY_MEDFORD || 124 enp->en_family == EFX_FAMILY_MEDFORD2); 125 126 #define MATCH_MASK(match) (EFX_MASK32(match) << EFX_LOW_BIT(match)) 127 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_HOST == 128 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_IP)); 129 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_HOST == 130 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_IP)); 131 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_MAC == 132 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_MAC)); 133 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_PORT == 134 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_PORT)); 135 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_MAC == 136 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_MAC)); 137 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_PORT == 138 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_PORT)); 139 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_ETHER_TYPE == 140 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_ETHER_TYPE)); 141 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_INNER_VID == 142 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_INNER_VLAN)); 143 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_OUTER_VID == 144 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_OUTER_VLAN)); 145 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO == 146 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IP_PROTO)); 147 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_VNI_OR_VSID == 148 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_VNI_OR_VSID)); 149 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_LOC_MAC == 150 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_DST_MAC)); 151 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST == 152 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_MCAST_DST)); 153 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST == 154 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST)); 155 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_UNKNOWN_MCAST_DST == 156 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST)); 157 EFX_STATIC_ASSERT((uint32_t)EFX_FILTER_MATCH_UNKNOWN_UCAST_DST == 158 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_UCAST_DST)); 159 #undef MATCH_MASK 160 161 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (ef10_filter_table_t), eftp); 162 163 if (!eftp) { 164 rc = ENOMEM; 165 goto fail1; 166 } 167 168 enp->en_filter.ef_ef10_filter_table = eftp; 169 170 return (0); 171 172 fail1: 173 EFSYS_PROBE1(fail1, efx_rc_t, rc); 174 175 return (rc); 176 } 177 178 void 179 ef10_filter_fini( 180 __in efx_nic_t *enp) 181 { 182 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 183 enp->en_family == EFX_FAMILY_MEDFORD || 184 enp->en_family == EFX_FAMILY_MEDFORD2); 185 186 if (enp->en_filter.ef_ef10_filter_table != NULL) { 187 EFSYS_KMEM_FREE(enp->en_esip, sizeof (ef10_filter_table_t), 188 enp->en_filter.ef_ef10_filter_table); 189 } 190 } 191 192 static __checkReturn efx_rc_t 193 efx_mcdi_filter_op_add( 194 __in efx_nic_t *enp, 195 __in efx_filter_spec_t *spec, 196 __in unsigned int filter_op, 197 __inout ef10_filter_handle_t *handle) 198 { 199 efx_mcdi_req_t req; 200 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_V3_IN_LEN, 201 MC_CMD_FILTER_OP_EXT_OUT_LEN); 202 efx_filter_match_flags_t match_flags; 203 efx_rc_t rc; 204 205 req.emr_cmd = MC_CMD_FILTER_OP; 206 req.emr_in_buf = payload; 207 req.emr_in_length = MC_CMD_FILTER_OP_V3_IN_LEN; 208 req.emr_out_buf = payload; 209 req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN; 210 211 /* 212 * Remove match flag for encapsulated filters that does not correspond 213 * to the MCDI match flags 214 */ 215 match_flags = spec->efs_match_flags & ~EFX_FILTER_MATCH_ENCAP_TYPE; 216 217 switch (filter_op) { 218 case MC_CMD_FILTER_OP_IN_OP_REPLACE: 219 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO, 220 handle->efh_lo); 221 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_HI, 222 handle->efh_hi); 223 /* Fall through */ 224 case MC_CMD_FILTER_OP_IN_OP_INSERT: 225 case MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE: 226 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP, filter_op); 227 break; 228 default: 229 EFSYS_ASSERT(0); 230 rc = EINVAL; 231 goto fail1; 232 } 233 234 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID, 235 EVB_PORT_ID_ASSIGNED); 236 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_MATCH_FIELDS, 237 match_flags); 238 if (spec->efs_dmaq_id == EFX_FILTER_SPEC_RX_DMAQ_ID_DROP) { 239 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST, 240 MC_CMD_FILTER_OP_EXT_IN_RX_DEST_DROP); 241 } else { 242 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST, 243 MC_CMD_FILTER_OP_EXT_IN_RX_DEST_HOST); 244 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_QUEUE, 245 spec->efs_dmaq_id); 246 } 247 248 #if EFSYS_OPT_RX_SCALE 249 if (spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) { 250 uint32_t rss_context; 251 252 if (spec->efs_rss_context == EFX_RSS_CONTEXT_DEFAULT) 253 rss_context = enp->en_rss_context; 254 else 255 rss_context = spec->efs_rss_context; 256 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_CONTEXT, 257 rss_context); 258 } 259 #endif 260 261 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_MODE, 262 spec->efs_flags & EFX_FILTER_FLAG_RX_RSS ? 263 MC_CMD_FILTER_OP_EXT_IN_RX_MODE_RSS : 264 MC_CMD_FILTER_OP_EXT_IN_RX_MODE_SIMPLE); 265 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_TX_DEST, 266 MC_CMD_FILTER_OP_EXT_IN_TX_DEST_DEFAULT); 267 268 if (filter_op != MC_CMD_FILTER_OP_IN_OP_REPLACE) { 269 /* 270 * NOTE: Unlike most MCDI requests, the filter fields 271 * are presented in network (big endian) byte order. 272 */ 273 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_SRC_MAC), 274 spec->efs_rem_mac, EFX_MAC_ADDR_LEN); 275 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_DST_MAC), 276 spec->efs_loc_mac, EFX_MAC_ADDR_LEN); 277 278 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_SRC_PORT, 279 __CPU_TO_BE_16(spec->efs_rem_port)); 280 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_DST_PORT, 281 __CPU_TO_BE_16(spec->efs_loc_port)); 282 283 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_ETHER_TYPE, 284 __CPU_TO_BE_16(spec->efs_ether_type)); 285 286 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_INNER_VLAN, 287 __CPU_TO_BE_16(spec->efs_inner_vid)); 288 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_OUTER_VLAN, 289 __CPU_TO_BE_16(spec->efs_outer_vid)); 290 291 /* IP protocol (in low byte, high byte is zero) */ 292 MCDI_IN_SET_BYTE(req, FILTER_OP_EXT_IN_IP_PROTO, 293 spec->efs_ip_proto); 294 295 EFX_STATIC_ASSERT(sizeof (spec->efs_rem_host) == 296 MC_CMD_FILTER_OP_EXT_IN_SRC_IP_LEN); 297 EFX_STATIC_ASSERT(sizeof (spec->efs_loc_host) == 298 MC_CMD_FILTER_OP_EXT_IN_DST_IP_LEN); 299 300 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_SRC_IP), 301 &spec->efs_rem_host.eo_byte[0], 302 MC_CMD_FILTER_OP_EXT_IN_SRC_IP_LEN); 303 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_DST_IP), 304 &spec->efs_loc_host.eo_byte[0], 305 MC_CMD_FILTER_OP_EXT_IN_DST_IP_LEN); 306 307 /* 308 * On Medford, filters for encapsulated packets match based on 309 * the ether type and IP protocol in the outer frame. In 310 * addition we need to fill in the VNI or VSID type field. 311 */ 312 switch (spec->efs_encap_type) { 313 case EFX_TUNNEL_PROTOCOL_NONE: 314 break; 315 case EFX_TUNNEL_PROTOCOL_VXLAN: 316 case EFX_TUNNEL_PROTOCOL_GENEVE: 317 MCDI_IN_POPULATE_DWORD_1(req, 318 FILTER_OP_EXT_IN_VNI_OR_VSID, 319 FILTER_OP_EXT_IN_VNI_TYPE, 320 spec->efs_encap_type == EFX_TUNNEL_PROTOCOL_VXLAN ? 321 MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_VXLAN : 322 MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_GENEVE); 323 break; 324 case EFX_TUNNEL_PROTOCOL_NVGRE: 325 MCDI_IN_POPULATE_DWORD_1(req, 326 FILTER_OP_EXT_IN_VNI_OR_VSID, 327 FILTER_OP_EXT_IN_VSID_TYPE, 328 MC_CMD_FILTER_OP_EXT_IN_VSID_TYPE_NVGRE); 329 break; 330 default: 331 EFSYS_ASSERT(0); 332 rc = EINVAL; 333 goto fail2; 334 } 335 336 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_VNI_OR_VSID), 337 spec->efs_vni_or_vsid, EFX_VNI_OR_VSID_LEN); 338 339 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_IFRM_DST_MAC), 340 spec->efs_ifrm_loc_mac, EFX_MAC_ADDR_LEN); 341 } 342 343 /* 344 * Set the "MARK" or "FLAG" action for all packets matching this filter 345 * if necessary (only useful with equal stride packed stream Rx mode 346 * which provide the information in pseudo-header). 347 * These actions require MC_CMD_FILTER_OP_V3_IN msgrequest. 348 */ 349 if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) && 350 (spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG)) { 351 rc = EINVAL; 352 goto fail3; 353 } 354 if (spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) { 355 MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_ACTION, 356 MC_CMD_FILTER_OP_V3_IN_MATCH_ACTION_MARK); 357 MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_MARK_VALUE, 358 spec->efs_mark); 359 } else if (spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) { 360 MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_ACTION, 361 MC_CMD_FILTER_OP_V3_IN_MATCH_ACTION_FLAG); 362 } 363 364 efx_mcdi_execute(enp, &req); 365 366 if (req.emr_rc != 0) { 367 rc = req.emr_rc; 368 goto fail4; 369 } 370 371 if (req.emr_out_length_used < MC_CMD_FILTER_OP_EXT_OUT_LEN) { 372 rc = EMSGSIZE; 373 goto fail5; 374 } 375 376 handle->efh_lo = MCDI_OUT_DWORD(req, FILTER_OP_EXT_OUT_HANDLE_LO); 377 handle->efh_hi = MCDI_OUT_DWORD(req, FILTER_OP_EXT_OUT_HANDLE_HI); 378 379 return (0); 380 381 fail5: 382 EFSYS_PROBE(fail5); 383 fail4: 384 EFSYS_PROBE(fail4); 385 fail3: 386 EFSYS_PROBE(fail3); 387 fail2: 388 EFSYS_PROBE(fail2); 389 fail1: 390 EFSYS_PROBE1(fail1, efx_rc_t, rc); 391 392 return (rc); 393 394 } 395 396 static __checkReturn efx_rc_t 397 efx_mcdi_filter_op_delete( 398 __in efx_nic_t *enp, 399 __in unsigned int filter_op, 400 __inout ef10_filter_handle_t *handle) 401 { 402 efx_mcdi_req_t req; 403 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_EXT_IN_LEN, 404 MC_CMD_FILTER_OP_EXT_OUT_LEN); 405 efx_rc_t rc; 406 407 req.emr_cmd = MC_CMD_FILTER_OP; 408 req.emr_in_buf = payload; 409 req.emr_in_length = MC_CMD_FILTER_OP_EXT_IN_LEN; 410 req.emr_out_buf = payload; 411 req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN; 412 413 switch (filter_op) { 414 case MC_CMD_FILTER_OP_IN_OP_REMOVE: 415 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP, 416 MC_CMD_FILTER_OP_IN_OP_REMOVE); 417 break; 418 case MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE: 419 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP, 420 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE); 421 break; 422 default: 423 EFSYS_ASSERT(0); 424 rc = EINVAL; 425 goto fail1; 426 } 427 428 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO, handle->efh_lo); 429 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_HI, handle->efh_hi); 430 431 efx_mcdi_execute_quiet(enp, &req); 432 433 if (req.emr_rc != 0) { 434 rc = req.emr_rc; 435 goto fail2; 436 } 437 438 if (req.emr_out_length_used < MC_CMD_FILTER_OP_EXT_OUT_LEN) { 439 rc = EMSGSIZE; 440 goto fail3; 441 } 442 443 return (0); 444 445 fail3: 446 EFSYS_PROBE(fail3); 447 448 fail2: 449 EFSYS_PROBE(fail2); 450 fail1: 451 EFSYS_PROBE1(fail1, efx_rc_t, rc); 452 453 return (rc); 454 } 455 456 static __checkReturn boolean_t 457 ef10_filter_equal( 458 __in const efx_filter_spec_t *left, 459 __in const efx_filter_spec_t *right) 460 { 461 /* FIXME: Consider rx vs tx filters (look at efs_flags) */ 462 if (left->efs_match_flags != right->efs_match_flags) 463 return (B_FALSE); 464 if (!EFX_OWORD_IS_EQUAL(left->efs_rem_host, right->efs_rem_host)) 465 return (B_FALSE); 466 if (!EFX_OWORD_IS_EQUAL(left->efs_loc_host, right->efs_loc_host)) 467 return (B_FALSE); 468 if (memcmp(left->efs_rem_mac, right->efs_rem_mac, EFX_MAC_ADDR_LEN)) 469 return (B_FALSE); 470 if (memcmp(left->efs_loc_mac, right->efs_loc_mac, EFX_MAC_ADDR_LEN)) 471 return (B_FALSE); 472 if (left->efs_rem_port != right->efs_rem_port) 473 return (B_FALSE); 474 if (left->efs_loc_port != right->efs_loc_port) 475 return (B_FALSE); 476 if (left->efs_inner_vid != right->efs_inner_vid) 477 return (B_FALSE); 478 if (left->efs_outer_vid != right->efs_outer_vid) 479 return (B_FALSE); 480 if (left->efs_ether_type != right->efs_ether_type) 481 return (B_FALSE); 482 if (left->efs_ip_proto != right->efs_ip_proto) 483 return (B_FALSE); 484 if (left->efs_encap_type != right->efs_encap_type) 485 return (B_FALSE); 486 if (memcmp(left->efs_vni_or_vsid, right->efs_vni_or_vsid, 487 EFX_VNI_OR_VSID_LEN)) 488 return (B_FALSE); 489 if (memcmp(left->efs_ifrm_loc_mac, right->efs_ifrm_loc_mac, 490 EFX_MAC_ADDR_LEN)) 491 return (B_FALSE); 492 493 return (B_TRUE); 494 495 } 496 497 static __checkReturn boolean_t 498 ef10_filter_same_dest( 499 __in const efx_filter_spec_t *left, 500 __in const efx_filter_spec_t *right) 501 { 502 if ((left->efs_flags & EFX_FILTER_FLAG_RX_RSS) && 503 (right->efs_flags & EFX_FILTER_FLAG_RX_RSS)) { 504 if (left->efs_rss_context == right->efs_rss_context) 505 return (B_TRUE); 506 } else if ((~(left->efs_flags) & EFX_FILTER_FLAG_RX_RSS) && 507 (~(right->efs_flags) & EFX_FILTER_FLAG_RX_RSS)) { 508 if (left->efs_dmaq_id == right->efs_dmaq_id) 509 return (B_TRUE); 510 } 511 return (B_FALSE); 512 } 513 514 static __checkReturn uint32_t 515 ef10_filter_hash( 516 __in efx_filter_spec_t *spec) 517 { 518 EFX_STATIC_ASSERT((sizeof (efx_filter_spec_t) % sizeof (uint32_t)) 519 == 0); 520 EFX_STATIC_ASSERT((EFX_FIELD_OFFSET(efx_filter_spec_t, efs_outer_vid) % 521 sizeof (uint32_t)) == 0); 522 523 /* 524 * As the area of the efx_filter_spec_t we need to hash is DWORD 525 * aligned and an exact number of DWORDs in size we can use the 526 * optimised efx_hash_dwords() rather than efx_hash_bytes() 527 */ 528 return (efx_hash_dwords((const uint32_t *)&spec->efs_outer_vid, 529 (sizeof (efx_filter_spec_t) - 530 EFX_FIELD_OFFSET(efx_filter_spec_t, efs_outer_vid)) / 531 sizeof (uint32_t), 0)); 532 } 533 534 /* 535 * Decide whether a filter should be exclusive or else should allow 536 * delivery to additional recipients. Currently we decide that 537 * filters for specific local unicast MAC and IP addresses are 538 * exclusive. 539 */ 540 static __checkReturn boolean_t 541 ef10_filter_is_exclusive( 542 __in efx_filter_spec_t *spec) 543 { 544 if ((spec->efs_match_flags & EFX_FILTER_MATCH_LOC_MAC) && 545 !EFX_MAC_ADDR_IS_MULTICAST(spec->efs_loc_mac)) 546 return (B_TRUE); 547 548 if ((spec->efs_match_flags & 549 (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) == 550 (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) { 551 if ((spec->efs_ether_type == EFX_ETHER_TYPE_IPV4) && 552 ((spec->efs_loc_host.eo_u8[0] & 0xf) != 0xe)) 553 return (B_TRUE); 554 if ((spec->efs_ether_type == EFX_ETHER_TYPE_IPV6) && 555 (spec->efs_loc_host.eo_u8[0] != 0xff)) 556 return (B_TRUE); 557 } 558 559 return (B_FALSE); 560 } 561 562 __checkReturn efx_rc_t 563 ef10_filter_restore( 564 __in efx_nic_t *enp) 565 { 566 int tbl_id; 567 efx_filter_spec_t *spec; 568 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 569 boolean_t restoring; 570 efsys_lock_state_t state; 571 efx_rc_t rc; 572 573 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 574 enp->en_family == EFX_FAMILY_MEDFORD || 575 enp->en_family == EFX_FAMILY_MEDFORD2); 576 577 for (tbl_id = 0; tbl_id < EFX_EF10_FILTER_TBL_ROWS; tbl_id++) { 578 EFSYS_LOCK(enp->en_eslp, state); 579 580 spec = ef10_filter_entry_spec(eftp, tbl_id); 581 if (spec == NULL) { 582 restoring = B_FALSE; 583 } else if (ef10_filter_entry_is_busy(eftp, tbl_id)) { 584 /* Ignore busy entries. */ 585 restoring = B_FALSE; 586 } else { 587 ef10_filter_set_entry_busy(eftp, tbl_id); 588 restoring = B_TRUE; 589 } 590 591 EFSYS_UNLOCK(enp->en_eslp, state); 592 593 if (restoring == B_FALSE) 594 continue; 595 596 if (ef10_filter_is_exclusive(spec)) { 597 rc = efx_mcdi_filter_op_add(enp, spec, 598 MC_CMD_FILTER_OP_IN_OP_INSERT, 599 &eftp->eft_entry[tbl_id].efe_handle); 600 } else { 601 rc = efx_mcdi_filter_op_add(enp, spec, 602 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE, 603 &eftp->eft_entry[tbl_id].efe_handle); 604 } 605 606 if (rc != 0) 607 goto fail1; 608 609 EFSYS_LOCK(enp->en_eslp, state); 610 611 ef10_filter_set_entry_not_busy(eftp, tbl_id); 612 613 EFSYS_UNLOCK(enp->en_eslp, state); 614 } 615 616 return (0); 617 618 fail1: 619 EFSYS_PROBE1(fail1, efx_rc_t, rc); 620 621 return (rc); 622 } 623 624 /* 625 * An arbitrary search limit for the software hash table. As per the linux net 626 * driver. 627 */ 628 #define EF10_FILTER_SEARCH_LIMIT 200 629 630 static __checkReturn efx_rc_t 631 ef10_filter_add_internal( 632 __in efx_nic_t *enp, 633 __inout efx_filter_spec_t *spec, 634 __in boolean_t may_replace, 635 __out_opt uint32_t *filter_id) 636 { 637 efx_rc_t rc; 638 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 639 efx_filter_spec_t *saved_spec; 640 uint32_t hash; 641 unsigned int depth; 642 int ins_index; 643 boolean_t replacing = B_FALSE; 644 unsigned int i; 645 efsys_lock_state_t state; 646 boolean_t locked = B_FALSE; 647 648 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 649 enp->en_family == EFX_FAMILY_MEDFORD || 650 enp->en_family == EFX_FAMILY_MEDFORD2); 651 652 hash = ef10_filter_hash(spec); 653 654 /* 655 * FIXME: Add support for inserting filters of different priorities 656 * and removing lower priority multicast filters (bug 42378) 657 */ 658 659 /* 660 * Find any existing filters with the same match tuple or 661 * else a free slot to insert at. If any of them are busy, 662 * we have to wait and retry. 663 */ 664 for (;;) { 665 ins_index = -1; 666 depth = 1; 667 EFSYS_LOCK(enp->en_eslp, state); 668 locked = B_TRUE; 669 670 for (;;) { 671 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); 672 saved_spec = ef10_filter_entry_spec(eftp, i); 673 674 if (!saved_spec) { 675 if (ins_index < 0) { 676 ins_index = i; 677 } 678 } else if (ef10_filter_equal(spec, saved_spec)) { 679 if (ef10_filter_entry_is_busy(eftp, i)) 680 break; 681 if (saved_spec->efs_priority 682 == EFX_FILTER_PRI_AUTO) { 683 ins_index = i; 684 goto found; 685 } else if (ef10_filter_is_exclusive(spec)) { 686 if (may_replace) { 687 ins_index = i; 688 goto found; 689 } else { 690 rc = EEXIST; 691 goto fail1; 692 } 693 } 694 695 /* Leave existing */ 696 } 697 698 /* 699 * Once we reach the maximum search depth, use 700 * the first suitable slot or return EBUSY if 701 * there was none. 702 */ 703 if (depth == EF10_FILTER_SEARCH_LIMIT) { 704 if (ins_index < 0) { 705 rc = EBUSY; 706 goto fail2; 707 } 708 goto found; 709 } 710 depth++; 711 } 712 EFSYS_UNLOCK(enp->en_eslp, state); 713 locked = B_FALSE; 714 } 715 716 found: 717 /* 718 * Create a software table entry if necessary, and mark it 719 * busy. We might yet fail to insert, but any attempt to 720 * insert a conflicting filter while we're waiting for the 721 * firmware must find the busy entry. 722 */ 723 saved_spec = ef10_filter_entry_spec(eftp, ins_index); 724 if (saved_spec) { 725 if (saved_spec->efs_priority == EFX_FILTER_PRI_AUTO) { 726 /* This is a filter we are refreshing */ 727 ef10_filter_set_entry_not_auto_old(eftp, ins_index); 728 goto out_unlock; 729 } 730 replacing = B_TRUE; 731 } else { 732 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), saved_spec); 733 if (!saved_spec) { 734 rc = ENOMEM; 735 goto fail3; 736 } 737 *saved_spec = *spec; 738 ef10_filter_set_entry(eftp, ins_index, saved_spec); 739 } 740 ef10_filter_set_entry_busy(eftp, ins_index); 741 742 EFSYS_UNLOCK(enp->en_eslp, state); 743 locked = B_FALSE; 744 745 /* 746 * On replacing the filter handle may change after after a successful 747 * replace operation. 748 */ 749 if (replacing) { 750 rc = efx_mcdi_filter_op_add(enp, spec, 751 MC_CMD_FILTER_OP_IN_OP_REPLACE, 752 &eftp->eft_entry[ins_index].efe_handle); 753 } else if (ef10_filter_is_exclusive(spec)) { 754 rc = efx_mcdi_filter_op_add(enp, spec, 755 MC_CMD_FILTER_OP_IN_OP_INSERT, 756 &eftp->eft_entry[ins_index].efe_handle); 757 } else { 758 rc = efx_mcdi_filter_op_add(enp, spec, 759 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE, 760 &eftp->eft_entry[ins_index].efe_handle); 761 } 762 763 if (rc != 0) 764 goto fail4; 765 766 EFSYS_LOCK(enp->en_eslp, state); 767 locked = B_TRUE; 768 769 if (replacing) { 770 /* Update the fields that may differ */ 771 saved_spec->efs_priority = spec->efs_priority; 772 saved_spec->efs_flags = spec->efs_flags; 773 saved_spec->efs_rss_context = spec->efs_rss_context; 774 saved_spec->efs_dmaq_id = spec->efs_dmaq_id; 775 } 776 777 ef10_filter_set_entry_not_busy(eftp, ins_index); 778 779 out_unlock: 780 781 EFSYS_UNLOCK(enp->en_eslp, state); 782 locked = B_FALSE; 783 784 if (filter_id) 785 *filter_id = ins_index; 786 787 return (0); 788 789 fail4: 790 EFSYS_PROBE(fail4); 791 792 if (!replacing) { 793 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), saved_spec); 794 saved_spec = NULL; 795 } 796 ef10_filter_set_entry_not_busy(eftp, ins_index); 797 ef10_filter_set_entry(eftp, ins_index, NULL); 798 799 fail3: 800 EFSYS_PROBE(fail3); 801 802 fail2: 803 EFSYS_PROBE(fail2); 804 805 fail1: 806 EFSYS_PROBE1(fail1, efx_rc_t, rc); 807 808 if (locked) 809 EFSYS_UNLOCK(enp->en_eslp, state); 810 811 return (rc); 812 } 813 814 __checkReturn efx_rc_t 815 ef10_filter_add( 816 __in efx_nic_t *enp, 817 __inout efx_filter_spec_t *spec, 818 __in boolean_t may_replace) 819 { 820 efx_rc_t rc; 821 822 rc = ef10_filter_add_internal(enp, spec, may_replace, NULL); 823 if (rc != 0) 824 goto fail1; 825 826 return (0); 827 828 fail1: 829 EFSYS_PROBE1(fail1, efx_rc_t, rc); 830 831 return (rc); 832 } 833 834 static __checkReturn efx_rc_t 835 ef10_filter_delete_internal( 836 __in efx_nic_t *enp, 837 __in uint32_t filter_id) 838 { 839 efx_rc_t rc; 840 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 841 efx_filter_spec_t *spec; 842 efsys_lock_state_t state; 843 uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS; 844 845 /* 846 * Find the software table entry and mark it busy. Don't 847 * remove it yet; any attempt to update while we're waiting 848 * for the firmware must find the busy entry. 849 * 850 * FIXME: What if the busy flag is never cleared? 851 */ 852 EFSYS_LOCK(enp->en_eslp, state); 853 while (ef10_filter_entry_is_busy(table, filter_idx)) { 854 EFSYS_UNLOCK(enp->en_eslp, state); 855 EFSYS_SPIN(1); 856 EFSYS_LOCK(enp->en_eslp, state); 857 } 858 if ((spec = ef10_filter_entry_spec(table, filter_idx)) != NULL) { 859 ef10_filter_set_entry_busy(table, filter_idx); 860 } 861 EFSYS_UNLOCK(enp->en_eslp, state); 862 863 if (spec == NULL) { 864 rc = ENOENT; 865 goto fail1; 866 } 867 868 /* 869 * Try to remove the hardware filter. This may fail if the MC has 870 * rebooted (which frees all hardware filter resources). 871 */ 872 if (ef10_filter_is_exclusive(spec)) { 873 rc = efx_mcdi_filter_op_delete(enp, 874 MC_CMD_FILTER_OP_IN_OP_REMOVE, 875 &table->eft_entry[filter_idx].efe_handle); 876 } else { 877 rc = efx_mcdi_filter_op_delete(enp, 878 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE, 879 &table->eft_entry[filter_idx].efe_handle); 880 } 881 882 /* Free the software table entry */ 883 EFSYS_LOCK(enp->en_eslp, state); 884 ef10_filter_set_entry_not_busy(table, filter_idx); 885 ef10_filter_set_entry(table, filter_idx, NULL); 886 EFSYS_UNLOCK(enp->en_eslp, state); 887 888 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec); 889 890 /* Check result of hardware filter removal */ 891 if (rc != 0) 892 goto fail2; 893 894 return (0); 895 896 fail2: 897 EFSYS_PROBE(fail2); 898 899 fail1: 900 EFSYS_PROBE1(fail1, efx_rc_t, rc); 901 902 return (rc); 903 } 904 905 __checkReturn efx_rc_t 906 ef10_filter_delete( 907 __in efx_nic_t *enp, 908 __inout efx_filter_spec_t *spec) 909 { 910 efx_rc_t rc; 911 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 912 efx_filter_spec_t *saved_spec; 913 unsigned int hash; 914 unsigned int depth; 915 unsigned int i; 916 efsys_lock_state_t state; 917 boolean_t locked = B_FALSE; 918 919 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 920 enp->en_family == EFX_FAMILY_MEDFORD || 921 enp->en_family == EFX_FAMILY_MEDFORD2); 922 923 hash = ef10_filter_hash(spec); 924 925 EFSYS_LOCK(enp->en_eslp, state); 926 locked = B_TRUE; 927 928 depth = 1; 929 for (;;) { 930 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); 931 saved_spec = ef10_filter_entry_spec(table, i); 932 if (saved_spec && ef10_filter_equal(spec, saved_spec) && 933 ef10_filter_same_dest(spec, saved_spec)) { 934 break; 935 } 936 if (depth == EF10_FILTER_SEARCH_LIMIT) { 937 rc = ENOENT; 938 goto fail1; 939 } 940 depth++; 941 } 942 943 EFSYS_UNLOCK(enp->en_eslp, state); 944 locked = B_FALSE; 945 946 rc = ef10_filter_delete_internal(enp, i); 947 if (rc != 0) 948 goto fail2; 949 950 return (0); 951 952 fail2: 953 EFSYS_PROBE(fail2); 954 955 fail1: 956 EFSYS_PROBE1(fail1, efx_rc_t, rc); 957 958 if (locked) 959 EFSYS_UNLOCK(enp->en_eslp, state); 960 961 return (rc); 962 } 963 964 static __checkReturn efx_rc_t 965 efx_mcdi_get_parser_disp_info( 966 __in efx_nic_t *enp, 967 __out_ecount(buffer_length) uint32_t *buffer, 968 __in size_t buffer_length, 969 __in boolean_t encap, 970 __out size_t *list_lengthp) 971 { 972 efx_mcdi_req_t req; 973 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PARSER_DISP_INFO_IN_LEN, 974 MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX); 975 size_t matches_count; 976 size_t list_size; 977 efx_rc_t rc; 978 979 req.emr_cmd = MC_CMD_GET_PARSER_DISP_INFO; 980 req.emr_in_buf = payload; 981 req.emr_in_length = MC_CMD_GET_PARSER_DISP_INFO_IN_LEN; 982 req.emr_out_buf = payload; 983 req.emr_out_length = MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX; 984 985 MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, encap ? 986 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_ENCAP_RX_MATCHES : 987 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_RX_MATCHES); 988 989 efx_mcdi_execute(enp, &req); 990 991 if (req.emr_rc != 0) { 992 rc = req.emr_rc; 993 goto fail1; 994 } 995 996 matches_count = MCDI_OUT_DWORD(req, 997 GET_PARSER_DISP_INFO_OUT_NUM_SUPPORTED_MATCHES); 998 999 if (req.emr_out_length_used < 1000 MC_CMD_GET_PARSER_DISP_INFO_OUT_LEN(matches_count)) { 1001 rc = EMSGSIZE; 1002 goto fail2; 1003 } 1004 1005 *list_lengthp = matches_count; 1006 1007 if (buffer_length < matches_count) { 1008 rc = ENOSPC; 1009 goto fail3; 1010 } 1011 1012 /* 1013 * Check that the elements in the list in the MCDI response are the size 1014 * we expect, so we can just copy them directly. Any conversion of the 1015 * flags is handled by the caller. 1016 */ 1017 EFX_STATIC_ASSERT(sizeof (uint32_t) == 1018 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN); 1019 1020 list_size = matches_count * 1021 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN; 1022 memcpy(buffer, 1023 MCDI_OUT2(req, uint32_t, 1024 GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES), 1025 list_size); 1026 1027 return (0); 1028 1029 fail3: 1030 EFSYS_PROBE(fail3); 1031 fail2: 1032 EFSYS_PROBE(fail2); 1033 fail1: 1034 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1035 1036 return (rc); 1037 } 1038 1039 __checkReturn efx_rc_t 1040 ef10_filter_supported_filters( 1041 __in efx_nic_t *enp, 1042 __out_ecount(buffer_length) uint32_t *buffer, 1043 __in size_t buffer_length, 1044 __out size_t *list_lengthp) 1045 { 1046 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1047 size_t mcdi_list_length; 1048 size_t mcdi_encap_list_length; 1049 size_t list_length; 1050 uint32_t i; 1051 uint32_t next_buf_idx; 1052 size_t next_buf_length; 1053 efx_rc_t rc; 1054 boolean_t no_space = B_FALSE; 1055 efx_filter_match_flags_t all_filter_flags = 1056 (EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_LOC_HOST | 1057 EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_REM_PORT | 1058 EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | 1059 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | 1060 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | 1061 EFX_FILTER_MATCH_VNI_OR_VSID | 1062 EFX_FILTER_MATCH_IFRM_LOC_MAC | 1063 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | 1064 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | 1065 EFX_FILTER_MATCH_ENCAP_TYPE | 1066 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | 1067 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); 1068 1069 /* 1070 * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the 1071 * list of supported filters for ordinary packets, and then another to 1072 * get the list of supported filters for encapsulated packets. To 1073 * distinguish the second list from the first, the 1074 * EFX_FILTER_MATCH_ENCAP_TYPE flag is added to each filter for 1075 * encapsulated packets. 1076 */ 1077 rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, 1078 &mcdi_list_length); 1079 if (rc != 0) { 1080 if (rc == ENOSPC) 1081 no_space = B_TRUE; 1082 else 1083 goto fail1; 1084 } 1085 1086 if (no_space) { 1087 next_buf_idx = 0; 1088 next_buf_length = 0; 1089 } else { 1090 EFSYS_ASSERT(mcdi_list_length <= buffer_length); 1091 next_buf_idx = mcdi_list_length; 1092 next_buf_length = buffer_length - mcdi_list_length; 1093 } 1094 1095 if (encp->enc_tunnel_encapsulations_supported != 0) { 1096 rc = efx_mcdi_get_parser_disp_info(enp, &buffer[next_buf_idx], 1097 next_buf_length, B_TRUE, &mcdi_encap_list_length); 1098 if (rc != 0) { 1099 if (rc == ENOSPC) 1100 no_space = B_TRUE; 1101 else 1102 goto fail2; 1103 } else { 1104 for (i = next_buf_idx; 1105 i < next_buf_idx + mcdi_encap_list_length; i++) 1106 buffer[i] |= EFX_FILTER_MATCH_ENCAP_TYPE; 1107 } 1108 } else { 1109 mcdi_encap_list_length = 0; 1110 } 1111 1112 if (no_space) { 1113 *list_lengthp = mcdi_list_length + mcdi_encap_list_length; 1114 rc = ENOSPC; 1115 goto fail3; 1116 } 1117 1118 /* 1119 * The static assertions in ef10_filter_init() ensure that the values of 1120 * the EFX_FILTER_MATCH flags match those used by MCDI, so they don't 1121 * need to be converted. 1122 * 1123 * In case support is added to MCDI for additional flags, remove any 1124 * matches from the list which include flags we don't support. The order 1125 * of the matches is preserved as they are ordered from highest to 1126 * lowest priority. 1127 */ 1128 EFSYS_ASSERT(mcdi_list_length + mcdi_encap_list_length <= 1129 buffer_length); 1130 list_length = 0; 1131 for (i = 0; i < mcdi_list_length + mcdi_encap_list_length; i++) { 1132 if ((buffer[i] & ~all_filter_flags) == 0) { 1133 buffer[list_length] = buffer[i]; 1134 list_length++; 1135 } 1136 } 1137 1138 *list_lengthp = list_length; 1139 1140 return (0); 1141 1142 fail3: 1143 EFSYS_PROBE(fail3); 1144 fail2: 1145 EFSYS_PROBE(fail2); 1146 fail1: 1147 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1148 1149 return (rc); 1150 } 1151 1152 static __checkReturn efx_rc_t 1153 ef10_filter_insert_unicast( 1154 __in efx_nic_t *enp, 1155 __in_ecount(6) uint8_t const *addr, 1156 __in efx_filter_flags_t filter_flags) 1157 { 1158 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1159 efx_filter_spec_t spec; 1160 efx_rc_t rc; 1161 1162 /* Insert the filter for the local station address */ 1163 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1164 filter_flags, 1165 eftp->eft_default_rxq); 1166 rc = efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC, 1167 addr); 1168 if (rc != 0) 1169 goto fail1; 1170 1171 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1172 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); 1173 if (rc != 0) 1174 goto fail2; 1175 1176 eftp->eft_unicst_filter_count++; 1177 EFSYS_ASSERT(eftp->eft_unicst_filter_count <= 1178 EFX_EF10_FILTER_UNICAST_FILTERS_MAX); 1179 1180 return (0); 1181 1182 fail2: 1183 EFSYS_PROBE(fail2); 1184 fail1: 1185 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1186 return (rc); 1187 } 1188 1189 static __checkReturn efx_rc_t 1190 ef10_filter_insert_all_unicast( 1191 __in efx_nic_t *enp, 1192 __in efx_filter_flags_t filter_flags) 1193 { 1194 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1195 efx_filter_spec_t spec; 1196 efx_rc_t rc; 1197 1198 /* Insert the unknown unicast filter */ 1199 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1200 filter_flags, 1201 eftp->eft_default_rxq); 1202 rc = efx_filter_spec_set_uc_def(&spec); 1203 if (rc != 0) 1204 goto fail1; 1205 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1206 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); 1207 if (rc != 0) 1208 goto fail2; 1209 1210 eftp->eft_unicst_filter_count++; 1211 EFSYS_ASSERT(eftp->eft_unicst_filter_count <= 1212 EFX_EF10_FILTER_UNICAST_FILTERS_MAX); 1213 1214 return (0); 1215 1216 fail2: 1217 EFSYS_PROBE(fail2); 1218 fail1: 1219 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1220 return (rc); 1221 } 1222 1223 static __checkReturn efx_rc_t 1224 ef10_filter_insert_multicast_list( 1225 __in efx_nic_t *enp, 1226 __in boolean_t mulcst, 1227 __in boolean_t brdcst, 1228 __in_ecount(6*count) uint8_t const *addrs, 1229 __in uint32_t count, 1230 __in efx_filter_flags_t filter_flags, 1231 __in boolean_t rollback) 1232 { 1233 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1234 efx_filter_spec_t spec; 1235 uint8_t addr[6]; 1236 uint32_t i; 1237 uint32_t filter_index; 1238 uint32_t filter_count; 1239 efx_rc_t rc; 1240 1241 if (mulcst == B_FALSE) 1242 count = 0; 1243 1244 if (count + (brdcst ? 1 : 0) > 1245 EFX_ARRAY_SIZE(eftp->eft_mulcst_filter_indexes)) { 1246 /* Too many MAC addresses */ 1247 rc = EINVAL; 1248 goto fail1; 1249 } 1250 1251 /* Insert/renew multicast address list filters */ 1252 filter_count = 0; 1253 for (i = 0; i < count; i++) { 1254 efx_filter_spec_init_rx(&spec, 1255 EFX_FILTER_PRI_AUTO, 1256 filter_flags, 1257 eftp->eft_default_rxq); 1258 1259 rc = efx_filter_spec_set_eth_local(&spec, 1260 EFX_FILTER_SPEC_VID_UNSPEC, 1261 &addrs[i * EFX_MAC_ADDR_LEN]); 1262 if (rc != 0) { 1263 if (rollback == B_TRUE) { 1264 /* Only stop upon failure if told to rollback */ 1265 goto rollback; 1266 } else { 1267 /* 1268 * Don't try to add a filter with a corrupt 1269 * specification. 1270 */ 1271 continue; 1272 } 1273 } 1274 1275 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1276 &filter_index); 1277 1278 if (rc == 0) { 1279 eftp->eft_mulcst_filter_indexes[filter_count] = 1280 filter_index; 1281 filter_count++; 1282 } else if (rollback == B_TRUE) { 1283 /* Only stop upon failure if told to rollback */ 1284 goto rollback; 1285 } 1286 } 1287 1288 if (brdcst == B_TRUE) { 1289 /* Insert/renew broadcast address filter */ 1290 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1291 filter_flags, 1292 eftp->eft_default_rxq); 1293 1294 EFX_MAC_BROADCAST_ADDR_SET(addr); 1295 rc = efx_filter_spec_set_eth_local(&spec, 1296 EFX_FILTER_SPEC_VID_UNSPEC, addr); 1297 if ((rc != 0) && (rollback == B_TRUE)) { 1298 /* Only stop upon failure if told to rollback */ 1299 goto rollback; 1300 } 1301 1302 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1303 &filter_index); 1304 1305 if (rc == 0) { 1306 eftp->eft_mulcst_filter_indexes[filter_count] = 1307 filter_index; 1308 filter_count++; 1309 } else if (rollback == B_TRUE) { 1310 /* Only stop upon failure if told to rollback */ 1311 goto rollback; 1312 } 1313 } 1314 1315 eftp->eft_mulcst_filter_count = filter_count; 1316 eftp->eft_using_all_mulcst = B_FALSE; 1317 1318 return (0); 1319 1320 rollback: 1321 /* Remove any filters we have inserted */ 1322 i = filter_count; 1323 while (i--) { 1324 (void) ef10_filter_delete_internal(enp, 1325 eftp->eft_mulcst_filter_indexes[i]); 1326 } 1327 eftp->eft_mulcst_filter_count = 0; 1328 1329 fail1: 1330 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1331 1332 return (rc); 1333 } 1334 1335 static __checkReturn efx_rc_t 1336 ef10_filter_insert_all_multicast( 1337 __in efx_nic_t *enp, 1338 __in efx_filter_flags_t filter_flags) 1339 { 1340 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1341 efx_filter_spec_t spec; 1342 efx_rc_t rc; 1343 1344 /* Insert the unknown multicast filter */ 1345 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1346 filter_flags, 1347 eftp->eft_default_rxq); 1348 rc = efx_filter_spec_set_mc_def(&spec); 1349 if (rc != 0) 1350 goto fail1; 1351 1352 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1353 &eftp->eft_mulcst_filter_indexes[0]); 1354 if (rc != 0) 1355 goto fail2; 1356 1357 eftp->eft_mulcst_filter_count = 1; 1358 eftp->eft_using_all_mulcst = B_TRUE; 1359 1360 /* 1361 * FIXME: If brdcst == B_FALSE, add a filter to drop broadcast traffic. 1362 */ 1363 1364 return (0); 1365 1366 fail2: 1367 EFSYS_PROBE(fail2); 1368 fail1: 1369 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1370 1371 return (rc); 1372 } 1373 1374 typedef struct ef10_filter_encap_entry_s { 1375 uint16_t ether_type; 1376 efx_tunnel_protocol_t encap_type; 1377 uint32_t inner_frame_match; 1378 } ef10_filter_encap_entry_t; 1379 1380 #define EF10_ENCAP_FILTER_ENTRY(ipv, encap_type, inner_frame_match) \ 1381 { EFX_ETHER_TYPE_##ipv, EFX_TUNNEL_PROTOCOL_##encap_type, \ 1382 EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_##inner_frame_match } 1383 1384 static ef10_filter_encap_entry_t ef10_filter_encap_list[] = { 1385 EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, UCAST_DST), 1386 EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, MCAST_DST), 1387 EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, UCAST_DST), 1388 EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, MCAST_DST), 1389 1390 EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, UCAST_DST), 1391 EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, MCAST_DST), 1392 EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, UCAST_DST), 1393 EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, MCAST_DST), 1394 1395 EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, UCAST_DST), 1396 EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, MCAST_DST), 1397 EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, UCAST_DST), 1398 EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, MCAST_DST), 1399 }; 1400 1401 #undef EF10_ENCAP_FILTER_ENTRY 1402 1403 static __checkReturn efx_rc_t 1404 ef10_filter_insert_encap_filters( 1405 __in efx_nic_t *enp, 1406 __in boolean_t mulcst, 1407 __in efx_filter_flags_t filter_flags) 1408 { 1409 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1410 uint32_t i; 1411 efx_rc_t rc; 1412 1413 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(ef10_filter_encap_list) <= 1414 EFX_ARRAY_SIZE(table->eft_encap_filter_indexes)); 1415 1416 /* 1417 * On Medford, full-featured firmware can identify packets as being 1418 * tunnel encapsulated, even if no encapsulated packet offloads are in 1419 * use. When packets are identified as such, ordinary filters are not 1420 * applied, only ones specific to encapsulated packets. Hence we need to 1421 * insert filters for encapsulated packets in order to receive them. 1422 * 1423 * Separate filters need to be inserted for each ether type, 1424 * encapsulation type, and inner frame type (unicast or multicast). To 1425 * keep things simple and reduce the number of filters needed, catch-all 1426 * filters for all combinations of types are inserted, even if 1427 * all_unicst or all_mulcst have not been set. (These catch-all filters 1428 * may well, however, fail to insert on unprivileged functions.) 1429 */ 1430 table->eft_encap_filter_count = 0; 1431 for (i = 0; i < EFX_ARRAY_SIZE(ef10_filter_encap_list); i++) { 1432 efx_filter_spec_t spec; 1433 ef10_filter_encap_entry_t *encap_filter = 1434 &ef10_filter_encap_list[i]; 1435 1436 /* 1437 * Skip multicast filters if we've not been asked for 1438 * any multicast traffic. 1439 */ 1440 if ((mulcst == B_FALSE) && 1441 (encap_filter->inner_frame_match == 1442 EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST)) 1443 continue; 1444 1445 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1446 filter_flags, 1447 table->eft_default_rxq); 1448 efx_filter_spec_set_ether_type(&spec, encap_filter->ether_type); 1449 rc = efx_filter_spec_set_encap_type(&spec, 1450 encap_filter->encap_type, 1451 encap_filter->inner_frame_match); 1452 if (rc != 0) 1453 goto fail1; 1454 1455 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1456 &table->eft_encap_filter_indexes[ 1457 table->eft_encap_filter_count]); 1458 if (rc != 0) { 1459 if (rc != EACCES) 1460 goto fail2; 1461 } else { 1462 table->eft_encap_filter_count++; 1463 } 1464 } 1465 1466 return (0); 1467 1468 fail2: 1469 EFSYS_PROBE(fail2); 1470 fail1: 1471 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1472 1473 return (rc); 1474 } 1475 1476 static void 1477 ef10_filter_remove_old( 1478 __in efx_nic_t *enp) 1479 { 1480 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1481 uint32_t i; 1482 1483 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) { 1484 if (ef10_filter_entry_is_auto_old(table, i)) { 1485 (void) ef10_filter_delete_internal(enp, i); 1486 } 1487 } 1488 } 1489 1490 static __checkReturn efx_rc_t 1491 ef10_filter_get_workarounds( 1492 __in efx_nic_t *enp) 1493 { 1494 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1495 uint32_t implemented = 0; 1496 uint32_t enabled = 0; 1497 efx_rc_t rc; 1498 1499 rc = efx_mcdi_get_workarounds(enp, &implemented, &enabled); 1500 if (rc == 0) { 1501 /* Check if chained multicast filter support is enabled */ 1502 if (implemented & enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807) 1503 encp->enc_bug26807_workaround = B_TRUE; 1504 else 1505 encp->enc_bug26807_workaround = B_FALSE; 1506 } else if (rc == ENOTSUP) { 1507 /* 1508 * Firmware is too old to support GET_WORKAROUNDS, and support 1509 * for this workaround was implemented later. 1510 */ 1511 encp->enc_bug26807_workaround = B_FALSE; 1512 } else { 1513 goto fail1; 1514 } 1515 1516 return (0); 1517 1518 fail1: 1519 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1520 1521 return (rc); 1522 1523 } 1524 1525 /* 1526 * Reconfigure all filters. 1527 * If all_unicst and/or all mulcst filters cannot be applied then 1528 * return ENOTSUP (Note the filters for the specified addresses are 1529 * still applied in this case). 1530 */ 1531 __checkReturn efx_rc_t 1532 ef10_filter_reconfigure( 1533 __in efx_nic_t *enp, 1534 __in_ecount(6) uint8_t const *mac_addr, 1535 __in boolean_t all_unicst, 1536 __in boolean_t mulcst, 1537 __in boolean_t all_mulcst, 1538 __in boolean_t brdcst, 1539 __in_ecount(6*count) uint8_t const *addrs, 1540 __in uint32_t count) 1541 { 1542 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1543 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1544 efx_filter_flags_t filter_flags; 1545 unsigned int i; 1546 efx_rc_t all_unicst_rc = 0; 1547 efx_rc_t all_mulcst_rc = 0; 1548 efx_rc_t rc; 1549 1550 if (table->eft_default_rxq == NULL) { 1551 /* 1552 * Filters direct traffic to the default RXQ, and so cannot be 1553 * inserted until it is available. Any currently configured 1554 * filters must be removed (ignore errors in case the MC 1555 * has rebooted, which removes hardware filters). 1556 */ 1557 for (i = 0; i < table->eft_unicst_filter_count; i++) { 1558 (void) ef10_filter_delete_internal(enp, 1559 table->eft_unicst_filter_indexes[i]); 1560 } 1561 table->eft_unicst_filter_count = 0; 1562 1563 for (i = 0; i < table->eft_mulcst_filter_count; i++) { 1564 (void) ef10_filter_delete_internal(enp, 1565 table->eft_mulcst_filter_indexes[i]); 1566 } 1567 table->eft_mulcst_filter_count = 0; 1568 1569 for (i = 0; i < table->eft_encap_filter_count; i++) { 1570 (void) ef10_filter_delete_internal(enp, 1571 table->eft_encap_filter_indexes[i]); 1572 } 1573 table->eft_encap_filter_count = 0; 1574 1575 return (0); 1576 } 1577 1578 if (table->eft_using_rss) 1579 filter_flags = EFX_FILTER_FLAG_RX_RSS; 1580 else 1581 filter_flags = 0; 1582 1583 /* Mark old filters which may need to be removed */ 1584 for (i = 0; i < table->eft_unicst_filter_count; i++) { 1585 ef10_filter_set_entry_auto_old(table, 1586 table->eft_unicst_filter_indexes[i]); 1587 } 1588 for (i = 0; i < table->eft_mulcst_filter_count; i++) { 1589 ef10_filter_set_entry_auto_old(table, 1590 table->eft_mulcst_filter_indexes[i]); 1591 } 1592 for (i = 0; i < table->eft_encap_filter_count; i++) { 1593 ef10_filter_set_entry_auto_old(table, 1594 table->eft_encap_filter_indexes[i]); 1595 } 1596 1597 /* 1598 * Insert or renew unicast filters. 1599 * 1600 * Firmware does not perform chaining on unicast filters. As traffic is 1601 * therefore only delivered to the first matching filter, we should 1602 * always insert the specific filter for our MAC address, to try and 1603 * ensure we get that traffic. 1604 * 1605 * (If the filter for our MAC address has already been inserted by 1606 * another function, we won't receive traffic sent to us, even if we 1607 * insert a unicast mismatch filter. To prevent traffic stealing, this 1608 * therefore relies on the privilege model only allowing functions to 1609 * insert filters for their own MAC address unless explicitly given 1610 * additional privileges by the user. This also means that, even on a 1611 * priviliged function, inserting a unicast mismatch filter may not 1612 * catch all traffic in multi PCI function scenarios.) 1613 */ 1614 table->eft_unicst_filter_count = 0; 1615 rc = ef10_filter_insert_unicast(enp, mac_addr, filter_flags); 1616 if (all_unicst || (rc != 0)) { 1617 all_unicst_rc = ef10_filter_insert_all_unicast(enp, 1618 filter_flags); 1619 if ((rc != 0) && (all_unicst_rc != 0)) 1620 goto fail1; 1621 } 1622 1623 /* 1624 * WORKAROUND_BUG26807 controls firmware support for chained multicast 1625 * filters, and can only be enabled or disabled when the hardware filter 1626 * table is empty. 1627 * 1628 * Chained multicast filters require support from the datapath firmware, 1629 * and may not be available (e.g. low-latency variants or old Huntington 1630 * firmware). 1631 * 1632 * Firmware will reset (FLR) functions which have inserted filters in 1633 * the hardware filter table when the workaround is enabled/disabled. 1634 * Functions without any hardware filters are not reset. 1635 * 1636 * Re-check if the workaround is enabled after adding unicast hardware 1637 * filters. This ensures that encp->enc_bug26807_workaround matches the 1638 * firmware state, and that later changes to enable/disable the 1639 * workaround will result in this function seeing a reset (FLR). 1640 * 1641 * In common-code drivers, we only support multiple PCI function 1642 * scenarios with firmware that supports multicast chaining, so we can 1643 * assume it is enabled for such cases and hence simplify the filter 1644 * insertion logic. Firmware that does not support multicast chaining 1645 * does not support multiple PCI function configurations either, so 1646 * filter insertion is much simpler and the same strategies can still be 1647 * used. 1648 */ 1649 if ((rc = ef10_filter_get_workarounds(enp)) != 0) 1650 goto fail2; 1651 1652 if ((table->eft_using_all_mulcst != all_mulcst) && 1653 (encp->enc_bug26807_workaround == B_TRUE)) { 1654 /* 1655 * Multicast filter chaining is enabled, so traffic that matches 1656 * more than one multicast filter will be replicated and 1657 * delivered to multiple recipients. To avoid this duplicate 1658 * delivery, remove old multicast filters before inserting new 1659 * multicast filters. 1660 */ 1661 ef10_filter_remove_old(enp); 1662 } 1663 1664 /* Insert or renew multicast filters */ 1665 if (all_mulcst == B_TRUE) { 1666 /* 1667 * Insert the all multicast filter. If that fails, try to insert 1668 * all of our multicast filters (but without rollback on 1669 * failure). 1670 */ 1671 all_mulcst_rc = ef10_filter_insert_all_multicast(enp, 1672 filter_flags); 1673 if (all_mulcst_rc != 0) { 1674 rc = ef10_filter_insert_multicast_list(enp, B_TRUE, 1675 brdcst, addrs, count, filter_flags, B_FALSE); 1676 if (rc != 0) 1677 goto fail3; 1678 } 1679 } else { 1680 /* 1681 * Insert filters for multicast addresses. 1682 * If any insertion fails, then rollback and try to insert the 1683 * all multicast filter instead. 1684 * If that also fails, try to insert all of the multicast 1685 * filters (but without rollback on failure). 1686 */ 1687 rc = ef10_filter_insert_multicast_list(enp, mulcst, brdcst, 1688 addrs, count, filter_flags, B_TRUE); 1689 if (rc != 0) { 1690 if ((table->eft_using_all_mulcst == B_FALSE) && 1691 (encp->enc_bug26807_workaround == B_TRUE)) { 1692 /* 1693 * Multicast filter chaining is on, so remove 1694 * old filters before inserting the multicast 1695 * all filter to avoid duplicate delivery caused 1696 * by packets matching multiple filters. 1697 */ 1698 ef10_filter_remove_old(enp); 1699 } 1700 1701 rc = ef10_filter_insert_all_multicast(enp, 1702 filter_flags); 1703 if (rc != 0) { 1704 rc = ef10_filter_insert_multicast_list(enp, 1705 mulcst, brdcst, 1706 addrs, count, filter_flags, B_FALSE); 1707 if (rc != 0) 1708 goto fail4; 1709 } 1710 } 1711 } 1712 1713 if (encp->enc_tunnel_encapsulations_supported != 0) { 1714 /* Try to insert filters for encapsulated packets. */ 1715 (void) ef10_filter_insert_encap_filters(enp, 1716 mulcst || all_mulcst || brdcst, 1717 filter_flags); 1718 } 1719 1720 /* Remove old filters which were not renewed */ 1721 ef10_filter_remove_old(enp); 1722 1723 /* report if any optional flags were rejected */ 1724 if (((all_unicst != B_FALSE) && (all_unicst_rc != 0)) || 1725 ((all_mulcst != B_FALSE) && (all_mulcst_rc != 0))) { 1726 rc = ENOTSUP; 1727 } 1728 1729 return (rc); 1730 1731 fail4: 1732 EFSYS_PROBE(fail4); 1733 fail3: 1734 EFSYS_PROBE(fail3); 1735 fail2: 1736 EFSYS_PROBE(fail2); 1737 fail1: 1738 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1739 1740 /* Clear auto old flags */ 1741 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) { 1742 if (ef10_filter_entry_is_auto_old(table, i)) { 1743 ef10_filter_set_entry_not_auto_old(table, i); 1744 } 1745 } 1746 1747 return (rc); 1748 } 1749 1750 void 1751 ef10_filter_get_default_rxq( 1752 __in efx_nic_t *enp, 1753 __out efx_rxq_t **erpp, 1754 __out boolean_t *using_rss) 1755 { 1756 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1757 1758 *erpp = table->eft_default_rxq; 1759 *using_rss = table->eft_using_rss; 1760 } 1761 1762 void 1763 ef10_filter_default_rxq_set( 1764 __in efx_nic_t *enp, 1765 __in efx_rxq_t *erp, 1766 __in boolean_t using_rss) 1767 { 1768 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1769 1770 #if EFSYS_OPT_RX_SCALE 1771 EFSYS_ASSERT((using_rss == B_FALSE) || 1772 (enp->en_rss_context != EF10_RSS_CONTEXT_INVALID)); 1773 table->eft_using_rss = using_rss; 1774 #else 1775 EFSYS_ASSERT(using_rss == B_FALSE); 1776 table->eft_using_rss = B_FALSE; 1777 #endif 1778 table->eft_default_rxq = erp; 1779 } 1780 1781 void 1782 ef10_filter_default_rxq_clear( 1783 __in efx_nic_t *enp) 1784 { 1785 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1786 1787 table->eft_default_rxq = NULL; 1788 table->eft_using_rss = B_FALSE; 1789 } 1790 1791 #endif /* EFSYS_OPT_FILTER */ 1792 1793 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 1794