xref: /freebsd-src/sys/dev/sfxge/common/efx_phy.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
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