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  __checkReturn           int
  32 siena_nic_get_partn_mask(
  33         __in                    efx_nic_t *enp,
  34         __out                   unsigned int *maskp)
  35 {
  36         efx_mcdi_req_t req;
  37         uint8_t outbuf[MC_CMD_NVRAM_TYPES_OUT_LEN];
  38         int rc;
  39 
  40         req.emr_cmd = MC_CMD_NVRAM_TYPES;
  41         EFX_STATIC_ASSERT(MC_CMD_NVRAM_TYPES_IN_LEN == 0);
  42         req.emr_in_buf = NULL;
  43         req.emr_in_length = 0;
  44         req.emr_out_buf = outbuf;
  45         req.emr_out_length = sizeof (outbuf);
  46 
  47         efx_mcdi_execute(enp, &req);
  48 
  49         if (req.emr_rc != 0) {
  50                 rc = req.emr_rc;
  51                 goto fail1;
  52         }
  53 
  54         if (req.emr_out_length_used < MC_CMD_NVRAM_TYPES_OUT_LEN) {
  55                 rc = EMSGSIZE;
  56                 goto fail2;
  57         }
  58 
  59         *maskp = MCDI_OUT_DWORD(req, NVRAM_TYPES_OUT_TYPES);
  60 
  61         return (0);
  62 
  63 fail2:
  64         EFSYS_PROBE(fail2);
  65 fail1:
  66         EFSYS_PROBE1(fail1, int, rc);
  67 
  68         return (rc);
  69 }
  70 
  71 static  __checkReturn   int
  72 siena_nic_exit_assertion_handler(
  73         __in            efx_nic_t *enp)
  74 {
  75         efx_mcdi_req_t req;
  76         uint8_t payload[MC_CMD_REBOOT_IN_LEN];
  77         int rc;
  78 
  79         req.emr_cmd = MC_CMD_REBOOT;
  80         req.emr_in_buf = payload;
  81         req.emr_in_length = MC_CMD_REBOOT_IN_LEN;
  82         EFX_STATIC_ASSERT(MC_CMD_REBOOT_OUT_LEN == 0);
  83         req.emr_out_buf = NULL;
  84         req.emr_out_length = 0;
  85 
  86         MCDI_IN_SET_DWORD(req, REBOOT_IN_FLAGS,
  87                             MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION);
  88 
  89         efx_mcdi_execute(enp, &req);
  90 
  91         if (req.emr_rc != 0 && req.emr_rc != EIO) {
  92                 rc = req.emr_rc;
  93                 goto fail1;
  94         }
  95 
  96         return (0);
  97 
  98 fail1:
  99         EFSYS_PROBE1(fail1, int, rc);
 100 
 101         return (rc);
 102 }
 103 
 104 static  __checkReturn   int
 105 siena_nic_read_assertion(
 106         __in            efx_nic_t *enp)
 107 {
 108         efx_mcdi_req_t req;
 109         uint8_t payload[MAX(MC_CMD_GET_ASSERTS_IN_LEN,
 110                             MC_CMD_GET_ASSERTS_OUT_LEN)];
 111         const char *reason;
 112         unsigned int flags;
 113         unsigned int index;
 114         unsigned int ofst;
 115         int retry;
 116         int rc;
 117 
 118         /*
 119          * Before we attempt to chat to the MC, we should verify that the MC
 120          * isn't in it's assertion handler, either due to a previous reboot,
 121          * or because we're reinitializing due to an eec_exception().
 122          *
 123          * Use GET_ASSERTS to read any assertion state that may be present.
 124          * Retry this command twice. Once because a boot-time assertion failure
 125          * might cause the 1st MCDI request to fail. And once again because
 126          * we might race with siena_nic_exit_assertion_handler() running on the
 127          * other port.
 128          */
 129         retry = 2;
 130         do {
 131                 req.emr_cmd = MC_CMD_GET_ASSERTS;
 132                 req.emr_in_buf = payload;
 133                 req.emr_in_length = MC_CMD_GET_ASSERTS_IN_LEN;
 134                 req.emr_out_buf = payload;
 135                 req.emr_out_length = MC_CMD_GET_ASSERTS_OUT_LEN;
 136 
 137                 MCDI_IN_SET_DWORD(req, GET_ASSERTS_IN_CLEAR, 1);
 138                 efx_mcdi_execute(enp, &req);
 139 
 140         } while ((req.emr_rc == EINTR || req.emr_rc == EIO) && retry-- > 0);
 141 
 142         if (req.emr_rc != 0) {
 143                 rc = req.emr_rc;
 144                 goto fail1;
 145         }
 146 
 147         if (req.emr_out_length_used < MC_CMD_GET_ASSERTS_OUT_LEN) {
 148                 rc = EMSGSIZE;
 149                 goto fail2;
 150         }
 151 
 152         /* Print out any assertion state recorded */
 153         flags = MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_GLOBAL_FLAGS);
 154         if (flags == MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS)
 155                 return (0);
 156 
 157         reason = (flags == MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL)
 158                 ? "system-level assertion"
 159                 : (flags == MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL)
 160                 ? "thread-level assertion"
 161                 : (flags == MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED)
 162                 ? "watchdog reset"
 163                 : "unknown assertion";
 164         EFSYS_PROBE3(mcpu_assertion,
 165             const char *, reason, unsigned int,
 166             MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_SAVED_PC_OFFS),
 167             unsigned int,
 168             MCDI_OUT_DWORD(req, GET_ASSERTS_OUT_THREAD_OFFS));
 169 
 170         /* Print out the registers */
 171         ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
 172         for (index = 1; index < 32; index++) {
 173                 EFSYS_PROBE2(mcpu_register, unsigned int, index, unsigned int,
 174                             EFX_DWORD_FIELD(*MCDI_OUT(req, efx_dword_t, ofst),
 175                                             EFX_DWORD_0));
 176                 ofst += sizeof (efx_dword_t);
 177         }
 178         EFSYS_ASSERT(ofst <= MC_CMD_GET_ASSERTS_OUT_LEN);
 179 
 180         return (0);
 181 
 182 fail2:
 183         EFSYS_PROBE(fail2);
 184 fail1:
 185         EFSYS_PROBE1(fail1, int, rc);
 186 
 187         return (rc);
 188 }
 189 
 190 static  __checkReturn   int
 191 siena_nic_attach(
 192         __in            efx_nic_t *enp,
 193         __in            boolean_t attach)
 194 {
 195         efx_mcdi_req_t req;
 196         uint8_t payload[MC_CMD_DRV_ATTACH_IN_LEN];
 197         int rc;
 198 
 199         req.emr_cmd = MC_CMD_DRV_ATTACH;
 200         req.emr_in_buf = payload;
 201         req.emr_in_length = MC_CMD_DRV_ATTACH_IN_LEN;
 202         req.emr_out_buf = NULL;
 203         req.emr_out_length = 0;
 204 
 205         MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_NEW_STATE, attach ? 1 : 0);
 206         MCDI_IN_SET_DWORD(req, DRV_ATTACH_IN_UPDATE, 1);
 207 
 208         efx_mcdi_execute(enp, &req);
 209 
 210         if (req.emr_rc != 0) {
 211                 rc = req.emr_rc;
 212                 goto fail1;
 213         }
 214 
 215         if (req.emr_out_length_used < MC_CMD_DRV_ATTACH_OUT_LEN) {
 216                 rc = EMSGSIZE;
 217                 goto fail2;
 218         }
 219 
 220         return (0);
 221 
 222 fail2:
 223         EFSYS_PROBE(fail2);
 224 fail1:
 225         EFSYS_PROBE1(fail1, int, rc);
 226 
 227         return (rc);
 228 }
 229 
 230 #if EFSYS_OPT_PCIE_TUNE
 231 
 232         __checkReturn   int
 233 siena_nic_pcie_extended_sync(
 234         __in            efx_nic_t *enp)
 235 {
 236         uint8_t inbuf[MC_CMD_WORKAROUND_IN_LEN];
 237         efx_mcdi_req_t req;
 238         int rc;
 239 
 240         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
 241 
 242         req.emr_cmd = MC_CMD_WORKAROUND;
 243         req.emr_in_buf = inbuf;
 244         req.emr_in_length = sizeof (inbuf);
 245         EFX_STATIC_ASSERT(MC_CMD_WORKAROUND_OUT_LEN == 0);
 246         req.emr_out_buf = NULL;
 247         req.emr_out_length = 0;
 248 
 249         MCDI_IN_SET_DWORD(req, WORKAROUND_IN_TYPE, MC_CMD_WORKAROUND_BUG17230);
 250         MCDI_IN_SET_DWORD(req, WORKAROUND_IN_ENABLED, 1);
 251 
 252         efx_mcdi_execute(enp, &req);
 253 
 254         if (req.emr_rc != 0) {
 255                 rc = req.emr_rc;
 256                 goto fail1;
 257         }
 258 
 259         return (0);
 260 
 261 fail1:
 262         EFSYS_PROBE1(fail1, int, rc);
 263 
 264         return (rc);
 265 }
 266 
 267 #endif  /* EFSYS_OPT_PCIE_TUNE */
 268 
 269 static  __checkReturn   int
 270 siena_board_cfg(
 271         __in            efx_nic_t *enp)
 272 {
 273         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 274         efx_mcdi_iface_t *emip = &(enp->en_u.siena.enu_mip);
 275         uint8_t outbuf[MAX(MC_CMD_GET_BOARD_CFG_OUT_LENMIN,
 276                     MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN)];
 277         efx_mcdi_req_t req;
 278         uint8_t *mac_addr;
 279         efx_dword_t *capabilities;
 280         int rc;
 281 
 282         /* Board configuration */
 283         req.emr_cmd = MC_CMD_GET_BOARD_CFG;
 284         EFX_STATIC_ASSERT(MC_CMD_GET_BOARD_CFG_IN_LEN == 0);
 285         req.emr_in_buf = NULL;
 286         req.emr_in_length = 0;
 287         req.emr_out_buf = outbuf;
 288         req.emr_out_length = MC_CMD_GET_BOARD_CFG_OUT_LENMIN;
 289 
 290         efx_mcdi_execute(enp, &req);
 291 
 292         if (req.emr_rc != 0) {
 293                 rc = req.emr_rc;
 294                 goto fail1;
 295         }
 296 
 297         if (req.emr_out_length_used < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) {
 298                 rc = EMSGSIZE;
 299                 goto fail2;
 300         }
 301 
 302         if (emip->emi_port == 1) {
 303                 mac_addr = MCDI_OUT2(req, uint8_t,
 304                             GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0);
 305                 capabilities = MCDI_OUT2(req, efx_dword_t,
 306                             GET_BOARD_CFG_OUT_CAPABILITIES_PORT0);
 307         } else {
 308                 mac_addr = MCDI_OUT2(req, uint8_t,
 309                             GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1);
 310                 capabilities = MCDI_OUT2(req, efx_dword_t,
 311                             GET_BOARD_CFG_OUT_CAPABILITIES_PORT1);
 312         }
 313         EFX_MAC_ADDR_COPY(encp->enc_mac_addr, mac_addr);
 314 
 315         encp->enc_board_type = MCDI_OUT_DWORD(req,
 316                                     GET_BOARD_CFG_OUT_BOARD_TYPE);
 317 
 318         /* Additional capabilities */
 319         encp->enc_clk_mult = 1;
 320         if (MCDI_CMD_DWORD_FIELD(capabilities, CAPABILITIES_TURBO)) {
 321                 enp->en_features |= EFX_FEATURE_TURBO;
 322 
 323                 if (MCDI_CMD_DWORD_FIELD(capabilities,
 324                     CAPABILITIES_TURBO_ACTIVE))
 325                         encp->enc_clk_mult = 2;
 326         }
 327 
 328         encp->enc_evq_timer_quantum_ns =
 329                 EFX_EVQ_SIENA_TIMER_QUANTUM_NS / encp->enc_clk_mult;
 330         encp->enc_evq_timer_max_us = (encp->enc_evq_timer_quantum_ns <<
 331                 FRF_CZ_TC_TIMER_VAL_WIDTH) / 1000;
 332 
 333         /* Resource limits */
 334         req.emr_cmd = MC_CMD_GET_RESOURCE_LIMITS;
 335         EFX_STATIC_ASSERT(MC_CMD_GET_RESOURCE_LIMITS_IN_LEN == 0);
 336         req.emr_in_buf = NULL;
 337         req.emr_in_length = 0;
 338         req.emr_out_buf = outbuf;
 339         req.emr_out_length = MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN;
 340 
 341         efx_mcdi_execute(enp, &req);
 342 
 343         if (req.emr_rc == 0) {
 344                 if (req.emr_out_length_used <
 345                     MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN) {
 346                         rc = EMSGSIZE;
 347                         goto fail3;
 348                 }
 349 
 350                 encp->enc_evq_limit = MCDI_OUT_DWORD(req,
 351                     GET_RESOURCE_LIMITS_OUT_EVQ);
 352                 encp->enc_txq_limit = MIN(EFX_TXQ_LIMIT_TARGET,
 353                     MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_TXQ));
 354                 encp->enc_rxq_limit = MIN(EFX_RXQ_LIMIT_TARGET,
 355                     MCDI_OUT_DWORD(req, GET_RESOURCE_LIMITS_OUT_RXQ));
 356         } else if (req.emr_rc == ENOTSUP) {
 357                 encp->enc_evq_limit = 1024;
 358                 encp->enc_txq_limit = EFX_TXQ_LIMIT_TARGET;
 359                 encp->enc_rxq_limit = EFX_RXQ_LIMIT_TARGET;
 360         } else {
 361                 rc = req.emr_rc;
 362                 goto fail4;
 363         }
 364 
 365         encp->enc_buftbl_limit = SIENA_SRAM_ROWS -
 366             (encp->enc_txq_limit * EFX_TXQ_DC_NDESCS(EFX_TXQ_DC_SIZE)) -
 367             (encp->enc_rxq_limit * EFX_RXQ_DC_NDESCS(EFX_RXQ_DC_SIZE));
 368 
 369         return (0);
 370 
 371 fail4:
 372         EFSYS_PROBE(fail4);
 373 fail3:
 374         EFSYS_PROBE(fail3);
 375 fail2:
 376         EFSYS_PROBE(fail2);
 377 fail1:
 378         EFSYS_PROBE1(fail1, int, rc);
 379 
 380         return (rc);
 381 }
 382 
 383 static  __checkReturn   int
 384 siena_phy_cfg(
 385         __in            efx_nic_t *enp)
 386 {
 387         efx_port_t *epp = &(enp->en_port);
 388         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 389         efx_mcdi_req_t req;
 390         uint8_t outbuf[MC_CMD_GET_PHY_CFG_OUT_LEN];
 391         int rc;
 392 
 393         req.emr_cmd = MC_CMD_GET_PHY_CFG;
 394         EFX_STATIC_ASSERT(MC_CMD_GET_PHY_CFG_IN_LEN == 0);
 395         req.emr_in_buf = NULL;
 396         req.emr_in_length = 0;
 397         req.emr_out_buf = outbuf;
 398         req.emr_out_length = sizeof (outbuf);
 399 
 400         efx_mcdi_execute(enp, &req);
 401 
 402         if (req.emr_rc != 0) {
 403                 rc = req.emr_rc;
 404                 goto fail1;
 405         }
 406 
 407         if (req.emr_out_length_used < MC_CMD_GET_PHY_CFG_OUT_LEN) {
 408                 rc = EMSGSIZE;
 409                 goto fail2;
 410         }
 411 
 412         encp->enc_phy_type = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_TYPE);
 413 #if EFSYS_OPT_NAMES
 414         (void) strncpy(encp->enc_phy_name,
 415                 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_NAME),
 416                 MIN(sizeof (encp->enc_phy_name) - 1,
 417                     MC_CMD_GET_PHY_CFG_OUT_NAME_LEN));
 418 #endif  /* EFSYS_OPT_NAMES */
 419         (void) memset(encp->enc_phy_revision, 0,
 420             sizeof (encp->enc_phy_revision));
 421         memcpy(encp->enc_phy_revision,
 422                 MCDI_OUT2(req, char, GET_PHY_CFG_OUT_REVISION),
 423                 MIN(sizeof (encp->enc_phy_revision) - 1,
 424                     MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN));
 425 #if EFSYS_OPT_PHY_LED_CONTROL
 426         encp->enc_led_mask = ((1 << EFX_PHY_LED_DEFAULT) |
 427                             (1 << EFX_PHY_LED_OFF) |
 428                             (1 << EFX_PHY_LED_ON));
 429 #endif  /* EFSYS_OPT_PHY_LED_CONTROL */
 430 
 431 #if EFSYS_OPT_PHY_PROPS
 432         encp->enc_phy_nprops  = 0;
 433 #endif  /* EFSYS_OPT_PHY_PROPS */
 434 
 435         /* Get the media type of the fixed port, if recognised. */
 436         EFX_STATIC_ASSERT(MC_CMD_MEDIA_XAUI == EFX_PHY_MEDIA_XAUI);
 437         EFX_STATIC_ASSERT(MC_CMD_MEDIA_CX4 == EFX_PHY_MEDIA_CX4);
 438         EFX_STATIC_ASSERT(MC_CMD_MEDIA_KX4 == EFX_PHY_MEDIA_KX4);
 439         EFX_STATIC_ASSERT(MC_CMD_MEDIA_XFP == EFX_PHY_MEDIA_XFP);
 440         EFX_STATIC_ASSERT(MC_CMD_MEDIA_SFP_PLUS == EFX_PHY_MEDIA_SFP_PLUS);
 441         EFX_STATIC_ASSERT(MC_CMD_MEDIA_BASE_T == EFX_PHY_MEDIA_BASE_T);
 442         epp->ep_fixed_port_type =
 443                 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_MEDIA_TYPE);
 444         if (epp->ep_fixed_port_type >= EFX_PHY_MEDIA_NTYPES)
 445                 epp->ep_fixed_port_type = EFX_PHY_MEDIA_INVALID;
 446 
 447         epp->ep_phy_cap_mask =
 448                 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_SUPPORTED_CAP);
 449 #if EFSYS_OPT_PHY_FLAGS
 450         encp->enc_phy_flags_mask = MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_FLAGS);
 451 #endif  /* EFSYS_OPT_PHY_FLAGS */
 452 
 453         encp->enc_port = (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_PRT);
 454 
 455         /* Populate internal state */
 456         encp->enc_siena_channel =
 457                 (uint8_t)MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_CHANNEL);
 458 
 459 #if EFSYS_OPT_PHY_STATS
 460         encp->enc_siena_phy_stat_mask =
 461                 MCDI_OUT_DWORD(req, GET_PHY_CFG_OUT_STATS_MASK);
 462 
 463         /* Convert the MCDI statistic mask into the EFX_PHY_STAT mask */
 464         siena_phy_decode_stats(enp, encp->enc_siena_phy_stat_mask,
 465                             NULL, &encp->enc_phy_stat_mask, NULL);
 466 #endif  /* EFSYS_OPT_PHY_STATS */
 467 
 468 #if EFSYS_OPT_PHY_BIST
 469         encp->enc_bist_mask = 0;
 470         if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
 471             GET_PHY_CFG_OUT_BIST_CABLE_SHORT))
 472                 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_SHORT);
 473         if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
 474             GET_PHY_CFG_OUT_BIST_CABLE_LONG))
 475                 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_CABLE_LONG);
 476         if (MCDI_OUT_DWORD_FIELD(req, GET_PHY_CFG_OUT_FLAGS,
 477             GET_PHY_CFG_OUT_BIST))
 478                 encp->enc_bist_mask |= (1 << EFX_PHY_BIST_TYPE_NORMAL);
 479 #endif  /* EFSYS_OPT_PHY_BIST */
 480 
 481         return (0);
 482 
 483 fail2:
 484         EFSYS_PROBE(fail2);
 485 fail1:
 486         EFSYS_PROBE1(fail1, int, rc);
 487 
 488         return (rc);
 489 }
 490 
 491 #if EFSYS_OPT_LOOPBACK
 492 
 493 static  __checkReturn   int
 494 siena_loopback_cfg(
 495         __in            efx_nic_t *enp)
 496 {
 497         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 498         efx_mcdi_req_t req;
 499         uint8_t outbuf[MC_CMD_GET_LOOPBACK_MODES_OUT_LEN];
 500         int rc;
 501 
 502         req.emr_cmd = MC_CMD_GET_LOOPBACK_MODES;
 503         EFX_STATIC_ASSERT(MC_CMD_GET_LOOPBACK_MODES_IN_LEN == 0);
 504         req.emr_in_buf = NULL;
 505         req.emr_in_length = 0;
 506         req.emr_out_buf = outbuf;
 507         req.emr_out_length = sizeof (outbuf);
 508 
 509         efx_mcdi_execute(enp, &req);
 510 
 511         if (req.emr_rc != 0) {
 512                 rc = req.emr_rc;
 513                 goto fail1;
 514         }
 515 
 516         if (req.emr_out_length_used < MC_CMD_GET_LOOPBACK_MODES_OUT_LEN) {
 517                 rc = EMSGSIZE;
 518                 goto fail2;
 519         }
 520 
 521         /*
 522          * We assert the MC_CMD_LOOPBACK and EFX_LOOPBACK namespaces agree
 523          * in siena_phy.c:siena_phy_get_link()
 524          */
 525         encp->enc_loopback_types[EFX_LINK_100FDX] = EFX_LOOPBACK_MASK &
 526             MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_100M) &
 527             MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
 528         encp->enc_loopback_types[EFX_LINK_1000FDX] = EFX_LOOPBACK_MASK &
 529             MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_1G) &
 530             MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
 531         encp->enc_loopback_types[EFX_LINK_10000FDX] = EFX_LOOPBACK_MASK &
 532             MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_10G) &
 533             MCDI_OUT_DWORD(req, GET_LOOPBACK_MODES_OUT_SUGGESTED);
 534         encp->enc_loopback_types[EFX_LINK_UNKNOWN] =
 535             (1 << EFX_LOOPBACK_OFF) |
 536             encp->enc_loopback_types[EFX_LINK_100FDX] |
 537             encp->enc_loopback_types[EFX_LINK_1000FDX] |
 538             encp->enc_loopback_types[EFX_LINK_10000FDX];
 539 
 540         return (0);
 541 
 542 fail2:
 543         EFSYS_PROBE(fail2);
 544 fail1:
 545         EFSYS_PROBE1(fail1, int, rc);
 546 
 547         return (rc);
 548 }
 549 
 550 #endif  /* EFSYS_OPT_LOOPBACK */
 551 
 552 #if EFSYS_OPT_MON_STATS
 553 
 554 static  __checkReturn   int
 555 siena_monitor_cfg(
 556         __in            efx_nic_t *enp)
 557 {
 558         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 559         efx_mcdi_req_t req;
 560         uint8_t outbuf[MCDI_CTL_SDU_LEN_MAX];
 561         int rc;
 562 
 563         req.emr_cmd = MC_CMD_SENSOR_INFO;
 564         EFX_STATIC_ASSERT(MC_CMD_SENSOR_INFO_IN_LEN == 0);
 565         req.emr_in_buf = NULL;
 566         req.emr_in_length = 0;
 567         req.emr_out_buf = outbuf;
 568         req.emr_out_length = sizeof (outbuf);
 569 
 570         efx_mcdi_execute(enp, &req);
 571 
 572         if (req.emr_rc != 0) {
 573                 rc = req.emr_rc;
 574                 goto fail1;
 575         }
 576 
 577         if (req.emr_out_length_used < MC_CMD_SENSOR_INFO_OUT_MASK_OFST + 4) {
 578                 rc = EMSGSIZE;
 579                 goto fail2;
 580         }
 581 
 582         encp->enc_siena_mon_stat_mask =
 583                 MCDI_OUT_DWORD(req, SENSOR_INFO_OUT_MASK);
 584         encp->enc_mon_type = EFX_MON_SFC90X0;
 585 
 586         siena_mon_decode_stats(enp, encp->enc_siena_mon_stat_mask,
 587                             NULL, &(encp->enc_mon_stat_mask), NULL);
 588 
 589         return (0);
 590 
 591 fail2:
 592         EFSYS_PROBE(fail2);
 593 fail1:
 594         EFSYS_PROBE1(fail1, int, rc);
 595 
 596         return (rc);
 597 }
 598 
 599 #endif  /* EFSYS_OPT_MON_STATS */
 600 
 601         __checkReturn   int
 602 siena_nic_probe(
 603         __in            efx_nic_t *enp)
 604 {
 605         efx_port_t *epp = &(enp->en_port);
 606         efx_nic_cfg_t *encp = &(enp->en_nic_cfg);
 607         siena_link_state_t sls;
 608         unsigned int mask;
 609         int rc;
 610 
 611         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
 612 
 613         /* Read clear any assertion state */
 614         if ((rc = siena_nic_read_assertion(enp)) != 0)
 615                 goto fail1;
 616 
 617         /* Exit the assertion handler */
 618         if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
 619                 goto fail2;
 620 
 621         /* Wrestle control from the BMC */
 622         if ((rc = siena_nic_attach(enp, B_TRUE)) != 0)
 623                 goto fail3;
 624 
 625         if ((rc = siena_board_cfg(enp)) != 0)
 626                 goto fail4;
 627 
 628         if ((rc = siena_phy_cfg(enp)) != 0)
 629                 goto fail5;
 630 
 631         /* Obtain the default PHY advertised capabilities */
 632         if ((rc = siena_nic_reset(enp)) != 0)
 633                 goto fail6;
 634         if ((rc = siena_phy_get_link(enp, &sls)) != 0)
 635                 goto fail7;
 636         epp->ep_default_adv_cap_mask = sls.sls_adv_cap_mask;
 637         epp->ep_adv_cap_mask = sls.sls_adv_cap_mask;
 638 
 639 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
 640         if ((rc = siena_nic_get_partn_mask(enp, &mask)) != 0)
 641                 goto fail8;
 642         enp->en_u.siena.enu_partn_mask = mask;
 643 #endif
 644 
 645 #if EFSYS_OPT_MAC_STATS
 646         /* Wipe the MAC statistics */
 647         if ((rc = siena_mac_stats_clear(enp)) != 0)
 648                 goto fail9;
 649 #endif
 650 
 651 #if EFSYS_OPT_LOOPBACK
 652         if ((rc = siena_loopback_cfg(enp)) != 0)
 653                 goto fail10;
 654 #endif
 655 
 656 #if EFSYS_OPT_MON_STATS
 657         if ((rc = siena_monitor_cfg(enp)) != 0)
 658                 goto fail11;
 659 #endif
 660 
 661         encp->enc_features = enp->en_features;
 662 
 663         return (0);
 664 
 665 #if EFSYS_OPT_MON_STATS
 666 fail11:
 667         EFSYS_PROBE(fail11);
 668 #endif
 669 #if EFSYS_OPT_LOOPBACK
 670 fail10:
 671         EFSYS_PROBE(fail10);
 672 #endif
 673 #if EFSYS_OPT_MAC_STATS
 674 fail9:
 675         EFSYS_PROBE(fail9);
 676 #endif
 677 #if EFSYS_OPT_VPD || EFSYS_OPT_NVRAM
 678 fail8:
 679         EFSYS_PROBE(fail8);
 680 #endif
 681 fail7:
 682         EFSYS_PROBE(fail7);
 683 fail6:
 684         EFSYS_PROBE(fail6);
 685 fail5:
 686         EFSYS_PROBE(fail5);
 687 fail4:
 688         EFSYS_PROBE(fail4);
 689 fail3:
 690         EFSYS_PROBE(fail3);
 691 fail2:
 692         EFSYS_PROBE(fail2);
 693 fail1:
 694         EFSYS_PROBE1(fail1, int, rc);
 695 
 696         return (rc);
 697 }
 698 
 699         __checkReturn   int
 700 siena_nic_reset(
 701         __in            efx_nic_t *enp)
 702 {
 703         efx_mcdi_req_t req;
 704         int rc;
 705 
 706         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
 707 
 708         /* siena_nic_reset() is called to recover from BADASSERT failures. */
 709         if ((rc = siena_nic_read_assertion(enp)) != 0)
 710                 goto fail1;
 711         if ((rc = siena_nic_exit_assertion_handler(enp)) != 0)
 712                 goto fail2;
 713 
 714         req.emr_cmd = MC_CMD_PORT_RESET;
 715         EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_IN_LEN == 0);
 716         req.emr_in_buf = NULL;
 717         req.emr_in_length = 0;
 718         EFX_STATIC_ASSERT(MC_CMD_PORT_RESET_OUT_LEN == 0);
 719         req.emr_out_buf = NULL;
 720         req.emr_out_length = 0;
 721 
 722         efx_mcdi_execute(enp, &req);
 723 
 724         if (req.emr_rc != 0) {
 725                 rc = req.emr_rc;
 726                 goto fail3;
 727         }
 728 
 729         return (0);
 730 
 731 fail3:
 732         EFSYS_PROBE(fail3);
 733 fail2:
 734         EFSYS_PROBE(fail2);
 735 fail1:
 736         EFSYS_PROBE1(fail1, int, rc);
 737 
 738         return (0);
 739 }
 740 
 741 static  __checkReturn   int
 742 siena_nic_logging(
 743         __in            efx_nic_t *enp)
 744 {
 745         efx_mcdi_req_t req;
 746         uint8_t payload[MC_CMD_LOG_CTRL_IN_LEN];
 747         int rc;
 748 
 749         req.emr_cmd = MC_CMD_LOG_CTRL;
 750         req.emr_in_buf = payload;
 751         req.emr_in_length = MC_CMD_LOG_CTRL_IN_LEN;
 752         EFX_STATIC_ASSERT(MC_CMD_LOG_CTRL_OUT_LEN == 0);
 753         req.emr_out_buf = NULL;
 754         req.emr_out_length = 0;
 755 
 756         MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST,
 757                     MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ);
 758         MCDI_IN_SET_DWORD(req, LOG_CTRL_IN_LOG_DEST_EVQ, 0);
 759 
 760         efx_mcdi_execute(enp, &req);
 761 
 762         if (req.emr_rc != 0) {
 763                 rc = req.emr_rc;
 764                 goto fail1;
 765         }
 766 
 767         return (0);
 768 
 769 fail1:
 770         EFSYS_PROBE1(fail1, int, rc);
 771 
 772         return (rc);
 773 }
 774 
 775 static                  void
 776 siena_nic_rx_cfg(
 777         __in            efx_nic_t *enp)
 778 {
 779         efx_oword_t oword;
 780 
 781         /*
 782          * RX_INGR_EN is always enabled on Siena, because we rely on
 783          * the RX parser to be resiliant to missing SOP/EOP.
 784          */
 785         EFX_BAR_READO(enp, FR_AZ_RX_CFG_REG, &oword);
 786         EFX_SET_OWORD_FIELD(oword, FRF_BZ_RX_INGR_EN, 1);
 787         EFX_BAR_WRITEO(enp, FR_AZ_RX_CFG_REG, &oword);
 788 
 789         /* Disable parsing of additional 802.1Q in Q packets */
 790         EFX_BAR_READO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
 791         EFX_SET_OWORD_FIELD(oword, FRF_CZ_RX_FILTER_ALL_VLAN_ETHERTYPES, 0);
 792         EFX_BAR_WRITEO(enp, FR_AZ_RX_FILTER_CTL_REG, &oword);
 793 }
 794 
 795 static                  void
 796 siena_nic_usrev_dis(
 797         __in            efx_nic_t *enp)
 798 {
 799         efx_oword_t     oword;
 800 
 801         EFX_POPULATE_OWORD_1(oword, FRF_CZ_USREV_DIS, 1);
 802         EFX_BAR_WRITEO(enp, FR_CZ_USR_EV_CFG, &oword);
 803 }
 804 
 805         __checkReturn   int
 806 siena_nic_init(
 807         __in            efx_nic_t *enp)
 808 {
 809         int rc;
 810 
 811         EFSYS_ASSERT3U(enp->en_family, ==, EFX_FAMILY_SIENA);
 812 
 813         if ((rc = siena_nic_logging(enp)) != 0)
 814                 goto fail1;
 815 
 816         siena_sram_init(enp);
 817 
 818         /* Configure Siena's RX block */
 819         siena_nic_rx_cfg(enp);
 820 
 821         /* Disable USR_EVents for now */
 822         siena_nic_usrev_dis(enp);
 823 
 824         /* bug17057: Ensure set_link is called */
 825         if ((rc = siena_phy_reconfigure(enp)) != 0)
 826                 goto fail2;
 827 
 828         return (0);
 829 
 830 fail2:
 831         EFSYS_PROBE(fail2);
 832 fail1:
 833         EFSYS_PROBE1(fail1, int, rc);
 834 
 835         return (rc);
 836 }
 837 
 838                         void
 839 siena_nic_fini(
 840         __in            efx_nic_t *enp)
 841 {
 842         _NOTE(ARGUNUSED(enp))
 843 }
 844 
 845                         void
 846 siena_nic_unprobe(
 847         __in            efx_nic_t *enp)
 848 {
 849         (void) siena_nic_attach(enp, B_FALSE);
 850 }
 851 
 852 #if EFSYS_OPT_DIAG
 853 
 854 static efx_register_set_t __cs  __siena_registers[] = {
 855         { FR_AZ_ADR_REGION_REG_OFST, 0, 1 },
 856         { FR_CZ_USR_EV_CFG_OFST, 0, 1 },
 857         { FR_AZ_RX_CFG_REG_OFST, 0, 1 },
 858         { FR_AZ_TX_CFG_REG_OFST, 0, 1 },
 859         { FR_AZ_TX_RESERVED_REG_OFST, 0, 1 },
 860         { FR_AZ_SRM_TX_DC_CFG_REG_OFST, 0, 1 },
 861         { FR_AZ_RX_DC_CFG_REG_OFST, 0, 1 },
 862         { FR_AZ_RX_DC_PF_WM_REG_OFST, 0, 1 },
 863         { FR_AZ_DP_CTRL_REG_OFST, 0, 1 },
 864         { FR_BZ_RX_RSS_TKEY_REG_OFST, 0, 1},
 865         { FR_CZ_RX_RSS_IPV6_REG1_OFST, 0, 1},
 866         { FR_CZ_RX_RSS_IPV6_REG2_OFST, 0, 1},
 867         { FR_CZ_RX_RSS_IPV6_REG3_OFST, 0, 1}
 868 };
 869 
 870 static const uint32_t __cs      __siena_register_masks[] = {
 871         0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF,
 872         0x000103FF, 0x00000000, 0x00000000, 0x00000000,
 873         0xFFFFFFFE, 0xFFFFFFFF, 0x0003FFFF, 0x00000000,
 874         0x7FFF0037, 0xFFFF8000, 0xFFFFFFFF, 0x03FFFFFF,
 875         0xFFFEFE80, 0x1FFFFFFF, 0x020000FE, 0x007FFFFF,
 876         0x001FFFFF, 0x00000000, 0x00000000, 0x00000000,
 877         0x00000003, 0x00000000, 0x00000000, 0x00000000,
 878         0x000003FF, 0x00000000, 0x00000000, 0x00000000,
 879         0x00000FFF, 0x00000000, 0x00000000, 0x00000000,
 880         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
 881         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
 882         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
 883         0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000
 884 };
 885 
 886 static efx_register_set_t __cs  __siena_tables[] = {
 887         { FR_AZ_RX_FILTER_TBL0_OFST, FR_AZ_RX_FILTER_TBL0_STEP,
 888             FR_AZ_RX_FILTER_TBL0_ROWS },
 889         { FR_CZ_RX_MAC_FILTER_TBL0_OFST, FR_CZ_RX_MAC_FILTER_TBL0_STEP,
 890             FR_CZ_RX_MAC_FILTER_TBL0_ROWS },
 891         { FR_AZ_RX_DESC_PTR_TBL_OFST,
 892             FR_AZ_RX_DESC_PTR_TBL_STEP, FR_CZ_RX_DESC_PTR_TBL_ROWS },
 893         { FR_AZ_TX_DESC_PTR_TBL_OFST,
 894             FR_AZ_TX_DESC_PTR_TBL_STEP, FR_CZ_TX_DESC_PTR_TBL_ROWS },
 895         { FR_AZ_TIMER_TBL_OFST, FR_AZ_TIMER_TBL_STEP, FR_CZ_TIMER_TBL_ROWS },
 896         { FR_CZ_TX_FILTER_TBL0_OFST,
 897             FR_CZ_TX_FILTER_TBL0_STEP, FR_CZ_TX_FILTER_TBL0_ROWS },
 898         { FR_CZ_TX_MAC_FILTER_TBL0_OFST,
 899             FR_CZ_TX_MAC_FILTER_TBL0_STEP, FR_CZ_TX_MAC_FILTER_TBL0_ROWS }
 900 };
 901 
 902 static const uint32_t __cs      __siena_table_masks[] = {
 903         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000003FF,
 904         0xFFFF0FFF, 0xFFFFFFFF, 0x00000E7F, 0x00000000,
 905         0xFFFFFFFE, 0x0FFFFFFF, 0x01800000, 0x00000000,
 906         0xFFFFFFFE, 0x0FFFFFFF, 0x0C000000, 0x00000000,
 907         0x3FFFFFFF, 0x00000000, 0x00000000, 0x00000000,
 908         0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000013FF,
 909         0xFFFF07FF, 0xFFFFFFFF, 0x0000007F, 0x00000000,
 910 };
 911 
 912         __checkReturn   int
 913 siena_nic_register_test(
 914         __in            efx_nic_t *enp)
 915 {
 916         efx_register_set_t *rsp;
 917         const uint32_t *dwordp;
 918         unsigned int nitems;
 919         unsigned int count;
 920         int rc;
 921 
 922         /* Fill out the register mask entries */
 923         EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_register_masks)
 924                     == EFX_ARRAY_SIZE(__siena_registers) * 4);
 925 
 926         nitems = EFX_ARRAY_SIZE(__siena_registers);
 927         dwordp = __siena_register_masks;
 928         for (count = 0; count < nitems; ++count) {
 929                 rsp = __siena_registers + count;
 930                 rsp->mask.eo_u32[0] = *dwordp++;
 931                 rsp->mask.eo_u32[1] = *dwordp++;
 932                 rsp->mask.eo_u32[2] = *dwordp++;
 933                 rsp->mask.eo_u32[3] = *dwordp++;
 934         }
 935 
 936         /* Fill out the register table entries */
 937         EFX_STATIC_ASSERT(EFX_ARRAY_SIZE(__siena_table_masks)
 938                     == EFX_ARRAY_SIZE(__siena_tables) * 4);
 939 
 940         nitems = EFX_ARRAY_SIZE(__siena_tables);
 941         dwordp = __siena_table_masks;
 942         for (count = 0; count < nitems; ++count) {
 943                 rsp = __siena_tables + count;
 944                 rsp->mask.eo_u32[0] = *dwordp++;
 945                 rsp->mask.eo_u32[1] = *dwordp++;
 946                 rsp->mask.eo_u32[2] = *dwordp++;
 947                 rsp->mask.eo_u32[3] = *dwordp++;
 948         }
 949 
 950         if ((rc = efx_nic_test_registers(enp, __siena_registers,
 951             EFX_ARRAY_SIZE(__siena_registers))) != 0)
 952                 goto fail1;
 953 
 954         if ((rc = efx_nic_test_tables(enp, __siena_tables,
 955             EFX_PATTERN_BYTE_ALTERNATE,
 956             EFX_ARRAY_SIZE(__siena_tables))) != 0)
 957                 goto fail2;
 958 
 959         if ((rc = efx_nic_test_tables(enp, __siena_tables,
 960             EFX_PATTERN_BYTE_CHANGING,
 961             EFX_ARRAY_SIZE(__siena_tables))) != 0)
 962                 goto fail3;
 963 
 964         if ((rc = efx_nic_test_tables(enp, __siena_tables,
 965             EFX_PATTERN_BIT_SWEEP, EFX_ARRAY_SIZE(__siena_tables))) != 0)
 966                 goto fail4;
 967 
 968         return (0);
 969 
 970 fail4:
 971         EFSYS_PROBE(fail4);
 972 fail3:
 973         EFSYS_PROBE(fail3);
 974 fail2:
 975         EFSYS_PROBE(fail2);
 976 fail1:
 977         EFSYS_PROBE1(fail1, int, rc);
 978 
 979         return (rc);
 980 }
 981 
 982 #endif  /* EFSYS_OPT_DIAG */
 983 
 984 #endif  /* EFSYS_OPT_SIENA */