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 581 EFSYS_LOCK(enp->en_eslp, state); 582 583 spec = ef10_filter_entry_spec(eftp, tbl_id); 584 if (spec == NULL) { 585 restoring = B_FALSE; 586 } else if (ef10_filter_entry_is_busy(eftp, tbl_id)) { 587 /* Ignore busy entries. */ 588 restoring = B_FALSE; 589 } else { 590 ef10_filter_set_entry_busy(eftp, tbl_id); 591 restoring = B_TRUE; 592 } 593 594 EFSYS_UNLOCK(enp->en_eslp, state); 595 596 if (restoring == B_FALSE) 597 continue; 598 599 if (ef10_filter_is_exclusive(spec)) { 600 rc = efx_mcdi_filter_op_add(enp, spec, 601 MC_CMD_FILTER_OP_IN_OP_INSERT, 602 &eftp->eft_entry[tbl_id].efe_handle); 603 } else { 604 rc = efx_mcdi_filter_op_add(enp, spec, 605 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE, 606 &eftp->eft_entry[tbl_id].efe_handle); 607 } 608 609 if (rc != 0) 610 goto fail1; 611 612 EFSYS_LOCK(enp->en_eslp, state); 613 614 ef10_filter_set_entry_not_busy(eftp, tbl_id); 615 616 EFSYS_UNLOCK(enp->en_eslp, state); 617 } 618 619 return (0); 620 621 fail1: 622 EFSYS_PROBE1(fail1, efx_rc_t, rc); 623 624 return (rc); 625 } 626 627 /* 628 * An arbitrary search limit for the software hash table. As per the linux net 629 * driver. 630 */ 631 #define EF10_FILTER_SEARCH_LIMIT 200 632 633 static __checkReturn efx_rc_t 634 ef10_filter_add_internal( 635 __in efx_nic_t *enp, 636 __inout efx_filter_spec_t *spec, 637 __in boolean_t may_replace, 638 __out_opt uint32_t *filter_id) 639 { 640 efx_rc_t rc; 641 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 642 efx_filter_spec_t *saved_spec; 643 uint32_t hash; 644 unsigned int depth; 645 int ins_index; 646 boolean_t replacing = B_FALSE; 647 unsigned int i; 648 efsys_lock_state_t state; 649 boolean_t locked = B_FALSE; 650 651 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 652 enp->en_family == EFX_FAMILY_MEDFORD || 653 enp->en_family == EFX_FAMILY_MEDFORD2); 654 655 hash = ef10_filter_hash(spec); 656 657 /* 658 * FIXME: Add support for inserting filters of different priorities 659 * and removing lower priority multicast filters (bug 42378) 660 */ 661 662 /* 663 * Find any existing filters with the same match tuple or 664 * else a free slot to insert at. If any of them are busy, 665 * we have to wait and retry. 666 */ 667 for (;;) { 668 ins_index = -1; 669 depth = 1; 670 EFSYS_LOCK(enp->en_eslp, state); 671 locked = B_TRUE; 672 673 for (;;) { 674 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); 675 saved_spec = ef10_filter_entry_spec(eftp, i); 676 677 if (!saved_spec) { 678 if (ins_index < 0) { 679 ins_index = i; 680 } 681 } else if (ef10_filter_equal(spec, saved_spec)) { 682 if (ef10_filter_entry_is_busy(eftp, i)) 683 break; 684 if (saved_spec->efs_priority 685 == EFX_FILTER_PRI_AUTO) { 686 ins_index = i; 687 goto found; 688 } else if (ef10_filter_is_exclusive(spec)) { 689 if (may_replace) { 690 ins_index = i; 691 goto found; 692 } else { 693 rc = EEXIST; 694 goto fail1; 695 } 696 } 697 698 /* Leave existing */ 699 } 700 701 /* 702 * Once we reach the maximum search depth, use 703 * the first suitable slot or return EBUSY if 704 * there was none. 705 */ 706 if (depth == EF10_FILTER_SEARCH_LIMIT) { 707 if (ins_index < 0) { 708 rc = EBUSY; 709 goto fail2; 710 } 711 goto found; 712 } 713 depth++; 714 } 715 EFSYS_UNLOCK(enp->en_eslp, state); 716 locked = B_FALSE; 717 } 718 719 found: 720 /* 721 * Create a software table entry if necessary, and mark it 722 * busy. We might yet fail to insert, but any attempt to 723 * insert a conflicting filter while we're waiting for the 724 * firmware must find the busy entry. 725 */ 726 saved_spec = ef10_filter_entry_spec(eftp, ins_index); 727 if (saved_spec) { 728 if (saved_spec->efs_priority == EFX_FILTER_PRI_AUTO) { 729 /* This is a filter we are refreshing */ 730 ef10_filter_set_entry_not_auto_old(eftp, ins_index); 731 goto out_unlock; 732 733 } 734 replacing = B_TRUE; 735 } else { 736 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*spec), saved_spec); 737 if (!saved_spec) { 738 rc = ENOMEM; 739 goto fail3; 740 } 741 *saved_spec = *spec; 742 ef10_filter_set_entry(eftp, ins_index, saved_spec); 743 } 744 ef10_filter_set_entry_busy(eftp, ins_index); 745 746 EFSYS_UNLOCK(enp->en_eslp, state); 747 locked = B_FALSE; 748 749 /* 750 * On replacing the filter handle may change after after a successful 751 * replace operation. 752 */ 753 if (replacing) { 754 rc = efx_mcdi_filter_op_add(enp, spec, 755 MC_CMD_FILTER_OP_IN_OP_REPLACE, 756 &eftp->eft_entry[ins_index].efe_handle); 757 } else if (ef10_filter_is_exclusive(spec)) { 758 rc = efx_mcdi_filter_op_add(enp, spec, 759 MC_CMD_FILTER_OP_IN_OP_INSERT, 760 &eftp->eft_entry[ins_index].efe_handle); 761 } else { 762 rc = efx_mcdi_filter_op_add(enp, spec, 763 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE, 764 &eftp->eft_entry[ins_index].efe_handle); 765 } 766 767 if (rc != 0) 768 goto fail4; 769 770 EFSYS_LOCK(enp->en_eslp, state); 771 locked = B_TRUE; 772 773 if (replacing) { 774 /* Update the fields that may differ */ 775 saved_spec->efs_priority = spec->efs_priority; 776 saved_spec->efs_flags = spec->efs_flags; 777 saved_spec->efs_rss_context = spec->efs_rss_context; 778 saved_spec->efs_dmaq_id = spec->efs_dmaq_id; 779 } 780 781 ef10_filter_set_entry_not_busy(eftp, ins_index); 782 783 out_unlock: 784 785 EFSYS_UNLOCK(enp->en_eslp, state); 786 locked = B_FALSE; 787 788 if (filter_id) 789 *filter_id = ins_index; 790 791 return (0); 792 793 fail4: 794 EFSYS_PROBE(fail4); 795 796 if (!replacing) { 797 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), saved_spec); 798 saved_spec = NULL; 799 } 800 ef10_filter_set_entry_not_busy(eftp, ins_index); 801 ef10_filter_set_entry(eftp, ins_index, NULL); 802 803 fail3: 804 EFSYS_PROBE(fail3); 805 806 fail2: 807 EFSYS_PROBE(fail2); 808 809 fail1: 810 EFSYS_PROBE1(fail1, efx_rc_t, rc); 811 812 if (locked) 813 EFSYS_UNLOCK(enp->en_eslp, state); 814 815 return (rc); 816 } 817 818 __checkReturn efx_rc_t 819 ef10_filter_add( 820 __in efx_nic_t *enp, 821 __inout efx_filter_spec_t *spec, 822 __in boolean_t may_replace) 823 { 824 efx_rc_t rc; 825 826 rc = ef10_filter_add_internal(enp, spec, may_replace, NULL); 827 if (rc != 0) 828 goto fail1; 829 830 return (0); 831 832 fail1: 833 EFSYS_PROBE1(fail1, efx_rc_t, rc); 834 835 return (rc); 836 } 837 838 839 static __checkReturn efx_rc_t 840 ef10_filter_delete_internal( 841 __in efx_nic_t *enp, 842 __in uint32_t filter_id) 843 { 844 efx_rc_t rc; 845 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 846 efx_filter_spec_t *spec; 847 efsys_lock_state_t state; 848 uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS; 849 850 /* 851 * Find the software table entry and mark it busy. Don't 852 * remove it yet; any attempt to update while we're waiting 853 * for the firmware must find the busy entry. 854 * 855 * FIXME: What if the busy flag is never cleared? 856 */ 857 EFSYS_LOCK(enp->en_eslp, state); 858 while (ef10_filter_entry_is_busy(table, filter_idx)) { 859 EFSYS_UNLOCK(enp->en_eslp, state); 860 EFSYS_SPIN(1); 861 EFSYS_LOCK(enp->en_eslp, state); 862 } 863 if ((spec = ef10_filter_entry_spec(table, filter_idx)) != NULL) { 864 ef10_filter_set_entry_busy(table, filter_idx); 865 } 866 EFSYS_UNLOCK(enp->en_eslp, state); 867 868 if (spec == NULL) { 869 rc = ENOENT; 870 goto fail1; 871 } 872 873 /* 874 * Try to remove the hardware filter. This may fail if the MC has 875 * rebooted (which frees all hardware filter resources). 876 */ 877 if (ef10_filter_is_exclusive(spec)) { 878 rc = efx_mcdi_filter_op_delete(enp, 879 MC_CMD_FILTER_OP_IN_OP_REMOVE, 880 &table->eft_entry[filter_idx].efe_handle); 881 } else { 882 rc = efx_mcdi_filter_op_delete(enp, 883 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE, 884 &table->eft_entry[filter_idx].efe_handle); 885 } 886 887 /* Free the software table entry */ 888 EFSYS_LOCK(enp->en_eslp, state); 889 ef10_filter_set_entry_not_busy(table, filter_idx); 890 ef10_filter_set_entry(table, filter_idx, NULL); 891 EFSYS_UNLOCK(enp->en_eslp, state); 892 893 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec); 894 895 /* Check result of hardware filter removal */ 896 if (rc != 0) 897 goto fail2; 898 899 return (0); 900 901 fail2: 902 EFSYS_PROBE(fail2); 903 904 fail1: 905 EFSYS_PROBE1(fail1, efx_rc_t, rc); 906 907 return (rc); 908 } 909 910 __checkReturn efx_rc_t 911 ef10_filter_delete( 912 __in efx_nic_t *enp, 913 __inout efx_filter_spec_t *spec) 914 { 915 efx_rc_t rc; 916 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 917 efx_filter_spec_t *saved_spec; 918 unsigned int hash; 919 unsigned int depth; 920 unsigned int i; 921 efsys_lock_state_t state; 922 boolean_t locked = B_FALSE; 923 924 EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON || 925 enp->en_family == EFX_FAMILY_MEDFORD || 926 enp->en_family == EFX_FAMILY_MEDFORD2); 927 928 hash = ef10_filter_hash(spec); 929 930 EFSYS_LOCK(enp->en_eslp, state); 931 locked = B_TRUE; 932 933 depth = 1; 934 for (;;) { 935 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1); 936 saved_spec = ef10_filter_entry_spec(table, i); 937 if (saved_spec && ef10_filter_equal(spec, saved_spec) && 938 ef10_filter_same_dest(spec, saved_spec)) { 939 break; 940 } 941 if (depth == EF10_FILTER_SEARCH_LIMIT) { 942 rc = ENOENT; 943 goto fail1; 944 } 945 depth++; 946 } 947 948 EFSYS_UNLOCK(enp->en_eslp, state); 949 locked = B_FALSE; 950 951 rc = ef10_filter_delete_internal(enp, i); 952 if (rc != 0) 953 goto fail2; 954 955 return (0); 956 957 fail2: 958 EFSYS_PROBE(fail2); 959 960 fail1: 961 EFSYS_PROBE1(fail1, efx_rc_t, rc); 962 963 if (locked) 964 EFSYS_UNLOCK(enp->en_eslp, state); 965 966 return (rc); 967 } 968 969 static __checkReturn efx_rc_t 970 efx_mcdi_get_parser_disp_info( 971 __in efx_nic_t *enp, 972 __out_ecount(buffer_length) uint32_t *buffer, 973 __in size_t buffer_length, 974 __in boolean_t encap, 975 __out size_t *list_lengthp) 976 { 977 efx_mcdi_req_t req; 978 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PARSER_DISP_INFO_IN_LEN, 979 MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX); 980 size_t matches_count; 981 size_t list_size; 982 efx_rc_t rc; 983 984 req.emr_cmd = MC_CMD_GET_PARSER_DISP_INFO; 985 req.emr_in_buf = payload; 986 req.emr_in_length = MC_CMD_GET_PARSER_DISP_INFO_IN_LEN; 987 req.emr_out_buf = payload; 988 req.emr_out_length = MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX; 989 990 MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, encap ? 991 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_ENCAP_RX_MATCHES : 992 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_RX_MATCHES); 993 994 efx_mcdi_execute(enp, &req); 995 996 if (req.emr_rc != 0) { 997 rc = req.emr_rc; 998 goto fail1; 999 } 1000 1001 matches_count = MCDI_OUT_DWORD(req, 1002 GET_PARSER_DISP_INFO_OUT_NUM_SUPPORTED_MATCHES); 1003 1004 if (req.emr_out_length_used < 1005 MC_CMD_GET_PARSER_DISP_INFO_OUT_LEN(matches_count)) { 1006 rc = EMSGSIZE; 1007 goto fail2; 1008 } 1009 1010 *list_lengthp = matches_count; 1011 1012 if (buffer_length < matches_count) { 1013 rc = ENOSPC; 1014 goto fail3; 1015 } 1016 1017 /* 1018 * Check that the elements in the list in the MCDI response are the size 1019 * we expect, so we can just copy them directly. Any conversion of the 1020 * flags is handled by the caller. 1021 */ 1022 EFX_STATIC_ASSERT(sizeof (uint32_t) == 1023 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN); 1024 1025 list_size = matches_count * 1026 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN; 1027 memcpy(buffer, 1028 MCDI_OUT2(req, uint32_t, 1029 GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES), 1030 list_size); 1031 1032 return (0); 1033 1034 fail3: 1035 EFSYS_PROBE(fail3); 1036 fail2: 1037 EFSYS_PROBE(fail2); 1038 fail1: 1039 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1040 1041 return (rc); 1042 } 1043 1044 __checkReturn efx_rc_t 1045 ef10_filter_supported_filters( 1046 __in efx_nic_t *enp, 1047 __out_ecount(buffer_length) uint32_t *buffer, 1048 __in size_t buffer_length, 1049 __out size_t *list_lengthp) 1050 { 1051 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 1052 size_t mcdi_list_length; 1053 size_t mcdi_encap_list_length; 1054 size_t list_length; 1055 uint32_t i; 1056 uint32_t next_buf_idx; 1057 size_t next_buf_length; 1058 efx_rc_t rc; 1059 boolean_t no_space = B_FALSE; 1060 efx_filter_match_flags_t all_filter_flags = 1061 (EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_LOC_HOST | 1062 EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_REM_PORT | 1063 EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT | 1064 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID | 1065 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO | 1066 EFX_FILTER_MATCH_VNI_OR_VSID | 1067 EFX_FILTER_MATCH_IFRM_LOC_MAC | 1068 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST | 1069 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST | 1070 EFX_FILTER_MATCH_ENCAP_TYPE | 1071 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST | 1072 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST); 1073 1074 /* 1075 * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the 1076 * list of supported filters for ordinary packets, and then another to 1077 * get the list of supported filters for encapsulated packets. To 1078 * distinguish the second list from the first, the 1079 * EFX_FILTER_MATCH_ENCAP_TYPE flag is added to each filter for 1080 * encapsulated packets. 1081 */ 1082 rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE, 1083 &mcdi_list_length); 1084 if (rc != 0) { 1085 if (rc == ENOSPC) 1086 no_space = B_TRUE; 1087 else 1088 goto fail1; 1089 } 1090 1091 if (no_space) { 1092 next_buf_idx = 0; 1093 next_buf_length = 0; 1094 } else { 1095 EFSYS_ASSERT(mcdi_list_length <= buffer_length); 1096 next_buf_idx = mcdi_list_length; 1097 next_buf_length = buffer_length - mcdi_list_length; 1098 } 1099 1100 if (encp->enc_tunnel_encapsulations_supported != 0) { 1101 rc = efx_mcdi_get_parser_disp_info(enp, &buffer[next_buf_idx], 1102 next_buf_length, B_TRUE, &mcdi_encap_list_length); 1103 if (rc != 0) { 1104 if (rc == ENOSPC) 1105 no_space = B_TRUE; 1106 else 1107 goto fail2; 1108 } else { 1109 for (i = next_buf_idx; 1110 i < next_buf_idx + mcdi_encap_list_length; i++) 1111 buffer[i] |= EFX_FILTER_MATCH_ENCAP_TYPE; 1112 } 1113 } else { 1114 mcdi_encap_list_length = 0; 1115 } 1116 1117 if (no_space) { 1118 *list_lengthp = mcdi_list_length + mcdi_encap_list_length; 1119 rc = ENOSPC; 1120 goto fail3; 1121 } 1122 1123 /* 1124 * The static assertions in ef10_filter_init() ensure that the values of 1125 * the EFX_FILTER_MATCH flags match those used by MCDI, so they don't 1126 * need to be converted. 1127 * 1128 * In case support is added to MCDI for additional flags, remove any 1129 * matches from the list which include flags we don't support. The order 1130 * of the matches is preserved as they are ordered from highest to 1131 * lowest priority. 1132 */ 1133 EFSYS_ASSERT(mcdi_list_length + mcdi_encap_list_length <= 1134 buffer_length); 1135 list_length = 0; 1136 for (i = 0; i < mcdi_list_length + mcdi_encap_list_length; i++) { 1137 if ((buffer[i] & ~all_filter_flags) == 0) { 1138 buffer[list_length] = buffer[i]; 1139 list_length++; 1140 } 1141 } 1142 1143 *list_lengthp = list_length; 1144 1145 return (0); 1146 1147 fail3: 1148 EFSYS_PROBE(fail3); 1149 fail2: 1150 EFSYS_PROBE(fail2); 1151 fail1: 1152 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1153 1154 return (rc); 1155 } 1156 1157 static __checkReturn efx_rc_t 1158 ef10_filter_insert_unicast( 1159 __in efx_nic_t *enp, 1160 __in_ecount(6) uint8_t const *addr, 1161 __in efx_filter_flags_t filter_flags) 1162 { 1163 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1164 efx_filter_spec_t spec; 1165 efx_rc_t rc; 1166 1167 /* Insert the filter for the local station address */ 1168 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1169 filter_flags, 1170 eftp->eft_default_rxq); 1171 rc = efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC, 1172 addr); 1173 if (rc != 0) 1174 goto fail1; 1175 1176 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1177 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); 1178 if (rc != 0) 1179 goto fail2; 1180 1181 eftp->eft_unicst_filter_count++; 1182 EFSYS_ASSERT(eftp->eft_unicst_filter_count <= 1183 EFX_EF10_FILTER_UNICAST_FILTERS_MAX); 1184 1185 return (0); 1186 1187 fail2: 1188 EFSYS_PROBE(fail2); 1189 fail1: 1190 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1191 return (rc); 1192 } 1193 1194 static __checkReturn efx_rc_t 1195 ef10_filter_insert_all_unicast( 1196 __in efx_nic_t *enp, 1197 __in efx_filter_flags_t filter_flags) 1198 { 1199 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1200 efx_filter_spec_t spec; 1201 efx_rc_t rc; 1202 1203 /* Insert the unknown unicast filter */ 1204 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1205 filter_flags, 1206 eftp->eft_default_rxq); 1207 rc = efx_filter_spec_set_uc_def(&spec); 1208 if (rc != 0) 1209 goto fail1; 1210 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1211 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]); 1212 if (rc != 0) 1213 goto fail2; 1214 1215 eftp->eft_unicst_filter_count++; 1216 EFSYS_ASSERT(eftp->eft_unicst_filter_count <= 1217 EFX_EF10_FILTER_UNICAST_FILTERS_MAX); 1218 1219 return (0); 1220 1221 fail2: 1222 EFSYS_PROBE(fail2); 1223 fail1: 1224 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1225 return (rc); 1226 } 1227 1228 static __checkReturn efx_rc_t 1229 ef10_filter_insert_multicast_list( 1230 __in efx_nic_t *enp, 1231 __in boolean_t mulcst, 1232 __in boolean_t brdcst, 1233 __in_ecount(6*count) uint8_t const *addrs, 1234 __in uint32_t count, 1235 __in efx_filter_flags_t filter_flags, 1236 __in boolean_t rollback) 1237 { 1238 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1239 efx_filter_spec_t spec; 1240 uint8_t addr[6]; 1241 uint32_t i; 1242 uint32_t filter_index; 1243 uint32_t filter_count; 1244 efx_rc_t rc; 1245 1246 if (mulcst == B_FALSE) 1247 count = 0; 1248 1249 if (count + (brdcst ? 1 : 0) > 1250 EFX_ARRAY_SIZE(eftp->eft_mulcst_filter_indexes)) { 1251 /* Too many MAC addresses */ 1252 rc = EINVAL; 1253 goto fail1; 1254 } 1255 1256 /* Insert/renew multicast address list filters */ 1257 filter_count = 0; 1258 for (i = 0; i < count; i++) { 1259 efx_filter_spec_init_rx(&spec, 1260 EFX_FILTER_PRI_AUTO, 1261 filter_flags, 1262 eftp->eft_default_rxq); 1263 1264 rc = efx_filter_spec_set_eth_local(&spec, 1265 EFX_FILTER_SPEC_VID_UNSPEC, 1266 &addrs[i * EFX_MAC_ADDR_LEN]); 1267 if (rc != 0) { 1268 if (rollback == B_TRUE) { 1269 /* Only stop upon failure if told to rollback */ 1270 goto rollback; 1271 } else { 1272 /* 1273 * Don't try to add a filter with a corrupt 1274 * specification. 1275 */ 1276 continue; 1277 } 1278 } 1279 1280 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1281 &filter_index); 1282 1283 if (rc == 0) { 1284 eftp->eft_mulcst_filter_indexes[filter_count] = 1285 filter_index; 1286 filter_count++; 1287 } else if (rollback == B_TRUE) { 1288 /* Only stop upon failure if told to rollback */ 1289 goto rollback; 1290 } 1291 1292 } 1293 1294 if (brdcst == B_TRUE) { 1295 /* Insert/renew broadcast address filter */ 1296 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1297 filter_flags, 1298 eftp->eft_default_rxq); 1299 1300 EFX_MAC_BROADCAST_ADDR_SET(addr); 1301 rc = efx_filter_spec_set_eth_local(&spec, 1302 EFX_FILTER_SPEC_VID_UNSPEC, addr); 1303 if ((rc != 0) && (rollback == B_TRUE)) { 1304 /* Only stop upon failure if told to rollback */ 1305 goto rollback; 1306 } 1307 1308 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1309 &filter_index); 1310 1311 if (rc == 0) { 1312 eftp->eft_mulcst_filter_indexes[filter_count] = 1313 filter_index; 1314 filter_count++; 1315 } else if (rollback == B_TRUE) { 1316 /* Only stop upon failure if told to rollback */ 1317 goto rollback; 1318 } 1319 } 1320 1321 eftp->eft_mulcst_filter_count = filter_count; 1322 eftp->eft_using_all_mulcst = B_FALSE; 1323 1324 return (0); 1325 1326 rollback: 1327 /* Remove any filters we have inserted */ 1328 i = filter_count; 1329 while (i--) { 1330 (void) ef10_filter_delete_internal(enp, 1331 eftp->eft_mulcst_filter_indexes[i]); 1332 } 1333 eftp->eft_mulcst_filter_count = 0; 1334 1335 fail1: 1336 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1337 1338 return (rc); 1339 } 1340 1341 static __checkReturn efx_rc_t 1342 ef10_filter_insert_all_multicast( 1343 __in efx_nic_t *enp, 1344 __in efx_filter_flags_t filter_flags) 1345 { 1346 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table; 1347 efx_filter_spec_t spec; 1348 efx_rc_t rc; 1349 1350 /* Insert the unknown multicast filter */ 1351 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1352 filter_flags, 1353 eftp->eft_default_rxq); 1354 rc = efx_filter_spec_set_mc_def(&spec); 1355 if (rc != 0) 1356 goto fail1; 1357 1358 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1359 &eftp->eft_mulcst_filter_indexes[0]); 1360 if (rc != 0) 1361 goto fail2; 1362 1363 eftp->eft_mulcst_filter_count = 1; 1364 eftp->eft_using_all_mulcst = B_TRUE; 1365 1366 /* 1367 * FIXME: If brdcst == B_FALSE, add a filter to drop broadcast traffic. 1368 */ 1369 1370 return (0); 1371 1372 fail2: 1373 EFSYS_PROBE(fail2); 1374 fail1: 1375 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1376 1377 return (rc); 1378 } 1379 1380 typedef struct ef10_filter_encap_entry_s { 1381 uint16_t ether_type; 1382 efx_tunnel_protocol_t encap_type; 1383 uint32_t inner_frame_match; 1384 } ef10_filter_encap_entry_t; 1385 1386 #define EF10_ENCAP_FILTER_ENTRY(ipv, encap_type, inner_frame_match) \ 1387 { EFX_ETHER_TYPE_##ipv, EFX_TUNNEL_PROTOCOL_##encap_type, \ 1388 EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_##inner_frame_match } 1389 1390 static ef10_filter_encap_entry_t ef10_filter_encap_list[] = { 1391 EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, UCAST_DST), 1392 EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, MCAST_DST), 1393 EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, UCAST_DST), 1394 EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, MCAST_DST), 1395 1396 EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, UCAST_DST), 1397 EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, MCAST_DST), 1398 EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, UCAST_DST), 1399 EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, MCAST_DST), 1400 1401 EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, UCAST_DST), 1402 EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, MCAST_DST), 1403 EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, UCAST_DST), 1404 EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, MCAST_DST), 1405 }; 1406 1407 #undef EF10_ENCAP_FILTER_ENTRY 1408 1409 static __checkReturn efx_rc_t 1410 ef10_filter_insert_encap_filters( 1411 __in efx_nic_t *enp, 1412 __in boolean_t mulcst, 1413 __in efx_filter_flags_t filter_flags) 1414 { 1415 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1416 uint32_t i; 1417 efx_rc_t rc; 1418 1419 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(ef10_filter_encap_list) <= 1420 EFX_ARRAY_SIZE(table->eft_encap_filter_indexes)); 1421 1422 /* 1423 * On Medford, full-featured firmware can identify packets as being 1424 * tunnel encapsulated, even if no encapsulated packet offloads are in 1425 * use. When packets are identified as such, ordinary filters are not 1426 * applied, only ones specific to encapsulated packets. Hence we need to 1427 * insert filters for encapsulated packets in order to receive them. 1428 * 1429 * Separate filters need to be inserted for each ether type, 1430 * encapsulation type, and inner frame type (unicast or multicast). To 1431 * keep things simple and reduce the number of filters needed, catch-all 1432 * filters for all combinations of types are inserted, even if 1433 * all_unicst or all_mulcst have not been set. (These catch-all filters 1434 * may well, however, fail to insert on unprivileged functions.) 1435 */ 1436 table->eft_encap_filter_count = 0; 1437 for (i = 0; i < EFX_ARRAY_SIZE(ef10_filter_encap_list); i++) { 1438 efx_filter_spec_t spec; 1439 ef10_filter_encap_entry_t *encap_filter = 1440 &ef10_filter_encap_list[i]; 1441 1442 /* 1443 * Skip multicast filters if we've not been asked for 1444 * any multicast traffic. 1445 */ 1446 if ((mulcst == B_FALSE) && 1447 (encap_filter->inner_frame_match == 1448 EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST)) 1449 continue; 1450 1451 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO, 1452 filter_flags, 1453 table->eft_default_rxq); 1454 efx_filter_spec_set_ether_type(&spec, encap_filter->ether_type); 1455 rc = efx_filter_spec_set_encap_type(&spec, 1456 encap_filter->encap_type, 1457 encap_filter->inner_frame_match); 1458 if (rc != 0) 1459 goto fail1; 1460 1461 rc = ef10_filter_add_internal(enp, &spec, B_TRUE, 1462 &table->eft_encap_filter_indexes[ 1463 table->eft_encap_filter_count]); 1464 if (rc != 0) { 1465 if (rc != EACCES) 1466 goto fail2; 1467 } else { 1468 table->eft_encap_filter_count++; 1469 } 1470 } 1471 1472 return (0); 1473 1474 fail2: 1475 EFSYS_PROBE(fail2); 1476 fail1: 1477 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1478 1479 return (rc); 1480 } 1481 1482 static void 1483 ef10_filter_remove_old( 1484 __in efx_nic_t *enp) 1485 { 1486 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1487 uint32_t i; 1488 1489 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) { 1490 if (ef10_filter_entry_is_auto_old(table, i)) { 1491 (void) ef10_filter_delete_internal(enp, i); 1492 } 1493 } 1494 } 1495 1496 1497 static __checkReturn efx_rc_t 1498 ef10_filter_get_workarounds( 1499 __in efx_nic_t *enp) 1500 { 1501 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1502 uint32_t implemented = 0; 1503 uint32_t enabled = 0; 1504 efx_rc_t rc; 1505 1506 rc = efx_mcdi_get_workarounds(enp, &implemented, &enabled); 1507 if (rc == 0) { 1508 /* Check if chained multicast filter support is enabled */ 1509 if (implemented & enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807) 1510 encp->enc_bug26807_workaround = B_TRUE; 1511 else 1512 encp->enc_bug26807_workaround = B_FALSE; 1513 } else if (rc == ENOTSUP) { 1514 /* 1515 * Firmware is too old to support GET_WORKAROUNDS, and support 1516 * for this workaround was implemented later. 1517 */ 1518 encp->enc_bug26807_workaround = B_FALSE; 1519 } else { 1520 goto fail1; 1521 } 1522 1523 return (0); 1524 1525 fail1: 1526 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1527 1528 return (rc); 1529 1530 } 1531 1532 1533 /* 1534 * Reconfigure all filters. 1535 * If all_unicst and/or all mulcst filters cannot be applied then 1536 * return ENOTSUP (Note the filters for the specified addresses are 1537 * still applied in this case). 1538 */ 1539 __checkReturn efx_rc_t 1540 ef10_filter_reconfigure( 1541 __in efx_nic_t *enp, 1542 __in_ecount(6) uint8_t const *mac_addr, 1543 __in boolean_t all_unicst, 1544 __in boolean_t mulcst, 1545 __in boolean_t all_mulcst, 1546 __in boolean_t brdcst, 1547 __in_ecount(6*count) uint8_t const *addrs, 1548 __in uint32_t count) 1549 { 1550 efx_nic_cfg_t *encp = &enp->en_nic_cfg; 1551 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1552 efx_filter_flags_t filter_flags; 1553 unsigned int i; 1554 efx_rc_t all_unicst_rc = 0; 1555 efx_rc_t all_mulcst_rc = 0; 1556 efx_rc_t rc; 1557 1558 if (table->eft_default_rxq == NULL) { 1559 /* 1560 * Filters direct traffic to the default RXQ, and so cannot be 1561 * inserted until it is available. Any currently configured 1562 * filters must be removed (ignore errors in case the MC 1563 * has rebooted, which removes hardware filters). 1564 */ 1565 for (i = 0; i < table->eft_unicst_filter_count; i++) { 1566 (void) ef10_filter_delete_internal(enp, 1567 table->eft_unicst_filter_indexes[i]); 1568 } 1569 table->eft_unicst_filter_count = 0; 1570 1571 for (i = 0; i < table->eft_mulcst_filter_count; i++) { 1572 (void) ef10_filter_delete_internal(enp, 1573 table->eft_mulcst_filter_indexes[i]); 1574 } 1575 table->eft_mulcst_filter_count = 0; 1576 1577 for (i = 0; i < table->eft_encap_filter_count; i++) { 1578 (void) ef10_filter_delete_internal(enp, 1579 table->eft_encap_filter_indexes[i]); 1580 } 1581 table->eft_encap_filter_count = 0; 1582 1583 return (0); 1584 } 1585 1586 if (table->eft_using_rss) 1587 filter_flags = EFX_FILTER_FLAG_RX_RSS; 1588 else 1589 filter_flags = 0; 1590 1591 /* Mark old filters which may need to be removed */ 1592 for (i = 0; i < table->eft_unicst_filter_count; i++) { 1593 ef10_filter_set_entry_auto_old(table, 1594 table->eft_unicst_filter_indexes[i]); 1595 } 1596 for (i = 0; i < table->eft_mulcst_filter_count; i++) { 1597 ef10_filter_set_entry_auto_old(table, 1598 table->eft_mulcst_filter_indexes[i]); 1599 } 1600 for (i = 0; i < table->eft_encap_filter_count; i++) { 1601 ef10_filter_set_entry_auto_old(table, 1602 table->eft_encap_filter_indexes[i]); 1603 } 1604 1605 /* 1606 * Insert or renew unicast filters. 1607 * 1608 * Firmware does not perform chaining on unicast filters. As traffic is 1609 * therefore only delivered to the first matching filter, we should 1610 * always insert the specific filter for our MAC address, to try and 1611 * ensure we get that traffic. 1612 * 1613 * (If the filter for our MAC address has already been inserted by 1614 * another function, we won't receive traffic sent to us, even if we 1615 * insert a unicast mismatch filter. To prevent traffic stealing, this 1616 * therefore relies on the privilege model only allowing functions to 1617 * insert filters for their own MAC address unless explicitly given 1618 * additional privileges by the user. This also means that, even on a 1619 * priviliged function, inserting a unicast mismatch filter may not 1620 * catch all traffic in multi PCI function scenarios.) 1621 */ 1622 table->eft_unicst_filter_count = 0; 1623 rc = ef10_filter_insert_unicast(enp, mac_addr, filter_flags); 1624 if (all_unicst || (rc != 0)) { 1625 all_unicst_rc = ef10_filter_insert_all_unicast(enp, 1626 filter_flags); 1627 if ((rc != 0) && (all_unicst_rc != 0)) 1628 goto fail1; 1629 } 1630 1631 /* 1632 * WORKAROUND_BUG26807 controls firmware support for chained multicast 1633 * filters, and can only be enabled or disabled when the hardware filter 1634 * table is empty. 1635 * 1636 * Chained multicast filters require support from the datapath firmware, 1637 * and may not be available (e.g. low-latency variants or old Huntington 1638 * firmware). 1639 * 1640 * Firmware will reset (FLR) functions which have inserted filters in 1641 * the hardware filter table when the workaround is enabled/disabled. 1642 * Functions without any hardware filters are not reset. 1643 * 1644 * Re-check if the workaround is enabled after adding unicast hardware 1645 * filters. This ensures that encp->enc_bug26807_workaround matches the 1646 * firmware state, and that later changes to enable/disable the 1647 * workaround will result in this function seeing a reset (FLR). 1648 * 1649 * In common-code drivers, we only support multiple PCI function 1650 * scenarios with firmware that supports multicast chaining, so we can 1651 * assume it is enabled for such cases and hence simplify the filter 1652 * insertion logic. Firmware that does not support multicast chaining 1653 * does not support multiple PCI function configurations either, so 1654 * filter insertion is much simpler and the same strategies can still be 1655 * used. 1656 */ 1657 if ((rc = ef10_filter_get_workarounds(enp)) != 0) 1658 goto fail2; 1659 1660 if ((table->eft_using_all_mulcst != all_mulcst) && 1661 (encp->enc_bug26807_workaround == B_TRUE)) { 1662 /* 1663 * Multicast filter chaining is enabled, so traffic that matches 1664 * more than one multicast filter will be replicated and 1665 * delivered to multiple recipients. To avoid this duplicate 1666 * delivery, remove old multicast filters before inserting new 1667 * multicast filters. 1668 */ 1669 ef10_filter_remove_old(enp); 1670 } 1671 1672 /* Insert or renew multicast filters */ 1673 if (all_mulcst == B_TRUE) { 1674 /* 1675 * Insert the all multicast filter. If that fails, try to insert 1676 * all of our multicast filters (but without rollback on 1677 * failure). 1678 */ 1679 all_mulcst_rc = ef10_filter_insert_all_multicast(enp, 1680 filter_flags); 1681 if (all_mulcst_rc != 0) { 1682 rc = ef10_filter_insert_multicast_list(enp, B_TRUE, 1683 brdcst, addrs, count, filter_flags, B_FALSE); 1684 if (rc != 0) 1685 goto fail3; 1686 } 1687 } else { 1688 /* 1689 * Insert filters for multicast addresses. 1690 * If any insertion fails, then rollback and try to insert the 1691 * all multicast filter instead. 1692 * If that also fails, try to insert all of the multicast 1693 * filters (but without rollback on failure). 1694 */ 1695 rc = ef10_filter_insert_multicast_list(enp, mulcst, brdcst, 1696 addrs, count, filter_flags, B_TRUE); 1697 if (rc != 0) { 1698 if ((table->eft_using_all_mulcst == B_FALSE) && 1699 (encp->enc_bug26807_workaround == B_TRUE)) { 1700 /* 1701 * Multicast filter chaining is on, so remove 1702 * old filters before inserting the multicast 1703 * all filter to avoid duplicate delivery caused 1704 * by packets matching multiple filters. 1705 */ 1706 ef10_filter_remove_old(enp); 1707 } 1708 1709 rc = ef10_filter_insert_all_multicast(enp, 1710 filter_flags); 1711 if (rc != 0) { 1712 rc = ef10_filter_insert_multicast_list(enp, 1713 mulcst, brdcst, 1714 addrs, count, filter_flags, B_FALSE); 1715 if (rc != 0) 1716 goto fail4; 1717 } 1718 } 1719 } 1720 1721 if (encp->enc_tunnel_encapsulations_supported != 0) { 1722 /* Try to insert filters for encapsulated packets. */ 1723 (void) ef10_filter_insert_encap_filters(enp, 1724 mulcst || all_mulcst || brdcst, 1725 filter_flags); 1726 } 1727 1728 /* Remove old filters which were not renewed */ 1729 ef10_filter_remove_old(enp); 1730 1731 /* report if any optional flags were rejected */ 1732 if (((all_unicst != B_FALSE) && (all_unicst_rc != 0)) || 1733 ((all_mulcst != B_FALSE) && (all_mulcst_rc != 0))) { 1734 rc = ENOTSUP; 1735 } 1736 1737 return (rc); 1738 1739 fail4: 1740 EFSYS_PROBE(fail4); 1741 fail3: 1742 EFSYS_PROBE(fail3); 1743 fail2: 1744 EFSYS_PROBE(fail2); 1745 fail1: 1746 EFSYS_PROBE1(fail1, efx_rc_t, rc); 1747 1748 /* Clear auto old flags */ 1749 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) { 1750 if (ef10_filter_entry_is_auto_old(table, i)) { 1751 ef10_filter_set_entry_not_auto_old(table, i); 1752 } 1753 } 1754 1755 return (rc); 1756 } 1757 1758 void 1759 ef10_filter_get_default_rxq( 1760 __in efx_nic_t *enp, 1761 __out efx_rxq_t **erpp, 1762 __out boolean_t *using_rss) 1763 { 1764 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1765 1766 *erpp = table->eft_default_rxq; 1767 *using_rss = table->eft_using_rss; 1768 } 1769 1770 1771 void 1772 ef10_filter_default_rxq_set( 1773 __in efx_nic_t *enp, 1774 __in efx_rxq_t *erp, 1775 __in boolean_t using_rss) 1776 { 1777 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1778 1779 #if EFSYS_OPT_RX_SCALE 1780 EFSYS_ASSERT((using_rss == B_FALSE) || 1781 (enp->en_rss_context != EF10_RSS_CONTEXT_INVALID)); 1782 table->eft_using_rss = using_rss; 1783 #else 1784 EFSYS_ASSERT(using_rss == B_FALSE); 1785 table->eft_using_rss = B_FALSE; 1786 #endif 1787 table->eft_default_rxq = erp; 1788 } 1789 1790 void 1791 ef10_filter_default_rxq_clear( 1792 __in efx_nic_t *enp) 1793 { 1794 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table; 1795 1796 table->eft_default_rxq = NULL; 1797 table->eft_using_rss = B_FALSE; 1798 } 1799 1800 1801 #endif /* EFSYS_OPT_FILTER */ 1802 1803 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */ 1804