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