]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/efx_port.c
Merge once more from ^/vendor/llvm-project/release-10.x, to get the
[FreeBSD/FreeBSD.git] / sys / dev / sfxge / common / efx_port.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2009-2016 Solarflare Communications Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright notice,
13  *    this list of conditions and the following disclaimer in the documentation
14  *    and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * The views and conclusions contained in the software and documentation are
29  * those of the authors and should not be interpreted as representing official
30  * policies, either expressed or implied, of the FreeBSD Project.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include "efx.h"
37 #include "efx_impl.h"
38
39         __checkReturn   efx_rc_t
40 efx_port_init(
41         __in            efx_nic_t *enp)
42 {
43         efx_port_t *epp = &(enp->en_port);
44         const efx_phy_ops_t *epop = epp->ep_epop;
45         efx_rc_t rc;
46
47         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
48         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
49         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
50
51         if (enp->en_mod_flags & EFX_MOD_PORT) {
52                 rc = EINVAL;
53                 goto fail1;
54         }
55
56         enp->en_mod_flags |= EFX_MOD_PORT;
57
58         epp->ep_mac_type = EFX_MAC_INVALID;
59         epp->ep_link_mode = EFX_LINK_UNKNOWN;
60         epp->ep_mac_drain = B_TRUE;
61
62         /* Configure the MAC */
63         if ((rc = efx_mac_select(enp)) != 0)
64                 goto fail1;
65
66         epp->ep_emop->emo_reconfigure(enp);
67
68         /* Pick up current phy capababilities */
69         (void) efx_port_poll(enp, NULL);
70
71         /*
72          * Turn on the PHY if available, otherwise reset it, and
73          * reconfigure it with the current configuration.
74          */
75         if (epop->epo_power != NULL) {
76                 if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
77                         goto fail2;
78         } else {
79                 if ((rc = epop->epo_reset(enp)) != 0)
80                         goto fail2;
81         }
82
83         EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
84         enp->en_reset_flags &= ~EFX_RESET_PHY;
85
86         if ((rc = epop->epo_reconfigure(enp)) != 0)
87                 goto fail3;
88
89         return (0);
90
91 fail3:
92         EFSYS_PROBE(fail3);
93 fail2:
94         EFSYS_PROBE(fail2);
95 fail1:
96         EFSYS_PROBE1(fail1, efx_rc_t, rc);
97
98         enp->en_mod_flags &= ~EFX_MOD_PORT;
99
100         return (rc);
101 }
102
103         __checkReturn   efx_rc_t
104 efx_port_poll(
105         __in            efx_nic_t *enp,
106         __out_opt       efx_link_mode_t *link_modep)
107 {
108         efx_port_t *epp = &(enp->en_port);
109         const efx_mac_ops_t *emop = epp->ep_emop;
110         efx_link_mode_t ignore_link_mode;
111         efx_rc_t rc;
112
113         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
114         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
115
116         EFSYS_ASSERT(emop != NULL);
117
118         if (link_modep == NULL)
119                 link_modep = &ignore_link_mode;
120
121         if ((rc = emop->emo_poll(enp, link_modep)) != 0)
122                 goto fail1;
123
124         return (0);
125
126 fail1:
127         EFSYS_PROBE1(fail1, efx_rc_t, rc);
128
129         return (rc);
130 }
131
132 #if EFSYS_OPT_LOOPBACK
133
134         __checkReturn   efx_rc_t
135 efx_port_loopback_set(
136         __in            efx_nic_t *enp,
137         __in            efx_link_mode_t link_mode,
138         __in            efx_loopback_type_t loopback_type)
139 {
140         efx_port_t *epp = &(enp->en_port);
141         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
142         const efx_mac_ops_t *emop = epp->ep_emop;
143         efx_rc_t rc;
144
145         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
146         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
147         EFSYS_ASSERT(emop != NULL);
148
149         EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
150
151         if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],
152                 (int)loopback_type) == 0) {
153                 rc = ENOTSUP;
154                 goto fail1;
155         }
156
157         if (epp->ep_loopback_type == loopback_type &&
158             epp->ep_loopback_link_mode == link_mode)
159                 return (0);
160
161         if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
162                 goto fail2;
163
164         return (0);
165
166 fail2:
167         EFSYS_PROBE(fail2);
168 fail1:
169         EFSYS_PROBE1(fail1, efx_rc_t, rc);
170
171         return (rc);
172 }
173
174 #if EFSYS_OPT_NAMES
175
176 static const char * const __efx_loopback_type_name[] = {
177         "OFF",
178         "DATA",
179         "GMAC",
180         "XGMII",
181         "XGXS",
182         "XAUI",
183         "GMII",
184         "SGMII",
185         "XGBR",
186         "XFI",
187         "XAUI_FAR",
188         "GMII_FAR",
189         "SGMII_FAR",
190         "XFI_FAR",
191         "GPHY",
192         "PHY_XS",
193         "PCS",
194         "PMA_PMD",
195         "XPORT",
196         "XGMII_WS",
197         "XAUI_WS",
198         "XAUI_WS_FAR",
199         "XAUI_WS_NEAR",
200         "GMII_WS",
201         "XFI_WS",
202         "XFI_WS_FAR",
203         "PHYXS_WS",
204         "PMA_INT",
205         "SD_NEAR",
206         "SD_FAR",
207         "PMA_INT_WS",
208         "SD_FEP2_WS",
209         "SD_FEP1_5_WS",
210         "SD_FEP_WS",
211         "SD_FES_WS",
212         "AOE_INT_NEAR",
213         "DATA_WS",
214         "FORCE_EXT_LINK",
215 };
216
217         __checkReturn   const char *
218 efx_loopback_type_name(
219         __in            efx_nic_t *enp,
220         __in            efx_loopback_type_t type)
221 {
222         EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
223             EFX_LOOPBACK_NTYPES);
224
225         _NOTE(ARGUNUSED(enp))
226         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
227         EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
228
229         return (__efx_loopback_type_name[type]);
230 }
231
232 #endif  /* EFSYS_OPT_NAMES */
233
234 #endif  /* EFSYS_OPT_LOOPBACK */
235
236                         void
237 efx_port_fini(
238         __in            efx_nic_t *enp)
239 {
240         efx_port_t *epp = &(enp->en_port);
241         const efx_phy_ops_t *epop = epp->ep_epop;
242
243         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
244         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
245         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
246         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
247
248         EFSYS_ASSERT(epp->ep_mac_drain);
249
250         epp->ep_emop = NULL;
251         epp->ep_mac_type = EFX_MAC_INVALID;
252         epp->ep_mac_drain = B_FALSE;
253
254         /* Turn off the PHY */
255         if (epop->epo_power != NULL)
256                 (void) epop->epo_power(enp, B_FALSE);
257
258         enp->en_mod_flags &= ~EFX_MOD_PORT;
259 }