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