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