xref: /illumos-gate/usr/src/uts/common/io/qede/qede_misc.c (revision 09a032ce55a4b25e9a50eba798b5dfa1f449cb4b)
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