xref: /freebsd/sys/dev/sfxge/common/efx_port.c (revision 5dee87d724ce7757c0f542476d7af21666406add)
1e948693eSPhilip Paeps /*-
2e948693eSPhilip Paeps  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3e948693eSPhilip Paeps  *
4e948693eSPhilip Paeps  * Redistribution and use in source and binary forms, with or without
5e948693eSPhilip Paeps  * modification, are permitted provided that the following conditions
6e948693eSPhilip Paeps  * are met:
7e948693eSPhilip Paeps  * 1. Redistributions of source code must retain the above copyright
8e948693eSPhilip Paeps  *    notice, this list of conditions and the following disclaimer.
9e948693eSPhilip Paeps  * 2. Redistributions in binary form must reproduce the above copyright
10e948693eSPhilip Paeps  *    notice, this list of conditions and the following disclaimer in the
11e948693eSPhilip Paeps  *    documentation and/or other materials provided with the distribution.
12e948693eSPhilip Paeps  *
13e948693eSPhilip Paeps  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14e948693eSPhilip Paeps  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15e948693eSPhilip Paeps  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16e948693eSPhilip Paeps  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17e948693eSPhilip Paeps  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18e948693eSPhilip Paeps  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19e948693eSPhilip Paeps  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20e948693eSPhilip Paeps  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21e948693eSPhilip Paeps  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22e948693eSPhilip Paeps  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23e948693eSPhilip Paeps  * SUCH DAMAGE.
24e948693eSPhilip Paeps  */
25e948693eSPhilip Paeps 
26*5dee87d7SPhilip Paeps #include <sys/cdefs.h>
27*5dee87d7SPhilip Paeps __FBSDID("$FreeBSD$");
28*5dee87d7SPhilip Paeps 
29e948693eSPhilip Paeps #include "efsys.h"
30e948693eSPhilip Paeps #include "efx.h"
31e948693eSPhilip Paeps #include "efx_types.h"
32e948693eSPhilip Paeps #include "efx_impl.h"
33e948693eSPhilip Paeps 
34e948693eSPhilip Paeps 	__checkReturn	int
35e948693eSPhilip Paeps efx_port_init(
36e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
37e948693eSPhilip Paeps {
38e948693eSPhilip Paeps 	efx_port_t *epp = &(enp->en_port);
39e948693eSPhilip Paeps 	efx_phy_ops_t *epop = epp->ep_epop;
40e948693eSPhilip Paeps 	int rc;
41e948693eSPhilip Paeps 
42e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
43e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
44e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
45e948693eSPhilip Paeps 
46e948693eSPhilip Paeps 	if (enp->en_mod_flags & EFX_MOD_PORT) {
47e948693eSPhilip Paeps 		rc = EINVAL;
48e948693eSPhilip Paeps 		goto fail1;
49e948693eSPhilip Paeps 	}
50e948693eSPhilip Paeps 
51e948693eSPhilip Paeps 	enp->en_mod_flags |= EFX_MOD_PORT;
52e948693eSPhilip Paeps 
53e948693eSPhilip Paeps 	epp->ep_mac_type = EFX_MAC_INVALID;
54e948693eSPhilip Paeps 	epp->ep_link_mode = EFX_LINK_UNKNOWN;
55e948693eSPhilip Paeps 	epp->ep_mac_poll_needed = B_TRUE;
56e948693eSPhilip Paeps 	epp->ep_mac_drain = B_TRUE;
57e948693eSPhilip Paeps 
58e948693eSPhilip Paeps 	/* Configure the MAC */
59e948693eSPhilip Paeps 	if ((rc = efx_mac_select(enp)) != 0)
60e948693eSPhilip Paeps 		goto fail1;
61e948693eSPhilip Paeps 
62e948693eSPhilip Paeps 	epp->ep_emop->emo_reconfigure(enp);
63e948693eSPhilip Paeps 
64e948693eSPhilip Paeps 	/*
65e948693eSPhilip Paeps 	 * Turn on the PHY if available, otherwise reset it, and
66e948693eSPhilip Paeps 	 * reconfigure it with the current configuration.
67e948693eSPhilip Paeps 	 */
68e948693eSPhilip Paeps 	if (epop->epo_power != NULL) {
69e948693eSPhilip Paeps 		if ((rc = epop->epo_power(enp, B_TRUE)) != 0)
70e948693eSPhilip Paeps 			goto fail2;
71e948693eSPhilip Paeps 	} else {
72e948693eSPhilip Paeps 		if ((rc = epop->epo_reset(enp)) != 0)
73e948693eSPhilip Paeps 			goto fail2;
74e948693eSPhilip Paeps 	}
75e948693eSPhilip Paeps 
76e948693eSPhilip Paeps 	EFSYS_ASSERT(enp->en_reset_flags & EFX_RESET_PHY);
77e948693eSPhilip Paeps 	enp->en_reset_flags &= ~EFX_RESET_PHY;
78e948693eSPhilip Paeps 
79e948693eSPhilip Paeps 	if ((rc = epop->epo_reconfigure(enp)) != 0)
80e948693eSPhilip Paeps 		goto fail3;
81e948693eSPhilip Paeps 
82e948693eSPhilip Paeps 	return (0);
83e948693eSPhilip Paeps 
84e948693eSPhilip Paeps fail3:
85e948693eSPhilip Paeps 	EFSYS_PROBE(fail3);
86e948693eSPhilip Paeps fail2:
87e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
88e948693eSPhilip Paeps fail1:
89e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
90e948693eSPhilip Paeps 
91e948693eSPhilip Paeps 	enp->en_mod_flags &= ~EFX_MOD_PORT;
92e948693eSPhilip Paeps 
93e948693eSPhilip Paeps 	return (rc);
94e948693eSPhilip Paeps }
95e948693eSPhilip Paeps 
96e948693eSPhilip Paeps 	__checkReturn	int
97e948693eSPhilip Paeps efx_port_poll(
98e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
99e948693eSPhilip Paeps 	__out		efx_link_mode_t	*link_modep)
100e948693eSPhilip Paeps {
101e948693eSPhilip Paeps 	efx_port_t *epp = &(enp->en_port);
102e948693eSPhilip Paeps 	efx_mac_ops_t *emop = epp->ep_emop;
103e948693eSPhilip Paeps 	efx_link_mode_t ignore_link_mode;
104e948693eSPhilip Paeps 	int rc;
105e948693eSPhilip Paeps 
106e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
107e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
108e948693eSPhilip Paeps 
109e948693eSPhilip Paeps 	EFSYS_ASSERT(emop != NULL);
110e948693eSPhilip Paeps 	EFSYS_ASSERT(!epp->ep_mac_stats_pending);
111e948693eSPhilip Paeps 
112e948693eSPhilip Paeps 	if (link_modep == NULL)
113e948693eSPhilip Paeps 		link_modep = &ignore_link_mode;
114e948693eSPhilip Paeps 
115e948693eSPhilip Paeps 	if ((rc = emop->emo_poll(enp, link_modep)) != 0)
116e948693eSPhilip Paeps 		goto fail1;
117e948693eSPhilip Paeps 
118e948693eSPhilip Paeps 	return (0);
119e948693eSPhilip Paeps 
120e948693eSPhilip Paeps fail1:
121e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
122e948693eSPhilip Paeps 
123e948693eSPhilip Paeps 	return (rc);
124e948693eSPhilip Paeps }
125e948693eSPhilip Paeps 
126e948693eSPhilip Paeps #if EFSYS_OPT_LOOPBACK
127e948693eSPhilip Paeps 
128e948693eSPhilip Paeps 	__checkReturn	int
129e948693eSPhilip Paeps efx_port_loopback_set(
130e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
131e948693eSPhilip Paeps 	__in		efx_link_mode_t link_mode,
132e948693eSPhilip Paeps 	__in		efx_loopback_type_t loopback_type)
133e948693eSPhilip Paeps {
134e948693eSPhilip Paeps 	efx_port_t *epp = &(enp->en_port);
135e948693eSPhilip Paeps 	efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
136e948693eSPhilip Paeps 	efx_mac_ops_t *emop = epp->ep_emop;
137e948693eSPhilip Paeps 	int rc;
138e948693eSPhilip Paeps 
139e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
140e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
141e948693eSPhilip Paeps 	EFSYS_ASSERT(emop != NULL);
142e948693eSPhilip Paeps 
143e948693eSPhilip Paeps 	EFSYS_ASSERT(link_mode < EFX_LINK_NMODES);
144e948693eSPhilip Paeps 	if ((1 << loopback_type) & ~encp->enc_loopback_types[link_mode]) {
145e948693eSPhilip Paeps 		rc = ENOTSUP;
146e948693eSPhilip Paeps 		goto fail1;
147e948693eSPhilip Paeps 	}
148e948693eSPhilip Paeps 
149e948693eSPhilip Paeps 	if (epp->ep_loopback_type == loopback_type &&
150e948693eSPhilip Paeps 	    epp->ep_loopback_link_mode == link_mode)
151e948693eSPhilip Paeps 		return (0);
152e948693eSPhilip Paeps 
153e948693eSPhilip Paeps 	if ((rc = emop->emo_loopback_set(enp, link_mode, loopback_type)) != 0)
154e948693eSPhilip Paeps 		goto fail2;
155e948693eSPhilip Paeps 
156e948693eSPhilip Paeps 	return (0);
157e948693eSPhilip Paeps 
158e948693eSPhilip Paeps fail2:
159e948693eSPhilip Paeps 	EFSYS_PROBE(fail2);
160e948693eSPhilip Paeps fail1:
161e948693eSPhilip Paeps 	EFSYS_PROBE1(fail1, int, rc);
162e948693eSPhilip Paeps 
163e948693eSPhilip Paeps 	return (rc);
164e948693eSPhilip Paeps }
165e948693eSPhilip Paeps 
166e948693eSPhilip Paeps #if EFSYS_OPT_NAMES
167e948693eSPhilip Paeps 
168e948693eSPhilip Paeps static const char 	__cs * __cs __efx_loopback_type_name[] = {
169e948693eSPhilip Paeps 	"OFF",
170e948693eSPhilip Paeps 	"DATA",
171e948693eSPhilip Paeps 	"GMAC",
172e948693eSPhilip Paeps 	"XGMII",
173e948693eSPhilip Paeps 	"XGXS",
174e948693eSPhilip Paeps 	"XAUI",
175e948693eSPhilip Paeps 	"GMII",
176e948693eSPhilip Paeps 	"SGMII",
177e948693eSPhilip Paeps 	"XGBR",
178e948693eSPhilip Paeps 	"XFI",
179e948693eSPhilip Paeps 	"XAUI_FAR",
180e948693eSPhilip Paeps 	"GMII_FAR",
181e948693eSPhilip Paeps 	"SGMII_FAR",
182e948693eSPhilip Paeps 	"XFI_FAR",
183e948693eSPhilip Paeps 	"GPHY",
184e948693eSPhilip Paeps 	"PHY_XS",
185e948693eSPhilip Paeps 	"PCS",
186e948693eSPhilip Paeps 	"PMA_PMD",
187e948693eSPhilip Paeps };
188e948693eSPhilip Paeps 
189e948693eSPhilip Paeps 	__checkReturn	const char __cs *
190e948693eSPhilip Paeps efx_loopback_type_name(
191e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
192e948693eSPhilip Paeps 	__in		efx_loopback_type_t type)
193e948693eSPhilip Paeps {
194e948693eSPhilip Paeps 	_NOTE(ARGUNUSED(enp))
195e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
196e948693eSPhilip Paeps 	EFSYS_ASSERT3U(type, <, EFX_LOOPBACK_NTYPES);
197e948693eSPhilip Paeps 
198e948693eSPhilip Paeps 	return (__efx_loopback_type_name[type]);
199e948693eSPhilip Paeps }
200e948693eSPhilip Paeps 
201e948693eSPhilip Paeps #endif	/* EFSYS_OPT_NAMES */
202e948693eSPhilip Paeps 
203e948693eSPhilip Paeps #endif	/* EFSYS_OPT_LOOPBACK */
204e948693eSPhilip Paeps 
205e948693eSPhilip Paeps 			void
206e948693eSPhilip Paeps efx_port_fini(
207e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
208e948693eSPhilip Paeps {
209e948693eSPhilip Paeps 	efx_port_t *epp = &(enp->en_port);
210e948693eSPhilip Paeps 	efx_phy_ops_t *epop = epp->ep_epop;
211e948693eSPhilip Paeps 
212e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
213e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
214e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
215e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PORT);
216e948693eSPhilip Paeps 
217e948693eSPhilip Paeps 	EFSYS_ASSERT(epp->ep_mac_drain);
218e948693eSPhilip Paeps 
219e948693eSPhilip Paeps 	epp->ep_emop = NULL;
220e948693eSPhilip Paeps 	epp->ep_mac_type = EFX_MAC_INVALID;
221e948693eSPhilip Paeps 	epp->ep_mac_drain = B_FALSE;
222e948693eSPhilip Paeps 	epp->ep_mac_poll_needed = B_FALSE;
223e948693eSPhilip Paeps 
224e948693eSPhilip Paeps 	/* Turn off the PHY */
225e948693eSPhilip Paeps 	if (epop->epo_power != NULL)
226e948693eSPhilip Paeps 		(void) epop->epo_power(enp, B_FALSE);
227e948693eSPhilip Paeps 
228e948693eSPhilip Paeps 	enp->en_mod_flags &= ~EFX_MOD_PORT;
229e948693eSPhilip Paeps }
230