49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Copyright (c) 2008-2016 Solarflare Communications Inc.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * All rights reserved.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Redistribution and use in source and binary forms, with or without
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * modification, are permitted provided that the following conditions are met:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * 1. Redistributions of source code must retain the above copyright notice,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * this list of conditions and the following disclaimer.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * 2. Redistributions in binary form must reproduce the above copyright notice,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * this list of conditions and the following disclaimer in the documentation
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * and/or other materials provided with the distribution.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * The views and conclusions contained in the software and documentation are
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * those of the authors and should not be interpreted as representing official
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * policies, either expressed or implied, of the FreeBSD Project.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/types.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/ddi.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/sunddi.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/modctl.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/conf.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/ethernet.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/pci.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/stream.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/strsun.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/processor.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/cpuvar.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include <sys/pghw.h>
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "sfxge.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "sfxge_version.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "efsys.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#include "efx.h"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#ifdef DEBUG
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreboolean_t sfxge_aask = B_FALSE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#endif
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Receive queue TRIM default polling interval (in microseconds) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#define SFXGE_RX_QPOLL_USEC (5000000)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/* Broadcast address */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreuint8_t sfxge_brdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * By default modinfo will display lines truncated to 80 characters and so just
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * show 32 characters of our sfxge_ident string.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreconst char sfxge_ident[] = "Solarflare 10Gb/40Gb Ethernet";
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreconst char sfxge_version[] = SFXGE_VERSION_STRING;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_cfg_build(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const efx_nic_cfg_t *encp = efx_nic_cfg_get(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(sp->s_cfg_kstat.buf.sck_mac, 64,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "%02X:%02X:%02X:%02X:%02X:%02X",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore encp->enc_mac_addr[0], encp->enc_mac_addr[1],
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore encp->enc_mac_addr[2], encp->enc_mac_addr[3],
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore encp->enc_mac_addr[4], encp->enc_mac_addr[5]);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_create(dev_info_t *dip, sfxge_t **spp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_t *enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore unsigned int rxq_size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rxq_poll_usec;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Allocate the object */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp = kmem_zalloc(sizeof (*sp), KM_SLEEP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_dip = dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_set_driver_private(dip, sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_init(&(sp->s_state_lock), NULL, MUTEX_DRIVER, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_UNINITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Get property values */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "mtu", ETHERMTU);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_action_on_hw_err = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "action_on_hw_err", SFXGE_RECOVER);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxq_size = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "rxq_size", SFXGE_DEFAULT_RXQ_SIZE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (!(ISP2(rxq_size)))
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxq_size = SFXGE_DEFAULT_RXQ_SIZE;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxq_size = min(rxq_size, EFX_RXQ_MAXNDESCS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rxq_size = (uint16_t)max(rxq_size, EFX_RXQ_MINNDESCS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Configure polling interval for queue refill/trim */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxq_poll_usec = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "rxq_poll_usec", SFXGE_RX_QPOLL_USEC);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rxq_poll_usec <= 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rxq_poll_usec = SFXGE_RX_QPOLL_USEC;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_rxq_poll_usec = rxq_poll_usec;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#if EFSYS_OPT_MCDI_LOGGING
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_mcdi_logging = ddi_prop_get_int(DDI_DEV_T_ANY, sp->s_dip,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_PROP_DONTPASS, "mcdi_logging", 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore#endif
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create a taskq */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_tqp = ddi_taskq_create(dip, "tq", 1, TASKQ_DEFAULTPRI, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_tqp == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Check and initialize PCI configuration space */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_pci_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Map the device registers */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_bar_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the NIC object */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_init(&(sp->s_nic_lock), NULL, MUTEX_DRIVER, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_nic_create(sp->s_family, (efsys_identifier_t *)sp,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &(sp->s_bar), &(sp->s_nic_lock), &enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail5;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_enp = enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Initialize MCDI to talk to the Microcontroller */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mcdi_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail6;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Probe the NIC and build the configuration data area */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_nic_probe(enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail7;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (sp->s_family) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case EFX_FAMILY_HUNTINGTON:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_pcie_check_link(sp, 8, 3); /* PCI 8x Gen3 */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case EFX_FAMILY_SIENA:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_pcie_check_link(sp, 8, 2); /* PCI 8x Gen2 */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_nvram_init(enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail8;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_vpd_init(enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail9;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_nic_reset(enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail10;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_init(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_intr_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail11;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_ev_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail12;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mac_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail13;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail14;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_tx_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail15;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mon_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail16;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_init(&(sp->s_tx_flush_lock), NULL, MUTEX_DRIVER,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DDI_INTR_PRI(sp->s_intr.si_intr_pri));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore cv_init(&(sp->s_tx_flush_kv), NULL, CV_DRIVER, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_INITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore *spp = sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail16:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail15);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_tx_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail15:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail14);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail14:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail14);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mac_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail13:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail13);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_ev_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail12:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail12);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail11:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail11);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_nic_reset(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail10:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail10);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_vpd_fini(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail9:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail9);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nvram_fini(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail8:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail8);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_unprobe(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail7:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail7);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mcdi_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail6:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail6);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_enp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_destroy(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail5:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail5);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(sp->s_nic_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_bar_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_pci_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_taskq_destroy(sp->s_tqp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_tqp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Clear property values */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_mtu = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the soft state */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_dip = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(sp, sfxge_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(sp, sizeof (*sp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_start_locked(sfxge_t *sp, boolean_t restart)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sp->s_state_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_state == SFXGE_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto done;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_state != SFXGE_REGISTERED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EINVAL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_STARTING;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Start a new epoch (allow fresh MCDI requests to succeed) */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_mcdi_new_epoch(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_nic_reset(sp->s_enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_nic_init(sp->s_enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_filter_init(sp->s_enp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_sram_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail5;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_intr_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail6;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_ev_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail7;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mac_start(sp, restart)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail8;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_rx_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail9;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_tx_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail10;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mon_start(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail11;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_STARTING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_STARTED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Notify any change of MTU */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_gld_mtu_update(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoredone:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail11:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail11);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_tx_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail10:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail10);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail9:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail9);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mac_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail8:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail8);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_ev_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail7:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail7);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail6:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail6);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail5:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail5);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_filter_fini(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_fini(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_nic_reset(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_STARTING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_REGISTERED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_start(sfxge_t *sp, boolean_t restart)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = sfxge_start_locked(sp, restart);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_stop_locked(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(mutex_owned(&(sp->s_state_lock)));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_state != SFXGE_STARTED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_STOPPING;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mon_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_tx_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mac_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Stop event processing - must be after rx_stop see sfxge_rx_qpoll() */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_ev_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_stop(sp); /* cope with late flush/soft events until here */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_filter_fini(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_fini(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_nic_reset(sp->s_enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_STOPPING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_REGISTERED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_stop(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_stop_locked(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore_sfxge_restart(void *arg)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = arg;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* logging on entry is in sfxge_restart_dispatch */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(_sfxge_restart);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_state != SFXGE_STARTED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto done;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* inform the OS that the link is down - may trigger IPMP failover */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_hw_err && sp->s_action_on_hw_err != SFXGE_INVISIBLE) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_mac.sm_link_mode = EFX_LINK_DOWN;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_gld_link_update(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Stop processing */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_stop_locked(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_hw_err && sp->s_action_on_hw_err == SFXGE_LEAVE_DEAD) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(sp->s_dip, CE_WARN, SFXGE_CMN_ERR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "NIC error - interface is"
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore " being left permanently DOWN per driver config");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) atomic_swap_32(&(sp->s_nested_restarts), 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore } else
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_hw_err = SFXGE_HW_OK;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Start processing */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_start_locked(sp, B_TRUE)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoredone:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) atomic_swap_32(&(sp->s_nested_restarts), 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(sp->s_dip, CE_WARN, SFXGE_CMN_ERR "NIC restart complete");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(sp->s_dip, CE_WARN,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_CMN_ERR "FATAL ERROR: NIC restart failed rc=%d", rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) atomic_swap_32(&(sp->s_nested_restarts), 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_restart_dispatch(sfxge_t *sp, uint_t cflags, sfxge_hw_err_t hw_err,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *reason, uint32_t errval)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (hw_err == SFXGE_HW_OK)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_num_restarts++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore else {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_hw_err = hw_err;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_num_restarts_hw_err++;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (atomic_inc_32_nv(&(sp->s_nested_restarts)) > 1) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* A restart is currently in progress */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE2(sfxge_restart_dispatch, sfxge_hw_err_t, hw_err, char *,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore reason);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(sp->s_dip, CE_WARN, SFXGE_CMN_ERR "NIC restart due to %s:%d",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore reason, errval);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* If cflags == DDI_SLEEP then guaranteed to succeed */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (ddi_taskq_dispatch(sp->s_tqp, _sfxge_restart, sp, cflags));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_can_destroy(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int index;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * In SFC bug 19834 it was noted that a mblk passed up to STREAMS
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * could be reused for transmit and sit in the sfxge_tx_packet_cache.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * This call to empty the TX deferred packet list may result in
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * rx_loaned reducing.
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore index = EFX_ARRAY_SIZE(sp->s_stp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore while (--index >= 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_txq_t *stp = sp->s_stp[index];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (stp != NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_tx_qdpl_flush(stp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Need to wait for desballoc free_func callback */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (sfxge_rx_loaned(sp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_destroy(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_taskq_t *tqp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_t *enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore enp = sp->s_enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sfxge_can_destroy(sp) != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EBUSY;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_UNINITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore cv_destroy(&(sp->s_tx_flush_kv));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(sp->s_tx_flush_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mon_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_tx_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_rx_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mac_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_ev_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_intr_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_sram_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) efx_nic_reset(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_vpd_fini(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nvram_fini(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_unprobe(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mcdi_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the NIC object */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_enp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_destroy(enp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(sp->s_nic_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Unmap the device registers */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_bar_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Tear down PCI configuration space */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_pci_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the taskq */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore tqp = sp->s_tqp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_tqp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_taskq_destroy(tqp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Clear property values */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_mtu = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Free the soft state */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_dip = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(sp, sfxge_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(sp, sizeof (*sp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorevoid
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_ioctl(sfxge_t *sp, queue_t *wq, mblk_t *mp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore struct iocblk *iocp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc, taskq_wait = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t ioclen = 0;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * single concurrent IOCTL
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * serialized from sfxge_create, _destroy, _(re)start, _stop
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*LINTED*/
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore iocp = (struct iocblk *)mp->b_rptr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (iocp->ioc_cmd) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_NVRAM_IOC:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ioclen = sizeof (sfxge_nvram_ioc_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_MCDI_IOC:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ioclen = sizeof (sfxge_mcdi_ioc_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_MCDI2_IOC:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ioclen = sizeof (sfxge_mcdi2_ioc_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_VPD_IOC:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ioclen = sizeof (sfxge_vpd_ioc_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_NIC_RESET_IOC:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOTSUP;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (iocp->ioc_count != ioclen) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = EINVAL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* if in multiple fragments pull it up to one linear buffer */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = miocpullup(mp, ioclen)) != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (iocp->ioc_cmd) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_NVRAM_IOC: {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_nvram_ioc_t *snip =
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (sfxge_nvram_ioc_t *)mp->b_cont->b_rptr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_nvram_ioctl(sp, snip)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_MCDI_IOC: {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mcdi_ioc_t *smip = (sfxge_mcdi_ioc_t *)mp->b_cont->b_rptr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mcdi_ioctl(sp, smip)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore taskq_wait = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_MCDI2_IOC: {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_mcdi2_ioc_t *smip =
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (sfxge_mcdi2_ioc_t *)mp->b_cont->b_rptr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_mcdi2_ioctl(sp, smip)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore taskq_wait = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_NIC_RESET_IOC: {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(nic_reset_ioc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* sp->s_state_lock held */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) sfxge_restart_dispatch(sp, DDI_SLEEP, SFXGE_HW_OK,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "NIC_RESET_IOC", 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore taskq_wait = 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case SFXGE_VPD_IOC: {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_vpd_ioc_t *svip = (sfxge_vpd_ioc_t *)mp->b_cont->b_rptr;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_vpd_ioctl(sp, svip)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (taskq_wait) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Wait for any tasks that may be accessing GLD functions
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * This may end up waiting for multiple nic_resets
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * as it needs to be outside of s_state_lock for sfxge_restart()
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_taskq_wait(sp->s_tqp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* The entire structure is the acknowledgement */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore miocack(wq, mp, iocp->ioc_count, 0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* no data returned */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore miocnak(wq, mp, 0, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_register(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_gld_register(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_REGISTERED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_unregister(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_REGISTERED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Wait for any tasks that may be accessing GLD functions */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_taskq_wait(sp->s_tqp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_gld_unregister(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state = SFXGE_INITIALIZED;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore_sfxge_vpd_kstat_init(sfxge_t *sp, caddr_t vpd, size_t size, efx_vpd_tag_t tag,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore const char *keyword, sfxge_vpd_type_t type)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore static const char unknown[] = "?";
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_t *enp = sp->s_enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_t *knp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_vpd_value_t *evvp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore evvp = svkp->svk_vv + type;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore evvp->evv_tag = tag;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore evvp->evv_keyword = EFX_VPD_KEYWORD(keyword[0], keyword[1]);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (efx_vpd_get(enp, vpd, size, evvp) != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore evvp->evv_length = strlen(unknown) + 1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bcopy(unknown, evvp->evv_value, evvp->evv_length);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore knp = &(svkp->svk_stat[type]);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(knp, (char *)keyword, KSTAT_DATA_STRING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_setstr(knp, (char *)evvp->evv_value);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore svkp->svk_ksp->ks_data_size += sizeof (*evvp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_vpd_kstat_init(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore efx_nic_t *enp = sp->s_enp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_info_t *dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore char name[MAXNAMELEN];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_t *ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore caddr_t vpd;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore size_t size;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "%s_vpd", ddi_driver_name(dip));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Get a copy of the VPD space */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_vpd_size(enp, &size)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((vpd = kmem_zalloc(size, KM_NOSLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((svkp->svk_vv = kmem_zalloc(sizeof (efx_vpd_value_t) *
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_VPD_MAX, KM_NOSLEEP)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = efx_vpd_read(enp, vpd, size)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((ksp = kstat_create((char *)ddi_driver_name(dip),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_get_instance(dip), name, "vpd", KSTAT_TYPE_NAMED, SFXGE_VPD_MAX,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore KSTAT_FLAG_VIRTUAL)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail5;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore svkp->svk_ksp = ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_data = &(svkp->svk_stat);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_ID, "ID", SFXGE_VPD_ID);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "PN", SFXGE_VPD_PN);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "SN", SFXGE_VPD_SN);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "EC", SFXGE_VPD_EC);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "MN", SFXGE_VPD_MN);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "VD", SFXGE_VPD_VD);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore _sfxge_vpd_kstat_init(sp, vpd, size, EFX_VPD_RO, "VE", SFXGE_VPD_VE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_install(ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(vpd, size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail5:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail5);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(svkp->svk_vv, sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(vpd, size);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_vpd_kstat_fini(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_vpd_kstat_t *svkp = &(sp->s_vpd_kstat);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* NOTE: VPD support is optional, so kstats might not be registered */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (svkp->svk_ksp != NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_delete(svkp->svk_ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(svkp->svk_vv,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (efx_vpd_value_t) * SFXGE_VPD_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(svkp->svk_stat,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (kstat_named_t) * SFXGE_VPD_MAX);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore svkp->svk_ksp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore SFXGE_OBJ_CHECK(svkp, sfxge_vpd_kstat_t);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_cfg_kstat_init(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_info_t *dip = sp->s_dip;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore char name[MAXNAMELEN];
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_t *ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cfg_kstat_t *sckp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cfg_build(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the set */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) snprintf(name, MAXNAMELEN - 1, "%s_cfg", ddi_driver_name(dip));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((ksp = kstat_create((char *)ddi_driver_name(dip),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_get_instance(dip), name, "cfg", KSTAT_TYPE_NAMED,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sizeof (sckp->kstat) / sizeof (kstat_named_t),
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore KSTAT_FLAG_VIRTUAL)) == NULL) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore rc = ENOMEM;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_cfg_ksp = ksp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_data = sckp = &(sp->s_cfg_kstat);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(&(sckp->kstat.sck_mac), "mac", KSTAT_DATA_STRING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_setstr(&(sckp->kstat.sck_mac), sckp->buf.sck_mac);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_data_size += sizeof (sckp->buf.sck_mac);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_init(&(sckp->kstat.sck_version), "version",
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore KSTAT_DATA_STRING);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_named_setstr(&(sckp->kstat.sck_version), sfxge_version);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ksp->ks_data_size += sizeof (sfxge_version);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_install(ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic void
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_cfg_kstat_fini(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_cfg_ksp == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kstat_delete(sp->s_cfg_ksp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_cfg_ksp = NULL;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore bzero(&(sp->s_cfg_kstat), sizeof (sfxge_cfg_kstat_t));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_resume(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Start processing */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_start(sp, B_FALSE)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_SUCCESS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (cmd) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_ATTACH:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_RESUME:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((sp = ddi_get_driver_private(dip)) == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (sfxge_resume(sp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the soft state */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_create(dip, &sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the configuration kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_cfg_kstat_init(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create the VPD kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_vpd_kstat_init(sp)) != 0) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (rc != ENOTSUP)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail3;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Register the interface */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_register(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail4;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Announce ourselves in the system log */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_report_dev(dip);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_SUCCESS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail4:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail4);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the VPD kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_vpd_kstat_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail3:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail3);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the configuration kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cfg_kstat_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the soft state */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (void) sfxge_destroy(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_suspend(sfxge_t *sp)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Stop processing */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_stop(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_SUCCESS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic int
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoresfxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_t *sp = ddi_get_driver_private(dip);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore switch (cmd) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_DETACH:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore break;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore case DDI_SUSPEND:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp == NULL)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (sfxge_suspend(sp));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore default:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(sp != NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Wait for any pending restarts to complete */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ddi_taskq_wait(sp->s_tqp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * IOCTLs from utilites can cause GLD mc_start() (SFXGE_STARTED state)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * And mc_stop() may not occur until detach time and race. SFC bug 19855
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Holding the lock seems to be enough - the log message is not seen
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_enter(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_state == SFXGE_STARTED) {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore dev_err(dip, CE_WARN, SFXGE_CMN_ERR
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore "STREAMS detach when STARTED");
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_stop_locked(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT3U(sp->s_state, ==, SFXGE_REGISTERED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_exit(&(sp->s_state_lock));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore ASSERT(sp->s_state == SFXGE_REGISTERED ||
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sp->s_state == SFXGE_INITIALIZED);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if (sp->s_state != SFXGE_REGISTERED)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto destroy;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Unregister the interface */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_unregister(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoredestroy:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the VPD kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_vpd_kstat_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy the configuration kstats */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cfg_kstat_fini(sp);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * Destroy the soft state - this might fail until rx_loaned packets that
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * have been passed up the STREAMS stack are returned
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = sfxge_destroy(sp)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail2;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_SUCCESS);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail2:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE1(fail1, int, rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (DDI_FAILURE);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore/*
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore * modlinkage
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'AmoreDDI_DEFINE_STREAM_OPS(sfxge_dev_ops, nulldev, nulldev, sfxge_attach,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_detach, nulldev, NULL, D_MP, NULL, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic struct modldrv sfxge_modldrv = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &mod_driverops,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore (char *)sfxge_ident,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore &sfxge_dev_ops,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorestatic struct modlinkage sfxge_modlinkage = {
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore MODREV_1,
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore { &sfxge_modldrv, NULL }
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore};
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorekmutex_t sfxge_global_lock;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreunsigned int *sfxge_cpu;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore_init(void)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_init(&sfxge_global_lock, NULL, MUTEX_DRIVER, NULL);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Create tables for CPU, core, cache and chip counts */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore sfxge_cpu = kmem_zalloc(sizeof (unsigned int) * NCPU, KM_SLEEP);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mac_init_ops(&sfxge_dev_ops, SFXGE_DRIVER_NAME);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = mod_install(&sfxge_modlinkage)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore goto fail1;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amorefail1:
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore DTRACE_PROBE(fail2);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mac_fini_ops(&sfxge_dev_ops);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(sfxge_cpu, sizeof (unsigned int) * NCPU);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&sfxge_global_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore_fini(void)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore int rc;
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore if ((rc = mod_remove(&sfxge_modlinkage)) != 0)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (rc);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mac_fini_ops(&sfxge_dev_ops);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore /* Destroy tables */
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore kmem_free(sfxge_cpu, sizeof (unsigned int) * NCPU);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore mutex_destroy(&sfxge_global_lock);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (0);
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amoreint
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore_info(struct modinfo *mip)
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore{
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore return (mod_info(&sfxge_modlinkage, mip));
49ef7e0638c8b771d8a136eae78b1c0f99acc8e0Garrett D'Amore}