1 /* SPDX-License-Identifier: BSD-3-Clause
2 *
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2007-2019 Solarflare Communications Inc.
5 */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10 #if EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10()
11
12 #if EFSYS_OPT_FILTER
13
14 #define EFE_SPEC(eftp, index) ((eftp)->eft_entry[(index)].efe_spec)
15
16 static efx_filter_spec_t *
ef10_filter_entry_spec(__in const ef10_filter_table_t * eftp,__in unsigned int index)17 ef10_filter_entry_spec(
18 __in const ef10_filter_table_t *eftp,
19 __in unsigned int index)
20 {
21 return ((efx_filter_spec_t *)(EFE_SPEC(eftp, index) &
22 ~(uintptr_t)EFX_EF10_FILTER_FLAGS));
23 }
24
25 static boolean_t
ef10_filter_entry_is_busy(__in const ef10_filter_table_t * eftp,__in unsigned int index)26 ef10_filter_entry_is_busy(
27 __in const ef10_filter_table_t *eftp,
28 __in unsigned int index)
29 {
30 if (EFE_SPEC(eftp, index) & EFX_EF10_FILTER_FLAG_BUSY)
31 return (B_TRUE);
32 else
33 return (B_FALSE);
34 }
35
36 static boolean_t
ef10_filter_entry_is_auto_old(__in const ef10_filter_table_t * eftp,__in unsigned int index)37 ef10_filter_entry_is_auto_old(
38 __in const ef10_filter_table_t *eftp,
39 __in unsigned int index)
40 {
41 if (EFE_SPEC(eftp, index) & EFX_EF10_FILTER_FLAG_AUTO_OLD)
42 return (B_TRUE);
43 else
44 return (B_FALSE);
45 }
46
47 static void
ef10_filter_set_entry(__inout ef10_filter_table_t * eftp,__in unsigned int index,__in_opt const efx_filter_spec_t * efsp)48 ef10_filter_set_entry(
49 __inout ef10_filter_table_t *eftp,
50 __in unsigned int index,
51 __in_opt const efx_filter_spec_t *efsp)
52 {
53 EFE_SPEC(eftp, index) = (uintptr_t)efsp;
54 }
55
56 static void
ef10_filter_set_entry_busy(__inout ef10_filter_table_t * eftp,__in unsigned int index)57 ef10_filter_set_entry_busy(
58 __inout ef10_filter_table_t *eftp,
59 __in unsigned int index)
60 {
61 EFE_SPEC(eftp, index) |= (uintptr_t)EFX_EF10_FILTER_FLAG_BUSY;
62 }
63
64 static void
ef10_filter_set_entry_not_busy(__inout ef10_filter_table_t * eftp,__in unsigned int index)65 ef10_filter_set_entry_not_busy(
66 __inout ef10_filter_table_t *eftp,
67 __in unsigned int index)
68 {
69 EFE_SPEC(eftp, index) &= ~(uintptr_t)EFX_EF10_FILTER_FLAG_BUSY;
70 }
71
72 static void
ef10_filter_set_entry_auto_old(__inout ef10_filter_table_t * eftp,__in unsigned int index)73 ef10_filter_set_entry_auto_old(
74 __inout ef10_filter_table_t *eftp,
75 __in unsigned int index)
76 {
77 EFSYS_ASSERT(ef10_filter_entry_spec(eftp, index) != NULL);
78 EFE_SPEC(eftp, index) |= (uintptr_t)EFX_EF10_FILTER_FLAG_AUTO_OLD;
79 }
80
81 static void
ef10_filter_set_entry_not_auto_old(__inout ef10_filter_table_t * eftp,__in unsigned int index)82 ef10_filter_set_entry_not_auto_old(
83 __inout ef10_filter_table_t *eftp,
84 __in unsigned int index)
85 {
86 EFE_SPEC(eftp, index) &= ~(uintptr_t)EFX_EF10_FILTER_FLAG_AUTO_OLD;
87 EFSYS_ASSERT(ef10_filter_entry_spec(eftp, index) != NULL);
88 }
89
90 __checkReturn efx_rc_t
ef10_filter_init(__in efx_nic_t * enp)91 ef10_filter_init(
92 __in efx_nic_t *enp)
93 {
94 efx_rc_t rc;
95 ef10_filter_table_t *eftp;
96
97 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
98
99 #define MATCH_MASK(match) (EFX_MASK32(match) << EFX_LOW_BIT(match))
100 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_HOST ==
101 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_IP));
102 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_HOST ==
103 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_IP));
104 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_MAC ==
105 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_MAC));
106 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_REM_PORT ==
107 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_SRC_PORT));
108 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_MAC ==
109 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_MAC));
110 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_LOC_PORT ==
111 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_DST_PORT));
112 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_ETHER_TYPE ==
113 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_ETHER_TYPE));
114 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_INNER_VID ==
115 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_INNER_VLAN));
116 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_OUTER_VID ==
117 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_OUTER_VLAN));
118 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IP_PROTO ==
119 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IP_PROTO));
120 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_VNI_OR_VSID ==
121 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_VNI_OR_VSID));
122 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_LOC_MAC ==
123 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_DST_MAC));
124 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST ==
125 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_MCAST_DST));
126 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST ==
127 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_IFRM_UNKNOWN_UCAST_DST));
128 EFX_STATIC_ASSERT(EFX_FILTER_MATCH_UNKNOWN_MCAST_DST ==
129 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_MCAST_DST));
130 EFX_STATIC_ASSERT((uint32_t)EFX_FILTER_MATCH_UNKNOWN_UCAST_DST ==
131 MATCH_MASK(MC_CMD_FILTER_OP_EXT_IN_MATCH_UNKNOWN_UCAST_DST));
132 #undef MATCH_MASK
133
134 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (ef10_filter_table_t), eftp);
135
136 if (!eftp) {
137 rc = ENOMEM;
138 goto fail1;
139 }
140
141 enp->en_filter.ef_ef10_filter_table = eftp;
142
143 return (0);
144
145 fail1:
146 EFSYS_PROBE1(fail1, efx_rc_t, rc);
147
148 return (rc);
149 }
150
151 void
ef10_filter_fini(__in efx_nic_t * enp)152 ef10_filter_fini(
153 __in efx_nic_t *enp)
154 {
155 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
156
157 if (enp->en_filter.ef_ef10_filter_table != NULL) {
158 EFSYS_KMEM_FREE(enp->en_esip, sizeof (ef10_filter_table_t),
159 enp->en_filter.ef_ef10_filter_table);
160 }
161 }
162
163 static __checkReturn efx_rc_t
efx_mcdi_filter_op_add(__in efx_nic_t * enp,__in efx_filter_spec_t * spec,__in unsigned int filter_op,__inout ef10_filter_handle_t * handle)164 efx_mcdi_filter_op_add(
165 __in efx_nic_t *enp,
166 __in efx_filter_spec_t *spec,
167 __in unsigned int filter_op,
168 __inout ef10_filter_handle_t *handle)
169 {
170 efx_mcdi_req_t req;
171 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_V3_IN_LEN,
172 MC_CMD_FILTER_OP_EXT_OUT_LEN);
173 efx_filter_match_flags_t match_flags;
174 efx_port_t *epp = &(enp->en_port);
175 uint32_t port_id;
176 efx_rc_t rc;
177
178 req.emr_cmd = MC_CMD_FILTER_OP;
179 req.emr_in_buf = payload;
180 req.emr_in_length = MC_CMD_FILTER_OP_V3_IN_LEN;
181 req.emr_out_buf = payload;
182 req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN;
183
184 /*
185 * Remove EFX match flags that do not correspond
186 * to the MCDI match flags
187 */
188 match_flags = spec->efs_match_flags & ~EFX_FILTER_MATCH_ENCAP_TYPE;
189 match_flags &= ~EFX_FILTER_MATCH_MPORT;
190
191 switch (filter_op) {
192 case MC_CMD_FILTER_OP_IN_OP_REPLACE:
193 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO,
194 handle->efh_lo);
195 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_HI,
196 handle->efh_hi);
197 /* Fall through */
198 case MC_CMD_FILTER_OP_IN_OP_INSERT:
199 case MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE:
200 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP, filter_op);
201 break;
202 default:
203 EFSYS_ASSERT(0);
204 rc = EINVAL;
205 goto fail1;
206 }
207
208 if (spec->efs_match_flags & EFX_FILTER_MATCH_MPORT)
209 port_id = spec->efs_ingress_mport;
210 else
211 port_id = enp->en_vport_id;
212
213 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_PORT_ID, port_id);
214 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_MATCH_FIELDS,
215 match_flags);
216 if (spec->efs_dmaq_id == EFX_FILTER_SPEC_RX_DMAQ_ID_DROP) {
217 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST,
218 MC_CMD_FILTER_OP_EXT_IN_RX_DEST_DROP);
219 } else {
220 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_DEST,
221 MC_CMD_FILTER_OP_EXT_IN_RX_DEST_HOST);
222 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_QUEUE,
223 spec->efs_dmaq_id);
224 }
225
226 #if EFSYS_OPT_RX_SCALE
227 if (spec->efs_flags & EFX_FILTER_FLAG_RX_RSS) {
228 uint32_t rss_context;
229
230 if (spec->efs_rss_context == EFX_RSS_CONTEXT_DEFAULT)
231 rss_context = enp->en_rss_context;
232 else
233 rss_context = spec->efs_rss_context;
234 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_CONTEXT,
235 rss_context);
236 }
237 #endif
238
239 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_RX_MODE,
240 spec->efs_flags & EFX_FILTER_FLAG_RX_RSS ?
241 MC_CMD_FILTER_OP_EXT_IN_RX_MODE_RSS :
242 MC_CMD_FILTER_OP_EXT_IN_RX_MODE_SIMPLE);
243 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_TX_DEST,
244 MC_CMD_FILTER_OP_EXT_IN_TX_DEST_DEFAULT);
245
246 if (filter_op != MC_CMD_FILTER_OP_IN_OP_REPLACE) {
247 /*
248 * NOTE: Unlike most MCDI requests, the filter fields
249 * are presented in network (big endian) byte order.
250 */
251 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_SRC_MAC),
252 spec->efs_rem_mac, EFX_MAC_ADDR_LEN);
253 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_DST_MAC),
254 spec->efs_loc_mac, EFX_MAC_ADDR_LEN);
255
256 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_SRC_PORT,
257 __CPU_TO_BE_16(spec->efs_rem_port));
258 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_DST_PORT,
259 __CPU_TO_BE_16(spec->efs_loc_port));
260
261 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_ETHER_TYPE,
262 __CPU_TO_BE_16(spec->efs_ether_type));
263
264 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_INNER_VLAN,
265 __CPU_TO_BE_16(spec->efs_inner_vid));
266 MCDI_IN_SET_WORD(req, FILTER_OP_EXT_IN_OUTER_VLAN,
267 __CPU_TO_BE_16(spec->efs_outer_vid));
268
269 /* IP protocol (in low byte, high byte is zero) */
270 MCDI_IN_SET_BYTE(req, FILTER_OP_EXT_IN_IP_PROTO,
271 spec->efs_ip_proto);
272
273 EFX_STATIC_ASSERT(sizeof (spec->efs_rem_host) ==
274 MC_CMD_FILTER_OP_EXT_IN_SRC_IP_LEN);
275 EFX_STATIC_ASSERT(sizeof (spec->efs_loc_host) ==
276 MC_CMD_FILTER_OP_EXT_IN_DST_IP_LEN);
277
278 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_SRC_IP),
279 &spec->efs_rem_host.eo_byte[0],
280 MC_CMD_FILTER_OP_EXT_IN_SRC_IP_LEN);
281 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_DST_IP),
282 &spec->efs_loc_host.eo_byte[0],
283 MC_CMD_FILTER_OP_EXT_IN_DST_IP_LEN);
284
285 /*
286 * On Medford, filters for encapsulated packets match based on
287 * the ether type and IP protocol in the outer frame. In
288 * addition we need to fill in the VNI or VSID type field.
289 */
290 switch (spec->efs_encap_type) {
291 case EFX_TUNNEL_PROTOCOL_NONE:
292 break;
293 case EFX_TUNNEL_PROTOCOL_VXLAN:
294 case EFX_TUNNEL_PROTOCOL_GENEVE:
295 MCDI_IN_POPULATE_DWORD_1(req,
296 FILTER_OP_EXT_IN_VNI_OR_VSID,
297 FILTER_OP_EXT_IN_VNI_TYPE,
298 spec->efs_encap_type == EFX_TUNNEL_PROTOCOL_VXLAN ?
299 MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_VXLAN :
300 MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_GENEVE);
301 break;
302 case EFX_TUNNEL_PROTOCOL_NVGRE:
303 MCDI_IN_POPULATE_DWORD_1(req,
304 FILTER_OP_EXT_IN_VNI_OR_VSID,
305 FILTER_OP_EXT_IN_VSID_TYPE,
306 MC_CMD_FILTER_OP_EXT_IN_VSID_TYPE_NVGRE);
307 break;
308 default:
309 EFSYS_ASSERT(0);
310 rc = EINVAL;
311 goto fail2;
312 }
313
314 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_VNI_OR_VSID),
315 spec->efs_vni_or_vsid, EFX_VNI_OR_VSID_LEN);
316
317 memcpy(MCDI_IN2(req, uint8_t, FILTER_OP_EXT_IN_IFRM_DST_MAC),
318 spec->efs_ifrm_loc_mac, EFX_MAC_ADDR_LEN);
319 }
320
321 /*
322 * Set the "MARK" or "FLAG" action for all packets matching this filter
323 * if necessary (only useful with equal stride packed stream Rx mode
324 * which provide the information in pseudo-header).
325 * These actions require MC_CMD_FILTER_OP_V3_IN msgrequest.
326 */
327 if ((spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) &&
328 (spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG)) {
329 rc = EINVAL;
330 goto fail3;
331 }
332 if (spec->efs_flags & EFX_FILTER_FLAG_ACTION_MARK) {
333 MCDI_IN_SET_DWORD_FIELD(req, FILTER_OP_V3_IN_MATCH_ACTION_FLAGS,
334 FILTER_OP_V3_IN_MATCH_SET_MARK, 1);
335 MCDI_IN_SET_DWORD(req, FILTER_OP_V3_IN_MATCH_MARK_VALUE,
336 spec->efs_mark);
337 } else if (spec->efs_flags & EFX_FILTER_FLAG_ACTION_FLAG) {
338 MCDI_IN_SET_DWORD_FIELD(req, FILTER_OP_V3_IN_MATCH_ACTION_FLAGS,
339 FILTER_OP_V3_IN_MATCH_SET_FLAG, 1);
340 }
341
342 if (epp->ep_vlan_strip) {
343 MCDI_IN_SET_DWORD_FIELD(req, FILTER_OP_V3_IN_MATCH_ACTION_FLAGS,
344 FILTER_OP_V3_IN_MATCH_STRIP_VLAN, 1);
345 }
346
347 efx_mcdi_execute(enp, &req);
348
349 if (req.emr_rc != 0) {
350 rc = req.emr_rc;
351 goto fail4;
352 }
353
354 if (req.emr_out_length_used < MC_CMD_FILTER_OP_EXT_OUT_LEN) {
355 rc = EMSGSIZE;
356 goto fail5;
357 }
358
359 handle->efh_lo = MCDI_OUT_DWORD(req, FILTER_OP_EXT_OUT_HANDLE_LO);
360 handle->efh_hi = MCDI_OUT_DWORD(req, FILTER_OP_EXT_OUT_HANDLE_HI);
361
362 return (0);
363
364 fail5:
365 EFSYS_PROBE(fail5);
366 fail4:
367 EFSYS_PROBE(fail4);
368 fail3:
369 EFSYS_PROBE(fail3);
370 fail2:
371 EFSYS_PROBE(fail2);
372 fail1:
373 EFSYS_PROBE1(fail1, efx_rc_t, rc);
374
375 return (rc);
376
377 }
378
379 static __checkReturn efx_rc_t
efx_mcdi_filter_op_delete(__in efx_nic_t * enp,__in unsigned int filter_op,__inout ef10_filter_handle_t * handle)380 efx_mcdi_filter_op_delete(
381 __in efx_nic_t *enp,
382 __in unsigned int filter_op,
383 __inout ef10_filter_handle_t *handle)
384 {
385 efx_mcdi_req_t req;
386 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_FILTER_OP_EXT_IN_LEN,
387 MC_CMD_FILTER_OP_EXT_OUT_LEN);
388 efx_rc_t rc;
389
390 req.emr_cmd = MC_CMD_FILTER_OP;
391 req.emr_in_buf = payload;
392 req.emr_in_length = MC_CMD_FILTER_OP_EXT_IN_LEN;
393 req.emr_out_buf = payload;
394 req.emr_out_length = MC_CMD_FILTER_OP_EXT_OUT_LEN;
395
396 switch (filter_op) {
397 case MC_CMD_FILTER_OP_IN_OP_REMOVE:
398 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP,
399 MC_CMD_FILTER_OP_IN_OP_REMOVE);
400 break;
401 case MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE:
402 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_OP,
403 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE);
404 break;
405 default:
406 EFSYS_ASSERT(0);
407 rc = EINVAL;
408 goto fail1;
409 }
410
411 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_LO, handle->efh_lo);
412 MCDI_IN_SET_DWORD(req, FILTER_OP_EXT_IN_HANDLE_HI, handle->efh_hi);
413
414 efx_mcdi_execute_quiet(enp, &req);
415
416 if (req.emr_rc != 0) {
417 rc = req.emr_rc;
418 goto fail2;
419 }
420
421 if (req.emr_out_length_used < MC_CMD_FILTER_OP_EXT_OUT_LEN) {
422 rc = EMSGSIZE;
423 goto fail3;
424 }
425
426 return (0);
427
428 fail3:
429 EFSYS_PROBE(fail3);
430
431 fail2:
432 EFSYS_PROBE(fail2);
433 fail1:
434 EFSYS_PROBE1(fail1, efx_rc_t, rc);
435
436 return (rc);
437 }
438
439 static __checkReturn boolean_t
ef10_filter_equal(__in const efx_filter_spec_t * left,__in const efx_filter_spec_t * right)440 ef10_filter_equal(
441 __in const efx_filter_spec_t *left,
442 __in const efx_filter_spec_t *right)
443 {
444 /* FIXME: Consider rx vs tx filters (look at efs_flags) */
445 if (left->efs_match_flags != right->efs_match_flags)
446 return (B_FALSE);
447 if (!EFX_OWORD_IS_EQUAL(left->efs_rem_host, right->efs_rem_host))
448 return (B_FALSE);
449 if (!EFX_OWORD_IS_EQUAL(left->efs_loc_host, right->efs_loc_host))
450 return (B_FALSE);
451 if (memcmp(left->efs_rem_mac, right->efs_rem_mac, EFX_MAC_ADDR_LEN))
452 return (B_FALSE);
453 if (memcmp(left->efs_loc_mac, right->efs_loc_mac, EFX_MAC_ADDR_LEN))
454 return (B_FALSE);
455 if (left->efs_rem_port != right->efs_rem_port)
456 return (B_FALSE);
457 if (left->efs_loc_port != right->efs_loc_port)
458 return (B_FALSE);
459 if (left->efs_inner_vid != right->efs_inner_vid)
460 return (B_FALSE);
461 if (left->efs_outer_vid != right->efs_outer_vid)
462 return (B_FALSE);
463 if (left->efs_ether_type != right->efs_ether_type)
464 return (B_FALSE);
465 if (left->efs_ip_proto != right->efs_ip_proto)
466 return (B_FALSE);
467 if (left->efs_encap_type != right->efs_encap_type)
468 return (B_FALSE);
469 if (memcmp(left->efs_vni_or_vsid, right->efs_vni_or_vsid,
470 EFX_VNI_OR_VSID_LEN))
471 return (B_FALSE);
472 if (memcmp(left->efs_ifrm_loc_mac, right->efs_ifrm_loc_mac,
473 EFX_MAC_ADDR_LEN))
474 return (B_FALSE);
475
476 return (B_TRUE);
477
478 }
479
480 static __checkReturn boolean_t
ef10_filter_same_dest(__in const efx_filter_spec_t * left,__in const efx_filter_spec_t * right)481 ef10_filter_same_dest(
482 __in const efx_filter_spec_t *left,
483 __in const efx_filter_spec_t *right)
484 {
485 if ((left->efs_flags & EFX_FILTER_FLAG_RX_RSS) &&
486 (right->efs_flags & EFX_FILTER_FLAG_RX_RSS)) {
487 if (left->efs_rss_context == right->efs_rss_context)
488 return (B_TRUE);
489 } else if ((~(left->efs_flags) & EFX_FILTER_FLAG_RX_RSS) &&
490 (~(right->efs_flags) & EFX_FILTER_FLAG_RX_RSS)) {
491 if (left->efs_dmaq_id == right->efs_dmaq_id)
492 return (B_TRUE);
493 }
494 return (B_FALSE);
495 }
496
497 static __checkReturn uint32_t
ef10_filter_hash(__in efx_filter_spec_t * spec)498 ef10_filter_hash(
499 __in efx_filter_spec_t *spec)
500 {
501 EFX_STATIC_ASSERT((sizeof (efx_filter_spec_t) % sizeof (uint32_t))
502 == 0);
503 EFX_STATIC_ASSERT((EFX_FIELD_OFFSET(efx_filter_spec_t, efs_outer_vid) %
504 sizeof (uint32_t)) == 0);
505
506 /*
507 * As the area of the efx_filter_spec_t we need to hash is DWORD
508 * aligned and an exact number of DWORDs in size we can use the
509 * optimised efx_hash_dwords() rather than efx_hash_bytes()
510 */
511 return (efx_hash_dwords((const uint32_t *)&spec->efs_outer_vid,
512 (sizeof (efx_filter_spec_t) -
513 EFX_FIELD_OFFSET(efx_filter_spec_t, efs_outer_vid)) /
514 sizeof (uint32_t), 0));
515 }
516
517 /*
518 * Decide whether a filter should be exclusive or else should allow
519 * delivery to additional recipients. Currently we decide that
520 * filters for specific local unicast MAC and IP addresses are
521 * exclusive.
522 */
523 static __checkReturn boolean_t
ef10_filter_is_exclusive(__in efx_filter_spec_t * spec)524 ef10_filter_is_exclusive(
525 __in efx_filter_spec_t *spec)
526 {
527 if ((spec->efs_match_flags & EFX_FILTER_MATCH_LOC_MAC) &&
528 !EFX_MAC_ADDR_IS_MULTICAST(spec->efs_loc_mac))
529 return (B_TRUE);
530
531 if ((spec->efs_match_flags &
532 (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) ==
533 (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_LOC_HOST)) {
534 if ((spec->efs_ether_type == EFX_ETHER_TYPE_IPV4) &&
535 ((spec->efs_loc_host.eo_u8[0] & 0xf) != 0xe))
536 return (B_TRUE);
537 if ((spec->efs_ether_type == EFX_ETHER_TYPE_IPV6) &&
538 (spec->efs_loc_host.eo_u8[0] != 0xff))
539 return (B_TRUE);
540 }
541
542 return (B_FALSE);
543 }
544
545 __checkReturn efx_rc_t
ef10_filter_restore(__in efx_nic_t * enp)546 ef10_filter_restore(
547 __in efx_nic_t *enp)
548 {
549 int tbl_id;
550 efx_filter_spec_t *spec;
551 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
552 boolean_t restoring;
553 efsys_lock_state_t state;
554 efx_rc_t rc;
555
556 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
557
558 for (tbl_id = 0; tbl_id < EFX_EF10_FILTER_TBL_ROWS; tbl_id++) {
559
560 EFSYS_LOCK(enp->en_eslp, state);
561
562 spec = ef10_filter_entry_spec(eftp, tbl_id);
563 if (spec == NULL) {
564 restoring = B_FALSE;
565 } else if (ef10_filter_entry_is_busy(eftp, tbl_id)) {
566 /* Ignore busy entries. */
567 restoring = B_FALSE;
568 } else {
569 ef10_filter_set_entry_busy(eftp, tbl_id);
570 restoring = B_TRUE;
571 }
572
573 EFSYS_UNLOCK(enp->en_eslp, state);
574
575 if (restoring == B_FALSE)
576 continue;
577
578 if (ef10_filter_is_exclusive(spec)) {
579 rc = efx_mcdi_filter_op_add(enp, spec,
580 MC_CMD_FILTER_OP_IN_OP_INSERT,
581 &eftp->eft_entry[tbl_id].efe_handle);
582 } else {
583 rc = efx_mcdi_filter_op_add(enp, spec,
584 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE,
585 &eftp->eft_entry[tbl_id].efe_handle);
586 }
587
588 if (rc != 0)
589 goto fail1;
590
591 EFSYS_LOCK(enp->en_eslp, state);
592
593 ef10_filter_set_entry_not_busy(eftp, tbl_id);
594
595 EFSYS_UNLOCK(enp->en_eslp, state);
596 }
597
598 return (0);
599
600 fail1:
601 EFSYS_PROBE1(fail1, efx_rc_t, rc);
602
603 return (rc);
604 }
605
606 enum ef10_filter_add_action_e {
607 /* Insert a new filter */
608 EF10_FILTER_ADD_NEW,
609 /*
610 * Replace old filter with a new, overriding the old one
611 * if it has lower priority.
612 */
613 EF10_FILTER_ADD_REPLACE,
614 /* Store new, lower priority filter as overridden by old filter */
615 EF10_FILTER_ADD_STORE,
616 /* Special case for AUTO filters, remove AUTO_OLD flag */
617 EF10_FILTER_ADD_REFRESH,
618 };
619
620 static __checkReturn efx_rc_t
ef10_filter_add_lookup_equal_spec(__in efx_filter_spec_t * spec,__in efx_filter_spec_t * probe_spec,__in efx_filter_replacement_policy_t policy,__out boolean_t * found)621 ef10_filter_add_lookup_equal_spec(
622 __in efx_filter_spec_t *spec,
623 __in efx_filter_spec_t *probe_spec,
624 __in efx_filter_replacement_policy_t policy,
625 __out boolean_t *found)
626 {
627 efx_rc_t rc;
628
629 /* Refreshing AUTO filter */
630 if (spec->efs_priority == EFX_FILTER_PRI_AUTO &&
631 probe_spec->efs_priority == EFX_FILTER_PRI_AUTO) {
632 *found = B_TRUE;
633 return (0);
634 }
635
636 /*
637 * With exclusive filters, higher priority ones
638 * override lower priority ones, and lower priority
639 * ones are stored in case the higher priority one
640 * is removed.
641 */
642 if (ef10_filter_is_exclusive(spec)) {
643 switch (policy) {
644 case EFX_FILTER_REPLACEMENT_HIGHER_OR_EQUAL_PRIORITY:
645 if (spec->efs_priority == probe_spec->efs_priority) {
646 *found = B_TRUE;
647 break;
648 }
649 /* Fall-through */
650 case EFX_FILTER_REPLACEMENT_HIGHER_PRIORITY:
651 if (spec->efs_priority > probe_spec->efs_priority) {
652 *found = B_TRUE;
653 break;
654 }
655 /* Fall-through */
656 case EFX_FILTER_REPLACEMENT_NEVER:
657 /*
658 * Lower priority filter needs to be
659 * stored. It does *not* replace the
660 * old one. That is why EEXIST is not
661 * returned in that case.
662 */
663 if (spec->efs_priority < probe_spec->efs_priority) {
664 *found = B_TRUE;
665 break;
666 } else {
667 rc = EEXIST;
668 goto fail1;
669 }
670 default:
671 EFSYS_ASSERT(0);
672 rc = EEXIST;
673 goto fail2;
674 }
675 } else {
676 *found = B_FALSE;
677 }
678
679 return (0);
680
681 fail2:
682 EFSYS_PROBE(fail2);
683
684 fail1:
685 EFSYS_PROBE1(fail1, efx_rc_t, rc);
686
687 return (rc);
688 }
689
690
691 static void
ef10_filter_add_select_action(__in efx_filter_spec_t * saved_spec,__in efx_filter_spec_t * spec,__out enum ef10_filter_add_action_e * action,__out efx_filter_spec_t ** overridden_spec)692 ef10_filter_add_select_action(
693 __in efx_filter_spec_t *saved_spec,
694 __in efx_filter_spec_t *spec,
695 __out enum ef10_filter_add_action_e *action,
696 __out efx_filter_spec_t **overridden_spec)
697 {
698 efx_filter_spec_t *overridden = NULL;
699
700 if (saved_spec == NULL) {
701 *action = EF10_FILTER_ADD_NEW;
702 } else if (ef10_filter_is_exclusive(spec) == B_FALSE) {
703 /*
704 * Non-exclusive filters are always stored in separate entries
705 * in the table. The only case involving a saved spec is
706 * refreshing an AUTO filter.
707 */
708 EFSYS_ASSERT(saved_spec->efs_overridden_spec == NULL);
709 EFSYS_ASSERT(spec->efs_priority == EFX_FILTER_PRI_AUTO);
710 EFSYS_ASSERT(saved_spec->efs_priority == EFX_FILTER_PRI_AUTO);
711 *action = EF10_FILTER_ADD_REFRESH;
712 } else {
713 /* Exclusive filters stored in the same entry */
714 if (spec->efs_priority > saved_spec->efs_priority) {
715 /*
716 * Insert a high priority filter over a lower priority
717 * one. Only two priority levels are implemented, so
718 * there must not already be an overridden filter.
719 */
720 EFX_STATIC_ASSERT(EFX_FILTER_NPRI == 2);
721 EFSYS_ASSERT(saved_spec->efs_overridden_spec == NULL);
722 overridden = saved_spec;
723 *action = EF10_FILTER_ADD_REPLACE;
724 } else if (spec->efs_priority == saved_spec->efs_priority) {
725 /* Replace in-place or refresh an existing filter */
726 if (spec->efs_priority == EFX_FILTER_PRI_AUTO)
727 *action = EF10_FILTER_ADD_REFRESH;
728 else
729 *action = EF10_FILTER_ADD_REPLACE;
730 } else {
731 /*
732 * Insert a lower priority filter, storing it in case
733 * the higher priority filter is removed.
734 *
735 * Currently there are only two priority levels, so this
736 * must be an AUTO filter.
737 */
738 EFX_STATIC_ASSERT(EFX_FILTER_NPRI == 2);
739 EFSYS_ASSERT(spec->efs_priority == EFX_FILTER_PRI_AUTO);
740 if (saved_spec->efs_overridden_spec != NULL) {
741 *action = EF10_FILTER_ADD_REFRESH;
742 } else {
743 overridden = spec;
744 *action = EF10_FILTER_ADD_STORE;
745 }
746 }
747 }
748
749 *overridden_spec = overridden;
750 }
751
752 static __checkReturn efx_rc_t
ef10_filter_add_execute_action(__in efx_nic_t * enp,__in efx_filter_spec_t * saved_spec,__in efx_filter_spec_t * spec,__in efx_filter_spec_t * overridden_spec,__in enum ef10_filter_add_action_e action,__in int ins_index)753 ef10_filter_add_execute_action(
754 __in efx_nic_t *enp,
755 __in efx_filter_spec_t *saved_spec,
756 __in efx_filter_spec_t *spec,
757 __in efx_filter_spec_t *overridden_spec,
758 __in enum ef10_filter_add_action_e action,
759 __in int ins_index)
760 {
761 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
762 efsys_lock_state_t state;
763 efx_rc_t rc;
764
765 EFSYS_LOCK(enp->en_eslp, state);
766
767 if (action == EF10_FILTER_ADD_REFRESH) {
768 ef10_filter_set_entry_not_auto_old(eftp, ins_index);
769 goto out_unlock;
770 } else if (action == EF10_FILTER_ADD_STORE) {
771 EFSYS_ASSERT(overridden_spec != NULL);
772 saved_spec->efs_overridden_spec = overridden_spec;
773 goto out_unlock;
774 }
775
776 EFSYS_UNLOCK(enp->en_eslp, state);
777
778 switch (action) {
779 case EF10_FILTER_ADD_REPLACE:
780 /*
781 * On replacing the filter handle may change after a
782 * successful replace operation.
783 */
784 rc = efx_mcdi_filter_op_add(enp, spec,
785 MC_CMD_FILTER_OP_IN_OP_REPLACE,
786 &eftp->eft_entry[ins_index].efe_handle);
787 break;
788 case EF10_FILTER_ADD_NEW:
789 if (ef10_filter_is_exclusive(spec)) {
790 rc = efx_mcdi_filter_op_add(enp, spec,
791 MC_CMD_FILTER_OP_IN_OP_INSERT,
792 &eftp->eft_entry[ins_index].efe_handle);
793 } else {
794 rc = efx_mcdi_filter_op_add(enp, spec,
795 MC_CMD_FILTER_OP_IN_OP_SUBSCRIBE,
796 &eftp->eft_entry[ins_index].efe_handle);
797 }
798 break;
799 default:
800 rc = EINVAL;
801 EFSYS_ASSERT(0);
802 break;
803 }
804 if (rc != 0)
805 goto fail1;
806
807 EFSYS_LOCK(enp->en_eslp, state);
808
809 if (action == EF10_FILTER_ADD_REPLACE) {
810 /* Update the fields that may differ */
811 saved_spec->efs_priority = spec->efs_priority;
812 saved_spec->efs_flags = spec->efs_flags;
813 saved_spec->efs_rss_context = spec->efs_rss_context;
814 saved_spec->efs_dmaq_id = spec->efs_dmaq_id;
815
816 if (overridden_spec != NULL)
817 saved_spec->efs_overridden_spec = overridden_spec;
818 }
819
820 out_unlock:
821 EFSYS_UNLOCK(enp->en_eslp, state);
822
823 return (0);
824
825 fail1:
826 EFSYS_PROBE1(fail1, efx_rc_t, rc);
827
828 return (rc);
829 }
830
831 /*
832 * An arbitrary search limit for the software hash table. As per the linux net
833 * driver.
834 */
835 #define EF10_FILTER_SEARCH_LIMIT 200
836
837 static __checkReturn efx_rc_t
ef10_filter_add_internal(__in efx_nic_t * enp,__inout efx_filter_spec_t * spec,__in efx_filter_replacement_policy_t policy,__out_opt uint32_t * filter_id)838 ef10_filter_add_internal(
839 __in efx_nic_t *enp,
840 __inout efx_filter_spec_t *spec,
841 __in efx_filter_replacement_policy_t policy,
842 __out_opt uint32_t *filter_id)
843 {
844 efx_rc_t rc;
845 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
846 enum ef10_filter_add_action_e action;
847 efx_filter_spec_t *overridden_spec = NULL;
848 efx_filter_spec_t *saved_spec;
849 uint32_t hash;
850 unsigned int depth;
851 int ins_index;
852 efsys_lock_state_t state;
853 boolean_t locked = B_FALSE;
854
855 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
856
857 EFSYS_ASSERT(spec->efs_overridden_spec == NULL);
858
859 hash = ef10_filter_hash(spec);
860
861 /*
862 * FIXME: Add support for inserting filters of different priorities
863 * and removing lower priority multicast filters (bug 42378)
864 */
865
866 /*
867 * Find any existing filters with the same match tuple or
868 * else a free slot to insert at. If any of them are busy,
869 * we have to wait and retry.
870 */
871 retry:
872 EFSYS_LOCK(enp->en_eslp, state);
873 locked = B_TRUE;
874
875 ins_index = -1;
876
877 for (depth = 1; depth <= EF10_FILTER_SEARCH_LIMIT; depth++) {
878 unsigned int probe_index;
879 efx_filter_spec_t *probe_spec;
880
881 probe_index = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
882 probe_spec = ef10_filter_entry_spec(eftp, probe_index);
883
884 if (probe_spec == NULL) {
885 if (ins_index < 0)
886 ins_index = probe_index;
887 } else if (ef10_filter_equal(spec, probe_spec)) {
888 boolean_t found;
889
890 if (ef10_filter_entry_is_busy(eftp, probe_index)) {
891 EFSYS_UNLOCK(enp->en_eslp, state);
892 locked = B_FALSE;
893 goto retry;
894 }
895
896 rc = ef10_filter_add_lookup_equal_spec(spec,
897 probe_spec, policy, &found);
898 if (rc != 0)
899 goto fail1;
900
901 if (found != B_FALSE) {
902 ins_index = probe_index;
903 break;
904 }
905 }
906 }
907
908 /*
909 * Once we reach the maximum search depth, use the first suitable slot
910 * or return EBUSY if there was none.
911 */
912 if (ins_index < 0) {
913 rc = EBUSY;
914 goto fail2;
915 }
916
917 /*
918 * Mark software table entry busy. We might yet fail to insert,
919 * but any attempt to insert a conflicting filter while we're
920 * waiting for the firmware must find the busy entry.
921 */
922 ef10_filter_set_entry_busy(eftp, ins_index);
923
924 saved_spec = ef10_filter_entry_spec(eftp, ins_index);
925 ef10_filter_add_select_action(saved_spec, spec, &action,
926 &overridden_spec);
927
928 /*
929 * Allocate a new filter if found entry is empty or
930 * a filter should be overridden.
931 */
932 if (overridden_spec != NULL || saved_spec == NULL) {
933 efx_filter_spec_t *new_spec;
934
935 EFSYS_UNLOCK(enp->en_eslp, state);
936 locked = B_FALSE;
937
938 EFSYS_KMEM_ALLOC(enp->en_esip, sizeof (*new_spec), new_spec);
939 if (new_spec == NULL) {
940 rc = ENOMEM;
941 overridden_spec = NULL;
942 goto fail3;
943 }
944
945 EFSYS_LOCK(enp->en_eslp, state);
946 locked = B_TRUE;
947
948 if (saved_spec == NULL) {
949 *new_spec = *spec;
950 ef10_filter_set_entry(eftp, ins_index, new_spec);
951 } else {
952 *new_spec = *overridden_spec;
953 overridden_spec = new_spec;
954 }
955 }
956
957 EFSYS_UNLOCK(enp->en_eslp, state);
958 locked = B_FALSE;
959
960 rc = ef10_filter_add_execute_action(enp, saved_spec, spec,
961 overridden_spec, action, ins_index);
962 if (rc != 0)
963 goto fail4;
964
965 if (filter_id)
966 *filter_id = ins_index;
967
968 EFSYS_LOCK(enp->en_eslp, state);
969 ef10_filter_set_entry_not_busy(eftp, ins_index);
970 EFSYS_UNLOCK(enp->en_eslp, state);
971
972 return (0);
973
974 fail4:
975 EFSYS_PROBE(fail4);
976
977 EFSYS_ASSERT(locked == B_FALSE);
978 EFSYS_LOCK(enp->en_eslp, state);
979
980 if (action == EF10_FILTER_ADD_NEW) {
981 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec),
982 ef10_filter_entry_spec(eftp, ins_index));
983 ef10_filter_set_entry(eftp, ins_index, NULL);
984 }
985
986 EFSYS_UNLOCK(enp->en_eslp, state);
987
988 if (overridden_spec != NULL)
989 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), overridden_spec);
990
991 fail3:
992 EFSYS_PROBE(fail3);
993
994 EFSYS_ASSERT(locked == B_FALSE);
995 EFSYS_LOCK(enp->en_eslp, state);
996
997 ef10_filter_set_entry_not_busy(eftp, ins_index);
998
999 EFSYS_UNLOCK(enp->en_eslp, state);
1000
1001 fail2:
1002 EFSYS_PROBE(fail2);
1003
1004 fail1:
1005 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1006
1007 if (locked)
1008 EFSYS_UNLOCK(enp->en_eslp, state);
1009
1010 return (rc);
1011 }
1012
1013 __checkReturn efx_rc_t
ef10_filter_add(__in efx_nic_t * enp,__inout efx_filter_spec_t * spec,__in enum efx_filter_replacement_policy_e policy)1014 ef10_filter_add(
1015 __in efx_nic_t *enp,
1016 __inout efx_filter_spec_t *spec,
1017 __in enum efx_filter_replacement_policy_e policy)
1018 {
1019 efx_rc_t rc;
1020
1021 rc = ef10_filter_add_internal(enp, spec, policy, NULL);
1022 if (rc != 0)
1023 goto fail1;
1024
1025 return (0);
1026
1027 fail1:
1028 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1029
1030 return (rc);
1031 }
1032
1033 /*
1034 * Delete a filter by index from the filter table with priority
1035 * that is not higher than specified.
1036 */
1037 static __checkReturn efx_rc_t
ef10_filter_delete_internal(__in efx_nic_t * enp,__in uint32_t filter_id,__in efx_filter_priority_t priority)1038 ef10_filter_delete_internal(
1039 __in efx_nic_t *enp,
1040 __in uint32_t filter_id,
1041 __in efx_filter_priority_t priority)
1042 {
1043 efx_rc_t rc;
1044 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1045 efx_filter_spec_t *spec;
1046 efsys_lock_state_t state;
1047 uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS;
1048
1049 /*
1050 * Find the software table entry and mark it busy. Don't
1051 * remove it yet; any attempt to update while we're waiting
1052 * for the firmware must find the busy entry.
1053 *
1054 * FIXME: What if the busy flag is never cleared?
1055 */
1056 EFSYS_LOCK(enp->en_eslp, state);
1057 while (ef10_filter_entry_is_busy(table, filter_idx)) {
1058 EFSYS_UNLOCK(enp->en_eslp, state);
1059 EFSYS_SPIN(1);
1060 EFSYS_LOCK(enp->en_eslp, state);
1061 }
1062 if ((spec = ef10_filter_entry_spec(table, filter_idx)) != NULL) {
1063 if (spec->efs_priority <= priority)
1064 ef10_filter_set_entry_busy(table, filter_idx);
1065 }
1066 EFSYS_UNLOCK(enp->en_eslp, state);
1067
1068 if (spec == NULL) {
1069 rc = ENOENT;
1070 goto fail1;
1071 }
1072
1073 if (spec->efs_priority > priority) {
1074 /*
1075 * Applied filter stays, but overridden filter is removed since
1076 * next user request to delete the applied filter should not
1077 * restore outdated filter.
1078 */
1079 if (spec->efs_overridden_spec != NULL) {
1080 EFSYS_ASSERT(spec->efs_overridden_spec->efs_overridden_spec ==
1081 NULL);
1082 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec),
1083 spec->efs_overridden_spec);
1084 spec->efs_overridden_spec = NULL;
1085 }
1086 } else {
1087 /*
1088 * Try to remove the hardware filter or replace it with the
1089 * saved automatic filter. This may fail if the MC has
1090 * rebooted (which frees all hardware filter resources).
1091 */
1092 if (spec->efs_overridden_spec != NULL) {
1093 rc = efx_mcdi_filter_op_add(enp,
1094 spec->efs_overridden_spec,
1095 MC_CMD_FILTER_OP_IN_OP_REPLACE,
1096 &table->eft_entry[filter_idx].efe_handle);
1097 } else if (ef10_filter_is_exclusive(spec)) {
1098 rc = efx_mcdi_filter_op_delete(enp,
1099 MC_CMD_FILTER_OP_IN_OP_REMOVE,
1100 &table->eft_entry[filter_idx].efe_handle);
1101 } else {
1102 rc = efx_mcdi_filter_op_delete(enp,
1103 MC_CMD_FILTER_OP_IN_OP_UNSUBSCRIBE,
1104 &table->eft_entry[filter_idx].efe_handle);
1105 }
1106
1107 /* Free the software table entry */
1108 EFSYS_LOCK(enp->en_eslp, state);
1109 ef10_filter_set_entry_not_busy(table, filter_idx);
1110 ef10_filter_set_entry(table, filter_idx,
1111 spec->efs_overridden_spec);
1112 EFSYS_UNLOCK(enp->en_eslp, state);
1113
1114 EFSYS_KMEM_FREE(enp->en_esip, sizeof (*spec), spec);
1115
1116 /* Check result of hardware filter removal */
1117 if (rc != 0)
1118 goto fail2;
1119 }
1120
1121 return (0);
1122
1123 fail2:
1124 EFSYS_PROBE(fail2);
1125
1126 fail1:
1127 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1128
1129 return (rc);
1130 }
1131
1132 static void
ef10_filter_delete_auto(__in efx_nic_t * enp,__in uint32_t filter_id)1133 ef10_filter_delete_auto(
1134 __in efx_nic_t *enp,
1135 __in uint32_t filter_id)
1136 {
1137 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1138 uint32_t filter_idx = filter_id % EFX_EF10_FILTER_TBL_ROWS;
1139
1140 /*
1141 * AUTO_OLD flag is cleared since the auto filter that is to be removed
1142 * may not be the filter at the specified index itself, but the filter
1143 * that is overridden by it.
1144 */
1145 ef10_filter_set_entry_not_auto_old(table, filter_idx);
1146
1147 (void) ef10_filter_delete_internal(enp, filter_idx,
1148 EFX_FILTER_PRI_AUTO);
1149 }
1150
1151 __checkReturn efx_rc_t
ef10_filter_delete(__in efx_nic_t * enp,__inout efx_filter_spec_t * spec)1152 ef10_filter_delete(
1153 __in efx_nic_t *enp,
1154 __inout efx_filter_spec_t *spec)
1155 {
1156 efx_rc_t rc;
1157 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1158 efx_filter_spec_t *saved_spec;
1159 unsigned int hash;
1160 unsigned int depth;
1161 unsigned int i;
1162 efsys_lock_state_t state;
1163 boolean_t locked = B_FALSE;
1164
1165 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
1166
1167 hash = ef10_filter_hash(spec);
1168
1169 EFSYS_LOCK(enp->en_eslp, state);
1170 locked = B_TRUE;
1171
1172 depth = 1;
1173 for (;;) {
1174 i = (hash + depth) & (EFX_EF10_FILTER_TBL_ROWS - 1);
1175 saved_spec = ef10_filter_entry_spec(table, i);
1176 if (saved_spec && ef10_filter_equal(spec, saved_spec) &&
1177 ef10_filter_same_dest(spec, saved_spec) &&
1178 saved_spec->efs_priority == EFX_FILTER_PRI_MANUAL) {
1179 break;
1180 }
1181 if (depth == EF10_FILTER_SEARCH_LIMIT) {
1182 rc = ENOENT;
1183 goto fail1;
1184 }
1185 depth++;
1186 }
1187
1188 EFSYS_UNLOCK(enp->en_eslp, state);
1189 locked = B_FALSE;
1190
1191 rc = ef10_filter_delete_internal(enp, i, EFX_FILTER_PRI_MANUAL);
1192 if (rc != 0)
1193 goto fail2;
1194
1195 return (0);
1196
1197 fail2:
1198 EFSYS_PROBE(fail2);
1199
1200 fail1:
1201 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1202
1203 if (locked)
1204 EFSYS_UNLOCK(enp->en_eslp, state);
1205
1206 return (rc);
1207 }
1208
1209 static __checkReturn efx_rc_t
efx_mcdi_get_parser_disp_info(__in efx_nic_t * enp,__out_ecount (buffer_length)uint32_t * buffer,__in size_t buffer_length,__in boolean_t encap,__out size_t * list_lengthp)1210 efx_mcdi_get_parser_disp_info(
1211 __in efx_nic_t *enp,
1212 __out_ecount(buffer_length) uint32_t *buffer,
1213 __in size_t buffer_length,
1214 __in boolean_t encap,
1215 __out size_t *list_lengthp)
1216 {
1217 efx_mcdi_req_t req;
1218 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PARSER_DISP_INFO_IN_LEN,
1219 MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX);
1220 size_t matches_count;
1221 size_t list_size;
1222 efx_rc_t rc;
1223
1224 req.emr_cmd = MC_CMD_GET_PARSER_DISP_INFO;
1225 req.emr_in_buf = payload;
1226 req.emr_in_length = MC_CMD_GET_PARSER_DISP_INFO_IN_LEN;
1227 req.emr_out_buf = payload;
1228 req.emr_out_length = MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMAX;
1229
1230 MCDI_IN_SET_DWORD(req, GET_PARSER_DISP_INFO_OUT_OP, encap ?
1231 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_ENCAP_RX_MATCHES :
1232 MC_CMD_GET_PARSER_DISP_INFO_IN_OP_GET_SUPPORTED_RX_MATCHES);
1233
1234 efx_mcdi_execute(enp, &req);
1235
1236 if (req.emr_rc != 0) {
1237 rc = req.emr_rc;
1238 goto fail1;
1239 }
1240
1241 if (req.emr_out_length_used < MC_CMD_GET_PARSER_DISP_INFO_OUT_LENMIN) {
1242 rc = EMSGSIZE;
1243 goto fail2;
1244 }
1245
1246 matches_count = MCDI_OUT_DWORD(req,
1247 GET_PARSER_DISP_INFO_OUT_NUM_SUPPORTED_MATCHES);
1248
1249 if (req.emr_out_length_used <
1250 MC_CMD_GET_PARSER_DISP_INFO_OUT_LEN(matches_count)) {
1251 rc = EMSGSIZE;
1252 goto fail3;
1253 }
1254
1255 *list_lengthp = matches_count;
1256
1257 if (buffer_length < matches_count) {
1258 rc = ENOSPC;
1259 goto fail4;
1260 }
1261
1262 /*
1263 * Check that the elements in the list in the MCDI response are the size
1264 * we expect, so we can just copy them directly. Any conversion of the
1265 * flags is handled by the caller.
1266 */
1267 EFX_STATIC_ASSERT(sizeof (uint32_t) ==
1268 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN);
1269
1270 list_size = matches_count *
1271 MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_LEN;
1272 memcpy(buffer,
1273 MCDI_OUT2(req, uint32_t,
1274 GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES),
1275 list_size);
1276
1277 return (0);
1278
1279 fail4:
1280 EFSYS_PROBE(fail4);
1281 fail3:
1282 EFSYS_PROBE(fail3);
1283 fail2:
1284 EFSYS_PROBE(fail2);
1285 fail1:
1286 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1287
1288 return (rc);
1289 }
1290
1291 __checkReturn efx_rc_t
ef10_filter_supported_filters(__in efx_nic_t * enp,__out_ecount (buffer_length)uint32_t * buffer,__in size_t buffer_length,__out size_t * list_lengthp)1292 ef10_filter_supported_filters(
1293 __in efx_nic_t *enp,
1294 __out_ecount(buffer_length) uint32_t *buffer,
1295 __in size_t buffer_length,
1296 __out size_t *list_lengthp)
1297 {
1298 efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
1299 size_t mcdi_list_length;
1300 size_t mcdi_encap_list_length;
1301 size_t list_length;
1302 uint32_t i;
1303 uint32_t next_buf_idx;
1304 size_t next_buf_length;
1305 efx_rc_t rc;
1306 boolean_t no_space = B_FALSE;
1307 efx_filter_match_flags_t all_filter_flags =
1308 (EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_LOC_HOST |
1309 EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_REM_PORT |
1310 EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_PORT |
1311 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_INNER_VID |
1312 EFX_FILTER_MATCH_OUTER_VID | EFX_FILTER_MATCH_IP_PROTO |
1313 EFX_FILTER_MATCH_VNI_OR_VSID |
1314 EFX_FILTER_MATCH_IFRM_LOC_MAC |
1315 EFX_FILTER_MATCH_IFRM_UNKNOWN_MCAST_DST |
1316 EFX_FILTER_MATCH_IFRM_UNKNOWN_UCAST_DST |
1317 EFX_FILTER_MATCH_ENCAP_TYPE |
1318 EFX_FILTER_MATCH_UNKNOWN_MCAST_DST |
1319 EFX_FILTER_MATCH_UNKNOWN_UCAST_DST);
1320
1321 /*
1322 * Two calls to MC_CMD_GET_PARSER_DISP_INFO are needed: one to get the
1323 * list of supported filters for ordinary packets, and then another to
1324 * get the list of supported filters for encapsulated packets. To
1325 * distinguish the second list from the first, the
1326 * EFX_FILTER_MATCH_ENCAP_TYPE flag is added to each filter for
1327 * encapsulated packets.
1328 */
1329 rc = efx_mcdi_get_parser_disp_info(enp, buffer, buffer_length, B_FALSE,
1330 &mcdi_list_length);
1331 if (rc != 0) {
1332 if (rc == ENOSPC)
1333 no_space = B_TRUE;
1334 else
1335 goto fail1;
1336 }
1337
1338 if (no_space) {
1339 next_buf_idx = 0;
1340 next_buf_length = 0;
1341 } else {
1342 EFSYS_ASSERT(mcdi_list_length <= buffer_length);
1343 next_buf_idx = mcdi_list_length;
1344 next_buf_length = buffer_length - mcdi_list_length;
1345 }
1346
1347 if (encp->enc_tunnel_encapsulations_supported != 0) {
1348 rc = efx_mcdi_get_parser_disp_info(enp, &buffer[next_buf_idx],
1349 next_buf_length, B_TRUE, &mcdi_encap_list_length);
1350 if (rc != 0) {
1351 if (rc == ENOSPC) {
1352 no_space = B_TRUE;
1353 } else if (rc == EINVAL) {
1354 /*
1355 * Do not fail if the MCDI do not recognize the
1356 * query for encapsulated packet filters.
1357 */
1358 mcdi_encap_list_length = 0;
1359 } else
1360 goto fail2;
1361 } else {
1362 for (i = next_buf_idx;
1363 i < next_buf_idx + mcdi_encap_list_length; i++)
1364 buffer[i] |= EFX_FILTER_MATCH_ENCAP_TYPE;
1365 }
1366 } else {
1367 mcdi_encap_list_length = 0;
1368 }
1369
1370 if (no_space) {
1371 *list_lengthp = mcdi_list_length + mcdi_encap_list_length;
1372 rc = ENOSPC;
1373 goto fail3;
1374 }
1375
1376 /*
1377 * The static assertions in ef10_filter_init() ensure that the values of
1378 * the EFX_FILTER_MATCH flags match those used by MCDI, so they don't
1379 * need to be converted.
1380 *
1381 * In case support is added to MCDI for additional flags, remove any
1382 * matches from the list which include flags we don't support. The order
1383 * of the matches is preserved as they are ordered from highest to
1384 * lowest priority.
1385 */
1386 EFSYS_ASSERT(mcdi_list_length + mcdi_encap_list_length <=
1387 buffer_length);
1388 list_length = 0;
1389 for (i = 0; i < mcdi_list_length + mcdi_encap_list_length; i++) {
1390 if ((buffer[i] & ~all_filter_flags) == 0) {
1391 buffer[list_length] = buffer[i];
1392 list_length++;
1393 }
1394 }
1395
1396 *list_lengthp = list_length;
1397
1398 return (0);
1399
1400 fail3:
1401 EFSYS_PROBE(fail3);
1402 fail2:
1403 EFSYS_PROBE(fail2);
1404 fail1:
1405 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1406
1407 return (rc);
1408 }
1409
1410 static __checkReturn efx_rc_t
1411 ef10_filter_insert_unicast(
1412 __in efx_nic_t *enp,
1413 __in_ecount(6) uint8_t const *addr,
1414 __in efx_filter_flags_t filter_flags)
1415 {
1416 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
1417 efx_filter_spec_t spec;
1418 efx_rc_t rc;
1419
1420 /* Insert the filter for the local station address */
1421 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
1422 filter_flags,
1423 eftp->eft_default_rxq);
1424 rc = efx_filter_spec_set_eth_local(&spec, EFX_FILTER_SPEC_VID_UNSPEC,
1425 addr);
1426 if (rc != 0)
1427 goto fail1;
1428
1429 rc = ef10_filter_add_internal(enp, &spec, EFX_FILTER_REPLACEMENT_NEVER,
1430 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]);
1431 if (rc != 0)
1432 goto fail2;
1433
1434 eftp->eft_unicst_filter_count++;
1435 EFSYS_ASSERT(eftp->eft_unicst_filter_count <=
1436 EFX_EF10_FILTER_UNICAST_FILTERS_MAX);
1437
1438 return (0);
1439
1440 fail2:
1441 EFSYS_PROBE(fail2);
1442 fail1:
1443 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1444 return (rc);
1445 }
1446
1447 static __checkReturn efx_rc_t
ef10_filter_insert_all_unicast(__in efx_nic_t * enp,__in efx_filter_flags_t filter_flags)1448 ef10_filter_insert_all_unicast(
1449 __in efx_nic_t *enp,
1450 __in efx_filter_flags_t filter_flags)
1451 {
1452 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
1453 efx_filter_spec_t spec;
1454 efx_rc_t rc;
1455
1456 /* Insert the unknown unicast filter */
1457 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
1458 filter_flags,
1459 eftp->eft_default_rxq);
1460 rc = efx_filter_spec_set_uc_def(&spec);
1461 if (rc != 0)
1462 goto fail1;
1463 rc = ef10_filter_add_internal(enp, &spec, EFX_FILTER_REPLACEMENT_NEVER,
1464 &eftp->eft_unicst_filter_indexes[eftp->eft_unicst_filter_count]);
1465 if (rc != 0)
1466 goto fail2;
1467
1468 eftp->eft_unicst_filter_count++;
1469 EFSYS_ASSERT(eftp->eft_unicst_filter_count <=
1470 EFX_EF10_FILTER_UNICAST_FILTERS_MAX);
1471
1472 return (0);
1473
1474 fail2:
1475 EFSYS_PROBE(fail2);
1476 fail1:
1477 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1478 return (rc);
1479 }
1480
1481 static __checkReturn efx_rc_t
1482 ef10_filter_insert_multicast_list(
1483 __in efx_nic_t *enp,
1484 __in boolean_t mulcst,
1485 __in boolean_t brdcst,
1486 __in_ecount(6*count) uint8_t const *addrs,
1487 __in uint32_t count,
1488 __in efx_filter_flags_t filter_flags,
1489 __in boolean_t rollback)
1490 {
1491 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
1492 efx_filter_spec_t spec;
1493 uint8_t addr[6];
1494 uint32_t i;
1495 uint32_t filter_index;
1496 uint32_t filter_count;
1497 efx_rc_t rc;
1498
1499 if (mulcst == B_FALSE)
1500 count = 0;
1501
1502 if (count + (brdcst ? 1 : 0) >
1503 EFX_ARRAY_SIZE(eftp->eft_mulcst_filter_indexes)) {
1504 /* Too many MAC addresses */
1505 rc = EINVAL;
1506 goto fail1;
1507 }
1508
1509 /* Insert/renew multicast address list filters */
1510 filter_count = 0;
1511 for (i = 0; i < count; i++) {
1512 efx_filter_spec_init_rx(&spec,
1513 EFX_FILTER_PRI_AUTO,
1514 filter_flags,
1515 eftp->eft_default_rxq);
1516
1517 rc = efx_filter_spec_set_eth_local(&spec,
1518 EFX_FILTER_SPEC_VID_UNSPEC,
1519 &addrs[i * EFX_MAC_ADDR_LEN]);
1520 if (rc != 0) {
1521 if (rollback == B_TRUE) {
1522 /* Only stop upon failure if told to rollback */
1523 goto rollback;
1524 } else {
1525 /*
1526 * Don't try to add a filter with a corrupt
1527 * specification.
1528 */
1529 continue;
1530 }
1531 }
1532
1533 rc = ef10_filter_add_internal(enp, &spec,
1534 EFX_FILTER_REPLACEMENT_NEVER, &filter_index);
1535
1536 if (rc == 0) {
1537 eftp->eft_mulcst_filter_indexes[filter_count] =
1538 filter_index;
1539 filter_count++;
1540 } else if (rollback == B_TRUE) {
1541 /* Only stop upon failure if told to rollback */
1542 goto rollback;
1543 }
1544
1545 }
1546
1547 if (brdcst == B_TRUE) {
1548 /* Insert/renew broadcast address filter */
1549 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
1550 filter_flags,
1551 eftp->eft_default_rxq);
1552
1553 EFX_MAC_BROADCAST_ADDR_SET(addr);
1554 rc = efx_filter_spec_set_eth_local(&spec,
1555 EFX_FILTER_SPEC_VID_UNSPEC, addr);
1556 if ((rc != 0) && (rollback == B_TRUE)) {
1557 /* Only stop upon failure if told to rollback */
1558 goto rollback;
1559 }
1560
1561 rc = ef10_filter_add_internal(enp, &spec,
1562 EFX_FILTER_REPLACEMENT_NEVER, &filter_index);
1563
1564 if (rc == 0) {
1565 eftp->eft_mulcst_filter_indexes[filter_count] =
1566 filter_index;
1567 filter_count++;
1568 } else if (rollback == B_TRUE) {
1569 /* Only stop upon failure if told to rollback */
1570 goto rollback;
1571 }
1572 }
1573
1574 eftp->eft_mulcst_filter_count = filter_count;
1575 eftp->eft_using_all_mulcst = B_FALSE;
1576
1577 return (0);
1578
1579 rollback:
1580 /* Remove any filters we have inserted */
1581 i = filter_count;
1582 while (i--) {
1583 ef10_filter_delete_auto(enp,
1584 eftp->eft_mulcst_filter_indexes[i]);
1585 }
1586 eftp->eft_mulcst_filter_count = 0;
1587
1588 fail1:
1589 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1590
1591 return (rc);
1592 }
1593
1594 static __checkReturn efx_rc_t
ef10_filter_insert_all_multicast(__in efx_nic_t * enp,__in efx_filter_flags_t filter_flags)1595 ef10_filter_insert_all_multicast(
1596 __in efx_nic_t *enp,
1597 __in efx_filter_flags_t filter_flags)
1598 {
1599 ef10_filter_table_t *eftp = enp->en_filter.ef_ef10_filter_table;
1600 efx_filter_spec_t spec;
1601 efx_rc_t rc;
1602
1603 /* Insert the unknown multicast filter */
1604 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
1605 filter_flags,
1606 eftp->eft_default_rxq);
1607 rc = efx_filter_spec_set_mc_def(&spec);
1608 if (rc != 0)
1609 goto fail1;
1610
1611 rc = ef10_filter_add_internal(enp, &spec, EFX_FILTER_REPLACEMENT_NEVER,
1612 &eftp->eft_mulcst_filter_indexes[0]);
1613 if (rc != 0)
1614 goto fail2;
1615
1616 eftp->eft_mulcst_filter_count = 1;
1617 eftp->eft_using_all_mulcst = B_TRUE;
1618
1619 /*
1620 * FIXME: If brdcst == B_FALSE, add a filter to drop broadcast traffic.
1621 */
1622
1623 return (0);
1624
1625 fail2:
1626 EFSYS_PROBE(fail2);
1627 fail1:
1628 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1629
1630 return (rc);
1631 }
1632
1633 typedef struct ef10_filter_encap_entry_s {
1634 uint16_t ether_type;
1635 efx_tunnel_protocol_t encap_type;
1636 uint32_t inner_frame_match;
1637 } ef10_filter_encap_entry_t;
1638
1639 #define EF10_ENCAP_FILTER_ENTRY(ipv, encap_type, inner_frame_match) \
1640 { EFX_ETHER_TYPE_##ipv, EFX_TUNNEL_PROTOCOL_##encap_type, \
1641 EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_##inner_frame_match }
1642
1643 static ef10_filter_encap_entry_t ef10_filter_encap_list[] = {
1644 EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, UCAST_DST),
1645 EF10_ENCAP_FILTER_ENTRY(IPV4, VXLAN, MCAST_DST),
1646 EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, UCAST_DST),
1647 EF10_ENCAP_FILTER_ENTRY(IPV6, VXLAN, MCAST_DST),
1648
1649 EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, UCAST_DST),
1650 EF10_ENCAP_FILTER_ENTRY(IPV4, GENEVE, MCAST_DST),
1651 EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, UCAST_DST),
1652 EF10_ENCAP_FILTER_ENTRY(IPV6, GENEVE, MCAST_DST),
1653
1654 EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, UCAST_DST),
1655 EF10_ENCAP_FILTER_ENTRY(IPV4, NVGRE, MCAST_DST),
1656 EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, UCAST_DST),
1657 EF10_ENCAP_FILTER_ENTRY(IPV6, NVGRE, MCAST_DST),
1658 };
1659
1660 #undef EF10_ENCAP_FILTER_ENTRY
1661
1662 static __checkReturn efx_rc_t
ef10_filter_insert_encap_filters(__in efx_nic_t * enp,__in boolean_t mulcst,__in efx_filter_flags_t filter_flags)1663 ef10_filter_insert_encap_filters(
1664 __in efx_nic_t *enp,
1665 __in boolean_t mulcst,
1666 __in efx_filter_flags_t filter_flags)
1667 {
1668 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1669 uint32_t i;
1670 efx_rc_t rc;
1671
1672 EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(ef10_filter_encap_list) <=
1673 EFX_ARRAY_SIZE(table->eft_encap_filter_indexes));
1674
1675 /*
1676 * On Medford, full-featured firmware can identify packets as being
1677 * tunnel encapsulated, even if no encapsulated packet offloads are in
1678 * use. When packets are identified as such, ordinary filters are not
1679 * applied, only ones specific to encapsulated packets. Hence we need to
1680 * insert filters for encapsulated packets in order to receive them.
1681 *
1682 * Separate filters need to be inserted for each ether type,
1683 * encapsulation type, and inner frame type (unicast or multicast). To
1684 * keep things simple and reduce the number of filters needed, catch-all
1685 * filters for all combinations of types are inserted, even if
1686 * all_unicst or all_mulcst have not been set. (These catch-all filters
1687 * may well, however, fail to insert on unprivileged functions.)
1688 */
1689 table->eft_encap_filter_count = 0;
1690 for (i = 0; i < EFX_ARRAY_SIZE(ef10_filter_encap_list); i++) {
1691 efx_filter_spec_t spec;
1692 ef10_filter_encap_entry_t *encap_filter =
1693 &ef10_filter_encap_list[i];
1694
1695 /*
1696 * Skip multicast filters if we've not been asked for
1697 * any multicast traffic.
1698 */
1699 if ((mulcst == B_FALSE) &&
1700 (encap_filter->inner_frame_match ==
1701 EFX_FILTER_INNER_FRAME_MATCH_UNKNOWN_MCAST_DST))
1702 continue;
1703
1704 efx_filter_spec_init_rx(&spec, EFX_FILTER_PRI_AUTO,
1705 filter_flags,
1706 table->eft_default_rxq);
1707 efx_filter_spec_set_ether_type(&spec, encap_filter->ether_type);
1708 rc = efx_filter_spec_set_encap_type(&spec,
1709 encap_filter->encap_type,
1710 encap_filter->inner_frame_match);
1711 if (rc != 0)
1712 goto fail1;
1713
1714 rc = ef10_filter_add_internal(enp, &spec,
1715 EFX_FILTER_REPLACEMENT_NEVER,
1716 &table->eft_encap_filter_indexes[
1717 table->eft_encap_filter_count]);
1718 if (rc != 0) {
1719 if (rc != EACCES)
1720 goto fail2;
1721 } else {
1722 table->eft_encap_filter_count++;
1723 }
1724 }
1725
1726 return (0);
1727
1728 fail2:
1729 EFSYS_PROBE(fail2);
1730 fail1:
1731 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1732
1733 return (rc);
1734 }
1735
1736 static void
ef10_filter_remove_old(__in efx_nic_t * enp)1737 ef10_filter_remove_old(
1738 __in efx_nic_t *enp)
1739 {
1740 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1741 uint32_t i;
1742
1743 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) {
1744 if (ef10_filter_entry_is_auto_old(table, i)) {
1745 ef10_filter_delete_auto(enp, i);
1746 }
1747 }
1748 }
1749
1750
1751 static __checkReturn efx_rc_t
ef10_filter_get_workarounds(__in efx_nic_t * enp)1752 ef10_filter_get_workarounds(
1753 __in efx_nic_t *enp)
1754 {
1755 efx_nic_cfg_t *encp = &enp->en_nic_cfg;
1756 uint32_t implemented = 0;
1757 uint32_t enabled = 0;
1758 efx_rc_t rc;
1759
1760 rc = efx_mcdi_get_workarounds(enp, &implemented, &enabled);
1761 if (rc == 0) {
1762 /* Check if chained multicast filter support is enabled */
1763 if (implemented & enabled & MC_CMD_GET_WORKAROUNDS_OUT_BUG26807)
1764 encp->enc_bug26807_workaround = B_TRUE;
1765 else
1766 encp->enc_bug26807_workaround = B_FALSE;
1767 } else if (rc == ENOTSUP) {
1768 /*
1769 * Firmware is too old to support GET_WORKAROUNDS, and support
1770 * for this workaround was implemented later.
1771 */
1772 encp->enc_bug26807_workaround = B_FALSE;
1773 } else {
1774 goto fail1;
1775 }
1776
1777 return (0);
1778
1779 fail1:
1780 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1781
1782 return (rc);
1783
1784 }
1785
1786 static void
ef10_filter_remove_all_existing_filters(__in efx_nic_t * enp)1787 ef10_filter_remove_all_existing_filters(
1788 __in efx_nic_t *enp)
1789 {
1790 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1791 efx_port_t *epp = &(enp->en_port);
1792 unsigned int i;
1793
1794 for (i = 0; i < table->eft_unicst_filter_count; i++) {
1795 ef10_filter_delete_auto(enp,
1796 table->eft_unicst_filter_indexes[i]);
1797 }
1798 table->eft_unicst_filter_count = 0;
1799
1800 for (i = 0; i < table->eft_mulcst_filter_count; i++) {
1801 ef10_filter_delete_auto(enp,
1802 table->eft_mulcst_filter_indexes[i]);
1803 }
1804 table->eft_mulcst_filter_count = 0;
1805
1806 for (i = 0; i < table->eft_encap_filter_count; i++) {
1807 ef10_filter_delete_auto(enp,
1808 table->eft_encap_filter_indexes[i]);
1809 }
1810 table->eft_encap_filter_count = 0;
1811
1812 epp->ep_all_unicst_inserted = B_FALSE;
1813 epp->ep_all_mulcst_inserted = B_FALSE;
1814 }
1815
1816 static void
ef10_filter_mark_old_filters(__in efx_nic_t * enp)1817 ef10_filter_mark_old_filters(
1818 __in efx_nic_t *enp)
1819 {
1820 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1821 unsigned int i;
1822
1823 for (i = 0; i < table->eft_unicst_filter_count; i++) {
1824 ef10_filter_set_entry_auto_old(table,
1825 table->eft_unicst_filter_indexes[i]);
1826 }
1827 for (i = 0; i < table->eft_mulcst_filter_count; i++) {
1828 ef10_filter_set_entry_auto_old(table,
1829 table->eft_mulcst_filter_indexes[i]);
1830 }
1831 for (i = 0; i < table->eft_encap_filter_count; i++) {
1832 ef10_filter_set_entry_auto_old(table,
1833 table->eft_encap_filter_indexes[i]);
1834 }
1835 }
1836
1837 static __checkReturn efx_rc_t
1838 ef10_filter_insert_renew_unicst_filters(
1839 __in efx_nic_t *enp,
1840 __in_ecount(6) uint8_t const *mac_addr,
1841 __in boolean_t all_unicst,
1842 __in efx_filter_flags_t filter_flags,
1843 __out boolean_t *all_unicst_inserted)
1844 {
1845 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1846 efx_port_t *epp = &(enp->en_port);
1847 efx_rc_t rc;
1848
1849 /*
1850 * Firmware does not perform chaining on unicast filters. As traffic is
1851 * therefore only delivered to the first matching filter, we should
1852 * always insert the specific filter for our MAC address, to try and
1853 * ensure we get that traffic.
1854 *
1855 * (If the filter for our MAC address has already been inserted by
1856 * another function, we won't receive traffic sent to us, even if we
1857 * insert a unicast mismatch filter. To prevent traffic stealing, this
1858 * therefore relies on the privilege model only allowing functions to
1859 * insert filters for their own MAC address unless explicitly given
1860 * additional privileges by the user. This also means that, even on a
1861 * privileged function, inserting a unicast mismatch filter may not
1862 * catch all traffic in multi PCI function scenarios.)
1863 */
1864 table->eft_unicst_filter_count = 0;
1865 rc = ef10_filter_insert_unicast(enp, mac_addr, filter_flags);
1866 *all_unicst_inserted = B_FALSE;
1867 if (all_unicst || (rc != 0)) {
1868 efx_rc_t all_unicst_rc;
1869
1870 all_unicst_rc = ef10_filter_insert_all_unicast(enp,
1871 filter_flags);
1872 if (all_unicst_rc == 0) {
1873 *all_unicst_inserted = B_TRUE;
1874 epp->ep_all_unicst_inserted = B_TRUE;
1875 } else if (rc != 0)
1876 goto fail1;
1877 }
1878
1879 return (0);
1880
1881 fail1:
1882 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1883
1884 return (rc);
1885 }
1886
1887 static __checkReturn efx_rc_t
1888 ef10_filter_insert_renew_mulcst_filters(
1889 __in efx_nic_t *enp,
1890 __in boolean_t mulcst,
1891 __in boolean_t all_mulcst,
1892 __in boolean_t brdcst,
1893 __in_ecount(6*count) uint8_t const *addrs,
1894 __in uint32_t count,
1895 __in efx_filter_flags_t filter_flags,
1896 __in boolean_t all_unicst_inserted,
1897 __out boolean_t *all_mulcst_inserted)
1898 {
1899 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1900 efx_nic_cfg_t *encp = &enp->en_nic_cfg;
1901 efx_port_t *epp = &(enp->en_port);
1902 efx_rc_t rc;
1903
1904 *all_mulcst_inserted = B_FALSE;
1905
1906 if (all_mulcst == B_TRUE) {
1907 efx_rc_t all_mulcst_rc;
1908
1909 /*
1910 * Insert the all multicast filter. If that fails, try to insert
1911 * all of our multicast filters (but without rollback on
1912 * failure).
1913 */
1914 all_mulcst_rc = ef10_filter_insert_all_multicast(enp,
1915 filter_flags);
1916 if (all_mulcst_rc == 0) {
1917 epp->ep_all_mulcst_inserted = B_TRUE;
1918 *all_mulcst_inserted = B_TRUE;
1919 } else {
1920 rc = ef10_filter_insert_multicast_list(enp, B_TRUE,
1921 brdcst, addrs, count, filter_flags, B_FALSE);
1922 if (rc != 0)
1923 goto fail1;
1924 }
1925 } else {
1926 /*
1927 * Insert filters for multicast addresses.
1928 * If any insertion fails, then rollback and try to insert the
1929 * all multicast filter instead.
1930 * If that also fails, try to insert all of the multicast
1931 * filters (but without rollback on failure).
1932 */
1933 rc = ef10_filter_insert_multicast_list(enp, mulcst, brdcst,
1934 addrs, count, filter_flags, B_TRUE);
1935 if (rc != 0) {
1936 if ((table->eft_using_all_mulcst == B_FALSE) &&
1937 (encp->enc_bug26807_workaround == B_TRUE)) {
1938 /*
1939 * Multicast filter chaining is on, so remove
1940 * old filters before inserting the multicast
1941 * all filter to avoid duplicate delivery caused
1942 * by packets matching multiple filters.
1943 */
1944 ef10_filter_remove_old(enp);
1945 if (all_unicst_inserted == B_FALSE)
1946 epp->ep_all_unicst_inserted = B_FALSE;
1947 if (*all_mulcst_inserted == B_FALSE)
1948 epp->ep_all_mulcst_inserted = B_FALSE;
1949 }
1950
1951 rc = ef10_filter_insert_all_multicast(enp,
1952 filter_flags);
1953 if (rc == 0) {
1954 epp->ep_all_mulcst_inserted = B_TRUE;
1955 *all_mulcst_inserted = B_TRUE;
1956 } else {
1957 rc = ef10_filter_insert_multicast_list(enp,
1958 mulcst, brdcst,
1959 addrs, count, filter_flags, B_FALSE);
1960 if (rc != 0)
1961 goto fail2;
1962 }
1963 }
1964 }
1965
1966 return (0);
1967
1968 fail2:
1969 EFSYS_PROBE1(fail2, efx_rc_t, rc);
1970
1971 fail1:
1972 EFSYS_PROBE1(fail1, efx_rc_t, rc);
1973
1974 return (rc);
1975 }
1976
1977 /*
1978 * Reconfigure all filters.
1979 * If all_unicst and/or all mulcst filters cannot be applied then
1980 * return ENOTSUP (Note the filters for the specified addresses are
1981 * still applied in this case).
1982 */
1983 __checkReturn efx_rc_t
1984 ef10_filter_reconfigure(
1985 __in efx_nic_t *enp,
1986 __in_ecount(6) uint8_t const *mac_addr,
1987 __in boolean_t all_unicst,
1988 __in boolean_t mulcst,
1989 __in boolean_t all_mulcst,
1990 __in boolean_t brdcst,
1991 __in_ecount(6*count) uint8_t const *addrs,
1992 __in uint32_t count)
1993 {
1994 efx_nic_cfg_t *encp = &enp->en_nic_cfg;
1995 efx_port_t *epp = &(enp->en_port);
1996 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
1997 efx_filter_flags_t filter_flags;
1998 unsigned int i;
1999 boolean_t all_unicst_inserted = B_FALSE;
2000 boolean_t all_mulcst_inserted = B_FALSE;
2001 efx_rc_t rc;
2002
2003 if (table->eft_default_rxq == NULL) {
2004 /*
2005 * Filters direct traffic to the default RXQ, and so cannot be
2006 * inserted until it is available. Any currently configured
2007 * filters must be removed (ignore errors in case the MC
2008 * has rebooted, which removes hardware filters).
2009 */
2010 ef10_filter_remove_all_existing_filters(enp);
2011 return (0);
2012 }
2013
2014 if (table->eft_using_rss)
2015 filter_flags = EFX_FILTER_FLAG_RX_RSS;
2016 else
2017 filter_flags = 0;
2018
2019 /* Mark old filters which may need to be removed */
2020 ef10_filter_mark_old_filters(enp);
2021
2022 /* Insert or renew unicast filters */
2023 rc = ef10_filter_insert_renew_unicst_filters(enp, mac_addr, all_unicst,
2024 filter_flags,
2025 &all_unicst_inserted);
2026 if (rc != 0)
2027 goto fail1;
2028
2029 /*
2030 * WORKAROUND_BUG26807 controls firmware support for chained multicast
2031 * filters, and can only be enabled or disabled when the hardware filter
2032 * table is empty.
2033 *
2034 * Chained multicast filters require support from the datapath firmware,
2035 * and may not be available (e.g. low-latency variants or old Huntington
2036 * firmware).
2037 *
2038 * Firmware will reset (FLR) functions which have inserted filters in
2039 * the hardware filter table when the workaround is enabled/disabled.
2040 * Functions without any hardware filters are not reset.
2041 *
2042 * Re-check if the workaround is enabled after adding unicast hardware
2043 * filters. This ensures that encp->enc_bug26807_workaround matches the
2044 * firmware state, and that later changes to enable/disable the
2045 * workaround will result in this function seeing a reset (FLR).
2046 *
2047 * In common-code drivers, we only support multiple PCI function
2048 * scenarios with firmware that supports multicast chaining, so we can
2049 * assume it is enabled for such cases and hence simplify the filter
2050 * insertion logic. Firmware that does not support multicast chaining
2051 * does not support multiple PCI function configurations either, so
2052 * filter insertion is much simpler and the same strategies can still be
2053 * used.
2054 */
2055 if ((rc = ef10_filter_get_workarounds(enp)) != 0)
2056 goto fail2;
2057
2058 if ((table->eft_using_all_mulcst != all_mulcst) &&
2059 (encp->enc_bug26807_workaround == B_TRUE)) {
2060 /*
2061 * Multicast filter chaining is enabled, so traffic that matches
2062 * more than one multicast filter will be replicated and
2063 * delivered to multiple recipients. To avoid this duplicate
2064 * delivery, remove old multicast filters before inserting new
2065 * multicast filters.
2066 */
2067 ef10_filter_remove_old(enp);
2068 if (all_unicst_inserted == B_FALSE)
2069 epp->ep_all_unicst_inserted = B_FALSE;
2070
2071 epp->ep_all_mulcst_inserted = B_FALSE;
2072 }
2073
2074 /* Insert or renew multicast filters */
2075 rc = ef10_filter_insert_renew_mulcst_filters(enp, mulcst, all_mulcst,
2076 brdcst, addrs, count,
2077 filter_flags,
2078 all_unicst_inserted,
2079 &all_mulcst_inserted);
2080 if (rc != 0)
2081 goto fail3;
2082
2083 if (encp->enc_tunnel_encapsulations_supported != 0) {
2084 /* Try to insert filters for encapsulated packets. */
2085 (void) ef10_filter_insert_encap_filters(enp,
2086 mulcst || all_mulcst || brdcst,
2087 filter_flags);
2088 }
2089
2090 /* Remove old filters which were not renewed */
2091 ef10_filter_remove_old(enp);
2092 if (all_unicst_inserted == B_FALSE)
2093 epp->ep_all_unicst_inserted = B_FALSE;
2094 if (all_mulcst_inserted == B_FALSE)
2095 epp->ep_all_mulcst_inserted = B_FALSE;
2096
2097 /* report if any optional flags were rejected */
2098 if (((all_unicst != B_FALSE) && (all_unicst_inserted == B_FALSE)) ||
2099 ((all_mulcst != B_FALSE) && (all_mulcst_inserted == B_FALSE))) {
2100 rc = ENOTSUP;
2101 }
2102
2103 return (rc);
2104
2105 fail3:
2106 EFSYS_PROBE(fail3);
2107 fail2:
2108 EFSYS_PROBE(fail2);
2109 fail1:
2110 EFSYS_PROBE1(fail1, efx_rc_t, rc);
2111
2112 /* Clear auto old flags */
2113 for (i = 0; i < EFX_ARRAY_SIZE(table->eft_entry); i++) {
2114 if (ef10_filter_entry_is_auto_old(table, i)) {
2115 ef10_filter_set_entry_not_auto_old(table, i);
2116 }
2117 }
2118
2119 return (rc);
2120 }
2121
2122 __checkReturn efx_rc_t
ef10_filter_get_count(__in efx_nic_t * enp,__out uint32_t * countp)2123 ef10_filter_get_count(
2124 __in efx_nic_t *enp,
2125 __out uint32_t *countp)
2126 {
2127 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
2128 uint32_t filter_count;
2129
2130 EFSYS_ASSERT(EFX_FAMILY_IS_EF100(enp) || EFX_FAMILY_IS_EF10(enp));
2131 EFSYS_ASSERT(countp != NULL);
2132
2133 filter_count = table->eft_unicst_filter_count +
2134 table->eft_mulcst_filter_count +
2135 table->eft_encap_filter_count;
2136
2137 *countp = filter_count;
2138
2139 return (0);
2140 }
2141
2142 void
ef10_filter_get_default_rxq(__in efx_nic_t * enp,__out efx_rxq_t ** erpp,__out boolean_t * using_rss)2143 ef10_filter_get_default_rxq(
2144 __in efx_nic_t *enp,
2145 __out efx_rxq_t **erpp,
2146 __out boolean_t *using_rss)
2147 {
2148 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
2149
2150 *erpp = table->eft_default_rxq;
2151 *using_rss = table->eft_using_rss;
2152 }
2153
2154
2155 void
ef10_filter_default_rxq_set(__in efx_nic_t * enp,__in efx_rxq_t * erp,__in boolean_t using_rss)2156 ef10_filter_default_rxq_set(
2157 __in efx_nic_t *enp,
2158 __in efx_rxq_t *erp,
2159 __in boolean_t using_rss)
2160 {
2161 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
2162
2163 #if EFSYS_OPT_RX_SCALE
2164 EFSYS_ASSERT((using_rss == B_FALSE) ||
2165 (enp->en_rss_context != EF10_RSS_CONTEXT_INVALID));
2166 table->eft_using_rss = using_rss;
2167 #else
2168 EFSYS_ASSERT(using_rss == B_FALSE);
2169 table->eft_using_rss = B_FALSE;
2170 #endif
2171 table->eft_default_rxq = erp;
2172 }
2173
2174 void
ef10_filter_default_rxq_clear(__in efx_nic_t * enp)2175 ef10_filter_default_rxq_clear(
2176 __in efx_nic_t *enp)
2177 {
2178 ef10_filter_table_t *table = enp->en_filter.ef_ef10_filter_table;
2179
2180 table->eft_default_rxq = NULL;
2181 table->eft_using_rss = B_FALSE;
2182 }
2183
2184
2185 #endif /* EFSYS_OPT_FILTER */
2186
2187 #endif /* EFSYS_OPT_RIVERHEAD || EFX_OPTS_EF10() */
2188