1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008-2013 Solarflare Communications Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/sysmacros.h> 29 #include <sys/ddi.h> 30 #include <sys/sunddi.h> 31 #include <sys/cyclic.h> 32 33 #include "sfxge.h" 34 #include "efx.h" 35 36 /* 37 * All efx_phy_*() must be after efx_port_init() 38 * 39 * LOCKING STRATEGY: Aquire sm_lock and test sm_state==SFXGE_MAC_STARTED 40 * to serialise against sfxge_restart() 41 * 42 * Note that there is no seperate PHY lock 43 * Everything is driven from MAC code and the MAC lock is used 44 */ 45 46 /* PHY DMA attributes */ 47 static ddi_device_acc_attr_t sfxge_phy_devacc = { 48 49 DDI_DEVICE_ATTR_V0, /* devacc_attr_version */ 50 DDI_NEVERSWAP_ACC, /* devacc_attr_endian_flags */ 51 DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ 52 }; 53 54 static ddi_dma_attr_t sfxge_phy_dma_attr = { 55 DMA_ATTR_V0, /* dma_attr_version */ 56 0, /* dma_attr_addr_lo */ 57 0xffffffffffffffffull, /* dma_attr_addr_hi */ 58 0xffffffffffffffffull, /* dma_attr_count_max */ 59 0x1000, /* dma_attr_align */ 60 0xffffffff, /* dma_attr_burstsizes */ 61 1, /* dma_attr_minxfer */ 62 0xffffffffffffffffull, /* dma_attr_maxxfer */ 63 0xffffffffffffffffull, /* dma_attr_seg */ 64 1, /* dma_attr_sgllen */ 65 1, /* dma_attr_granular */ 66 0 /* dma_attr_flags */ 67 }; 68 69 70 /* The common code requires the loader *without* the REFLASH_HEADER */ 71 #if EFSYS_OPT_FALCON && EFSYS_OPT_NVRAM_SFT9001 72 static const uint8_t SFT9001_FULL_LOADER[] = { 73 #include "firmware/image.h" 74 #include "firmware/SFT9001A_LOADER.c" 75 }; 76 const uint8_t * const sft9001_loader = SFT9001_FULL_LOADER + 77 sizeof (image_header_t); 78 const size_t sft9001_loader_size = sizeof (SFT9001_FULL_LOADER) - 79 sizeof (image_header_t); 80 #endif 81 82 #if EFSYS_OPT_FALCON && EFSYS_OPT_NVRAM_SFX7101 83 static const uint8_t SFX7101_FULL_LOADER[] = { 84 #include "firmware/image.h" 85 #include "firmware/SFX7101B_LOADER.c" 86 }; 87 const uint8_t * const sfx7101_loader = SFX7101_FULL_LOADER + 88 sizeof (image_header_t); 89 const size_t sfx7101_loader_size = sizeof (SFX7101_FULL_LOADER) - 90 sizeof (image_header_t); 91 #endif 92 93 94 static int 95 sfxge_phy_kstat_update(kstat_t *ksp, int rw) 96 { 97 sfxge_t *sp = ksp->ks_private; 98 sfxge_mac_t *smp = &(sp->s_mac); 99 sfxge_phy_t *spp = &(smp->sm_phy); 100 efx_nic_t *enp = sp->s_enp; 101 kstat_named_t *knp; 102 const efx_nic_cfg_t *encp; 103 int rc, sn; 104 105 if (rw != KSTAT_READ) { 106 rc = EACCES; 107 goto fail1; 108 } 109 110 ASSERT(mutex_owned(&(smp->sm_lock))); 111 112 if (smp->sm_state != SFXGE_MAC_STARTED) 113 goto done; 114 115 /* Synchronize the DMA memory for reading */ 116 (void) ddi_dma_sync(spp->sp_mem.esm_dma_handle, 117 0, 118 EFX_PHY_STATS_SIZE, 119 DDI_DMA_SYNC_FORKERNEL); 120 121 if ((rc = efx_phy_stats_update(enp, &spp->sp_mem, spp->sp_statbuf)) 122 != 0) 123 goto fail2; 124 125 knp = spp->sp_stat; 126 for (sn = 0; sn < EFX_PHY_NSTATS; sn++) { 127 knp->value.ui64 = spp->sp_statbuf[sn]; 128 knp++; 129 } 130 131 encp = efx_nic_cfg_get(enp); 132 knp->value.ui64 = encp->enc_port; 133 134 done: 135 return (0); 136 137 fail2: 138 DTRACE_PROBE(fail2); 139 fail1: 140 DTRACE_PROBE1(fail1, int, rc); 141 142 return (rc); 143 } 144 145 int 146 sfxge_phy_kstat_init(sfxge_t *sp) 147 { 148 dev_info_t *dip = sp->s_dip; 149 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 150 efx_nic_t *enp = sp->s_enp; 151 kstat_t *ksp; 152 kstat_named_t *knp; 153 const efx_nic_cfg_t *encp; 154 unsigned int id; 155 char name[MAXNAMELEN]; 156 int rc; 157 158 if ((spp->sp_statbuf = kmem_zalloc(sizeof (uint32_t) * EFX_PHY_NSTATS, 159 KM_NOSLEEP)) == NULL) { 160 rc = ENOMEM; 161 goto fail1; 162 } 163 164 encp = efx_nic_cfg_get(enp); 165 166 (void) snprintf(name, MAXNAMELEN - 1, "%s_%s", ddi_driver_name(dip), 167 encp->enc_phy_name); 168 169 /* Create the set */ 170 if ((ksp = kstat_create((char *)ddi_driver_name(dip), 171 ddi_get_instance(dip), name, "phy", KSTAT_TYPE_NAMED, 172 EFX_PHY_NSTATS + 1, 0)) == NULL) { 173 rc = ENOMEM; 174 goto fail2; 175 } 176 177 spp->sp_ksp = ksp; 178 179 ksp->ks_update = sfxge_phy_kstat_update; 180 ksp->ks_private = sp; 181 ksp->ks_lock = &(sp->s_mac.sm_lock); 182 183 /* Initialise the named stats */ 184 spp->sp_stat = knp = ksp->ks_data; 185 for (id = 0; id < EFX_PHY_NSTATS; id++) { 186 kstat_named_init(knp, (char *)efx_phy_stat_name(enp, id), 187 KSTAT_DATA_UINT64); 188 knp++; 189 } 190 191 kstat_named_init(knp, "port", KSTAT_DATA_UINT64); 192 kstat_install(ksp); 193 194 return (0); 195 196 fail2: 197 DTRACE_PROBE(fail2) 198 kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS); 199 200 fail1: 201 DTRACE_PROBE1(fail1, int, rc); 202 203 return (rc); 204 } 205 206 void 207 sfxge_phy_kstat_fini(sfxge_t *sp) 208 { 209 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 210 211 /* Destroy the set */ 212 kstat_delete(spp->sp_ksp); 213 spp->sp_ksp = NULL; 214 spp->sp_stat = NULL; 215 216 kmem_free(spp->sp_statbuf, sizeof (uint32_t) * EFX_PHY_NSTATS); 217 } 218 219 220 int 221 sfxge_phy_init(sfxge_t *sp) 222 { 223 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 224 efsys_mem_t *esmp = &(spp->sp_mem); 225 sfxge_dma_buffer_attr_t dma_attr; 226 int rc; 227 228 dma_attr.sdba_dip = sp->s_dip; 229 dma_attr.sdba_dattrp = &sfxge_phy_dma_attr; 230 dma_attr.sdba_callback = DDI_DMA_SLEEP; 231 dma_attr.sdba_length = EFX_PHY_STATS_SIZE; 232 dma_attr.sdba_memflags = DDI_DMA_CONSISTENT; 233 dma_attr.sdba_devaccp = &sfxge_phy_devacc; 234 dma_attr.sdba_bindflags = DDI_DMA_READ | DDI_DMA_CONSISTENT; 235 dma_attr.sdba_maxcookies = 1; 236 dma_attr.sdba_zeroinit = B_TRUE; 237 238 if ((rc = sfxge_dma_buffer_create(esmp, &dma_attr)) != 0) 239 goto fail1; 240 241 return (0); 242 243 fail1: 244 DTRACE_PROBE1(fail1, int, rc); 245 SFXGE_OBJ_CHECK(spp, sfxge_phy_t); 246 247 return (rc); 248 } 249 250 static int 251 sfxge_phy_led_mode_set(sfxge_t *sp, efx_phy_led_mode_t mode) 252 { 253 sfxge_mac_t *smp = &(sp->s_mac); 254 int rc; 255 256 ASSERT3U(smp->sm_state, ==, SFXGE_MAC_STARTED); 257 258 if (mode >= EFX_PHY_LED_NMODES) { 259 rc = EINVAL; 260 goto fail1; 261 } 262 263 mutex_enter(&(smp->sm_lock)); 264 265 if ((rc = efx_phy_led_set(sp->s_enp, mode)) != 0) 266 goto fail2; 267 268 mutex_exit(&(smp->sm_lock)); 269 270 return (0); 271 272 fail2: 273 DTRACE_PROBE(fail2); 274 275 mutex_exit(&(smp->sm_lock)); 276 277 fail1: 278 DTRACE_PROBE1(fail1, int, rc); 279 280 return (rc); 281 } 282 283 284 int 285 sfxge_phy_ioctl(sfxge_t *sp, sfxge_phy_ioc_t *spip) 286 { 287 int rc; 288 289 switch (spip->spi_op) { 290 case SFXGE_PHY_OP_LINK: { 291 break; 292 } 293 case SFXGE_PHY_OP_LED: { 294 efx_phy_led_mode_t mode = spip->spi_data; 295 296 if ((rc = sfxge_phy_led_mode_set(sp, mode)) != 0) 297 goto fail1; 298 299 break; 300 } 301 default: 302 rc = ENOTSUP; 303 goto fail1; 304 } 305 306 return (0); 307 308 fail1: 309 DTRACE_PROBE1(fail1, int, rc); 310 311 return (rc); 312 } 313 314 315 static uint8_t 316 bist_status(unsigned long value) 317 { 318 uint8_t ret; 319 320 efx_phy_cable_status_t status = (efx_phy_cable_status_t)value; 321 switch (status) { 322 case EFX_PHY_CABLE_STATUS_OK: 323 ret = SFXGE_PHY_BIST_CABLE_OK; 324 break; 325 case EFX_PHY_CABLE_STATUS_INVALID: 326 ret = SFXGE_PHY_BIST_CABLE_INVALID; 327 break; 328 case EFX_PHY_CABLE_STATUS_OPEN: 329 ret = SFXGE_PHY_BIST_CABLE_OPEN; 330 break; 331 case EFX_PHY_CABLE_STATUS_INTRAPAIRSHORT: 332 ret = SFXGE_PHY_BIST_CABLE_INTRAPAIRSHORT; 333 break; 334 case EFX_PHY_CABLE_STATUS_INTERPAIRSHORT: 335 ret = SFXGE_PHY_BIST_CABLE_INTERPAIRSHORT; 336 break; 337 case EFX_PHY_CABLE_STATUS_BUSY: 338 ret = SFXGE_PHY_BIST_CABLE_BUSY; 339 break; 340 default: 341 ret = SFXGE_PHY_BIST_CABLE_UNKNOWN; 342 } 343 344 return (ret); 345 } 346 347 348 int 349 sfxge_phy_bist_ioctl(sfxge_t *sp, sfxge_phy_bist_ioc_t *spbip) 350 { 351 sfxge_mac_t *smp = &(sp->s_mac); 352 efx_phy_bist_type_t bist_type; 353 efx_nic_t *enp; 354 const efx_nic_cfg_t *encp; 355 efx_phy_bist_result_t result; 356 unsigned long values[EFX_PHY_BIST_NVALUES]; 357 uint32_t mask; 358 int rc; 359 360 mutex_enter(&(smp->sm_lock)); 361 enp = sp->s_enp; 362 encp = efx_nic_cfg_get(enp); 363 364 bist_type = spbip->spbi_break_link ? EFX_PHY_BIST_TYPE_CABLE_LONG : 365 EFX_PHY_BIST_TYPE_CABLE_SHORT; 366 367 if (~encp->enc_bist_mask & (1 << bist_type)) { 368 rc = ENOTSUP; 369 goto fail1; 370 } 371 372 if ((rc = efx_phy_bist_start(enp, bist_type)) != 0) 373 goto fail2; 374 375 do { 376 /* Spin for 1 ms */ 377 drv_usecwait(1000); 378 379 if ((rc = efx_phy_bist_poll(enp, bist_type, &result, &mask, 380 values, sizeof (values) / sizeof (values[0]))) != 0) 381 goto fail3; 382 383 ASSERT3U(result, !=, EFX_PHY_BIST_RESULT_UNKNOWN); 384 385 } while (result == EFX_PHY_BIST_RESULT_RUNNING); 386 387 ASSERT3U(mask, ==, ((1 << EFX_PHY_BIST_CABLE_LENGTH_A) | 388 (1 << EFX_PHY_BIST_CABLE_LENGTH_B) | 389 (1 << EFX_PHY_BIST_CABLE_LENGTH_C) | 390 (1 << EFX_PHY_BIST_CABLE_LENGTH_D) | 391 (1 << EFX_PHY_BIST_CABLE_STATUS_A) | 392 (1 << EFX_PHY_BIST_CABLE_STATUS_B) | 393 (1 << EFX_PHY_BIST_CABLE_STATUS_C) | 394 (1 << EFX_PHY_BIST_CABLE_STATUS_D))); 395 396 spbip->spbi_status_a = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_A]); 397 spbip->spbi_status_b = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_B]); 398 spbip->spbi_status_c = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_C]); 399 spbip->spbi_status_d = bist_status(values[EFX_PHY_BIST_CABLE_STATUS_D]); 400 401 spbip->spbi_length_ind_a = 402 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_A]; 403 spbip->spbi_length_ind_b = 404 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_B]; 405 spbip->spbi_length_ind_c = 406 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_C]; 407 spbip->spbi_length_ind_d = 408 (uint16_t)values[EFX_PHY_BIST_CABLE_LENGTH_D]; 409 410 /* Bring the PHY back to life */ 411 efx_phy_bist_stop(enp, bist_type); 412 413 mutex_exit(&(smp->sm_lock)); 414 415 return (0); 416 417 fail3: 418 DTRACE_PROBE(fail3); 419 efx_phy_bist_stop(enp, bist_type); 420 fail2: 421 DTRACE_PROBE(fail2); 422 fail1: 423 mutex_exit(&(smp->sm_lock)); 424 DTRACE_PROBE1(fail1, int, rc); 425 426 return (rc); 427 } 428 429 430 uint8_t 431 sfxge_phy_lp_cap_test(sfxge_t *sp, uint32_t field) 432 { 433 sfxge_mac_t *smp = &(sp->s_mac); 434 uint32_t cap = 0; 435 436 mutex_enter(&(smp->sm_lock)); 437 438 if (smp->sm_state != SFXGE_MAC_STARTED) 439 goto done; 440 441 efx_phy_lp_cap_get(sp->s_enp, &cap); 442 443 done: 444 mutex_exit(&(smp->sm_lock)); 445 446 return (cap & (1 << field)); 447 } 448 449 /* 450 * Set up the advertised capabilities that may have been asked for 451 * when the mac was not in the state SFXGE_MAC_STARTED. 452 * Must be called after efx_port_init(). 453 */ 454 int 455 sfxge_phy_cap_apply(sfxge_t *sp, boolean_t use_default) 456 { 457 sfxge_mac_t *smp = &(sp->s_mac); 458 efx_nic_t *enp; 459 uint32_t adv_cap; 460 int rc; 461 int err; 462 463 ASSERT(mutex_owned(&(smp->sm_lock))); 464 465 enp = sp->s_enp; 466 467 if (use_default) 468 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap); 469 else 470 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &adv_cap); 471 472 adv_cap |= smp->sm_phy_cap_to_set; 473 smp->sm_phy_cap_to_set = 0; 474 adv_cap &= ~(smp->sm_phy_cap_to_unset); 475 smp->sm_phy_cap_to_unset = 0; 476 if ((err = efx_phy_adv_cap_set(enp, adv_cap)) != 0) { 477 if (err == EINVAL) { 478 /* 479 * The configuation wasn't accepted, so set to 480 * defaults. 481 */ 482 uint32_t requested = adv_cap; 483 uint32_t supported; 484 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &supported); 485 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_DEFAULT, &adv_cap); 486 if ((rc = efx_phy_adv_cap_set(enp, adv_cap)) != 0) 487 goto fail1; 488 cmn_err(CE_WARN, SFXGE_CMN_ERR 489 "[%s%d] Setting of advertised link " 490 "capabilities failed. " 491 "Using default settings. " 492 "(Requested 0x%x Given 0x%x Supported 0x%x)", 493 ddi_driver_name(sp->s_dip), 494 ddi_get_instance(sp->s_dip), 495 requested, 496 adv_cap, 497 supported); 498 } else { 499 rc = err; 500 goto fail2; 501 } 502 } 503 504 return (0); 505 506 fail2: 507 DTRACE_PROBE(fail2); 508 509 fail1: 510 DTRACE_PROBE1(fail1, int, rc); 511 512 return (rc); 513 } 514 515 uint8_t 516 sfxge_phy_cap_test(sfxge_t *sp, uint32_t flag, uint32_t field, 517 boolean_t *mutablep) 518 { 519 sfxge_mac_t *smp = &(sp->s_mac); 520 efx_nic_t *enp; 521 uint32_t cap = 0; 522 uint32_t perm = 0; 523 524 mutex_enter(&(smp->sm_lock)); 525 enp = sp->s_enp; 526 527 if (smp->sm_state != SFXGE_MAC_STARTED) 528 goto done; 529 530 efx_phy_adv_cap_get(enp, flag, &cap); 531 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_PERM, &perm); 532 533 done: 534 mutex_exit(&(smp->sm_lock)); 535 536 if (mutablep) 537 *mutablep = (perm & (1 << field)) ? B_TRUE : B_FALSE; 538 539 return ((cap & (1 << field)) ? 1 : 0); 540 } 541 542 543 int 544 sfxge_phy_cap_set(sfxge_t *sp, uint32_t field, int set) 545 { 546 sfxge_mac_t *smp = &(sp->s_mac); 547 efx_nic_t *enp = sp->s_enp; 548 uint32_t cap; 549 int rc = 0; 550 551 mutex_enter(&(smp->sm_lock)); 552 553 if (smp->sm_state != SFXGE_MAC_STARTED) { 554 /* Store the request for when the mac is started */ 555 if (set) 556 smp->sm_phy_cap_to_set |= (1 << field); 557 else 558 smp->sm_phy_cap_to_unset |= (1 << field); 559 goto done; 560 } 561 562 efx_phy_adv_cap_get(enp, EFX_PHY_CAP_CURRENT, &cap); 563 564 if (set) 565 cap |= (1 << field); 566 else 567 cap &= ~(1 << field); 568 569 rc = efx_phy_adv_cap_set(enp, cap); 570 done: 571 mutex_exit(&(smp->sm_lock)); 572 573 return (rc); 574 } 575 576 577 int 578 sfxge_phy_prop_get(sfxge_t *sp, unsigned int id, uint32_t flags, uint32_t *valp) 579 { 580 sfxge_mac_t *smp = &(sp->s_mac); 581 efx_nic_t *enp = sp->s_enp; 582 int rc = 0; 583 584 mutex_enter(&(smp->sm_lock)); 585 586 if (smp->sm_state != SFXGE_MAC_STARTED) 587 goto done; 588 589 rc = efx_phy_prop_get(enp, id, flags, valp); 590 591 done: 592 mutex_exit(&(smp->sm_lock)); 593 594 return (rc); 595 } 596 597 598 int 599 sfxge_phy_prop_set(sfxge_t *sp, unsigned int id, uint32_t val) 600 { 601 sfxge_mac_t *smp = &(sp->s_mac); 602 efx_nic_t *enp = sp->s_enp; 603 int rc = 0; 604 605 mutex_enter(&(smp->sm_lock)); 606 607 if (smp->sm_state != SFXGE_MAC_STARTED) 608 goto done; 609 610 rc = efx_phy_prop_set(enp, id, val); 611 612 done: 613 mutex_exit(&(smp->sm_lock)); 614 615 return (rc); 616 } 617 618 619 void 620 sfxge_phy_fini(sfxge_t *sp) 621 { 622 sfxge_phy_t *spp = &(sp->s_mac.sm_phy); 623 efsys_mem_t *esmp = &(spp->sp_mem); 624 625 sfxge_dma_buffer_destroy(esmp); 626 }