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