]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * | |
3 | * Copyright (c) 2009-2018 Solarflare Communications Inc. | |
4 | * All rights reserved. | |
5 | */ | |
6 | ||
7 | #include "efx.h" | |
8 | #include "efx_impl.h" | |
9 | ||
10 | __checkReturn efx_rc_t | |
11 | efx_port_init( | |
12 | __in efx_nic_t *enp) | |
13 | { | |
14 | efx_port_t *epp = &(enp->en_port); | |
15 | const efx_phy_ops_t *epop = epp->ep_epop; | |
16 | efx_rc_t rc; | |
17 | ||
18 | EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); | |
19 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); | |
20 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); | |
21 | ||
22 | if (enp->en_mod_flags & EFX_MOD_PORT) { | |
23 | rc = EINVAL; | |
24 | goto fail1; | |
25 | } | |
26 | ||
27 | enp->en_mod_flags |= EFX_MOD_PORT; | |
28 | ||
29 | epp->ep_mac_type = EFX_MAC_INVALID; | |
30 | epp->ep_link_mode = EFX_LINK_UNKNOWN; | |
31 | epp->ep_mac_drain = B_TRUE; | |
32 | ||
33 | /* Configure the MAC */ | |
34 | if ((rc = efx_mac_select(enp)) != 0) | |
35 | goto fail1; | |
36 | ||
37 | epp->ep_emop->emo_reconfigure(enp); | |
38 | ||
39 | /* Pick up current phy capababilities */ | |
9f95a23c | 40 | (void) efx_port_poll(enp, NULL); |
11fdf7f2 TL |
41 | |
42 | /* | |
43 | * Turn on the PHY if available, otherwise reset it, and | |
44 | * reconfigure it with the current configuration. | |
45 | */ | |
46 | if (epop->epo_power != NULL) { | |
47 | if ((rc = epop->epo_power(enp, B_TRUE)) != 0) | |
48 | goto fail2; | |
49 | } else { | |
50 | if ((rc = epop->epo_reset(enp)) != 0) | |
51 | goto fail2; | |
52 | } | |
53 | ||
54 | EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY); | |
55 | enp->en_reset_flags &= ~EFX_RESET_PHY; | |
56 | ||
57 | if ((rc = epop->epo_reconfigure(enp)) != 0) | |
58 | goto fail3; | |
59 | ||
60 | return (0); | |
61 | ||
62 | fail3: | |
63 | EFSYS_PROBE(fail3); | |
64 | fail2: | |
65 | EFSYS_PROBE(fail2); | |
66 | fail1: | |
67 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
68 | ||
69 | enp->en_mod_flags &= ~EFX_MOD_PORT; | |
70 | ||
71 | return (rc); | |
72 | } | |
73 | ||
74 | __checkReturn efx_rc_t | |
75 | efx_port_poll( | |
76 | __in efx_nic_t *enp, | |
77 | __out_opt efx_link_mode_t *link_modep) | |
78 | { | |
79 | efx_port_t *epp = &(enp->en_port); | |
80 | const efx_mac_ops_t *emop = epp->ep_emop; | |
81 | efx_link_mode_t ignore_link_mode; | |
82 | efx_rc_t rc; | |
83 | ||
84 | EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); | |
85 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); | |
86 | ||
87 | EFSYS_ASSERT(emop != NULL); | |
88 | ||
89 | if (link_modep == NULL) | |
90 | link_modep = &ignore_link_mode; | |
91 | ||
92 | if ((rc = emop->emo_poll(enp, link_modep)) != 0) | |
93 | goto fail1; | |
94 | ||
95 | return (0); | |
96 | ||
97 | fail1: | |
98 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
99 | ||
100 | return (rc); | |
101 | } | |
102 | ||
103 | #if EFSYS_OPT_LOOPBACK | |
104 | ||
105 | __checkReturn efx_rc_t | |
106 | efx_port_loopback_set( | |
107 | __in efx_nic_t *enp, | |
108 | __in efx_link_mode_t link_mode, | |
109 | __in efx_loopback_type_t loopback_type) | |
110 | { | |
111 | efx_port_t *epp = &(enp->en_port); | |
112 | efx_nic_cfg_t *encp = &(enp->en_nic_cfg); | |
113 | const efx_mac_ops_t *emop = epp->ep_emop; | |
114 | efx_rc_t rc; | |
115 | ||
116 | EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); | |
117 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); | |
118 | EFSYS_ASSERT(emop != NULL); | |
119 | ||
120 | EFSYS_ASSERT(link_mode < EFX_LINK_NMODES); | |
121 | ||
122 | if (EFX_TEST_QWORD_BIT(encp->enc_loopback_types[link_mode], | |
123 | (int)loopback_type) == 0) { | |
124 | rc = ENOTSUP; | |
125 | goto fail1; | |
126 | } | |
127 | ||
128 | if (epp->ep_loopback_type == loopback_type && | |
129 | epp->ep_loopback_link_mode == link_mode) | |
130 | return (0); | |
131 | ||
132 | if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0) | |
133 | goto fail2; | |
134 | ||
135 | return (0); | |
136 | ||
137 | fail2: | |
138 | EFSYS_PROBE(fail2); | |
139 | fail1: | |
140 | EFSYS_PROBE1(fail1, efx_rc_t, rc); | |
141 | ||
142 | return (rc); | |
143 | } | |
144 | ||
145 | #if EFSYS_OPT_NAMES | |
146 | ||
147 | static const char * const __efx_loopback_type_name[] = { | |
148 | "OFF", | |
149 | "DATA", | |
150 | "GMAC", | |
151 | "XGMII", | |
152 | "XGXS", | |
153 | "XAUI", | |
154 | "GMII", | |
155 | "SGMII", | |
156 | "XGBR", | |
157 | "XFI", | |
158 | "XAUI_FAR", | |
159 | "GMII_FAR", | |
160 | "SGMII_FAR", | |
161 | "XFI_FAR", | |
162 | "GPHY", | |
163 | "PHY_XS", | |
164 | "PCS", | |
165 | "PMA_PMD", | |
166 | "XPORT", | |
167 | "XGMII_WS", | |
168 | "XAUI_WS", | |
169 | "XAUI_WS_FAR", | |
170 | "XAUI_WS_NEAR", | |
171 | "GMII_WS", | |
172 | "XFI_WS", | |
173 | "XFI_WS_FAR", | |
174 | "PHYXS_WS", | |
175 | "PMA_INT", | |
176 | "SD_NEAR", | |
177 | "SD_FAR", | |
178 | "PMA_INT_WS", | |
179 | "SD_FEP2_WS", | |
180 | "SD_FEP1_5_WS", | |
181 | "SD_FEP_WS", | |
182 | "SD_FES_WS", | |
183 | "AOE_INT_NEAR", | |
184 | "DATA_WS", | |
185 | "FORCE_EXT_LINK", | |
186 | }; | |
187 | ||
188 | __checkReturn const char * | |
189 | efx_loopback_type_name( | |
190 | __in efx_nic_t *enp, | |
191 | __in efx_loopback_type_t type) | |
192 | { | |
193 | EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__efx_loopback_type_name) == | |
194 | EFX_LOOPBACK_NTYPES); | |
195 | ||
196 | _NOTE(ARGUNUSED(enp)) | |
197 | EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); | |
198 | EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES); | |
199 | ||
200 | return (__efx_loopback_type_name[type]); | |
201 | } | |
202 | ||
203 | #endif /* EFSYS_OPT_NAMES */ | |
204 | ||
205 | #endif /* EFSYS_OPT_LOOPBACK */ | |
206 | ||
207 | void | |
208 | efx_port_fini( | |
209 | __in efx_nic_t *enp) | |
210 | { | |
211 | efx_port_t *epp = &(enp->en_port); | |
212 | const efx_phy_ops_t *epop = epp->ep_epop; | |
213 | ||
214 | EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC); | |
215 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE); | |
216 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC); | |
217 | EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT); | |
218 | ||
219 | EFSYS_ASSERT(epp->ep_mac_drain); | |
220 | ||
221 | epp->ep_emop = NULL; | |
222 | epp->ep_mac_type = EFX_MAC_INVALID; | |
223 | epp->ep_mac_drain = B_FALSE; | |
224 | ||
225 | /* Turn off the PHY */ | |
226 | if (epop->epo_power != NULL) | |
227 | (void) epop->epo_power(enp, B_FALSE); | |
228 | ||
229 | enp->en_mod_flags &= ~EFX_MOD_PORT; | |
230 | } |