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