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 }