]> CyberLeo.Net >> Repos - FreeBSD/releng/10.3.git/blob - sys/dev/sfxge/common/efx_port.c
- Copy stable/10@296371 to releng/10.3 in preparation for 10.3-RC1
[FreeBSD/releng/10.3.git] / sys / dev / sfxge / common / efx_port.c
1 /*-
2  * Copyright (c) 2009-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 <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "efx.h"
35 #include "efx_impl.h"
36
37         __checkReturn   efx_rc_t
38 efx_port_init(
39         __in            efx_nic_t *enp)
40 {
41         efx_port_t *epp = &(enp->en_port);
42         efx_phy_ops_t *epop = epp->ep_epop;
43         efx_rc_t rc;
44
45         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
46         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
47         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
48
49         if (enp->en_mod_flags & EFX_MOD_PORT) {
50                 rc = EINVAL;
51                 goto fail1;
52         }
53
54         enp->en_mod_flags |= EFX_MOD_PORT;
55
56         epp->ep_mac_type = EFX_MAC_INVALID;
57         epp->ep_link_mode = EFX_LINK_UNKNOWN;
58         epp->ep_mac_poll_needed = B_TRUE;
59         epp->ep_mac_drain = B_TRUE;
60
61         /* Configure the MAC */
62         if ((rc = efx_mac_select(enp)) != 0)
63                 goto fail1;
64
65         epp->ep_emop->emo_reconfigure(enp);
66
67         /* Pick up current phy capababilities */
68         efx_port_poll(enp, NULL);
69
70         /*
71          * Turn on the PHY if available, otherwise reset it, and
72          * reconfigure it with the current configuration.
73          */
74         if (epop->epo_power != NULL) {
75                 if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
76                         goto fail2;
77         } else {
78                 if ((rc = epop->epo_reset(enp)) != 0)
79                         goto fail2;
80         }
81
82         EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
83         enp->en_reset_flags &= ~EFX_RESET_PHY;
84
85         if ((rc = epop->epo_reconfigure(enp)) != 0)
86                 goto fail3;
87
88         return (0);
89
90 fail3:
91         EFSYS_PROBE(fail3);
92 fail2:
93         EFSYS_PROBE(fail2);
94 fail1:
95         EFSYS_PROBE1(fail1, efx_rc_t, rc);
96
97         enp->en_mod_flags &= ~EFX_MOD_PORT;
98
99         return (rc);
100 }
101
102         __checkReturn   efx_rc_t
103 efx_port_poll(
104         __in            efx_nic_t *enp,
105         __out_opt       efx_link_mode_t *link_modep)
106 {
107         efx_port_t *epp = &(enp->en_port);
108         efx_mac_ops_t *emop = epp->ep_emop;
109         efx_link_mode_t ignore_link_mode;
110         efx_rc_t rc;
111
112         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
113         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
114
115         EFSYS_ASSERT(emop != NULL);
116         EFSYS_ASSERT(!epp->ep_mac_stats_pending);
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         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                 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       *__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 };
213
214         __checkReturn   const char *
215 efx_loopback_type_name(
216         __in            efx_nic_t *enp,
217         __in            efx_loopback_type_t type)
218 {
219         EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) ==
220             EFX_LOOPBACK_NTYPES);
221
222         _NOTE(ARGUNUSED(enp))
223         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
224         EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
225
226         return (__efx_loopback_type_name[type]);
227 }
228
229 #endif  /* EFSYS_OPT_NAMES */
230
231 #endif  /* EFSYS_OPT_LOOPBACK */
232
233                         void
234 efx_port_fini(
235         __in            efx_nic_t *enp)
236 {
237         efx_port_t *epp = &(enp->en_port);
238         efx_phy_ops_t *epop = epp->ep_epop;
239
240         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
241         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
242         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
243         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
244
245         EFSYS_ASSERT(epp->ep_mac_drain);
246
247         epp->ep_emop = NULL;
248         epp->ep_mac_type = EFX_MAC_INVALID;
249         epp->ep_mac_drain = B_FALSE;
250         epp->ep_mac_poll_needed = 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 }