2 * Copyright 2007-2009 Solarflare Communications Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
31 #include "efx_types.h"
38 /* "Fudge factors" - difference between programmed value and actual depth.
39 * Due to pipelined implementation we need to program H/W with a value that
40 * is larger than the hop limit we want.
42 #define FILTER_CTL_SRCH_FUDGE_WILD 3
43 #define FILTER_CTL_SRCH_FUDGE_FULL 1
45 /* Hard maximum hop limit. Hardware will time-out beyond 200-something.
46 * We also need to avoid infinite loops in efx_filter_search() when the
49 #define FILTER_CTL_SRCH_MAX 200
51 /* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
52 * key derived from the n-tuple. */
60 tmp = 0x1fff ^ (uint16_t)(key >> 16);
61 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
65 tmp = tmp ^ tmp << 13 ^ (uint16_t)(key & 0xffff);
66 tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
73 /* To allow for hash collisions, filter search continues at these
74 * increments from the first possible entry selected by the hash. */
76 efx_filter_tbl_increment(
79 return ((uint16_t)(key * 2 - 1));
82 static __checkReturn boolean_t
84 __in efx_filter_tbl_t *eftp,
85 __in unsigned int index)
87 EFSYS_ASSERT3P(eftp->eft_bitmap, !=, NULL);
88 return ((eftp->eft_bitmap[index / 32] & (1 << (index % 32))) != 0);
93 __in efx_filter_tbl_t *eftp,
94 __in unsigned int index)
96 EFSYS_ASSERT3P(eftp->eft_bitmap, !=, NULL);
97 eftp->eft_bitmap[index / 32] |= (1 << (index % 32));
102 efx_filter_clear_used(
103 __in efx_filter_tbl_t *eftp,
104 __in unsigned int index)
106 EFSYS_ASSERT3P(eftp->eft_bitmap, !=, NULL);
107 eftp->eft_bitmap[index / 32] &= ~(1 << (index % 32));
110 EFSYS_ASSERT3U(eftp->eft_used, >=, 0);
114 static efx_filter_tbl_id_t
116 __in efx_filter_type_t type)
118 efx_filter_tbl_id_t tbl_id;
122 case EFX_FILTER_RX_TCP_FULL:
123 case EFX_FILTER_RX_TCP_WILD:
124 case EFX_FILTER_RX_UDP_FULL:
125 case EFX_FILTER_RX_UDP_WILD:
126 tbl_id = EFX_FILTER_TBL_RX_IP;
130 case EFX_FILTER_RX_MAC_FULL:
131 case EFX_FILTER_RX_MAC_WILD:
132 tbl_id = EFX_FILTER_TBL_RX_MAC;
135 case EFX_FILTER_TX_TCP_FULL:
136 case EFX_FILTER_TX_TCP_WILD:
137 case EFX_FILTER_TX_UDP_FULL:
138 case EFX_FILTER_TX_UDP_WILD:
139 tbl_id = EFX_FILTER_TBL_TX_IP;
142 case EFX_FILTER_TX_MAC_FULL:
143 case EFX_FILTER_TX_MAC_WILD:
144 tbl_id = EFX_FILTER_TBL_RX_MAC;
146 #endif /* EFSYS_OPT_SIENA */
149 EFSYS_ASSERT(B_FALSE);
156 efx_filter_reset_search_depth(
157 __inout efx_filter_t *efp,
158 __in efx_filter_tbl_id_t tbl_id)
162 case EFX_FILTER_TBL_RX_IP:
163 efp->ef_depth[EFX_FILTER_RX_TCP_FULL] = 0;
164 efp->ef_depth[EFX_FILTER_RX_TCP_WILD] = 0;
165 efp->ef_depth[EFX_FILTER_RX_UDP_FULL] = 0;
166 efp->ef_depth[EFX_FILTER_RX_UDP_WILD] = 0;
170 case EFX_FILTER_TBL_RX_MAC:
171 efp->ef_depth[EFX_FILTER_RX_MAC_FULL] = 0;
172 efp->ef_depth[EFX_FILTER_RX_MAC_WILD] = 0;
175 case EFX_FILTER_TBL_TX_IP:
176 efp->ef_depth[EFX_FILTER_TX_TCP_FULL] = 0;
177 efp->ef_depth[EFX_FILTER_TX_TCP_WILD] = 0;
178 efp->ef_depth[EFX_FILTER_TX_UDP_FULL] = 0;
179 efp->ef_depth[EFX_FILTER_TX_UDP_WILD] = 0;
182 case EFX_FILTER_TBL_TX_MAC:
183 efp->ef_depth[EFX_FILTER_TX_MAC_FULL] = 0;
184 efp->ef_depth[EFX_FILTER_TX_MAC_WILD] = 0;
186 #endif /* EFSYS_OPT_SIENA */
189 EFSYS_ASSERT(B_FALSE);
195 efx_filter_push_rx_limits(
198 efx_filter_t *efp = &enp->en_filter;
201 EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
203 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_FULL_SRCH_LIMIT,
204 efp->ef_depth[EFX_FILTER_RX_TCP_FULL] +
205 FILTER_CTL_SRCH_FUDGE_FULL);
206 EFX_SET_OWORD_FIELD(oword, FRF_AZ_TCP_WILD_SRCH_LIMIT,
207 efp->ef_depth[EFX_FILTER_RX_TCP_WILD] +
208 FILTER_CTL_SRCH_FUDGE_WILD);
209 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_FULL_SRCH_LIMIT,
210 efp->ef_depth[EFX_FILTER_RX_UDP_FULL] +
211 FILTER_CTL_SRCH_FUDGE_FULL);
212 EFX_SET_OWORD_FIELD(oword, FRF_AZ_UDP_WILD_SRCH_LIMIT,
213 efp->ef_depth[EFX_FILTER_RX_UDP_WILD] +
214 FILTER_CTL_SRCH_FUDGE_WILD);
217 if (efp->ef_tbl[EFX_FILTER_TBL_RX_MAC].eft_size) {
218 EFX_SET_OWORD_FIELD(oword,
219 FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
220 efp->ef_depth[EFX_FILTER_RX_MAC_FULL] +
221 FILTER_CTL_SRCH_FUDGE_FULL);
222 EFX_SET_OWORD_FIELD(oword,
223 FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
224 efp->ef_depth[EFX_FILTER_RX_MAC_WILD] +
225 FILTER_CTL_SRCH_FUDGE_WILD);
227 #endif /* EFSYS_OPT_SIENA */
229 EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
233 efx_filter_push_tx_limits(
236 efx_filter_t *efp = &enp->en_filter;
239 if (efp->ef_tbl[EFX_FILTER_TBL_TX_IP].eft_size == 0)
242 EFX_BAR_READO(enp, FR_AZ_TX_CFG_REG, &oword);
244 EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_TCPIP_FILTER_FULL_SEARCH_RANGE,
245 efp->ef_depth[EFX_FILTER_TX_TCP_FULL] +
246 FILTER_CTL_SRCH_FUDGE_FULL);
247 EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_TCPIP_FILTER_WILD_SEARCH_RANGE,
248 efp->ef_depth[EFX_FILTER_TX_TCP_WILD] +
249 FILTER_CTL_SRCH_FUDGE_WILD);
250 EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_UDPIP_FILTER_FULL_SEARCH_RANGE,
251 efp->ef_depth[EFX_FILTER_TX_UDP_FULL] +
252 FILTER_CTL_SRCH_FUDGE_FULL);
253 EFX_SET_OWORD_FIELD(oword, FRF_CZ_TX_UDPIP_FILTER_WILD_SEARCH_RANGE,
254 efp->ef_depth[EFX_FILTER_TX_UDP_WILD] +
255 FILTER_CTL_SRCH_FUDGE_WILD);
257 EFX_BAR_WRITEO(enp, FR_AZ_TX_CFG_REG, &oword);
260 /* Build a filter entry and return its n-tuple key. */
261 static __checkReturn uint32_t
263 __out efx_oword_t *filter,
264 __in efx_filter_spec_t *spec)
268 uint8_t type = spec->efs_type;
269 uint8_t flags = spec->efs_flags;
271 switch (efx_filter_tbl_id(type)) {
272 case EFX_FILTER_TBL_RX_IP: {
273 boolean_t is_udp = (type == EFX_FILTER_RX_UDP_FULL ||
274 type == EFX_FILTER_RX_UDP_WILD);
275 EFX_POPULATE_OWORD_7(*filter,
276 FRF_BZ_RSS_EN, (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
277 FRF_BZ_SCATTER_EN, (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
278 FRF_AZ_TCP_UDP, is_udp,
279 FRF_AZ_RXQ_ID, spec->efs_dmaq_id,
280 EFX_DWORD_2, spec->efs_dword[2],
281 EFX_DWORD_1, spec->efs_dword[1],
282 EFX_DWORD_0, spec->efs_dword[0]);
288 case EFX_FILTER_TBL_RX_MAC: {
289 boolean_t is_wild = (type == EFX_FILTER_RX_MAC_WILD);
290 EFX_POPULATE_OWORD_8(*filter,
291 FRF_CZ_RMFT_RSS_EN, (flags & EFX_FILTER_FLAG_RX_RSS) ? 1 : 0,
292 FRF_CZ_RMFT_SCATTER_EN, (flags & EFX_FILTER_FLAG_RX_SCATTER) ? 1 : 0,
293 FRF_CZ_RMFT_IP_OVERRIDE, (flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) ? 1 : 0,
294 FRF_CZ_RMFT_RXQ_ID, spec->efs_dmaq_id,
295 FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
296 FRF_CZ_RMFT_DEST_MAC_DW1, spec->efs_dword[2],
297 FRF_CZ_RMFT_DEST_MAC_DW0, spec->efs_dword[1],
298 FRF_CZ_RMFT_VLAN_ID, spec->efs_dword[0]);
302 #endif /* EFSYS_OPT_SIENA */
304 case EFX_FILTER_TBL_TX_IP: {
305 boolean_t is_udp = (type == EFX_FILTER_TX_UDP_FULL ||
306 type == EFX_FILTER_TX_UDP_WILD);
307 EFX_POPULATE_OWORD_5(*filter,
308 FRF_CZ_TIFT_TCP_UDP, is_udp,
309 FRF_CZ_TIFT_TXQ_ID, spec->efs_dmaq_id,
310 EFX_DWORD_2, spec->efs_dword[2],
311 EFX_DWORD_1, spec->efs_dword[1],
312 EFX_DWORD_0, spec->efs_dword[0]);
313 dword3 = is_udp | spec->efs_dmaq_id << 1;
318 case EFX_FILTER_TBL_TX_MAC: {
319 boolean_t is_wild = (type == EFX_FILTER_TX_MAC_WILD);
320 EFX_POPULATE_OWORD_5(*filter,
321 FRF_CZ_TMFT_TXQ_ID, spec->efs_dmaq_id,
322 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
323 FRF_CZ_TMFT_SRC_MAC_DW1, spec->efs_dword[2],
324 FRF_CZ_TMFT_SRC_MAC_DW0, spec->efs_dword[1],
325 FRF_CZ_TMFT_VLAN_ID, spec->efs_dword[0]);
326 dword3 = is_wild | spec->efs_dmaq_id << 1;
329 #endif /* EFSYS_OPT_SIENA */
332 EFSYS_ASSERT(B_FALSE);
335 key = spec->efs_dword[0] ^ spec->efs_dword[1] ^ spec->efs_dword[2] ^ dword3;
339 static __checkReturn int
340 efx_filter_push_entry(
341 __inout efx_nic_t *enp,
342 __in efx_filter_type_t type,
344 __in efx_oword_t *eop)
350 case EFX_FILTER_RX_TCP_FULL:
351 case EFX_FILTER_RX_TCP_WILD:
352 case EFX_FILTER_RX_UDP_FULL:
353 case EFX_FILTER_RX_UDP_WILD:
354 EFX_BAR_TBL_WRITEO(enp, FR_AZ_RX_FILTER_TBL0, index, eop);
358 case EFX_FILTER_RX_MAC_FULL:
359 case EFX_FILTER_RX_MAC_WILD:
360 EFX_BAR_TBL_WRITEO(enp, FR_CZ_RX_MAC_FILTER_TBL0, index, eop);
363 case EFX_FILTER_TX_TCP_FULL:
364 case EFX_FILTER_TX_TCP_WILD:
365 case EFX_FILTER_TX_UDP_FULL:
366 case EFX_FILTER_TX_UDP_WILD:
367 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_FILTER_TBL0, index, eop);
370 case EFX_FILTER_TX_MAC_FULL:
371 case EFX_FILTER_TX_MAC_WILD:
372 EFX_BAR_TBL_WRITEO(enp, FR_CZ_TX_MAC_FILTER_TBL0, index, eop);
374 #endif /* EFSYS_OPT_SIENA */
387 static __checkReturn boolean_t
389 __in const efx_filter_spec_t *left,
390 __in const efx_filter_spec_t *right)
392 efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(left->efs_type);
394 if (left->efs_type != right->efs_type)
397 if (memcmp(left->efs_dword, right->efs_dword, sizeof(left->efs_dword)))
400 if ((tbl_id == EFX_FILTER_TBL_TX_IP ||
401 tbl_id == EFX_FILTER_TBL_TX_MAC) &&
402 left->efs_dmaq_id != right->efs_dmaq_id)
408 static __checkReturn int
410 __in efx_filter_tbl_t *eftp,
411 __in efx_filter_spec_t *spec,
413 __in boolean_t for_insert,
414 __out int *filter_index,
415 __out int *depth_required)
417 unsigned hash, incr, filter_idx, depth;
419 hash = efx_filter_tbl_hash(key);
420 incr = efx_filter_tbl_increment(key);
422 filter_idx = hash & (eftp->eft_size - 1);
426 /* Return success if entry is used and matches this spec
427 * or entry is unused and we are trying to insert.
429 if (efx_filter_test_used(eftp, filter_idx) ?
430 efx_filter_equal(spec, &eftp->eft_spec[filter_idx]) :
432 *filter_index = filter_idx;
433 *depth_required = depth;
437 /* Return failure if we reached the maximum search depth */
438 if (depth == FILTER_CTL_SRCH_MAX)
439 return for_insert ? EBUSY : ENOENT;
441 filter_idx = (filter_idx + incr) & (eftp->eft_size - 1);
447 efx_filter_insert_filter(
449 __in efx_filter_spec_t *spec,
450 __in boolean_t replace)
452 efx_filter_t *efp = &enp->en_filter;
453 efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(spec->efs_type);
454 efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
455 efx_filter_spec_t *saved_spec;
463 if (eftp->eft_size == 0)
466 key = efx_filter_build(&filter, spec);
468 EFSYS_LOCK(enp->en_eslp, state);
470 rc = efx_filter_search(eftp, spec, key, B_TRUE, &filter_idx, &depth);
474 EFSYS_ASSERT3U(filter_idx, <, eftp->eft_size);
475 saved_spec = &eftp->eft_spec[filter_idx];
477 if (efx_filter_test_used(eftp, filter_idx)) {
478 if (replace == B_FALSE) {
483 efx_filter_set_used(eftp, filter_idx);
486 if (efp->ef_depth[spec->efs_type] < depth) {
487 efp->ef_depth[spec->efs_type] = depth;
488 if (tbl_id == EFX_FILTER_TBL_TX_IP ||
489 tbl_id == EFX_FILTER_TBL_TX_MAC)
490 efx_filter_push_tx_limits(enp);
492 efx_filter_push_rx_limits(enp);
495 efx_filter_push_entry(enp, spec->efs_type, filter_idx, &filter);
498 EFSYS_UNLOCK(enp->en_eslp, state);
503 efx_filter_clear_entry(
505 __in efx_filter_tbl_t *eftp,
510 if (efx_filter_test_used(eftp, index)) {
511 efx_filter_clear_used(eftp, index);
513 EFX_ZERO_OWORD(filter);
514 efx_filter_push_entry(enp, eftp->eft_spec[index].efs_type,
517 memset(&eftp->eft_spec[index], 0, sizeof(eftp->eft_spec[0]));
522 efx_filter_remove_filter(
524 __in efx_filter_spec_t *spec)
526 efx_filter_t *efp = &enp->en_filter;
527 efx_filter_tbl_id_t tbl_id = efx_filter_tbl_id(spec->efs_type);
528 efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
529 efx_filter_spec_t *saved_spec;
531 int filter_idx, depth;
536 key = efx_filter_build(&filter, spec);
538 EFSYS_LOCK(enp->en_eslp, state);
540 rc = efx_filter_search(eftp, spec, key, B_FALSE, &filter_idx, &depth);
544 saved_spec = &eftp->eft_spec[filter_idx];
546 efx_filter_clear_entry(enp, eftp, filter_idx);
547 if (eftp->eft_used == 0)
548 efx_filter_reset_search_depth(efp, tbl_id);
553 EFSYS_UNLOCK(enp->en_eslp, state);
558 efx_filter_remove_index(
559 __inout efx_nic_t *enp,
560 __in efx_filter_type_t type,
563 efx_filter_t *efp = &enp->en_filter;
564 enum efx_filter_tbl_id tbl_id = efx_filter_tbl_id(type);
565 efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
571 EFSYS_LOCK(enp->en_eslp, state);
573 efx_filter_clear_entry(enp, eftp, index);
574 if (eftp->eft_used == 0)
575 efx_filter_reset_search_depth(efp, tbl_id);
577 EFSYS_UNLOCK(enp->en_eslp, state);
581 efx_filter_tbl_clear(
582 __inout efx_nic_t *enp,
583 __in efx_filter_tbl_id_t tbl_id)
585 efx_filter_t *efp = &enp->en_filter;
586 efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
590 EFSYS_LOCK(enp->en_eslp, state);
592 for (index = 0; index < eftp->eft_size; ++index) {
593 efx_filter_clear_entry(enp, eftp, index);
596 if (eftp->eft_used == 0)
597 efx_filter_reset_search_depth(efp, tbl_id);
599 EFSYS_UNLOCK(enp->en_eslp, state);
602 /* Restore filter state after a reset */
607 efx_filter_t *efp = &enp->en_filter;
608 efx_filter_tbl_id_t tbl_id;
609 efx_filter_tbl_t *eftp;
610 efx_filter_spec_t *spec;
615 EFSYS_LOCK(enp->en_eslp, state);
617 for (tbl_id = 0; tbl_id < EFX_FILTER_NTBLS; tbl_id++) {
618 eftp = &efp->ef_tbl[tbl_id];
619 for (filter_idx = 0; filter_idx < eftp->eft_size; filter_idx++) {
620 if (!efx_filter_test_used(eftp, filter_idx))
623 spec = &eftp->eft_spec[filter_idx];
624 efx_filter_build(&filter, spec);
625 efx_filter_push_entry(enp, spec->efs_type,
626 filter_idx, &filter);
630 efx_filter_push_rx_limits(enp);
631 efx_filter_push_tx_limits(enp);
633 EFSYS_UNLOCK(enp->en_eslp, state);
637 efx_filter_redirect_index(
638 __inout efx_nic_t *enp,
639 __in efx_filter_type_t type,
640 __in int filter_index,
643 efx_filter_t *efp = &enp->en_filter;
644 efx_filter_tbl_t *eftp =
645 &efp->ef_tbl[efx_filter_tbl_id(type)];
646 efx_filter_spec_t *spec;
650 EFSYS_LOCK(enp->en_eslp, state);
652 spec = &eftp->eft_spec[filter_index];
653 spec->efs_dmaq_id = (uint16_t)rxq_index;
655 efx_filter_build(&filter, spec);
656 efx_filter_push_entry(enp, spec->efs_type, filter_index, &filter);
658 EFSYS_UNLOCK(enp->en_eslp, state);
665 efx_filter_t *efp = &enp->en_filter;
666 efx_filter_tbl_t *eftp;
670 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
671 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
672 EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_FILTER));
674 switch (enp->en_family)
677 case EFX_FAMILY_FALCON:
678 eftp = &efp->ef_tbl[EFX_FILTER_TBL_RX_IP];
679 eftp->eft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
681 #endif /* EFSYS_OPT_FALCON */
684 case EFX_FAMILY_SIENA:
685 eftp = &efp->ef_tbl[EFX_FILTER_TBL_RX_IP];
686 eftp->eft_size = FR_AZ_RX_FILTER_TBL0_ROWS;
688 eftp = &efp->ef_tbl[EFX_FILTER_TBL_RX_MAC];
689 eftp->eft_size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
691 eftp = &efp->ef_tbl[EFX_FILTER_TBL_TX_IP];
692 eftp->eft_size = FR_CZ_TX_FILTER_TBL0_ROWS;
694 eftp = &efp->ef_tbl[EFX_FILTER_TBL_TX_MAC];
695 eftp->eft_size = FR_CZ_TX_MAC_FILTER_TBL0_ROWS;
697 #endif /* EFSYS_OPT_SIENA */
704 for (tbl_id = 0; tbl_id < EFX_FILTER_NTBLS; tbl_id++) {
705 unsigned int bitmap_size;
707 eftp = &efp->ef_tbl[tbl_id];
708 if (eftp->eft_size == 0)
711 EFX_STATIC_ASSERT(sizeof(eftp->eft_bitmap[0]) == sizeof(uint32_t));
712 bitmap_size = (eftp->eft_size + (sizeof(uint32_t) * 8) - 1) / 8;
714 EFSYS_KMEM_ALLOC(enp->en_esip, bitmap_size, eftp->eft_bitmap);
715 if (!eftp->eft_bitmap) {
720 EFSYS_KMEM_ALLOC(enp->en_esip, eftp->eft_size * sizeof(*eftp->eft_spec),
722 if (!eftp->eft_spec) {
726 memset(eftp->eft_spec, 0, eftp->eft_size * sizeof(*eftp->eft_spec));
728 enp->en_mod_flags |= EFX_MOD_FILTER;
734 efx_filter_fini(enp);
737 EFSYS_PROBE1(fail1, int, rc);
745 efx_filter_t *efp = &enp->en_filter;
746 efx_filter_tbl_id_t tbl_id;
748 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
749 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
751 for (tbl_id = 0; tbl_id < EFX_FILTER_NTBLS; tbl_id++) {
752 efx_filter_tbl_t *eftp = &efp->ef_tbl[tbl_id];
753 unsigned int bitmap_size;
755 EFX_STATIC_ASSERT(sizeof(eftp->eft_bitmap[0]) == sizeof(uint32_t));
756 bitmap_size = (eftp->eft_size + (sizeof(uint32_t) * 8) - 1) / 8;
758 EFSYS_KMEM_FREE(enp->en_esip, bitmap_size, eftp->eft_bitmap);
759 eftp->eft_bitmap = NULL;
761 EFSYS_KMEM_FREE(enp->en_esip, eftp->eft_size * sizeof(*eftp->eft_spec),
763 eftp->eft_spec = NULL;
766 enp->en_mod_flags &= ~EFX_MOD_FILTER;
770 efx_filter_spec_rx_ipv4_tcp_full(
771 __inout efx_filter_spec_t *spec,
772 __in unsigned int flags,
773 __in uint32_t src_ip,
774 __in uint16_t src_tcp,
775 __in uint32_t dest_ip,
776 __in uint16_t dest_tcp)
778 EFSYS_ASSERT3P(spec, !=, NULL);
779 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
780 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
782 spec->efs_type = EFX_FILTER_RX_TCP_FULL;
783 spec->efs_flags = (uint8_t)flags;
784 spec->efs_dword[0] = src_tcp | src_ip << 16;
785 spec->efs_dword[1] = dest_tcp << 16 | src_ip >> 16;
786 spec->efs_dword[2] = dest_ip;
790 efx_filter_spec_rx_ipv4_tcp_wild(
791 __inout efx_filter_spec_t *spec,
792 __in unsigned int flags,
793 __in uint32_t dest_ip,
794 __in uint16_t dest_tcp)
796 EFSYS_ASSERT3P(spec, !=, NULL);
797 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
798 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
800 spec->efs_type = EFX_FILTER_RX_TCP_WILD;
801 spec->efs_flags = (uint8_t)flags;
802 spec->efs_dword[0] = 0;
803 spec->efs_dword[1] = dest_tcp << 16;
804 spec->efs_dword[2] = dest_ip;
808 efx_filter_spec_rx_ipv4_udp_full(
809 __inout efx_filter_spec_t *spec,
810 __in unsigned int flags,
811 __in uint32_t src_ip,
812 __in uint16_t src_udp,
813 __in uint32_t dest_ip,
814 __in uint16_t dest_udp)
816 EFSYS_ASSERT3P(spec, !=, NULL);
817 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
818 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
820 spec->efs_type = EFX_FILTER_RX_UDP_FULL;
821 spec->efs_flags = (uint8_t)flags;
822 spec->efs_dword[0] = src_udp | src_ip << 16;
823 spec->efs_dword[1] = dest_udp << 16 | src_ip >> 16;
824 spec->efs_dword[2] = dest_ip;
828 efx_filter_spec_rx_ipv4_udp_wild(
829 __inout efx_filter_spec_t *spec,
830 __in unsigned int flags,
831 __in uint32_t dest_ip,
832 __in uint16_t dest_udp)
834 EFSYS_ASSERT3P(spec, !=, NULL);
835 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
836 EFX_FILTER_FLAG_RX_SCATTER)) == 0);
838 spec->efs_type = EFX_FILTER_RX_UDP_WILD;
839 spec->efs_flags = (uint8_t)flags;
840 spec->efs_dword[0] = dest_udp;
841 spec->efs_dword[1] = 0;
842 spec->efs_dword[2] = dest_ip;
847 efx_filter_spec_rx_mac_full(
848 __inout efx_filter_spec_t *spec,
849 __in unsigned int flags,
850 __in uint16_t vlan_id,
851 __in uint8_t *dest_mac)
853 EFSYS_ASSERT3P(spec, !=, NULL);
854 EFSYS_ASSERT3P(dest_mac, !=, NULL);
855 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
856 EFX_FILTER_FLAG_RX_SCATTER |
857 EFX_FILTER_FLAG_RX_OVERRIDE_IP)) == 0);
859 spec->efs_type = EFX_FILTER_RX_MAC_FULL;
860 spec->efs_flags = (uint8_t)flags;
861 spec->efs_dword[0] = vlan_id;
871 #endif /* EFSYS_OPT_SIENA */
875 efx_filter_spec_rx_mac_wild(
876 __inout efx_filter_spec_t *spec,
877 __in unsigned int flags,
878 __in uint8_t *dest_mac)
880 EFSYS_ASSERT3P(spec, !=, NULL);
881 EFSYS_ASSERT3P(dest_mac, !=, NULL);
882 EFSYS_ASSERT((flags & ~(EFX_FILTER_FLAG_RX_RSS |
883 EFX_FILTER_FLAG_RX_SCATTER |
884 EFX_FILTER_FLAG_RX_OVERRIDE_IP)) == 0);
886 spec->efs_type = EFX_FILTER_RX_MAC_WILD;
887 spec->efs_flags = (uint8_t)flags;
888 spec->efs_dword[0] = 0;
898 #endif /* EFSYS_OPT_SIENA */
902 efx_filter_spec_tx_ipv4_tcp_full(
903 __inout efx_filter_spec_t *spec,
904 __in uint32_t src_ip,
905 __in uint16_t src_tcp,
906 __in uint32_t dest_ip,
907 __in uint16_t dest_tcp)
909 EFSYS_ASSERT3P(spec, !=, NULL);
911 spec->efs_type = EFX_FILTER_TX_TCP_FULL;
913 spec->efs_dword[0] = src_tcp | src_ip << 16;
914 spec->efs_dword[1] = dest_tcp << 16 | src_ip >> 16;
915 spec->efs_dword[2] = dest_ip;
917 #endif /* EFSYS_OPT_SIENA */
921 efx_filter_spec_tx_ipv4_tcp_wild(
922 __inout efx_filter_spec_t *spec,
923 __in uint32_t src_ip,
924 __in uint16_t src_tcp)
926 EFSYS_ASSERT3P(spec, !=, NULL);
928 spec->efs_type = EFX_FILTER_TX_TCP_WILD;
930 spec->efs_dword[0] = 0;
931 spec->efs_dword[1] = src_tcp << 16;
932 spec->efs_dword[2] = src_ip;
934 #endif /* EFSYS_OPT_SIENA */
938 efx_filter_spec_tx_ipv4_udp_full(
939 __inout efx_filter_spec_t *spec,
940 __in uint32_t src_ip,
941 __in uint16_t src_udp,
942 __in uint32_t dest_ip,
943 __in uint16_t dest_udp)
945 EFSYS_ASSERT3P(spec, !=, NULL);
947 spec->efs_type = EFX_FILTER_TX_UDP_FULL;
949 spec->efs_dword[0] = src_udp | src_ip << 16;
950 spec->efs_dword[1] = dest_udp << 16 | src_ip >> 16;
951 spec->efs_dword[2] = dest_ip;
953 #endif /* EFSYS_OPT_SIENA */
957 efx_filter_spec_tx_ipv4_udp_wild(
958 __inout efx_filter_spec_t *spec,
959 __in uint32_t src_ip,
960 __in uint16_t src_udp)
962 EFSYS_ASSERT3P(spec, !=, NULL);
964 spec->efs_type = EFX_FILTER_TX_UDP_WILD;
966 spec->efs_dword[0] = src_udp;
967 spec->efs_dword[1] = 0;
968 spec->efs_dword[2] = src_ip;
970 #endif /* EFSYS_OPT_SIENA */
974 efx_filter_spec_tx_mac_full(
975 __inout efx_filter_spec_t *spec,
976 __in uint16_t vlan_id,
977 __in uint8_t *src_mac)
979 EFSYS_ASSERT3P(spec, !=, NULL);
980 EFSYS_ASSERT3P(src_mac, !=, NULL);
982 spec->efs_type = EFX_FILTER_TX_MAC_FULL;
984 spec->efs_dword[0] = vlan_id;
994 #endif /* EFSYS_OPT_SIENA */
998 efx_filter_spec_tx_mac_wild(
999 __inout efx_filter_spec_t *spec,
1000 __in uint8_t *src_mac)
1002 EFSYS_ASSERT3P(spec, !=, NULL);
1003 EFSYS_ASSERT3P(src_mac, !=, NULL);
1005 spec->efs_type = EFX_FILTER_TX_MAC_WILD;
1006 spec->efs_flags = 0;
1007 spec->efs_dword[0] = 0;
1008 spec->efs_dword[1] =
1013 spec->efs_dword[2] =
1017 #endif /* EFSYS_OPT_SIENA */
1020 #endif /* EFSYS_OPT_FILTER */