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