xref: /illumos-gate/usr/src/uts/common/io/ixgbe/ixgbe_transceiver.c (revision 533affcbc7fc4d0c8132976ea454aaa715fe2307)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright (c) 2017, Joyent, Inc.
14  * Copyright 2023 Oxide Computer Company
15  */
16 
17 /*
18  * Routines to get access to the phy and transceiver that require routines and
19  * definitions that aren't part of the common ixgbe API.
20  */
21 
22 #include "ixgbe_sw.h"
23 #include "ixgbe_phy.h"
24 
25 /*
26  * This is a table that maps various link types, speeds, and physical media
27  * types together to something that can be used. We prefer to use the supported
28  * physical layer types so we can attempt to abstract around the various PHY and
29  * media types and try to create a single coherent place for these.
30  */
31 typedef struct {
32 	uint64_t ipm_phys;
33 	uint32_t ipm_speed;
34 	mac_ether_media_t ipm_media;
35 } ixgbe_phys_map_t;
36 
37 const ixgbe_phys_map_t ixgbe_phys_map[] = {
38 	/*
39 	 * First we lead off with all copper based speeds. Note, some of these
40 	 * may be used through an SFP or similar. SPEED_10 is listed here for
41 	 * completeness sake, as other drivers list them, though it is is hard
42 	 * to figure out how it is possible to get to 10 Mb/s because the X540 /
43 	 * X550 do not support 10BASE-T.
44 	 */
45 	{ IXGBE_PHYSICAL_LAYER_10GBASE_T, SPEED_10GB, ETHER_MEDIA_10GBASE_T },
46 	{ IXGBE_PHYSICAL_LAYER_10GBASE_T, SPEED_5GB, ETHER_MEDIA_5000BASE_T },
47 	{ IXGBE_PHYSICAL_LAYER_10GBASE_T, SPEED_2_5GB, ETHER_MEDIA_2500BASE_T },
48 	{ IXGBE_PHYSICAL_LAYER_10GBASE_T, SPEED_1GB, ETHER_MEDIA_1000BASE_T },
49 	{ IXGBE_PHYSICAL_LAYER_1000BASE_T, SPEED_1GB, ETHER_MEDIA_1000BASE_T },
50 	{ IXGBE_PHYSICAL_LAYER_10GBASE_T, SPEED_100, ETHER_MEDIA_100BASE_TX },
51 	{ IXGBE_PHYSICAL_LAYER_1000BASE_T, SPEED_100, ETHER_MEDIA_100BASE_TX },
52 	{ IXGBE_PHYSICAL_LAYER_100BASE_TX, SPEED_100, ETHER_MEDIA_100BASE_TX },
53 	{ IXGBE_PHYSICAL_LAYER_10GBASE_T, SPEED_10, ETHER_MEDIA_10BASE_T },
54 	{ IXGBE_PHYSICAL_LAYER_1000BASE_T, SPEED_10, ETHER_MEDIA_10BASE_T },
55 	{ IXGBE_PHYSICAL_LAYER_100BASE_TX, SPEED_10, ETHER_MEDIA_10BASE_T },
56 	{ IXGBE_PHYSICAL_LAYER_10BASE_T, SPEED_10, ETHER_MEDIA_10BASE_T },
57 	/*
58 	 * After this point we mostly are in backplane or SFP based formats. In
59 	 * general there is a 1:1 mapping between a physical ability and a
60 	 * speed. However, a few allow multiple speeds to be set and we have to
61 	 * derive this from the common code. Example of this nuance in
62 	 * particular are around KR/KX.
63 	 */
64 	{ IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU, SPEED_10GB,
65 	    ETHER_MEDIA_10GBASE_CR },
66 	{ IXGBE_PHYSICAL_LAYER_10GBASE_LR, SPEED_10GB,
67 	    ETHER_MEDIA_10GBASE_LR },
68 	{ IXGBE_PHYSICAL_LAYER_10GBASE_LR, SPEED_1GB,
69 	    ETHER_MEDIA_1000BASE_LX },
70 	{ IXGBE_PHYSICAL_LAYER_10GBASE_LRM, SPEED_10GB,
71 	    ETHER_MEDIA_10GBASE_LRM },
72 	{ IXGBE_PHYSICAL_LAYER_10GBASE_LRM, SPEED_1GB,
73 	    ETHER_MEDIA_1000BASE_LX },
74 	{ IXGBE_PHYSICAL_LAYER_10GBASE_SR, SPEED_10GB,
75 	    ETHER_MEDIA_10GBASE_SR },
76 	{ IXGBE_PHYSICAL_LAYER_10GBASE_SR, SPEED_1GB,
77 	    ETHER_MEDIA_1000BASE_SX },
78 	{ IXGBE_PHYSICAL_LAYER_10GBASE_KX4, SPEED_10GB,
79 	    ETHER_MEDIA_10GBASE_KX4 },
80 	{ IXGBE_PHYSICAL_LAYER_10GBASE_KX4, SPEED_1GB,
81 	    ETHER_MEDIA_1000BASE_KX },
82 	{ IXGBE_PHYSICAL_LAYER_10GBASE_CX4, SPEED_10GB,
83 	    ETHER_MEDIA_10GBASE_CX4 },
84 	{ IXGBE_PHYSICAL_LAYER_1000BASE_KX, SPEED_1GB,
85 	    ETHER_MEDIA_1000BASE_KX },
86 	{ IXGBE_PHYSICAL_LAYER_1000BASE_BX, SPEED_1GB,
87 	    ETHER_MEDIA_1000BASE_BX },
88 	{ IXGBE_PHYSICAL_LAYER_10GBASE_KR, SPEED_10GB,
89 	    ETHER_MEDIA_10GBASE_KR },
90 	{ IXGBE_PHYSICAL_LAYER_10GBASE_KR, SPEED_2_5GB,
91 	    ETHER_MEDIA_2500BASE_KX },
92 	{ IXGBE_PHYSICAL_LAYER_10GBASE_XAUI, SPEED_10GB,
93 	    ETHER_MEDIA_10G_XAUI },
94 	{ IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA, SPEED_10GB,
95 	    ETHER_MEDIA_10GBASE_ACC },
96 	{ IXGBE_PHYSICAL_LAYER_1000BASE_SX, SPEED_1GB,
97 	    ETHER_MEDIA_1000BASE_SX },
98 	{ IXGBE_PHYSICAL_LAYER_2500BASE_KX, SPEED_2_5GB,
99 	    ETHER_MEDIA_2500BASE_KX }
100 };
101 
102 mac_ether_media_t
103 ixgbe_phy_to_media(ixgbe_t *ixgbe)
104 {
105 	struct ixgbe_hw *hw = &ixgbe->hw;
106 
107 	ASSERT(MUTEX_HELD(&ixgbe->gen_lock));
108 	switch (hw->phy.media_type) {
109 	case ixgbe_media_type_copper:
110 	case ixgbe_media_type_fiber:
111 	case ixgbe_media_type_fiber_fixed:
112 	case ixgbe_media_type_fiber_qsfp:
113 	case ixgbe_media_type_backplane:
114 	case ixgbe_media_type_cx4:
115 		for (size_t i = 0; i < ARRAY_SIZE(ixgbe_phys_map); i++) {
116 			const ixgbe_phys_map_t *map = &ixgbe_phys_map[i];
117 			if ((ixgbe->phys_supported & map->ipm_phys) != 0 &&
118 			    ixgbe->link_speed == map->ipm_speed) {
119 				return (map->ipm_media);
120 			}
121 		}
122 
123 		if (ixgbe->link_state != LINK_STATE_DOWN) {
124 			return (ETHER_MEDIA_UNKNOWN);
125 		} else {
126 			return (ETHER_MEDIA_NONE);
127 		}
128 		break;
129 	/*
130 	 * We don't bother trying to make up anything for a VF.
131 	 */
132 	case ixgbe_media_type_virtual:
133 		return (ETHER_MEDIA_NONE);
134 	default:
135 		return (ETHER_MEDIA_UNKNOWN);
136 	}
137 }
138 
139 static int
140 ixgbe_transceiver_is_8472(ixgbe_t *ixgbe, boolean_t *valp)
141 {
142 	int32_t ret;
143 	uint8_t rev, swap;
144 	struct ixgbe_hw *hw = &ixgbe->hw;
145 
146 	ASSERT(MUTEX_HELD(&ixgbe->gen_lock));
147 	if (hw->phy.ops.read_i2c_eeprom == NULL)
148 		return (ENOTSUP);
149 
150 	ret = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_SFF_8472_COMP, &rev);
151 	if (ret != 0)
152 		return (EIO);
153 
154 	ret = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_SFF_8472_SWAP, &swap);
155 	if (ret != 0)
156 		return (EIO);
157 
158 	if (swap & IXGBE_SFF_ADDRESSING_MODE) {
159 		ixgbe_log(ixgbe, "transceiver requires unsupported address "
160 		    "change for page 0xa2. Access will only be allowed to "
161 		    "page 0xa0.");
162 	}
163 
164 	if (rev == IXGBE_SFF_SFF_8472_UNSUP ||
165 	    (swap & IXGBE_SFF_ADDRESSING_MODE)) {
166 		*valp = B_FALSE;
167 	} else {
168 		*valp = B_TRUE;
169 	}
170 
171 	return (0);
172 }
173 
174 /*
175  * Note, we presume that the mac perimeter is held during these calls. As such,
176  * we rely on that for guaranteeing that only one thread is calling the i2c
177  * routines at any time.
178  */
179 int
180 ixgbe_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
181 {
182 	ixgbe_t *ixgbe = arg;
183 	struct ixgbe_hw *hw = &ixgbe->hw;
184 	boolean_t present, usable;
185 
186 	if (id != 0 || infop == NULL)
187 		return (EINVAL);
188 
189 	mutex_enter(&ixgbe->gen_lock);
190 	if (ixgbe_get_media_type(&ixgbe->hw) == ixgbe_media_type_copper) {
191 		mutex_exit(&ixgbe->gen_lock);
192 		return (ENOTSUP);
193 	}
194 
195 	/*
196 	 * Make sure we have the latest sfp information. This is especially
197 	 * important if the SFP is removed as that doesn't trigger interrupts in
198 	 * our current configuration.
199 	 */
200 	(void) hw->phy.ops.identify_sfp(hw);
201 	if (hw->phy.type == ixgbe_phy_none ||
202 	    (hw->phy.type == ixgbe_phy_unknown &&
203 	    hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
204 		present = B_FALSE;
205 		usable = B_FALSE;
206 	} else {
207 		present = B_TRUE;
208 		usable = hw->phy.type != ixgbe_phy_sfp_unsupported;
209 	}
210 
211 	mutex_exit(&ixgbe->gen_lock);
212 
213 	mac_transceiver_info_set_present(infop, present);
214 	mac_transceiver_info_set_usable(infop, usable);
215 
216 	return (0);
217 }
218 
219 /*
220  * Note, we presume that the mac perimeter is held during these calls. As such,
221  * we rely on that for guaranteeing that only one thread is calling the i2c
222  * routines at any time.
223  */
224 int
225 ixgbe_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
226     size_t nbytes, off_t offset, size_t *nread)
227 {
228 	ixgbe_t *ixgbe = arg;
229 	struct ixgbe_hw *hw = &ixgbe->hw;
230 	uint8_t *buf = bp;
231 	size_t i;
232 	boolean_t is8472;
233 
234 	if (id != 0 || buf == NULL || nbytes == 0 || nread == NULL ||
235 	    (page != 0xa0 && page != 0xa2) || offset < 0)
236 		return (EINVAL);
237 
238 	/*
239 	 * Both supported pages have a length of 256 bytes, ensure nothing asks
240 	 * us to go beyond that.
241 	 */
242 	if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
243 		return (EINVAL);
244 	}
245 
246 	mutex_enter(&ixgbe->gen_lock);
247 	if (ixgbe_get_media_type(&ixgbe->hw) == ixgbe_media_type_copper) {
248 		mutex_exit(&ixgbe->gen_lock);
249 		return (ENOTSUP);
250 	}
251 
252 	if (hw->phy.ops.read_i2c_eeprom == NULL) {
253 		mutex_exit(&ixgbe->gen_lock);
254 		return (ENOTSUP);
255 	}
256 
257 	if (ixgbe_transceiver_is_8472(ixgbe, &is8472) != 0) {
258 		mutex_exit(&ixgbe->gen_lock);
259 		return (EIO);
260 	}
261 
262 	if (!is8472 && page == 0xa2) {
263 		mutex_exit(&ixgbe->gen_lock);
264 		return (EINVAL);
265 	}
266 
267 	for (i = 0; i < nbytes; i++, offset++, buf++) {
268 		int32_t ret;
269 
270 		if (page == 0xa0) {
271 			ret = hw->phy.ops.read_i2c_eeprom(hw, offset, buf);
272 		} else {
273 			ret = hw->phy.ops.read_i2c_sff8472(hw, offset, buf);
274 		}
275 		if (ret != 0) {
276 			mutex_exit(&ixgbe->gen_lock);
277 			return (EIO);
278 		}
279 	}
280 	mutex_exit(&ixgbe->gen_lock);
281 	*nread = i;
282 
283 	return (0);
284 }
285