]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/sfxge/common/efx_port.c
Update to bmake-201802222
[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         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         EFSYS_ASSERT(!epp->ep_mac_stats_pending);
118
119         if (link_modep == NULL)
120                 link_modep = &ignore_link_mode;
121
122         if ((rc = emop->emo_poll(enp, link_modep)) != 0)
123                 goto fail1;
124
125         return (0);
126
127 fail1:
128         EFSYS_PROBE1(fail1, efx_rc_t, rc);
129
130         return (rc);
131 }
132
133 #if EFSYS_OPT_LOOPBACK
134
135         __checkReturn   efx_rc_t
136 efx_port_loopback_set(
137         __in            efx_nic_t *enp,
138         __in            efx_link_mode_t link_mode,
139         __in            efx_loopback_type_t loopback_type)
140 {
141         efx_port_t *epp = &(enp->en_port);
142         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
143         const efx_mac_ops_t *emop = epp->ep_emop;
144         efx_rc_t rc;
145
146         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
147         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
148         EFSYS_ASSERT(emop != NULL);
149
150         EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
151
152         if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode],
153                 loopback_type) == 0) {
154                 rc = ENOTSUP;
155                 goto fail1;
156         }
157
158         if (epp->ep_loopback_type == loopback_type &&
159             epp->ep_loopback_link_mode == link_mode)
160                 return (0);
161
162         if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
163                 goto fail2;
164
165         return (0);
166
167 fail2:
168         EFSYS_PROBE(fail2);
169 fail1:
170         EFSYS_PROBE1(fail1, efx_rc_t, rc);
171
172         return (rc);
173 }
174
175 #if EFSYS_OPT_NAMES
176
177 static const char * const __efx_loopback_type_name[] = {
178         "OFF",
179         "DATA",
180         "GMAC",
181         "XGMII",
182         "XGXS",
183         "XAUI",
184         "GMII",
185         "SGMII",
186         "XGBR",
187         "XFI",
188         "XAUI_FAR",
189         "GMII_FAR",
190         "SGMII_FAR",
191         "XFI_FAR",
192         "GPHY",
193         "PHY_XS",
194         "PCS",
195         "PMA_PMD",
196         "XPORT",
197         "XGMII_WS",
198         "XAUI_WS",
199         "XAUI_WS_FAR",
200         "XAUI_WS_NEAR",
201         "GMII_WS",
202         "XFI_WS",
203         "XFI_WS_FAR",
204         "PHYXS_WS",
205         "PMA_INT",
206         "SD_NEAR",
207         "SD_FAR",
208         "PMA_INT_WS",
209         "SD_FEP2_WS",
210         "SD_FEP1_5_WS",
211         "SD_FEP_WS",
212         "SD_FES_WS",
213 };
214
215         __checkReturn   const char *
216 efx_loopback_type_name(
217         __in            efx_nic_t *enp,
218         __in            efx_loopback_type_t type)
219 {
220         EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
221             EFX_LOOPBACK_NTYPES);
222
223         _NOTE(ARGUNUSED(enp))
224         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
225         EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
226
227         return (__efx_loopback_type_name[type]);
228 }
229
230 #endif  /* EFSYS_OPT_NAMES */
231
232 #endif  /* EFSYS_OPT_LOOPBACK */
233
234                         void
235 efx_port_fini(
236         __in            efx_nic_t *enp)
237 {
238         efx_port_t *epp = &(enp->en_port);
239         const efx_phy_ops_t *epop = epp->ep_epop;
240
241         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
242         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
243         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
244         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
245
246         EFSYS_ASSERT(epp->ep_mac_drain);
247
248         epp->ep_emop = NULL;
249         epp->ep_mac_type = EFX_MAC_INVALID;
250         epp->ep_mac_drain = B_FALSE;
251
252         /* Turn off the PHY */
253         if (epop->epo_power != NULL)
254                 (void) epop->epo_power(enp, B_FALSE);
255
256         enp->en_mod_flags &= ~EFX_MOD_PORT;
257 }