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 * Misc. support routines
19 */
20
21 #include <sys/cmn_err.h>
22 #include <sys/ddi.h>
23 #include <sys/sunddi.h>
24 #include "qede.h"
25
26 typedef struct {
27 uint32_t qsm_type;
28 uint32_t qsm_speed;
29 mac_ether_media_t qsm_media;
30 } qede_sfp_map_t;
31
32 typedef enum {
33 QS_1G = 1000,
34 QS_10G = 10000,
35 QS_25G = 25000,
36 QS_40G = 40000,
37 QS_100G = 100000
38 } qede_speed_t;
39
40 /*
41 * Note, we currently have no mapping for the QEDE 1G PCC/ACC as it is not clear
42 * what spec those are actually referring to. While they have explicit
43 * multi-speed settings for 40/100, we assume the 1/10 multi-speed could occur
44 * and check just in case.
45 */
46 static const qede_sfp_map_t qede_sfp_map[] = {
47 { ETH_TRANSCEIVER_TYPE_1G_LX, QS_1G, ETHER_MEDIA_1000BASE_LX },
48 { ETH_TRANSCEIVER_TYPE_1G_SX, QS_1G, ETHER_MEDIA_1000BASE_SX },
49 { ETH_TRANSCEIVER_TYPE_10G_SR, QS_10G, ETHER_MEDIA_10GBASE_SR },
50 { ETH_TRANSCEIVER_TYPE_10G_SR, QS_1G, ETHER_MEDIA_1000BASE_SX },
51 { ETH_TRANSCEIVER_TYPE_10G_LR, QS_10G, ETHER_MEDIA_10GBASE_LR },
52 { ETH_TRANSCEIVER_TYPE_10G_LR, QS_1G, ETHER_MEDIA_1000BASE_LX },
53 { ETH_TRANSCEIVER_TYPE_10G_LRM, QS_10G, ETHER_MEDIA_10GBASE_LRM },
54 { ETH_TRANSCEIVER_TYPE_10G_ER, QS_10G, ETHER_MEDIA_10GBASE_ER },
55 { ETH_TRANSCEIVER_TYPE_10G_PCC, QS_10G, ETHER_MEDIA_10GBASE_CR },
56 { ETH_TRANSCEIVER_TYPE_10G_ACC, QS_10G, ETHER_MEDIA_10GBASE_ACC },
57 { ETH_TRANSCEIVER_TYPE_XLPPI, QS_40G, ETHER_MEDIA_40G_XLPPI },
58 { ETH_TRANSCEIVER_TYPE_40G_LR4, QS_40G, ETHER_MEDIA_40GBASE_LR4 },
59 { ETH_TRANSCEIVER_TYPE_40G_SR4, QS_40G, ETHER_MEDIA_40GBASE_SR4 },
60 { ETH_TRANSCEIVER_TYPE_40G_CR4, QS_40G, ETHER_MEDIA_40GBASE_CR4 },
61 { ETH_TRANSCEIVER_TYPE_100G_AOC, QS_100G, ETHER_MEDIA_100GBASE_AOC4 },
62 { ETH_TRANSCEIVER_TYPE_100G_SR4, QS_100G, ETHER_MEDIA_100GBASE_SR4 },
63 { ETH_TRANSCEIVER_TYPE_100G_LR4, QS_100G, ETHER_MEDIA_100GBASE_LR4 },
64 { ETH_TRANSCEIVER_TYPE_100G_ER4, QS_100G, ETHER_MEDIA_100GBASE_ER4 },
65 { ETH_TRANSCEIVER_TYPE_100G_ACC, QS_100G, ETHER_MEDIA_100GBASE_ACC4 },
66 { ETH_TRANSCEIVER_TYPE_100G_CR4, QS_100G, ETHER_MEDIA_100GBASE_CR4 },
67 { ETH_TRANSCEIVER_TYPE_4x10G_SR, QS_40G, ETHER_MEDIA_40GBASE_SR4 },
68 { ETH_TRANSCEIVER_TYPE_25G_CA_N, QS_25G, ETHER_MEDIA_25GBASE_CR },
69 { ETH_TRANSCEIVER_TYPE_25G_CA_L, QS_25G, ETHER_MEDIA_25GBASE_CR },
70 { ETH_TRANSCEIVER_TYPE_25G_CA_S, QS_25G, ETHER_MEDIA_25GBASE_CR },
71 { ETH_TRANSCEIVER_TYPE_25G_ACC_S, QS_25G, ETHER_MEDIA_25GBASE_ACC },
72 { ETH_TRANSCEIVER_TYPE_25G_ACC_M, QS_25G, ETHER_MEDIA_25GBASE_ACC },
73 { ETH_TRANSCEIVER_TYPE_25G_ACC_L, QS_25G, ETHER_MEDIA_25GBASE_ACC },
74 { ETH_TRANSCEIVER_TYPE_25G_SR, QS_25G, ETHER_MEDIA_25GBASE_SR },
75 { ETH_TRANSCEIVER_TYPE_25G_LR, QS_25G, ETHER_MEDIA_25GBASE_LR },
76 { ETH_TRANSCEIVER_TYPE_25G_AOC, QS_25G, ETHER_MEDIA_25GBASE_AOC },
77 { ETH_TRANSCEIVER_TYPE_4x10G, QS_40G, ETHER_MEDIA_40GBASE_CR4 },
78 { ETH_TRANSCEIVER_TYPE_4x25G_CR, QS_100G, ETHER_MEDIA_100GBASE_CR4 },
79 { ETH_TRANSCEIVER_TYPE_1000BASET, QS_1G, ETHER_MEDIA_1000BASE_T },
80 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR, QS_40G,
81 ETHER_MEDIA_40GBASE_SR4 },
82 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR, QS_10G,
83 ETHER_MEDIA_10GBASE_SR },
84 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR, QS_40G,
85 ETHER_MEDIA_40GBASE_CR4 },
86 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR, QS_10G,
87 ETHER_MEDIA_10GBASE_CR },
88 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR, QS_40G,
89 ETHER_MEDIA_40GBASE_LR4 },
90 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR, QS_10G,
91 ETHER_MEDIA_10GBASE_LR },
92 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR, QS_100G,
93 ETHER_MEDIA_100GBASE_SR4 },
94 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR, QS_40G,
95 ETHER_MEDIA_40GBASE_SR4 },
96 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR, QS_100G,
97 ETHER_MEDIA_100GBASE_CR4 },
98 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR, QS_40G,
99 ETHER_MEDIA_40GBASE_CR4 },
100 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR, QS_100G,
101 ETHER_MEDIA_100GBASE_LR4 },
102 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR, QS_40G,
103 ETHER_MEDIA_40GBASE_LR4 },
104 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC, QS_100G,
105 ETHER_MEDIA_100GBASE_AOC4 },
106 { ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC, QS_40G,
107 ETHER_MEDIA_40GBASE_AOC4 },
108 };
109
110 mac_ether_media_t
qede_link_to_media(qede_link_cfg_t * cfg,uint32_t speed)111 qede_link_to_media(qede_link_cfg_t *cfg, uint32_t speed)
112 {
113 uint32_t type = (cfg->txr_data & ETH_TRANSCEIVER_TYPE_MASK) >>
114 ETH_TRANSCEIVER_TYPE_SHIFT;
115 switch (cfg->media) {
116 case MEDIA_SFPP_10G_FIBER:
117 case MEDIA_XFP_FIBER:
118 case MEDIA_DA_TWINAX:
119 case MEDIA_SFP_1G_FIBER:
120 case MEDIA_MODULE_FIBER:
121 for (size_t i = 0; i < ARRAY_SIZE(qede_sfp_map); i++) {
122 if (qede_sfp_map[i].qsm_type == type &&
123 qede_sfp_map[i].qsm_speed == speed) {
124 return (qede_sfp_map[i].qsm_media);
125 }
126 }
127 return (ETHER_MEDIA_UNKNOWN);
128 case MEDIA_BASE_T:
129 switch (speed) {
130 case QS_1G:
131 return (ETHER_MEDIA_1000BASE_T);
132 case QS_10G:
133 return (ETHER_MEDIA_10GBASE_T);
134 default:
135 return (ETHER_MEDIA_UNKNOWN);
136 }
137 /*
138 * We don't really know which KR speeds this driver supports and they
139 * don't show up in the common code, so just put our best guesses in
140 * case it ever does.
141 */
142 case MEDIA_KR:
143 switch (speed) {
144 case QS_1G:
145 return (ETHER_MEDIA_1000BASE_KX);
146 case QS_10G:
147 return (ETHER_MEDIA_10GBASE_KR);
148 case QS_25G:
149 return (ETHER_MEDIA_25GBASE_KR);
150 case QS_40G:
151 return (ETHER_MEDIA_40GBASE_KR4);
152 case QS_100G:
153 return (ETHER_MEDIA_100GBASE_KR4);
154 default:
155 return (ETHER_MEDIA_UNKNOWN);
156 }
157 case MEDIA_NOT_PRESENT:
158 return (ETHER_MEDIA_NONE);
159 case MEDIA_UNSPECIFIED:
160 default:
161 return (ETHER_MEDIA_UNKNOWN);
162 }
163 }
164
165 /*
166 * This is our own wrapper around the underlying ecore APIs to read both a
167 * module type and transceiver information data in one go. This should be used
168 * whenever the link is being updated as we cache it to answer questions about
169 * the MAC media or to know whether or not to allow transceiver access to
170 * continue.
171 *
172 * If this fails we will just update the media info with a claim of unknown.
173 */
174 void
qede_update_media_info(struct ecore_dev * edev,qede_link_cfg_t * link)175 qede_update_media_info(struct ecore_dev *edev, qede_link_cfg_t *link)
176 {
177 struct ecore_hwfn *hwfn = &edev->hwfns[0];
178 struct ecore_ptt *ptt;
179
180 link->media = MEDIA_UNSPECIFIED;
181 link->txr_data = ETH_TRANSCEIVER_STATE_UPDATING;
182
183 if (IS_VF(edev) || !ecore_mcp_is_init(hwfn))
184 return;
185
186 ptt = ecore_ptt_acquire(hwfn);
187 if (ptt == NULL)
188 return;
189
190 link->media = ecore_rd(hwfn, ptt, hwfn->mcp_info->port_addr +
191 offsetof(struct public_port, media_type));
192 link->txr_data = ecore_rd(hwfn, ptt, hwfn->mcp_info->port_addr +
193 offsetof(struct public_port, transceiver_data));
194 ecore_ptt_release(hwfn, ptt);
195 }
196
197 /*
198 * We need to emulate sprintf. Unfortunately illumos sprintf does not return the
199 * number of bytes written, only a pointer to the string. Therefore we need this
200 * wrapper.
201 */
202 size_t
qede_sprintf(char * s,const char * fmt,...)203 qede_sprintf(char *s, const char *fmt, ...)
204 {
205 size_t r;
206 va_list args;
207
208 va_start(args, fmt);
209 r = vsnprintf(s, SIZE_MAX, fmt, args);
210 va_end(args);
211
212 return (r);
213 }
214