1e948693eSPhilip Paeps /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4929c7febSAndrew Rybchenko * Copyright (c) 2009-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
37460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_port_init(__in efx_nic_t * enp)38e948693eSPhilip Paeps efx_port_init(
39e948693eSPhilip Paeps __in efx_nic_t *enp)
40e948693eSPhilip Paeps {
41e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
42ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
43460cb568SAndrew Rybchenko efx_rc_t rc;
44e948693eSPhilip Paeps
45e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
46e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
47e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
48e948693eSPhilip Paeps
49e948693eSPhilip Paeps if (enp->en_mod_flags & EFX_MOD_PORT) {
50e948693eSPhilip Paeps rc = EINVAL;
51e948693eSPhilip Paeps goto fail1;
52e948693eSPhilip Paeps }
53e948693eSPhilip Paeps
54e948693eSPhilip Paeps enp->en_mod_flags |= EFX_MOD_PORT;
55e948693eSPhilip Paeps
56e948693eSPhilip Paeps epp->ep_mac_type = EFX_MAC_INVALID;
57e948693eSPhilip Paeps epp->ep_link_mode = EFX_LINK_UNKNOWN;
58e948693eSPhilip Paeps epp->ep_mac_drain = B_TRUE;
59e948693eSPhilip Paeps
60e948693eSPhilip Paeps /* Configure the MAC */
61e948693eSPhilip Paeps if ((rc = efx_mac_select(enp)) != 0)
62e948693eSPhilip Paeps goto fail1;
63e948693eSPhilip Paeps
64e948693eSPhilip Paeps epp->ep_emop->emo_reconfigure(enp);
65e948693eSPhilip Paeps
663c838a9fSAndrew Rybchenko /* Pick up current phy capababilities */
67e4ddd4ccSAndrew Rybchenko (void) efx_port_poll(enp, NULL);
683c838a9fSAndrew Rybchenko
69e948693eSPhilip Paeps /*
70e948693eSPhilip Paeps * Turn on the PHY if available, otherwise reset it, and
71e948693eSPhilip Paeps * reconfigure it with the current configuration.
72e948693eSPhilip Paeps */
73e948693eSPhilip Paeps if (epop->epo_power != NULL) {
74e948693eSPhilip Paeps if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
75e948693eSPhilip Paeps goto fail2;
76e948693eSPhilip Paeps } else {
77e948693eSPhilip Paeps if ((rc = epop->epo_reset(enp)) != 0)
78e948693eSPhilip Paeps goto fail2;
79e948693eSPhilip Paeps }
80e948693eSPhilip Paeps
81e948693eSPhilip Paeps EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
82e948693eSPhilip Paeps enp->en_reset_flags &= ~EFX_RESET_PHY;
83e948693eSPhilip Paeps
84e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0)
85e948693eSPhilip Paeps goto fail3;
86e948693eSPhilip Paeps
87e948693eSPhilip Paeps return (0);
88e948693eSPhilip Paeps
89e948693eSPhilip Paeps fail3:
90e948693eSPhilip Paeps EFSYS_PROBE(fail3);
91e948693eSPhilip Paeps fail2:
92e948693eSPhilip Paeps EFSYS_PROBE(fail2);
93e948693eSPhilip Paeps fail1:
94460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
95e948693eSPhilip Paeps
96e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_PORT;
97e948693eSPhilip Paeps
98e948693eSPhilip Paeps return (rc);
99e948693eSPhilip Paeps }
100e948693eSPhilip Paeps
101460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_port_poll(__in efx_nic_t * enp,__out_opt efx_link_mode_t * link_modep)102e948693eSPhilip Paeps efx_port_poll(
103e948693eSPhilip Paeps __in efx_nic_t *enp,
1043c838a9fSAndrew Rybchenko __out_opt efx_link_mode_t *link_modep)
105e948693eSPhilip Paeps {
106e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
107ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
108e948693eSPhilip Paeps efx_link_mode_t ignore_link_mode;
109460cb568SAndrew Rybchenko efx_rc_t rc;
110e948693eSPhilip Paeps
111e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
112e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
113e948693eSPhilip Paeps
114e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
115e948693eSPhilip Paeps
116e948693eSPhilip Paeps if (link_modep == NULL)
117e948693eSPhilip Paeps link_modep = &ignore_link_mode;
118e948693eSPhilip Paeps
119e948693eSPhilip Paeps if ((rc = emop->emo_poll(enp, link_modep)) != 0)
120e948693eSPhilip Paeps goto fail1;
121e948693eSPhilip Paeps
122e948693eSPhilip Paeps return (0);
123e948693eSPhilip Paeps
124e948693eSPhilip Paeps fail1:
125460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
126e948693eSPhilip Paeps
127e948693eSPhilip Paeps return (rc);
128e948693eSPhilip Paeps }
129e948693eSPhilip Paeps
130e948693eSPhilip Paeps #if EFSYS_OPT_LOOPBACK
131e948693eSPhilip Paeps
132460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_port_loopback_set(__in efx_nic_t * enp,__in efx_link_mode_t link_mode,__in efx_loopback_type_t loopback_type)133e948693eSPhilip Paeps efx_port_loopback_set(
134e948693eSPhilip Paeps __in efx_nic_t *enp,
135e948693eSPhilip Paeps __in efx_link_mode_t link_mode,
136e948693eSPhilip Paeps __in efx_loopback_type_t loopback_type)
137e948693eSPhilip Paeps {
138e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
139e948693eSPhilip Paeps efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
140ec831f7fSAndrew Rybchenko const efx_mac_ops_t *emop = epp->ep_emop;
141460cb568SAndrew Rybchenko efx_rc_t rc;
142e948693eSPhilip Paeps
143e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
144e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
145e948693eSPhilip Paeps EFSYS_ASSERT(emop != NULL);
146e948693eSPhilip Paeps
147e948693eSPhilip Paeps EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
1483c838a9fSAndrew Rybchenko
1493c838a9fSAndrew Rybchenko if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],
1502a67ba30SAndrew Rybchenko (int)loopback_type) == 0) {
151e948693eSPhilip Paeps rc = ENOTSUP;
152e948693eSPhilip Paeps goto fail1;
153e948693eSPhilip Paeps }
154e948693eSPhilip Paeps
155e948693eSPhilip Paeps if (epp->ep_loopback_type == loopback_type &&
156e948693eSPhilip Paeps epp->ep_loopback_link_mode == link_mode)
157e948693eSPhilip Paeps return (0);
158e948693eSPhilip Paeps
159e948693eSPhilip Paeps if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
160e948693eSPhilip Paeps goto fail2;
161e948693eSPhilip Paeps
162e948693eSPhilip Paeps return (0);
163e948693eSPhilip Paeps
164e948693eSPhilip Paeps fail2:
165e948693eSPhilip Paeps EFSYS_PROBE(fail2);
166e948693eSPhilip Paeps fail1:
167460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
168e948693eSPhilip Paeps
169e948693eSPhilip Paeps return (rc);
170e948693eSPhilip Paeps }
171e948693eSPhilip Paeps
172e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
173e948693eSPhilip Paeps
17409b3e655SAndrew Rybchenko static const char * const __efx_loopback_type_name[] = {
175e948693eSPhilip Paeps "OFF",
176e948693eSPhilip Paeps "DATA",
177e948693eSPhilip Paeps "GMAC",
178e948693eSPhilip Paeps "XGMII",
179e948693eSPhilip Paeps "XGXS",
180e948693eSPhilip Paeps "XAUI",
181e948693eSPhilip Paeps "GMII",
182e948693eSPhilip Paeps "SGMII",
183e948693eSPhilip Paeps "XGBR",
184e948693eSPhilip Paeps "XFI",
185e948693eSPhilip Paeps "XAUI_FAR",
186e948693eSPhilip Paeps "GMII_FAR",
187e948693eSPhilip Paeps "SGMII_FAR",
188e948693eSPhilip Paeps "XFI_FAR",
189e948693eSPhilip Paeps "GPHY",
190e948693eSPhilip Paeps "PHY_XS",
191e948693eSPhilip Paeps "PCS",
192e948693eSPhilip Paeps "PMA_PMD",
1933c838a9fSAndrew Rybchenko "XPORT",
1943c838a9fSAndrew Rybchenko "XGMII_WS",
1953c838a9fSAndrew Rybchenko "XAUI_WS",
1963c838a9fSAndrew Rybchenko "XAUI_WS_FAR",
1973c838a9fSAndrew Rybchenko "XAUI_WS_NEAR",
1983c838a9fSAndrew Rybchenko "GMII_WS",
1993c838a9fSAndrew Rybchenko "XFI_WS",
2003c838a9fSAndrew Rybchenko "XFI_WS_FAR",
2013c838a9fSAndrew Rybchenko "PHYXS_WS",
2023c838a9fSAndrew Rybchenko "PMA_INT",
2033c838a9fSAndrew Rybchenko "SD_NEAR",
2043c838a9fSAndrew Rybchenko "SD_FAR",
2053c838a9fSAndrew Rybchenko "PMA_INT_WS",
2063c838a9fSAndrew Rybchenko "SD_FEP2_WS",
2073c838a9fSAndrew Rybchenko "SD_FEP1_5_WS",
2083c838a9fSAndrew Rybchenko "SD_FEP_WS",
2093c838a9fSAndrew Rybchenko "SD_FES_WS",
210725bb178SAndrew Rybchenko "AOE_INT_NEAR",
211725bb178SAndrew Rybchenko "DATA_WS",
212725bb178SAndrew Rybchenko "FORCE_EXT_LINK",
213e948693eSPhilip Paeps };
214e948693eSPhilip Paeps
2153c838a9fSAndrew Rybchenko __checkReturn const char *
efx_loopback_type_name(__in efx_nic_t * enp,__in efx_loopback_type_t type)216e948693eSPhilip Paeps efx_loopback_type_name(
217e948693eSPhilip Paeps __in efx_nic_t *enp,
218e948693eSPhilip Paeps __in efx_loopback_type_t type)
219e948693eSPhilip Paeps {
2203c838a9fSAndrew Rybchenko EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
2213c838a9fSAndrew Rybchenko EFX_LOOPBACK_NTYPES);
2223c838a9fSAndrew Rybchenko
223e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp))
224e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
225e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
226e948693eSPhilip Paeps
227e948693eSPhilip Paeps return (__efx_loopback_type_name[type]);
228e948693eSPhilip Paeps }
229e948693eSPhilip Paeps
230e948693eSPhilip Paeps #endif /* EFSYS_OPT_NAMES */
231e948693eSPhilip Paeps
232e948693eSPhilip Paeps #endif /* EFSYS_OPT_LOOPBACK */
233e948693eSPhilip Paeps
234e948693eSPhilip Paeps void
efx_port_fini(__in efx_nic_t * enp)235e948693eSPhilip Paeps efx_port_fini(
236e948693eSPhilip Paeps __in efx_nic_t *enp)
237e948693eSPhilip Paeps {
238e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
239ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
240e948693eSPhilip Paeps
241e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
243e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
244e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
245e948693eSPhilip Paeps
246e948693eSPhilip Paeps EFSYS_ASSERT(epp->ep_mac_drain);
247e948693eSPhilip Paeps
248e948693eSPhilip Paeps epp->ep_emop = NULL;
249e948693eSPhilip Paeps epp->ep_mac_type = EFX_MAC_INVALID;
250e948693eSPhilip Paeps epp->ep_mac_drain = B_FALSE;
251e948693eSPhilip Paeps
252e948693eSPhilip Paeps /* Turn off the PHY */
253e948693eSPhilip Paeps if (epop->epo_power != NULL)
254e948693eSPhilip Paeps (void) epop->epo_power(enp, B_FALSE);
255e948693eSPhilip Paeps
256e948693eSPhilip Paeps enp->en_mod_flags &= ~EFX_MOD_PORT;
257e948693eSPhilip Paeps }
258