1 /* SPDX-License-Identifier: BSD-3-Clause 2 * 3 * Copyright(c) 2019-2021 Xilinx, Inc. 4 * Copyright(c) 2009-2019 Solarflare Communications Inc. 5 */ 6 7 #include "efx.h" 8 #include "efx_impl.h" 9 10 #if EFSYS_OPT_SIENA 11 12 static void 13 siena_phy_decode_cap( 14 __in uint32_t mcdi_cap, 15 __out uint32_t *maskp) 16 { 17 uint32_t mask; 18 19 mask = 0; 20 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10HDX_LBN)) 21 mask |= (1 << EFX_PHY_CAP_10HDX); 22 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10FDX_LBN)) 23 mask |= (1 << EFX_PHY_CAP_10FDX); 24 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100HDX_LBN)) 25 mask |= (1 << EFX_PHY_CAP_100HDX); 26 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_100FDX_LBN)) 27 mask |= (1 << EFX_PHY_CAP_100FDX); 28 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000HDX_LBN)) 29 mask |= (1 << EFX_PHY_CAP_1000HDX); 30 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_1000FDX_LBN)) 31 mask |= (1 << EFX_PHY_CAP_1000FDX); 32 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_10000FDX_LBN)) 33 mask |= (1 << EFX_PHY_CAP_10000FDX); 34 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_PAUSE_LBN)) 35 mask |= (1 << EFX_PHY_CAP_PAUSE); 36 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_ASYM_LBN)) 37 mask |= (1 << EFX_PHY_CAP_ASYM); 38 if (mcdi_cap & (1 << MC_CMD_PHY_CAP_AN_LBN)) 39 mask |= (1 << EFX_PHY_CAP_AN); 40 41 *maskp = mask; 42 } 43 44 static void 45 siena_phy_decode_link_mode( 46 __in efx_nic_t *enp, 47 __in uint32_t link_flags, 48 __in unsigned int speed, 49 __in unsigned int fcntl, 50 __out efx_link_mode_t *link_modep, 51 __out unsigned int *fcntlp) 52 { 53 boolean_t fd = !!(link_flags & 54 (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN)); 55 boolean_t up = !!(link_flags & 56 (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN)); 57 58 _NOTE(ARGUNUSED(enp)) 59 60 if (!up) 61 *link_modep = EFX_LINK_DOWN; 62 else if (speed == 10000 && fd) 63 *link_modep = EFX_LINK_10000FDX; 64 else if (speed == 1000) 65 *link_modep = fd ? EFX_LINK_1000FDX : EFX_LINK_1000HDX; 66 else if (speed == 100) 67 *link_modep = fd ? EFX_LINK_100FDX : EFX_LINK_100HDX; 68 else if (speed == 10) 69 *link_modep = fd ? EFX_LINK_10FDX : EFX_LINK_10HDX; 70 else 71 *link_modep = EFX_LINK_UNKNOWN; 72 73 if (fcntl == MC_CMD_FCNTL_OFF) 74 *fcntlp = 0; 75 else if (fcntl == MC_CMD_FCNTL_RESPOND) 76 *fcntlp = EFX_FCNTL_RESPOND; 77 else if (fcntl == MC_CMD_FCNTL_BIDIR) 78 *fcntlp = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE; 79 else { 80 EFSYS_PROBE1(mc_pcol_error, int, fcntl); 81 *fcntlp = 0; 82 } 83 } 84 85 void 86 siena_phy_link_ev( 87 __in efx_nic_t *enp, 88 __in efx_qword_t *eqp, 89 __out efx_link_mode_t *link_modep) 90 { 91 efx_port_t *epp = &(enp->en_port); 92 unsigned int link_flags; 93 unsigned int speed; 94 unsigned int fcntl; 95 efx_link_mode_t link_mode; 96 uint32_t lp_cap_mask; 97 98 /* 99 * Convert the LINKCHANGE speed enumeration into mbit/s, in the 100 * same way as GET_LINK encodes the speed 101 */ 102 switch (MCDI_EV_FIELD(eqp, LINKCHANGE_SPEED)) { 103 case MCDI_EVENT_LINKCHANGE_SPEED_100M: 104 speed = 100; 105 break; 106 case MCDI_EVENT_LINKCHANGE_SPEED_1G: 107 speed = 1000; 108 break; 109 case MCDI_EVENT_LINKCHANGE_SPEED_10G: 110 speed = 10000; 111 break; 112 default: 113 speed = 0; 114 break; 115 } 116 117 link_flags = MCDI_EV_FIELD(eqp, LINKCHANGE_LINK_FLAGS); 118 siena_phy_decode_link_mode(enp, link_flags, speed, 119 MCDI_EV_FIELD(eqp, LINKCHANGE_FCNTL), 120 &link_mode, &fcntl); 121 siena_phy_decode_cap(MCDI_EV_FIELD(eqp, LINKCHANGE_LP_CAP), 122 &lp_cap_mask); 123 124 /* 125 * It's safe to update ep_lp_cap_mask without the driver's port lock 126 * because presumably any concurrently running efx_port_poll() is 127 * only going to arrive at the same value. 128 * 129 * ep_fcntl has two meanings. It's either the link common fcntl 130 * (if the PHY supports AN), or it's the forced link state. If 131 * the former, it's safe to update the value for the same reason as 132 * for ep_lp_cap_mask. If the latter, then just ignore the value, 133 * because we can race with efx_mac_fcntl_set(). 134 */ 135 epp->ep_lp_cap_mask = lp_cap_mask; 136 if (epp->ep_phy_cap_mask & (1 << EFX_PHY_CAP_AN)) 137 epp->ep_fcntl = fcntl; 138 139 *link_modep = link_mode; 140 } 141 142 __checkReturn efx_rc_t 143 siena_phy_power( 144 __in efx_nic_t *enp, 145 __in boolean_t power) 146 { 147 efx_rc_t rc; 148 149 if (!power) 150 return (0); 151 152 /* Check if the PHY is a zombie */ 153 if ((rc = siena_phy_verify(enp)) != 0) 154 goto fail1; 155 156 enp->en_reset_flags |= EFX_RESET_PHY; 157 158 return (0); 159 160 fail1: 161 EFSYS_PROBE1(fail1, efx_rc_t, rc); 162 163 return (rc); 164 } 165 166 __checkReturn efx_rc_t 167 siena_phy_get_link( 168 __in efx_nic_t *enp, 169 __out siena_link_state_t *slsp) 170 { 171 efx_mcdi_req_t req; 172 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_LINK_IN_LEN, 173 MC_CMD_GET_LINK_OUT_LEN); 174 efx_rc_t rc; 175 176 req.emr_cmd = MC_CMD_GET_LINK; 177 req.emr_in_buf = payload; 178 req.emr_in_length = MC_CMD_GET_LINK_IN_LEN; 179 req.emr_out_buf = payload; 180 req.emr_out_length = MC_CMD_GET_LINK_OUT_LEN; 181 182 efx_mcdi_execute(enp, &req); 183 184 if (req.emr_rc != 0) { 185 rc = req.emr_rc; 186 goto fail1; 187 } 188 189 if (req.emr_out_length_used < MC_CMD_GET_LINK_OUT_LEN) { 190 rc = EMSGSIZE; 191 goto fail2; 192 } 193 194 siena_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_CAP), 195 &slsp->sls_adv_cap_mask); 196 siena_phy_decode_cap(MCDI_OUT_DWORD(req, GET_LINK_OUT_LP_CAP), 197 &slsp->sls_lp_cap_mask); 198 199 siena_phy_decode_link_mode(enp, MCDI_OUT_DWORD(req, GET_LINK_OUT_FLAGS), 200 MCDI_OUT_DWORD(req, GET_LINK_OUT_LINK_SPEED), 201 MCDI_OUT_DWORD(req, GET_LINK_OUT_FCNTL), 202 &slsp->sls_link_mode, &slsp->sls_fcntl); 203 204 #if EFSYS_OPT_LOOPBACK 205 /* Assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespace agree */ 206 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_NONE == EFX_LOOPBACK_OFF); 207 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_DATA == EFX_LOOPBACK_DATA); 208 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMAC == EFX_LOOPBACK_GMAC); 209 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGMII == EFX_LOOPBACK_XGMII); 210 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGXS == EFX_LOOPBACK_XGXS); 211 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI == EFX_LOOPBACK_XAUI); 212 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII == EFX_LOOPBACK_GMII); 213 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII == EFX_LOOPBACK_SGMII); 214 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XGBR == EFX_LOOPBACK_XGBR); 215 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI == EFX_LOOPBACK_XFI); 216 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XAUI_FAR == EFX_LOOPBACK_XAUI_FAR); 217 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GMII_FAR == EFX_LOOPBACK_GMII_FAR); 218 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_SGMII_FAR == EFX_LOOPBACK_SGMII_FAR); 219 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_XFI_FAR == EFX_LOOPBACK_XFI_FAR); 220 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_GPHY == EFX_LOOPBACK_GPHY); 221 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PHYXS == EFX_LOOPBACK_PHY_XS); 222 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PCS == EFX_LOOPBACK_PCS); 223 EFX_STATIC_ASSERT(MC_CMD_LOOPBACK_PMAPMD == EFX_LOOPBACK_PMA_PMD); 224 225 slsp->sls_loopback = MCDI_OUT_DWORD(req, GET_LINK_OUT_LOOPBACK_MODE); 226 #endif /* EFSYS_OPT_LOOPBACK */ 227 228 slsp->sls_mac_up = MCDI_OUT_DWORD(req, GET_LINK_OUT_MAC_FAULT) == 0; 229 230 return (0); 231 232 fail2: 233 EFSYS_PROBE(fail2); 234 fail1: 235 EFSYS_PROBE1(fail1, efx_rc_t, rc); 236 237 return (rc); 238 } 239 240 __checkReturn efx_rc_t 241 siena_phy_reconfigure( 242 __in efx_nic_t *enp) 243 { 244 efx_port_t *epp = &(enp->en_port); 245 efx_mcdi_req_t req; 246 EFX_MCDI_DECLARE_BUF(payload, 247 MAX(MC_CMD_SET_ID_LED_IN_LEN, MC_CMD_SET_LINK_IN_LEN), 248 MAX(MC_CMD_SET_ID_LED_OUT_LEN, MC_CMD_SET_LINK_OUT_LEN)); 249 uint32_t cap_mask; 250 #if EFSYS_OPT_PHY_LED_CONTROL 251 unsigned int led_mode; 252 #endif 253 unsigned int speed; 254 efx_rc_t rc; 255 256 req.emr_cmd = MC_CMD_SET_LINK; 257 req.emr_in_buf = payload; 258 req.emr_in_length = MC_CMD_SET_LINK_IN_LEN; 259 req.emr_out_buf = payload; 260 req.emr_out_length = MC_CMD_SET_LINK_OUT_LEN; 261 262 cap_mask = epp->ep_adv_cap_mask; 263 MCDI_IN_POPULATE_DWORD_10(req, SET_LINK_IN_CAP, 264 PHY_CAP_10HDX, (cap_mask >> EFX_PHY_CAP_10HDX) & 0x1, 265 PHY_CAP_10FDX, (cap_mask >> EFX_PHY_CAP_10FDX) & 0x1, 266 PHY_CAP_100HDX, (cap_mask >> EFX_PHY_CAP_100HDX) & 0x1, 267 PHY_CAP_100FDX, (cap_mask >> EFX_PHY_CAP_100FDX) & 0x1, 268 PHY_CAP_1000HDX, (cap_mask >> EFX_PHY_CAP_1000HDX) & 0x1, 269 PHY_CAP_1000FDX, (cap_mask >> EFX_PHY_CAP_1000FDX) & 0x1, 270 PHY_CAP_10000FDX, (cap_mask >> EFX_PHY_CAP_10000FDX) & 0x1, 271 PHY_CAP_PAUSE, (cap_mask >> EFX_PHY_CAP_PAUSE) & 0x1, 272 PHY_CAP_ASYM, (cap_mask >> EFX_PHY_CAP_ASYM) & 0x1, 273 PHY_CAP_AN, (cap_mask >> EFX_PHY_CAP_AN) & 0x1); 274 275 #if EFSYS_OPT_LOOPBACK 276 MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, 277 epp->ep_loopback_type); 278 switch (epp->ep_loopback_link_mode) { 279 case EFX_LINK_100FDX: 280 speed = 100; 281 break; 282 case EFX_LINK_1000FDX: 283 speed = 1000; 284 break; 285 case EFX_LINK_10000FDX: 286 speed = 10000; 287 break; 288 default: 289 speed = 0; 290 } 291 #else 292 MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_MODE, MC_CMD_LOOPBACK_NONE); 293 speed = 0; 294 #endif /* EFSYS_OPT_LOOPBACK */ 295 MCDI_IN_SET_DWORD(req, SET_LINK_IN_LOOPBACK_SPEED, speed); 296 297 #if EFSYS_OPT_PHY_FLAGS 298 MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, epp->ep_phy_flags); 299 #else 300 MCDI_IN_SET_DWORD(req, SET_LINK_IN_FLAGS, 0); 301 #endif /* EFSYS_OPT_PHY_FLAGS */ 302 303 efx_mcdi_execute(enp, &req); 304 305 if (req.emr_rc != 0) { 306 rc = req.emr_rc; 307 goto fail1; 308 } 309 310 /* And set the blink mode */ 311 (void) memset(payload, 0, sizeof (payload)); 312 req.emr_cmd = MC_CMD_SET_ID_LED; 313 req.emr_in_buf = payload; 314 req.emr_in_length = MC_CMD_SET_ID_LED_IN_LEN; 315 req.emr_out_buf = payload; 316 req.emr_out_length = MC_CMD_SET_ID_LED_OUT_LEN; 317 318 #if EFSYS_OPT_PHY_LED_CONTROL 319 switch (epp->ep_phy_led_mode) { 320 case EFX_PHY_LED_DEFAULT: 321 led_mode = MC_CMD_LED_DEFAULT; 322 break; 323 case EFX_PHY_LED_OFF: 324 led_mode = MC_CMD_LED_OFF; 325 break; 326 case EFX_PHY_LED_ON: 327 led_mode = MC_CMD_LED_ON; 328 break; 329 default: 330 EFSYS_ASSERT(0); 331 led_mode = MC_CMD_LED_DEFAULT; 332 } 333 334 MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, led_mode); 335 #else 336 MCDI_IN_SET_DWORD(req, SET_ID_LED_IN_STATE, MC_CMD_LED_DEFAULT); 337 #endif /* EFSYS_OPT_PHY_LED_CONTROL */ 338 339 efx_mcdi_execute(enp, &req); 340 341 if (req.emr_rc != 0) { 342 rc = req.emr_rc; 343 goto fail2; 344 } 345 346 return (0); 347 348 fail2: 349 EFSYS_PROBE(fail2); 350 fail1: 351 EFSYS_PROBE1(fail1, efx_rc_t, rc); 352 353 return (rc); 354 } 355 356 __checkReturn efx_rc_t 357 siena_phy_verify( 358 __in efx_nic_t *enp) 359 { 360 efx_mcdi_req_t req; 361 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_GET_PHY_STATE_IN_LEN, 362 MC_CMD_GET_PHY_STATE_OUT_LEN); 363 uint32_t state; 364 efx_rc_t rc; 365 366 req.emr_cmd = MC_CMD_GET_PHY_STATE; 367 req.emr_in_buf = payload; 368 req.emr_in_length = MC_CMD_GET_PHY_STATE_IN_LEN; 369 req.emr_out_buf = payload; 370 req.emr_out_length = MC_CMD_GET_PHY_STATE_OUT_LEN; 371 372 efx_mcdi_execute(enp, &req); 373 374 if (req.emr_rc != 0) { 375 rc = req.emr_rc; 376 goto fail1; 377 } 378 379 if (req.emr_out_length_used < MC_CMD_GET_PHY_STATE_OUT_LEN) { 380 rc = EMSGSIZE; 381 goto fail2; 382 } 383 384 state = MCDI_OUT_DWORD(req, GET_PHY_STATE_OUT_STATE); 385 if (state != MC_CMD_PHY_STATE_OK) { 386 if (state != MC_CMD_PHY_STATE_ZOMBIE) 387 EFSYS_PROBE1(mc_pcol_error, int, state); 388 rc = ENOTACTIVE; 389 goto fail3; 390 } 391 392 return (0); 393 394 fail3: 395 EFSYS_PROBE(fail3); 396 fail2: 397 EFSYS_PROBE(fail2); 398 fail1: 399 EFSYS_PROBE1(fail1, efx_rc_t, rc); 400 401 return (rc); 402 } 403 404 __checkReturn efx_rc_t 405 siena_phy_oui_get( 406 __in efx_nic_t *enp, 407 __out uint32_t *ouip) 408 { 409 _NOTE(ARGUNUSED(enp, ouip)) 410 411 return (ENOTSUP); 412 } 413 414 #if EFSYS_OPT_PHY_STATS 415 416 #define SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \ 417 _mc_record, _efx_record) \ 418 if ((_vmask) & (1ULL << (_mc_record))) { \ 419 (_smask) |= (1ULL << (_efx_record)); \ 420 if ((_stat) != NULL && !EFSYS_MEM_IS_NULL(_esmp)) { \ 421 efx_dword_t dword; \ 422 EFSYS_MEM_READD(_esmp, (_mc_record) * 4, &dword);\ 423 (_stat)[_efx_record] = \ 424 EFX_DWORD_FIELD(dword, EFX_DWORD_0); \ 425 } \ 426 } 427 428 #define SIENA_SIMPLE_STAT_SET2(_vmask, _esmp, _smask, _stat, _record) \ 429 SIENA_SIMPLE_STAT_SET(_vmask, _esmp, _smask, _stat, \ 430 MC_CMD_ ## _record, \ 431 EFX_PHY_STAT_ ## _record) 432 433 void 434 siena_phy_decode_stats( 435 __in efx_nic_t *enp, 436 __in uint32_t vmask, 437 __in_opt efsys_mem_t *esmp, 438 __out_opt uint64_t *smaskp, 439 __inout_ecount_opt(EFX_PHY_NSTATS) uint32_t *stat) 440 { 441 uint64_t smask = 0; 442 443 _NOTE(ARGUNUSED(enp)) 444 445 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, OUI); 446 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_LINK_UP); 447 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_RX_FAULT); 448 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PMA_PMD_TX_FAULT); 449 450 if (vmask & (1 << MC_CMD_PMA_PMD_SIGNAL)) { 451 smask |= ((1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_A) | 452 (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_B) | 453 (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_C) | 454 (1ULL << EFX_PHY_STAT_PMA_PMD_SIGNAL_D)); 455 if (stat != NULL && esmp != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 456 efx_dword_t dword; 457 uint32_t sig; 458 EFSYS_MEM_READD(esmp, 4 * MC_CMD_PMA_PMD_SIGNAL, 459 &dword); 460 sig = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 461 stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_A] = (sig >> 1) & 1; 462 stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_B] = (sig >> 2) & 1; 463 stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_C] = (sig >> 3) & 1; 464 stat[EFX_PHY_STAT_PMA_PMD_SIGNAL_D] = (sig >> 4) & 1; 465 } 466 } 467 468 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_A, 469 EFX_PHY_STAT_SNR_A); 470 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_B, 471 EFX_PHY_STAT_SNR_B); 472 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_C, 473 EFX_PHY_STAT_SNR_C); 474 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PMA_PMD_SNR_D, 475 EFX_PHY_STAT_SNR_D); 476 477 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_LINK_UP); 478 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_RX_FAULT); 479 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_TX_FAULT); 480 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BER); 481 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, PCS_BLOCK_ERRORS); 482 483 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_LINK_UP, 484 EFX_PHY_STAT_PHY_XS_LINK_UP); 485 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_RX_FAULT, 486 EFX_PHY_STAT_PHY_XS_RX_FAULT); 487 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_TX_FAULT, 488 EFX_PHY_STAT_PHY_XS_TX_FAULT); 489 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_PHYXS_ALIGN, 490 EFX_PHY_STAT_PHY_XS_ALIGN); 491 492 if (vmask & (1 << MC_CMD_PHYXS_SYNC)) { 493 smask |= ((1 << EFX_PHY_STAT_PHY_XS_SYNC_A) | 494 (1 << EFX_PHY_STAT_PHY_XS_SYNC_B) | 495 (1 << EFX_PHY_STAT_PHY_XS_SYNC_C) | 496 (1 << EFX_PHY_STAT_PHY_XS_SYNC_D)); 497 if (stat != NULL && !EFSYS_MEM_IS_NULL(esmp)) { 498 efx_dword_t dword; 499 uint32_t sync; 500 EFSYS_MEM_READD(esmp, 4 * MC_CMD_PHYXS_SYNC, &dword); 501 sync = EFX_DWORD_FIELD(dword, EFX_DWORD_0); 502 stat[EFX_PHY_STAT_PHY_XS_SYNC_A] = (sync >> 0) & 1; 503 stat[EFX_PHY_STAT_PHY_XS_SYNC_B] = (sync >> 1) & 1; 504 stat[EFX_PHY_STAT_PHY_XS_SYNC_C] = (sync >> 2) & 1; 505 stat[EFX_PHY_STAT_PHY_XS_SYNC_D] = (sync >> 3) & 1; 506 } 507 } 508 509 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_LINK_UP); 510 SIENA_SIMPLE_STAT_SET2(vmask, esmp, smask, stat, AN_COMPLETE); 511 512 SIENA_SIMPLE_STAT_SET(vmask, esmp, smask, stat, MC_CMD_CL22_LINK_UP, 513 EFX_PHY_STAT_CL22EXT_LINK_UP); 514 515 if (smaskp != NULL) 516 *smaskp = smask; 517 } 518 519 __checkReturn efx_rc_t 520 siena_phy_stats_update( 521 __in efx_nic_t *enp, 522 __in efsys_mem_t *esmp, 523 __inout_ecount(EFX_PHY_NSTATS) uint32_t *stat) 524 { 525 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 526 uint32_t vmask = encp->enc_mcdi_phy_stat_mask; 527 uint64_t smask; 528 efx_mcdi_req_t req; 529 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_PHY_STATS_IN_LEN, 530 MC_CMD_PHY_STATS_OUT_DMA_LEN); 531 efx_rc_t rc; 532 533 if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_PHY_STATS_SIZE)) { 534 rc = EINVAL; 535 goto fail1; 536 } 537 538 req.emr_cmd = MC_CMD_PHY_STATS; 539 req.emr_in_buf = payload; 540 req.emr_in_length = MC_CMD_PHY_STATS_IN_LEN; 541 req.emr_out_buf = payload; 542 req.emr_out_length = MC_CMD_PHY_STATS_OUT_DMA_LEN; 543 544 MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_LO, 545 EFSYS_MEM_ADDR(esmp) & 0xffffffff); 546 MCDI_IN_SET_DWORD(req, PHY_STATS_IN_DMA_ADDR_HI, 547 EFSYS_MEM_ADDR(esmp) >> 32); 548 549 efx_mcdi_execute(enp, &req); 550 551 if (req.emr_rc != 0) { 552 rc = req.emr_rc; 553 goto fail2; 554 } 555 EFSYS_ASSERT3U(req.emr_out_length, ==, MC_CMD_PHY_STATS_OUT_DMA_LEN); 556 557 siena_phy_decode_stats(enp, vmask, esmp, &smask, stat); 558 EFSYS_ASSERT(smask == encp->enc_phy_stat_mask); 559 560 return (0); 561 562 fail2: 563 EFSYS_PROBE(fail2); 564 fail1: 565 EFSYS_PROBE1(fail1, efx_rc_t, rc); 566 567 return (0); 568 } 569 570 #endif /* EFSYS_OPT_PHY_STATS */ 571 572 #if EFSYS_OPT_BIST 573 574 __checkReturn efx_rc_t 575 siena_phy_bist_start( 576 __in efx_nic_t *enp, 577 __in efx_bist_type_t type) 578 { 579 efx_rc_t rc; 580 581 if ((rc = efx_mcdi_bist_start(enp, type)) != 0) 582 goto fail1; 583 584 return (0); 585 586 fail1: 587 EFSYS_PROBE1(fail1, efx_rc_t, rc); 588 589 return (rc); 590 } 591 592 static __checkReturn unsigned long 593 siena_phy_sft9001_bist_status( 594 __in uint16_t code) 595 { 596 switch (code) { 597 case MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY: 598 return (EFX_PHY_CABLE_STATUS_BUSY); 599 case MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT: 600 return (EFX_PHY_CABLE_STATUS_INTERPAIRSHORT); 601 case MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT: 602 return (EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT); 603 case MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN: 604 return (EFX_PHY_CABLE_STATUS_OPEN); 605 case MC_CMD_POLL_BIST_SFT9001_PAIR_OK: 606 return (EFX_PHY_CABLE_STATUS_OK); 607 default: 608 return (EFX_PHY_CABLE_STATUS_INVALID); 609 } 610 } 611 612 __checkReturn efx_rc_t 613 siena_phy_bist_poll( 614 __in efx_nic_t *enp, 615 __in efx_bist_type_t type, 616 __out efx_bist_result_t *resultp, 617 __out_opt __drv_when(count > 0, __notnull) 618 uint32_t *value_maskp, 619 __out_ecount_opt(count) __drv_when(count > 0, __notnull) 620 unsigned long *valuesp, 621 __in size_t count) 622 { 623 efx_nic_cfg_t *encp = &(enp->en_nic_cfg); 624 EFX_MCDI_DECLARE_BUF(payload, MC_CMD_POLL_BIST_IN_LEN, 625 MCDI_CTL_SDU_LEN_MAX); 626 uint32_t value_mask = 0; 627 efx_mcdi_req_t req; 628 uint32_t result; 629 efx_rc_t rc; 630 631 req.emr_cmd = MC_CMD_POLL_BIST; 632 req.emr_in_buf = payload; 633 req.emr_in_length = MC_CMD_POLL_BIST_IN_LEN; 634 req.emr_out_buf = payload; 635 req.emr_out_length = MCDI_CTL_SDU_LEN_MAX; 636 637 efx_mcdi_execute(enp, &req); 638 639 if (req.emr_rc != 0) { 640 rc = req.emr_rc; 641 goto fail1; 642 } 643 644 if (req.emr_out_length_used < MC_CMD_POLL_BIST_OUT_RESULT_OFST + 4) { 645 rc = EMSGSIZE; 646 goto fail2; 647 } 648 649 if (count > 0) 650 (void) memset(valuesp, '\0', count * sizeof (unsigned long)); 651 652 result = MCDI_OUT_DWORD(req, POLL_BIST_OUT_RESULT); 653 654 /* Extract PHY specific results */ 655 if (result == MC_CMD_POLL_BIST_PASSED && 656 encp->enc_phy_type == EFX_PHY_SFT9001B && 657 req.emr_out_length_used >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN && 658 (type == EFX_BIST_TYPE_PHY_CABLE_SHORT || 659 type == EFX_BIST_TYPE_PHY_CABLE_LONG)) { 660 uint16_t word; 661 662 if (count > EFX_BIST_PHY_CABLE_LENGTH_A) { 663 if (valuesp != NULL) 664 valuesp[EFX_BIST_PHY_CABLE_LENGTH_A] = 665 MCDI_OUT_DWORD(req, 666 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A); 667 value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_A); 668 } 669 670 if (count > EFX_BIST_PHY_CABLE_LENGTH_B) { 671 if (valuesp != NULL) 672 valuesp[EFX_BIST_PHY_CABLE_LENGTH_B] = 673 MCDI_OUT_DWORD(req, 674 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B); 675 value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_B); 676 } 677 678 if (count > EFX_BIST_PHY_CABLE_LENGTH_C) { 679 if (valuesp != NULL) 680 valuesp[EFX_BIST_PHY_CABLE_LENGTH_C] = 681 MCDI_OUT_DWORD(req, 682 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C); 683 value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_C); 684 } 685 686 if (count > EFX_BIST_PHY_CABLE_LENGTH_D) { 687 if (valuesp != NULL) 688 valuesp[EFX_BIST_PHY_CABLE_LENGTH_D] = 689 MCDI_OUT_DWORD(req, 690 POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D); 691 value_mask |= (1 << EFX_BIST_PHY_CABLE_LENGTH_D); 692 } 693 694 if (count > EFX_BIST_PHY_CABLE_STATUS_A) { 695 if (valuesp != NULL) { 696 word = MCDI_OUT_WORD(req, 697 POLL_BIST_OUT_SFT9001_CABLE_STATUS_A); 698 valuesp[EFX_BIST_PHY_CABLE_STATUS_A] = 699 siena_phy_sft9001_bist_status(word); 700 } 701 value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_A); 702 } 703 704 if (count > EFX_BIST_PHY_CABLE_STATUS_B) { 705 if (valuesp != NULL) { 706 word = MCDI_OUT_WORD(req, 707 POLL_BIST_OUT_SFT9001_CABLE_STATUS_B); 708 valuesp[EFX_BIST_PHY_CABLE_STATUS_B] = 709 siena_phy_sft9001_bist_status(word); 710 } 711 value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_B); 712 } 713 714 if (count > EFX_BIST_PHY_CABLE_STATUS_C) { 715 if (valuesp != NULL) { 716 word = MCDI_OUT_WORD(req, 717 POLL_BIST_OUT_SFT9001_CABLE_STATUS_C); 718 valuesp[EFX_BIST_PHY_CABLE_STATUS_C] = 719 siena_phy_sft9001_bist_status(word); 720 } 721 value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_C); 722 } 723 724 if (count > EFX_BIST_PHY_CABLE_STATUS_D) { 725 if (valuesp != NULL) { 726 word = MCDI_OUT_WORD(req, 727 POLL_BIST_OUT_SFT9001_CABLE_STATUS_D); 728 valuesp[EFX_BIST_PHY_CABLE_STATUS_D] = 729 siena_phy_sft9001_bist_status(word); 730 } 731 value_mask |= (1 << EFX_BIST_PHY_CABLE_STATUS_D); 732 } 733 734 } else if (result == MC_CMD_POLL_BIST_FAILED && 735 encp->enc_phy_type == EFX_PHY_QLX111V && 736 req.emr_out_length >= MC_CMD_POLL_BIST_OUT_MRSFP_LEN && 737 count > EFX_BIST_FAULT_CODE) { 738 if (valuesp != NULL) 739 valuesp[EFX_BIST_FAULT_CODE] = 740 MCDI_OUT_DWORD(req, POLL_BIST_OUT_MRSFP_TEST); 741 value_mask |= 1 << EFX_BIST_FAULT_CODE; 742 } 743 744 if (value_maskp != NULL) 745 *value_maskp = value_mask; 746 747 EFSYS_ASSERT(resultp != NULL); 748 if (result == MC_CMD_POLL_BIST_RUNNING) 749 *resultp = EFX_BIST_RESULT_RUNNING; 750 else if (result == MC_CMD_POLL_BIST_PASSED) 751 *resultp = EFX_BIST_RESULT_PASSED; 752 else 753 *resultp = EFX_BIST_RESULT_FAILED; 754 755 return (0); 756 757 fail2: 758 EFSYS_PROBE(fail2); 759 fail1: 760 EFSYS_PROBE1(fail1, efx_rc_t, rc); 761 762 return (rc); 763 } 764 765 void 766 siena_phy_bist_stop( 767 __in efx_nic_t *enp, 768 __in efx_bist_type_t type) 769 { 770 /* There is no way to stop BIST on Siena */ 771 _NOTE(ARGUNUSED(enp, type)) 772 } 773 774 #endif /* EFSYS_OPT_BIST */ 775 776 #endif /* EFSYS_OPT_SIENA */ 777