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 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 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 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