1e948693eSPhilip Paeps /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4929c7febSAndrew Rybchenko * Copyright (c) 2007-2016 Solarflare Communications Inc.
53c838a9fSAndrew Rybchenko * All rights reserved.
6e948693eSPhilip Paeps *
7e948693eSPhilip Paeps * Redistribution and use in source and binary forms, with or without
83c838a9fSAndrew Rybchenko * modification, are permitted provided that the following conditions are met:
9e948693eSPhilip Paeps *
103c838a9fSAndrew Rybchenko * 1. Redistributions of source code must retain the above copyright notice,
113c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer.
123c838a9fSAndrew Rybchenko * 2. Redistributions in binary form must reproduce the above copyright notice,
133c838a9fSAndrew Rybchenko * this list of conditions and the following disclaimer in the documentation
143c838a9fSAndrew Rybchenko * and/or other materials provided with the distribution.
153c838a9fSAndrew Rybchenko *
163c838a9fSAndrew Rybchenko * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
173c838a9fSAndrew Rybchenko * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
183c838a9fSAndrew Rybchenko * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
193c838a9fSAndrew Rybchenko * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
203c838a9fSAndrew Rybchenko * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
213c838a9fSAndrew Rybchenko * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
223c838a9fSAndrew Rybchenko * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
233c838a9fSAndrew Rybchenko * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
243c838a9fSAndrew Rybchenko * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
253c838a9fSAndrew Rybchenko * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
263c838a9fSAndrew Rybchenko * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273c838a9fSAndrew Rybchenko *
283c838a9fSAndrew Rybchenko * The views and conclusions contained in the software and documentation are
293c838a9fSAndrew Rybchenko * those of the authors and should not be interpreted as representing official
303c838a9fSAndrew Rybchenko * policies, either expressed or implied, of the FreeBSD Project.
31e948693eSPhilip Paeps */
32e948693eSPhilip Paeps
335dee87d7SPhilip Paeps #include <sys/cdefs.h>
34e948693eSPhilip Paeps #include "efx.h"
35e948693eSPhilip Paeps #include "efx_impl.h"
36e948693eSPhilip Paeps
37e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
383c838a9fSAndrew Rybchenko
39460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
405cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set(
413c838a9fSAndrew Rybchenko __in efx_nic_t *enp);
423c838a9fSAndrew Rybchenko
43e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
443c838a9fSAndrew Rybchenko
45e948693eSPhilip Paeps #if EFSYS_OPT_SIENA
46ae346558SAndrew Rybchenko static const efx_mac_ops_t __efx_mac_siena_ops = {
47e948693eSPhilip Paeps siena_mac_poll, /* emo_poll */
48e948693eSPhilip Paeps siena_mac_up, /* emo_up */
493c838a9fSAndrew Rybchenko siena_mac_reconfigure, /* emo_addr_set */
5008c5af79SAndrew Rybchenko siena_mac_reconfigure, /* emo_pdu_set */
51d8484af2SAndrew Rybchenko siena_mac_pdu_get, /* emo_pdu_get */
52e948693eSPhilip Paeps siena_mac_reconfigure, /* emo_reconfigure */
535cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set, /* emo_multicast_list_set */
543c838a9fSAndrew Rybchenko NULL, /* emo_filter_set_default_rxq */
553c838a9fSAndrew Rybchenko NULL, /* emo_filter_default_rxq_clear */
56e948693eSPhilip Paeps #if EFSYS_OPT_LOOPBACK
57e948693eSPhilip Paeps siena_mac_loopback_set, /* emo_loopback_set */
58e948693eSPhilip Paeps #endif /* EFSYS_OPT_LOOPBACK */
59e948693eSPhilip Paeps #if EFSYS_OPT_MAC_STATS
6058a72cb2SAndrew Rybchenko siena_mac_stats_get_mask, /* emo_stats_get_mask */
6131e518b4SAndrew Rybchenko efx_mcdi_mac_stats_clear, /* emo_stats_clear */
623c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_upload, /* emo_stats_upload */
633c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
64e948693eSPhilip Paeps siena_mac_stats_update /* emo_stats_update */
65e948693eSPhilip Paeps #endif /* EFSYS_OPT_MAC_STATS */
66e948693eSPhilip Paeps };
67e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */
68e948693eSPhilip Paeps
69cbc3f94fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
70ae346558SAndrew Rybchenko static const efx_mac_ops_t __efx_mac_ef10_ops = {
71c15d6d21SAndrew Rybchenko ef10_mac_poll, /* emo_poll */
72c15d6d21SAndrew Rybchenko ef10_mac_up, /* emo_up */
73c15d6d21SAndrew Rybchenko ef10_mac_addr_set, /* emo_addr_set */
7408c5af79SAndrew Rybchenko ef10_mac_pdu_set, /* emo_pdu_set */
75d8484af2SAndrew Rybchenko ef10_mac_pdu_get, /* emo_pdu_get */
76c15d6d21SAndrew Rybchenko ef10_mac_reconfigure, /* emo_reconfigure */
77c15d6d21SAndrew Rybchenko ef10_mac_multicast_list_set, /* emo_multicast_list_set */
78c15d6d21SAndrew Rybchenko ef10_mac_filter_default_rxq_set, /* emo_filter_default_rxq_set */
79c15d6d21SAndrew Rybchenko ef10_mac_filter_default_rxq_clear,
803c838a9fSAndrew Rybchenko /* emo_filter_default_rxq_clear */
813c838a9fSAndrew Rybchenko #if EFSYS_OPT_LOOPBACK
82c15d6d21SAndrew Rybchenko ef10_mac_loopback_set, /* emo_loopback_set */
833c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_LOOPBACK */
843c838a9fSAndrew Rybchenko #if EFSYS_OPT_MAC_STATS
8558a72cb2SAndrew Rybchenko ef10_mac_stats_get_mask, /* emo_stats_get_mask */
8631e518b4SAndrew Rybchenko efx_mcdi_mac_stats_clear, /* emo_stats_clear */
873c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_upload, /* emo_stats_upload */
883c838a9fSAndrew Rybchenko efx_mcdi_mac_stats_periodic, /* emo_stats_periodic */
89c15d6d21SAndrew Rybchenko ef10_mac_stats_update /* emo_stats_update */
903c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_MAC_STATS */
913c838a9fSAndrew Rybchenko };
92cbc3f94fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
933c838a9fSAndrew Rybchenko
94460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_pdu_set(__in efx_nic_t * enp,__in size_t pdu)95e948693eSPhilip Paeps efx_mac_pdu_set(
96e948693eSPhilip Paeps __in efx_nic_t *enp,
97e948693eSPhilip Paeps __in size_t pdu)
98e948693eSPhilip Paeps {
99e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
100ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
101e948693eSPhilip Paeps uint32_t old_pdu;
102460cb568SAndrew Rybchenko efx_rc_t rc;
103e948693eSPhilip Paeps
104e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
105e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
106e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
107e948693eSPhilip Paeps
108e948693eSPhilip Paeps if (pdu < EFX_MAC_PDU_MIN) {
109e948693eSPhilip Paeps rc = EINVAL;
110e948693eSPhilip Paeps goto fail1;
111e948693eSPhilip Paeps }
112e948693eSPhilip Paeps
113e948693eSPhilip Paeps if (pdu > EFX_MAC_PDU_MAX) {
114e948693eSPhilip Paeps rc = EINVAL;
115e948693eSPhilip Paeps goto fail2;
116e948693eSPhilip Paeps }
117e948693eSPhilip Paeps
118e948693eSPhilip Paeps old_pdu = epp->ep_mac_pdu;
119e948693eSPhilip Paeps epp->ep_mac_pdu = (uint32_t)pdu;
12008c5af79SAndrew Rybchenko if ((rc = emop->emo_pdu_set(enp)) != 0)
121e948693eSPhilip Paeps goto fail3;
122e948693eSPhilip Paeps
123e948693eSPhilip Paeps return (0);
124e948693eSPhilip Paeps
125e948693eSPhilip Paeps fail3:
126e948693eSPhilip Paeps EFSYS_PROBE(fail3);
127e948693eSPhilip Paeps
128e948693eSPhilip Paeps epp->ep_mac_pdu = old_pdu;
129e948693eSPhilip Paeps
130e948693eSPhilip Paeps fail2:
131e948693eSPhilip Paeps EFSYS_PROBE(fail2);
132e948693eSPhilip Paeps fail1:
133460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
134e948693eSPhilip Paeps
135e948693eSPhilip Paeps return (rc);
136e948693eSPhilip Paeps }
137e948693eSPhilip Paeps
138460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_pdu_get(__in efx_nic_t * enp,__out size_t * pdu)139d8484af2SAndrew Rybchenko efx_mac_pdu_get(
140d8484af2SAndrew Rybchenko __in efx_nic_t *enp,
141d8484af2SAndrew Rybchenko __out size_t *pdu)
142d8484af2SAndrew Rybchenko {
143d8484af2SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
144d8484af2SAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
145d8484af2SAndrew Rybchenko efx_rc_t rc;
146d8484af2SAndrew Rybchenko
147d8484af2SAndrew Rybchenko if ((rc = emop->emo_pdu_get(enp, pdu)) != 0)
148d8484af2SAndrew Rybchenko goto fail1;
149d8484af2SAndrew Rybchenko
150d8484af2SAndrew Rybchenko return (0);
151d8484af2SAndrew Rybchenko
152d8484af2SAndrew Rybchenko fail1:
153d8484af2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
154d8484af2SAndrew Rybchenko
155d8484af2SAndrew Rybchenko return (rc);
156d8484af2SAndrew Rybchenko }
157d8484af2SAndrew Rybchenko
158d8484af2SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_addr_set(__in efx_nic_t * enp,__in uint8_t * addr)159e948693eSPhilip Paeps efx_mac_addr_set(
160e948693eSPhilip Paeps __in efx_nic_t *enp,
161e948693eSPhilip Paeps __in uint8_t *addr)
162e948693eSPhilip Paeps {
163e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
164ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
165e948693eSPhilip Paeps uint8_t old_addr[6];
166e948693eSPhilip Paeps uint32_t oui;
167460cb568SAndrew Rybchenko efx_rc_t rc;
168e948693eSPhilip Paeps
169e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
170e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
171e948693eSPhilip Paeps
1723c838a9fSAndrew Rybchenko if (EFX_MAC_ADDR_IS_MULTICAST(addr)) {
173e948693eSPhilip Paeps rc = EINVAL;
174e948693eSPhilip Paeps goto fail1;
175e948693eSPhilip Paeps }
176e948693eSPhilip Paeps
177e948693eSPhilip Paeps oui = addr[0] << 16 | addr[1] << 8 | addr[2];
178e948693eSPhilip Paeps if (oui == 0x000000) {
179e948693eSPhilip Paeps rc = EINVAL;
180e948693eSPhilip Paeps goto fail2;
181e948693eSPhilip Paeps }
182e948693eSPhilip Paeps
183e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(old_addr, epp->ep_mac_addr);
184e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(epp->ep_mac_addr, addr);
1853c838a9fSAndrew Rybchenko if ((rc = emop->emo_addr_set(enp)) != 0)
186e948693eSPhilip Paeps goto fail3;
187e948693eSPhilip Paeps
188e948693eSPhilip Paeps return (0);
189e948693eSPhilip Paeps
190e948693eSPhilip Paeps fail3:
191e948693eSPhilip Paeps EFSYS_PROBE(fail3);
192e948693eSPhilip Paeps
193e948693eSPhilip Paeps EFX_MAC_ADDR_COPY(epp->ep_mac_addr, old_addr);
194e948693eSPhilip Paeps
195e948693eSPhilip Paeps fail2:
196e948693eSPhilip Paeps EFSYS_PROBE(fail2);
197e948693eSPhilip Paeps fail1:
198460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
199e948693eSPhilip Paeps
200e948693eSPhilip Paeps return (rc);
201e948693eSPhilip Paeps }
202e948693eSPhilip Paeps
203460cb568SAndrew Rybchenko __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)204e948693eSPhilip Paeps efx_mac_filter_set(
205e948693eSPhilip Paeps __in efx_nic_t *enp,
2063c838a9fSAndrew Rybchenko __in boolean_t all_unicst,
2073c838a9fSAndrew Rybchenko __in boolean_t mulcst,
2083c838a9fSAndrew Rybchenko __in boolean_t all_mulcst,
209e948693eSPhilip Paeps __in boolean_t brdcst)
210e948693eSPhilip Paeps {
211e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
212ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
2133c838a9fSAndrew Rybchenko boolean_t old_all_unicst;
2143c838a9fSAndrew Rybchenko boolean_t old_mulcst;
2153c838a9fSAndrew Rybchenko boolean_t old_all_mulcst;
216e948693eSPhilip Paeps boolean_t old_brdcst;
217460cb568SAndrew Rybchenko efx_rc_t rc;
218e948693eSPhilip Paeps
219e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
220e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
221e948693eSPhilip Paeps
2223c838a9fSAndrew Rybchenko old_all_unicst = epp->ep_all_unicst;
2233c838a9fSAndrew Rybchenko old_mulcst = epp->ep_mulcst;
2243c838a9fSAndrew Rybchenko old_all_mulcst = epp->ep_all_mulcst;
2253c838a9fSAndrew Rybchenko old_brdcst = epp->ep_brdcst;
226e948693eSPhilip Paeps
2273c838a9fSAndrew Rybchenko epp->ep_all_unicst = all_unicst;
2283c838a9fSAndrew Rybchenko epp->ep_mulcst = mulcst;
2293c838a9fSAndrew Rybchenko epp->ep_all_mulcst = all_mulcst;
230e948693eSPhilip Paeps epp->ep_brdcst = brdcst;
231e948693eSPhilip Paeps
232e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0)
233e948693eSPhilip Paeps goto fail1;
234e948693eSPhilip Paeps
235e948693eSPhilip Paeps return (0);
236e948693eSPhilip Paeps
237e948693eSPhilip Paeps fail1:
238460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
239e948693eSPhilip Paeps
2403c838a9fSAndrew Rybchenko epp->ep_all_unicst = old_all_unicst;
2413c838a9fSAndrew Rybchenko epp->ep_mulcst = old_mulcst;
2423c838a9fSAndrew Rybchenko epp->ep_all_mulcst = old_all_mulcst;
243e948693eSPhilip Paeps epp->ep_brdcst = old_brdcst;
244e948693eSPhilip Paeps
245e948693eSPhilip Paeps return (rc);
246e948693eSPhilip Paeps }
247e948693eSPhilip Paeps
248460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_drain(__in efx_nic_t * enp,__in boolean_t enabled)249e948693eSPhilip Paeps efx_mac_drain(
250e948693eSPhilip Paeps __in efx_nic_t *enp,
251e948693eSPhilip Paeps __in boolean_t enabled)
252e948693eSPhilip Paeps {
253e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
254ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
255460cb568SAndrew Rybchenko efx_rc_t rc;
256e948693eSPhilip Paeps
257e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
258e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
259e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
260e948693eSPhilip Paeps
261e948693eSPhilip Paeps if (epp->ep_mac_drain == enabled)
262e948693eSPhilip Paeps return (0);
263e948693eSPhilip Paeps
264e948693eSPhilip Paeps epp->ep_mac_drain = enabled;
265e948693eSPhilip Paeps
266e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0)
2670c909247SAndrew Rybchenko goto fail1;
268e948693eSPhilip Paeps
269e948693eSPhilip Paeps return (0);
270e948693eSPhilip Paeps
271e948693eSPhilip Paeps fail1:
272460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
273e948693eSPhilip Paeps
274e948693eSPhilip Paeps return (rc);
275e948693eSPhilip Paeps }
276e948693eSPhilip Paeps
277460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_up(__in efx_nic_t * enp,__out boolean_t * mac_upp)278e948693eSPhilip Paeps efx_mac_up(
279e948693eSPhilip Paeps __in efx_nic_t *enp,
280e948693eSPhilip Paeps __out boolean_t *mac_upp)
281e948693eSPhilip Paeps {
282e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
283ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
284460cb568SAndrew Rybchenko efx_rc_t rc;
285e948693eSPhilip Paeps
286e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
287e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
288e948693eSPhilip Paeps
289e948693eSPhilip Paeps if ((rc = emop->emo_up(enp, mac_upp)) != 0)
290e948693eSPhilip Paeps goto fail1;
291e948693eSPhilip Paeps
292e948693eSPhilip Paeps return (0);
293e948693eSPhilip Paeps
294e948693eSPhilip Paeps fail1:
295460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
296e948693eSPhilip Paeps
297e948693eSPhilip Paeps return (rc);
298e948693eSPhilip Paeps }
299e948693eSPhilip Paeps
300460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_fcntl_set(__in efx_nic_t * enp,__in unsigned int fcntl,__in boolean_t autoneg)301e948693eSPhilip Paeps efx_mac_fcntl_set(
302e948693eSPhilip Paeps __in efx_nic_t *enp,
303e948693eSPhilip Paeps __in unsigned int fcntl,
304e948693eSPhilip Paeps __in boolean_t autoneg)
305e948693eSPhilip Paeps {
306e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
307ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
308ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
309e948693eSPhilip Paeps unsigned int old_fcntl;
310e948693eSPhilip Paeps boolean_t old_autoneg;
311e948693eSPhilip Paeps unsigned int old_adv_cap;
312460cb568SAndrew Rybchenko efx_rc_t rc;
313e948693eSPhilip Paeps
314e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
315e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
316e948693eSPhilip Paeps
317e948693eSPhilip Paeps if ((fcntl & ~(EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE)) != 0) {
318e948693eSPhilip Paeps rc = EINVAL;
319e948693eSPhilip Paeps goto fail1;
320e948693eSPhilip Paeps }
321e948693eSPhilip Paeps
322e948693eSPhilip Paeps /*
3233c838a9fSAndrew Rybchenko * Ignore a request to set flow control auto-negotiation
324e948693eSPhilip Paeps * if the PHY doesn't support it.
325e948693eSPhilip Paeps */
326e948693eSPhilip Paeps if (~epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN))
327e948693eSPhilip Paeps autoneg = B_FALSE;
328e948693eSPhilip Paeps
329e948693eSPhilip Paeps old_fcntl = epp->ep_fcntl;
3303c838a9fSAndrew Rybchenko old_autoneg = epp->ep_fcntl_autoneg;
331e948693eSPhilip Paeps old_adv_cap = epp->ep_adv_cap_mask;
332e948693eSPhilip Paeps
333e948693eSPhilip Paeps epp->ep_fcntl = fcntl;
334e948693eSPhilip Paeps epp->ep_fcntl_autoneg = autoneg;
335e948693eSPhilip Paeps
336e948693eSPhilip Paeps /*
3373c838a9fSAndrew Rybchenko * Always encode the flow control settings in the advertised
3383c838a9fSAndrew Rybchenko * capabilities even if we are not trying to auto-negotiate
3393c838a9fSAndrew Rybchenko * them and reconfigure both the PHY and the MAC.
340e948693eSPhilip Paeps */
341e948693eSPhilip Paeps if (fcntl & EFX_FCNTL_RESPOND)
342e948693eSPhilip Paeps epp->ep_adv_cap_mask |= (1 << EFX_PHY_CAP_PAUSE |
343e948693eSPhilip Paeps 1 << EFX_PHY_CAP_ASYM);
344e948693eSPhilip Paeps else
345e948693eSPhilip Paeps epp->ep_adv_cap_mask &= ~(1 << EFX_PHY_CAP_PAUSE |
346e948693eSPhilip Paeps 1 << EFX_PHY_CAP_ASYM);
347e948693eSPhilip Paeps
348e948693eSPhilip Paeps if (fcntl & EFX_FCNTL_GENERATE)
349e948693eSPhilip Paeps epp->ep_adv_cap_mask ^= (1 << EFX_PHY_CAP_ASYM);
350e948693eSPhilip Paeps
351e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0)
352e948693eSPhilip Paeps goto fail2;
353e948693eSPhilip Paeps
354e948693eSPhilip Paeps if ((rc = emop->emo_reconfigure(enp)) != 0)
3553c838a9fSAndrew Rybchenko goto fail3;
356e948693eSPhilip Paeps
357e948693eSPhilip Paeps return (0);
358e948693eSPhilip Paeps
3593c838a9fSAndrew Rybchenko fail3:
3603c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
3613c838a9fSAndrew Rybchenko
362e948693eSPhilip Paeps fail2:
363e948693eSPhilip Paeps EFSYS_PROBE(fail2);
364e948693eSPhilip Paeps
365e948693eSPhilip Paeps epp->ep_fcntl = old_fcntl;
366e948693eSPhilip Paeps epp->ep_fcntl_autoneg = old_autoneg;
367e948693eSPhilip Paeps epp->ep_adv_cap_mask = old_adv_cap;
368e948693eSPhilip Paeps
369e948693eSPhilip Paeps fail1:
370460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
371e948693eSPhilip Paeps
372e948693eSPhilip Paeps return (rc);
373e948693eSPhilip Paeps }
374e948693eSPhilip Paeps
375e948693eSPhilip Paeps void
efx_mac_fcntl_get(__in efx_nic_t * enp,__out unsigned int * fcntl_wantedp,__out unsigned int * fcntl_linkp)376e948693eSPhilip Paeps efx_mac_fcntl_get(
377e948693eSPhilip Paeps __in efx_nic_t *enp,
378e948693eSPhilip Paeps __out unsigned int *fcntl_wantedp,
379e948693eSPhilip Paeps __out unsigned int *fcntl_linkp)
380e948693eSPhilip Paeps {
381e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
3823c838a9fSAndrew Rybchenko unsigned int wanted = 0;
383e948693eSPhilip Paeps
384e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
385e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
386e948693eSPhilip Paeps
387e948693eSPhilip Paeps /*
3883c838a9fSAndrew Rybchenko * Decode the requested flow control settings from the PHY
3893c838a9fSAndrew Rybchenko * advertised capabilities.
390e948693eSPhilip Paeps */
391e948693eSPhilip Paeps if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_PAUSE))
392e948693eSPhilip Paeps wanted = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
393e948693eSPhilip Paeps if (epp->ep_adv_cap_mask & (1 << EFX_PHY_CAP_ASYM))
394e948693eSPhilip Paeps wanted ^= EFX_FCNTL_GENERATE;
395e948693eSPhilip Paeps
396e948693eSPhilip Paeps *fcntl_linkp = epp->ep_fcntl;
397e948693eSPhilip Paeps *fcntl_wantedp = wanted;
398e948693eSPhilip Paeps }
399e948693eSPhilip Paeps
400460cb568SAndrew Rybchenko __checkReturn efx_rc_t
4013c838a9fSAndrew Rybchenko efx_mac_multicast_list_set(
4023c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
4033c838a9fSAndrew Rybchenko __in_ecount(6*count) uint8_t const *addrs,
4043c838a9fSAndrew Rybchenko __in int count)
4053c838a9fSAndrew Rybchenko {
4063c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
407ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
4083c838a9fSAndrew Rybchenko uint8_t *old_mulcst_addr_list = NULL;
4093c838a9fSAndrew Rybchenko uint32_t old_mulcst_addr_count;
410460cb568SAndrew Rybchenko efx_rc_t rc;
4113c838a9fSAndrew Rybchenko
4123c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4133c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
4143c838a9fSAndrew Rybchenko
4153c838a9fSAndrew Rybchenko if (count > EFX_MAC_MULTICAST_LIST_MAX) {
4163c838a9fSAndrew Rybchenko rc = EINVAL;
4173c838a9fSAndrew Rybchenko goto fail1;
4183c838a9fSAndrew Rybchenko }
4193c838a9fSAndrew Rybchenko
4203c838a9fSAndrew Rybchenko old_mulcst_addr_count = epp->ep_mulcst_addr_count;
4213c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) {
4223c838a9fSAndrew Rybchenko /* Allocate memory to store old list (instead of using stack) */
4233c838a9fSAndrew Rybchenko EFSYS_KMEM_ALLOC(enp->en_esip,
4243c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
4253c838a9fSAndrew Rybchenko old_mulcst_addr_list);
4263c838a9fSAndrew Rybchenko if (old_mulcst_addr_list == NULL) {
4273c838a9fSAndrew Rybchenko rc = ENOMEM;
4283c838a9fSAndrew Rybchenko goto fail2;
4293c838a9fSAndrew Rybchenko }
4303c838a9fSAndrew Rybchenko
4313c838a9fSAndrew Rybchenko /* Save the old list in case we need to rollback */
4323c838a9fSAndrew Rybchenko memcpy(old_mulcst_addr_list, epp->ep_mulcst_addr_list,
4333c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
4343c838a9fSAndrew Rybchenko }
4353c838a9fSAndrew Rybchenko
4363c838a9fSAndrew Rybchenko /* Store the new list */
4373c838a9fSAndrew Rybchenko memcpy(epp->ep_mulcst_addr_list, addrs,
4383c838a9fSAndrew Rybchenko count * EFX_MAC_ADDR_LEN);
4393c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count = count;
4403c838a9fSAndrew Rybchenko
4413c838a9fSAndrew Rybchenko if ((rc = emop->emo_multicast_list_set(enp)) != 0)
4423c838a9fSAndrew Rybchenko goto fail3;
4433c838a9fSAndrew Rybchenko
4443c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) {
4453c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip,
4463c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
4473c838a9fSAndrew Rybchenko old_mulcst_addr_list);
4483c838a9fSAndrew Rybchenko }
4493c838a9fSAndrew Rybchenko
4503c838a9fSAndrew Rybchenko return (0);
4513c838a9fSAndrew Rybchenko
4523c838a9fSAndrew Rybchenko fail3:
4533c838a9fSAndrew Rybchenko EFSYS_PROBE(fail3);
4543c838a9fSAndrew Rybchenko
4553c838a9fSAndrew Rybchenko /* Restore original list on failure */
4563c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count = old_mulcst_addr_count;
4573c838a9fSAndrew Rybchenko if (old_mulcst_addr_count > 0) {
4583c838a9fSAndrew Rybchenko memcpy(epp->ep_mulcst_addr_list, old_mulcst_addr_list,
4593c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN);
4603c838a9fSAndrew Rybchenko
4613c838a9fSAndrew Rybchenko EFSYS_KMEM_FREE(enp->en_esip,
4623c838a9fSAndrew Rybchenko old_mulcst_addr_count * EFX_MAC_ADDR_LEN,
4633c838a9fSAndrew Rybchenko old_mulcst_addr_list);
4643c838a9fSAndrew Rybchenko }
4653c838a9fSAndrew Rybchenko
4663c838a9fSAndrew Rybchenko fail2:
4673c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
4683c838a9fSAndrew Rybchenko
4693c838a9fSAndrew Rybchenko fail1:
470460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4713c838a9fSAndrew Rybchenko
4723c838a9fSAndrew Rybchenko return (rc);
4733c838a9fSAndrew Rybchenko
4743c838a9fSAndrew Rybchenko }
4753c838a9fSAndrew Rybchenko
476460cb568SAndrew Rybchenko __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)4773c838a9fSAndrew Rybchenko efx_mac_filter_default_rxq_set(
4783c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
4793c838a9fSAndrew Rybchenko __in efx_rxq_t *erp,
4803c838a9fSAndrew Rybchenko __in boolean_t using_rss)
4813c838a9fSAndrew Rybchenko {
4823c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
483ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
484460cb568SAndrew Rybchenko efx_rc_t rc;
4853c838a9fSAndrew Rybchenko
4863c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4873c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
4883c838a9fSAndrew Rybchenko
4893c838a9fSAndrew Rybchenko if (emop->emo_filter_default_rxq_set != NULL) {
4903c838a9fSAndrew Rybchenko rc = emop->emo_filter_default_rxq_set(enp, erp, using_rss);
4913c838a9fSAndrew Rybchenko if (rc != 0)
4923c838a9fSAndrew Rybchenko goto fail1;
4933c838a9fSAndrew Rybchenko }
4943c838a9fSAndrew Rybchenko
4953c838a9fSAndrew Rybchenko return (0);
4963c838a9fSAndrew Rybchenko
4973c838a9fSAndrew Rybchenko fail1:
498460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
4993c838a9fSAndrew Rybchenko
5003c838a9fSAndrew Rybchenko return (rc);
5013c838a9fSAndrew Rybchenko }
5023c838a9fSAndrew Rybchenko
5033c838a9fSAndrew Rybchenko void
efx_mac_filter_default_rxq_clear(__in efx_nic_t * enp)5043c838a9fSAndrew Rybchenko efx_mac_filter_default_rxq_clear(
5053c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
5063c838a9fSAndrew Rybchenko {
5073c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
508ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
5093c838a9fSAndrew Rybchenko
5103c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5113c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
5123c838a9fSAndrew Rybchenko
5133c838a9fSAndrew Rybchenko if (emop->emo_filter_default_rxq_clear != NULL)
5143c838a9fSAndrew Rybchenko emop->emo_filter_default_rxq_clear(enp);
5153c838a9fSAndrew Rybchenko }
5163c838a9fSAndrew Rybchenko
517e948693eSPhilip Paeps #if EFSYS_OPT_MAC_STATS
518e948693eSPhilip Paeps
519e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
520e948693eSPhilip Paeps
521c27e7228SAndrew Rybchenko /* START MKCONFIG GENERATED EfxMacStatNamesBlock 1a45a82fcfb30c1b */
522a260bd77SAndrew Rybchenko static const char * const __efx_mac_stat_name[] = {
523e948693eSPhilip Paeps "rx_octets",
524e948693eSPhilip Paeps "rx_pkts",
525e948693eSPhilip Paeps "rx_unicst_pkts",
526e948693eSPhilip Paeps "rx_multicst_pkts",
527e948693eSPhilip Paeps "rx_brdcst_pkts",
528e948693eSPhilip Paeps "rx_pause_pkts",
529e948693eSPhilip Paeps "rx_le_64_pkts",
530e948693eSPhilip Paeps "rx_65_to_127_pkts",
531e948693eSPhilip Paeps "rx_128_to_255_pkts",
532e948693eSPhilip Paeps "rx_256_to_511_pkts",
533e948693eSPhilip Paeps "rx_512_to_1023_pkts",
534e948693eSPhilip Paeps "rx_1024_to_15xx_pkts",
535e948693eSPhilip Paeps "rx_ge_15xx_pkts",
536e948693eSPhilip Paeps "rx_errors",
537e948693eSPhilip Paeps "rx_fcs_errors",
538e948693eSPhilip Paeps "rx_drop_events",
539e948693eSPhilip Paeps "rx_false_carrier_errors",
540e948693eSPhilip Paeps "rx_symbol_errors",
541e948693eSPhilip Paeps "rx_align_errors",
542e948693eSPhilip Paeps "rx_internal_errors",
543e948693eSPhilip Paeps "rx_jabber_pkts",
544e948693eSPhilip Paeps "rx_lane0_char_err",
545e948693eSPhilip Paeps "rx_lane1_char_err",
546e948693eSPhilip Paeps "rx_lane2_char_err",
547e948693eSPhilip Paeps "rx_lane3_char_err",
548e948693eSPhilip Paeps "rx_lane0_disp_err",
549e948693eSPhilip Paeps "rx_lane1_disp_err",
550e948693eSPhilip Paeps "rx_lane2_disp_err",
551e948693eSPhilip Paeps "rx_lane3_disp_err",
552e948693eSPhilip Paeps "rx_match_fault",
553e948693eSPhilip Paeps "rx_nodesc_drop_cnt",
554e948693eSPhilip Paeps "tx_octets",
555e948693eSPhilip Paeps "tx_pkts",
556e948693eSPhilip Paeps "tx_unicst_pkts",
557e948693eSPhilip Paeps "tx_multicst_pkts",
558e948693eSPhilip Paeps "tx_brdcst_pkts",
559e948693eSPhilip Paeps "tx_pause_pkts",
560e948693eSPhilip Paeps "tx_le_64_pkts",
561e948693eSPhilip Paeps "tx_65_to_127_pkts",
562e948693eSPhilip Paeps "tx_128_to_255_pkts",
563e948693eSPhilip Paeps "tx_256_to_511_pkts",
564e948693eSPhilip Paeps "tx_512_to_1023_pkts",
565e948693eSPhilip Paeps "tx_1024_to_15xx_pkts",
566e948693eSPhilip Paeps "tx_ge_15xx_pkts",
567e948693eSPhilip Paeps "tx_errors",
568e948693eSPhilip Paeps "tx_sgl_col_pkts",
569e948693eSPhilip Paeps "tx_mult_col_pkts",
570e948693eSPhilip Paeps "tx_ex_col_pkts",
571e948693eSPhilip Paeps "tx_late_col_pkts",
572e948693eSPhilip Paeps "tx_def_pkts",
573e948693eSPhilip Paeps "tx_ex_def_pkts",
5743c838a9fSAndrew Rybchenko "pm_trunc_bb_overflow",
5753c838a9fSAndrew Rybchenko "pm_discard_bb_overflow",
5763c838a9fSAndrew Rybchenko "pm_trunc_vfifo_full",
5773c838a9fSAndrew Rybchenko "pm_discard_vfifo_full",
5783c838a9fSAndrew Rybchenko "pm_trunc_qbb",
5793c838a9fSAndrew Rybchenko "pm_discard_qbb",
5803c838a9fSAndrew Rybchenko "pm_discard_mapping",
5813c838a9fSAndrew Rybchenko "rxdp_q_disabled_pkts",
5823c838a9fSAndrew Rybchenko "rxdp_di_dropped_pkts",
5833c838a9fSAndrew Rybchenko "rxdp_streaming_pkts",
5843c838a9fSAndrew Rybchenko "rxdp_hlb_fetch",
5853c838a9fSAndrew Rybchenko "rxdp_hlb_wait",
5863c838a9fSAndrew Rybchenko "vadapter_rx_unicast_packets",
5873c838a9fSAndrew Rybchenko "vadapter_rx_unicast_bytes",
5883c838a9fSAndrew Rybchenko "vadapter_rx_multicast_packets",
5893c838a9fSAndrew Rybchenko "vadapter_rx_multicast_bytes",
5903c838a9fSAndrew Rybchenko "vadapter_rx_broadcast_packets",
5913c838a9fSAndrew Rybchenko "vadapter_rx_broadcast_bytes",
5923c838a9fSAndrew Rybchenko "vadapter_rx_bad_packets",
5933c838a9fSAndrew Rybchenko "vadapter_rx_bad_bytes",
5943c838a9fSAndrew Rybchenko "vadapter_rx_overflow",
5953c838a9fSAndrew Rybchenko "vadapter_tx_unicast_packets",
5963c838a9fSAndrew Rybchenko "vadapter_tx_unicast_bytes",
5973c838a9fSAndrew Rybchenko "vadapter_tx_multicast_packets",
5983c838a9fSAndrew Rybchenko "vadapter_tx_multicast_bytes",
5993c838a9fSAndrew Rybchenko "vadapter_tx_broadcast_packets",
6003c838a9fSAndrew Rybchenko "vadapter_tx_broadcast_bytes",
6013c838a9fSAndrew Rybchenko "vadapter_tx_bad_packets",
6023c838a9fSAndrew Rybchenko "vadapter_tx_bad_bytes",
6033c838a9fSAndrew Rybchenko "vadapter_tx_overflow",
60479300430SAndrew Rybchenko "fec_uncorrected_errors",
60579300430SAndrew Rybchenko "fec_corrected_errors",
60679300430SAndrew Rybchenko "fec_corrected_symbols_lane0",
60779300430SAndrew Rybchenko "fec_corrected_symbols_lane1",
60879300430SAndrew Rybchenko "fec_corrected_symbols_lane2",
60979300430SAndrew Rybchenko "fec_corrected_symbols_lane3",
6102fdc432cSAndrew Rybchenko "ctpio_vi_busy_fallback",
6112fdc432cSAndrew Rybchenko "ctpio_long_write_success",
6122fdc432cSAndrew Rybchenko "ctpio_missing_dbell_fail",
6132fdc432cSAndrew Rybchenko "ctpio_overflow_fail",
6142fdc432cSAndrew Rybchenko "ctpio_underflow_fail",
6152fdc432cSAndrew Rybchenko "ctpio_timeout_fail",
6162fdc432cSAndrew Rybchenko "ctpio_noncontig_wr_fail",
6172fdc432cSAndrew Rybchenko "ctpio_frm_clobber_fail",
6182fdc432cSAndrew Rybchenko "ctpio_invalid_wr_fail",
6192fdc432cSAndrew Rybchenko "ctpio_vi_clobber_fallback",
6202fdc432cSAndrew Rybchenko "ctpio_unqualified_fallback",
6212fdc432cSAndrew Rybchenko "ctpio_runt_fallback",
6222fdc432cSAndrew Rybchenko "ctpio_success",
6232fdc432cSAndrew Rybchenko "ctpio_fallback",
6242fdc432cSAndrew Rybchenko "ctpio_poison",
6252fdc432cSAndrew Rybchenko "ctpio_erase",
626c27e7228SAndrew Rybchenko "rxdp_scatter_disabled_trunc",
627c27e7228SAndrew Rybchenko "rxdp_hlb_idle",
628c27e7228SAndrew Rybchenko "rxdp_hlb_timeout",
629e948693eSPhilip Paeps };
630e948693eSPhilip Paeps /* END MKCONFIG GENERATED EfxMacStatNamesBlock */
631e948693eSPhilip Paeps
6323c838a9fSAndrew Rybchenko __checkReturn const char *
efx_mac_stat_name(__in efx_nic_t * enp,__in unsigned int id)633e948693eSPhilip Paeps efx_mac_stat_name(
634e948693eSPhilip Paeps __in efx_nic_t *enp,
635e948693eSPhilip Paeps __in unsigned int id)
636e948693eSPhilip Paeps {
637e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp))
638e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
639e948693eSPhilip Paeps
640e948693eSPhilip Paeps EFSYS_ASSERT3U(id, <, EFX_MAC_NSTATS);
641e948693eSPhilip Paeps return (__efx_mac_stat_name[id]);
642e948693eSPhilip Paeps }
643e948693eSPhilip Paeps
6443c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_NAMES */
645e948693eSPhilip Paeps
64658a72cb2SAndrew Rybchenko static efx_rc_t
efx_mac_stats_mask_add_range(__inout_bcount (mask_size)uint32_t * maskp,__in size_t mask_size,__in const struct efx_mac_stats_range * rngp)64758a72cb2SAndrew Rybchenko efx_mac_stats_mask_add_range(
64858a72cb2SAndrew Rybchenko __inout_bcount(mask_size) uint32_t *maskp,
64958a72cb2SAndrew Rybchenko __in size_t mask_size,
65058a72cb2SAndrew Rybchenko __in const struct efx_mac_stats_range *rngp)
65158a72cb2SAndrew Rybchenko {
65258a72cb2SAndrew Rybchenko unsigned int mask_npages = mask_size / sizeof (*maskp);
65358a72cb2SAndrew Rybchenko unsigned int el;
65458a72cb2SAndrew Rybchenko unsigned int el_min;
65558a72cb2SAndrew Rybchenko unsigned int el_max;
65658a72cb2SAndrew Rybchenko unsigned int low;
65758a72cb2SAndrew Rybchenko unsigned int high;
65858a72cb2SAndrew Rybchenko unsigned int width;
65958a72cb2SAndrew Rybchenko efx_rc_t rc;
66058a72cb2SAndrew Rybchenko
66158a72cb2SAndrew Rybchenko if ((mask_npages * EFX_MAC_STATS_MASK_BITS_PER_PAGE) <=
66258a72cb2SAndrew Rybchenko (unsigned int)rngp->last) {
66358a72cb2SAndrew Rybchenko rc = EINVAL;
66458a72cb2SAndrew Rybchenko goto fail1;
66558a72cb2SAndrew Rybchenko }
66658a72cb2SAndrew Rybchenko
66758a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(rngp->first, <=, rngp->last);
66858a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(rngp->last, <, EFX_MAC_NSTATS);
66958a72cb2SAndrew Rybchenko
67058a72cb2SAndrew Rybchenko for (el = 0; el < mask_npages; ++el) {
67158a72cb2SAndrew Rybchenko el_min = el * EFX_MAC_STATS_MASK_BITS_PER_PAGE;
67258a72cb2SAndrew Rybchenko el_max =
67358a72cb2SAndrew Rybchenko el_min + (EFX_MAC_STATS_MASK_BITS_PER_PAGE - 1);
67458a72cb2SAndrew Rybchenko if ((unsigned int)rngp->first > el_max ||
67558a72cb2SAndrew Rybchenko (unsigned int)rngp->last < el_min)
67658a72cb2SAndrew Rybchenko continue;
67758a72cb2SAndrew Rybchenko low = MAX((unsigned int)rngp->first, el_min);
67858a72cb2SAndrew Rybchenko high = MIN((unsigned int)rngp->last, el_max);
67958a72cb2SAndrew Rybchenko width = high - low + 1;
68058a72cb2SAndrew Rybchenko maskp[el] |=
68158a72cb2SAndrew Rybchenko (width == EFX_MAC_STATS_MASK_BITS_PER_PAGE) ?
68258a72cb2SAndrew Rybchenko (~0ULL) : (((1ULL << width) - 1) << (low - el_min));
68358a72cb2SAndrew Rybchenko }
68458a72cb2SAndrew Rybchenko
68558a72cb2SAndrew Rybchenko return (0);
68658a72cb2SAndrew Rybchenko
68758a72cb2SAndrew Rybchenko fail1:
68858a72cb2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
68958a72cb2SAndrew Rybchenko
69058a72cb2SAndrew Rybchenko return (rc);
69158a72cb2SAndrew Rybchenko }
69258a72cb2SAndrew Rybchenko
69358a72cb2SAndrew Rybchenko efx_rc_t
efx_mac_stats_mask_add_ranges(__inout_bcount (mask_size)uint32_t * maskp,__in size_t mask_size,__in_ecount (rng_count)const struct efx_mac_stats_range * rngp,__in unsigned int rng_count)69458a72cb2SAndrew Rybchenko efx_mac_stats_mask_add_ranges(
69558a72cb2SAndrew Rybchenko __inout_bcount(mask_size) uint32_t *maskp,
69658a72cb2SAndrew Rybchenko __in size_t mask_size,
69758a72cb2SAndrew Rybchenko __in_ecount(rng_count) const struct efx_mac_stats_range *rngp,
69858a72cb2SAndrew Rybchenko __in unsigned int rng_count)
69958a72cb2SAndrew Rybchenko {
70058a72cb2SAndrew Rybchenko unsigned int i;
70158a72cb2SAndrew Rybchenko efx_rc_t rc;
70258a72cb2SAndrew Rybchenko
70358a72cb2SAndrew Rybchenko for (i = 0; i < rng_count; ++i) {
70458a72cb2SAndrew Rybchenko if ((rc = efx_mac_stats_mask_add_range(maskp, mask_size,
70558a72cb2SAndrew Rybchenko &rngp[i])) != 0)
70658a72cb2SAndrew Rybchenko goto fail1;
70758a72cb2SAndrew Rybchenko }
70858a72cb2SAndrew Rybchenko
70958a72cb2SAndrew Rybchenko return (0);
71058a72cb2SAndrew Rybchenko
71158a72cb2SAndrew Rybchenko fail1:
71258a72cb2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
71358a72cb2SAndrew Rybchenko
71458a72cb2SAndrew Rybchenko return (rc);
71558a72cb2SAndrew Rybchenko }
71658a72cb2SAndrew Rybchenko
71758a72cb2SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_stats_get_mask(__in efx_nic_t * enp,__out_bcount (mask_size)uint32_t * maskp,__in size_t mask_size)71858a72cb2SAndrew Rybchenko efx_mac_stats_get_mask(
71958a72cb2SAndrew Rybchenko __in efx_nic_t *enp,
72058a72cb2SAndrew Rybchenko __out_bcount(mask_size) uint32_t *maskp,
72158a72cb2SAndrew Rybchenko __in size_t mask_size)
72258a72cb2SAndrew Rybchenko {
72358a72cb2SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
72458a72cb2SAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
72558a72cb2SAndrew Rybchenko efx_rc_t rc;
72658a72cb2SAndrew Rybchenko
72758a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
72858a72cb2SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
72958a72cb2SAndrew Rybchenko EFSYS_ASSERT(maskp != NULL);
73058a72cb2SAndrew Rybchenko EFSYS_ASSERT(mask_size % sizeof (maskp[0]) == 0);
73158a72cb2SAndrew Rybchenko
73258a72cb2SAndrew Rybchenko (void) memset(maskp, 0, mask_size);
73358a72cb2SAndrew Rybchenko
73458a72cb2SAndrew Rybchenko if ((rc = emop->emo_stats_get_mask(enp, maskp, mask_size)) != 0)
73558a72cb2SAndrew Rybchenko goto fail1;
73658a72cb2SAndrew Rybchenko
73758a72cb2SAndrew Rybchenko return (0);
73858a72cb2SAndrew Rybchenko
73958a72cb2SAndrew Rybchenko fail1:
74058a72cb2SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
74158a72cb2SAndrew Rybchenko
74258a72cb2SAndrew Rybchenko return (rc);
74358a72cb2SAndrew Rybchenko }
74458a72cb2SAndrew Rybchenko
745460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_stats_clear(__in efx_nic_t * enp)74631e518b4SAndrew Rybchenko efx_mac_stats_clear(
74731e518b4SAndrew Rybchenko __in efx_nic_t *enp)
74831e518b4SAndrew Rybchenko {
74931e518b4SAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
75031e518b4SAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
75131e518b4SAndrew Rybchenko efx_rc_t rc;
75231e518b4SAndrew Rybchenko
75331e518b4SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
75431e518b4SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
75531e518b4SAndrew Rybchenko EFSYS_ASSERT(emop != NULL);
75631e518b4SAndrew Rybchenko
75731e518b4SAndrew Rybchenko if ((rc = emop->emo_stats_clear(enp)) != 0)
75831e518b4SAndrew Rybchenko goto fail1;
75931e518b4SAndrew Rybchenko
76031e518b4SAndrew Rybchenko return (0);
76131e518b4SAndrew Rybchenko
76231e518b4SAndrew Rybchenko fail1:
76331e518b4SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
76431e518b4SAndrew Rybchenko
76531e518b4SAndrew Rybchenko return (rc);
76631e518b4SAndrew Rybchenko }
76731e518b4SAndrew Rybchenko
76831e518b4SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_stats_upload(__in efx_nic_t * enp,__in efsys_mem_t * esmp)769e948693eSPhilip Paeps efx_mac_stats_upload(
770e948693eSPhilip Paeps __in efx_nic_t *enp,
771e948693eSPhilip Paeps __in efsys_mem_t *esmp)
772e948693eSPhilip Paeps {
773e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
774ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
775460cb568SAndrew Rybchenko efx_rc_t rc;
776e948693eSPhilip Paeps
777e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
778e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
779e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
780e948693eSPhilip Paeps
781e948693eSPhilip Paeps if ((rc = emop->emo_stats_upload(enp, esmp)) != 0)
782e948693eSPhilip Paeps goto fail1;
783e948693eSPhilip Paeps
784e948693eSPhilip Paeps return (0);
785e948693eSPhilip Paeps
786e948693eSPhilip Paeps fail1:
787460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
788e948693eSPhilip Paeps
789e948693eSPhilip Paeps return (rc);
790e948693eSPhilip Paeps }
791e948693eSPhilip Paeps
792460cb568SAndrew Rybchenko __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)793e948693eSPhilip Paeps efx_mac_stats_periodic(
794e948693eSPhilip Paeps __in efx_nic_t *enp,
795e948693eSPhilip Paeps __in efsys_mem_t *esmp,
796e948693eSPhilip Paeps __in uint16_t period_ms,
797e948693eSPhilip Paeps __in boolean_t events)
798e948693eSPhilip Paeps {
799e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
800ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
801460cb568SAndrew Rybchenko efx_rc_t rc;
802e948693eSPhilip Paeps
803e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
804e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
805e948693eSPhilip Paeps
806e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
807e948693eSPhilip Paeps
808e948693eSPhilip Paeps if (emop->emo_stats_periodic == NULL) {
809e948693eSPhilip Paeps rc = EINVAL;
810e948693eSPhilip Paeps goto fail1;
811e948693eSPhilip Paeps }
812e948693eSPhilip Paeps
813e948693eSPhilip Paeps if ((rc = emop->emo_stats_periodic(enp, esmp, period_ms, events)) != 0)
814e948693eSPhilip Paeps goto fail2;
815e948693eSPhilip Paeps
816e948693eSPhilip Paeps return (0);
817e948693eSPhilip Paeps
818e948693eSPhilip Paeps fail2:
819e948693eSPhilip Paeps EFSYS_PROBE(fail2);
820e948693eSPhilip Paeps fail1:
821460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
822e948693eSPhilip Paeps
823e948693eSPhilip Paeps return (rc);
824e948693eSPhilip Paeps }
825e948693eSPhilip Paeps
826460cb568SAndrew Rybchenko __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)827e948693eSPhilip Paeps efx_mac_stats_update(
828e948693eSPhilip Paeps __in efx_nic_t *enp,
829e948693eSPhilip Paeps __in efsys_mem_t *esmp,
830e948693eSPhilip Paeps __inout_ecount(EFX_MAC_NSTATS) efsys_stat_t *essp,
83114c3e490SAndrew Rybchenko __inout_opt uint32_t *generationp)
832e948693eSPhilip Paeps {
833e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
834ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
835460cb568SAndrew Rybchenko efx_rc_t rc;
836e948693eSPhilip Paeps
837e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
838e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
839e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
840e948693eSPhilip Paeps
841e948693eSPhilip Paeps rc = emop->emo_stats_update(enp, esmp, essp, generationp);
842e948693eSPhilip Paeps
843e948693eSPhilip Paeps return (rc);
844e948693eSPhilip Paeps }
845e948693eSPhilip Paeps
846e948693eSPhilip Paeps #endif /* EFSYS_OPT_MAC_STATS */
847e948693eSPhilip Paeps
848460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_mac_select(__in efx_nic_t * enp)849e948693eSPhilip Paeps efx_mac_select(
850e948693eSPhilip Paeps __in efx_nic_t *enp)
851e948693eSPhilip Paeps {
852e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
853e948693eSPhilip Paeps efx_mac_type_t type = EFX_MAC_INVALID;
854ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop;
855e948693eSPhilip Paeps int rc = EINVAL;
856e948693eSPhilip Paeps
85795812f27SAndrew Rybchenko switch (enp->en_family) {
858c15d6d21SAndrew Rybchenko #if EFSYS_OPT_SIENA
85995812f27SAndrew Rybchenko case EFX_FAMILY_SIENA:
860ae346558SAndrew Rybchenko emop = &__efx_mac_siena_ops;
861c15d6d21SAndrew Rybchenko type = EFX_MAC_SIENA;
86295812f27SAndrew Rybchenko break;
86395812f27SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
864c15d6d21SAndrew Rybchenko
8653c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
86695812f27SAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
867ae346558SAndrew Rybchenko emop = &__efx_mac_ef10_ops;
8683c838a9fSAndrew Rybchenko type = EFX_MAC_HUNTINGTON;
86995812f27SAndrew Rybchenko break;
87095812f27SAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
8713c838a9fSAndrew Rybchenko
872c15d6d21SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
87395812f27SAndrew Rybchenko case EFX_FAMILY_MEDFORD:
874ae346558SAndrew Rybchenko emop = &__efx_mac_ef10_ops;
875c15d6d21SAndrew Rybchenko type = EFX_MAC_MEDFORD;
87695812f27SAndrew Rybchenko break;
87795812f27SAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
878e948693eSPhilip Paeps
879cbc3f94fSAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
880cbc3f94fSAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
881cbc3f94fSAndrew Rybchenko emop = &__efx_mac_ef10_ops;
882cbc3f94fSAndrew Rybchenko type = EFX_MAC_MEDFORD2;
883cbc3f94fSAndrew Rybchenko break;
884cbc3f94fSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
885cbc3f94fSAndrew Rybchenko
88695812f27SAndrew Rybchenko default:
88795812f27SAndrew Rybchenko rc = EINVAL;
88895812f27SAndrew Rybchenko goto fail1;
88995812f27SAndrew Rybchenko }
89095812f27SAndrew Rybchenko
891e948693eSPhilip Paeps EFSYS_ASSERT(type != EFX_MAC_INVALID);
892e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_MAC_NTYPES);
893e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
894e948693eSPhilip Paeps
89595812f27SAndrew Rybchenko epp->ep_emop = emop;
896e948693eSPhilip Paeps epp->ep_mac_type = type;
897e948693eSPhilip Paeps
898e948693eSPhilip Paeps return (0);
899e948693eSPhilip Paeps
900e948693eSPhilip Paeps fail1:
901460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
902e948693eSPhilip Paeps
903e948693eSPhilip Paeps return (rc);
904e948693eSPhilip Paeps }
9053c838a9fSAndrew Rybchenko
906e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
9073c838a9fSAndrew Rybchenko
90874bb0ed8SAndrew Rybchenko #define EFX_MAC_HASH_BITS (1 << 8)
90974bb0ed8SAndrew Rybchenko
9103c838a9fSAndrew Rybchenko /* Compute the multicast hash as used on Falcon and Siena. */
9113c838a9fSAndrew Rybchenko static void
9125cab4fc7SAndrew Rybchenko siena_mac_multicast_hash_compute(
9133c838a9fSAndrew Rybchenko __in_ecount(6*count) uint8_t const *addrs,
9143c838a9fSAndrew Rybchenko __in int count,
9153c838a9fSAndrew Rybchenko __out efx_oword_t *hash_low,
9163c838a9fSAndrew Rybchenko __out efx_oword_t *hash_high)
9173c838a9fSAndrew Rybchenko {
9183c838a9fSAndrew Rybchenko uint32_t crc, index;
9193c838a9fSAndrew Rybchenko int i;
9203c838a9fSAndrew Rybchenko
9213c838a9fSAndrew Rybchenko EFSYS_ASSERT(hash_low != NULL);
9223c838a9fSAndrew Rybchenko EFSYS_ASSERT(hash_high != NULL);
9233c838a9fSAndrew Rybchenko
9243c838a9fSAndrew Rybchenko EFX_ZERO_OWORD(*hash_low);
9253c838a9fSAndrew Rybchenko EFX_ZERO_OWORD(*hash_high);
9263c838a9fSAndrew Rybchenko
9273c838a9fSAndrew Rybchenko for (i = 0; i < count; i++) {
9283c838a9fSAndrew Rybchenko /* Calculate hash bucket (IEEE 802.3 CRC32 of the MAC addr) */
9293c838a9fSAndrew Rybchenko crc = efx_crc32_calculate(0xffffffff, addrs, EFX_MAC_ADDR_LEN);
9303c838a9fSAndrew Rybchenko index = crc % EFX_MAC_HASH_BITS;
9313c838a9fSAndrew Rybchenko if (index < 128) {
9323c838a9fSAndrew Rybchenko EFX_SET_OWORD_BIT(*hash_low, index);
9333c838a9fSAndrew Rybchenko } else {
9343c838a9fSAndrew Rybchenko EFX_SET_OWORD_BIT(*hash_high, index - 128);
9353c838a9fSAndrew Rybchenko }
9363c838a9fSAndrew Rybchenko
9373c838a9fSAndrew Rybchenko addrs += EFX_MAC_ADDR_LEN;
9383c838a9fSAndrew Rybchenko }
9393c838a9fSAndrew Rybchenko }
9403c838a9fSAndrew Rybchenko
941460cb568SAndrew Rybchenko static __checkReturn efx_rc_t
siena_mac_multicast_list_set(__in efx_nic_t * enp)9425cab4fc7SAndrew Rybchenko siena_mac_multicast_list_set(
9433c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
9443c838a9fSAndrew Rybchenko {
9453c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
946ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
9473c838a9fSAndrew Rybchenko efx_oword_t old_hash[2];
948460cb568SAndrew Rybchenko efx_rc_t rc;
9493c838a9fSAndrew Rybchenko
9503c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
9513c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
9523c838a9fSAndrew Rybchenko
9533c838a9fSAndrew Rybchenko memcpy(old_hash, epp->ep_multicst_hash, sizeof (old_hash));
9543c838a9fSAndrew Rybchenko
9555cab4fc7SAndrew Rybchenko siena_mac_multicast_hash_compute(
9565cab4fc7SAndrew Rybchenko epp->ep_mulcst_addr_list,
9573c838a9fSAndrew Rybchenko epp->ep_mulcst_addr_count,
9583c838a9fSAndrew Rybchenko &epp->ep_multicst_hash[0],
9593c838a9fSAndrew Rybchenko &epp->ep_multicst_hash[1]);
9603c838a9fSAndrew Rybchenko
9613c838a9fSAndrew Rybchenko if ((rc = emop->emo_reconfigure(enp)) != 0)
9623c838a9fSAndrew Rybchenko goto fail1;
9633c838a9fSAndrew Rybchenko
9643c838a9fSAndrew Rybchenko return (0);
9653c838a9fSAndrew Rybchenko
9663c838a9fSAndrew Rybchenko fail1:
967460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
9683c838a9fSAndrew Rybchenko
9693c838a9fSAndrew Rybchenko memcpy(epp->ep_multicst_hash, old_hash, sizeof (old_hash));
9703c838a9fSAndrew Rybchenko
9713c838a9fSAndrew Rybchenko return (rc);
9723c838a9fSAndrew Rybchenko }
9733c838a9fSAndrew Rybchenko
974e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
975