1 /*
2 * Copyright (c) 2007-2015 Solarflare Communications Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * The views and conclusions contained in the software and documentation are
27 * those of the authors and should not be interpreted as representing official
28 * policies, either expressed or implied, of the FreeBSD Project.
29 */
30
31 #include "efx.h"
32 #include "efx_impl.h"
33
34 #if EFSYS_OPT_SIENA
35
36 static __checkReturn efx_rc_t
37 siena_mac_multicast_list_set(
38 __in efx_nic_t *enp);
39
40 #endif /* EFSYS_OPT_SIENA */
41
42 #if EFSYS_OPT_SIENA
43 static const efx_mac_ops_t __efx_siena_mac_ops = {
44 siena_mac_poll, /* emo_poll */
45 siena_mac_up, /* emo_up */
46 siena_mac_reconfigure, /* emo_addr_set */
47 siena_mac_reconfigure, /* emo_pdu_set */
48 siena_mac_reconfigure, /* emo_reconfigure */
49 siena_mac_multicast_list_set, /* emo_multicast_list_set */
50 NULL, /* emo_filter_set_default_rxq */
51 NULL, /* emo_filter_default_rxq_clear */
52 #if EFSYS_OPT_LOOPBACK
53 siena_mac_loopback_set, /* emo_loopback_set */
54 #endif /* EFSYS_OPT_LOOPBACK */
55 #if EFSYS_OPT_MAC_STATS
56 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
57 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
58 siena_mac_stats_update /* emo_stats_update */
59 #endif /* EFSYS_OPT_MAC_STATS */
60 };
61 #endif /* EFSYS_OPT_SIENA */
62
63 #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD
64 static const efx_mac_ops_t __efx_ef10_mac_ops = {
65 ef10_mac_poll, /* emo_poll */
66 ef10_mac_up, /* emo_up */
67 ef10_mac_addr_set, /* emo_addr_set */
68 ef10_mac_pdu_set, /* emo_pdu_set */
69 ef10_mac_reconfigure, /* emo_reconfigure */
70 ef10_mac_multicast_list_set, /* emo_multicast_list_set */
71 ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
72 ef10_mac_filter_default_rxq_clear,
73 /* emo_filter_default_rxq_clear */
74 #if EFSYS_OPT_LOOPBACK
75 ef10_mac_loopback_set, /* emo_loopback_set */
76 #endif /* EFSYS_OPT_LOOPBACK */
77 #if EFSYS_OPT_MAC_STATS
78 efx_mcdi_mac_stats_upload, /* emo_stats_upload */
79 efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
80 ef10_mac_stats_update /* emo_stats_update */
81 #endif /* EFSYS_OPT_MAC_STATS */
82 };
83 #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
84
85
86 __checkReturn efx_rc_t
efx_mac_pdu_set(__in efx_nic_t * enp,__in size_t pdu)87 efx_mac_pdu_set(
88 __in efx_nic_t *enp,
89 __in size_t pdu)
90 {
91 efx_port_t *epp = &(enp->en_port);
92 const efx_mac_ops_t *emop = epp->ep_emop;
93 uint32_t old_pdu;
94 efx_rc_t rc;
95
96 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
97 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
98 EFSYS_ASSERT(emop != NULL);
99
100 if (pdu < EFX_MAC_PDU_MIN) {
101 rc = EINVAL;
102 goto fail1;
103 }
104
105 if (pdu > EFX_MAC_PDU_MAX) {
106 rc = EINVAL;
107 goto fail2;
108 }
109
110 old_pdu = epp->ep_mac_pdu;
111 epp->ep_mac_pdu = (uint32_t)pdu;
112 if ((rc = emop->emo_pdu_set(enp)) != 0)
113 goto fail3;
114
115 return (0);
116
117 fail3:
118 EFSYS_PROBE(fail3);
119
120 epp->ep_mac_pdu = old_pdu;
121
122 fail2:
123 EFSYS_PROBE(fail2);
124 fail1:
125 EFSYS_PROBE1(fail1, efx_rc_t, rc);
126
127 return (rc);
128 }
129
130 __checkReturn efx_rc_t
efx_mac_addr_set(__in efx_nic_t * enp,__in uint8_t * addr)131 efx_mac_addr_set(
132 __in efx_nic_t *enp,
133 __in uint8_t *addr)
134 {
135 efx_port_t *epp = &(enp->en_port);
136 const efx_mac_ops_t *emop = epp->ep_emop;
137 uint8_t old_addr[6];
138 uint32_t oui;
139 efx_rc_t rc;
140
141 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
142 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
143
144 if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
145 rc = EINVAL;
146 goto fail1;
147 }
148
149 oui = addr[0] << 16 | addr[1] << 8 | addr[2];
150 if (oui == 0x000000) {
151 rc = EINVAL;
152 goto fail2;
153 }
154
155 EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
156 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
157 if ((rc = emop->emo_addr_set(enp)) != 0)
158 goto fail3;
159
160 return (0);
161
162 fail3:
163 EFSYS_PROBE(fail3);
164
165 EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
166
167 fail2:
168 EFSYS_PROBE(fail2);
169 fail1:
170 EFSYS_PROBE1(fail1, efx_rc_t, rc);
171
172 return (rc);
173 }
174
175 __checkReturn efx_rc_t
efx_mac_filter_set(__in efx_nic_t * enp,__in boolean_t all_unicst,__in boolean_t mulcst,__in boolean_t all_mulcst,__in boolean_t brdcst)176 efx_mac_filter_set(
177 __in efx_nic_t *enp,
178 __in boolean_t all_unicst,
179 __in boolean_t mulcst,
180 __in boolean_t all_mulcst,
181 __in boolean_t brdcst)
182 {
183 efx_port_t *epp = &(enp->en_port);
184 const efx_mac_ops_t *emop = epp->ep_emop;
185 boolean_t old_all_unicst;
186 boolean_t old_mulcst;
187 boolean_t old_all_mulcst;
188 boolean_t old_brdcst;
189 efx_rc_t rc;
190
191 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
192 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
193
194 old_all_unicst = epp->ep_all_unicst;
195 old_mulcst = epp->ep_mulcst;
196 old_all_mulcst = epp->ep_all_mulcst;
197 old_brdcst = epp->ep_brdcst;
198
199 epp->ep_all_unicst = all_unicst;
200 epp->ep_mulcst = mulcst;
201 epp->ep_all_mulcst = all_mulcst;
202 epp->ep_brdcst = brdcst;
203
204 if ((rc = emop->emo_reconfigure(enp)) != 0)
205 goto fail1;
206
207 return (0);
208
209 fail1:
210 EFSYS_PROBE1(fail1, efx_rc_t, rc);
211
212 epp->ep_all_unicst = old_all_unicst;
213 epp->ep_mulcst = old_mulcst;
214 epp->ep_all_mulcst = old_all_mulcst;
215 epp->ep_brdcst = old_brdcst;
216
217 return (rc);
218 }
219
220 __checkReturn efx_rc_t
efx_mac_drain(__in efx_nic_t * enp,__in boolean_t enabled)221 efx_mac_drain(
222 __in efx_nic_t *enp,
223 __in boolean_t enabled)
224 {
225 efx_port_t *epp = &(enp->en_port);
226 const efx_mac_ops_t *emop = epp->ep_emop;
227 efx_rc_t rc;
228
229 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
230 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
231 EFSYS_ASSERT(emop != NULL);
232
233 if (epp->ep_mac_drain == enabled)
234 return (0);
235
236 epp->ep_mac_drain = enabled;
237
238 if ((rc = emop->emo_reconfigure(enp)) != 0)
239 goto fail1;
240
241 return (0);
242
243 fail1:
244 EFSYS_PROBE1(fail1, efx_rc_t, rc);
245
246 return (rc);
247 }
248
249 __checkReturn efx_rc_t
efx_mac_up(__in efx_nic_t * enp,__out boolean_t * mac_upp)250 efx_mac_up(
251 __in efx_nic_t *enp,
252 __out boolean_t *mac_upp)
253 {
254 efx_port_t *epp = &(enp->en_port);
255 const efx_mac_ops_t *emop = epp->ep_emop;
256 efx_rc_t rc;
257
258 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
259 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
260
261 if ((rc = emop->emo_up(enp, mac_upp)) != 0)
262 goto fail1;
263
264 return (0);
265
266 fail1:
267 EFSYS_PROBE1(fail1, efx_rc_t, rc);
268
269 return (rc);
270 }
271
272 __checkReturn efx_rc_t
efx_mac_fcntl_set(__in efx_nic_t * enp,__in unsigned int fcntl,__in boolean_t autoneg)273 efx_mac_fcntl_set(
274 __in efx_nic_t *enp,
275 __in unsigned int fcntl,
276 __in boolean_t autoneg)
277 {
278 efx_port_t *epp = &(enp->en_port);
279 const efx_mac_ops_t *emop = epp->ep_emop;
280 const efx_phy_ops_t *epop = epp->ep_epop;
281 unsigned int old_fcntl;
282 boolean_t old_autoneg;
283 unsigned int old_adv_cap;
284 efx_rc_t rc;
285
286 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
287 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
288
289 if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
290 rc = EINVAL;
291 goto fail1;
292 }
293
294 /*
295 * Ignore a request to set flow control auto-negotiation
296 * if the PHY doesn't support it.
297 */
298 if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
299 autoneg = B_FALSE;
300
301 old_fcntl = epp->ep_fcntl;
302 old_autoneg = epp->ep_fcntl_autoneg;
303 old_adv_cap = epp->ep_adv_cap_mask;
304
305 epp->ep_fcntl = fcntl;
306 epp->ep_fcntl_autoneg = autoneg;
307
308 /*
309 * Always encode the flow control settings in the advertised
310 * capabilities even if we are not trying to auto-negotiate
311 * them and reconfigure both the PHY and the MAC.
312 */
313 if (fcntl & EFX_FCNTL_RESPOND)
314 epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
315 1 << EFX_PHY_CAP_ASYM);
316 else
317 epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
318 1 << EFX_PHY_CAP_ASYM);
319
320 if (fcntl & EFX_FCNTL_GENERATE)
321 epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
322
323 if ((rc = epop->epo_reconfigure(enp)) != 0)
324 goto fail2;
325
326 if ((rc = emop->emo_reconfigure(enp)) != 0)
327 goto fail3;
328
329 return (0);
330
331 fail3:
332 EFSYS_PROBE(fail3);
333
334 fail2:
335 EFSYS_PROBE(fail2);
336
337 epp->ep_fcntl = old_fcntl;
338 epp->ep_fcntl_autoneg = old_autoneg;
339 epp->ep_adv_cap_mask = old_adv_cap;
340
341 fail1:
342 EFSYS_PROBE1(fail1, efx_rc_t, rc);
343
344 return (rc);
345 }
346
347 void
efx_mac_fcntl_get(__in efx_nic_t * enp,__out unsigned int * fcntl_wantedp,__out unsigned int * fcntl_linkp)348 efx_mac_fcntl_get(
349 __in efx_nic_t *enp,
350 __out unsigned int *fcntl_wantedp,
351 __out unsigned int *fcntl_linkp)
352 {
353 efx_port_t *epp = &(enp->en_port);
354 unsigned int wanted = 0;
355
356 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
357 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
358
359 /*
360 * Decode the requested flow control settings from the PHY
361 * advertised capabilities.
362 */
363 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
364 wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
365 if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
366 wanted ^= EFX_FCNTL_GENERATE;
367
368 *fcntl_linkp = epp->ep_fcntl;
369 *fcntl_wantedp = wanted;
370 }
371
372 __checkReturn efx_rc_t
373 efx_mac_multicast_list_set(
374 __in efx_nic_t *enp,
375 __in_ecount(6*count) uint8_t const *addrs,
376 __in int count)
377 {
378 efx_port_t *epp = &(enp->en_port);
379 const efx_mac_ops_t *emop = epp->ep_emop;
380 uint8_t *old_mulcst_addr_list = NULL;
381 uint32_t old_mulcst_addr_count;
382 efx_rc_t rc;
383
384 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
385 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
386
387 if (count > EFX_MAC_MULTICAST_LIST_MAX) {
388 rc = EINVAL;
389 goto fail1;
390 }
391
392 old_mulcst_addr_count = epp->ep_mulcst_addr_count;
393 if (old_mulcst_addr_count > 0) {
394 /* Allocate memory to store old list (instead of using stack) */
395 EFSYS_KMEM_ALLOC(enp->en_esip,
396 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
397 old_mulcst_addr_list);
398 if (old_mulcst_addr_list == NULL) {
399 rc = ENOMEM;
400 goto fail2;
401 }
402
403 /* Save the old list in case we need to rollback */
404 (void) memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
405 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
406 }
407
408 /* Store the new list */
409 (void) memcpy(epp->ep_mulcst_addr_list, addrs,
410 count * EFX_MAC_ADDR_LEN);
411 epp->ep_mulcst_addr_count = count;
412
413 if ((rc = emop->emo_multicast_list_set(enp)) != 0)
414 goto fail3;
415
416 if (old_mulcst_addr_count > 0) {
417 EFSYS_KMEM_FREE(enp->en_esip,
418 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
419 old_mulcst_addr_list);
420 }
421
422 return (0);
423
424 fail3:
425 EFSYS_PROBE(fail3);
426
427 /* Restore original list on failure */
428 epp->ep_mulcst_addr_count = old_mulcst_addr_count;
429 if (old_mulcst_addr_count > 0) {
430 (void) memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
431 old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
432
433 EFSYS_KMEM_FREE(enp->en_esip,
434 old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
435 old_mulcst_addr_list);
436 }
437
438 fail2:
439 EFSYS_PROBE(fail2);
440
441 fail1:
442 EFSYS_PROBE1(fail1, efx_rc_t, rc);
443
444 return (rc);
445
446 }
447
448 __checkReturn efx_rc_t
efx_mac_filter_default_rxq_set(__in efx_nic_t * enp,__in efx_rxq_t * erp,__in boolean_t using_rss)449 efx_mac_filter_default_rxq_set(
450 __in efx_nic_t *enp,
451 __in efx_rxq_t *erp,
452 __in boolean_t using_rss)
453 {
454 efx_port_t *epp = &(enp->en_port);
455 const efx_mac_ops_t *emop = epp->ep_emop;
456 efx_rc_t rc;
457
458 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
459 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
460
461 if (emop->emo_filter_default_rxq_set != NULL) {
462 rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
463 if (rc != 0)
464 goto fail1;
465 }
466
467 return (0);
468
469 fail1:
470 EFSYS_PROBE1(fail1, efx_rc_t, rc);
471
472 return (rc);
473 }
474
475 void
efx_mac_filter_default_rxq_clear(__in efx_nic_t * enp)476 efx_mac_filter_default_rxq_clear(
477 __in efx_nic_t *enp)
478 {
479 efx_port_t *epp = &(enp->en_port);
480 const efx_mac_ops_t *emop = epp->ep_emop;
481
482 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
483 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
484
485 if (emop->emo_filter_default_rxq_clear != NULL)
486 emop->emo_filter_default_rxq_clear(enp);
487 }
488
489
490 #if EFSYS_OPT_MAC_STATS
491
492 #if EFSYS_OPT_NAMES
493
494 /* START MKCONFIG GENERATED EfxMacStatNamesBlock 054d43a31d2d7a45 */
495 static const char *__efx_mac_stat_name[] = {
496 "rx_octets",
497 "rx_pkts",
498 "rx_unicst_pkts",
499 "rx_multicst_pkts",
500 "rx_brdcst_pkts",
501 "rx_pause_pkts",
502 "rx_le_64_pkts",
503 "rx_65_to_127_pkts",
504 "rx_128_to_255_pkts",
505 "rx_256_to_511_pkts",
506 "rx_512_to_1023_pkts",
507 "rx_1024_to_15xx_pkts",
508 "rx_ge_15xx_pkts",
509 "rx_errors",
510 "rx_fcs_errors",
511 "rx_drop_events",
512 "rx_false_carrier_errors",
513 "rx_symbol_errors",
514 "rx_align_errors",
515 "rx_internal_errors",
516 "rx_jabber_pkts",
517 "rx_lane0_char_err",
518 "rx_lane1_char_err",
519 "rx_lane2_char_err",
520 "rx_lane3_char_err",
521 "rx_lane0_disp_err",
522 "rx_lane1_disp_err",
523 "rx_lane2_disp_err",
524 "rx_lane3_disp_err",
525 "rx_match_fault",
526 "rx_nodesc_drop_cnt",
527 "tx_octets",
528 "tx_pkts",
529 "tx_unicst_pkts",
530 "tx_multicst_pkts",
531 "tx_brdcst_pkts",
532 "tx_pause_pkts",
533 "tx_le_64_pkts",
534 "tx_65_to_127_pkts",
535 "tx_128_to_255_pkts",
536 "tx_256_to_511_pkts",
537 "tx_512_to_1023_pkts",
538 "tx_1024_to_15xx_pkts",
539 "tx_ge_15xx_pkts",
540 "tx_errors",
541 "tx_sgl_col_pkts",
542 "tx_mult_col_pkts",
543 "tx_ex_col_pkts",
544 "tx_late_col_pkts",
545 "tx_def_pkts",
546 "tx_ex_def_pkts",
547 "pm_trunc_bb_overflow",
548 "pm_discard_bb_overflow",
549 "pm_trunc_vfifo_full",
550 "pm_discard_vfifo_full",
551 "pm_trunc_qbb",
552 "pm_discard_qbb",
553 "pm_discard_mapping",
554 "rxdp_q_disabled_pkts",
555 "rxdp_di_dropped_pkts",
556 "rxdp_streaming_pkts",
557 "rxdp_hlb_fetch",
558 "rxdp_hlb_wait",
559 "vadapter_rx_unicast_packets",
560 "vadapter_rx_unicast_bytes",
561 "vadapter_rx_multicast_packets",
562 "vadapter_rx_multicast_bytes",
563 "vadapter_rx_broadcast_packets",
564 "vadapter_rx_broadcast_bytes",
565 "vadapter_rx_bad_packets",
566 "vadapter_rx_bad_bytes",
567 "vadapter_rx_overflow",
568 "vadapter_tx_unicast_packets",
569 "vadapter_tx_unicast_bytes",
570 "vadapter_tx_multicast_packets",
571 "vadapter_tx_multicast_bytes",
572 "vadapter_tx_broadcast_packets",
573 "vadapter_tx_broadcast_bytes",
574 "vadapter_tx_bad_packets",
575 "vadapter_tx_bad_bytes",
576 "vadapter_tx_overflow",
577 };
578 /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
579
580 __checkReturn const char *
efx_mac_stat_name(__in efx_nic_t * enp,__in unsigned int id)581 efx_mac_stat_name(
582 __in efx_nic_t *enp,
583 __in unsigned int id)
584 {
585 _NOTE(ARGUNUSED(enp))
586 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
587
588 EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
589 return (__efx_mac_stat_name[id]);
590 }
591
592 #endif /* EFSYS_OPT_NAMES */
593
594 __checkReturn efx_rc_t
efx_mac_stats_upload(__in efx_nic_t * enp,__in efsys_mem_t * esmp)595 efx_mac_stats_upload(
596 __in efx_nic_t *enp,
597 __in efsys_mem_t *esmp)
598 {
599 efx_port_t *epp = &(enp->en_port);
600 const efx_mac_ops_t *emop = epp->ep_emop;
601 efx_rc_t rc;
602
603 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
604 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
605 EFSYS_ASSERT(emop != NULL);
606
607 /*
608 * Don't assert !ep_mac_stats_pending, because the client might
609 * have failed to finalise statistics when previously stopping
610 * the port.
611 */
612 if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
613 goto fail1;
614
615 epp->ep_mac_stats_pending = B_TRUE;
616
617 return (0);
618
619 fail1:
620 EFSYS_PROBE1(fail1, efx_rc_t, rc);
621
622 return (rc);
623 }
624
625 __checkReturn efx_rc_t
efx_mac_stats_periodic(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__in uint16_t period_ms,__in boolean_t events)626 efx_mac_stats_periodic(
627 __in efx_nic_t *enp,
628 __in efsys_mem_t *esmp,
629 __in uint16_t period_ms,
630 __in boolean_t events)
631 {
632 efx_port_t *epp = &(enp->en_port);
633 const efx_mac_ops_t *emop = epp->ep_emop;
634 efx_rc_t rc;
635
636 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
637 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
638
639 EFSYS_ASSERT(emop != NULL);
640
641 if (emop->emo_stats_periodic == NULL) {
642 rc = EINVAL;
643 goto fail1;
644 }
645
646 if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
647 goto fail2;
648
649 return (0);
650
651 fail2:
652 EFSYS_PROBE(fail2);
653 fail1:
654 EFSYS_PROBE1(fail1, efx_rc_t, rc);
655
656 return (rc);
657 }
658
659
660 __checkReturn efx_rc_t
efx_mac_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_MAC_NSTATS)efsys_stat_t * essp,__inout_opt uint32_t * generationp)661 efx_mac_stats_update(
662 __in efx_nic_t *enp,
663 __in efsys_mem_t *esmp,
664 __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
665 __inout_opt uint32_t *generationp)
666 {
667 efx_port_t *epp = &(enp->en_port);
668 const efx_mac_ops_t *emop = epp->ep_emop;
669 efx_rc_t rc;
670
671 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
672 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
673 EFSYS_ASSERT(emop != NULL);
674
675 rc = emop->emo_stats_update(enp, esmp, essp, generationp);
676 if (rc == 0)
677 epp->ep_mac_stats_pending = B_FALSE;
678
679 return (rc);
680 }
681
682 #endif /* EFSYS_OPT_MAC_STATS */
683
684 __checkReturn efx_rc_t
efx_mac_select(__in efx_nic_t * enp)685 efx_mac_select(
686 __in efx_nic_t *enp)
687 {
688 efx_port_t *epp = &(enp->en_port);
689 efx_mac_type_t type = EFX_MAC_INVALID;
690 const efx_mac_ops_t *emop;
691 int rc = EINVAL;
692
693 switch (enp->en_family) {
694 #if EFSYS_OPT_SIENA
695 case EFX_FAMILY_SIENA:
696 emop = &__efx_siena_mac_ops;
697 type = EFX_MAC_SIENA;
698 break;
699 #endif /* EFSYS_OPT_SIENA */
700
701 #if EFSYS_OPT_HUNTINGTON
702 case EFX_FAMILY_HUNTINGTON:
703 emop = &__efx_ef10_mac_ops;
704 type = EFX_MAC_HUNTINGTON;
705 break;
706 #endif /* EFSYS_OPT_HUNTINGTON */
707
708 #if EFSYS_OPT_MEDFORD
709 case EFX_FAMILY_MEDFORD:
710 emop = &__efx_ef10_mac_ops;
711 type = EFX_MAC_MEDFORD;
712 break;
713 #endif /* EFSYS_OPT_MEDFORD */
714
715 default:
716 rc = EINVAL;
717 goto fail1;
718 }
719
720 EFSYS_ASSERT(type != EFX_MAC_INVALID);
721 EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
722 EFSYS_ASSERT(emop != NULL);
723
724 epp->ep_emop = emop;
725 epp->ep_mac_type = type;
726
727 return (0);
728
729 fail1:
730 EFSYS_PROBE1(fail1, efx_rc_t, rc);
731
732 return (rc);
733 }
734
735
736 #if EFSYS_OPT_SIENA
737
738 #define EFX_MAC_HASH_BITS (1 << 8)
739
740 /* Compute the multicast hash as used on Falcon and Siena. */
741 static void
742 siena_mac_multicast_hash_compute(
743 __in_ecount(6*count) uint8_t const *addrs,
744 __in int count,
745 __out efx_oword_t *hash_low,
746 __out efx_oword_t *hash_high)
747 {
748 uint32_t crc, index;
749 int i;
750
751 EFSYS_ASSERT(hash_low != NULL);
752 EFSYS_ASSERT(hash_high != NULL);
753
754 EFX_ZERO_OWORD(*hash_low);
755 EFX_ZERO_OWORD(*hash_high);
756
757 for (i = 0; i < count; i++) {
758 /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
759 crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
760 index = crc % EFX_MAC_HASH_BITS;
761 if (index < 128) {
762 EFX_SET_OWORD_BIT(*hash_low, index);
763 } else {
764 EFX_SET_OWORD_BIT(*hash_high, index - 128);
765 }
766
767 addrs += EFX_MAC_ADDR_LEN;
768 }
769 }
770
771 static __checkReturn efx_rc_t
siena_mac_multicast_list_set(__in efx_nic_t * enp)772 siena_mac_multicast_list_set(
773 __in efx_nic_t *enp)
774 {
775 efx_port_t *epp = &(enp->en_port);
776 const efx_mac_ops_t *emop = epp->ep_emop;
777 efx_oword_t old_hash[2];
778 efx_rc_t rc;
779
780 EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
781 EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
782
783 (void) memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
784
785 siena_mac_multicast_hash_compute(
786 epp->ep_mulcst_addr_list,
787 epp->ep_mulcst_addr_count,
788 &epp->ep_multicst_hash[0],
789 &epp->ep_multicst_hash[1]);
790
791 if ((rc = emop->emo_reconfigure(enp)) != 0)
792 goto fail1;
793
794 return (0);
795
796 fail1:
797 EFSYS_PROBE1(fail1, efx_rc_t, rc);
798
799 (void) memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
800
801 return (rc);
802 }
803
804 #endif /* EFSYS_OPT_SIENA */
805