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
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 *
ef10_filter_entry_spec(__in const ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_entry_is_busy(__in const ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_entry_is_auto_old(__in const ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_set_entry(__inout ef10_filter_table_t * eftp,__in unsigned int index,__in_opt const efx_filter_spec_t * efsp)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
ef10_filter_set_entry_busy(__inout ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_set_entry_not_busy(__inout ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_set_entry_auto_old(__inout ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_set_entry_not_auto_old(__inout ef10_filter_table_t * eftp,__in unsigned int index)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
ef10_filter_init(__in efx_nic_t * enp)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 
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 
169 fail1:
170 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
171 
172 	return (rc);
173 }
174 
175 			void
ef10_filter_fini(__in efx_nic_t * enp)176 ef10_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 
188 static	__checkReturn	efx_rc_t
efx_mcdi_filter_op_add(__in efx_nic_t * enp,__in efx_filter_spec_t * spec,__in unsigned int filter_op,__inout ef10_filter_handle_t * handle)189 efx_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 
328 fail4:
329 	EFSYS_PROBE(fail4);
330 fail3:
331 	EFSYS_PROBE(fail3);
332 fail2:
333 	EFSYS_PROBE(fail2);
334 fail1:
335 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
336 
337 	return (rc);
338 
339 }
340 
341 static	__checkReturn	efx_rc_t
efx_mcdi_filter_op_delete(__in efx_nic_t * enp,__in unsigned int filter_op,__inout ef10_filter_handle_t * handle)342 efx_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 
390 fail3:
391 	EFSYS_PROBE(fail3);
392 
393 fail2:
394 	EFSYS_PROBE(fail2);
395 fail1:
396 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
397 
398 	return (rc);
399 }
400 
401 static	__checkReturn	boolean_t
ef10_filter_equal(__in const efx_filter_spec_t * left,__in const efx_filter_spec_t * right)402 ef10_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 
436 static	__checkReturn	boolean_t
ef10_filter_same_dest(__in const efx_filter_spec_t * left,__in const efx_filter_spec_t * right)437 ef10_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 
453 static	__checkReturn	uint32_t
ef10_filter_hash(__in efx_filter_spec_t * spec)454 ef10_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  */
479 static	__checkReturn	boolean_t
ef10_filter_is_exclusive(__in efx_filter_spec_t * spec)480 ef10_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
ef10_filter_restore(__in efx_nic_t * enp)502 ef10_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 
557 fail1:
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 
569 static	__checkReturn	efx_rc_t
ef10_filter_add_internal(__in efx_nic_t * enp,__inout efx_filter_spec_t * spec,__in boolean_t may_replace,__out_opt uint32_t * filter_id)570 ef10_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 
658 found:
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 
722 out_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 
732 fail4:
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 
742 fail3:
743 	EFSYS_PROBE(fail3);
744 
745 fail2:
746 	EFSYS_PROBE(fail2);
747 
748 fail1:
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
ef10_filter_add(__in efx_nic_t * enp,__inout efx_filter_spec_t * spec,__in boolean_t may_replace)758 ef10_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 
771 fail1:
772 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
773 
774 	return (rc);
775 }
776 
777 
778 static	__checkReturn	efx_rc_t
ef10_filter_delete_internal(__in efx_nic_t * enp,__in uint32_t filter_id)779 ef10_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 
840 fail2:
841 	EFSYS_PROBE(fail2);
842 
843 fail1:
844 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
845 
846 	return (rc);
847 }
848 
849 	__checkReturn	efx_rc_t
ef10_filter_delete(__in efx_nic_t * enp,__inout efx_filter_spec_t * spec)850 ef10_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 
895 fail2:
896 	EFSYS_PROBE(fail2);
897 
898 fail1:
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 
907 static	__checkReturn	efx_rc_t
efx_mcdi_get_parser_disp_info(__in efx_nic_t * enp,__out_ecount (buffer_length)uint32_t * buffer,__in size_t buffer_length,__out size_t * list_lengthp)908 efx_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 
970 fail3:
971 	EFSYS_PROBE(fail3);
972 fail2:
973 	EFSYS_PROBE(fail2);
974 fail1:
975 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
976 
977 	return (rc);
978 }
979 
980 	__checkReturn	efx_rc_t
ef10_filter_supported_filters(__in efx_nic_t * enp,__out_ecount (buffer_length)uint32_t * buffer,__in size_t buffer_length,__out size_t * list_lengthp)981 ef10_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 
1034 fail1:
1035 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1036 
1037 	return (rc);
1038 }
1039 
1040 static	__checkReturn	efx_rc_t
1041 ef10_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 
1070 fail2:
1071 	EFSYS_PROBE(fail2);
1072 fail1:
1073 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1074 	return (rc);
1075 }
1076 
1077 static	__checkReturn	efx_rc_t
ef10_filter_insert_all_unicast(__in efx_nic_t * enp,__in efx_filter_flags_t filter_flags)1078 ef10_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 
1104 fail2:
1105 	EFSYS_PROBE(fail2);
1106 fail1:
1107 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1108 	return (rc);
1109 }
1110 
1111 static	__checkReturn	efx_rc_t
1112 ef10_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 
1209 rollback:
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 
1218 fail1:
1219 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1220 
1221 	return (rc);
1222 }
1223 
1224 static	__checkReturn	efx_rc_t
ef10_filter_insert_all_multicast(__in efx_nic_t * enp,__in efx_filter_flags_t filter_flags)1225 ef10_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 
1255 fail2:
1256 	EFSYS_PROBE(fail2);
1257 fail1:
1258 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1259 
1260 	return (rc);
1261 }
1262 
1263 typedef 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 
1273 static 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 
1292 static	__checkReturn	efx_rc_t
ef10_filter_insert_encap_filters(__in efx_nic_t * enp,__in boolean_t mulcst,__in efx_filter_flags_t filter_flags)1293 ef10_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 
1357 fail2:
1358 	EFSYS_PROBE(fail2);
1359 fail1:
1360 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1361 
1362 	return (rc);
1363 }
1364 
1365 static			void
ef10_filter_remove_old(__in efx_nic_t * enp)1366 ef10_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 
1380 static	__checkReturn	efx_rc_t
ef10_filter_get_workarounds(__in efx_nic_t * enp)1381 ef10_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 
1408 fail1:
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
1423 ef10_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 
1622 fail4:
1623 	EFSYS_PROBE(fail4);
1624 fail3:
1625 	EFSYS_PROBE(fail3);
1626 fail2:
1627 	EFSYS_PROBE(fail2);
1628 fail1:
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
ef10_filter_get_default_rxq(__in efx_nic_t * enp,__out efx_rxq_t ** erpp,__out boolean_t * using_rss)1642 ef10_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
ef10_filter_default_rxq_set(__in efx_nic_t * enp,__in efx_rxq_t * erp,__in boolean_t using_rss)1655 ef10_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
ef10_filter_default_rxq_clear(__in efx_nic_t * enp)1674 ef10_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