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