1e948693eSPhilip Paeps /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni *
4929c7febSAndrew Rybchenko * Copyright (c) 2007-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
37e948693eSPhilip Paeps #if EFSYS_OPT_SIENA
38ec831f7fSAndrew Rybchenko static const efx_phy_ops_t __efx_phy_siena_ops = {
39e948693eSPhilip Paeps siena_phy_power, /* epo_power */
40e948693eSPhilip Paeps NULL, /* epo_reset */
41e948693eSPhilip Paeps siena_phy_reconfigure, /* epo_reconfigure */
42e948693eSPhilip Paeps siena_phy_verify, /* epo_verify */
43e948693eSPhilip Paeps siena_phy_oui_get, /* epo_oui_get */
44cf94ca37SAndrew Rybchenko NULL, /* epo_link_state_get */
45e948693eSPhilip Paeps #if EFSYS_OPT_PHY_STATS
46e948693eSPhilip Paeps siena_phy_stats_update, /* epo_stats_update */
47e948693eSPhilip Paeps #endif /* EFSYS_OPT_PHY_STATS */
483c838a9fSAndrew Rybchenko #if EFSYS_OPT_BIST
493c838a9fSAndrew Rybchenko NULL, /* epo_bist_enable_offline */
50e948693eSPhilip Paeps siena_phy_bist_start, /* epo_bist_start */
51e948693eSPhilip Paeps siena_phy_bist_poll, /* epo_bist_poll */
52e948693eSPhilip Paeps siena_phy_bist_stop, /* epo_bist_stop */
533c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
54e948693eSPhilip Paeps };
55e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */
56e948693eSPhilip Paeps
5710d4c14dSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
58ec831f7fSAndrew Rybchenko static const efx_phy_ops_t __efx_phy_ef10_ops = {
59ee2812adSAndrew Rybchenko ef10_phy_power, /* epo_power */
603c838a9fSAndrew Rybchenko NULL, /* epo_reset */
61ee2812adSAndrew Rybchenko ef10_phy_reconfigure, /* epo_reconfigure */
62ee2812adSAndrew Rybchenko ef10_phy_verify, /* epo_verify */
63ee2812adSAndrew Rybchenko ef10_phy_oui_get, /* epo_oui_get */
64cf94ca37SAndrew Rybchenko ef10_phy_link_state_get, /* epo_link_state_get */
653c838a9fSAndrew Rybchenko #if EFSYS_OPT_PHY_STATS
66ee2812adSAndrew Rybchenko ef10_phy_stats_update, /* epo_stats_update */
673c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_PHY_STATS */
683c838a9fSAndrew Rybchenko #if EFSYS_OPT_BIST
69c75d6362SAndrew Rybchenko ef10_bist_enable_offline, /* epo_bist_enable_offline */
70c75d6362SAndrew Rybchenko ef10_bist_start, /* epo_bist_start */
71c75d6362SAndrew Rybchenko ef10_bist_poll, /* epo_bist_poll */
72c75d6362SAndrew Rybchenko ef10_bist_stop, /* epo_bist_stop */
733c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
743c838a9fSAndrew Rybchenko };
7510d4c14dSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
763c838a9fSAndrew Rybchenko
77460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_probe(__in efx_nic_t * enp)78e948693eSPhilip Paeps efx_phy_probe(
79e948693eSPhilip Paeps __in efx_nic_t *enp)
80e948693eSPhilip Paeps {
81e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
82e948693eSPhilip Paeps efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
83ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop;
84460cb568SAndrew Rybchenko efx_rc_t rc;
85e948693eSPhilip Paeps
86e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
87e948693eSPhilip Paeps
88e948693eSPhilip Paeps epp->ep_port = encp->enc_port;
89e948693eSPhilip Paeps epp->ep_phy_type = encp->enc_phy_type;
90e948693eSPhilip Paeps
91e948693eSPhilip Paeps /* Hook in operations structure */
92e948693eSPhilip Paeps switch (enp->en_family) {
93e948693eSPhilip Paeps #if EFSYS_OPT_SIENA
94e948693eSPhilip Paeps case EFX_FAMILY_SIENA:
95ec831f7fSAndrew Rybchenko epop = &__efx_phy_siena_ops;
96e948693eSPhilip Paeps break;
97e948693eSPhilip Paeps #endif /* EFSYS_OPT_SIENA */
9810d4c14dSAndrew Rybchenko
993c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
1003c838a9fSAndrew Rybchenko case EFX_FAMILY_HUNTINGTON:
101ec831f7fSAndrew Rybchenko epop = &__efx_phy_ef10_ops;
1023c838a9fSAndrew Rybchenko break;
1033c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_HUNTINGTON */
10410d4c14dSAndrew Rybchenko
105ee2812adSAndrew Rybchenko #if EFSYS_OPT_MEDFORD
106ee2812adSAndrew Rybchenko case EFX_FAMILY_MEDFORD:
107ec831f7fSAndrew Rybchenko epop = &__efx_phy_ef10_ops;
108ee2812adSAndrew Rybchenko break;
109ee2812adSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD */
11010d4c14dSAndrew Rybchenko
11110d4c14dSAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
11210d4c14dSAndrew Rybchenko case EFX_FAMILY_MEDFORD2:
11310d4c14dSAndrew Rybchenko epop = &__efx_phy_ef10_ops;
11410d4c14dSAndrew Rybchenko break;
11510d4c14dSAndrew Rybchenko #endif /* EFSYS_OPT_MEDFORD2 */
11610d4c14dSAndrew Rybchenko
117e948693eSPhilip Paeps default:
118e948693eSPhilip Paeps rc = ENOTSUP;
119e948693eSPhilip Paeps goto fail1;
120e948693eSPhilip Paeps }
121e948693eSPhilip Paeps
122e948693eSPhilip Paeps epp->ep_epop = epop;
123e948693eSPhilip Paeps
124e948693eSPhilip Paeps return (0);
125e948693eSPhilip Paeps
126e948693eSPhilip Paeps fail1:
127460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
128e948693eSPhilip Paeps
129e948693eSPhilip Paeps epp->ep_port = 0;
130e948693eSPhilip Paeps epp->ep_phy_type = 0;
131e948693eSPhilip Paeps
132e948693eSPhilip Paeps return (rc);
133e948693eSPhilip Paeps }
134e948693eSPhilip Paeps
135460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_verify(__in efx_nic_t * enp)136e948693eSPhilip Paeps efx_phy_verify(
137e948693eSPhilip Paeps __in efx_nic_t *enp)
138e948693eSPhilip Paeps {
139e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
140ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
141e948693eSPhilip Paeps
142e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
143e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
144e948693eSPhilip Paeps
145e948693eSPhilip Paeps return (epop->epo_verify(enp));
146e948693eSPhilip Paeps }
147e948693eSPhilip Paeps
148e948693eSPhilip Paeps #if EFSYS_OPT_PHY_LED_CONTROL
149e948693eSPhilip Paeps
150460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_led_set(__in efx_nic_t * enp,__in efx_phy_led_mode_t mode)151e948693eSPhilip Paeps efx_phy_led_set(
152e948693eSPhilip Paeps __in efx_nic_t *enp,
153e948693eSPhilip Paeps __in efx_phy_led_mode_t mode)
154e948693eSPhilip Paeps {
155e948693eSPhilip Paeps efx_nic_cfg_t *encp = (&enp->en_nic_cfg);
156e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
157ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
158e948693eSPhilip Paeps uint32_t mask;
159460cb568SAndrew Rybchenko efx_rc_t rc;
160e948693eSPhilip Paeps
161e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
162e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
163e948693eSPhilip Paeps
164e948693eSPhilip Paeps if (epp->ep_phy_led_mode == mode)
165e948693eSPhilip Paeps goto done;
166e948693eSPhilip Paeps
167e948693eSPhilip Paeps mask = (1 << EFX_PHY_LED_DEFAULT);
168e948693eSPhilip Paeps mask |= encp->enc_led_mask;
169e948693eSPhilip Paeps
170e948693eSPhilip Paeps if (!((1 << mode) & mask)) {
171e948693eSPhilip Paeps rc = ENOTSUP;
172e948693eSPhilip Paeps goto fail1;
173e948693eSPhilip Paeps }
174e948693eSPhilip Paeps
175e948693eSPhilip Paeps EFSYS_ASSERT3U(mode, <, EFX_PHY_LED_NMODES);
176e948693eSPhilip Paeps epp->ep_phy_led_mode = mode;
177e948693eSPhilip Paeps
178e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0)
179e948693eSPhilip Paeps goto fail2;
180e948693eSPhilip Paeps
181e948693eSPhilip Paeps done:
182e948693eSPhilip Paeps return (0);
183e948693eSPhilip Paeps
184e948693eSPhilip Paeps fail2:
185e948693eSPhilip Paeps EFSYS_PROBE(fail2);
186e948693eSPhilip Paeps fail1:
187460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
188e948693eSPhilip Paeps
189e948693eSPhilip Paeps return (rc);
190e948693eSPhilip Paeps }
191e948693eSPhilip Paeps #endif /* EFSYS_OPT_PHY_LED_CONTROL */
192e948693eSPhilip Paeps
193e948693eSPhilip Paeps void
efx_phy_adv_cap_get(__in efx_nic_t * enp,__in uint32_t flag,__out uint32_t * maskp)194e948693eSPhilip Paeps efx_phy_adv_cap_get(
195e948693eSPhilip Paeps __in efx_nic_t *enp,
196e948693eSPhilip Paeps __in uint32_t flag,
197e948693eSPhilip Paeps __out uint32_t *maskp)
198e948693eSPhilip Paeps {
199e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
200e948693eSPhilip Paeps
201e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
202e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
203e948693eSPhilip Paeps
204e948693eSPhilip Paeps switch (flag) {
205e948693eSPhilip Paeps case EFX_PHY_CAP_CURRENT:
206e948693eSPhilip Paeps *maskp = epp->ep_adv_cap_mask;
207e948693eSPhilip Paeps break;
208e948693eSPhilip Paeps case EFX_PHY_CAP_DEFAULT:
209e948693eSPhilip Paeps *maskp = epp->ep_default_adv_cap_mask;
210e948693eSPhilip Paeps break;
211e948693eSPhilip Paeps case EFX_PHY_CAP_PERM:
212e948693eSPhilip Paeps *maskp = epp->ep_phy_cap_mask;
213e948693eSPhilip Paeps break;
214e948693eSPhilip Paeps default:
215e948693eSPhilip Paeps EFSYS_ASSERT(B_FALSE);
216b20c54ffSAndrew Rybchenko *maskp = 0;
217e948693eSPhilip Paeps break;
218e948693eSPhilip Paeps }
219e948693eSPhilip Paeps }
220e948693eSPhilip Paeps
221460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_adv_cap_set(__in efx_nic_t * enp,__in uint32_t mask)222e948693eSPhilip Paeps efx_phy_adv_cap_set(
223e948693eSPhilip Paeps __in efx_nic_t *enp,
224e948693eSPhilip Paeps __in uint32_t mask)
225e948693eSPhilip Paeps {
226e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
227ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
2284e41fb10SAndrew Rybchenko uint32_t old_mask;
229460cb568SAndrew Rybchenko efx_rc_t rc;
230e948693eSPhilip Paeps
231e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
232e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
233e948693eSPhilip Paeps
2343f3f5d85SAndrew Rybchenko if ((mask & ~epp->ep_phy_cap_mask) != 0) {
235e948693eSPhilip Paeps rc = ENOTSUP;
236e948693eSPhilip Paeps goto fail1;
237e948693eSPhilip Paeps }
238e948693eSPhilip Paeps
239e948693eSPhilip Paeps if (epp->ep_adv_cap_mask == mask)
240e948693eSPhilip Paeps goto done;
241e948693eSPhilip Paeps
2424e41fb10SAndrew Rybchenko old_mask = epp->ep_adv_cap_mask;
243e948693eSPhilip Paeps epp->ep_adv_cap_mask = mask;
244e948693eSPhilip Paeps
245e948693eSPhilip Paeps if ((rc = epop->epo_reconfigure(enp)) != 0)
246e948693eSPhilip Paeps goto fail2;
247e948693eSPhilip Paeps
248e948693eSPhilip Paeps done:
249e948693eSPhilip Paeps return (0);
250e948693eSPhilip Paeps
251e948693eSPhilip Paeps fail2:
252e948693eSPhilip Paeps EFSYS_PROBE(fail2);
2534e41fb10SAndrew Rybchenko
2544e41fb10SAndrew Rybchenko epp->ep_adv_cap_mask = old_mask;
2554e41fb10SAndrew Rybchenko /* Reconfigure for robustness */
2564e41fb10SAndrew Rybchenko if (epop->epo_reconfigure(enp) != 0) {
2574e41fb10SAndrew Rybchenko /*
2584e41fb10SAndrew Rybchenko * We may have an inconsistent view of our advertised speed
2594e41fb10SAndrew Rybchenko * capabilities.
2604e41fb10SAndrew Rybchenko */
2614e41fb10SAndrew Rybchenko EFSYS_ASSERT(0);
2624e41fb10SAndrew Rybchenko }
2634e41fb10SAndrew Rybchenko
264e948693eSPhilip Paeps fail1:
265460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
266e948693eSPhilip Paeps
267e948693eSPhilip Paeps return (rc);
268e948693eSPhilip Paeps }
269e948693eSPhilip Paeps
270e948693eSPhilip Paeps void
efx_phy_lp_cap_get(__in efx_nic_t * enp,__out uint32_t * maskp)271e948693eSPhilip Paeps efx_phy_lp_cap_get(
272e948693eSPhilip Paeps __in efx_nic_t *enp,
273e948693eSPhilip Paeps __out uint32_t *maskp)
274e948693eSPhilip Paeps {
275e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
276e948693eSPhilip Paeps
277e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
278e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
279e948693eSPhilip Paeps
280e948693eSPhilip Paeps *maskp = epp->ep_lp_cap_mask;
281e948693eSPhilip Paeps }
282e948693eSPhilip Paeps
283460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_oui_get(__in efx_nic_t * enp,__out uint32_t * ouip)284e948693eSPhilip Paeps efx_phy_oui_get(
285e948693eSPhilip Paeps __in efx_nic_t *enp,
286e948693eSPhilip Paeps __out uint32_t *ouip)
287e948693eSPhilip Paeps {
288e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
289ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
290e948693eSPhilip Paeps
291e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
292e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
293e948693eSPhilip Paeps
294e948693eSPhilip Paeps return (epop->epo_oui_get(enp, ouip));
295e948693eSPhilip Paeps }
296e948693eSPhilip Paeps
297e948693eSPhilip Paeps void
efx_phy_media_type_get(__in efx_nic_t * enp,__out efx_phy_media_type_t * typep)298e948693eSPhilip Paeps efx_phy_media_type_get(
299e948693eSPhilip Paeps __in efx_nic_t *enp,
300e948693eSPhilip Paeps __out efx_phy_media_type_t *typep)
301e948693eSPhilip Paeps {
302e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
303e948693eSPhilip Paeps
304e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
305e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
306e948693eSPhilip Paeps
307e948693eSPhilip Paeps if (epp->ep_module_type != EFX_PHY_MEDIA_INVALID)
308e948693eSPhilip Paeps *typep = epp->ep_module_type;
309e948693eSPhilip Paeps else
310e948693eSPhilip Paeps *typep = epp->ep_fixed_port_type;
311e948693eSPhilip Paeps }
312e948693eSPhilip Paeps
3131e76f8b8SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_module_get_info(__in efx_nic_t * enp,__in uint8_t dev_addr,__in size_t offset,__in size_t len,__out_bcount (len)uint8_t * data)3141e76f8b8SAndrew Rybchenko efx_phy_module_get_info(
3151e76f8b8SAndrew Rybchenko __in efx_nic_t *enp,
3161e76f8b8SAndrew Rybchenko __in uint8_t dev_addr,
3173c3b9542SAndrew Rybchenko __in size_t offset,
3183c3b9542SAndrew Rybchenko __in size_t len,
3191e76f8b8SAndrew Rybchenko __out_bcount(len) uint8_t *data)
3201e76f8b8SAndrew Rybchenko {
3211e76f8b8SAndrew Rybchenko efx_rc_t rc;
3221e76f8b8SAndrew Rybchenko
3231e76f8b8SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
3241e76f8b8SAndrew Rybchenko EFSYS_ASSERT(data != NULL);
3251e76f8b8SAndrew Rybchenko
3263c3b9542SAndrew Rybchenko if ((offset > EFX_PHY_MEDIA_INFO_MAX_OFFSET) ||
3273c3b9542SAndrew Rybchenko ((offset + len) > EFX_PHY_MEDIA_INFO_MAX_OFFSET)) {
3281e76f8b8SAndrew Rybchenko rc = EINVAL;
3291e76f8b8SAndrew Rybchenko goto fail1;
3301e76f8b8SAndrew Rybchenko }
3311e76f8b8SAndrew Rybchenko
3321e76f8b8SAndrew Rybchenko if ((rc = efx_mcdi_phy_module_get_info(enp, dev_addr,
3331e76f8b8SAndrew Rybchenko offset, len, data)) != 0)
3341e76f8b8SAndrew Rybchenko goto fail2;
3351e76f8b8SAndrew Rybchenko
3361e76f8b8SAndrew Rybchenko return (0);
3371e76f8b8SAndrew Rybchenko
3381e76f8b8SAndrew Rybchenko fail2:
3391e76f8b8SAndrew Rybchenko EFSYS_PROBE(fail2);
3401e76f8b8SAndrew Rybchenko fail1:
3411e76f8b8SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
3421e76f8b8SAndrew Rybchenko
3431e76f8b8SAndrew Rybchenko return (rc);
3441e76f8b8SAndrew Rybchenko }
3451e76f8b8SAndrew Rybchenko
346a8c1489fSAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_fec_type_get(__in efx_nic_t * enp,__out efx_phy_fec_type_t * typep)347a8c1489fSAndrew Rybchenko efx_phy_fec_type_get(
348a8c1489fSAndrew Rybchenko __in efx_nic_t *enp,
349a8c1489fSAndrew Rybchenko __out efx_phy_fec_type_t *typep)
350a8c1489fSAndrew Rybchenko {
351cf94ca37SAndrew Rybchenko efx_rc_t rc;
352cf94ca37SAndrew Rybchenko efx_phy_link_state_t epls;
353cf94ca37SAndrew Rybchenko
354cf94ca37SAndrew Rybchenko if ((rc = efx_phy_link_state_get(enp, &epls)) != 0)
355cf94ca37SAndrew Rybchenko goto fail1;
356cf94ca37SAndrew Rybchenko
357cf94ca37SAndrew Rybchenko *typep = epls.epls_fec;
358cf94ca37SAndrew Rybchenko
359cf94ca37SAndrew Rybchenko return (0);
360cf94ca37SAndrew Rybchenko
361cf94ca37SAndrew Rybchenko fail1:
362cf94ca37SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
363cf94ca37SAndrew Rybchenko
364cf94ca37SAndrew Rybchenko return (rc);
365cf94ca37SAndrew Rybchenko }
366cf94ca37SAndrew Rybchenko
367cf94ca37SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_link_state_get(__in efx_nic_t * enp,__out efx_phy_link_state_t * eplsp)368cf94ca37SAndrew Rybchenko efx_phy_link_state_get(
369cf94ca37SAndrew Rybchenko __in efx_nic_t *enp,
370cf94ca37SAndrew Rybchenko __out efx_phy_link_state_t *eplsp)
371cf94ca37SAndrew Rybchenko {
372a8c1489fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
373a8c1489fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
374a8c1489fSAndrew Rybchenko efx_rc_t rc;
375a8c1489fSAndrew Rybchenko
376a8c1489fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
377cf94ca37SAndrew Rybchenko EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
378a8c1489fSAndrew Rybchenko
379cf94ca37SAndrew Rybchenko if (epop->epo_link_state_get == NULL) {
380a8c1489fSAndrew Rybchenko rc = ENOTSUP;
381a8c1489fSAndrew Rybchenko goto fail1;
382a8c1489fSAndrew Rybchenko }
383a8c1489fSAndrew Rybchenko
384cf94ca37SAndrew Rybchenko if ((rc = epop->epo_link_state_get(enp, eplsp)) != 0)
385a8c1489fSAndrew Rybchenko goto fail2;
386a8c1489fSAndrew Rybchenko
387a8c1489fSAndrew Rybchenko return (0);
388a8c1489fSAndrew Rybchenko
389a8c1489fSAndrew Rybchenko fail2:
390a8c1489fSAndrew Rybchenko EFSYS_PROBE(fail2);
391a8c1489fSAndrew Rybchenko fail1:
392a8c1489fSAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
393a8c1489fSAndrew Rybchenko
394a8c1489fSAndrew Rybchenko return (rc);
395a8c1489fSAndrew Rybchenko }
396a8c1489fSAndrew Rybchenko
397e948693eSPhilip Paeps #if EFSYS_OPT_PHY_STATS
398e948693eSPhilip Paeps
399e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
400e948693eSPhilip Paeps
401a260bd77SAndrew Rybchenko /* START MKCONFIG GENERATED PhyStatNamesBlock af9ffa24da3bc100 */
402a260bd77SAndrew Rybchenko static const char * const __efx_phy_stat_name[] = {
403e948693eSPhilip Paeps "oui",
404e948693eSPhilip Paeps "pma_pmd_link_up",
405e948693eSPhilip Paeps "pma_pmd_rx_fault",
406e948693eSPhilip Paeps "pma_pmd_tx_fault",
407e948693eSPhilip Paeps "pma_pmd_rev_a",
408e948693eSPhilip Paeps "pma_pmd_rev_b",
409e948693eSPhilip Paeps "pma_pmd_rev_c",
410e948693eSPhilip Paeps "pma_pmd_rev_d",
411e948693eSPhilip Paeps "pcs_link_up",
412e948693eSPhilip Paeps "pcs_rx_fault",
413e948693eSPhilip Paeps "pcs_tx_fault",
414e948693eSPhilip Paeps "pcs_ber",
415e948693eSPhilip Paeps "pcs_block_errors",
416e948693eSPhilip Paeps "phy_xs_link_up",
417e948693eSPhilip Paeps "phy_xs_rx_fault",
418e948693eSPhilip Paeps "phy_xs_tx_fault",
419e948693eSPhilip Paeps "phy_xs_align",
420e948693eSPhilip Paeps "phy_xs_sync_a",
421e948693eSPhilip Paeps "phy_xs_sync_b",
422e948693eSPhilip Paeps "phy_xs_sync_c",
423e948693eSPhilip Paeps "phy_xs_sync_d",
424e948693eSPhilip Paeps "an_link_up",
425e948693eSPhilip Paeps "an_master",
426e948693eSPhilip Paeps "an_local_rx_ok",
427e948693eSPhilip Paeps "an_remote_rx_ok",
428e948693eSPhilip Paeps "cl22ext_link_up",
429e948693eSPhilip Paeps "snr_a",
430e948693eSPhilip Paeps "snr_b",
431e948693eSPhilip Paeps "snr_c",
432e948693eSPhilip Paeps "snr_d",
433e948693eSPhilip Paeps "pma_pmd_signal_a",
434e948693eSPhilip Paeps "pma_pmd_signal_b",
435e948693eSPhilip Paeps "pma_pmd_signal_c",
436e948693eSPhilip Paeps "pma_pmd_signal_d",
437e948693eSPhilip Paeps "an_complete",
438e948693eSPhilip Paeps "pma_pmd_rev_major",
439e948693eSPhilip Paeps "pma_pmd_rev_minor",
440e948693eSPhilip Paeps "pma_pmd_rev_micro",
441e948693eSPhilip Paeps "pcs_fw_version_0",
442e948693eSPhilip Paeps "pcs_fw_version_1",
443e948693eSPhilip Paeps "pcs_fw_version_2",
444e948693eSPhilip Paeps "pcs_fw_version_3",
445e948693eSPhilip Paeps "pcs_fw_build_yy",
446e948693eSPhilip Paeps "pcs_fw_build_mm",
447e948693eSPhilip Paeps "pcs_fw_build_dd",
448e948693eSPhilip Paeps "pcs_op_mode",
449e948693eSPhilip Paeps };
450e948693eSPhilip Paeps
451e948693eSPhilip Paeps /* END MKCONFIG GENERATED PhyStatNamesBlock */
452e948693eSPhilip Paeps
4533c838a9fSAndrew Rybchenko const char *
efx_phy_stat_name(__in efx_nic_t * enp,__in efx_phy_stat_t type)454e948693eSPhilip Paeps efx_phy_stat_name(
455e948693eSPhilip Paeps __in efx_nic_t *enp,
456e948693eSPhilip Paeps __in efx_phy_stat_t type)
457e948693eSPhilip Paeps {
458e948693eSPhilip Paeps _NOTE(ARGUNUSED(enp))
459e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
460e948693eSPhilip Paeps EFSYS_ASSERT3U(type, <, EFX_PHY_NSTATS);
461e948693eSPhilip Paeps
462e948693eSPhilip Paeps return (__efx_phy_stat_name[type]);
463e948693eSPhilip Paeps }
464e948693eSPhilip Paeps
465e948693eSPhilip Paeps #endif /* EFSYS_OPT_NAMES */
466e948693eSPhilip Paeps
467460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_phy_stats_update(__in efx_nic_t * enp,__in efsys_mem_t * esmp,__inout_ecount (EFX_PHY_NSTATS)uint32_t * stat)468e948693eSPhilip Paeps efx_phy_stats_update(
469e948693eSPhilip Paeps __in efx_nic_t *enp,
470e948693eSPhilip Paeps __in efsys_mem_t *esmp,
471536c03c2SAndrew Rybchenko __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat)
472e948693eSPhilip Paeps {
473e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
474ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
475e948693eSPhilip Paeps
476e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
477e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
478e948693eSPhilip Paeps
479e948693eSPhilip Paeps return (epop->epo_stats_update(enp, esmp, stat));
480e948693eSPhilip Paeps }
481e948693eSPhilip Paeps
482e948693eSPhilip Paeps #endif /* EFSYS_OPT_PHY_STATS */
483e948693eSPhilip Paeps
4843c838a9fSAndrew Rybchenko #if EFSYS_OPT_BIST
485e948693eSPhilip Paeps
486460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_bist_enable_offline(__in efx_nic_t * enp)4873c838a9fSAndrew Rybchenko efx_bist_enable_offline(
4883c838a9fSAndrew Rybchenko __in efx_nic_t *enp)
489e948693eSPhilip Paeps {
490e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
491ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
492460cb568SAndrew Rybchenko efx_rc_t rc;
493e948693eSPhilip Paeps
494e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
495e948693eSPhilip Paeps
4963c838a9fSAndrew Rybchenko if (epop->epo_bist_enable_offline == NULL) {
4973c838a9fSAndrew Rybchenko rc = ENOTSUP;
4983c838a9fSAndrew Rybchenko goto fail1;
4993c838a9fSAndrew Rybchenko }
5003c838a9fSAndrew Rybchenko
5013c838a9fSAndrew Rybchenko if ((rc = epop->epo_bist_enable_offline(enp)) != 0)
5023c838a9fSAndrew Rybchenko goto fail2;
5033c838a9fSAndrew Rybchenko
5043c838a9fSAndrew Rybchenko return (0);
5053c838a9fSAndrew Rybchenko
5063c838a9fSAndrew Rybchenko fail2:
5073c838a9fSAndrew Rybchenko EFSYS_PROBE(fail2);
5083c838a9fSAndrew Rybchenko fail1:
509460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
5103c838a9fSAndrew Rybchenko
5113c838a9fSAndrew Rybchenko return (rc);
5123c838a9fSAndrew Rybchenko
5133c838a9fSAndrew Rybchenko }
5143c838a9fSAndrew Rybchenko
515460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_bist_start(__in efx_nic_t * enp,__in efx_bist_type_t type)5163c838a9fSAndrew Rybchenko efx_bist_start(
5173c838a9fSAndrew Rybchenko __in efx_nic_t *enp,
5183c838a9fSAndrew Rybchenko __in efx_bist_type_t type)
5193c838a9fSAndrew Rybchenko {
5203c838a9fSAndrew Rybchenko efx_port_t *epp = &(enp->en_port);
521ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
522460cb568SAndrew Rybchenko efx_rc_t rc;
5233c838a9fSAndrew Rybchenko
5243c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5253c838a9fSAndrew Rybchenko
5263c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
5273c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
5283c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(epp->ep_current_bist, ==, EFX_BIST_TYPE_UNKNOWN);
529e948693eSPhilip Paeps
530e948693eSPhilip Paeps if (epop->epo_bist_start == NULL) {
531e948693eSPhilip Paeps rc = ENOTSUP;
532e948693eSPhilip Paeps goto fail1;
533e948693eSPhilip Paeps }
534e948693eSPhilip Paeps
535e948693eSPhilip Paeps if ((rc = epop->epo_bist_start(enp, type)) != 0)
536e948693eSPhilip Paeps goto fail2;
537e948693eSPhilip Paeps
538e948693eSPhilip Paeps epp->ep_current_bist = type;
539e948693eSPhilip Paeps
540e948693eSPhilip Paeps return (0);
541e948693eSPhilip Paeps
542e948693eSPhilip Paeps fail2:
543e948693eSPhilip Paeps EFSYS_PROBE(fail2);
544e948693eSPhilip Paeps fail1:
545460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
546e948693eSPhilip Paeps
547e948693eSPhilip Paeps return (rc);
548e948693eSPhilip Paeps }
549e948693eSPhilip Paeps
550460cb568SAndrew Rybchenko __checkReturn efx_rc_t
efx_bist_poll(__in efx_nic_t * enp,__in efx_bist_type_t type,__out efx_bist_result_t * resultp,__out_opt uint32_t * value_maskp,__out_ecount_opt (count)unsigned long * valuesp,__in size_t count)5513c838a9fSAndrew Rybchenko efx_bist_poll(
552e948693eSPhilip Paeps __in efx_nic_t *enp,
5533c838a9fSAndrew Rybchenko __in efx_bist_type_t type,
5543c838a9fSAndrew Rybchenko __out efx_bist_result_t *resultp,
555e948693eSPhilip Paeps __out_opt uint32_t *value_maskp,
556e948693eSPhilip Paeps __out_ecount_opt(count) unsigned long *valuesp,
557e948693eSPhilip Paeps __in size_t count)
558e948693eSPhilip Paeps {
559e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
560ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
561460cb568SAndrew Rybchenko efx_rc_t rc;
562e948693eSPhilip Paeps
563e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
564e948693eSPhilip Paeps
5653c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
5663c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
567e948693eSPhilip Paeps EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
568e948693eSPhilip Paeps
569e948693eSPhilip Paeps EFSYS_ASSERT(epop->epo_bist_poll != NULL);
570e948693eSPhilip Paeps if (epop->epo_bist_poll == NULL) {
571e948693eSPhilip Paeps rc = ENOTSUP;
572e948693eSPhilip Paeps goto fail1;
573e948693eSPhilip Paeps }
574e948693eSPhilip Paeps
575e948693eSPhilip Paeps if ((rc = epop->epo_bist_poll(enp, type, resultp, value_maskp,
576e948693eSPhilip Paeps valuesp, count)) != 0)
577e948693eSPhilip Paeps goto fail2;
578e948693eSPhilip Paeps
579e948693eSPhilip Paeps return (0);
580e948693eSPhilip Paeps
581e948693eSPhilip Paeps fail2:
582e948693eSPhilip Paeps EFSYS_PROBE(fail2);
583e948693eSPhilip Paeps fail1:
584460cb568SAndrew Rybchenko EFSYS_PROBE1(fail1, efx_rc_t, rc);
585e948693eSPhilip Paeps
586e948693eSPhilip Paeps return (rc);
587e948693eSPhilip Paeps }
588e948693eSPhilip Paeps
589e948693eSPhilip Paeps void
efx_bist_stop(__in efx_nic_t * enp,__in efx_bist_type_t type)5903c838a9fSAndrew Rybchenko efx_bist_stop(
591e948693eSPhilip Paeps __in efx_nic_t *enp,
5923c838a9fSAndrew Rybchenko __in efx_bist_type_t type)
593e948693eSPhilip Paeps {
594e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
595ec831f7fSAndrew Rybchenko const efx_phy_ops_t *epop = epp->ep_epop;
596e948693eSPhilip Paeps
597e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
598e948693eSPhilip Paeps
5993c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(type, !=, EFX_BIST_TYPE_UNKNOWN);
6003c838a9fSAndrew Rybchenko EFSYS_ASSERT3U(type, <, EFX_BIST_TYPE_NTYPES);
601e948693eSPhilip Paeps EFSYS_ASSERT3U(epp->ep_current_bist, ==, type);
602e948693eSPhilip Paeps
603e948693eSPhilip Paeps EFSYS_ASSERT(epop->epo_bist_stop != NULL);
604e948693eSPhilip Paeps
605e948693eSPhilip Paeps if (epop->epo_bist_stop != NULL)
606e948693eSPhilip Paeps epop->epo_bist_stop(enp, type);
607e948693eSPhilip Paeps
6083c838a9fSAndrew Rybchenko epp->ep_current_bist = EFX_BIST_TYPE_UNKNOWN;
609e948693eSPhilip Paeps }
610e948693eSPhilip Paeps
6113c838a9fSAndrew Rybchenko #endif /* EFSYS_OPT_BIST */
612e948693eSPhilip Paeps void
efx_phy_unprobe(__in efx_nic_t * enp)613e948693eSPhilip Paeps efx_phy_unprobe(
614e948693eSPhilip Paeps __in efx_nic_t *enp)
615e948693eSPhilip Paeps {
616e948693eSPhilip Paeps efx_port_t *epp = &(enp->en_port);
617e948693eSPhilip Paeps
618e948693eSPhilip Paeps EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
619e948693eSPhilip Paeps
620e948693eSPhilip Paeps epp->ep_epop = NULL;
621e948693eSPhilip Paeps
622e948693eSPhilip Paeps epp->ep_adv_cap_mask = 0;
623e948693eSPhilip Paeps
624e948693eSPhilip Paeps epp->ep_port = 0;
625e948693eSPhilip Paeps epp->ep_phy_type = 0;
626e948693eSPhilip Paeps }
627