Branch data Line data Source code
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_SIENA
11 : :
12 : : static __checkReturn efx_rc_t
13 : : siena_mac_multicast_list_set(
14 : : __in efx_nic_t *enp);
15 : :
16 : : #endif /* EFSYS_OPT_SIENA */
17 : :
18 : : #if EFSYS_OPT_SIENA
19 : : static const efx_mac_ops_t __efx_mac_siena_ops = {
20 : : siena_mac_poll, /* emo_poll */
21 : : siena_mac_up, /* emo_up */
22 : : siena_mac_reconfigure, /* emo_addr_set */
23 : : siena_mac_reconfigure, /* emo_pdu_set */
24 : : siena_mac_pdu_get, /* emo_pdu_get */
25 : : siena_mac_reconfigure, /* emo_reconfigure */
26 : : siena_mac_multicast_list_set, /* emo_multicast_list_set */
27 : : NULL, /* emo_filter_set_default_rxq */
28 : : NULL, /* emo_filter_default_rxq_clear */
29 : : #if EFSYS_OPT_LOOPBACK
30 : : siena_mac_loopback_set, /* emo_loopback_set */
31 : : #endif /* EFSYS_OPT_LOOPBACK */
32 : : #if EFSYS_OPT_MAC_STATS
33 : : siena_mac_stats_get_mask, /* emo_stats_get_mask */
34 : : efx_mcdi_mac_stats_clear, /* emo_stats_clear */
35 : : efx_mcdi_mac_stats_upload, /* emo_stats_upload */
36 : : efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
37 : : siena_mac_stats_update /* emo_stats_update */
38 : : #endif /* EFSYS_OPT_MAC_STATS */
39 : : };
40 : : #endif /* EFSYS_OPT_SIENA */
41 : :
42 : : #if EFX_OPTS_EF10()
43 : : static const efx_mac_ops_t __efx_mac_ef10_ops = {
44 : : ef10_mac_poll, /* emo_poll */
45 : : ef10_mac_up, /* emo_up */
46 : : ef10_mac_addr_set, /* emo_addr_set */
47 : : ef10_mac_pdu_set, /* emo_pdu_set */
48 : : ef10_mac_pdu_get, /* emo_pdu_get */
49 : : ef10_mac_reconfigure, /* emo_reconfigure */
50 : : ef10_mac_multicast_list_set, /* emo_multicast_list_set */
51 : : ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
52 : : ef10_mac_filter_default_rxq_clear,
53 : : /* emo_filter_default_rxq_clear */
54 : : #if EFSYS_OPT_LOOPBACK
55 : : ef10_mac_loopback_set, /* emo_loopback_set */
56 : : #endif /* EFSYS_OPT_LOOPBACK */
57 : : #if EFSYS_OPT_MAC_STATS
58 : : ef10_mac_stats_get_mask, /* emo_stats_get_mask */
59 : : efx_mcdi_mac_stats_clear, /* emo_stats_clear */
60 : : efx_mcdi_mac_stats_upload, /* emo_stats_upload */
61 : : efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
62 : : ef10_mac_stats_update /* emo_stats_update */
63 : : #endif /* EFSYS_OPT_MAC_STATS */
64 : : };
65 : : #endif /* EFX_OPTS_EF10() */
66 : :
67 : : #if EFSYS_OPT_RIVERHEAD
68 : : static const efx_mac_ops_t __efx_mac_rhead_ops = {
69 : : ef10_mac_poll, /* emo_poll */
70 : : ef10_mac_up, /* emo_up */
71 : : ef10_mac_addr_set, /* emo_addr_set */
72 : : ef10_mac_pdu_set, /* emo_pdu_set */
73 : : ef10_mac_pdu_get, /* emo_pdu_get */
74 : : ef10_mac_reconfigure, /* emo_reconfigure */
75 : : ef10_mac_multicast_list_set, /* emo_multicast_list_set */
76 : : ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
77 : : ef10_mac_filter_default_rxq_clear,
78 : : /* emo_filter_default_rxq_clear */
79 : : #if EFSYS_OPT_LOOPBACK
80 : : ef10_mac_loopback_set, /* emo_loopback_set */
81 : : #endif /* EFSYS_OPT_LOOPBACK */
82 : : #if EFSYS_OPT_MAC_STATS
83 : : ef10_mac_stats_get_mask, /* emo_stats_get_mask */
84 : : efx_mcdi_mac_stats_clear, /* emo_stats_clear */
85 : : efx_mcdi_mac_stats_upload, /* emo_stats_upload */
86 : : efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
87 : : ef10_mac_stats_update /* emo_stats_update */
88 : : #endif /* EFSYS_OPT_MAC_STATS */
89 : : };
90 : : #endif /* EFSYS_OPT_RIVERHEAD */
91 : :
92 : : __checkReturn efx_rc_t
93 : 0 : efx_mac_pdu_set(
94 : : __in efx_nic_t *enp,
95 : : __in size_t pdu)
96 : : {
97 : : efx_port_t *epp = &(enp->en_port);
98 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
99 : : uint32_t old_pdu;
100 : : efx_rc_t rc;
101 : :
102 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
103 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
104 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
105 : :
106 [ # # ]: 0 : if (pdu < EFX_MAC_PDU_MIN) {
107 : : rc = EINVAL;
108 : 0 : goto fail1;
109 : : }
110 : :
111 [ # # ]: 0 : if (pdu > EFX_MAC_PDU_MAX) {
112 : : rc = EINVAL;
113 : 0 : goto fail2;
114 : : }
115 : :
116 : 0 : old_pdu = epp->ep_mac_pdu;
117 : 0 : epp->ep_mac_pdu = (uint32_t)pdu;
118 [ # # ]: 0 : if ((rc = emop->emo_pdu_set(enp)) != 0)
119 : 0 : goto fail3;
120 : :
121 : : return (0);
122 : :
123 : : fail3:
124 : : EFSYS_PROBE(fail3);
125 : :
126 : 0 : epp->ep_mac_pdu = old_pdu;
127 : :
128 : : fail2:
129 : : EFSYS_PROBE(fail2);
130 : : fail1:
131 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
132 : :
133 : : return (rc);
134 : : }
135 : :
136 : : __checkReturn efx_rc_t
137 : 0 : efx_mac_pdu_get(
138 : : __in efx_nic_t *enp,
139 : : __out size_t *pdu)
140 : : {
141 : : efx_port_t *epp = &(enp->en_port);
142 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
143 : : efx_rc_t rc;
144 : :
145 [ # # ]: 0 : if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
146 : 0 : goto fail1;
147 : :
148 : : return (0);
149 : :
150 : : fail1:
151 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
152 : :
153 : 0 : return (rc);
154 : : }
155 : :
156 : : __checkReturn efx_rc_t
157 : 0 : efx_mac_addr_set(
158 : : __in efx_nic_t *enp,
159 : : __in uint8_t *addr)
160 : : {
161 : : efx_port_t *epp = &(enp->en_port);
162 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
163 : : uint8_t old_addr[6];
164 : : uint32_t oui;
165 : : efx_rc_t rc;
166 : :
167 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
168 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
169 : :
170 [ # # ]: 0 : if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
171 : : rc = EINVAL;
172 : 0 : goto fail1;
173 : : }
174 : :
175 : 0 : oui = addr[0] << 16 | addr[1] << 8 | addr[2];
176 [ # # ]: 0 : if (oui == 0x000000) {
177 : : rc = EINVAL;
178 : 0 : goto fail2;
179 : : }
180 : :
181 : 0 : EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
182 : 0 : EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
183 [ # # ]: 0 : if ((rc = emop->emo_addr_set(enp)) != 0)
184 : 0 : goto fail3;
185 : :
186 : : return (0);
187 : :
188 : : fail3:
189 : : EFSYS_PROBE(fail3);
190 : :
191 : 0 : EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
192 : :
193 : : fail2:
194 : : EFSYS_PROBE(fail2);
195 : : fail1:
196 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
197 : :
198 : : return (rc);
199 : : }
200 : :
201 : : __checkReturn efx_rc_t
202 : 0 : efx_mac_filter_set(
203 : : __in efx_nic_t *enp,
204 : : __in boolean_t all_unicst,
205 : : __in boolean_t mulcst,
206 : : __in boolean_t all_mulcst,
207 : : __in boolean_t brdcst)
208 : : {
209 : : efx_port_t *epp = &(enp->en_port);
210 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
211 : : boolean_t old_all_unicst;
212 : : boolean_t old_mulcst;
213 : : boolean_t old_all_mulcst;
214 : : boolean_t old_brdcst;
215 : : efx_rc_t rc;
216 : :
217 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
218 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
219 : :
220 : 0 : old_all_unicst = epp->ep_all_unicst;
221 : 0 : old_mulcst = epp->ep_mulcst;
222 : 0 : old_all_mulcst = epp->ep_all_mulcst;
223 : 0 : old_brdcst = epp->ep_brdcst;
224 : :
225 : 0 : epp->ep_all_unicst = all_unicst;
226 : 0 : epp->ep_mulcst = mulcst;
227 : 0 : epp->ep_all_mulcst = all_mulcst;
228 : 0 : epp->ep_brdcst = brdcst;
229 : :
230 [ # # ]: 0 : if ((rc = emop->emo_reconfigure(enp)) != 0)
231 : 0 : goto fail1;
232 : :
233 : : return (0);
234 : :
235 : : fail1:
236 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
237 : :
238 : 0 : epp->ep_all_unicst = old_all_unicst;
239 : 0 : epp->ep_mulcst = old_mulcst;
240 : 0 : epp->ep_all_mulcst = old_all_mulcst;
241 : 0 : epp->ep_brdcst = old_brdcst;
242 : :
243 : 0 : return (rc);
244 : : }
245 : :
246 : : void
247 : 0 : efx_mac_filter_get_all_ucast_mcast(
248 : : __in efx_nic_t *enp,
249 : : __out boolean_t *all_unicst,
250 : : __out boolean_t *all_mulcst)
251 : : {
252 : : efx_port_t *epp = &(enp->en_port);
253 : :
254 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
255 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
256 : :
257 : 0 : *all_unicst = epp->ep_all_unicst_inserted;
258 : 0 : *all_mulcst = epp->ep_all_mulcst_inserted;
259 : 0 : }
260 : :
261 : : __checkReturn efx_rc_t
262 : 0 : efx_mac_drain(
263 : : __in efx_nic_t *enp,
264 : : __in boolean_t enabled)
265 : : {
266 : : efx_port_t *epp = &(enp->en_port);
267 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
268 : : efx_rc_t rc;
269 : :
270 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
271 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
272 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
273 : :
274 [ # # ]: 0 : if (epp->ep_mac_drain == enabled)
275 : : return (0);
276 : :
277 : 0 : epp->ep_mac_drain = enabled;
278 : :
279 [ # # ]: 0 : if ((rc = emop->emo_reconfigure(enp)) != 0)
280 : 0 : goto fail1;
281 : :
282 : : return (0);
283 : :
284 : : fail1:
285 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
286 : :
287 : 0 : return (rc);
288 : : }
289 : :
290 : : __checkReturn efx_rc_t
291 : 0 : efx_mac_up(
292 : : __in efx_nic_t *enp,
293 : : __out boolean_t *mac_upp)
294 : : {
295 : : efx_port_t *epp = &(enp->en_port);
296 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
297 : : efx_rc_t rc;
298 : :
299 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
300 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
301 : :
302 [ # # ]: 0 : if ((rc = emop->emo_up(enp, mac_upp)) != 0)
303 : 0 : goto fail1;
304 : :
305 : : return (0);
306 : :
307 : : fail1:
308 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
309 : :
310 : 0 : return (rc);
311 : : }
312 : :
313 : : __checkReturn efx_rc_t
314 : 0 : efx_mac_fcntl_set(
315 : : __in efx_nic_t *enp,
316 : : __in unsigned int fcntl,
317 : : __in boolean_t autoneg)
318 : : {
319 : : efx_port_t *epp = &(enp->en_port);
320 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
321 : 0 : const efx_phy_ops_t *epop = epp->ep_epop;
322 : : unsigned int old_fcntl;
323 : : boolean_t old_autoneg;
324 : : unsigned int old_adv_cap;
325 : : efx_rc_t rc;
326 : :
327 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
328 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
329 : :
330 [ # # ]: 0 : if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
331 : : rc = EINVAL;
332 : 0 : goto fail1;
333 : : }
334 : :
335 : : /*
336 : : * Ignore a request to set flow control auto-negotiation
337 : : * if the PHY doesn't support it.
338 : : */
339 [ # # ]: 0 : if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
340 : : autoneg = B_FALSE;
341 : :
342 : 0 : old_fcntl = epp->ep_fcntl;
343 : 0 : old_autoneg = epp->ep_fcntl_autoneg;
344 : 0 : old_adv_cap = epp->ep_adv_cap_mask;
345 : :
346 : 0 : epp->ep_fcntl = fcntl;
347 : 0 : epp->ep_fcntl_autoneg = autoneg;
348 : :
349 : : /*
350 : : * Always encode the flow control settings in the advertised
351 : : * capabilities even if we are not trying to auto-negotiate
352 : : * them and reconfigure both the PHY and the MAC.
353 : : */
354 [ # # ]: 0 : if (fcntl & EFX_FCNTL_RESPOND)
355 : 0 : epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
356 : : 1 << EFX_PHY_CAP_ASYM);
357 : : else
358 : 0 : epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
359 : : 1 << EFX_PHY_CAP_ASYM);
360 : :
361 [ # # ]: 0 : if (fcntl & EFX_FCNTL_GENERATE)
362 : 0 : epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
363 : :
364 [ # # ]: 0 : if ((rc = epop->epo_reconfigure(enp)) != 0)
365 : 0 : goto fail2;
366 : :
367 [ # # ]: 0 : if ((rc = emop->emo_reconfigure(enp)) != 0)
368 : 0 : goto fail3;
369 : :
370 : : return (0);
371 : :
372 : : fail3:
373 : : EFSYS_PROBE(fail3);
374 : :
375 : 0 : fail2:
376 : : EFSYS_PROBE(fail2);
377 : :
378 : 0 : epp->ep_fcntl = old_fcntl;
379 : 0 : epp->ep_fcntl_autoneg = old_autoneg;
380 : 0 : epp->ep_adv_cap_mask = old_adv_cap;
381 : :
382 : : fail1:
383 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
384 : :
385 : : return (rc);
386 : : }
387 : :
388 : : void
389 : 0 : efx_mac_fcntl_get(
390 : : __in efx_nic_t *enp,
391 : : __out unsigned int *fcntl_wantedp,
392 : : __out unsigned int *fcntl_linkp)
393 : : {
394 : : efx_port_t *epp = &(enp->en_port);
395 : : unsigned int wanted = 0;
396 : :
397 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
398 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
399 : :
400 : : /*
401 : : * Decode the requested flow control settings from the PHY
402 : : * advertised capabilities.
403 : : */
404 [ # # ]: 0 : if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
405 : : wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
406 [ # # ]: 0 : if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
407 : 0 : wanted ^= EFX_FCNTL_GENERATE;
408 : :
409 : 0 : *fcntl_linkp = epp->ep_fcntl;
410 : 0 : *fcntl_wantedp = wanted;
411 : 0 : }
412 : :
413 : : __checkReturn efx_rc_t
414 : 0 : efx_mac_multicast_list_set(
415 : : __in efx_nic_t *enp,
416 : : __in_ecount(6*count) uint8_t const *addrs,
417 : : __in int count)
418 : : {
419 : : efx_port_t *epp = &(enp->en_port);
420 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
421 : : uint8_t *old_mulcst_addr_list = NULL;
422 : : uint32_t old_mulcst_addr_count;
423 : : efx_rc_t rc;
424 : :
425 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
426 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
427 : :
428 [ # # ]: 0 : if (count > EFX_MAC_MULTICAST_LIST_MAX) {
429 : : rc = EINVAL;
430 : 0 : goto fail1;
431 : : }
432 : :
433 : 0 : old_mulcst_addr_count = epp->ep_mulcst_addr_count;
434 [ # # ]: 0 : if (old_mulcst_addr_count > 0) {
435 : : /* Allocate memory to store old list (instead of using stack) */
436 : 0 : EFSYS_KMEM_ALLOC(enp->en_esip,
437 : : old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
438 : : old_mulcst_addr_list);
439 [ # # ]: 0 : if (old_mulcst_addr_list == NULL) {
440 : : rc = ENOMEM;
441 : 0 : goto fail2;
442 : : }
443 : :
444 : : /* Save the old list in case we need to rollback */
445 : 0 : memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
446 : : old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
447 : : }
448 : :
449 : : /* Store the new list */
450 : 0 : memcpy(epp->ep_mulcst_addr_list, addrs,
451 : 0 : count * EFX_MAC_ADDR_LEN);
452 : 0 : epp->ep_mulcst_addr_count = count;
453 : :
454 [ # # ]: 0 : if ((rc = emop->emo_multicast_list_set(enp)) != 0)
455 : 0 : goto fail3;
456 : :
457 [ # # ]: 0 : if (old_mulcst_addr_count > 0) {
458 : 0 : EFSYS_KMEM_FREE(enp->en_esip,
459 : : old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
460 : : old_mulcst_addr_list);
461 : : }
462 : :
463 : : return (0);
464 : :
465 : : fail3:
466 : : EFSYS_PROBE(fail3);
467 : :
468 : : /* Restore original list on failure */
469 : 0 : epp->ep_mulcst_addr_count = old_mulcst_addr_count;
470 [ # # ]: 0 : if (old_mulcst_addr_count > 0) {
471 : 0 : memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
472 : 0 : old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
473 : :
474 : 0 : EFSYS_KMEM_FREE(enp->en_esip,
475 : : old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
476 : : old_mulcst_addr_list);
477 : : }
478 : :
479 : 0 : fail2:
480 : : EFSYS_PROBE(fail2);
481 : :
482 : : fail1:
483 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
484 : :
485 : : return (rc);
486 : :
487 : : }
488 : :
489 : : __checkReturn efx_rc_t
490 : 0 : efx_mac_filter_default_rxq_set(
491 : : __in efx_nic_t *enp,
492 : : __in efx_rxq_t *erp,
493 : : __in boolean_t using_rss)
494 : : {
495 : : efx_port_t *epp = &(enp->en_port);
496 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
497 : : efx_rc_t rc;
498 : :
499 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
500 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
501 : :
502 [ # # ]: 0 : if (emop->emo_filter_default_rxq_set != NULL) {
503 : 0 : rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
504 [ # # ]: 0 : if (rc != 0)
505 : 0 : goto fail1;
506 : : }
507 : :
508 : : return (0);
509 : :
510 : : fail1:
511 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
512 : :
513 : 0 : return (rc);
514 : : }
515 : :
516 : : void
517 : 0 : efx_mac_filter_default_rxq_clear(
518 : : __in efx_nic_t *enp)
519 : : {
520 : : efx_port_t *epp = &(enp->en_port);
521 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
522 : :
523 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
524 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
525 : :
526 [ # # ]: 0 : if (emop->emo_filter_default_rxq_clear != NULL)
527 : 0 : emop->emo_filter_default_rxq_clear(enp);
528 : 0 : }
529 : :
530 : : __checkReturn efx_rc_t
531 : 0 : efx_mac_include_fcs_set(
532 : : __in efx_nic_t *enp,
533 : : __in boolean_t enabled)
534 : : {
535 : : efx_port_t *epp = &(enp->en_port);
536 : : efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
537 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
538 : : efx_rc_t rc;
539 : :
540 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
541 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
542 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
543 : :
544 [ # # # # ]: 0 : if (enabled && !encp->enc_rx_include_fcs_supported) {
545 : : rc = ENOTSUP;
546 : 0 : goto fail1;
547 : : }
548 : :
549 : : /*
550 : : * Enabling 'include FCS' changes link control state and affects
551 : : * behaviour for all PCI functions on the port, so to avoid this it
552 : : * can be enabled only if the PCI function is exclusive port user
553 : : */
554 [ # # # # ]: 0 : if (enabled && encp->enc_port_usage != EFX_PORT_USAGE_EXCLUSIVE) {
555 : : rc = EACCES;
556 : 0 : goto fail2;
557 : : }
558 : :
559 [ # # ]: 0 : if (epp->ep_include_fcs != enabled) {
560 : 0 : epp->ep_include_fcs = enabled;
561 : :
562 : 0 : rc = emop->emo_reconfigure(enp);
563 [ # # ]: 0 : if (rc != 0)
564 : 0 : goto fail3;
565 : : }
566 : :
567 : : return 0;
568 : :
569 : : fail3:
570 : : EFSYS_PROBE(fail3);
571 : : fail2:
572 : : EFSYS_PROBE(fail2);
573 : : fail1:
574 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
575 : :
576 : : return rc;
577 : : }
578 : :
579 : : #if EFSYS_OPT_MAC_STATS
580 : :
581 : : #if EFSYS_OPT_NAMES
582 : :
583 : : /* START MKCONFIG GENERATED EfxMacStatNamesBlock 1a45a82fcfb30c1b */
584 : : static const char * const __efx_mac_stat_name[] = {
585 : : "rx_octets",
586 : : "rx_pkts",
587 : : "rx_unicst_pkts",
588 : : "rx_multicst_pkts",
589 : : "rx_brdcst_pkts",
590 : : "rx_pause_pkts",
591 : : "rx_le_64_pkts",
592 : : "rx_65_to_127_pkts",
593 : : "rx_128_to_255_pkts",
594 : : "rx_256_to_511_pkts",
595 : : "rx_512_to_1023_pkts",
596 : : "rx_1024_to_15xx_pkts",
597 : : "rx_ge_15xx_pkts",
598 : : "rx_errors",
599 : : "rx_fcs_errors",
600 : : "rx_drop_events",
601 : : "rx_false_carrier_errors",
602 : : "rx_symbol_errors",
603 : : "rx_align_errors",
604 : : "rx_internal_errors",
605 : : "rx_jabber_pkts",
606 : : "rx_lane0_char_err",
607 : : "rx_lane1_char_err",
608 : : "rx_lane2_char_err",
609 : : "rx_lane3_char_err",
610 : : "rx_lane0_disp_err",
611 : : "rx_lane1_disp_err",
612 : : "rx_lane2_disp_err",
613 : : "rx_lane3_disp_err",
614 : : "rx_match_fault",
615 : : "rx_nodesc_drop_cnt",
616 : : "tx_octets",
617 : : "tx_pkts",
618 : : "tx_unicst_pkts",
619 : : "tx_multicst_pkts",
620 : : "tx_brdcst_pkts",
621 : : "tx_pause_pkts",
622 : : "tx_le_64_pkts",
623 : : "tx_65_to_127_pkts",
624 : : "tx_128_to_255_pkts",
625 : : "tx_256_to_511_pkts",
626 : : "tx_512_to_1023_pkts",
627 : : "tx_1024_to_15xx_pkts",
628 : : "tx_ge_15xx_pkts",
629 : : "tx_errors",
630 : : "tx_sgl_col_pkts",
631 : : "tx_mult_col_pkts",
632 : : "tx_ex_col_pkts",
633 : : "tx_late_col_pkts",
634 : : "tx_def_pkts",
635 : : "tx_ex_def_pkts",
636 : : "pm_trunc_bb_overflow",
637 : : "pm_discard_bb_overflow",
638 : : "pm_trunc_vfifo_full",
639 : : "pm_discard_vfifo_full",
640 : : "pm_trunc_qbb",
641 : : "pm_discard_qbb",
642 : : "pm_discard_mapping",
643 : : "rxdp_q_disabled_pkts",
644 : : "rxdp_di_dropped_pkts",
645 : : "rxdp_streaming_pkts",
646 : : "rxdp_hlb_fetch",
647 : : "rxdp_hlb_wait",
648 : : "vadapter_rx_unicast_packets",
649 : : "vadapter_rx_unicast_bytes",
650 : : "vadapter_rx_multicast_packets",
651 : : "vadapter_rx_multicast_bytes",
652 : : "vadapter_rx_broadcast_packets",
653 : : "vadapter_rx_broadcast_bytes",
654 : : "vadapter_rx_bad_packets",
655 : : "vadapter_rx_bad_bytes",
656 : : "vadapter_rx_overflow",
657 : : "vadapter_tx_unicast_packets",
658 : : "vadapter_tx_unicast_bytes",
659 : : "vadapter_tx_multicast_packets",
660 : : "vadapter_tx_multicast_bytes",
661 : : "vadapter_tx_broadcast_packets",
662 : : "vadapter_tx_broadcast_bytes",
663 : : "vadapter_tx_bad_packets",
664 : : "vadapter_tx_bad_bytes",
665 : : "vadapter_tx_overflow",
666 : : "fec_uncorrected_errors",
667 : : "fec_corrected_errors",
668 : : "fec_corrected_symbols_lane0",
669 : : "fec_corrected_symbols_lane1",
670 : : "fec_corrected_symbols_lane2",
671 : : "fec_corrected_symbols_lane3",
672 : : "ctpio_vi_busy_fallback",
673 : : "ctpio_long_write_success",
674 : : "ctpio_missing_dbell_fail",
675 : : "ctpio_overflow_fail",
676 : : "ctpio_underflow_fail",
677 : : "ctpio_timeout_fail",
678 : : "ctpio_noncontig_wr_fail",
679 : : "ctpio_frm_clobber_fail",
680 : : "ctpio_invalid_wr_fail",
681 : : "ctpio_vi_clobber_fallback",
682 : : "ctpio_unqualified_fallback",
683 : : "ctpio_runt_fallback",
684 : : "ctpio_success",
685 : : "ctpio_fallback",
686 : : "ctpio_poison",
687 : : "ctpio_erase",
688 : : "rxdp_scatter_disabled_trunc",
689 : : "rxdp_hlb_idle",
690 : : "rxdp_hlb_timeout",
691 : : };
692 : : /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
693 : :
694 : : __checkReturn const char *
695 : 0 : efx_mac_stat_name(
696 : : __in efx_nic_t *enp,
697 : : __in unsigned int id)
698 : : {
699 : : _NOTE(ARGUNUSED(enp))
700 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
701 : :
702 [ # # ]: 0 : EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
703 : 0 : return (__efx_mac_stat_name[id]);
704 : : }
705 : :
706 : : #endif /* EFSYS_OPT_NAMES */
707 : :
708 : : static efx_rc_t
709 : 0 : efx_mac_stats_mask_add_range(
710 : : __inout_bcount(mask_size) uint32_t *maskp,
711 : : __in size_t mask_size,
712 : : __in const struct efx_mac_stats_range *rngp)
713 : : {
714 : 0 : unsigned int mask_npages = mask_size / sizeof (*maskp);
715 : : unsigned int el;
716 : : unsigned int el_min;
717 : : unsigned int el_max;
718 : : unsigned int low;
719 : : unsigned int high;
720 : : unsigned int width;
721 : : efx_rc_t rc;
722 : :
723 : 0 : if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
724 [ # # ]: 0 : (unsigned int)rngp->last) {
725 : : rc = EINVAL;
726 : 0 : goto fail1;
727 : : }
728 : :
729 [ # # ]: 0 : EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
730 [ # # ]: 0 : EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
731 : :
732 [ # # ]: 0 : for (el = 0; el < mask_npages; ++el) {
733 : 0 : el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
734 : 0 : el_max =
735 : : el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
736 [ # # ]: 0 : if ((unsigned int)rngp->first > el_max ||
737 [ # # ]: 0 : (unsigned int)rngp->last < el_min)
738 : 0 : continue;
739 : 0 : low = MAX((unsigned int)rngp->first, el_min);
740 : 0 : high = MIN((unsigned int)rngp->last, el_max);
741 : 0 : width = high - low + 1;
742 [ # # ]: 0 : maskp[el] |=
743 : : (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
744 : 0 : (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
745 : : }
746 : :
747 : : return (0);
748 : :
749 : : fail1:
750 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
751 : :
752 : 0 : return (rc);
753 : : }
754 : :
755 : : efx_rc_t
756 : 0 : efx_mac_stats_mask_add_ranges(
757 : : __inout_bcount(mask_size) uint32_t *maskp,
758 : : __in size_t mask_size,
759 : : __in_ecount(rng_count) const struct efx_mac_stats_range *rngp,
760 : : __in unsigned int rng_count)
761 : : {
762 : : unsigned int i;
763 : : efx_rc_t rc;
764 : :
765 [ # # ]: 0 : for (i = 0; i < rng_count; ++i) {
766 [ # # ]: 0 : if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
767 : 0 : &rngp[i])) != 0)
768 : 0 : goto fail1;
769 : : }
770 : :
771 : : return (0);
772 : :
773 : : fail1:
774 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
775 : :
776 : 0 : return (rc);
777 : : }
778 : :
779 : : __checkReturn efx_rc_t
780 : 0 : efx_mac_stats_get_mask(
781 : : __in efx_nic_t *enp,
782 : : __out_bcount(mask_size) uint32_t *maskp,
783 : : __in size_t mask_size)
784 : : {
785 : : efx_port_t *epp = &(enp->en_port);
786 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
787 : : efx_rc_t rc;
788 : :
789 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
790 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
791 [ # # ]: 0 : EFSYS_ASSERT(maskp != NULL);
792 [ # # ]: 0 : EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
793 : :
794 : : (void) memset(maskp, 0, mask_size);
795 : :
796 [ # # ]: 0 : if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
797 : 0 : goto fail1;
798 : :
799 : : return (0);
800 : :
801 : : fail1:
802 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
803 : :
804 : 0 : return (rc);
805 : : }
806 : :
807 : : __checkReturn efx_rc_t
808 : 0 : efx_mac_stats_clear(
809 : : __in efx_nic_t *enp)
810 : : {
811 : : efx_port_t *epp = &(enp->en_port);
812 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
813 : : efx_rc_t rc;
814 : :
815 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
816 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
817 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
818 : :
819 [ # # ]: 0 : if ((rc = emop->emo_stats_clear(enp)) != 0)
820 : 0 : goto fail1;
821 : :
822 : : return (0);
823 : :
824 : : fail1:
825 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
826 : :
827 : 0 : return (rc);
828 : : }
829 : :
830 : : __checkReturn efx_rc_t
831 : 0 : efx_mac_stats_upload(
832 : : __in efx_nic_t *enp,
833 : : __in efsys_mem_t *esmp)
834 : : {
835 : : efx_port_t *epp = &(enp->en_port);
836 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
837 : : efx_rc_t rc;
838 : :
839 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
840 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
841 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
842 : :
843 [ # # ]: 0 : if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
844 : 0 : goto fail1;
845 : :
846 : : return (0);
847 : :
848 : : fail1:
849 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
850 : :
851 : 0 : return (rc);
852 : : }
853 : :
854 : : __checkReturn efx_rc_t
855 : 0 : efx_mac_stats_periodic(
856 : : __in efx_nic_t *enp,
857 : : __in efsys_mem_t *esmp,
858 : : __in uint16_t period_ms,
859 : : __in boolean_t events)
860 : : {
861 : : efx_port_t *epp = &(enp->en_port);
862 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
863 : : efx_rc_t rc;
864 : :
865 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
866 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
867 : :
868 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
869 : :
870 [ # # ]: 0 : if (emop->emo_stats_periodic == NULL) {
871 : : rc = EINVAL;
872 : 0 : goto fail1;
873 : : }
874 : :
875 [ # # ]: 0 : if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
876 : 0 : goto fail2;
877 : :
878 : : return (0);
879 : :
880 : : fail2:
881 : : EFSYS_PROBE(fail2);
882 : : fail1:
883 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
884 : :
885 : : return (rc);
886 : : }
887 : :
888 : :
889 : : __checkReturn efx_rc_t
890 : 0 : efx_mac_stats_update(
891 : : __in efx_nic_t *enp,
892 : : __in efsys_mem_t *esmp,
893 : : __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
894 : : __inout_opt uint32_t *generationp)
895 : : {
896 : : efx_port_t *epp = &(enp->en_port);
897 : 0 : const efx_mac_ops_t *emop = epp->ep_emop;
898 : : efx_rc_t rc;
899 : :
900 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
901 [ # # ]: 0 : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
902 [ # # ]: 0 : EFSYS_ASSERT(emop != NULL);
903 : :
904 : 0 : rc = emop->emo_stats_update(enp, esmp, essp, generationp);
905 : :
906 : 0 : return (rc);
907 : : }
908 : :
909 : : #endif /* EFSYS_OPT_MAC_STATS */
910 : :
911 : : __checkReturn efx_rc_t
912 : 0 : efx_mac_select(
913 : : __in efx_nic_t *enp)
914 : : {
915 : : efx_port_t *epp = &(enp->en_port);
916 : : efx_mac_type_t type = EFX_MAC_INVALID;
917 : : const efx_mac_ops_t *emop;
918 : : int rc = EINVAL;
919 : :
920 [ # # # # : 0 : switch (enp->en_family) {
# ]
921 : : #if EFSYS_OPT_SIENA
922 : : case EFX_FAMILY_SIENA:
923 : : emop = &__efx_mac_siena_ops;
924 : : type = EFX_MAC_SIENA;
925 : : break;
926 : : #endif /* EFSYS_OPT_SIENA */
927 : :
928 : : #if EFSYS_OPT_HUNTINGTON
929 : : case EFX_FAMILY_HUNTINGTON:
930 : : emop = &__efx_mac_ef10_ops;
931 : : type = EFX_MAC_HUNTINGTON;
932 : : break;
933 : : #endif /* EFSYS_OPT_HUNTINGTON */
934 : :
935 : : #if EFSYS_OPT_MEDFORD
936 : 0 : case EFX_FAMILY_MEDFORD:
937 : : emop = &__efx_mac_ef10_ops;
938 : : type = EFX_MAC_MEDFORD;
939 : 0 : break;
940 : : #endif /* EFSYS_OPT_MEDFORD */
941 : :
942 : : #if EFSYS_OPT_MEDFORD2
943 : 0 : case EFX_FAMILY_MEDFORD2:
944 : : emop = &__efx_mac_ef10_ops;
945 : : type = EFX_MAC_MEDFORD2;
946 : 0 : break;
947 : : #endif /* EFSYS_OPT_MEDFORD2 */
948 : :
949 : : #if EFSYS_OPT_RIVERHEAD
950 : 0 : case EFX_FAMILY_RIVERHEAD:
951 : : emop = &__efx_mac_rhead_ops;
952 : : type = EFX_MAC_RIVERHEAD;
953 : 0 : break;
954 : : #endif /* EFSYS_OPT_RIVERHEAD */
955 : :
956 : 0 : default:
957 : : rc = EINVAL;
958 : 0 : goto fail1;
959 : : }
960 : :
961 : : EFSYS_ASSERT(type != EFX_MAC_INVALID);
962 : : EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
963 : : EFSYS_ASSERT(emop != NULL);
964 : :
965 : 0 : epp->ep_emop = emop;
966 : 0 : epp->ep_mac_type = type;
967 : :
968 : 0 : return (0);
969 : :
970 : : fail1:
971 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
972 : :
973 : 0 : return (rc);
974 : : }
975 : :
976 : :
977 : : #if EFSYS_OPT_SIENA
978 : :
979 : : #define EFX_MAC_HASH_BITS (1 << 8)
980 : :
981 : : /* Compute the multicast hash as used on Falcon and Siena. */
982 : : static void
983 : : siena_mac_multicast_hash_compute(
984 : : __in_ecount(6*count) uint8_t const *addrs,
985 : : __in int count,
986 : : __out efx_oword_t *hash_low,
987 : : __out efx_oword_t *hash_high)
988 : : {
989 : : uint32_t crc, index;
990 : : int i;
991 : :
992 : : EFSYS_ASSERT(hash_low != NULL);
993 : : EFSYS_ASSERT(hash_high != NULL);
994 : :
995 : : EFX_ZERO_OWORD(*hash_low);
996 : : EFX_ZERO_OWORD(*hash_high);
997 : :
998 : : for (i = 0; i < count; i++) {
999 : : /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
1000 : : crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
1001 : : index = crc % EFX_MAC_HASH_BITS;
1002 : : if (index < 128) {
1003 : : EFX_SET_OWORD_BIT(*hash_low, index);
1004 : : } else {
1005 : : EFX_SET_OWORD_BIT(*hash_high, index - 128);
1006 : : }
1007 : :
1008 : : addrs += EFX_MAC_ADDR_LEN;
1009 : : }
1010 : : }
1011 : :
1012 : : static __checkReturn efx_rc_t
1013 : : siena_mac_multicast_list_set(
1014 : : __in efx_nic_t *enp)
1015 : : {
1016 : : efx_port_t *epp = &(enp->en_port);
1017 : : const efx_mac_ops_t *emop = epp->ep_emop;
1018 : : efx_oword_t old_hash[2];
1019 : : efx_rc_t rc;
1020 : :
1021 : : EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1022 : : EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
1023 : :
1024 : : memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
1025 : :
1026 : : siena_mac_multicast_hash_compute(
1027 : : epp->ep_mulcst_addr_list,
1028 : : epp->ep_mulcst_addr_count,
1029 : : &epp->ep_multicst_hash[0],
1030 : : &epp->ep_multicst_hash[1]);
1031 : :
1032 : : if ((rc = emop->emo_reconfigure(enp)) != 0)
1033 : : goto fail1;
1034 : :
1035 : : return (0);
1036 : :
1037 : : fail1:
1038 : : EFSYS_PROBE1(fail1, efx_rc_t, rc);
1039 : :
1040 : : memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
1041 : :
1042 : : return (rc);
1043 : : }
1044 : :
1045 : : #endif /* EFSYS_OPT_SIENA */
|