xref: /onnv-gate/usr/src/uts/common/io/ixgbe/ixgbe_main.c (revision 7167:0a0852a36735)
16621Sbt150084 /*
26621Sbt150084  * CDDL HEADER START
36621Sbt150084  *
46621Sbt150084  * Copyright(c) 2007-2008 Intel Corporation. All rights reserved.
56621Sbt150084  * The contents of this file are subject to the terms of the
66621Sbt150084  * Common Development and Distribution License (the "License").
76621Sbt150084  * You may not use this file except in compliance with the License.
86621Sbt150084  *
96621Sbt150084  * You can obtain a copy of the license at:
106621Sbt150084  *      http://www.opensolaris.org/os/licensing.
116621Sbt150084  * See the License for the specific language governing permissions
126621Sbt150084  * and limitations under the License.
136621Sbt150084  *
146621Sbt150084  * When using or redistributing this file, you may do so under the
156621Sbt150084  * License only. No other modification of this header is permitted.
166621Sbt150084  *
176621Sbt150084  * If applicable, add the following below this CDDL HEADER, with the
186621Sbt150084  * fields enclosed by brackets "[]" replaced with your own identifying
196621Sbt150084  * information: Portions Copyright [yyyy] [name of copyright owner]
206621Sbt150084  *
216621Sbt150084  * CDDL HEADER END
226621Sbt150084  */
236621Sbt150084 
246621Sbt150084 /*
256621Sbt150084  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
266621Sbt150084  * Use is subject to license terms of the CDDL.
276621Sbt150084  */
286621Sbt150084 
296621Sbt150084 #pragma ident	"%Z%%M%	%I%	%E% SMI"
306621Sbt150084 
316621Sbt150084 #include "ixgbe_sw.h"
326621Sbt150084 
33*7167Sgg161487 static char ident[] = "Intel 10Gb Ethernet 1.0.1";
346621Sbt150084 
356621Sbt150084 /*
366621Sbt150084  * Local function protoypes
376621Sbt150084  */
386621Sbt150084 static int ixgbe_register_mac(ixgbe_t *);
396621Sbt150084 static int ixgbe_identify_hardware(ixgbe_t *);
406621Sbt150084 static int ixgbe_regs_map(ixgbe_t *);
416621Sbt150084 static void ixgbe_init_properties(ixgbe_t *);
426621Sbt150084 static int ixgbe_init_driver_settings(ixgbe_t *);
436621Sbt150084 static void ixgbe_init_locks(ixgbe_t *);
446621Sbt150084 static void ixgbe_destroy_locks(ixgbe_t *);
456621Sbt150084 static int ixgbe_init(ixgbe_t *);
466621Sbt150084 static int ixgbe_chip_start(ixgbe_t *);
476621Sbt150084 static void ixgbe_chip_stop(ixgbe_t *);
486621Sbt150084 static int ixgbe_reset(ixgbe_t *);
496621Sbt150084 static void ixgbe_tx_clean(ixgbe_t *);
506621Sbt150084 static boolean_t ixgbe_tx_drain(ixgbe_t *);
516621Sbt150084 static boolean_t ixgbe_rx_drain(ixgbe_t *);
526621Sbt150084 static int ixgbe_alloc_rings(ixgbe_t *);
536621Sbt150084 static int ixgbe_init_rings(ixgbe_t *);
546621Sbt150084 static void ixgbe_free_rings(ixgbe_t *);
556621Sbt150084 static void ixgbe_fini_rings(ixgbe_t *);
566621Sbt150084 static void ixgbe_setup_rings(ixgbe_t *);
576621Sbt150084 static void ixgbe_setup_rx(ixgbe_t *);
586621Sbt150084 static void ixgbe_setup_tx(ixgbe_t *);
596621Sbt150084 static void ixgbe_setup_rx_ring(ixgbe_rx_ring_t *);
606621Sbt150084 static void ixgbe_setup_tx_ring(ixgbe_tx_ring_t *);
616621Sbt150084 static void ixgbe_setup_rss(ixgbe_t *);
626621Sbt150084 static void ixgbe_init_unicst(ixgbe_t *);
636621Sbt150084 static void ixgbe_setup_multicst(ixgbe_t *);
646621Sbt150084 static void ixgbe_get_hw_state(ixgbe_t *);
656621Sbt150084 static void ixgbe_get_conf(ixgbe_t *);
666621Sbt150084 static int ixgbe_get_prop(ixgbe_t *, char *, int, int, int);
676621Sbt150084 static boolean_t ixgbe_driver_link_check(ixgbe_t *);
686621Sbt150084 static void ixgbe_local_timer(void *);
696621Sbt150084 static void ixgbe_arm_watchdog_timer(ixgbe_t *);
706621Sbt150084 static void ixgbe_start_watchdog_timer(ixgbe_t *);
716621Sbt150084 static void ixgbe_restart_watchdog_timer(ixgbe_t *);
726621Sbt150084 static void ixgbe_stop_watchdog_timer(ixgbe_t *);
736621Sbt150084 static void ixgbe_disable_adapter_interrupts(ixgbe_t *);
746621Sbt150084 static void ixgbe_enable_adapter_interrupts(ixgbe_t *);
756621Sbt150084 static boolean_t is_valid_mac_addr(uint8_t *);
766621Sbt150084 static boolean_t ixgbe_stall_check(ixgbe_t *);
776621Sbt150084 static boolean_t ixgbe_set_loopback_mode(ixgbe_t *, uint32_t);
786621Sbt150084 static void ixgbe_set_internal_mac_loopback(ixgbe_t *);
796621Sbt150084 static boolean_t ixgbe_find_mac_address(ixgbe_t *);
806621Sbt150084 static int ixgbe_alloc_intrs(ixgbe_t *);
816621Sbt150084 static int ixgbe_alloc_intr_handles(ixgbe_t *, int);
826621Sbt150084 static int ixgbe_add_intr_handlers(ixgbe_t *);
836621Sbt150084 static void ixgbe_map_rxring_to_vector(ixgbe_t *, int, int);
846621Sbt150084 static void ixgbe_map_txring_to_vector(ixgbe_t *, int, int);
856621Sbt150084 static void ixgbe_set_ivar(ixgbe_t *, uint16_t, uint8_t);
866621Sbt150084 static int ixgbe_map_rings_to_vectors(ixgbe_t *);
876621Sbt150084 static void ixgbe_setup_adapter_vector(ixgbe_t *);
886621Sbt150084 static void ixgbe_rem_intr_handlers(ixgbe_t *);
896621Sbt150084 static void ixgbe_rem_intrs(ixgbe_t *);
906621Sbt150084 static int ixgbe_enable_intrs(ixgbe_t *);
916621Sbt150084 static int ixgbe_disable_intrs(ixgbe_t *);
926621Sbt150084 static uint_t ixgbe_intr_legacy(void *, void *);
936621Sbt150084 static uint_t ixgbe_intr_msi(void *, void *);
946621Sbt150084 static uint_t ixgbe_intr_rx(void *, void *);
956621Sbt150084 static uint_t ixgbe_intr_tx_other(void *, void *);
966621Sbt150084 static void ixgbe_intr_rx_work(ixgbe_rx_ring_t *);
976621Sbt150084 static void ixgbe_intr_tx_work(ixgbe_tx_ring_t *);
986621Sbt150084 static void ixgbe_intr_other_work(ixgbe_t *);
996621Sbt150084 static void ixgbe_get_driver_control(struct ixgbe_hw *);
1006621Sbt150084 static void ixgbe_release_driver_control(struct ixgbe_hw *);
1016621Sbt150084 
1026621Sbt150084 static int ixgbe_attach(dev_info_t *, ddi_attach_cmd_t);
1036621Sbt150084 static int ixgbe_detach(dev_info_t *, ddi_detach_cmd_t);
1046621Sbt150084 static int ixgbe_resume(dev_info_t *);
1056621Sbt150084 static int ixgbe_suspend(dev_info_t *);
1066621Sbt150084 static void ixgbe_unconfigure(dev_info_t *, ixgbe_t *);
1076621Sbt150084 static uint8_t *ixgbe_mc_table_itr(struct ixgbe_hw *, uint8_t **, uint32_t *);
1086621Sbt150084 
1096621Sbt150084 static int ixgbe_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err,
1106621Sbt150084     const void *impl_data);
1116621Sbt150084 static void ixgbe_fm_init(ixgbe_t *);
1126621Sbt150084 static void ixgbe_fm_fini(ixgbe_t *);
1136621Sbt150084 
1146621Sbt150084 static struct cb_ops ixgbe_cb_ops = {
1156621Sbt150084 	nulldev,		/* cb_open */
1166621Sbt150084 	nulldev,		/* cb_close */
1176621Sbt150084 	nodev,			/* cb_strategy */
1186621Sbt150084 	nodev,			/* cb_print */
1196621Sbt150084 	nodev,			/* cb_dump */
1206621Sbt150084 	nodev,			/* cb_read */
1216621Sbt150084 	nodev,			/* cb_write */
1226621Sbt150084 	nodev,			/* cb_ioctl */
1236621Sbt150084 	nodev,			/* cb_devmap */
1246621Sbt150084 	nodev,			/* cb_mmap */
1256621Sbt150084 	nodev,			/* cb_segmap */
1266621Sbt150084 	nochpoll,		/* cb_chpoll */
1276621Sbt150084 	ddi_prop_op,		/* cb_prop_op */
1286621Sbt150084 	NULL,			/* cb_stream */
1296621Sbt150084 	D_MP | D_HOTPLUG,	/* cb_flag */
1306621Sbt150084 	CB_REV,			/* cb_rev */
1316621Sbt150084 	nodev,			/* cb_aread */
1326621Sbt150084 	nodev			/* cb_awrite */
1336621Sbt150084 };
1346621Sbt150084 
1356621Sbt150084 static struct dev_ops ixgbe_dev_ops = {
1366621Sbt150084 	DEVO_REV,		/* devo_rev */
1376621Sbt150084 	0,			/* devo_refcnt */
1386621Sbt150084 	NULL,			/* devo_getinfo */
1396621Sbt150084 	nulldev,		/* devo_identify */
1406621Sbt150084 	nulldev,		/* devo_probe */
1416621Sbt150084 	ixgbe_attach,		/* devo_attach */
1426621Sbt150084 	ixgbe_detach,		/* devo_detach */
1436621Sbt150084 	nodev,			/* devo_reset */
1446621Sbt150084 	&ixgbe_cb_ops,		/* devo_cb_ops */
1456621Sbt150084 	NULL,			/* devo_bus_ops */
1466621Sbt150084 	ddi_power		/* devo_power */
1476621Sbt150084 };
1486621Sbt150084 
1496621Sbt150084 static struct modldrv ixgbe_modldrv = {
1506621Sbt150084 	&mod_driverops,		/* Type of module.  This one is a driver */
1516621Sbt150084 	ident,			/* Discription string */
1526621Sbt150084 	&ixgbe_dev_ops		/* driver ops */
1536621Sbt150084 };
1546621Sbt150084 
1556621Sbt150084 static struct modlinkage ixgbe_modlinkage = {
1566621Sbt150084 	MODREV_1, &ixgbe_modldrv, NULL
1576621Sbt150084 };
1586621Sbt150084 
1596621Sbt150084 /*
1606621Sbt150084  * Access attributes for register mapping
1616621Sbt150084  */
1626621Sbt150084 ddi_device_acc_attr_t ixgbe_regs_acc_attr = {
1636621Sbt150084 	DDI_DEVICE_ATTR_V0,
1646621Sbt150084 	DDI_STRUCTURE_LE_ACC,
1656621Sbt150084 	DDI_STRICTORDER_ACC,
1666621Sbt150084 	DDI_FLAGERR_ACC
1676621Sbt150084 };
1686621Sbt150084 
1696621Sbt150084 /*
1706621Sbt150084  * Loopback property
1716621Sbt150084  */
1726621Sbt150084 static lb_property_t lb_normal = {
1736621Sbt150084 	normal,	"normal", IXGBE_LB_NONE
1746621Sbt150084 };
1756621Sbt150084 
1766621Sbt150084 static lb_property_t lb_mac = {
1776621Sbt150084 	internal, "MAC", IXGBE_LB_INTERNAL_MAC
1786621Sbt150084 };
1796621Sbt150084 
1806621Sbt150084 #define	IXGBE_M_CALLBACK_FLAGS	(MC_IOCTL | MC_GETCAPAB)
1816621Sbt150084 
1826621Sbt150084 static mac_callbacks_t ixgbe_m_callbacks = {
1836621Sbt150084 	IXGBE_M_CALLBACK_FLAGS,
1846621Sbt150084 	ixgbe_m_stat,
1856621Sbt150084 	ixgbe_m_start,
1866621Sbt150084 	ixgbe_m_stop,
1876621Sbt150084 	ixgbe_m_promisc,
1886621Sbt150084 	ixgbe_m_multicst,
1896621Sbt150084 	ixgbe_m_unicst,
1906621Sbt150084 	ixgbe_m_tx,
1916621Sbt150084 	NULL,
1926621Sbt150084 	ixgbe_m_ioctl,
1936621Sbt150084 	ixgbe_m_getcapab
1946621Sbt150084 };
1956621Sbt150084 
1966621Sbt150084 /*
1976621Sbt150084  * Module Initialization Functions.
1986621Sbt150084  */
1996621Sbt150084 
2006621Sbt150084 int
2016621Sbt150084 _init(void)
2026621Sbt150084 {
2036621Sbt150084 	int status;
2046621Sbt150084 
2056621Sbt150084 	mac_init_ops(&ixgbe_dev_ops, MODULE_NAME);
2066621Sbt150084 
2076621Sbt150084 	status = mod_install(&ixgbe_modlinkage);
2086621Sbt150084 
2096621Sbt150084 	if (status != DDI_SUCCESS) {
2106621Sbt150084 		mac_fini_ops(&ixgbe_dev_ops);
2116621Sbt150084 	}
2126621Sbt150084 
2136621Sbt150084 	return (status);
2146621Sbt150084 }
2156621Sbt150084 
2166621Sbt150084 int
2176621Sbt150084 _fini(void)
2186621Sbt150084 {
2196621Sbt150084 	int status;
2206621Sbt150084 
2216621Sbt150084 	status = mod_remove(&ixgbe_modlinkage);
2226621Sbt150084 
2236621Sbt150084 	if (status == DDI_SUCCESS) {
2246621Sbt150084 		mac_fini_ops(&ixgbe_dev_ops);
2256621Sbt150084 	}
2266621Sbt150084 
2276621Sbt150084 	return (status);
2286621Sbt150084 }
2296621Sbt150084 
2306621Sbt150084 int
2316621Sbt150084 _info(struct modinfo *modinfop)
2326621Sbt150084 {
2336621Sbt150084 	int status;
2346621Sbt150084 
2356621Sbt150084 	status = mod_info(&ixgbe_modlinkage, modinfop);
2366621Sbt150084 
2376621Sbt150084 	return (status);
2386621Sbt150084 }
2396621Sbt150084 
2406621Sbt150084 /*
2416621Sbt150084  * ixgbe_attach - Driver attach.
2426621Sbt150084  *
2436621Sbt150084  * This function is the device specific initialization entry
2446621Sbt150084  * point. This entry point is required and must be written.
2456621Sbt150084  * The DDI_ATTACH command must be provided in the attach entry
2466621Sbt150084  * point. When attach() is called with cmd set to DDI_ATTACH,
2476621Sbt150084  * all normal kernel services (such as kmem_alloc(9F)) are
2486621Sbt150084  * available for use by the driver.
2496621Sbt150084  *
2506621Sbt150084  * The attach() function will be called once for each instance
2516621Sbt150084  * of  the  device  on  the  system with cmd set to DDI_ATTACH.
2526621Sbt150084  * Until attach() succeeds, the only driver entry points which
2536621Sbt150084  * may be called are open(9E) and getinfo(9E).
2546621Sbt150084  */
2556621Sbt150084 static int
2566621Sbt150084 ixgbe_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
2576621Sbt150084 {
2586621Sbt150084 	ixgbe_t *ixgbe;
2596621Sbt150084 	struct ixgbe_osdep *osdep;
2606621Sbt150084 	struct ixgbe_hw *hw;
2616621Sbt150084 	int instance;
2626621Sbt150084 
2636621Sbt150084 	/*
2646621Sbt150084 	 * Check the command and perform corresponding operations
2656621Sbt150084 	 */
2666621Sbt150084 	switch (cmd) {
2676621Sbt150084 	default:
2686621Sbt150084 		return (DDI_FAILURE);
2696621Sbt150084 
2706621Sbt150084 	case DDI_RESUME:
2716621Sbt150084 		return (ixgbe_resume(devinfo));
2726621Sbt150084 
2736621Sbt150084 	case DDI_ATTACH:
2746621Sbt150084 		break;
2756621Sbt150084 	}
2766621Sbt150084 
2776621Sbt150084 	/* Get the device instance */
2786621Sbt150084 	instance = ddi_get_instance(devinfo);
2796621Sbt150084 
2806621Sbt150084 	/* Allocate memory for the instance data structure */
2816621Sbt150084 	ixgbe = kmem_zalloc(sizeof (ixgbe_t), KM_SLEEP);
2826621Sbt150084 
2836621Sbt150084 	ixgbe->dip = devinfo;
2846621Sbt150084 	ixgbe->instance = instance;
2856621Sbt150084 
2866621Sbt150084 	hw = &ixgbe->hw;
2876621Sbt150084 	osdep = &ixgbe->osdep;
2886621Sbt150084 	hw->back = osdep;
2896621Sbt150084 	osdep->ixgbe = ixgbe;
2906621Sbt150084 
2916621Sbt150084 	/* Attach the instance pointer to the dev_info data structure */
2926621Sbt150084 	ddi_set_driver_private(devinfo, ixgbe);
2936621Sbt150084 
2946621Sbt150084 	/*
2956621Sbt150084 	 * Initialize for fma support
2966621Sbt150084 	 */
297*7167Sgg161487 	ixgbe->fm_capabilities = ixgbe_get_prop(ixgbe, PROP_FM_CAPABLE,
2986621Sbt150084 	    0, 0x0f, DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
2996621Sbt150084 	    DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
3006621Sbt150084 	ixgbe_fm_init(ixgbe);
3016621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_FM_INIT;
3026621Sbt150084 
3036621Sbt150084 	/*
3046621Sbt150084 	 * Map PCI config space registers
3056621Sbt150084 	 */
3066621Sbt150084 	if (pci_config_setup(devinfo, &osdep->cfg_handle) != DDI_SUCCESS) {
3076621Sbt150084 		ixgbe_error(ixgbe, "Failed to map PCI configurations");
3086621Sbt150084 		goto attach_fail;
3096621Sbt150084 	}
3106621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_PCI_CONFIG;
3116621Sbt150084 
3126621Sbt150084 	/*
3136621Sbt150084 	 * Identify the chipset family
3146621Sbt150084 	 */
3156621Sbt150084 	if (ixgbe_identify_hardware(ixgbe) != IXGBE_SUCCESS) {
3166621Sbt150084 		ixgbe_error(ixgbe, "Failed to identify hardware");
3176621Sbt150084 		goto attach_fail;
3186621Sbt150084 	}
3196621Sbt150084 
3206621Sbt150084 	/*
3216621Sbt150084 	 * Map device registers
3226621Sbt150084 	 */
3236621Sbt150084 	if (ixgbe_regs_map(ixgbe) != IXGBE_SUCCESS) {
3246621Sbt150084 		ixgbe_error(ixgbe, "Failed to map device registers");
3256621Sbt150084 		goto attach_fail;
3266621Sbt150084 	}
3276621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_REGS_MAP;
3286621Sbt150084 
3296621Sbt150084 	/*
3306621Sbt150084 	 * Initialize driver parameters
3316621Sbt150084 	 */
3326621Sbt150084 	ixgbe_init_properties(ixgbe);
3336621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_PROPS;
3346621Sbt150084 
3356621Sbt150084 	/*
3366621Sbt150084 	 * Allocate interrupts
3376621Sbt150084 	 */
3386621Sbt150084 	if (ixgbe_alloc_intrs(ixgbe) != IXGBE_SUCCESS) {
3396621Sbt150084 		ixgbe_error(ixgbe, "Failed to allocate interrupts");
3406621Sbt150084 		goto attach_fail;
3416621Sbt150084 	}
3426621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_ALLOC_INTR;
3436621Sbt150084 
3446621Sbt150084 	/*
3456621Sbt150084 	 * Allocate rx/tx rings based on the ring numbers.
3466621Sbt150084 	 * The actual numbers of rx/tx rings are decided by the number of
3476621Sbt150084 	 * allocated interrupt vectors, so we should allocate the rings after
3486621Sbt150084 	 * interrupts are allocated.
3496621Sbt150084 	 */
3506621Sbt150084 	if (ixgbe_alloc_rings(ixgbe) != IXGBE_SUCCESS) {
3516621Sbt150084 		ixgbe_error(ixgbe, "Failed to allocate rx and tx rings");
3526621Sbt150084 		goto attach_fail;
3536621Sbt150084 	}
3546621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_ALLOC_RINGS;
3556621Sbt150084 
3566621Sbt150084 	/*
3576621Sbt150084 	 * Map rings to interrupt vectors
3586621Sbt150084 	 */
3596621Sbt150084 	if (ixgbe_map_rings_to_vectors(ixgbe) != IXGBE_SUCCESS) {
3606621Sbt150084 		ixgbe_error(ixgbe, "Failed to map rings to vectors");
3616621Sbt150084 		goto attach_fail;
3626621Sbt150084 	}
3636621Sbt150084 
3646621Sbt150084 	/*
3656621Sbt150084 	 * Add interrupt handlers
3666621Sbt150084 	 */
3676621Sbt150084 	if (ixgbe_add_intr_handlers(ixgbe) != IXGBE_SUCCESS) {
3686621Sbt150084 		ixgbe_error(ixgbe, "Failed to add interrupt handlers");
3696621Sbt150084 		goto attach_fail;
3706621Sbt150084 	}
3716621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_ADD_INTR;
3726621Sbt150084 
3736621Sbt150084 	/*
3746621Sbt150084 	 * Initialize driver parameters
3756621Sbt150084 	 */
3766621Sbt150084 	if (ixgbe_init_driver_settings(ixgbe) != IXGBE_SUCCESS) {
3776621Sbt150084 		ixgbe_error(ixgbe, "Failed to initialize driver settings");
3786621Sbt150084 		goto attach_fail;
3796621Sbt150084 	}
3806621Sbt150084 
3816621Sbt150084 	/*
3826621Sbt150084 	 * Initialize mutexes for this device.
3836621Sbt150084 	 * Do this before enabling the interrupt handler and
3846621Sbt150084 	 * register the softint to avoid the condition where
3856621Sbt150084 	 * interrupt handler can try using uninitialized mutex.
3866621Sbt150084 	 */
3876621Sbt150084 	ixgbe_init_locks(ixgbe);
3886621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_LOCKS;
3896621Sbt150084 
3906621Sbt150084 	/*
3916621Sbt150084 	 * Initialize chipset hardware
3926621Sbt150084 	 */
3936621Sbt150084 	if (ixgbe_init(ixgbe) != IXGBE_SUCCESS) {
3946621Sbt150084 		ixgbe_error(ixgbe, "Failed to initialize adapter");
3956621Sbt150084 		goto attach_fail;
3966621Sbt150084 	}
3976621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_INIT;
3986621Sbt150084 
3996621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.cfg_handle) != DDI_FM_OK) {
4006621Sbt150084 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_LOST);
4016621Sbt150084 		goto attach_fail;
4026621Sbt150084 	}
4036621Sbt150084 
4046621Sbt150084 	/*
4056621Sbt150084 	 * Initialize DMA and hardware settings for rx/tx rings
4066621Sbt150084 	 */
4076621Sbt150084 	if (ixgbe_init_rings(ixgbe) != IXGBE_SUCCESS) {
4086621Sbt150084 		ixgbe_error(ixgbe, "Failed to initialize rings");
4096621Sbt150084 		goto attach_fail;
4106621Sbt150084 	}
4116621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_INIT_RINGS;
4126621Sbt150084 
4136621Sbt150084 	/*
4146621Sbt150084 	 * Initialize statistics
4156621Sbt150084 	 */
4166621Sbt150084 	if (ixgbe_init_stats(ixgbe) != IXGBE_SUCCESS) {
4176621Sbt150084 		ixgbe_error(ixgbe, "Failed to initialize statistics");
4186621Sbt150084 		goto attach_fail;
4196621Sbt150084 	}
4206621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_STATS;
4216621Sbt150084 
4226621Sbt150084 	/*
4236621Sbt150084 	 * Initialize NDD parameters
4246621Sbt150084 	 */
4256621Sbt150084 	if (ixgbe_nd_init(ixgbe) != IXGBE_SUCCESS) {
4266621Sbt150084 		ixgbe_error(ixgbe, "Failed to initialize ndd");
4276621Sbt150084 		goto attach_fail;
4286621Sbt150084 	}
4296621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_NDD;
4306621Sbt150084 
4316621Sbt150084 	/*
4326621Sbt150084 	 * Register the driver to the MAC
4336621Sbt150084 	 */
4346621Sbt150084 	if (ixgbe_register_mac(ixgbe) != IXGBE_SUCCESS) {
4356621Sbt150084 		ixgbe_error(ixgbe, "Failed to register MAC");
4366621Sbt150084 		goto attach_fail;
4376621Sbt150084 	}
4386621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_MAC;
4396621Sbt150084 
4406621Sbt150084 	/*
4416621Sbt150084 	 * Now that mutex locks are initialized, and the chip is also
4426621Sbt150084 	 * initialized, enable interrupts.
4436621Sbt150084 	 */
4446621Sbt150084 	if (ixgbe_enable_intrs(ixgbe) != IXGBE_SUCCESS) {
4456621Sbt150084 		ixgbe_error(ixgbe, "Failed to enable DDI interrupts");
4466621Sbt150084 		goto attach_fail;
4476621Sbt150084 	}
4486621Sbt150084 	ixgbe->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR;
4496621Sbt150084 
4506621Sbt150084 	ixgbe->ixgbe_state |= IXGBE_INITIALIZED;
4516621Sbt150084 
4526621Sbt150084 	return (DDI_SUCCESS);
4536621Sbt150084 
4546621Sbt150084 attach_fail:
4556621Sbt150084 	ixgbe_unconfigure(devinfo, ixgbe);
4566621Sbt150084 	return (DDI_FAILURE);
4576621Sbt150084 }
4586621Sbt150084 
4596621Sbt150084 /*
4606621Sbt150084  * ixgbe_detach - Driver detach.
4616621Sbt150084  *
4626621Sbt150084  * The detach() function is the complement of the attach routine.
4636621Sbt150084  * If cmd is set to DDI_DETACH, detach() is used to remove  the
4646621Sbt150084  * state  associated  with  a  given  instance of a device node
4656621Sbt150084  * prior to the removal of that instance from the system.
4666621Sbt150084  *
4676621Sbt150084  * The detach() function will be called once for each  instance
4686621Sbt150084  * of the device for which there has been a successful attach()
4696621Sbt150084  * once there are no longer  any  opens  on  the  device.
4706621Sbt150084  *
4716621Sbt150084  * Interrupts routine are disabled, All memory allocated by this
4726621Sbt150084  * driver are freed.
4736621Sbt150084  */
4746621Sbt150084 static int
4756621Sbt150084 ixgbe_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
4766621Sbt150084 {
4776621Sbt150084 	ixgbe_t *ixgbe;
4786621Sbt150084 
4796621Sbt150084 	/*
4806621Sbt150084 	 * Check detach command
4816621Sbt150084 	 */
4826621Sbt150084 	switch (cmd) {
4836621Sbt150084 	default:
4846621Sbt150084 		return (DDI_FAILURE);
4856621Sbt150084 
4866621Sbt150084 	case DDI_SUSPEND:
4876621Sbt150084 		return (ixgbe_suspend(devinfo));
4886621Sbt150084 
4896621Sbt150084 	case DDI_DETACH:
4906621Sbt150084 		break;
4916621Sbt150084 	}
4926621Sbt150084 
4936621Sbt150084 
4946621Sbt150084 	/*
4956621Sbt150084 	 * Get the pointer to the driver private data structure
4966621Sbt150084 	 */
4976621Sbt150084 	ixgbe = (ixgbe_t *)ddi_get_driver_private(devinfo);
4986621Sbt150084 	if (ixgbe == NULL)
4996621Sbt150084 		return (DDI_FAILURE);
5006621Sbt150084 
5016621Sbt150084 	/*
5026621Sbt150084 	 * Unregister MAC. If failed, we have to fail the detach
5036621Sbt150084 	 */
5046621Sbt150084 	if (mac_unregister(ixgbe->mac_hdl) != 0) {
5056621Sbt150084 		ixgbe_error(ixgbe, "Failed to unregister MAC");
5066621Sbt150084 		return (DDI_FAILURE);
5076621Sbt150084 	}
5086621Sbt150084 	ixgbe->attach_progress &= ~ATTACH_PROGRESS_MAC;
5096621Sbt150084 
5106621Sbt150084 	/*
5116621Sbt150084 	 * If the device is still running, it needs to be stopped first.
5126621Sbt150084 	 * This check is necessary because under some specific circumstances,
5136621Sbt150084 	 * the detach routine can be called without stopping the interface
5146621Sbt150084 	 * first.
5156621Sbt150084 	 */
5166621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
5176621Sbt150084 	if (ixgbe->ixgbe_state & IXGBE_STARTED) {
5186621Sbt150084 		ixgbe->ixgbe_state &= ~IXGBE_STARTED;
5196621Sbt150084 		ixgbe_stop(ixgbe);
5206621Sbt150084 		mutex_exit(&ixgbe->gen_lock);
5216621Sbt150084 		/* Disable and stop the watchdog timer */
5226621Sbt150084 		ixgbe_disable_watchdog_timer(ixgbe);
5236621Sbt150084 	} else
5246621Sbt150084 		mutex_exit(&ixgbe->gen_lock);
5256621Sbt150084 
5266621Sbt150084 	/*
5276621Sbt150084 	 * Check if there are still rx buffers held by the upper layer.
5286621Sbt150084 	 * If so, fail the detach.
5296621Sbt150084 	 */
5306621Sbt150084 	if (!ixgbe_rx_drain(ixgbe))
5316621Sbt150084 		return (DDI_FAILURE);
5326621Sbt150084 
5336621Sbt150084 	/*
5346621Sbt150084 	 * Do the remaining unconfigure routines
5356621Sbt150084 	 */
5366621Sbt150084 	ixgbe_unconfigure(devinfo, ixgbe);
5376621Sbt150084 
5386621Sbt150084 	return (DDI_SUCCESS);
5396621Sbt150084 }
5406621Sbt150084 
5416621Sbt150084 static void
5426621Sbt150084 ixgbe_unconfigure(dev_info_t *devinfo, ixgbe_t *ixgbe)
5436621Sbt150084 {
5446621Sbt150084 	/*
5456621Sbt150084 	 * Disable interrupt
5466621Sbt150084 	 */
5476621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_ENABLE_INTR) {
5486621Sbt150084 		(void) ixgbe_disable_intrs(ixgbe);
5496621Sbt150084 	}
5506621Sbt150084 
5516621Sbt150084 	/*
5526621Sbt150084 	 * Unregister MAC
5536621Sbt150084 	 */
5546621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_MAC) {
5556621Sbt150084 		(void) mac_unregister(ixgbe->mac_hdl);
5566621Sbt150084 	}
5576621Sbt150084 
5586621Sbt150084 	/*
5596621Sbt150084 	 * Free ndd parameters
5606621Sbt150084 	 */
5616621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_NDD) {
5626621Sbt150084 		ixgbe_nd_cleanup(ixgbe);
5636621Sbt150084 	}
5646621Sbt150084 
5656621Sbt150084 	/*
5666621Sbt150084 	 * Free statistics
5676621Sbt150084 	 */
5686621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_STATS) {
5696621Sbt150084 		kstat_delete((kstat_t *)ixgbe->ixgbe_ks);
5706621Sbt150084 	}
5716621Sbt150084 
5726621Sbt150084 	/*
5736621Sbt150084 	 * Remove interrupt handlers
5746621Sbt150084 	 */
5756621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_ADD_INTR) {
5766621Sbt150084 		ixgbe_rem_intr_handlers(ixgbe);
5776621Sbt150084 	}
5786621Sbt150084 
5796621Sbt150084 	/*
5806621Sbt150084 	 * Remove interrupts
5816621Sbt150084 	 */
5826621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_ALLOC_INTR) {
5836621Sbt150084 		ixgbe_rem_intrs(ixgbe);
5846621Sbt150084 	}
5856621Sbt150084 
5866621Sbt150084 	/*
5876621Sbt150084 	 * Remove driver properties
5886621Sbt150084 	 */
5896621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_PROPS) {
5906621Sbt150084 		(void) ddi_prop_remove_all(devinfo);
5916621Sbt150084 	}
5926621Sbt150084 
5936621Sbt150084 	/*
5946621Sbt150084 	 * Release the DMA resources of rx/tx rings
5956621Sbt150084 	 */
5966621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_INIT_RINGS) {
5976621Sbt150084 		ixgbe_fini_rings(ixgbe);
5986621Sbt150084 	}
5996621Sbt150084 
6006621Sbt150084 	/*
6016621Sbt150084 	 * Stop the chipset
6026621Sbt150084 	 */
6036621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_INIT) {
6046621Sbt150084 		mutex_enter(&ixgbe->gen_lock);
6056621Sbt150084 		ixgbe_chip_stop(ixgbe);
6066621Sbt150084 		mutex_exit(&ixgbe->gen_lock);
6076621Sbt150084 	}
6086621Sbt150084 
6096621Sbt150084 	/*
6106621Sbt150084 	 * Free register handle
6116621Sbt150084 	 */
6126621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_REGS_MAP) {
6136621Sbt150084 		if (ixgbe->osdep.reg_handle != NULL)
6146621Sbt150084 			ddi_regs_map_free(&ixgbe->osdep.reg_handle);
6156621Sbt150084 	}
6166621Sbt150084 
6176621Sbt150084 	/*
6186621Sbt150084 	 * Free PCI config handle
6196621Sbt150084 	 */
6206621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_PCI_CONFIG) {
6216621Sbt150084 		if (ixgbe->osdep.cfg_handle != NULL)
6226621Sbt150084 			pci_config_teardown(&ixgbe->osdep.cfg_handle);
6236621Sbt150084 	}
6246621Sbt150084 
6256621Sbt150084 	/*
6266621Sbt150084 	 * Free locks
6276621Sbt150084 	 */
6286621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_LOCKS) {
6296621Sbt150084 		ixgbe_destroy_locks(ixgbe);
6306621Sbt150084 	}
6316621Sbt150084 
6326621Sbt150084 	/*
6336621Sbt150084 	 * Free the rx/tx rings
6346621Sbt150084 	 */
6356621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_ALLOC_RINGS) {
6366621Sbt150084 		ixgbe_free_rings(ixgbe);
6376621Sbt150084 	}
6386621Sbt150084 
6396621Sbt150084 	/*
6406621Sbt150084 	 * Unregister FMA capabilities
6416621Sbt150084 	 */
6426621Sbt150084 	if (ixgbe->attach_progress & ATTACH_PROGRESS_FM_INIT) {
6436621Sbt150084 		ixgbe_fm_fini(ixgbe);
6446621Sbt150084 	}
6456621Sbt150084 
6466621Sbt150084 	/*
6476621Sbt150084 	 * Free the driver data structure
6486621Sbt150084 	 */
6496621Sbt150084 	kmem_free(ixgbe, sizeof (ixgbe_t));
6506621Sbt150084 
6516621Sbt150084 	ddi_set_driver_private(devinfo, NULL);
6526621Sbt150084 }
6536621Sbt150084 
6546621Sbt150084 /*
6556621Sbt150084  * ixgbe_register_mac - Register the driver and its function pointers with
6566621Sbt150084  * the GLD interface.
6576621Sbt150084  */
6586621Sbt150084 static int
6596621Sbt150084 ixgbe_register_mac(ixgbe_t *ixgbe)
6606621Sbt150084 {
6616621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
6626621Sbt150084 	mac_register_t *mac;
6636621Sbt150084 	int status;
6646621Sbt150084 
6656621Sbt150084 	if ((mac = mac_alloc(MAC_VERSION)) == NULL)
6666621Sbt150084 		return (IXGBE_FAILURE);
6676621Sbt150084 
6686621Sbt150084 	mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
6696621Sbt150084 	mac->m_driver = ixgbe;
6706621Sbt150084 	mac->m_dip = ixgbe->dip;
6716621Sbt150084 	mac->m_src_addr = hw->mac.addr;
6726621Sbt150084 	mac->m_callbacks = &ixgbe_m_callbacks;
6736621Sbt150084 	mac->m_min_sdu = 0;
6746621Sbt150084 	mac->m_max_sdu = ixgbe->default_mtu;
6756621Sbt150084 	mac->m_margin = VLAN_TAGSZ;
6766621Sbt150084 
6776621Sbt150084 	status = mac_register(mac, &ixgbe->mac_hdl);
6786621Sbt150084 
6796621Sbt150084 	mac_free(mac);
6806621Sbt150084 
6816621Sbt150084 	return ((status == 0) ? IXGBE_SUCCESS : IXGBE_FAILURE);
6826621Sbt150084 }
6836621Sbt150084 
6846621Sbt150084 /*
6856621Sbt150084  * ixgbe_identify_hardware - Identify the type of the chipset.
6866621Sbt150084  */
6876621Sbt150084 static int
6886621Sbt150084 ixgbe_identify_hardware(ixgbe_t *ixgbe)
6896621Sbt150084 {
6906621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
6916621Sbt150084 	struct ixgbe_osdep *osdep = &ixgbe->osdep;
6926621Sbt150084 
6936621Sbt150084 	/*
6946621Sbt150084 	 * Get the device id
6956621Sbt150084 	 */
6966621Sbt150084 	hw->vendor_id =
6976621Sbt150084 	    pci_config_get16(osdep->cfg_handle, PCI_CONF_VENID);
6986621Sbt150084 	hw->device_id =
6996621Sbt150084 	    pci_config_get16(osdep->cfg_handle, PCI_CONF_DEVID);
7006621Sbt150084 	hw->revision_id =
7016621Sbt150084 	    pci_config_get8(osdep->cfg_handle, PCI_CONF_REVID);
7026621Sbt150084 	hw->subsystem_device_id =
7036621Sbt150084 	    pci_config_get16(osdep->cfg_handle, PCI_CONF_SUBSYSID);
7046621Sbt150084 	hw->subsystem_vendor_id =
7056621Sbt150084 	    pci_config_get16(osdep->cfg_handle, PCI_CONF_SUBVENID);
7066621Sbt150084 
7076621Sbt150084 	return (IXGBE_SUCCESS);
7086621Sbt150084 }
7096621Sbt150084 
7106621Sbt150084 /*
7116621Sbt150084  * ixgbe_regs_map - Map the device registers.
7126621Sbt150084  *
7136621Sbt150084  */
7146621Sbt150084 static int
7156621Sbt150084 ixgbe_regs_map(ixgbe_t *ixgbe)
7166621Sbt150084 {
7176621Sbt150084 	dev_info_t *devinfo = ixgbe->dip;
7186621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
7196621Sbt150084 	struct ixgbe_osdep *osdep = &ixgbe->osdep;
7206621Sbt150084 	off_t mem_size;
7216621Sbt150084 
7226621Sbt150084 	/*
7236621Sbt150084 	 * First get the size of device registers to be mapped.
7246621Sbt150084 	 */
7256621Sbt150084 	if (ddi_dev_regsize(devinfo, 1, &mem_size) != DDI_SUCCESS) {
7266621Sbt150084 		return (IXGBE_FAILURE);
7276621Sbt150084 	}
7286621Sbt150084 
7296621Sbt150084 	/*
7306621Sbt150084 	 * Call ddi_regs_map_setup() to map registers
7316621Sbt150084 	 */
7326621Sbt150084 	if ((ddi_regs_map_setup(devinfo, 1,
7336621Sbt150084 	    (caddr_t *)&hw->hw_addr, 0,
7346621Sbt150084 	    mem_size, &ixgbe_regs_acc_attr,
7356621Sbt150084 	    &osdep->reg_handle)) != DDI_SUCCESS) {
7366621Sbt150084 		return (IXGBE_FAILURE);
7376621Sbt150084 	}
7386621Sbt150084 
7396621Sbt150084 	return (IXGBE_SUCCESS);
7406621Sbt150084 }
7416621Sbt150084 
7426621Sbt150084 /*
7436621Sbt150084  * ixgbe_init_properties - Initialize driver properties.
7446621Sbt150084  */
7456621Sbt150084 static void
7466621Sbt150084 ixgbe_init_properties(ixgbe_t *ixgbe)
7476621Sbt150084 {
7486621Sbt150084 	/*
7496621Sbt150084 	 * Get conf file properties, including link settings
7506621Sbt150084 	 * jumbo frames, ring number, descriptor number, etc.
7516621Sbt150084 	 */
7526621Sbt150084 	ixgbe_get_conf(ixgbe);
7536621Sbt150084 }
7546621Sbt150084 
7556621Sbt150084 /*
7566621Sbt150084  * ixgbe_init_driver_settings - Initialize driver settings.
7576621Sbt150084  *
7586621Sbt150084  * The settings include hardware function pointers, bus information,
7596621Sbt150084  * rx/tx rings settings, link state, and any other parameters that
7606621Sbt150084  * need to be setup during driver initialization.
7616621Sbt150084  */
7626621Sbt150084 static int
7636621Sbt150084 ixgbe_init_driver_settings(ixgbe_t *ixgbe)
7646621Sbt150084 {
7656621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
7666621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
7676621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
7686621Sbt150084 	uint32_t rx_size;
7696621Sbt150084 	uint32_t tx_size;
7706621Sbt150084 	int i;
7716621Sbt150084 
7726621Sbt150084 	/*
7736621Sbt150084 	 * Initialize chipset specific hardware function pointers
7746621Sbt150084 	 */
7756621Sbt150084 	if (ixgbe_init_shared_code(hw) != IXGBE_SUCCESS) {
7766621Sbt150084 		return (IXGBE_FAILURE);
7776621Sbt150084 	}
7786621Sbt150084 
7796621Sbt150084 	/*
7806621Sbt150084 	 * Set rx buffer size
7816621Sbt150084 	 *
7826621Sbt150084 	 * The IP header alignment room is counted in the calculation.
7836621Sbt150084 	 * The rx buffer size is in unit of 1K that is required by the
7846621Sbt150084 	 * chipset hardware.
7856621Sbt150084 	 */
7866621Sbt150084 	rx_size = ixgbe->max_frame_size + IPHDR_ALIGN_ROOM;
7876621Sbt150084 	ixgbe->rx_buf_size = ((rx_size >> 10) +
7886621Sbt150084 	    ((rx_size & (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
7896621Sbt150084 
7906621Sbt150084 	/*
7916621Sbt150084 	 * Set tx buffer size
7926621Sbt150084 	 */
7936621Sbt150084 	tx_size = ixgbe->max_frame_size;
7946621Sbt150084 	ixgbe->tx_buf_size = ((tx_size >> 10) +
7956621Sbt150084 	    ((tx_size & (((uint32_t)1 << 10) - 1)) > 0 ? 1 : 0)) << 10;
7966621Sbt150084 
7976621Sbt150084 	/*
7986621Sbt150084 	 * Initialize rx/tx rings parameters
7996621Sbt150084 	 */
8006621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
8016621Sbt150084 		rx_ring = &ixgbe->rx_rings[i];
8026621Sbt150084 		rx_ring->index = i;
8036621Sbt150084 		rx_ring->ixgbe = ixgbe;
8046621Sbt150084 
8056621Sbt150084 		rx_ring->ring_size = ixgbe->rx_ring_size;
8066621Sbt150084 		rx_ring->free_list_size = ixgbe->rx_ring_size;
8076621Sbt150084 		rx_ring->copy_thresh = ixgbe->rx_copy_thresh;
8086621Sbt150084 		rx_ring->limit_per_intr = ixgbe->rx_limit_per_intr;
8096621Sbt150084 	}
8106621Sbt150084 
8116621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
8126621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
8136621Sbt150084 		tx_ring->index = i;
8146621Sbt150084 		tx_ring->ixgbe = ixgbe;
8156621Sbt150084 		if (ixgbe->tx_head_wb_enable)
8166621Sbt150084 			tx_ring->tx_recycle = ixgbe_tx_recycle_head_wb;
8176621Sbt150084 		else
8186621Sbt150084 			tx_ring->tx_recycle = ixgbe_tx_recycle_legacy;
8196621Sbt150084 
8206621Sbt150084 		tx_ring->ring_size = ixgbe->tx_ring_size;
8216621Sbt150084 		tx_ring->free_list_size = ixgbe->tx_ring_size +
8226621Sbt150084 		    (ixgbe->tx_ring_size >> 1);
8236621Sbt150084 		tx_ring->copy_thresh = ixgbe->tx_copy_thresh;
8246621Sbt150084 		tx_ring->recycle_thresh = ixgbe->tx_recycle_thresh;
8256621Sbt150084 		tx_ring->overload_thresh = ixgbe->tx_overload_thresh;
8266621Sbt150084 	tx_ring->resched_thresh = ixgbe->tx_resched_thresh;
8276621Sbt150084 	}
8286621Sbt150084 
8296621Sbt150084 	/*
8306621Sbt150084 	 * Initialize values of interrupt throttling rate
8316621Sbt150084 	 */
8326621Sbt150084 	for (i = 1; i < IXGBE_MAX_RING_VECTOR; i++)
8336621Sbt150084 		ixgbe->intr_throttling[i] = ixgbe->intr_throttling[0];
8346621Sbt150084 
8356621Sbt150084 	/*
8366621Sbt150084 	 * The initial link state should be "unknown"
8376621Sbt150084 	 */
8386621Sbt150084 	ixgbe->link_state = LINK_STATE_UNKNOWN;
8396621Sbt150084 	return (IXGBE_SUCCESS);
8406621Sbt150084 }
8416621Sbt150084 
8426621Sbt150084 /*
8436621Sbt150084  * ixgbe_init_locks - Initialize locks.
8446621Sbt150084  */
8456621Sbt150084 static void
8466621Sbt150084 ixgbe_init_locks(ixgbe_t *ixgbe)
8476621Sbt150084 {
8486621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
8496621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
8506621Sbt150084 	int i;
8516621Sbt150084 
8526621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
8536621Sbt150084 		rx_ring = &ixgbe->rx_rings[i];
8546621Sbt150084 		mutex_init(&rx_ring->rx_lock, NULL,
8556621Sbt150084 		    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8566621Sbt150084 		mutex_init(&rx_ring->recycle_lock, NULL,
8576621Sbt150084 		    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8586621Sbt150084 	}
8596621Sbt150084 
8606621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
8616621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
8626621Sbt150084 		mutex_init(&tx_ring->tx_lock, NULL,
8636621Sbt150084 		    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8646621Sbt150084 		mutex_init(&tx_ring->recycle_lock, NULL,
8656621Sbt150084 		    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8666621Sbt150084 		mutex_init(&tx_ring->tcb_head_lock, NULL,
8676621Sbt150084 		    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8686621Sbt150084 		mutex_init(&tx_ring->tcb_tail_lock, NULL,
8696621Sbt150084 		    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8706621Sbt150084 	}
8716621Sbt150084 
8726621Sbt150084 	mutex_init(&ixgbe->gen_lock, NULL,
8736621Sbt150084 	    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8746621Sbt150084 
8756621Sbt150084 	mutex_init(&ixgbe->watchdog_lock, NULL,
8766621Sbt150084 	    MUTEX_DRIVER, DDI_INTR_PRI(ixgbe->intr_pri));
8776621Sbt150084 }
8786621Sbt150084 
8796621Sbt150084 /*
8806621Sbt150084  * ixgbe_destroy_locks - Destroy locks.
8816621Sbt150084  */
8826621Sbt150084 static void
8836621Sbt150084 ixgbe_destroy_locks(ixgbe_t *ixgbe)
8846621Sbt150084 {
8856621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
8866621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
8876621Sbt150084 	int i;
8886621Sbt150084 
8896621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
8906621Sbt150084 		rx_ring = &ixgbe->rx_rings[i];
8916621Sbt150084 		mutex_destroy(&rx_ring->rx_lock);
8926621Sbt150084 		mutex_destroy(&rx_ring->recycle_lock);
8936621Sbt150084 	}
8946621Sbt150084 
8956621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
8966621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
8976621Sbt150084 		mutex_destroy(&tx_ring->tx_lock);
8986621Sbt150084 		mutex_destroy(&tx_ring->recycle_lock);
8996621Sbt150084 		mutex_destroy(&tx_ring->tcb_head_lock);
9006621Sbt150084 		mutex_destroy(&tx_ring->tcb_tail_lock);
9016621Sbt150084 	}
9026621Sbt150084 
9036621Sbt150084 	mutex_destroy(&ixgbe->gen_lock);
9046621Sbt150084 	mutex_destroy(&ixgbe->watchdog_lock);
9056621Sbt150084 }
9066621Sbt150084 
9076621Sbt150084 static int
9086621Sbt150084 ixgbe_resume(dev_info_t *devinfo)
9096621Sbt150084 {
9106621Sbt150084 	ixgbe_t *ixgbe;
9116621Sbt150084 
9126621Sbt150084 	ixgbe = (ixgbe_t *)ddi_get_driver_private(devinfo);
9136621Sbt150084 	if (ixgbe == NULL)
9146621Sbt150084 		return (DDI_FAILURE);
9156621Sbt150084 
9166621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
9176621Sbt150084 
9186621Sbt150084 	if (ixgbe->ixgbe_state & IXGBE_STARTED) {
9196621Sbt150084 		if (ixgbe_start(ixgbe) != IXGBE_SUCCESS) {
9206621Sbt150084 			mutex_exit(&ixgbe->gen_lock);
9216621Sbt150084 			return (DDI_FAILURE);
9226621Sbt150084 		}
9236621Sbt150084 
9246621Sbt150084 		/*
9256621Sbt150084 		 * Enable and start the watchdog timer
9266621Sbt150084 		 */
9276621Sbt150084 		ixgbe_enable_watchdog_timer(ixgbe);
9286621Sbt150084 	}
9296621Sbt150084 
9306621Sbt150084 	ixgbe->ixgbe_state &= ~IXGBE_SUSPENDED;
9316621Sbt150084 
9326621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
9336621Sbt150084 
9346621Sbt150084 	return (DDI_SUCCESS);
9356621Sbt150084 }
9366621Sbt150084 
9376621Sbt150084 static int
9386621Sbt150084 ixgbe_suspend(dev_info_t *devinfo)
9396621Sbt150084 {
9406621Sbt150084 	ixgbe_t *ixgbe;
9416621Sbt150084 
9426621Sbt150084 	ixgbe = (ixgbe_t *)ddi_get_driver_private(devinfo);
9436621Sbt150084 	if (ixgbe == NULL)
9446621Sbt150084 		return (DDI_FAILURE);
9456621Sbt150084 
9466621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
9476621Sbt150084 
9486621Sbt150084 	ixgbe->ixgbe_state |= IXGBE_SUSPENDED;
9496621Sbt150084 
9506621Sbt150084 	ixgbe_stop(ixgbe);
9516621Sbt150084 
9526621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
9536621Sbt150084 
9546621Sbt150084 	/*
9556621Sbt150084 	 * Disable and stop the watchdog timer
9566621Sbt150084 	 */
9576621Sbt150084 	ixgbe_disable_watchdog_timer(ixgbe);
9586621Sbt150084 
9596621Sbt150084 	return (DDI_SUCCESS);
9606621Sbt150084 }
9616621Sbt150084 
9626621Sbt150084 /*
9636621Sbt150084  * ixgbe_init - Initialize the device.
9646621Sbt150084  */
9656621Sbt150084 static int
9666621Sbt150084 ixgbe_init(ixgbe_t *ixgbe)
9676621Sbt150084 {
9686621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
9696621Sbt150084 
9706621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
9716621Sbt150084 
9726621Sbt150084 	/*
9736621Sbt150084 	 * Reset chipset to put the hardware in a known state
9746621Sbt150084 	 * before we try to do anything with the eeprom.
9756621Sbt150084 	 */
9766621Sbt150084 	if (ixgbe_reset_hw(hw) != IXGBE_SUCCESS) {
9776621Sbt150084 		ixgbe_fm_ereport(ixgbe, DDI_FM_DEVICE_INVAL_STATE);
9786621Sbt150084 		goto init_fail;
9796621Sbt150084 	}
9806621Sbt150084 
9816621Sbt150084 	/*
9826621Sbt150084 	 * Need to init eeprom before validating the checksum.
9836621Sbt150084 	 */
9846621Sbt150084 	if (ixgbe_init_eeprom_params(hw) < 0) {
9856621Sbt150084 		ixgbe_error(ixgbe,
9866621Sbt150084 		    "Unable to intitialize the eeprom interface.");
9876621Sbt150084 		ixgbe_fm_ereport(ixgbe, DDI_FM_DEVICE_INVAL_STATE);
9886621Sbt150084 		goto init_fail;
9896621Sbt150084 	}
9906621Sbt150084 
9916621Sbt150084 	/*
9926621Sbt150084 	 * NVM validation
9936621Sbt150084 	 */
9946621Sbt150084 	if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
9956621Sbt150084 		/*
9966621Sbt150084 		 * Some PCI-E parts fail the first check due to
9976621Sbt150084 		 * the link being in sleep state.  Call it again,
9986621Sbt150084 		 * if it fails a second time it's a real issue.
9996621Sbt150084 		 */
10006621Sbt150084 		if (ixgbe_validate_eeprom_checksum(hw, NULL) < 0) {
10016621Sbt150084 			ixgbe_error(ixgbe,
10026621Sbt150084 			    "Invalid NVM checksum. Please contact "
10036621Sbt150084 			    "the vendor to update the NVM.");
10046621Sbt150084 			ixgbe_fm_ereport(ixgbe, DDI_FM_DEVICE_INVAL_STATE);
10056621Sbt150084 			goto init_fail;
10066621Sbt150084 		}
10076621Sbt150084 	}
10086621Sbt150084 
10096621Sbt150084 	/*
10106621Sbt150084 	 * Setup default flow control thresholds - enable/disable
10116621Sbt150084 	 * & flow control type is controlled by ixgbe.conf
10126621Sbt150084 	 */
10136621Sbt150084 	hw->fc.high_water = DEFAULT_FCRTH;
10146621Sbt150084 	hw->fc.low_water = DEFAULT_FCRTL;
10156621Sbt150084 	hw->fc.pause_time = DEFAULT_FCPAUSE;
10166621Sbt150084 	hw->fc.send_xon = B_TRUE;
10176621Sbt150084 
10186621Sbt150084 	/*
10196621Sbt150084 	 * Don't wait for auto-negotiation to complete
10206621Sbt150084 	 */
10216621Sbt150084 	hw->phy.autoneg_wait_to_complete = B_FALSE;
10226621Sbt150084 
10236621Sbt150084 	/*
10246621Sbt150084 	 * Initialize link settings
10256621Sbt150084 	 */
10266621Sbt150084 	(void) ixgbe_driver_setup_link(ixgbe, B_FALSE);
10276621Sbt150084 
10286621Sbt150084 	/*
10296621Sbt150084 	 * Initialize the chipset hardware
10306621Sbt150084 	 */
10316621Sbt150084 	if (ixgbe_chip_start(ixgbe) != IXGBE_SUCCESS) {
10326621Sbt150084 		ixgbe_fm_ereport(ixgbe, DDI_FM_DEVICE_INVAL_STATE);
10336621Sbt150084 		goto init_fail;
10346621Sbt150084 	}
10356621Sbt150084 
10366621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.cfg_handle) != DDI_FM_OK) {
10376621Sbt150084 		goto init_fail;
10386621Sbt150084 	}
10396621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
10406621Sbt150084 		goto init_fail;
10416621Sbt150084 	}
10426621Sbt150084 
10436621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
10446621Sbt150084 	return (IXGBE_SUCCESS);
10456621Sbt150084 
10466621Sbt150084 init_fail:
10476621Sbt150084 	/*
10486621Sbt150084 	 * Reset PHY
10496621Sbt150084 	 */
10506621Sbt150084 	(void) ixgbe_reset_phy(hw);
10516621Sbt150084 
10526621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
10536621Sbt150084 	ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_LOST);
10546621Sbt150084 	return (IXGBE_FAILURE);
10556621Sbt150084 }
10566621Sbt150084 
10576621Sbt150084 /*
10586621Sbt150084  * ixgbe_init_rings - Allocate DMA resources for all rx/tx rings and
10596621Sbt150084  * initialize relevant hardware settings.
10606621Sbt150084  */
10616621Sbt150084 static int
10626621Sbt150084 ixgbe_init_rings(ixgbe_t *ixgbe)
10636621Sbt150084 {
10646621Sbt150084 	int i;
10656621Sbt150084 
10666621Sbt150084 	/*
10676621Sbt150084 	 * Allocate buffers for all the rx/tx rings
10686621Sbt150084 	 */
10696621Sbt150084 	if (ixgbe_alloc_dma(ixgbe) != IXGBE_SUCCESS)
10706621Sbt150084 		return (IXGBE_FAILURE);
10716621Sbt150084 
10726621Sbt150084 	/*
10736621Sbt150084 	 * Setup the rx/tx rings
10746621Sbt150084 	 */
10756621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
10766621Sbt150084 
10776621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++)
10786621Sbt150084 		mutex_enter(&ixgbe->rx_rings[i].rx_lock);
10796621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++)
10806621Sbt150084 		mutex_enter(&ixgbe->tx_rings[i].tx_lock);
10816621Sbt150084 
10826621Sbt150084 	ixgbe_setup_rings(ixgbe);
10836621Sbt150084 
10846621Sbt150084 	for (i = ixgbe->num_tx_rings - 1; i >= 0; i--)
10856621Sbt150084 		mutex_exit(&ixgbe->tx_rings[i].tx_lock);
10866621Sbt150084 	for (i = ixgbe->num_rx_rings - 1; i >= 0; i--)
10876621Sbt150084 		mutex_exit(&ixgbe->rx_rings[i].rx_lock);
10886621Sbt150084 
10896621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
10906621Sbt150084 
10916621Sbt150084 	return (IXGBE_SUCCESS);
10926621Sbt150084 }
10936621Sbt150084 
10946621Sbt150084 /*
10956621Sbt150084  * ixgbe_fini_rings - Release DMA resources of all rx/tx rings.
10966621Sbt150084  */
10976621Sbt150084 static void
10986621Sbt150084 ixgbe_fini_rings(ixgbe_t *ixgbe)
10996621Sbt150084 {
11006621Sbt150084 	/*
11016621Sbt150084 	 * Release the DMA/memory resources of rx/tx rings
11026621Sbt150084 	 */
11036621Sbt150084 	ixgbe_free_dma(ixgbe);
11046621Sbt150084 }
11056621Sbt150084 
11066621Sbt150084 /*
11076621Sbt150084  * ixgbe_chip_start - Initialize and start the chipset hardware.
11086621Sbt150084  */
11096621Sbt150084 static int
11106621Sbt150084 ixgbe_chip_start(ixgbe_t *ixgbe)
11116621Sbt150084 {
11126621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
11136621Sbt150084 	int i;
11146621Sbt150084 
11156621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
11166621Sbt150084 
11176621Sbt150084 	/*
11186621Sbt150084 	 * Get the mac address
11196621Sbt150084 	 * This function should handle SPARC case correctly.
11206621Sbt150084 	 */
11216621Sbt150084 	if (!ixgbe_find_mac_address(ixgbe)) {
11226621Sbt150084 		ixgbe_error(ixgbe, "Failed to get the mac address");
11236621Sbt150084 		return (IXGBE_FAILURE);
11246621Sbt150084 	}
11256621Sbt150084 
11266621Sbt150084 	/*
11276621Sbt150084 	 * Validate the mac address
11286621Sbt150084 	 */
11296621Sbt150084 	(void) ixgbe_init_rx_addrs(hw);
11306621Sbt150084 	if (!is_valid_mac_addr(hw->mac.addr)) {
11316621Sbt150084 		ixgbe_error(ixgbe, "Invalid mac address");
11326621Sbt150084 		return (IXGBE_FAILURE);
11336621Sbt150084 	}
11346621Sbt150084 
11356621Sbt150084 	/*
11366621Sbt150084 	 * Configure/Initialize hardware
11376621Sbt150084 	 */
11386621Sbt150084 	if (ixgbe_init_hw(hw) != IXGBE_SUCCESS) {
11396621Sbt150084 		ixgbe_error(ixgbe, "Failed to initialize hardware");
11406621Sbt150084 		return (IXGBE_FAILURE);
11416621Sbt150084 	}
11426621Sbt150084 
11436621Sbt150084 	/*
11446621Sbt150084 	 * Setup adapter interrupt vectors
11456621Sbt150084 	 */
11466621Sbt150084 	ixgbe_setup_adapter_vector(ixgbe);
11476621Sbt150084 
11486621Sbt150084 	/*
11496621Sbt150084 	 * Initialize unicast addresses.
11506621Sbt150084 	 */
11516621Sbt150084 	ixgbe_init_unicst(ixgbe);
11526621Sbt150084 
11536621Sbt150084 	/*
11546621Sbt150084 	 * Setup and initialize the mctable structures.
11556621Sbt150084 	 */
11566621Sbt150084 	ixgbe_setup_multicst(ixgbe);
11576621Sbt150084 
11586621Sbt150084 	/*
11596621Sbt150084 	 * Set interrupt throttling rate
11606621Sbt150084 	 */
11616621Sbt150084 	for (i = 0; i < ixgbe->intr_cnt; i++)
11626621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_EITR(i), ixgbe->intr_throttling[i]);
11636621Sbt150084 
11646621Sbt150084 	/*
11656621Sbt150084 	 * Save the state of the phy
11666621Sbt150084 	 */
11676621Sbt150084 	ixgbe_get_hw_state(ixgbe);
11686621Sbt150084 
11696621Sbt150084 	/*
11706621Sbt150084 	 * Make sure driver has control
11716621Sbt150084 	 */
11726621Sbt150084 	ixgbe_get_driver_control(hw);
11736621Sbt150084 
11746621Sbt150084 	return (IXGBE_SUCCESS);
11756621Sbt150084 }
11766621Sbt150084 
11776621Sbt150084 /*
11786621Sbt150084  * ixgbe_chip_stop - Stop the chipset hardware
11796621Sbt150084  */
11806621Sbt150084 static void
11816621Sbt150084 ixgbe_chip_stop(ixgbe_t *ixgbe)
11826621Sbt150084 {
11836621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
11846621Sbt150084 
11856621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
11866621Sbt150084 
11876621Sbt150084 	/*
11886621Sbt150084 	 * Tell firmware driver is no longer in control
11896621Sbt150084 	 */
11906621Sbt150084 	ixgbe_release_driver_control(hw);
11916621Sbt150084 
11926621Sbt150084 	/*
11936621Sbt150084 	 * Reset the chipset
11946621Sbt150084 	 */
11956621Sbt150084 	(void) ixgbe_reset_hw(hw);
11966621Sbt150084 
11976621Sbt150084 	/*
11986621Sbt150084 	 * Reset PHY
11996621Sbt150084 	 */
12006621Sbt150084 	(void) ixgbe_reset_phy(hw);
12016621Sbt150084 }
12026621Sbt150084 
12036621Sbt150084 /*
12046621Sbt150084  * ixgbe_reset - Reset the chipset and re-start the driver.
12056621Sbt150084  *
12066621Sbt150084  * It involves stopping and re-starting the chipset,
12076621Sbt150084  * and re-configuring the rx/tx rings.
12086621Sbt150084  */
12096621Sbt150084 static int
12106621Sbt150084 ixgbe_reset(ixgbe_t *ixgbe)
12116621Sbt150084 {
12126621Sbt150084 	int i;
12136621Sbt150084 
12146621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
12156621Sbt150084 
12166621Sbt150084 	ASSERT(ixgbe->ixgbe_state & IXGBE_STARTED);
12176621Sbt150084 	ixgbe->ixgbe_state &= ~IXGBE_STARTED;
12186621Sbt150084 
12196621Sbt150084 	/*
12206621Sbt150084 	 * Disable the adapter interrupts to stop any rx/tx activities
12216621Sbt150084 	 * before draining pending data and resetting hardware.
12226621Sbt150084 	 */
12236621Sbt150084 	ixgbe_disable_adapter_interrupts(ixgbe);
12246621Sbt150084 
12256621Sbt150084 	/*
12266621Sbt150084 	 * Drain the pending transmit packets
12276621Sbt150084 	 */
12286621Sbt150084 	(void) ixgbe_tx_drain(ixgbe);
12296621Sbt150084 
12306621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++)
12316621Sbt150084 		mutex_enter(&ixgbe->rx_rings[i].rx_lock);
12326621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++)
12336621Sbt150084 		mutex_enter(&ixgbe->tx_rings[i].tx_lock);
12346621Sbt150084 
12356621Sbt150084 	/*
12366621Sbt150084 	 * Stop the chipset hardware
12376621Sbt150084 	 */
12386621Sbt150084 	ixgbe_chip_stop(ixgbe);
12396621Sbt150084 
12406621Sbt150084 	/*
12416621Sbt150084 	 * Clean the pending tx data/resources
12426621Sbt150084 	 */
12436621Sbt150084 	ixgbe_tx_clean(ixgbe);
12446621Sbt150084 
12456621Sbt150084 	/*
12466621Sbt150084 	 * Start the chipset hardware
12476621Sbt150084 	 */
12486621Sbt150084 	if (ixgbe_chip_start(ixgbe) != IXGBE_SUCCESS) {
12496621Sbt150084 		ixgbe_fm_ereport(ixgbe, DDI_FM_DEVICE_INVAL_STATE);
12506621Sbt150084 		goto reset_failure;
12516621Sbt150084 	}
12526621Sbt150084 
12536621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
12546621Sbt150084 		goto reset_failure;
12556621Sbt150084 	}
12566621Sbt150084 
12576621Sbt150084 	/*
12586621Sbt150084 	 * Setup the rx/tx rings
12596621Sbt150084 	 */
12606621Sbt150084 	ixgbe_setup_rings(ixgbe);
12616621Sbt150084 
12626621Sbt150084 	/*
12636621Sbt150084 	 * Enable adapter interrupts
12646621Sbt150084 	 * The interrupts must be enabled after the driver state is START
12656621Sbt150084 	 */
12666621Sbt150084 	ixgbe_enable_adapter_interrupts(ixgbe);
12676621Sbt150084 
12686621Sbt150084 	for (i = ixgbe->num_tx_rings - 1; i >= 0; i--)
12696621Sbt150084 		mutex_exit(&ixgbe->tx_rings[i].tx_lock);
12706621Sbt150084 	for (i = ixgbe->num_rx_rings - 1; i >= 0; i--)
12716621Sbt150084 		mutex_exit(&ixgbe->rx_rings[i].rx_lock);
12726621Sbt150084 
12736621Sbt150084 	ixgbe->ixgbe_state |= IXGBE_STARTED;
12746621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
12756621Sbt150084 
12766621Sbt150084 	return (IXGBE_SUCCESS);
12776621Sbt150084 
12786621Sbt150084 reset_failure:
12796621Sbt150084 	for (i = ixgbe->num_tx_rings - 1; i >= 0; i--)
12806621Sbt150084 		mutex_exit(&ixgbe->tx_rings[i].tx_lock);
12816621Sbt150084 	for (i = ixgbe->num_rx_rings - 1; i >= 0; i--)
12826621Sbt150084 		mutex_exit(&ixgbe->rx_rings[i].rx_lock);
12836621Sbt150084 
12846621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
12856621Sbt150084 
12866621Sbt150084 	ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_LOST);
12876621Sbt150084 
12886621Sbt150084 	return (IXGBE_FAILURE);
12896621Sbt150084 }
12906621Sbt150084 
12916621Sbt150084 /*
12926621Sbt150084  * ixgbe_tx_clean - Clean the pending transmit packets and DMA resources.
12936621Sbt150084  */
12946621Sbt150084 static void
12956621Sbt150084 ixgbe_tx_clean(ixgbe_t *ixgbe)
12966621Sbt150084 {
12976621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
12986621Sbt150084 	tx_control_block_t *tcb;
12996621Sbt150084 	link_list_t pending_list;
13006621Sbt150084 	uint32_t desc_num;
13016621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
13026621Sbt150084 	int i, j;
13036621Sbt150084 
13046621Sbt150084 	LINK_LIST_INIT(&pending_list);
13056621Sbt150084 
13066621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
13076621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
13086621Sbt150084 
13096621Sbt150084 		mutex_enter(&tx_ring->recycle_lock);
13106621Sbt150084 
13116621Sbt150084 		/*
13126621Sbt150084 		 * Clean the pending tx data - the pending packets in the
13136621Sbt150084 		 * work_list that have no chances to be transmitted again.
13146621Sbt150084 		 *
13156621Sbt150084 		 * We must ensure the chipset is stopped or the link is down
13166621Sbt150084 		 * before cleaning the transmit packets.
13176621Sbt150084 		 */
13186621Sbt150084 		desc_num = 0;
13196621Sbt150084 		for (j = 0; j < tx_ring->ring_size; j++) {
13206621Sbt150084 			tcb = tx_ring->work_list[j];
13216621Sbt150084 			if (tcb != NULL) {
13226621Sbt150084 				desc_num += tcb->desc_num;
13236621Sbt150084 
13246621Sbt150084 				tx_ring->work_list[j] = NULL;
13256621Sbt150084 
13266621Sbt150084 				ixgbe_free_tcb(tcb);
13276621Sbt150084 
13286621Sbt150084 				LIST_PUSH_TAIL(&pending_list, &tcb->link);
13296621Sbt150084 			}
13306621Sbt150084 		}
13316621Sbt150084 
13326621Sbt150084 		if (desc_num > 0) {
13336621Sbt150084 			atomic_add_32(&tx_ring->tbd_free, desc_num);
13346621Sbt150084 			ASSERT(tx_ring->tbd_free == tx_ring->ring_size);
13356621Sbt150084 
13366621Sbt150084 			/*
13376621Sbt150084 			 * Reset the head and tail pointers of the tbd ring;
13386621Sbt150084 			 * Reset the writeback head if it's enable.
13396621Sbt150084 			 */
13406621Sbt150084 			tx_ring->tbd_head = 0;
13416621Sbt150084 			tx_ring->tbd_tail = 0;
13426621Sbt150084 			if (ixgbe->tx_head_wb_enable)
13436621Sbt150084 				*tx_ring->tbd_head_wb = 0;
13446621Sbt150084 
13456621Sbt150084 			IXGBE_WRITE_REG(&ixgbe->hw,
13466621Sbt150084 			    IXGBE_TDH(tx_ring->index), 0);
13476621Sbt150084 			IXGBE_WRITE_REG(&ixgbe->hw,
13486621Sbt150084 			    IXGBE_TDT(tx_ring->index), 0);
13496621Sbt150084 		}
13506621Sbt150084 
13516621Sbt150084 		mutex_exit(&tx_ring->recycle_lock);
13526621Sbt150084 
13536621Sbt150084 		/*
13546621Sbt150084 		 * Add the tx control blocks in the pending list to
13556621Sbt150084 		 * the free list.
13566621Sbt150084 		 */
13576621Sbt150084 		ixgbe_put_free_list(tx_ring, &pending_list);
13586621Sbt150084 	}
13596621Sbt150084 }
13606621Sbt150084 
13616621Sbt150084 /*
13626621Sbt150084  * ixgbe_tx_drain - Drain the tx rings to allow pending packets to be
13636621Sbt150084  * transmitted.
13646621Sbt150084  */
13656621Sbt150084 static boolean_t
13666621Sbt150084 ixgbe_tx_drain(ixgbe_t *ixgbe)
13676621Sbt150084 {
13686621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
13696621Sbt150084 	boolean_t done;
13706621Sbt150084 	int i, j;
13716621Sbt150084 
13726621Sbt150084 	/*
13736621Sbt150084 	 * Wait for a specific time to allow pending tx packets
13746621Sbt150084 	 * to be transmitted.
13756621Sbt150084 	 *
13766621Sbt150084 	 * Check the counter tbd_free to see if transmission is done.
13776621Sbt150084 	 * No lock protection is needed here.
13786621Sbt150084 	 *
13796621Sbt150084 	 * Return B_TRUE if all pending packets have been transmitted;
13806621Sbt150084 	 * Otherwise return B_FALSE;
13816621Sbt150084 	 */
13826621Sbt150084 	for (i = 0; i < TX_DRAIN_TIME; i++) {
13836621Sbt150084 
13846621Sbt150084 		done = B_TRUE;
13856621Sbt150084 		for (j = 0; j < ixgbe->num_tx_rings; j++) {
13866621Sbt150084 			tx_ring = &ixgbe->tx_rings[j];
13876621Sbt150084 			done = done &&
13886621Sbt150084 			    (tx_ring->tbd_free == tx_ring->ring_size);
13896621Sbt150084 		}
13906621Sbt150084 
13916621Sbt150084 		if (done)
13926621Sbt150084 			break;
13936621Sbt150084 
13946621Sbt150084 		msec_delay(1);
13956621Sbt150084 	}
13966621Sbt150084 
13976621Sbt150084 	return (done);
13986621Sbt150084 }
13996621Sbt150084 
14006621Sbt150084 /*
14016621Sbt150084  * ixgbe_rx_drain - Wait for all rx buffers to be released by upper layer.
14026621Sbt150084  */
14036621Sbt150084 static boolean_t
14046621Sbt150084 ixgbe_rx_drain(ixgbe_t *ixgbe)
14056621Sbt150084 {
14066621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
14076621Sbt150084 	boolean_t done;
14086621Sbt150084 	int i, j;
14096621Sbt150084 
14106621Sbt150084 	/*
14116621Sbt150084 	 * Polling the rx free list to check if those rx buffers held by
14126621Sbt150084 	 * the upper layer are released.
14136621Sbt150084 	 *
14146621Sbt150084 	 * Check the counter rcb_free to see if all pending buffers are
14156621Sbt150084 	 * released. No lock protection is needed here.
14166621Sbt150084 	 *
14176621Sbt150084 	 * Return B_TRUE if all pending buffers have been released;
14186621Sbt150084 	 * Otherwise return B_FALSE;
14196621Sbt150084 	 */
14206621Sbt150084 	for (i = 0; i < RX_DRAIN_TIME; i++) {
14216621Sbt150084 
14226621Sbt150084 		done = B_TRUE;
14236621Sbt150084 		for (j = 0; j < ixgbe->num_rx_rings; j++) {
14246621Sbt150084 			rx_ring = &ixgbe->rx_rings[j];
14256621Sbt150084 			done = done &&
14266621Sbt150084 			    (rx_ring->rcb_free == rx_ring->free_list_size);
14276621Sbt150084 		}
14286621Sbt150084 
14296621Sbt150084 		if (done)
14306621Sbt150084 			break;
14316621Sbt150084 
14326621Sbt150084 		msec_delay(1);
14336621Sbt150084 	}
14346621Sbt150084 
14356621Sbt150084 	return (done);
14366621Sbt150084 }
14376621Sbt150084 
14386621Sbt150084 /*
14396621Sbt150084  * ixgbe_start - Start the driver/chipset.
14406621Sbt150084  */
14416621Sbt150084 int
14426621Sbt150084 ixgbe_start(ixgbe_t *ixgbe)
14436621Sbt150084 {
14446621Sbt150084 	int i;
14456621Sbt150084 
14466621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
14476621Sbt150084 
14486621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++)
14496621Sbt150084 		mutex_enter(&ixgbe->rx_rings[i].rx_lock);
14506621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++)
14516621Sbt150084 		mutex_enter(&ixgbe->tx_rings[i].tx_lock);
14526621Sbt150084 
14536621Sbt150084 	/*
14546621Sbt150084 	 * Start the chipset hardware
14556621Sbt150084 	 */
14566621Sbt150084 	if (ixgbe_chip_start(ixgbe) != IXGBE_SUCCESS) {
14576621Sbt150084 		ixgbe_fm_ereport(ixgbe, DDI_FM_DEVICE_INVAL_STATE);
14586621Sbt150084 		goto start_failure;
14596621Sbt150084 	}
14606621Sbt150084 
14616621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
14626621Sbt150084 		goto start_failure;
14636621Sbt150084 	}
14646621Sbt150084 
14656621Sbt150084 	/*
14666621Sbt150084 	 * Setup the rx/tx rings
14676621Sbt150084 	 */
14686621Sbt150084 	ixgbe_setup_rings(ixgbe);
14696621Sbt150084 
14706621Sbt150084 	/*
14716621Sbt150084 	 * Enable adapter interrupts
14726621Sbt150084 	 * The interrupts must be enabled after the driver state is START
14736621Sbt150084 	 */
14746621Sbt150084 	ixgbe_enable_adapter_interrupts(ixgbe);
14756621Sbt150084 
14766621Sbt150084 	for (i = ixgbe->num_tx_rings - 1; i >= 0; i--)
14776621Sbt150084 		mutex_exit(&ixgbe->tx_rings[i].tx_lock);
14786621Sbt150084 	for (i = ixgbe->num_rx_rings - 1; i >= 0; i--)
14796621Sbt150084 		mutex_exit(&ixgbe->rx_rings[i].rx_lock);
14806621Sbt150084 
14816621Sbt150084 	return (IXGBE_SUCCESS);
14826621Sbt150084 
14836621Sbt150084 start_failure:
14846621Sbt150084 	for (i = ixgbe->num_tx_rings - 1; i >= 0; i--)
14856621Sbt150084 		mutex_exit(&ixgbe->tx_rings[i].tx_lock);
14866621Sbt150084 	for (i = ixgbe->num_rx_rings - 1; i >= 0; i--)
14876621Sbt150084 		mutex_exit(&ixgbe->rx_rings[i].rx_lock);
14886621Sbt150084 
14896621Sbt150084 	ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_LOST);
14906621Sbt150084 
14916621Sbt150084 	return (IXGBE_FAILURE);
14926621Sbt150084 }
14936621Sbt150084 
14946621Sbt150084 /*
14956621Sbt150084  * ixgbe_stop - Stop the driver/chipset.
14966621Sbt150084  */
14976621Sbt150084 void
14986621Sbt150084 ixgbe_stop(ixgbe_t *ixgbe)
14996621Sbt150084 {
15006621Sbt150084 	int i;
15016621Sbt150084 
15026621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
15036621Sbt150084 
15046621Sbt150084 	/*
15056621Sbt150084 	 * Disable the adapter interrupts
15066621Sbt150084 	 */
15076621Sbt150084 	ixgbe_disable_adapter_interrupts(ixgbe);
15086621Sbt150084 
15096621Sbt150084 	/*
15106621Sbt150084 	 * Drain the pending tx packets
15116621Sbt150084 	 */
15126621Sbt150084 	(void) ixgbe_tx_drain(ixgbe);
15136621Sbt150084 
15146621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++)
15156621Sbt150084 		mutex_enter(&ixgbe->rx_rings[i].rx_lock);
15166621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++)
15176621Sbt150084 		mutex_enter(&ixgbe->tx_rings[i].tx_lock);
15186621Sbt150084 
15196621Sbt150084 	/*
15206621Sbt150084 	 * Stop the chipset hardware
15216621Sbt150084 	 */
15226621Sbt150084 	ixgbe_chip_stop(ixgbe);
15236621Sbt150084 
15246621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
15256621Sbt150084 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_LOST);
15266621Sbt150084 	}
15276621Sbt150084 
15286621Sbt150084 	/*
15296621Sbt150084 	 * Clean the pending tx data/resources
15306621Sbt150084 	 */
15316621Sbt150084 	ixgbe_tx_clean(ixgbe);
15326621Sbt150084 
15336621Sbt150084 	for (i = ixgbe->num_tx_rings - 1; i >= 0; i--)
15346621Sbt150084 		mutex_exit(&ixgbe->tx_rings[i].tx_lock);
15356621Sbt150084 	for (i = ixgbe->num_rx_rings - 1; i >= 0; i--)
15366621Sbt150084 		mutex_exit(&ixgbe->rx_rings[i].rx_lock);
15376621Sbt150084 }
15386621Sbt150084 
15396621Sbt150084 /*
15406621Sbt150084  * ixgbe_alloc_rings - Allocate memory space for rx/tx rings.
15416621Sbt150084  */
15426621Sbt150084 static int
15436621Sbt150084 ixgbe_alloc_rings(ixgbe_t *ixgbe)
15446621Sbt150084 {
15456621Sbt150084 	/*
15466621Sbt150084 	 * Allocate memory space for rx rings
15476621Sbt150084 	 */
15486621Sbt150084 	ixgbe->rx_rings = kmem_zalloc(
15496621Sbt150084 	    sizeof (ixgbe_rx_ring_t) * ixgbe->num_rx_rings,
15506621Sbt150084 	    KM_NOSLEEP);
15516621Sbt150084 
15526621Sbt150084 	if (ixgbe->rx_rings == NULL) {
15536621Sbt150084 		return (IXGBE_FAILURE);
15546621Sbt150084 	}
15556621Sbt150084 
15566621Sbt150084 	/*
15576621Sbt150084 	 * Allocate memory space for tx rings
15586621Sbt150084 	 */
15596621Sbt150084 	ixgbe->tx_rings = kmem_zalloc(
15606621Sbt150084 	    sizeof (ixgbe_tx_ring_t) * ixgbe->num_tx_rings,
15616621Sbt150084 	    KM_NOSLEEP);
15626621Sbt150084 
15636621Sbt150084 	if (ixgbe->tx_rings == NULL) {
15646621Sbt150084 		kmem_free(ixgbe->rx_rings,
15656621Sbt150084 		    sizeof (ixgbe_rx_ring_t) * ixgbe->num_rx_rings);
15666621Sbt150084 		ixgbe->rx_rings = NULL;
15676621Sbt150084 		return (IXGBE_FAILURE);
15686621Sbt150084 	}
15696621Sbt150084 
15706621Sbt150084 	return (IXGBE_SUCCESS);
15716621Sbt150084 }
15726621Sbt150084 
15736621Sbt150084 /*
15746621Sbt150084  * ixgbe_free_rings - Free the memory space of rx/tx rings.
15756621Sbt150084  */
15766621Sbt150084 static void
15776621Sbt150084 ixgbe_free_rings(ixgbe_t *ixgbe)
15786621Sbt150084 {
15796621Sbt150084 	if (ixgbe->rx_rings != NULL) {
15806621Sbt150084 		kmem_free(ixgbe->rx_rings,
15816621Sbt150084 		    sizeof (ixgbe_rx_ring_t) * ixgbe->num_rx_rings);
15826621Sbt150084 		ixgbe->rx_rings = NULL;
15836621Sbt150084 	}
15846621Sbt150084 
15856621Sbt150084 	if (ixgbe->tx_rings != NULL) {
15866621Sbt150084 		kmem_free(ixgbe->tx_rings,
15876621Sbt150084 		    sizeof (ixgbe_tx_ring_t) * ixgbe->num_tx_rings);
15886621Sbt150084 		ixgbe->tx_rings = NULL;
15896621Sbt150084 	}
15906621Sbt150084 }
15916621Sbt150084 
15926621Sbt150084 /*
15936621Sbt150084  * ixgbe_setup_rings - Setup rx/tx rings.
15946621Sbt150084  */
15956621Sbt150084 static void
15966621Sbt150084 ixgbe_setup_rings(ixgbe_t *ixgbe)
15976621Sbt150084 {
15986621Sbt150084 	/*
15996621Sbt150084 	 * Setup the rx/tx rings, including the following:
16006621Sbt150084 	 *
16016621Sbt150084 	 * 1. Setup the descriptor ring and the control block buffers;
16026621Sbt150084 	 * 2. Initialize necessary registers for receive/transmit;
16036621Sbt150084 	 * 3. Initialize software pointers/parameters for receive/transmit;
16046621Sbt150084 	 */
16056621Sbt150084 	ixgbe_setup_rx(ixgbe);
16066621Sbt150084 
16076621Sbt150084 	ixgbe_setup_tx(ixgbe);
16086621Sbt150084 }
16096621Sbt150084 
16106621Sbt150084 static void
16116621Sbt150084 ixgbe_setup_rx_ring(ixgbe_rx_ring_t *rx_ring)
16126621Sbt150084 {
16136621Sbt150084 	ixgbe_t *ixgbe = rx_ring->ixgbe;
16146621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
16156621Sbt150084 	rx_control_block_t *rcb;
16166621Sbt150084 	union ixgbe_adv_rx_desc	*rbd;
16176621Sbt150084 	uint32_t size;
16186621Sbt150084 	uint32_t buf_low;
16196621Sbt150084 	uint32_t buf_high;
16206621Sbt150084 	uint32_t reg_val;
16216621Sbt150084 	int i;
16226621Sbt150084 
16236621Sbt150084 	ASSERT(mutex_owned(&rx_ring->rx_lock));
16246621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
16256621Sbt150084 
16266621Sbt150084 	for (i = 0; i < ixgbe->rx_ring_size; i++) {
16276621Sbt150084 		rcb = rx_ring->work_list[i];
16286621Sbt150084 		rbd = &rx_ring->rbd_ring[i];
16296621Sbt150084 
16306621Sbt150084 		rbd->read.pkt_addr = rcb->rx_buf.dma_address;
16316621Sbt150084 		rbd->read.hdr_addr = NULL;
16326621Sbt150084 	}
16336621Sbt150084 
16346621Sbt150084 	/*
16356621Sbt150084 	 * Initialize the length register
16366621Sbt150084 	 */
16376621Sbt150084 	size = rx_ring->ring_size * sizeof (union ixgbe_adv_rx_desc);
16386621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RDLEN(rx_ring->index), size);
16396621Sbt150084 
16406621Sbt150084 	/*
16416621Sbt150084 	 * Initialize the base address registers
16426621Sbt150084 	 */
16436621Sbt150084 	buf_low = (uint32_t)rx_ring->rbd_area.dma_address;
16446621Sbt150084 	buf_high = (uint32_t)(rx_ring->rbd_area.dma_address >> 32);
16456621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RDBAH(rx_ring->index), buf_high);
16466621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RDBAL(rx_ring->index), buf_low);
16476621Sbt150084 
16486621Sbt150084 	/*
16496621Sbt150084 	 * Setup head & tail pointers
16506621Sbt150084 	 */
16516621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RDT(rx_ring->index), rx_ring->ring_size - 1);
16526621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RDH(rx_ring->index), 0);
16536621Sbt150084 
16546621Sbt150084 	rx_ring->rbd_next = 0;
16556621Sbt150084 
16566621Sbt150084 	/*
16576621Sbt150084 	 * Note: Considering the case that the chipset is being reset
16586621Sbt150084 	 * and there are still some buffers held by the upper layer,
16596621Sbt150084 	 * we should not reset the values of rcb_head, rcb_tail and
16606621Sbt150084 	 * rcb_free if the state is not IXGBE_UNKNOWN.
16616621Sbt150084 	 */
16626621Sbt150084 	if (ixgbe->ixgbe_state == IXGBE_UNKNOWN) {
16636621Sbt150084 		rx_ring->rcb_head = 0;
16646621Sbt150084 		rx_ring->rcb_tail = 0;
16656621Sbt150084 		rx_ring->rcb_free = rx_ring->free_list_size;
16666621Sbt150084 	}
16676621Sbt150084 
16686621Sbt150084 	/*
16696621Sbt150084 	 * Setup the Receive Descriptor Control Register (RXDCTL)
16706621Sbt150084 	 * PTHRESH=32 descriptors (half the internal cache)
16716621Sbt150084 	 * HTHRESH=0 descriptors (to minimize latency on fetch)
16726621Sbt150084 	 * WTHRESH defaults to 1 (writeback each descriptor)
16736621Sbt150084 	 */
16746621Sbt150084 	reg_val = IXGBE_READ_REG(hw, IXGBE_RXDCTL(rx_ring->index));
16756621Sbt150084 	reg_val |= IXGBE_RXDCTL_ENABLE;	/* enable queue */
16766621Sbt150084 	reg_val |= 0x0020;		/* pthresh */
16776621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(rx_ring->index), reg_val);
16786621Sbt150084 
16796621Sbt150084 	/*
16806621Sbt150084 	 * Setup the Split and Replication Receive Control Register.
16816621Sbt150084 	 * Set the rx buffer size and the advanced descriptor type.
16826621Sbt150084 	 */
16836621Sbt150084 	reg_val = (ixgbe->rx_buf_size >> IXGBE_SRRCTL_BSIZEPKT_SHIFT) |
16846621Sbt150084 	    IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
16856621Sbt150084 
16866621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(rx_ring->index), reg_val);
16876621Sbt150084 }
16886621Sbt150084 
16896621Sbt150084 static void
16906621Sbt150084 ixgbe_setup_rx(ixgbe_t *ixgbe)
16916621Sbt150084 {
16926621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
16936621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
16946621Sbt150084 	uint32_t reg_val;
16956621Sbt150084 	int i;
16966621Sbt150084 
16976621Sbt150084 	/*
16986621Sbt150084 	 * Set filter control in FCTRL to accept broadcast packets and do
16996621Sbt150084 	 * not pass pause frames to host.  Flow control settings are already
17006621Sbt150084 	 * in this register, so preserve them.
17016621Sbt150084 	 */
17026621Sbt150084 	reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL);
17036621Sbt150084 	reg_val |= IXGBE_FCTRL_BAM;	/* broadcast accept mode */
17046621Sbt150084 	reg_val |= IXGBE_FCTRL_DPF;	/* discard pause frames */
17056621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg_val);
17066621Sbt150084 
17076621Sbt150084 	/*
17086621Sbt150084 	 * Enable the receive unit.  This must be done after filter
17096621Sbt150084 	 * control is set in FCTRL.
17106621Sbt150084 	 */
17116621Sbt150084 	reg_val = (IXGBE_RXCTRL_RXEN	/* Enable Receive Unit */
17126621Sbt150084 	    | IXGBE_RXCTRL_DMBYPS);	/* descriptor monitor bypass */
17136621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg_val);
17146621Sbt150084 
17156621Sbt150084 	/*
17166621Sbt150084 	 * ixgbe_setup_rx_ring must be called after configuring RXCTRL
17176621Sbt150084 	 */
17186621Sbt150084 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
17196621Sbt150084 		rx_ring = &ixgbe->rx_rings[i];
17206621Sbt150084 		ixgbe_setup_rx_ring(rx_ring);
17216621Sbt150084 	}
17226621Sbt150084 
17236621Sbt150084 	/*
17246621Sbt150084 	 * The Max Frame Size in MHADD will be internally increased by four
17256621Sbt150084 	 * bytes if the packet has a VLAN field, so includes MTU, ethernet
17266621Sbt150084 	 * header and frame check sequence.
17276621Sbt150084 	 */
17286621Sbt150084 	reg_val = (ixgbe->default_mtu + sizeof (struct ether_header)
17296621Sbt150084 	    + ETHERFCSL) << IXGBE_MHADD_MFS_SHIFT;
17306621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_MHADD, reg_val);
17316621Sbt150084 
17326621Sbt150084 	/*
17336621Sbt150084 	 * Setup Jumbo Frame enable bit
17346621Sbt150084 	 */
17356621Sbt150084 	if (ixgbe->default_mtu > ETHERMTU) {
17366621Sbt150084 		reg_val = IXGBE_READ_REG(hw, IXGBE_HLREG0);
17376621Sbt150084 		reg_val |= IXGBE_HLREG0_JUMBOEN;
17386621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg_val);
17396621Sbt150084 	}
17406621Sbt150084 
17416621Sbt150084 	/*
17426621Sbt150084 	 * Hardware checksum settings
17436621Sbt150084 	 */
17446621Sbt150084 	if (ixgbe->rx_hcksum_enable) {
17456621Sbt150084 		reg_val = IXGBE_RXCSUM_IPPCSE;	/* IP checksum */
17466621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, reg_val);
17476621Sbt150084 	}
17486621Sbt150084 
17496621Sbt150084 	/*
17506621Sbt150084 	 * Setup RSS for multiple receive queues
17516621Sbt150084 	 */
17526621Sbt150084 	if (ixgbe->num_rx_rings > 1)
17536621Sbt150084 		ixgbe_setup_rss(ixgbe);
17546621Sbt150084 }
17556621Sbt150084 
17566621Sbt150084 static void
17576621Sbt150084 ixgbe_setup_tx_ring(ixgbe_tx_ring_t *tx_ring)
17586621Sbt150084 {
17596621Sbt150084 	ixgbe_t *ixgbe = tx_ring->ixgbe;
17606621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
17616621Sbt150084 	uint32_t size;
17626621Sbt150084 	uint32_t buf_low;
17636621Sbt150084 	uint32_t buf_high;
17646621Sbt150084 	uint32_t reg_val;
17656621Sbt150084 
17666621Sbt150084 	ASSERT(mutex_owned(&tx_ring->tx_lock));
17676621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
17686621Sbt150084 
17696621Sbt150084 	/*
17706621Sbt150084 	 * Initialize the length register
17716621Sbt150084 	 */
17726621Sbt150084 	size = tx_ring->ring_size * sizeof (union ixgbe_adv_tx_desc);
17736621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_TDLEN(tx_ring->index), size);
17746621Sbt150084 
17756621Sbt150084 	/*
17766621Sbt150084 	 * Initialize the base address registers
17776621Sbt150084 	 */
17786621Sbt150084 	buf_low = (uint32_t)tx_ring->tbd_area.dma_address;
17796621Sbt150084 	buf_high = (uint32_t)(tx_ring->tbd_area.dma_address >> 32);
17806621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_TDBAL(tx_ring->index), buf_low);
17816621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_TDBAH(tx_ring->index), buf_high);
17826621Sbt150084 
17836621Sbt150084 	/*
17846621Sbt150084 	 * setup TXDCTL(tx_ring->index)
17856621Sbt150084 	 */
17866621Sbt150084 	reg_val = IXGBE_TXDCTL_ENABLE;
17876621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->index), reg_val);
17886621Sbt150084 
17896621Sbt150084 	/*
17906621Sbt150084 	 * Setup head & tail pointers
17916621Sbt150084 	 */
17926621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_TDH(tx_ring->index), 0);
17936621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_TDT(tx_ring->index), 0);
17946621Sbt150084 
17956621Sbt150084 	/*
17966621Sbt150084 	 * Setup head write-back
17976621Sbt150084 	 */
17986621Sbt150084 	if (ixgbe->tx_head_wb_enable) {
17996621Sbt150084 		/*
18006621Sbt150084 		 * The memory of the head write-back is allocated using
18016621Sbt150084 		 * the extra tbd beyond the tail of the tbd ring.
18026621Sbt150084 		 */
18036621Sbt150084 		tx_ring->tbd_head_wb = (uint32_t *)
18046621Sbt150084 		    ((uintptr_t)tx_ring->tbd_area.address + size);
18056621Sbt150084 		*tx_ring->tbd_head_wb = 0;
18066621Sbt150084 
18076621Sbt150084 		buf_low = (uint32_t)
18086621Sbt150084 		    (tx_ring->tbd_area.dma_address + size);
18096621Sbt150084 		buf_high = (uint32_t)
18106621Sbt150084 		    ((tx_ring->tbd_area.dma_address + size) >> 32);
18116621Sbt150084 
18126621Sbt150084 		/* Set the head write-back enable bit */
18136621Sbt150084 		buf_low |= IXGBE_TDWBAL_HEAD_WB_ENABLE;
18146621Sbt150084 
18156621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(tx_ring->index), buf_low);
18166621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(tx_ring->index), buf_high);
18176621Sbt150084 
18186621Sbt150084 		/*
18196621Sbt150084 		 * Turn off relaxed ordering for head write back or it will
18206621Sbt150084 		 * cause problems with the tx recycling
18216621Sbt150084 		 */
18226621Sbt150084 		reg_val = IXGBE_READ_REG(hw,
18236621Sbt150084 		    IXGBE_DCA_TXCTRL(tx_ring->index));
18246621Sbt150084 		reg_val &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
18256621Sbt150084 		IXGBE_WRITE_REG(hw,
18266621Sbt150084 		    IXGBE_DCA_TXCTRL(tx_ring->index), reg_val);
18276621Sbt150084 	} else {
18286621Sbt150084 		tx_ring->tbd_head_wb = NULL;
18296621Sbt150084 	}
18306621Sbt150084 
18316621Sbt150084 	tx_ring->tbd_head = 0;
18326621Sbt150084 	tx_ring->tbd_tail = 0;
18336621Sbt150084 	tx_ring->tbd_free = tx_ring->ring_size;
18346621Sbt150084 
18356621Sbt150084 	/*
18366621Sbt150084 	 * Note: Considering the case that the chipset is being reset,
18376621Sbt150084 	 * and there are still some tcb in the pending list,
18386621Sbt150084 	 * we should not reset the values of tcb_head, tcb_tail and
18396621Sbt150084 	 * tcb_free if the state is not IXGBE_UNKNOWN.
18406621Sbt150084 	 */
18416621Sbt150084 	if (ixgbe->ixgbe_state == IXGBE_UNKNOWN) {
18426621Sbt150084 		tx_ring->tcb_head = 0;
18436621Sbt150084 		tx_ring->tcb_tail = 0;
18446621Sbt150084 		tx_ring->tcb_free = tx_ring->free_list_size;
18456621Sbt150084 	}
18466621Sbt150084 
18476621Sbt150084 	/*
18486621Sbt150084 	 * Initialize hardware checksum offload settings
18496621Sbt150084 	 */
1850*7167Sgg161487 	tx_ring->tx_context.hcksum_flags = 0;
1851*7167Sgg161487 	tx_ring->tx_context.ip_hdr_len = 0;
1852*7167Sgg161487 	tx_ring->tx_context.mac_hdr_len = 0;
1853*7167Sgg161487 	tx_ring->tx_context.l4_proto = 0;
18546621Sbt150084 }
18556621Sbt150084 
18566621Sbt150084 static void
18576621Sbt150084 ixgbe_setup_tx(ixgbe_t *ixgbe)
18586621Sbt150084 {
1859*7167Sgg161487 	struct ixgbe_hw *hw = &ixgbe->hw;
18606621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
1861*7167Sgg161487 	uint32_t reg_val;
18626621Sbt150084 	int i;
18636621Sbt150084 
18646621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
18656621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
18666621Sbt150084 		ixgbe_setup_tx_ring(tx_ring);
18676621Sbt150084 	}
1868*7167Sgg161487 
1869*7167Sgg161487 	/*
1870*7167Sgg161487 	 * Enable CRC appending and TX padding (for short tx frames)
1871*7167Sgg161487 	 */
1872*7167Sgg161487 	reg_val = IXGBE_READ_REG(hw, IXGBE_HLREG0);
1873*7167Sgg161487 	reg_val |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_TXPADEN;
1874*7167Sgg161487 	IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg_val);
18756621Sbt150084 }
18766621Sbt150084 
18776621Sbt150084 /*
18786621Sbt150084  * ixgbe_setup_rss - Setup receive-side scaling feature.
18796621Sbt150084  */
18806621Sbt150084 static void
18816621Sbt150084 ixgbe_setup_rss(ixgbe_t *ixgbe)
18826621Sbt150084 {
18836621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
1884*7167Sgg161487 	uint32_t i, mrqc, rxcsum;
18856621Sbt150084 	uint32_t random;
18866621Sbt150084 	uint32_t reta;
18876621Sbt150084 
18886621Sbt150084 	/*
18896621Sbt150084 	 * Fill out redirection table
18906621Sbt150084 	 */
18916621Sbt150084 	reta = 0;
18926621Sbt150084 	for (i = 0; i < 128; i++) {
1893*7167Sgg161487 		reta = (reta << 8) | (i % ixgbe->num_rx_rings);
1894*7167Sgg161487 		if ((i & 3) == 3)
18956621Sbt150084 			IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta);
18966621Sbt150084 	}
18976621Sbt150084 
18986621Sbt150084 	/*
18996621Sbt150084 	 * Fill out hash function seeds with a random constant
19006621Sbt150084 	 */
19016621Sbt150084 	for (i = 0; i < 10; i++) {
19026621Sbt150084 		(void) random_get_pseudo_bytes((uint8_t *)&random,
19036621Sbt150084 		    sizeof (uint32_t));
19046621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), random);
19056621Sbt150084 	}
19066621Sbt150084 
19076621Sbt150084 	/*
1908*7167Sgg161487 	 * Enable RSS & perform hash on these packet types
19096621Sbt150084 	 */
19106621Sbt150084 	mrqc = IXGBE_MRQC_RSSEN |
19116621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV4 |
19126621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV4_TCP |
19136621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV4_UDP |
19146621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV6_EX_TCP |
19156621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV6_EX |
19166621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV6 |
19176621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV6_TCP |
19186621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV6_UDP |
19196621Sbt150084 	    IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP;
19206621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc);
19216621Sbt150084 
19226621Sbt150084 	/*
19236621Sbt150084 	 * Disable Packet Checksum to enable RSS for multiple receive queues.
19246621Sbt150084 	 * It is an adapter hardware limitation that Packet Checksum is
19256621Sbt150084 	 * mutually exclusive with RSS.
19266621Sbt150084 	 */
19276621Sbt150084 	rxcsum = IXGBE_READ_REG(hw, IXGBE_RXCSUM);
19286621Sbt150084 	rxcsum |= IXGBE_RXCSUM_PCSD;
19296621Sbt150084 	rxcsum &= ~IXGBE_RXCSUM_IPPCSE;
19306621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
19316621Sbt150084 }
19326621Sbt150084 
19336621Sbt150084 /*
19346621Sbt150084  * ixgbe_init_unicst - Initialize the unicast addresses.
19356621Sbt150084  */
19366621Sbt150084 static void
19376621Sbt150084 ixgbe_init_unicst(ixgbe_t *ixgbe)
19386621Sbt150084 {
19396621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
19406621Sbt150084 	int slot;
19416621Sbt150084 	/*
19426621Sbt150084 	 * Here we should consider two situations:
19436621Sbt150084 	 *
19446621Sbt150084 	 * 1. Chipset is initialized the first time
19456621Sbt150084 	 *    Initialize the multiple unicast addresses, and
19466621Sbt150084 	 *    save the default mac address.
19476621Sbt150084 	 *
19486621Sbt150084 	 * 2. Chipset is reset
19496621Sbt150084 	 *    Recover the multiple unicast addresses from the
19506621Sbt150084 	 *    software data structure to the RAR registers.
19516621Sbt150084 	 */
19526621Sbt150084 	if (!ixgbe->unicst_init) {
19536621Sbt150084 		/*
19546621Sbt150084 		 * Initialize the multiple unicast addresses
19556621Sbt150084 		 */
19566621Sbt150084 		ixgbe->unicst_total = MAX_NUM_UNICAST_ADDRESSES;
19576621Sbt150084 
19586621Sbt150084 		ixgbe->unicst_avail = ixgbe->unicst_total - 1;
19596621Sbt150084 
19606621Sbt150084 		bcopy(hw->mac.addr, ixgbe->unicst_addr[0].mac.addr,
19616621Sbt150084 		    ETHERADDRL);
19626621Sbt150084 		ixgbe->unicst_addr[0].mac.set = 1;
19636621Sbt150084 
19646621Sbt150084 		for (slot = 1; slot < ixgbe->unicst_total; slot++)
19656621Sbt150084 			ixgbe->unicst_addr[slot].mac.set = 0;
19666621Sbt150084 
19676621Sbt150084 		ixgbe->unicst_init = B_TRUE;
19686621Sbt150084 	} else {
19696621Sbt150084 		/*
19706621Sbt150084 		 * Recover the default mac address
19716621Sbt150084 		 */
19726621Sbt150084 		bcopy(ixgbe->unicst_addr[0].mac.addr, hw->mac.addr,
19736621Sbt150084 		    ETHERADDRL);
19746621Sbt150084 
19756621Sbt150084 		/* Re-configure the RAR registers */
19766621Sbt150084 		for (slot = 1; slot < ixgbe->unicst_total; slot++)
19776621Sbt150084 			(void) ixgbe_set_rar(hw, slot,
19786621Sbt150084 			    ixgbe->unicst_addr[slot].mac.addr, NULL, NULL);
19796621Sbt150084 	}
19806621Sbt150084 }
19816621Sbt150084 /*
19826621Sbt150084  * ixgbe_unicst_set - Set the unicast address to the specified slot.
19836621Sbt150084  */
19846621Sbt150084 int
19856621Sbt150084 ixgbe_unicst_set(ixgbe_t *ixgbe, const uint8_t *mac_addr,
19866621Sbt150084     mac_addr_slot_t slot)
19876621Sbt150084 {
19886621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
19896621Sbt150084 
19906621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
19916621Sbt150084 
19926621Sbt150084 	/*
19936621Sbt150084 	 * Save the unicast address in the software data structure
19946621Sbt150084 	 */
19956621Sbt150084 	bcopy(mac_addr, ixgbe->unicst_addr[slot].mac.addr, ETHERADDRL);
19966621Sbt150084 
19976621Sbt150084 	/*
19986621Sbt150084 	 * Set the unicast address to the RAR register
19996621Sbt150084 	 */
20006621Sbt150084 	(void) ixgbe_set_rar(hw, slot, (uint8_t *)mac_addr, NULL, NULL);
20016621Sbt150084 
20026621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
20036621Sbt150084 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_DEGRADED);
20046621Sbt150084 		return (EIO);
20056621Sbt150084 	}
20066621Sbt150084 
20076621Sbt150084 	return (0);
20086621Sbt150084 }
20096621Sbt150084 
20106621Sbt150084 /*
20116621Sbt150084  * ixgbe_multicst_add - Add a multicst address.
20126621Sbt150084  */
20136621Sbt150084 int
20146621Sbt150084 ixgbe_multicst_add(ixgbe_t *ixgbe, const uint8_t *multiaddr)
20156621Sbt150084 {
20166621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
20176621Sbt150084 
20186621Sbt150084 	if ((multiaddr[0] & 01) == 0) {
20196621Sbt150084 		return (EINVAL);
20206621Sbt150084 	}
20216621Sbt150084 
20226621Sbt150084 	if (ixgbe->mcast_count >= MAX_NUM_MULTICAST_ADDRESSES) {
20236621Sbt150084 		return (ENOENT);
20246621Sbt150084 	}
20256621Sbt150084 
20266621Sbt150084 	bcopy(multiaddr,
20276621Sbt150084 	    &ixgbe->mcast_table[ixgbe->mcast_count], ETHERADDRL);
20286621Sbt150084 	ixgbe->mcast_count++;
20296621Sbt150084 
20306621Sbt150084 	/*
20316621Sbt150084 	 * Update the multicast table in the hardware
20326621Sbt150084 	 */
20336621Sbt150084 	ixgbe_setup_multicst(ixgbe);
20346621Sbt150084 
20356621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
20366621Sbt150084 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_DEGRADED);
20376621Sbt150084 		return (EIO);
20386621Sbt150084 	}
20396621Sbt150084 
20406621Sbt150084 	return (0);
20416621Sbt150084 }
20426621Sbt150084 
20436621Sbt150084 /*
20446621Sbt150084  * ixgbe_multicst_remove - Remove a multicst address.
20456621Sbt150084  */
20466621Sbt150084 int
20476621Sbt150084 ixgbe_multicst_remove(ixgbe_t *ixgbe, const uint8_t *multiaddr)
20486621Sbt150084 {
20496621Sbt150084 	int i;
20506621Sbt150084 
20516621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
20526621Sbt150084 
20536621Sbt150084 	for (i = 0; i < ixgbe->mcast_count; i++) {
20546621Sbt150084 		if (bcmp(multiaddr, &ixgbe->mcast_table[i],
20556621Sbt150084 		    ETHERADDRL) == 0) {
20566621Sbt150084 			for (i++; i < ixgbe->mcast_count; i++) {
20576621Sbt150084 				ixgbe->mcast_table[i - 1] =
20586621Sbt150084 				    ixgbe->mcast_table[i];
20596621Sbt150084 			}
20606621Sbt150084 			ixgbe->mcast_count--;
20616621Sbt150084 			break;
20626621Sbt150084 		}
20636621Sbt150084 	}
20646621Sbt150084 
20656621Sbt150084 	/*
20666621Sbt150084 	 * Update the multicast table in the hardware
20676621Sbt150084 	 */
20686621Sbt150084 	ixgbe_setup_multicst(ixgbe);
20696621Sbt150084 
20706621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
20716621Sbt150084 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_DEGRADED);
20726621Sbt150084 		return (EIO);
20736621Sbt150084 	}
20746621Sbt150084 
20756621Sbt150084 	return (0);
20766621Sbt150084 }
20776621Sbt150084 
20786621Sbt150084 /*
20796621Sbt150084  * ixgbe_setup_multicast - Setup multicast data structures.
20806621Sbt150084  *
20816621Sbt150084  * This routine initializes all of the multicast related structures
20826621Sbt150084  * and save them in the hardware registers.
20836621Sbt150084  */
20846621Sbt150084 static void
20856621Sbt150084 ixgbe_setup_multicst(ixgbe_t *ixgbe)
20866621Sbt150084 {
20876621Sbt150084 	uint8_t *mc_addr_list;
20886621Sbt150084 	uint32_t mc_addr_count;
20896621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
20906621Sbt150084 
20916621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
20926621Sbt150084 
20936621Sbt150084 	ASSERT(ixgbe->mcast_count <= MAX_NUM_MULTICAST_ADDRESSES);
20946621Sbt150084 
20956621Sbt150084 	mc_addr_list = (uint8_t *)ixgbe->mcast_table;
20966621Sbt150084 	mc_addr_count = ixgbe->mcast_count;
20976621Sbt150084 
20986621Sbt150084 	/*
20996621Sbt150084 	 * Update the multicast addresses to the MTA registers
21006621Sbt150084 	 */
21016621Sbt150084 	(void) ixgbe_update_mc_addr_list(hw, mc_addr_list, mc_addr_count,
21026621Sbt150084 	    ixgbe_mc_table_itr);
21036621Sbt150084 }
21046621Sbt150084 
21056621Sbt150084 /*
21066621Sbt150084  * ixgbe_get_conf - Get driver configurations set in driver.conf.
21076621Sbt150084  *
21086621Sbt150084  * This routine gets user-configured values out of the configuration
21096621Sbt150084  * file ixgbe.conf.
21106621Sbt150084  *
21116621Sbt150084  * For each configurable value, there is a minimum, a maximum, and a
21126621Sbt150084  * default.
21136621Sbt150084  * If user does not configure a value, use the default.
21146621Sbt150084  * If user configures below the minimum, use the minumum.
21156621Sbt150084  * If user configures above the maximum, use the maxumum.
21166621Sbt150084  */
21176621Sbt150084 static void
21186621Sbt150084 ixgbe_get_conf(ixgbe_t *ixgbe)
21196621Sbt150084 {
21206621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
21216621Sbt150084 	uint32_t flow_control;
21226621Sbt150084 
21236621Sbt150084 	/*
21246621Sbt150084 	 * ixgbe driver supports the following user configurations:
21256621Sbt150084 	 *
21266621Sbt150084 	 * Jumbo frame configuration:
21276621Sbt150084 	 *    default_mtu
21286621Sbt150084 	 *
21296621Sbt150084 	 * Ethernet flow control configuration:
21306621Sbt150084 	 *    flow_control
21316621Sbt150084 	 *
21326621Sbt150084 	 * Multiple rings configurations:
21336621Sbt150084 	 *    tx_queue_number
21346621Sbt150084 	 *    tx_ring_size
21356621Sbt150084 	 *    rx_queue_number
21366621Sbt150084 	 *    rx_ring_size
21376621Sbt150084 	 *
21386621Sbt150084 	 * Call ixgbe_get_prop() to get the value for a specific
21396621Sbt150084 	 * configuration parameter.
21406621Sbt150084 	 */
21416621Sbt150084 
21426621Sbt150084 	/*
21436621Sbt150084 	 * Jumbo frame configuration - max_frame_size controls host buffer
21446621Sbt150084 	 * allocation, so includes MTU, ethernet header, vlan tag and
21456621Sbt150084 	 * frame check sequence.
21466621Sbt150084 	 */
21476621Sbt150084 	ixgbe->default_mtu = ixgbe_get_prop(ixgbe, PROP_DEFAULT_MTU,
21486621Sbt150084 	    MIN_MTU, MAX_MTU, DEFAULT_MTU);
21496621Sbt150084 
21506621Sbt150084 	ixgbe->max_frame_size = ixgbe->default_mtu +
21516621Sbt150084 	    sizeof (struct ether_vlan_header) + ETHERFCSL;
21526621Sbt150084 
21536621Sbt150084 	/*
21546621Sbt150084 	 * Ethernet flow control configuration
21556621Sbt150084 	 */
21566621Sbt150084 	flow_control = ixgbe_get_prop(ixgbe, PROP_FLOW_CONTROL,
21576621Sbt150084 	    ixgbe_fc_none, 3, ixgbe_fc_full);
21586621Sbt150084 	if (flow_control == 3)
21596621Sbt150084 		flow_control = ixgbe_fc_default;
21606621Sbt150084 
21616621Sbt150084 	hw->fc.type = flow_control;
21626621Sbt150084 
21636621Sbt150084 	/*
21646621Sbt150084 	 * Multiple rings configurations
21656621Sbt150084 	 */
21666621Sbt150084 	ixgbe->num_tx_rings = ixgbe_get_prop(ixgbe, PROP_TX_QUEUE_NUM,
21676621Sbt150084 	    MIN_TX_QUEUE_NUM, MAX_TX_QUEUE_NUM, DEFAULT_TX_QUEUE_NUM);
21686621Sbt150084 	ixgbe->tx_ring_size = ixgbe_get_prop(ixgbe, PROP_TX_RING_SIZE,
21696621Sbt150084 	    MIN_TX_RING_SIZE, MAX_TX_RING_SIZE, DEFAULT_TX_RING_SIZE);
21706621Sbt150084 
21716621Sbt150084 	ixgbe->num_rx_rings = ixgbe_get_prop(ixgbe, PROP_RX_QUEUE_NUM,
21726621Sbt150084 	    MIN_RX_QUEUE_NUM, MAX_RX_QUEUE_NUM, DEFAULT_RX_QUEUE_NUM);
21736621Sbt150084 	ixgbe->rx_ring_size = ixgbe_get_prop(ixgbe, PROP_RX_RING_SIZE,
21746621Sbt150084 	    MIN_RX_RING_SIZE, MAX_RX_RING_SIZE, DEFAULT_RX_RING_SIZE);
21756621Sbt150084 
21766621Sbt150084 	/*
21776621Sbt150084 	 * Tunable used to force an interrupt type. The only use is
21786621Sbt150084 	 * for testing of the lesser interrupt types.
21796621Sbt150084 	 * 0 = don't force interrupt type
21806621Sbt150084 	 * 1 = force interrupt type MSIX
21816621Sbt150084 	 * 2 = force interrupt type MSI
21826621Sbt150084 	 * 3 = force interrupt type Legacy
21836621Sbt150084 	 */
21846621Sbt150084 	ixgbe->intr_force = ixgbe_get_prop(ixgbe, PROP_INTR_FORCE,
21856621Sbt150084 	    IXGBE_INTR_NONE, IXGBE_INTR_LEGACY, IXGBE_INTR_NONE);
21866621Sbt150084 	ixgbe_log(ixgbe, "interrupt force: %d\n", ixgbe->intr_force);
21876621Sbt150084 
21886621Sbt150084 	ixgbe->tx_hcksum_enable = ixgbe_get_prop(ixgbe, PROP_TX_HCKSUM_ENABLE,
2189*7167Sgg161487 	    0, 1, DEFAULT_TX_HCKSUM_ENABLE);
21906621Sbt150084 	ixgbe->rx_hcksum_enable = ixgbe_get_prop(ixgbe, PROP_RX_HCKSUM_ENABLE,
2191*7167Sgg161487 	    0, 1, DEFAULT_RX_HCKSUM_ENABLE);
21926621Sbt150084 	ixgbe->lso_enable = ixgbe_get_prop(ixgbe, PROP_LSO_ENABLE,
2193*7167Sgg161487 	    0, 1, DEFAULT_LSO_ENABLE);
21946621Sbt150084 	ixgbe->tx_head_wb_enable = ixgbe_get_prop(ixgbe, PROP_TX_HEAD_WB_ENABLE,
2195*7167Sgg161487 	    0, 1, DEFAULT_TX_HEAD_WB_ENABLE);
2196*7167Sgg161487 
2197*7167Sgg161487 	/*
2198*7167Sgg161487 	 * ixgbe LSO needs the tx h/w checksum support.
2199*7167Sgg161487 	 * LSO will be disabled if tx h/w checksum is not
2200*7167Sgg161487 	 * enabled.
2201*7167Sgg161487 	 */
2202*7167Sgg161487 	if (ixgbe->tx_hcksum_enable == B_FALSE) {
2203*7167Sgg161487 		ixgbe->lso_enable = B_FALSE;
2204*7167Sgg161487 	}
22056621Sbt150084 
22066621Sbt150084 	ixgbe->tx_copy_thresh = ixgbe_get_prop(ixgbe, PROP_TX_COPY_THRESHOLD,
22076621Sbt150084 	    MIN_TX_COPY_THRESHOLD, MAX_TX_COPY_THRESHOLD,
22086621Sbt150084 	    DEFAULT_TX_COPY_THRESHOLD);
22096621Sbt150084 	ixgbe->tx_recycle_thresh = ixgbe_get_prop(ixgbe,
22106621Sbt150084 	    PROP_TX_RECYCLE_THRESHOLD, MIN_TX_RECYCLE_THRESHOLD,
22116621Sbt150084 	    MAX_TX_RECYCLE_THRESHOLD, DEFAULT_TX_RECYCLE_THRESHOLD);
22126621Sbt150084 	ixgbe->tx_overload_thresh = ixgbe_get_prop(ixgbe,
22136621Sbt150084 	    PROP_TX_OVERLOAD_THRESHOLD, MIN_TX_OVERLOAD_THRESHOLD,
22146621Sbt150084 	    MAX_TX_OVERLOAD_THRESHOLD, DEFAULT_TX_OVERLOAD_THRESHOLD);
22156621Sbt150084 	ixgbe->tx_resched_thresh = ixgbe_get_prop(ixgbe,
22166621Sbt150084 	    PROP_TX_RESCHED_THRESHOLD, MIN_TX_RESCHED_THRESHOLD,
22176621Sbt150084 	    MAX_TX_RESCHED_THRESHOLD, DEFAULT_TX_RESCHED_THRESHOLD);
22186621Sbt150084 
22196621Sbt150084 	ixgbe->rx_copy_thresh = ixgbe_get_prop(ixgbe, PROP_RX_COPY_THRESHOLD,
22206621Sbt150084 	    MIN_RX_COPY_THRESHOLD, MAX_RX_COPY_THRESHOLD,
22216621Sbt150084 	    DEFAULT_RX_COPY_THRESHOLD);
22226621Sbt150084 	ixgbe->rx_limit_per_intr = ixgbe_get_prop(ixgbe, PROP_RX_LIMIT_PER_INTR,
22236621Sbt150084 	    MIN_RX_LIMIT_PER_INTR, MAX_RX_LIMIT_PER_INTR,
22246621Sbt150084 	    DEFAULT_RX_LIMIT_PER_INTR);
22256621Sbt150084 
22266621Sbt150084 	ixgbe->intr_throttling[0] = ixgbe_get_prop(ixgbe, PROP_INTR_THROTTLING,
22276621Sbt150084 	    MIN_INTR_THROTTLING, MAX_INTR_THROTTLING,
22286621Sbt150084 	    DEFAULT_INTR_THROTTLING);
22296621Sbt150084 }
22306621Sbt150084 
22316621Sbt150084 /*
22326621Sbt150084  * ixgbe_get_prop - Get a property value out of the configuration file
22336621Sbt150084  * ixgbe.conf.
22346621Sbt150084  *
22356621Sbt150084  * Caller provides the name of the property, a default value, a minimum
22366621Sbt150084  * value, and a maximum value.
22376621Sbt150084  *
22386621Sbt150084  * Return configured value of the property, with default, minimum and
22396621Sbt150084  * maximum properly applied.
22406621Sbt150084  */
22416621Sbt150084 static int
22426621Sbt150084 ixgbe_get_prop(ixgbe_t *ixgbe,
22436621Sbt150084     char *propname,	/* name of the property */
22446621Sbt150084     int minval,		/* minimum acceptable value */
22456621Sbt150084     int maxval,		/* maximim acceptable value */
22466621Sbt150084     int defval)		/* default value */
22476621Sbt150084 {
22486621Sbt150084 	int value;
22496621Sbt150084 
22506621Sbt150084 	/*
22516621Sbt150084 	 * Call ddi_prop_get_int() to read the conf settings
22526621Sbt150084 	 */
22536621Sbt150084 	value = ddi_prop_get_int(DDI_DEV_T_ANY, ixgbe->dip,
22546621Sbt150084 	    DDI_PROP_DONTPASS, propname, defval);
22556621Sbt150084 	if (value > maxval)
22566621Sbt150084 		value = maxval;
22576621Sbt150084 
22586621Sbt150084 	if (value < minval)
22596621Sbt150084 		value = minval;
22606621Sbt150084 
22616621Sbt150084 	return (value);
22626621Sbt150084 }
22636621Sbt150084 
22646621Sbt150084 /*
22656621Sbt150084  * ixgbe_driver_setup_link - Using the link properties to setup the link.
22666621Sbt150084  */
22676621Sbt150084 int
22686621Sbt150084 ixgbe_driver_setup_link(ixgbe_t *ixgbe, boolean_t setup_hw)
22696621Sbt150084 {
22706621Sbt150084 	struct ixgbe_mac_info *mac;
22716621Sbt150084 	struct ixgbe_phy_info *phy;
22726621Sbt150084 	boolean_t invalid;
22736621Sbt150084 
22746621Sbt150084 	mac = &ixgbe->hw.mac;
22756621Sbt150084 	phy = &ixgbe->hw.phy;
22766621Sbt150084 	invalid = B_FALSE;
22776621Sbt150084 
22786621Sbt150084 	if (ixgbe->param_adv_autoneg_cap == 1) {
22796621Sbt150084 		mac->autoneg = B_TRUE;
22806621Sbt150084 		phy->autoneg_advertised = 0;
22816621Sbt150084 
22826621Sbt150084 		/*
22836621Sbt150084 		 * No half duplex support with 10Gb parts
22846621Sbt150084 		 */
22856621Sbt150084 		if (ixgbe->param_adv_10000fdx_cap == 1)
22866621Sbt150084 			phy->autoneg_advertised |= IXGBE_LINK_SPEED_10GB_FULL;
22876621Sbt150084 
22886621Sbt150084 		if (ixgbe->param_adv_1000fdx_cap == 1)
22896621Sbt150084 			phy->autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
22906621Sbt150084 
22916621Sbt150084 		if (ixgbe->param_adv_100fdx_cap == 1)
22926621Sbt150084 			phy->autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
22936621Sbt150084 
22946621Sbt150084 		if (phy->autoneg_advertised == 0)
22956621Sbt150084 			invalid = B_TRUE;
22966621Sbt150084 	} else {
22976621Sbt150084 		ixgbe->hw.mac.autoneg = B_FALSE;
22986621Sbt150084 	}
22996621Sbt150084 
23006621Sbt150084 	if (invalid) {
23016621Sbt150084 		ixgbe_notice(ixgbe, "Invalid link settings. Setup link to "
23026621Sbt150084 		    "autonegotiation with full link capabilities.");
23036621Sbt150084 		ixgbe->hw.mac.autoneg = B_TRUE;
23046621Sbt150084 	}
23056621Sbt150084 
23066621Sbt150084 	if (setup_hw) {
23076621Sbt150084 		if (ixgbe_setup_link(&ixgbe->hw) != IXGBE_SUCCESS)
23086621Sbt150084 			return (IXGBE_FAILURE);
23096621Sbt150084 	}
23106621Sbt150084 
23116621Sbt150084 	return (IXGBE_SUCCESS);
23126621Sbt150084 }
23136621Sbt150084 
23146621Sbt150084 /*
23156621Sbt150084  * ixgbe_driver_link_check - Link status processing.
23166621Sbt150084  */
23176621Sbt150084 static boolean_t
23186621Sbt150084 ixgbe_driver_link_check(ixgbe_t *ixgbe)
23196621Sbt150084 {
23206621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
23216621Sbt150084 	ixgbe_link_speed speed = IXGBE_LINK_SPEED_UNKNOWN;
23226621Sbt150084 	boolean_t link_up = B_FALSE;
23236621Sbt150084 	boolean_t link_changed = B_FALSE;
23246621Sbt150084 
23256621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
23266621Sbt150084 
23276621Sbt150084 	(void) ixgbe_check_link(hw, &speed, &link_up);
23286621Sbt150084 	if (link_up) {
23296621Sbt150084 		/*
23306621Sbt150084 		 * The Link is up, check whether it was marked as down earlier
23316621Sbt150084 		 */
23326621Sbt150084 		if (ixgbe->link_state != LINK_STATE_UP) {
23336621Sbt150084 			switch (speed) {
23346621Sbt150084 				case IXGBE_LINK_SPEED_10GB_FULL:
23356621Sbt150084 					ixgbe->link_speed = SPEED_10GB;
23366621Sbt150084 					break;
23376621Sbt150084 				case IXGBE_LINK_SPEED_1GB_FULL:
23386621Sbt150084 					ixgbe->link_speed = SPEED_1GB;
23396621Sbt150084 					break;
23406621Sbt150084 				case IXGBE_LINK_SPEED_100_FULL:
23416621Sbt150084 					ixgbe->link_speed = SPEED_100;
23426621Sbt150084 			}
23436621Sbt150084 			ixgbe->link_duplex = LINK_DUPLEX_FULL;
23446621Sbt150084 			ixgbe->link_state = LINK_STATE_UP;
23456621Sbt150084 			ixgbe->link_down_timeout = 0;
23466621Sbt150084 			link_changed = B_TRUE;
23476621Sbt150084 		}
23486621Sbt150084 	} else {
23496621Sbt150084 		if (ixgbe->link_state != LINK_STATE_DOWN) {
23506621Sbt150084 			ixgbe->link_speed = 0;
23516621Sbt150084 			ixgbe->link_duplex = 0;
23526621Sbt150084 			ixgbe->link_state = LINK_STATE_DOWN;
23536621Sbt150084 			link_changed = B_TRUE;
23546621Sbt150084 		}
23556621Sbt150084 
23566621Sbt150084 		if (ixgbe->ixgbe_state & IXGBE_STARTED) {
23576621Sbt150084 			if (ixgbe->link_down_timeout < MAX_LINK_DOWN_TIMEOUT) {
23586621Sbt150084 				ixgbe->link_down_timeout++;
23596621Sbt150084 			} else if (ixgbe->link_down_timeout ==
23606621Sbt150084 			    MAX_LINK_DOWN_TIMEOUT) {
23616621Sbt150084 				ixgbe_tx_clean(ixgbe);
23626621Sbt150084 				ixgbe->link_down_timeout++;
23636621Sbt150084 			}
23646621Sbt150084 		}
23656621Sbt150084 	}
23666621Sbt150084 
23676621Sbt150084 	return (link_changed);
23686621Sbt150084 }
23696621Sbt150084 
23706621Sbt150084 /*
23716621Sbt150084  * ixgbe_local_timer - Driver watchdog function.
23726621Sbt150084  *
23736621Sbt150084  * This function will handle the transmit stall check, link status check and
23746621Sbt150084  * other routines.
23756621Sbt150084  */
23766621Sbt150084 static void
23776621Sbt150084 ixgbe_local_timer(void *arg)
23786621Sbt150084 {
23796621Sbt150084 	ixgbe_t *ixgbe = (ixgbe_t *)arg;
23806621Sbt150084 
23816621Sbt150084 	if (ixgbe_stall_check(ixgbe)) {
23826621Sbt150084 		ixgbe->reset_count++;
23836621Sbt150084 		if (ixgbe_reset(ixgbe) == IXGBE_SUCCESS)
23846621Sbt150084 			ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_RESTORED);
23856621Sbt150084 	}
23866621Sbt150084 
23876621Sbt150084 	ixgbe_restart_watchdog_timer(ixgbe);
23886621Sbt150084 }
23896621Sbt150084 
23906621Sbt150084 /*
23916621Sbt150084  * ixgbe_stall_check - Check for transmit stall.
23926621Sbt150084  *
23936621Sbt150084  * This function checks if the adapter is stalled (in transmit).
23946621Sbt150084  *
23956621Sbt150084  * It is called each time the watchdog timeout is invoked.
23966621Sbt150084  * If the transmit descriptor reclaim continuously fails,
23976621Sbt150084  * the watchdog value will increment by 1. If the watchdog
23986621Sbt150084  * value exceeds the threshold, the ixgbe is assumed to
23996621Sbt150084  * have stalled and need to be reset.
24006621Sbt150084  */
24016621Sbt150084 static boolean_t
24026621Sbt150084 ixgbe_stall_check(ixgbe_t *ixgbe)
24036621Sbt150084 {
24046621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
24056621Sbt150084 	boolean_t result;
24066621Sbt150084 	int i;
24076621Sbt150084 
24086621Sbt150084 	if (ixgbe->link_state != LINK_STATE_UP)
24096621Sbt150084 		return (B_FALSE);
24106621Sbt150084 
24116621Sbt150084 	/*
24126621Sbt150084 	 * If any tx ring is stalled, we'll reset the chipset
24136621Sbt150084 	 */
24146621Sbt150084 	result = B_FALSE;
24156621Sbt150084 	for (i = 0; i < ixgbe->num_tx_rings; i++) {
24166621Sbt150084 		tx_ring = &ixgbe->tx_rings[i];
24176621Sbt150084 
24186621Sbt150084 		if (tx_ring->recycle_fail > 0)
24196621Sbt150084 			tx_ring->stall_watchdog++;
24206621Sbt150084 		else
24216621Sbt150084 			tx_ring->stall_watchdog = 0;
24226621Sbt150084 
24236621Sbt150084 		if (tx_ring->stall_watchdog >= STALL_WATCHDOG_TIMEOUT) {
24246621Sbt150084 			result = B_TRUE;
24256621Sbt150084 			break;
24266621Sbt150084 		}
24276621Sbt150084 	}
24286621Sbt150084 
24296621Sbt150084 	if (result) {
24306621Sbt150084 		tx_ring->stall_watchdog = 0;
24316621Sbt150084 		tx_ring->recycle_fail = 0;
24326621Sbt150084 	}
24336621Sbt150084 
24346621Sbt150084 	return (result);
24356621Sbt150084 }
24366621Sbt150084 
24376621Sbt150084 
24386621Sbt150084 /*
24396621Sbt150084  * is_valid_mac_addr - Check if the mac address is valid.
24406621Sbt150084  */
24416621Sbt150084 static boolean_t
24426621Sbt150084 is_valid_mac_addr(uint8_t *mac_addr)
24436621Sbt150084 {
24446621Sbt150084 	const uint8_t addr_test1[6] = { 0, 0, 0, 0, 0, 0 };
24456621Sbt150084 	const uint8_t addr_test2[6] =
24466621Sbt150084 	    { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
24476621Sbt150084 
24486621Sbt150084 	if (!(bcmp(addr_test1, mac_addr, ETHERADDRL)) ||
24496621Sbt150084 	    !(bcmp(addr_test2, mac_addr, ETHERADDRL)))
24506621Sbt150084 		return (B_FALSE);
24516621Sbt150084 
24526621Sbt150084 	return (B_TRUE);
24536621Sbt150084 }
24546621Sbt150084 
24556621Sbt150084 static boolean_t
24566621Sbt150084 ixgbe_find_mac_address(ixgbe_t *ixgbe)
24576621Sbt150084 {
24586621Sbt150084 #ifdef __sparc
24596621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
24606621Sbt150084 	uchar_t *bytes;
24616621Sbt150084 	struct ether_addr sysaddr;
24626621Sbt150084 	uint_t nelts;
24636621Sbt150084 	int err;
24646621Sbt150084 	boolean_t found = B_FALSE;
24656621Sbt150084 
24666621Sbt150084 	/*
24676621Sbt150084 	 * The "vendor's factory-set address" may already have
24686621Sbt150084 	 * been extracted from the chip, but if the property
24696621Sbt150084 	 * "local-mac-address" is set we use that instead.
24706621Sbt150084 	 *
24716621Sbt150084 	 * We check whether it looks like an array of 6
24726621Sbt150084 	 * bytes (which it should, if OBP set it).  If we can't
24736621Sbt150084 	 * make sense of it this way, we'll ignore it.
24746621Sbt150084 	 */
24756621Sbt150084 	err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, ixgbe->dip,
24766621Sbt150084 	    DDI_PROP_DONTPASS, "local-mac-address", &bytes, &nelts);
24776621Sbt150084 	if (err == DDI_PROP_SUCCESS) {
24786621Sbt150084 		if (nelts == ETHERADDRL) {
24796621Sbt150084 			while (nelts--)
24806621Sbt150084 				hw->mac.addr[nelts] = bytes[nelts];
24816621Sbt150084 			found = B_TRUE;
24826621Sbt150084 		}
24836621Sbt150084 		ddi_prop_free(bytes);
24846621Sbt150084 	}
24856621Sbt150084 
24866621Sbt150084 	/*
24876621Sbt150084 	 * Look up the OBP property "local-mac-address?". If the user has set
24886621Sbt150084 	 * 'local-mac-address? = false', use "the system address" instead.
24896621Sbt150084 	 */
24906621Sbt150084 	if (ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, ixgbe->dip, 0,
24916621Sbt150084 	    "local-mac-address?", &bytes, &nelts) == DDI_PROP_SUCCESS) {
24926621Sbt150084 		if (strncmp("false", (caddr_t)bytes, (size_t)nelts) == 0) {
24936621Sbt150084 			if (localetheraddr(NULL, &sysaddr) != 0) {
24946621Sbt150084 				bcopy(&sysaddr, hw->mac.addr, ETHERADDRL);
24956621Sbt150084 				found = B_TRUE;
24966621Sbt150084 			}
24976621Sbt150084 		}
24986621Sbt150084 		ddi_prop_free(bytes);
24996621Sbt150084 	}
25006621Sbt150084 
25016621Sbt150084 	/*
25026621Sbt150084 	 * Finally(!), if there's a valid "mac-address" property (created
25036621Sbt150084 	 * if we netbooted from this interface), we must use this instead
25046621Sbt150084 	 * of any of the above to ensure that the NFS/install server doesn't
25056621Sbt150084 	 * get confused by the address changing as Solaris takes over!
25066621Sbt150084 	 */
25076621Sbt150084 	err = ddi_prop_lookup_byte_array(DDI_DEV_T_ANY, ixgbe->dip,
25086621Sbt150084 	    DDI_PROP_DONTPASS, "mac-address", &bytes, &nelts);
25096621Sbt150084 	if (err == DDI_PROP_SUCCESS) {
25106621Sbt150084 		if (nelts == ETHERADDRL) {
25116621Sbt150084 			while (nelts--)
25126621Sbt150084 				hw->mac.addr[nelts] = bytes[nelts];
25136621Sbt150084 			found = B_TRUE;
25146621Sbt150084 		}
25156621Sbt150084 		ddi_prop_free(bytes);
25166621Sbt150084 	}
25176621Sbt150084 
25186621Sbt150084 	if (found) {
25196621Sbt150084 		bcopy(hw->mac.addr, hw->mac.perm_addr, ETHERADDRL);
25206621Sbt150084 		return (B_TRUE);
25216621Sbt150084 	}
25226621Sbt150084 #else
25236621Sbt150084 	_NOTE(ARGUNUSED(ixgbe));
25246621Sbt150084 #endif
25256621Sbt150084 
25266621Sbt150084 	return (B_TRUE);
25276621Sbt150084 }
25286621Sbt150084 
25296621Sbt150084 #pragma inline(ixgbe_arm_watchdog_timer)
25306621Sbt150084 static void
25316621Sbt150084 ixgbe_arm_watchdog_timer(ixgbe_t *ixgbe)
25326621Sbt150084 {
25336621Sbt150084 	/*
25346621Sbt150084 	 * Fire a watchdog timer
25356621Sbt150084 	 */
25366621Sbt150084 	ixgbe->watchdog_tid =
25376621Sbt150084 	    timeout(ixgbe_local_timer,
25386621Sbt150084 	    (void *)ixgbe, 1 * drv_usectohz(1000000));
25396621Sbt150084 
25406621Sbt150084 }
25416621Sbt150084 
25426621Sbt150084 /*
25436621Sbt150084  * ixgbe_enable_watchdog_timer - Enable and start the driver watchdog timer.
25446621Sbt150084  */
25456621Sbt150084 void
25466621Sbt150084 ixgbe_enable_watchdog_timer(ixgbe_t *ixgbe)
25476621Sbt150084 {
25486621Sbt150084 	mutex_enter(&ixgbe->watchdog_lock);
25496621Sbt150084 
25506621Sbt150084 	if (!ixgbe->watchdog_enable) {
25516621Sbt150084 		ixgbe->watchdog_enable = B_TRUE;
25526621Sbt150084 		ixgbe->watchdog_start = B_TRUE;
25536621Sbt150084 		ixgbe_arm_watchdog_timer(ixgbe);
25546621Sbt150084 	}
25556621Sbt150084 
25566621Sbt150084 	mutex_exit(&ixgbe->watchdog_lock);
25576621Sbt150084 }
25586621Sbt150084 
25596621Sbt150084 /*
25606621Sbt150084  * ixgbe_disable_watchdog_timer - Disable and stop the driver watchdog timer.
25616621Sbt150084  */
25626621Sbt150084 void
25636621Sbt150084 ixgbe_disable_watchdog_timer(ixgbe_t *ixgbe)
25646621Sbt150084 {
25656621Sbt150084 	timeout_id_t tid;
25666621Sbt150084 
25676621Sbt150084 	mutex_enter(&ixgbe->watchdog_lock);
25686621Sbt150084 
25696621Sbt150084 	ixgbe->watchdog_enable = B_FALSE;
25706621Sbt150084 	ixgbe->watchdog_start = B_FALSE;
25716621Sbt150084 	tid = ixgbe->watchdog_tid;
25726621Sbt150084 	ixgbe->watchdog_tid = 0;
25736621Sbt150084 
25746621Sbt150084 	mutex_exit(&ixgbe->watchdog_lock);
25756621Sbt150084 
25766621Sbt150084 	if (tid != 0)
25776621Sbt150084 		(void) untimeout(tid);
25786621Sbt150084 }
25796621Sbt150084 
25806621Sbt150084 /*
25816621Sbt150084  * ixgbe_start_watchdog_timer - Start the driver watchdog timer.
25826621Sbt150084  */
25836621Sbt150084 static void
25846621Sbt150084 ixgbe_start_watchdog_timer(ixgbe_t *ixgbe)
25856621Sbt150084 {
25866621Sbt150084 	mutex_enter(&ixgbe->watchdog_lock);
25876621Sbt150084 
25886621Sbt150084 	if (ixgbe->watchdog_enable) {
25896621Sbt150084 		if (!ixgbe->watchdog_start) {
25906621Sbt150084 			ixgbe->watchdog_start = B_TRUE;
25916621Sbt150084 			ixgbe_arm_watchdog_timer(ixgbe);
25926621Sbt150084 		}
25936621Sbt150084 	}
25946621Sbt150084 
25956621Sbt150084 	mutex_exit(&ixgbe->watchdog_lock);
25966621Sbt150084 }
25976621Sbt150084 
25986621Sbt150084 /*
25996621Sbt150084  * ixgbe_restart_watchdog_timer - Restart the driver watchdog timer.
26006621Sbt150084  */
26016621Sbt150084 static void
26026621Sbt150084 ixgbe_restart_watchdog_timer(ixgbe_t *ixgbe)
26036621Sbt150084 {
26046621Sbt150084 	mutex_enter(&ixgbe->watchdog_lock);
26056621Sbt150084 
26066621Sbt150084 	if (ixgbe->watchdog_start)
26076621Sbt150084 		ixgbe_arm_watchdog_timer(ixgbe);
26086621Sbt150084 
26096621Sbt150084 	mutex_exit(&ixgbe->watchdog_lock);
26106621Sbt150084 }
26116621Sbt150084 
26126621Sbt150084 /*
26136621Sbt150084  * ixgbe_stop_watchdog_timer - Stop the driver watchdog timer.
26146621Sbt150084  */
26156621Sbt150084 static void
26166621Sbt150084 ixgbe_stop_watchdog_timer(ixgbe_t *ixgbe)
26176621Sbt150084 {
26186621Sbt150084 	timeout_id_t tid;
26196621Sbt150084 
26206621Sbt150084 	mutex_enter(&ixgbe->watchdog_lock);
26216621Sbt150084 
26226621Sbt150084 	ixgbe->watchdog_start = B_FALSE;
26236621Sbt150084 	tid = ixgbe->watchdog_tid;
26246621Sbt150084 	ixgbe->watchdog_tid = 0;
26256621Sbt150084 
26266621Sbt150084 	mutex_exit(&ixgbe->watchdog_lock);
26276621Sbt150084 
26286621Sbt150084 	if (tid != 0)
26296621Sbt150084 		(void) untimeout(tid);
26306621Sbt150084 }
26316621Sbt150084 
26326621Sbt150084 /*
26336621Sbt150084  * ixgbe_disable_adapter_interrupts - Disable all adapter interrupts.
26346621Sbt150084  */
26356621Sbt150084 static void
26366621Sbt150084 ixgbe_disable_adapter_interrupts(ixgbe_t *ixgbe)
26376621Sbt150084 {
26386621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
26396621Sbt150084 
26406621Sbt150084 	/*
26416621Sbt150084 	 * mask all interrupts off
26426621Sbt150084 	 */
26436621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_EIMC, 0xffffffff);
26446621Sbt150084 
26456621Sbt150084 	/*
26466621Sbt150084 	 * for MSI-X, also disable autoclear
26476621Sbt150084 	 */
26486621Sbt150084 	if (ixgbe->intr_type == DDI_INTR_TYPE_MSIX) {
26496621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_EIAC, 0x0);
26506621Sbt150084 	}
26516621Sbt150084 
26526621Sbt150084 	IXGBE_WRITE_FLUSH(hw);
26536621Sbt150084 }
26546621Sbt150084 
26556621Sbt150084 /*
26566621Sbt150084  * ixgbe_enable_adapter_interrupts - Enable all hardware interrupts.
26576621Sbt150084  */
26586621Sbt150084 static void
26596621Sbt150084 ixgbe_enable_adapter_interrupts(ixgbe_t *ixgbe)
26606621Sbt150084 {
26616621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
26626621Sbt150084 	uint32_t eims, eiac, gpie;
26636621Sbt150084 
26646621Sbt150084 	gpie = 0;
26656621Sbt150084 	eims = IXGBE_EIMS_ENABLE_MASK;	/* shared code default */
26666621Sbt150084 	eims &= ~IXGBE_EIMS_TCP_TIMER;	/* minus tcp timer */
26676621Sbt150084 
26686621Sbt150084 	/*
26696621Sbt150084 	 * msi-x mode
26706621Sbt150084 	 */
26716621Sbt150084 	if (ixgbe->intr_type == DDI_INTR_TYPE_MSIX) {
26726621Sbt150084 		/* enable autoclear but not on bits 29:20 */
26736621Sbt150084 		eiac = (eims & ~0x3ff00000);
26746621Sbt150084 
26756621Sbt150084 		/* general purpose interrupt enable */
26766621Sbt150084 		gpie |= (IXGBE_GPIE_MSIX_MODE |
26776621Sbt150084 		    IXGBE_GPIE_PBA_SUPPORT |IXGBE_GPIE_OCD);
26786621Sbt150084 	/*
26796621Sbt150084 	 * non-msi-x mode
26806621Sbt150084 	 */
26816621Sbt150084 	} else {
26826621Sbt150084 
26836621Sbt150084 		/* disable autoclear, leave gpie at default */
26846621Sbt150084 		eiac = 0;
26856621Sbt150084 	}
26866621Sbt150084 
26876621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_EIMS, eims);
26886621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_EIAC, eiac);
26896621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
26906621Sbt150084 	IXGBE_WRITE_FLUSH(hw);
26916621Sbt150084 }
26926621Sbt150084 
26936621Sbt150084 /*
26946621Sbt150084  * ixgbe_loopback_ioctl - Loopback support.
26956621Sbt150084  */
26966621Sbt150084 enum ioc_reply
26976621Sbt150084 ixgbe_loopback_ioctl(ixgbe_t *ixgbe, struct iocblk *iocp, mblk_t *mp)
26986621Sbt150084 {
26996621Sbt150084 	lb_info_sz_t *lbsp;
27006621Sbt150084 	lb_property_t *lbpp;
27016621Sbt150084 	uint32_t *lbmp;
27026621Sbt150084 	uint32_t size;
27036621Sbt150084 	uint32_t value;
27046621Sbt150084 
27056621Sbt150084 	if (mp->b_cont == NULL)
27066621Sbt150084 		return (IOC_INVAL);
27076621Sbt150084 
27086621Sbt150084 	switch (iocp->ioc_cmd) {
27096621Sbt150084 	default:
27106621Sbt150084 		return (IOC_INVAL);
27116621Sbt150084 
27126621Sbt150084 	case LB_GET_INFO_SIZE:
27136621Sbt150084 		size = sizeof (lb_info_sz_t);
27146621Sbt150084 		if (iocp->ioc_count != size)
27156621Sbt150084 			return (IOC_INVAL);
27166621Sbt150084 
27176621Sbt150084 		value = sizeof (lb_normal);
27186621Sbt150084 		value += sizeof (lb_mac);
27196621Sbt150084 
27206621Sbt150084 		lbsp = (lb_info_sz_t *)(uintptr_t)mp->b_cont->b_rptr;
27216621Sbt150084 		*lbsp = value;
27226621Sbt150084 		break;
27236621Sbt150084 
27246621Sbt150084 	case LB_GET_INFO:
27256621Sbt150084 		value = sizeof (lb_normal);
27266621Sbt150084 		value += sizeof (lb_mac);
27276621Sbt150084 
27286621Sbt150084 		size = value;
27296621Sbt150084 		if (iocp->ioc_count != size)
27306621Sbt150084 			return (IOC_INVAL);
27316621Sbt150084 
27326621Sbt150084 		value = 0;
27336621Sbt150084 		lbpp = (lb_property_t *)(uintptr_t)mp->b_cont->b_rptr;
27346621Sbt150084 
27356621Sbt150084 		lbpp[value++] = lb_normal;
27366621Sbt150084 		lbpp[value++] = lb_mac;
27376621Sbt150084 		break;
27386621Sbt150084 
27396621Sbt150084 	case LB_GET_MODE:
27406621Sbt150084 		size = sizeof (uint32_t);
27416621Sbt150084 		if (iocp->ioc_count != size)
27426621Sbt150084 			return (IOC_INVAL);
27436621Sbt150084 
27446621Sbt150084 		lbmp = (uint32_t *)(uintptr_t)mp->b_cont->b_rptr;
27456621Sbt150084 		*lbmp = ixgbe->loopback_mode;
27466621Sbt150084 		break;
27476621Sbt150084 
27486621Sbt150084 	case LB_SET_MODE:
27496621Sbt150084 		size = 0;
27506621Sbt150084 		if (iocp->ioc_count != sizeof (uint32_t))
27516621Sbt150084 			return (IOC_INVAL);
27526621Sbt150084 
27536621Sbt150084 		lbmp = (uint32_t *)(uintptr_t)mp->b_cont->b_rptr;
27546621Sbt150084 		if (!ixgbe_set_loopback_mode(ixgbe, *lbmp))
27556621Sbt150084 			return (IOC_INVAL);
27566621Sbt150084 		break;
27576621Sbt150084 	}
27586621Sbt150084 
27596621Sbt150084 	iocp->ioc_count = size;
27606621Sbt150084 	iocp->ioc_error = 0;
27616621Sbt150084 
27626621Sbt150084 	if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) {
27636621Sbt150084 		ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_DEGRADED);
27646621Sbt150084 		return (IOC_INVAL);
27656621Sbt150084 	}
27666621Sbt150084 
27676621Sbt150084 	return (IOC_REPLY);
27686621Sbt150084 }
27696621Sbt150084 
27706621Sbt150084 /*
27716621Sbt150084  * ixgbe_set_loopback_mode - Setup loopback based on the loopback mode.
27726621Sbt150084  */
27736621Sbt150084 static boolean_t
27746621Sbt150084 ixgbe_set_loopback_mode(ixgbe_t *ixgbe, uint32_t mode)
27756621Sbt150084 {
27766621Sbt150084 	struct ixgbe_hw *hw;
27776621Sbt150084 
27786621Sbt150084 	if (mode == ixgbe->loopback_mode)
27796621Sbt150084 		return (B_TRUE);
27806621Sbt150084 
27816621Sbt150084 	hw = &ixgbe->hw;
27826621Sbt150084 
27836621Sbt150084 	ixgbe->loopback_mode = mode;
27846621Sbt150084 
27856621Sbt150084 	if (mode == IXGBE_LB_NONE) {
27866621Sbt150084 		/*
27876621Sbt150084 		 * Reset the chip
27886621Sbt150084 		 */
27896621Sbt150084 		hw->phy.autoneg_wait_to_complete = B_TRUE;
27906621Sbt150084 		(void) ixgbe_reset(ixgbe);
27916621Sbt150084 		hw->phy.autoneg_wait_to_complete = B_FALSE;
27926621Sbt150084 		return (B_TRUE);
27936621Sbt150084 	}
27946621Sbt150084 
27956621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
27966621Sbt150084 
27976621Sbt150084 	switch (mode) {
27986621Sbt150084 	default:
27996621Sbt150084 		mutex_exit(&ixgbe->gen_lock);
28006621Sbt150084 		return (B_FALSE);
28016621Sbt150084 
28026621Sbt150084 	case IXGBE_LB_INTERNAL_MAC:
28036621Sbt150084 		ixgbe_set_internal_mac_loopback(ixgbe);
28046621Sbt150084 		break;
28056621Sbt150084 	}
28066621Sbt150084 
28076621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
28086621Sbt150084 
28096621Sbt150084 	return (B_TRUE);
28106621Sbt150084 }
28116621Sbt150084 
28126621Sbt150084 /*
28136621Sbt150084  * ixgbe_set_internal_mac_loopback - Set the internal MAC loopback mode.
28146621Sbt150084  */
28156621Sbt150084 static void
28166621Sbt150084 ixgbe_set_internal_mac_loopback(ixgbe_t *ixgbe)
28176621Sbt150084 {
28186621Sbt150084 	struct ixgbe_hw *hw;
28196621Sbt150084 	uint32_t reg;
28206621Sbt150084 	uint8_t atlas;
28216621Sbt150084 
28226621Sbt150084 	hw = &ixgbe->hw;
28236621Sbt150084 
28246621Sbt150084 	/*
28256621Sbt150084 	 * Setup MAC loopback
28266621Sbt150084 	 */
28276621Sbt150084 	reg = IXGBE_READ_REG(&ixgbe->hw, IXGBE_HLREG0);
28286621Sbt150084 	reg |= IXGBE_HLREG0_LPBK;
28296621Sbt150084 	IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_HLREG0, reg);
28306621Sbt150084 
28316621Sbt150084 	reg = IXGBE_READ_REG(&ixgbe->hw, IXGBE_AUTOC);
28326621Sbt150084 	reg &= ~IXGBE_AUTOC_LMS_MASK;
28336621Sbt150084 	IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_AUTOC, reg);
28346621Sbt150084 
28356621Sbt150084 	/*
28366621Sbt150084 	 * Disable Atlas Tx lanes to keep packets in loopback and not on wire
28376621Sbt150084 	 */
28386621Sbt150084 	if (hw->mac.type == ixgbe_mac_82598EB) {
28396621Sbt150084 		(void) ixgbe_read_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_LPBK,
28406621Sbt150084 		    &atlas);
28416621Sbt150084 		atlas |= IXGBE_ATLAS_PDN_TX_REG_EN;
28426621Sbt150084 		(void) ixgbe_write_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_LPBK,
28436621Sbt150084 		    atlas);
28446621Sbt150084 
28456621Sbt150084 		(void) ixgbe_read_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_10G,
28466621Sbt150084 		    &atlas);
28476621Sbt150084 		atlas |= IXGBE_ATLAS_PDN_TX_10G_QL_ALL;
28486621Sbt150084 		(void) ixgbe_write_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_10G,
28496621Sbt150084 		    atlas);
28506621Sbt150084 
28516621Sbt150084 		(void) ixgbe_read_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_1G,
28526621Sbt150084 		    &atlas);
28536621Sbt150084 		atlas |= IXGBE_ATLAS_PDN_TX_1G_QL_ALL;
28546621Sbt150084 		(void) ixgbe_write_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_1G,
28556621Sbt150084 		    atlas);
28566621Sbt150084 
28576621Sbt150084 		(void) ixgbe_read_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_AN,
28586621Sbt150084 		    &atlas);
28596621Sbt150084 		atlas |= IXGBE_ATLAS_PDN_TX_AN_QL_ALL;
28606621Sbt150084 		(void) ixgbe_write_analog_reg8(&ixgbe->hw, IXGBE_ATLAS_PDN_AN,
28616621Sbt150084 		    atlas);
28626621Sbt150084 	}
28636621Sbt150084 }
28646621Sbt150084 
28656621Sbt150084 #pragma inline(ixgbe_intr_rx_work)
28666621Sbt150084 /*
28676621Sbt150084  * ixgbe_intr_rx_work - RX processing of ISR.
28686621Sbt150084  */
28696621Sbt150084 static void
28706621Sbt150084 ixgbe_intr_rx_work(ixgbe_rx_ring_t *rx_ring)
28716621Sbt150084 {
28726621Sbt150084 	mblk_t *mp;
28736621Sbt150084 
28746621Sbt150084 	mutex_enter(&rx_ring->rx_lock);
28756621Sbt150084 
28766621Sbt150084 	mp = ixgbe_rx(rx_ring);
28776621Sbt150084 	mutex_exit(&rx_ring->rx_lock);
28786621Sbt150084 
28796621Sbt150084 	if (mp != NULL)
28806621Sbt150084 		mac_rx(rx_ring->ixgbe->mac_hdl, NULL, mp);
28816621Sbt150084 }
28826621Sbt150084 
28836621Sbt150084 #pragma inline(ixgbe_intr_tx_work)
28846621Sbt150084 /*
28856621Sbt150084  * ixgbe_intr_tx_work - TX processing of ISR.
28866621Sbt150084  */
28876621Sbt150084 static void
28886621Sbt150084 ixgbe_intr_tx_work(ixgbe_tx_ring_t *tx_ring)
28896621Sbt150084 {
28906621Sbt150084 	/*
28916621Sbt150084 	 * Recycle the tx descriptors
28926621Sbt150084 	 */
28936621Sbt150084 	tx_ring->tx_recycle(tx_ring);
28946621Sbt150084 
28956621Sbt150084 	/*
28966621Sbt150084 	 * Schedule the re-transmit
28976621Sbt150084 	 */
28986621Sbt150084 	if (tx_ring->reschedule &&
28996621Sbt150084 	    (tx_ring->tbd_free >= tx_ring->resched_thresh)) {
29006621Sbt150084 		tx_ring->reschedule = B_FALSE;
29016621Sbt150084 		mac_tx_update(tx_ring->ixgbe->mac_hdl);
29026621Sbt150084 		IXGBE_DEBUG_STAT(tx_ring->stat_reschedule);
29036621Sbt150084 	}
29046621Sbt150084 }
29056621Sbt150084 
29066621Sbt150084 #pragma inline(ixgbe_intr_other_work)
29076621Sbt150084 /*
29086621Sbt150084  * ixgbe_intr_other_work - Other processing of ISR.
29096621Sbt150084  */
29106621Sbt150084 static void
29116621Sbt150084 ixgbe_intr_other_work(ixgbe_t *ixgbe)
29126621Sbt150084 {
29136621Sbt150084 	boolean_t link_changed;
29146621Sbt150084 
29156621Sbt150084 	ixgbe_stop_watchdog_timer(ixgbe);
29166621Sbt150084 
29176621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
29186621Sbt150084 
29196621Sbt150084 	/*
29206621Sbt150084 	 * Take care of link status change
29216621Sbt150084 	 */
29226621Sbt150084 	link_changed = ixgbe_driver_link_check(ixgbe);
29236621Sbt150084 
29246621Sbt150084 	/*
29256621Sbt150084 	 * Get new phy state
29266621Sbt150084 	 */
29276621Sbt150084 	ixgbe_get_hw_state(ixgbe);
29286621Sbt150084 
29296621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
29306621Sbt150084 
29316621Sbt150084 	if (link_changed)
29326621Sbt150084 		mac_link_update(ixgbe->mac_hdl, ixgbe->link_state);
29336621Sbt150084 
29346621Sbt150084 	ixgbe_start_watchdog_timer(ixgbe);
29356621Sbt150084 }
29366621Sbt150084 
29376621Sbt150084 /*
29386621Sbt150084  * ixgbe_intr_legacy - Interrupt handler for legacy interrupts.
29396621Sbt150084  */
29406621Sbt150084 static uint_t
29416621Sbt150084 ixgbe_intr_legacy(void *arg1, void *arg2)
29426621Sbt150084 {
29436621Sbt150084 	_NOTE(ARGUNUSED(arg2));
29446621Sbt150084 	ixgbe_t *ixgbe = (ixgbe_t *)arg1;
29456621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
29466621Sbt150084 	ixgbe_tx_ring_t *tx_ring;
29476621Sbt150084 	uint32_t eicr;
29486621Sbt150084 	mblk_t *mp;
29496621Sbt150084 	boolean_t tx_reschedule;
29506621Sbt150084 	boolean_t link_changed;
29516621Sbt150084 	uint_t result;
29526621Sbt150084 
29536621Sbt150084 
29546621Sbt150084 	mutex_enter(&ixgbe->gen_lock);
29556621Sbt150084 
29566621Sbt150084 	if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) {
29576621Sbt150084 		mutex_exit(&ixgbe->gen_lock);
29586621Sbt150084 		return (DDI_INTR_UNCLAIMED);
29596621Sbt150084 	}
29606621Sbt150084 
29616621Sbt150084 	mp = NULL;
29626621Sbt150084 	tx_reschedule = B_FALSE;
29636621Sbt150084 	link_changed = B_FALSE;
29646621Sbt150084 
29656621Sbt150084 	/*
29666621Sbt150084 	 * Any bit set in eicr: claim this interrupt
29676621Sbt150084 	 */
29686621Sbt150084 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
29696621Sbt150084 	if (eicr) {
29706621Sbt150084 		/*
29716621Sbt150084 		 * For legacy interrupt, we have only one interrupt,
29726621Sbt150084 		 * so we have only one rx ring and one tx ring enabled.
29736621Sbt150084 		 */
29746621Sbt150084 		ASSERT(ixgbe->num_rx_rings == 1);
29756621Sbt150084 		ASSERT(ixgbe->num_tx_rings == 1);
29766621Sbt150084 
29776621Sbt150084 		/*
29786621Sbt150084 		 * For legacy interrupt, we can't differentiate
29796621Sbt150084 		 * between tx and rx, so always clean both
29806621Sbt150084 		 */
29816621Sbt150084 		if (eicr & IXGBE_EICR_RTX_QUEUE) {
29826621Sbt150084 
29836621Sbt150084 			/*
29846621Sbt150084 			 * Clean the rx descriptors
29856621Sbt150084 			 */
29866621Sbt150084 			mp = ixgbe_rx(&ixgbe->rx_rings[0]);
29876621Sbt150084 
29886621Sbt150084 			/*
29896621Sbt150084 			 * Recycle the tx descriptors
29906621Sbt150084 			 */
29916621Sbt150084 			tx_ring = &ixgbe->tx_rings[0];
29926621Sbt150084 			tx_ring->tx_recycle(tx_ring);
29936621Sbt150084 
29946621Sbt150084 			/*
29956621Sbt150084 			 * Schedule the re-transmit
29966621Sbt150084 			 */
29976621Sbt150084 			tx_reschedule = (tx_ring->reschedule &&
29986621Sbt150084 			    (tx_ring->tbd_free >= tx_ring->resched_thresh));
29996621Sbt150084 		}
30006621Sbt150084 
30016621Sbt150084 		if (eicr & IXGBE_EICR_LSC) {
30026621Sbt150084 
30036621Sbt150084 			/* take care of link status change */
30046621Sbt150084 			link_changed = ixgbe_driver_link_check(ixgbe);
30056621Sbt150084 
30066621Sbt150084 			/* Get new phy state */
30076621Sbt150084 			ixgbe_get_hw_state(ixgbe);
30086621Sbt150084 		}
30096621Sbt150084 
30106621Sbt150084 		result = DDI_INTR_CLAIMED;
30116621Sbt150084 	} else {
30126621Sbt150084 		/*
30136621Sbt150084 		 * No interrupt cause bits set: don't claim this interrupt.
30146621Sbt150084 		 */
30156621Sbt150084 		result = DDI_INTR_UNCLAIMED;
30166621Sbt150084 	}
30176621Sbt150084 
30186621Sbt150084 	mutex_exit(&ixgbe->gen_lock);
30196621Sbt150084 
30206621Sbt150084 	/*
30216621Sbt150084 	 * Do the following work outside of the gen_lock
30226621Sbt150084 	 */
30236621Sbt150084 	if (mp != NULL)
30246621Sbt150084 		mac_rx(ixgbe->mac_hdl, NULL, mp);
30256621Sbt150084 
30266621Sbt150084 	if (tx_reschedule)  {
30276621Sbt150084 		tx_ring->reschedule = B_FALSE;
30286621Sbt150084 		mac_tx_update(ixgbe->mac_hdl);
30296621Sbt150084 		IXGBE_DEBUG_STAT(tx_ring->stat_reschedule);
30306621Sbt150084 	}
30316621Sbt150084 
30326621Sbt150084 	if (link_changed)
30336621Sbt150084 		mac_link_update(ixgbe->mac_hdl, ixgbe->link_state);
30346621Sbt150084 
30356621Sbt150084 	return (result);
30366621Sbt150084 }
30376621Sbt150084 
30386621Sbt150084 /*
30396621Sbt150084  * ixgbe_intr_msi - Interrupt handler for MSI.
30406621Sbt150084  */
30416621Sbt150084 static uint_t
30426621Sbt150084 ixgbe_intr_msi(void *arg1, void *arg2)
30436621Sbt150084 {
30446621Sbt150084 	_NOTE(ARGUNUSED(arg2));
30456621Sbt150084 	ixgbe_t *ixgbe = (ixgbe_t *)arg1;
30466621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
30476621Sbt150084 	uint32_t eicr;
30486621Sbt150084 
30496621Sbt150084 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
30506621Sbt150084 
30516621Sbt150084 	/*
30526621Sbt150084 	 * For MSI interrupt, we have only one vector,
30536621Sbt150084 	 * so we have only one rx ring and one tx ring enabled.
30546621Sbt150084 	 */
30556621Sbt150084 	ASSERT(ixgbe->num_rx_rings == 1);
30566621Sbt150084 	ASSERT(ixgbe->num_tx_rings == 1);
30576621Sbt150084 
30586621Sbt150084 	/*
30596621Sbt150084 	 * For MSI interrupt, we can't differentiate
30606621Sbt150084 	 * between tx and rx, so always clean both.
30616621Sbt150084 	 */
30626621Sbt150084 	if (eicr & IXGBE_EICR_RTX_QUEUE) {
30636621Sbt150084 		ixgbe_intr_rx_work(&ixgbe->rx_rings[0]);
30646621Sbt150084 		ixgbe_intr_tx_work(&ixgbe->tx_rings[0]);
30656621Sbt150084 	}
30666621Sbt150084 
30676621Sbt150084 	if (eicr & IXGBE_EICR_LSC) {
30686621Sbt150084 		ixgbe_intr_other_work(ixgbe);
30696621Sbt150084 	}
30706621Sbt150084 
30716621Sbt150084 	return (DDI_INTR_CLAIMED);
30726621Sbt150084 }
30736621Sbt150084 
30746621Sbt150084 /*
30756621Sbt150084  * ixgbe_intr_rx - Interrupt handler for rx.
30766621Sbt150084  */
30776621Sbt150084 static uint_t
30786621Sbt150084 ixgbe_intr_rx(void *arg1, void *arg2)
30796621Sbt150084 {
30806621Sbt150084 	_NOTE(ARGUNUSED(arg2));
30816621Sbt150084 	ixgbe_ring_vector_t	*vect = (ixgbe_ring_vector_t *)arg1;
30826621Sbt150084 	ixgbe_t			*ixgbe = vect->ixgbe;
30836621Sbt150084 	int			r_idx;
30846621Sbt150084 
30856621Sbt150084 	/*
30866621Sbt150084 	 * clean each rx ring that has its bit set in the map
30876621Sbt150084 	 */
30886621Sbt150084 	r_idx = bt_getlowbit(vect->rx_map, 0, (ixgbe->num_rx_rings - 1));
30896621Sbt150084 
30906621Sbt150084 	while (r_idx >= 0) {
30916621Sbt150084 		ixgbe_intr_rx_work(&ixgbe->rx_rings[r_idx]);
30926621Sbt150084 		r_idx = bt_getlowbit(vect->rx_map, (r_idx + 1),
30936621Sbt150084 		    (ixgbe->num_rx_rings - 1));
30946621Sbt150084 	}
30956621Sbt150084 
30966621Sbt150084 	return (DDI_INTR_CLAIMED);
30976621Sbt150084 }
30986621Sbt150084 
30996621Sbt150084 /*
31006621Sbt150084  * ixgbe_intr_tx_other - Interrupt handler for both tx and other.
31016621Sbt150084  *
31026621Sbt150084  * Always look for Tx cleanup work.  Only look for other work if the right
31036621Sbt150084  * bits are set in the Interrupt Cause Register.
31046621Sbt150084  */
31056621Sbt150084 static uint_t
31066621Sbt150084 ixgbe_intr_tx_other(void *arg1, void *arg2)
31076621Sbt150084 {
31086621Sbt150084 	_NOTE(ARGUNUSED(arg2));
31096621Sbt150084 	ixgbe_t *ixgbe = (ixgbe_t *)arg1;
31106621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
31116621Sbt150084 	uint32_t eicr;
31126621Sbt150084 
31136621Sbt150084 	eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
31146621Sbt150084 
31156621Sbt150084 	/*
31166621Sbt150084 	 * Always look for Tx cleanup work.  We don't have separate
31176621Sbt150084 	 * transmit vectors, so we have only one tx ring enabled.
31186621Sbt150084 	 */
31196621Sbt150084 	ASSERT(ixgbe->num_tx_rings == 1);
31206621Sbt150084 	ixgbe_intr_tx_work(&ixgbe->tx_rings[0]);
31216621Sbt150084 
31226621Sbt150084 	/*
31236621Sbt150084 	 * Check for "other" causes.
31246621Sbt150084 	 */
31256621Sbt150084 	if (eicr & IXGBE_EICR_LSC) {
31266621Sbt150084 		ixgbe_intr_other_work(ixgbe);
31276621Sbt150084 	}
31286621Sbt150084 
31296621Sbt150084 	return (DDI_INTR_CLAIMED);
31306621Sbt150084 }
31316621Sbt150084 
31326621Sbt150084 /*
31336621Sbt150084  * ixgbe_alloc_intrs - Allocate interrupts for the driver.
31346621Sbt150084  *
31356621Sbt150084  * Normal sequence is to try MSI-X; if not sucessful, try MSI;
31366621Sbt150084  * if not successful, try Legacy.
31376621Sbt150084  * ixgbe->intr_force can be used to force sequence to start with
31386621Sbt150084  * any of the 3 types.
31396621Sbt150084  * If MSI-X is not used, number of tx/rx rings is forced to 1.
31406621Sbt150084  */
31416621Sbt150084 static int
31426621Sbt150084 ixgbe_alloc_intrs(ixgbe_t *ixgbe)
31436621Sbt150084 {
31446621Sbt150084 	dev_info_t *devinfo;
31456621Sbt150084 	int intr_types;
31466621Sbt150084 	int rc;
31476621Sbt150084 
31486621Sbt150084 	devinfo = ixgbe->dip;
31496621Sbt150084 
31506621Sbt150084 	/*
31516621Sbt150084 	 * Get supported interrupt types
31526621Sbt150084 	 */
31536621Sbt150084 	rc = ddi_intr_get_supported_types(devinfo, &intr_types);
31546621Sbt150084 
31556621Sbt150084 	if (rc != DDI_SUCCESS) {
31566621Sbt150084 		ixgbe_log(ixgbe,
31576621Sbt150084 		    "Get supported interrupt types failed: %d", rc);
31586621Sbt150084 		return (IXGBE_FAILURE);
31596621Sbt150084 	}
31606621Sbt150084 	IXGBE_DEBUGLOG_1(ixgbe, "Supported interrupt types: %x", intr_types);
31616621Sbt150084 
31626621Sbt150084 	ixgbe->intr_type = 0;
31636621Sbt150084 
31646621Sbt150084 	/*
31656621Sbt150084 	 * Install MSI-X interrupts
31666621Sbt150084 	 */
31676621Sbt150084 	if ((intr_types & DDI_INTR_TYPE_MSIX) &&
31686621Sbt150084 	    (ixgbe->intr_force <= IXGBE_INTR_MSIX)) {
31696621Sbt150084 		rc = ixgbe_alloc_intr_handles(ixgbe, DDI_INTR_TYPE_MSIX);
31706621Sbt150084 		if (rc == IXGBE_SUCCESS)
31716621Sbt150084 			return (IXGBE_SUCCESS);
31726621Sbt150084 
31736621Sbt150084 		ixgbe_log(ixgbe,
31746621Sbt150084 		    "Allocate MSI-X failed, trying MSI interrupts...");
31756621Sbt150084 	}
31766621Sbt150084 
31776621Sbt150084 	/*
31786621Sbt150084 	 * MSI-X not used, force rings to 1
31796621Sbt150084 	 */
31806621Sbt150084 	ixgbe->num_rx_rings = 1;
31816621Sbt150084 	ixgbe->num_tx_rings = 1;
31826621Sbt150084 	ixgbe_log(ixgbe,
31836621Sbt150084 	    "MSI-X not used, force rx and tx queue number to 1");
31846621Sbt150084 
31856621Sbt150084 	/*
31866621Sbt150084 	 * Install MSI interrupts
31876621Sbt150084 	 */
31886621Sbt150084 	if ((intr_types & DDI_INTR_TYPE_MSI) &&
31896621Sbt150084 	    (ixgbe->intr_force <= IXGBE_INTR_MSI)) {
31906621Sbt150084 		rc = ixgbe_alloc_intr_handles(ixgbe, DDI_INTR_TYPE_MSI);
31916621Sbt150084 		if (rc == IXGBE_SUCCESS)
31926621Sbt150084 			return (IXGBE_SUCCESS);
31936621Sbt150084 
31946621Sbt150084 		ixgbe_log(ixgbe,
31956621Sbt150084 		    "Allocate MSI failed, trying Legacy interrupts...");
31966621Sbt150084 	}
31976621Sbt150084 
31986621Sbt150084 	/*
31996621Sbt150084 	 * Install legacy interrupts
32006621Sbt150084 	 */
32016621Sbt150084 	if (intr_types & DDI_INTR_TYPE_FIXED) {
32026621Sbt150084 		rc = ixgbe_alloc_intr_handles(ixgbe, DDI_INTR_TYPE_FIXED);
32036621Sbt150084 		if (rc == IXGBE_SUCCESS)
32046621Sbt150084 			return (IXGBE_SUCCESS);
32056621Sbt150084 
32066621Sbt150084 		ixgbe_log(ixgbe,
32076621Sbt150084 		    "Allocate Legacy interrupts failed");
32086621Sbt150084 	}
32096621Sbt150084 
32106621Sbt150084 	/*
32116621Sbt150084 	 * If none of the 3 types succeeded, return failure
32126621Sbt150084 	 */
32136621Sbt150084 	return (IXGBE_FAILURE);
32146621Sbt150084 }
32156621Sbt150084 
32166621Sbt150084 /*
32176621Sbt150084  * ixgbe_alloc_intr_handles - Allocate interrupt handles.
32186621Sbt150084  *
32196621Sbt150084  * For legacy and MSI, only 1 handle is needed.  For MSI-X,
32206621Sbt150084  * if fewer than 2 handles are available, return failure.
32216621Sbt150084  * Upon success, this sets the number of Rx rings to a number that
32226621Sbt150084  * matches the handles available for Rx interrupts.
32236621Sbt150084  */
32246621Sbt150084 static int
32256621Sbt150084 ixgbe_alloc_intr_handles(ixgbe_t *ixgbe, int intr_type)
32266621Sbt150084 {
32276621Sbt150084 	dev_info_t *devinfo;
32286621Sbt150084 	int request, count, avail, actual;
32296621Sbt150084 	int rx_rings, minimum;
32306621Sbt150084 	int rc;
32316621Sbt150084 
32326621Sbt150084 	devinfo = ixgbe->dip;
32336621Sbt150084 
32346621Sbt150084 	/*
32356621Sbt150084 	 * Currently only 1 tx ring is supported. More tx rings
32366621Sbt150084 	 * will be supported with future enhancement.
32376621Sbt150084 	 */
32386621Sbt150084 	if (ixgbe->num_tx_rings > 1) {
32396621Sbt150084 		ixgbe->num_tx_rings = 1;
32406621Sbt150084 		ixgbe_log(ixgbe,
32416621Sbt150084 		    "Use only 1 MSI-X vector for tx, "
32426621Sbt150084 		    "force tx queue number to 1");
32436621Sbt150084 	}
32446621Sbt150084 
32456621Sbt150084 	switch (intr_type) {
32466621Sbt150084 	case DDI_INTR_TYPE_FIXED:
32476621Sbt150084 		request = 1;	/* Request 1 legacy interrupt handle */
32486621Sbt150084 		minimum = 1;
32496621Sbt150084 		IXGBE_DEBUGLOG_0(ixgbe, "interrupt type: legacy");
32506621Sbt150084 		break;
32516621Sbt150084 
32526621Sbt150084 	case DDI_INTR_TYPE_MSI:
32536621Sbt150084 		request = 1;	/* Request 1 MSI interrupt handle */
32546621Sbt150084 		minimum = 1;
32556621Sbt150084 		IXGBE_DEBUGLOG_0(ixgbe, "interrupt type: MSI");
32566621Sbt150084 		break;
32576621Sbt150084 
32586621Sbt150084 	case DDI_INTR_TYPE_MSIX:
32596621Sbt150084 		/*
32606621Sbt150084 		 * Best number of vectors for the adapter is
32616621Sbt150084 		 * # rx rings + # tx rings + 1 for other
32626621Sbt150084 		 * But currently we only support number of vectors of
32636621Sbt150084 		 * # rx rings + 1 for tx & other
32646621Sbt150084 		 */
32656621Sbt150084 		request = ixgbe->num_rx_rings + 1;
32666621Sbt150084 		minimum = 2;
32676621Sbt150084 		IXGBE_DEBUGLOG_0(ixgbe, "interrupt type: MSI-X");
32686621Sbt150084 		break;
32696621Sbt150084 
32706621Sbt150084 	default:
32716621Sbt150084 		ixgbe_log(ixgbe,
32726621Sbt150084 		    "invalid call to ixgbe_alloc_intr_handles(): %d\n",
32736621Sbt150084 		    intr_type);
32746621Sbt150084 		return (IXGBE_FAILURE);
32756621Sbt150084 	}
32766621Sbt150084 	IXGBE_DEBUGLOG_2(ixgbe, "interrupt handles requested: %d  minimum: %d",
32776621Sbt150084 	    request, minimum);
32786621Sbt150084 
32796621Sbt150084 	/*
32806621Sbt150084 	 * Get number of supported interrupts
32816621Sbt150084 	 */
32826621Sbt150084 	rc = ddi_intr_get_nintrs(devinfo, intr_type, &count);
32836621Sbt150084 	if ((rc != DDI_SUCCESS) || (count < minimum)) {
32846621Sbt150084 		ixgbe_log(ixgbe,
32856621Sbt150084 		    "Get interrupt number failed. Return: %d, count: %d",
32866621Sbt150084 		    rc, count);
32876621Sbt150084 		return (IXGBE_FAILURE);
32886621Sbt150084 	}
32896621Sbt150084 	IXGBE_DEBUGLOG_1(ixgbe, "interrupts supported: %d", count);
32906621Sbt150084 
32916621Sbt150084 	/*
32926621Sbt150084 	 * Get number of available interrupts
32936621Sbt150084 	 */
32946621Sbt150084 	rc = ddi_intr_get_navail(devinfo, intr_type, &avail);
32956621Sbt150084 	if ((rc != DDI_SUCCESS) || (avail < minimum)) {
32966621Sbt150084 		ixgbe_log(ixgbe,
32976621Sbt150084 		    "Get interrupt available number failed. "
32986621Sbt150084 		    "Return: %d, available: %d", rc, avail);
32996621Sbt150084 		return (IXGBE_FAILURE);
33006621Sbt150084 	}
33016621Sbt150084 	IXGBE_DEBUGLOG_1(ixgbe, "interrupts available: %d", avail);
33026621Sbt150084 
33036621Sbt150084 	if (avail < request) {
33046621Sbt150084 		ixgbe_log(ixgbe, "Request %d handles, %d available",
33056621Sbt150084 		    request, avail);
33066621Sbt150084 		request = avail;
33076621Sbt150084 	}
33086621Sbt150084 
33096621Sbt150084 	actual = 0;
33106621Sbt150084 	ixgbe->intr_cnt = 0;
33116621Sbt150084 
33126621Sbt150084 	/*
33136621Sbt150084 	 * Allocate an array of interrupt handles
33146621Sbt150084 	 */
33156621Sbt150084 	ixgbe->intr_size = request * sizeof (ddi_intr_handle_t);
33166621Sbt150084 	ixgbe->htable = kmem_alloc(ixgbe->intr_size, KM_SLEEP);
33176621Sbt150084 
33186621Sbt150084 	rc = ddi_intr_alloc(devinfo, ixgbe->htable, intr_type, 0,
33196621Sbt150084 	    request, &actual, DDI_INTR_ALLOC_NORMAL);
33206621Sbt150084 	if (rc != DDI_SUCCESS) {
33216621Sbt150084 		ixgbe_log(ixgbe, "Allocate interrupts failed. "
33226621Sbt150084 		    "return: %d, request: %d, actual: %d",
33236621Sbt150084 		    rc, request, actual);
33246621Sbt150084 		goto alloc_handle_fail;
33256621Sbt150084 	}
33266621Sbt150084 	IXGBE_DEBUGLOG_1(ixgbe, "interrupts actually allocated: %d", actual);
33276621Sbt150084 
33286621Sbt150084 	ixgbe->intr_cnt = actual;
33296621Sbt150084 
33306621Sbt150084 	/*
33316621Sbt150084 	 * Now we know the actual number of vectors.  Here we assume that
33326621Sbt150084 	 * tx and other will share 1 vector and all remaining (must be at
33336621Sbt150084 	 * least 1 remaining) will be used for rx.
33346621Sbt150084 	 */
33356621Sbt150084 	if (actual < minimum) {
33366621Sbt150084 		ixgbe_log(ixgbe, "Insufficient interrupt handles available: %d",
33376621Sbt150084 		    actual);
33386621Sbt150084 		goto alloc_handle_fail;
33396621Sbt150084 	}
33406621Sbt150084 
33416621Sbt150084 	/*
33426621Sbt150084 	 * For MSI-X, actual might force us to reduce number of rx rings
33436621Sbt150084 	 */
33446621Sbt150084 	if (intr_type == DDI_INTR_TYPE_MSIX) {
33456621Sbt150084 		rx_rings = actual - 1;
33466621Sbt150084 		if (rx_rings < ixgbe->num_rx_rings) {
33476621Sbt150084 			ixgbe_log(ixgbe,
33486621Sbt150084 			    "MSI-X vectors force Rx queue number to %d",
33496621Sbt150084 			    rx_rings);
33506621Sbt150084 			ixgbe->num_rx_rings = rx_rings;
33516621Sbt150084 		}
33526621Sbt150084 	}
33536621Sbt150084 
33546621Sbt150084 	/*
33556621Sbt150084 	 * Get priority for first vector, assume remaining are all the same
33566621Sbt150084 	 */
33576621Sbt150084 	rc = ddi_intr_get_pri(ixgbe->htable[0], &ixgbe->intr_pri);
33586621Sbt150084 	if (rc != DDI_SUCCESS) {
33596621Sbt150084 		ixgbe_log(ixgbe,
33606621Sbt150084 		    "Get interrupt priority failed: %d", rc);
33616621Sbt150084 		goto alloc_handle_fail;
33626621Sbt150084 	}
33636621Sbt150084 
33646621Sbt150084 	rc = ddi_intr_get_cap(ixgbe->htable[0], &ixgbe->intr_cap);
33656621Sbt150084 	if (rc != DDI_SUCCESS) {
33666621Sbt150084 		ixgbe_log(ixgbe,
33676621Sbt150084 		    "Get interrupt cap failed: %d", rc);
33686621Sbt150084 		goto alloc_handle_fail;
33696621Sbt150084 	}
33706621Sbt150084 
33716621Sbt150084 	ixgbe->intr_type = intr_type;
33726621Sbt150084 
33736621Sbt150084 	return (IXGBE_SUCCESS);
33746621Sbt150084 
33756621Sbt150084 alloc_handle_fail:
33766621Sbt150084 	ixgbe_rem_intrs(ixgbe);
33776621Sbt150084 
33786621Sbt150084 	return (IXGBE_FAILURE);
33796621Sbt150084 }
33806621Sbt150084 
33816621Sbt150084 /*
33826621Sbt150084  * ixgbe_add_intr_handlers - Add interrupt handlers based on the interrupt type.
33836621Sbt150084  *
33846621Sbt150084  * Before adding the interrupt handlers, the interrupt vectors have
33856621Sbt150084  * been allocated, and the rx/tx rings have also been allocated.
33866621Sbt150084  */
33876621Sbt150084 static int
33886621Sbt150084 ixgbe_add_intr_handlers(ixgbe_t *ixgbe)
33896621Sbt150084 {
33906621Sbt150084 	ixgbe_rx_ring_t *rx_ring;
33916621Sbt150084 	int vector;
33926621Sbt150084 	int rc;
33936621Sbt150084 	int i;
33946621Sbt150084 
33956621Sbt150084 	vector = 0;
33966621Sbt150084 
33976621Sbt150084 	switch (ixgbe->intr_type) {
33986621Sbt150084 	case DDI_INTR_TYPE_MSIX:
33996621Sbt150084 		/*
34006621Sbt150084 		 * Add interrupt handler for tx + other
34016621Sbt150084 		 */
34026621Sbt150084 		rc = ddi_intr_add_handler(ixgbe->htable[vector],
34036621Sbt150084 		    (ddi_intr_handler_t *)ixgbe_intr_tx_other,
34046621Sbt150084 		    (void *)ixgbe, NULL);
34056621Sbt150084 		if (rc != DDI_SUCCESS) {
34066621Sbt150084 			ixgbe_log(ixgbe,
34076621Sbt150084 			    "Add tx/other interrupt handler failed: %d", rc);
34086621Sbt150084 			return (IXGBE_FAILURE);
34096621Sbt150084 		}
34106621Sbt150084 		vector++;
34116621Sbt150084 
34126621Sbt150084 		/*
34136621Sbt150084 		 * Add interrupt handler for each rx ring
34146621Sbt150084 		 */
34156621Sbt150084 		for (i = 0; i < ixgbe->num_rx_rings; i++) {
34166621Sbt150084 			rx_ring = &ixgbe->rx_rings[i];
34176621Sbt150084 
34186621Sbt150084 			/*
34196621Sbt150084 			 * install pointer to vect_map[vector]
34206621Sbt150084 			 */
34216621Sbt150084 			rc = ddi_intr_add_handler(ixgbe->htable[vector],
34226621Sbt150084 			    (ddi_intr_handler_t *)ixgbe_intr_rx,
34236621Sbt150084 			    (void *)&ixgbe->vect_map[vector], NULL);
34246621Sbt150084 
34256621Sbt150084 			if (rc != DDI_SUCCESS) {
34266621Sbt150084 				ixgbe_log(ixgbe,
34276621Sbt150084 				    "Add rx interrupt handler failed. "
34286621Sbt150084 				    "return: %d, rx ring: %d", rc, i);
34296621Sbt150084 				for (vector--; vector >= 0; vector--) {
34306621Sbt150084 					(void) ddi_intr_remove_handler(
34316621Sbt150084 					    ixgbe->htable[vector]);
34326621Sbt150084 				}
34336621Sbt150084 				return (IXGBE_FAILURE);
34346621Sbt150084 			}
34356621Sbt150084 
34366621Sbt150084 			rx_ring->intr_vector = vector;
34376621Sbt150084 
34386621Sbt150084 			vector++;
34396621Sbt150084 		}
34406621Sbt150084 		break;
34416621Sbt150084 
34426621Sbt150084 	case DDI_INTR_TYPE_MSI:
34436621Sbt150084 		/*
34446621Sbt150084 		 * Add interrupt handlers for the only vector
34456621Sbt150084 		 */
34466621Sbt150084 		rc = ddi_intr_add_handler(ixgbe->htable[vector],
34476621Sbt150084 		    (ddi_intr_handler_t *)ixgbe_intr_msi,
34486621Sbt150084 		    (void *)ixgbe, NULL);
34496621Sbt150084 
34506621Sbt150084 		if (rc != DDI_SUCCESS) {
34516621Sbt150084 			ixgbe_log(ixgbe,
34526621Sbt150084 			    "Add MSI interrupt handler failed: %d", rc);
34536621Sbt150084 			return (IXGBE_FAILURE);
34546621Sbt150084 		}
34556621Sbt150084 
34566621Sbt150084 		rx_ring = &ixgbe->rx_rings[0];
34576621Sbt150084 		rx_ring->intr_vector = vector;
34586621Sbt150084 
34596621Sbt150084 		vector++;
34606621Sbt150084 		break;
34616621Sbt150084 
34626621Sbt150084 	case DDI_INTR_TYPE_FIXED:
34636621Sbt150084 		/*
34646621Sbt150084 		 * Add interrupt handlers for the only vector
34656621Sbt150084 		 */
34666621Sbt150084 		rc = ddi_intr_add_handler(ixgbe->htable[vector],
34676621Sbt150084 		    (ddi_intr_handler_t *)ixgbe_intr_legacy,
34686621Sbt150084 		    (void *)ixgbe, NULL);
34696621Sbt150084 
34706621Sbt150084 		if (rc != DDI_SUCCESS) {
34716621Sbt150084 			ixgbe_log(ixgbe,
34726621Sbt150084 			    "Add legacy interrupt handler failed: %d", rc);
34736621Sbt150084 			return (IXGBE_FAILURE);
34746621Sbt150084 		}
34756621Sbt150084 
34766621Sbt150084 		rx_ring = &ixgbe->rx_rings[0];
34776621Sbt150084 		rx_ring->intr_vector = vector;
34786621Sbt150084 
34796621Sbt150084 		vector++;
34806621Sbt150084 		break;
34816621Sbt150084 
34826621Sbt150084 	default:
34836621Sbt150084 		return (IXGBE_FAILURE);
34846621Sbt150084 	}
34856621Sbt150084 
34866621Sbt150084 	ASSERT(vector == ixgbe->intr_cnt);
34876621Sbt150084 
34886621Sbt150084 	return (IXGBE_SUCCESS);
34896621Sbt150084 }
34906621Sbt150084 
34916621Sbt150084 #pragma inline(ixgbe_map_rxring_to_vector)
34926621Sbt150084 /*
34936621Sbt150084  * ixgbe_map_rxring_to_vector - Map given rx ring to given interrupt vector.
34946621Sbt150084  */
34956621Sbt150084 static void
34966621Sbt150084 ixgbe_map_rxring_to_vector(ixgbe_t *ixgbe, int r_idx, int v_idx)
34976621Sbt150084 {
34986621Sbt150084 	ixgbe->vect_map[v_idx].ixgbe = ixgbe;
34996621Sbt150084 
35006621Sbt150084 	/*
35016621Sbt150084 	 * Set bit in map
35026621Sbt150084 	 */
35036621Sbt150084 	BT_SET(ixgbe->vect_map[v_idx].rx_map, r_idx);
35046621Sbt150084 
35056621Sbt150084 	/*
35066621Sbt150084 	 * Count bits set
35076621Sbt150084 	 */
35086621Sbt150084 	ixgbe->vect_map[v_idx].rxr_cnt++;
35096621Sbt150084 
35106621Sbt150084 	/*
35116621Sbt150084 	 * Remember bit position
35126621Sbt150084 	 */
35136621Sbt150084 	ixgbe->rx_rings[r_idx].vect_bit = 1 << v_idx;
35146621Sbt150084 }
35156621Sbt150084 
35166621Sbt150084 #pragma inline(ixgbe_map_txring_to_vector)
35176621Sbt150084 /*
35186621Sbt150084  * ixgbe_map_txring_to_vector - Map given tx ring to given interrupt vector.
35196621Sbt150084  */
35206621Sbt150084 static void
35216621Sbt150084 ixgbe_map_txring_to_vector(ixgbe_t *ixgbe, int t_idx, int v_idx)
35226621Sbt150084 {
35236621Sbt150084 	ixgbe->vect_map[v_idx].ixgbe = ixgbe;
35246621Sbt150084 
35256621Sbt150084 	/*
35266621Sbt150084 	 * Set bit in map
35276621Sbt150084 	 */
35286621Sbt150084 	BT_SET(ixgbe->vect_map[v_idx].tx_map, t_idx);
35296621Sbt150084 
35306621Sbt150084 	/*
35316621Sbt150084 	 * Count bits set
35326621Sbt150084 	 */
35336621Sbt150084 	ixgbe->vect_map[v_idx].txr_cnt++;
35346621Sbt150084 
35356621Sbt150084 	/*
35366621Sbt150084 	 * Remember bit position
35376621Sbt150084 	 */
35386621Sbt150084 	ixgbe->tx_rings[t_idx].vect_bit = 1 << v_idx;
35396621Sbt150084 }
35406621Sbt150084 
35416621Sbt150084 /*
35426621Sbt150084  * ixgbe_set_ivar - Set the given entry in the given interrupt vector
35436621Sbt150084  * allocation register (IVAR).
35446621Sbt150084  */
35456621Sbt150084 static void
35466621Sbt150084 ixgbe_set_ivar(ixgbe_t *ixgbe, uint16_t int_alloc_entry, uint8_t msix_vector)
35476621Sbt150084 {
35486621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
35496621Sbt150084 	u32 ivar, index;
35506621Sbt150084 
35516621Sbt150084 	msix_vector |= IXGBE_IVAR_ALLOC_VAL;
35526621Sbt150084 	index = (int_alloc_entry >> 2) & 0x1F;
35536621Sbt150084 	ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(index));
35546621Sbt150084 	ivar &= ~(0xFF << (8 * (int_alloc_entry & 0x3)));
35556621Sbt150084 	ivar |= (msix_vector << (8 * (int_alloc_entry & 0x3)));
35566621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_IVAR(index), ivar);
35576621Sbt150084 }
35586621Sbt150084 
35596621Sbt150084 /*
35606621Sbt150084  * ixgbe_map_rings_to_vectors - Map descriptor rings to interrupt vectors.
35616621Sbt150084  *
35626621Sbt150084  * For msi-x, this currently implements only the scheme which is
35636621Sbt150084  * 1 vector for tx + other, 1 vector for each rx ring.
35646621Sbt150084  */
35656621Sbt150084 static int
35666621Sbt150084 ixgbe_map_rings_to_vectors(ixgbe_t *ixgbe)
35676621Sbt150084 {
35686621Sbt150084 	int i, vector = 0;
35696621Sbt150084 	int vect_remain = ixgbe->intr_cnt;
35706621Sbt150084 
35716621Sbt150084 	/* initialize vector map */
35726621Sbt150084 	bzero(&ixgbe->vect_map, sizeof (ixgbe->vect_map));
35736621Sbt150084 
35746621Sbt150084 	/*
35756621Sbt150084 	 * non-MSI-X case is very simple: all interrupts on vector 0
35766621Sbt150084 	 */
35776621Sbt150084 	if (ixgbe->intr_type != DDI_INTR_TYPE_MSIX) {
35786621Sbt150084 		ixgbe_map_rxring_to_vector(ixgbe, 0, 0);
35796621Sbt150084 		ixgbe_map_txring_to_vector(ixgbe, 0, 0);
35806621Sbt150084 		return (IXGBE_SUCCESS);
35816621Sbt150084 	}
35826621Sbt150084 
35836621Sbt150084 	/*
35846621Sbt150084 	 * Ring/vector mapping for MSI-X
35856621Sbt150084 	 */
35866621Sbt150084 
35876621Sbt150084 	/*
35886621Sbt150084 	 * Map vector 0 to tx
35896621Sbt150084 	 */
35906621Sbt150084 	ixgbe_map_txring_to_vector(ixgbe, 0, vector++);
35916621Sbt150084 	vect_remain--;
35926621Sbt150084 
35936621Sbt150084 	/*
35946621Sbt150084 	 * Map remaining vectors to rx rings
35956621Sbt150084 	 */
35966621Sbt150084 	for (i = 0; i < vect_remain; i++) {
35976621Sbt150084 		ixgbe_map_rxring_to_vector(ixgbe, i, vector++);
35986621Sbt150084 	}
35996621Sbt150084 
36006621Sbt150084 	return (IXGBE_SUCCESS);
36016621Sbt150084 }
36026621Sbt150084 
36036621Sbt150084 /*
36046621Sbt150084  * ixgbe_setup_adapter_vector - Setup the adapter interrupt vector(s).
36056621Sbt150084  *
36066621Sbt150084  * This relies on queue/vector mapping already set up in the
36076621Sbt150084  * vect_map[] structures
36086621Sbt150084  */
36096621Sbt150084 static void
36106621Sbt150084 ixgbe_setup_adapter_vector(ixgbe_t *ixgbe)
36116621Sbt150084 {
36126621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
36136621Sbt150084 	ixgbe_ring_vector_t	*vect;	/* vector bitmap */
36146621Sbt150084 	int			r_idx;	/* ring index */
36156621Sbt150084 	int			v_idx;	/* vector index */
36166621Sbt150084 
36176621Sbt150084 	/*
36186621Sbt150084 	 * Clear any previous entries
36196621Sbt150084 	 */
36206621Sbt150084 	for (v_idx = 0; v_idx < IXGBE_IVAR_REG_NUM; v_idx++)
36216621Sbt150084 		IXGBE_WRITE_REG(hw, IXGBE_IVAR(v_idx), 0);
36226621Sbt150084 
36236621Sbt150084 	/*
36246621Sbt150084 	 * "Other" is always on vector 0
36256621Sbt150084 	 */
36266621Sbt150084 	ixgbe_set_ivar(ixgbe, IXGBE_IVAR_OTHER_CAUSES_INDEX, 0);
36276621Sbt150084 
36286621Sbt150084 	/*
36296621Sbt150084 	 * For each interrupt vector, populate the IVAR table
36306621Sbt150084 	 */
36316621Sbt150084 	for (v_idx = 0; v_idx < ixgbe->intr_cnt; v_idx++) {
36326621Sbt150084 		vect = &ixgbe->vect_map[v_idx];
36336621Sbt150084 
36346621Sbt150084 		/*
36356621Sbt150084 		 * For each rx ring bit set
36366621Sbt150084 		 */
36376621Sbt150084 		r_idx = bt_getlowbit(vect->rx_map, 0,
36386621Sbt150084 		    (ixgbe->num_rx_rings - 1));
36396621Sbt150084 
36406621Sbt150084 		while (r_idx >= 0) {
36416621Sbt150084 			ixgbe_set_ivar(ixgbe, IXGBE_IVAR_RX_QUEUE(r_idx),
36426621Sbt150084 			    v_idx);
36436621Sbt150084 			r_idx = bt_getlowbit(vect->rx_map, (r_idx + 1),
36446621Sbt150084 			    (ixgbe->num_rx_rings - 1));
36456621Sbt150084 		}
36466621Sbt150084 
36476621Sbt150084 		/*
36486621Sbt150084 		 * For each tx ring bit set
36496621Sbt150084 		 */
36506621Sbt150084 		r_idx = bt_getlowbit(vect->tx_map, 0,
36516621Sbt150084 		    (ixgbe->num_tx_rings - 1));
36526621Sbt150084 
36536621Sbt150084 		while (r_idx >= 0) {
36546621Sbt150084 			ixgbe_set_ivar(ixgbe, IXGBE_IVAR_TX_QUEUE(r_idx),
36556621Sbt150084 			    v_idx);
36566621Sbt150084 			r_idx = bt_getlowbit(vect->tx_map, (r_idx + 1),
36576621Sbt150084 			    (ixgbe->num_tx_rings - 1));
36586621Sbt150084 		}
36596621Sbt150084 	}
36606621Sbt150084 }
36616621Sbt150084 
36626621Sbt150084 /*
36636621Sbt150084  * ixgbe_rem_intr_handlers - Remove the interrupt handlers.
36646621Sbt150084  */
36656621Sbt150084 static void
36666621Sbt150084 ixgbe_rem_intr_handlers(ixgbe_t *ixgbe)
36676621Sbt150084 {
36686621Sbt150084 	int i;
36696621Sbt150084 	int rc;
36706621Sbt150084 
36716621Sbt150084 	for (i = 0; i < ixgbe->intr_cnt; i++) {
36726621Sbt150084 		rc = ddi_intr_remove_handler(ixgbe->htable[i]);
36736621Sbt150084 		if (rc != DDI_SUCCESS) {
36746621Sbt150084 			IXGBE_DEBUGLOG_1(ixgbe,
36756621Sbt150084 			    "Remove intr handler failed: %d", rc);
36766621Sbt150084 		}
36776621Sbt150084 	}
36786621Sbt150084 }
36796621Sbt150084 
36806621Sbt150084 /*
36816621Sbt150084  * ixgbe_rem_intrs - Remove the allocated interrupts.
36826621Sbt150084  */
36836621Sbt150084 static void
36846621Sbt150084 ixgbe_rem_intrs(ixgbe_t *ixgbe)
36856621Sbt150084 {
36866621Sbt150084 	int i;
36876621Sbt150084 	int rc;
36886621Sbt150084 
36896621Sbt150084 	for (i = 0; i < ixgbe->intr_cnt; i++) {
36906621Sbt150084 		rc = ddi_intr_free(ixgbe->htable[i]);
36916621Sbt150084 		if (rc != DDI_SUCCESS) {
36926621Sbt150084 			IXGBE_DEBUGLOG_1(ixgbe,
36936621Sbt150084 			    "Free intr failed: %d", rc);
36946621Sbt150084 		}
36956621Sbt150084 	}
36966621Sbt150084 
36976621Sbt150084 	kmem_free(ixgbe->htable, ixgbe->intr_size);
36986621Sbt150084 	ixgbe->htable = NULL;
36996621Sbt150084 }
37006621Sbt150084 
37016621Sbt150084 /*
37026621Sbt150084  * ixgbe_enable_intrs - Enable all the ddi interrupts.
37036621Sbt150084  */
37046621Sbt150084 static int
37056621Sbt150084 ixgbe_enable_intrs(ixgbe_t *ixgbe)
37066621Sbt150084 {
37076621Sbt150084 	int i;
37086621Sbt150084 	int rc;
37096621Sbt150084 
37106621Sbt150084 	/*
37116621Sbt150084 	 * Enable interrupts
37126621Sbt150084 	 */
37136621Sbt150084 	if (ixgbe->intr_cap & DDI_INTR_FLAG_BLOCK) {
37146621Sbt150084 		/*
37156621Sbt150084 		 * Call ddi_intr_block_enable() for MSI
37166621Sbt150084 		 */
37176621Sbt150084 		rc = ddi_intr_block_enable(ixgbe->htable, ixgbe->intr_cnt);
37186621Sbt150084 		if (rc != DDI_SUCCESS) {
37196621Sbt150084 			ixgbe_log(ixgbe,
37206621Sbt150084 			    "Enable block intr failed: %d", rc);
37216621Sbt150084 			return (IXGBE_FAILURE);
37226621Sbt150084 		}
37236621Sbt150084 	} else {
37246621Sbt150084 		/*
37256621Sbt150084 		 * Call ddi_intr_enable() for Legacy/MSI non block enable
37266621Sbt150084 		 */
37276621Sbt150084 		for (i = 0; i < ixgbe->intr_cnt; i++) {
37286621Sbt150084 			rc = ddi_intr_enable(ixgbe->htable[i]);
37296621Sbt150084 			if (rc != DDI_SUCCESS) {
37306621Sbt150084 				ixgbe_log(ixgbe,
37316621Sbt150084 				    "Enable intr failed: %d", rc);
37326621Sbt150084 				return (IXGBE_FAILURE);
37336621Sbt150084 			}
37346621Sbt150084 		}
37356621Sbt150084 	}
37366621Sbt150084 
37376621Sbt150084 	return (IXGBE_SUCCESS);
37386621Sbt150084 }
37396621Sbt150084 
37406621Sbt150084 /*
37416621Sbt150084  * ixgbe_disable_intrs - Disable all the interrupts.
37426621Sbt150084  */
37436621Sbt150084 static int
37446621Sbt150084 ixgbe_disable_intrs(ixgbe_t *ixgbe)
37456621Sbt150084 {
37466621Sbt150084 	int i;
37476621Sbt150084 	int rc;
37486621Sbt150084 
37496621Sbt150084 	/*
37506621Sbt150084 	 * Disable all interrupts
37516621Sbt150084 	 */
37526621Sbt150084 	if (ixgbe->intr_cap & DDI_INTR_FLAG_BLOCK) {
37536621Sbt150084 		rc = ddi_intr_block_disable(ixgbe->htable, ixgbe->intr_cnt);
37546621Sbt150084 		if (rc != DDI_SUCCESS) {
37556621Sbt150084 			ixgbe_log(ixgbe,
37566621Sbt150084 			    "Disable block intr failed: %d", rc);
37576621Sbt150084 			return (IXGBE_FAILURE);
37586621Sbt150084 		}
37596621Sbt150084 	} else {
37606621Sbt150084 		for (i = 0; i < ixgbe->intr_cnt; i++) {
37616621Sbt150084 			rc = ddi_intr_disable(ixgbe->htable[i]);
37626621Sbt150084 			if (rc != DDI_SUCCESS) {
37636621Sbt150084 				ixgbe_log(ixgbe,
37646621Sbt150084 				    "Disable intr failed: %d", rc);
37656621Sbt150084 				return (IXGBE_FAILURE);
37666621Sbt150084 			}
37676621Sbt150084 		}
37686621Sbt150084 	}
37696621Sbt150084 
37706621Sbt150084 	return (IXGBE_SUCCESS);
37716621Sbt150084 }
37726621Sbt150084 
37736621Sbt150084 /*
37746621Sbt150084  * ixgbe_get_hw_state - Get and save parameters related to adapter hardware.
37756621Sbt150084  */
37766621Sbt150084 static void
37776621Sbt150084 ixgbe_get_hw_state(ixgbe_t *ixgbe)
37786621Sbt150084 {
37796621Sbt150084 	struct ixgbe_hw *hw = &ixgbe->hw;
37806621Sbt150084 	uint32_t links;
37816621Sbt150084 	uint32_t pcs1g_anlp = 0;
37826621Sbt150084 	uint32_t pcs1g_ana = 0;
37836621Sbt150084 
37846621Sbt150084 	ASSERT(mutex_owned(&ixgbe->gen_lock));
37856621Sbt150084 	ixgbe->param_lp_1000fdx_cap = 0;
37866621Sbt150084 	ixgbe->param_lp_100fdx_cap  = 0;
37876621Sbt150084 
37886621Sbt150084 	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
37896621Sbt150084 	if (links & IXGBE_LINKS_PCS_1G_EN) {
37906621Sbt150084 		pcs1g_anlp = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
37916621Sbt150084 		pcs1g_ana = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
37926621Sbt150084 
37936621Sbt150084 		ixgbe->param_lp_1000fdx_cap =
37946621Sbt150084 		    (pcs1g_anlp & IXGBE_PCS1GANLP_LPFD) ? 1 : 0;
37956621Sbt150084 		ixgbe->param_lp_100fdx_cap =
37966621Sbt150084 		    (pcs1g_anlp & IXGBE_PCS1GANLP_LPFD) ? 1 : 0;
37976621Sbt150084 	}
37986621Sbt150084 
37996621Sbt150084 	ixgbe->param_1000fdx_cap = (pcs1g_ana & IXGBE_PCS1GANA_FDC)  ? 1 : 0;
38006621Sbt150084 	ixgbe->param_100fdx_cap = (pcs1g_ana & IXGBE_PCS1GANA_FDC)  ? 1 : 0;
38016621Sbt150084 }
38026621Sbt150084 
38036621Sbt150084 /*
38046621Sbt150084  * ixgbe_get_driver_control - Notify that driver is in control of device.
38056621Sbt150084  */
38066621Sbt150084 static void
38076621Sbt150084 ixgbe_get_driver_control(struct ixgbe_hw *hw)
38086621Sbt150084 {
38096621Sbt150084 	uint32_t ctrl_ext;
38106621Sbt150084 
38116621Sbt150084 	/*
38126621Sbt150084 	 * Notify firmware that driver is in control of device
38136621Sbt150084 	 */
38146621Sbt150084 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
38156621Sbt150084 	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
38166621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
38176621Sbt150084 }
38186621Sbt150084 
38196621Sbt150084 /*
38206621Sbt150084  * ixgbe_release_driver_control - Notify that driver is no longer in control
38216621Sbt150084  * of device.
38226621Sbt150084  */
38236621Sbt150084 static void
38246621Sbt150084 ixgbe_release_driver_control(struct ixgbe_hw *hw)
38256621Sbt150084 {
38266621Sbt150084 	uint32_t ctrl_ext;
38276621Sbt150084 
38286621Sbt150084 	/*
38296621Sbt150084 	 * Notify firmware that driver is no longer in control of device
38306621Sbt150084 	 */
38316621Sbt150084 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
38326621Sbt150084 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
38336621Sbt150084 	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
38346621Sbt150084 }
38356621Sbt150084 
38366621Sbt150084 /*
38376621Sbt150084  * ixgbe_atomic_reserve - Atomic decrease operation.
38386621Sbt150084  */
38396621Sbt150084 int
38406621Sbt150084 ixgbe_atomic_reserve(uint32_t *count_p, uint32_t n)
38416621Sbt150084 {
38426621Sbt150084 	uint32_t oldval;
38436621Sbt150084 	uint32_t newval;
38446621Sbt150084 
38456621Sbt150084 	/*
38466621Sbt150084 	 * ATOMICALLY
38476621Sbt150084 	 */
38486621Sbt150084 	do {
38496621Sbt150084 		oldval = *count_p;
38506621Sbt150084 		if (oldval < n)
38516621Sbt150084 			return (-1);
38526621Sbt150084 		newval = oldval - n;
38536621Sbt150084 	} while (atomic_cas_32(count_p, oldval, newval) != oldval);
38546621Sbt150084 
38556621Sbt150084 	return (newval);
38566621Sbt150084 }
38576621Sbt150084 
38586621Sbt150084 /*
38596621Sbt150084  * ixgbe_mc_table_itr - Traverse the entries in the multicast table.
38606621Sbt150084  */
38616621Sbt150084 static uint8_t *
38626621Sbt150084 ixgbe_mc_table_itr(struct ixgbe_hw *hw, uint8_t **upd_ptr, uint32_t *vmdq)
38636621Sbt150084 {
38646621Sbt150084 	_NOTE(ARGUNUSED(hw));
38656621Sbt150084 	_NOTE(ARGUNUSED(vmdq));
38666621Sbt150084 	uint8_t *addr = *upd_ptr;
38676621Sbt150084 	uint8_t *new_ptr;
38686621Sbt150084 
38696621Sbt150084 	new_ptr = addr + IXGBE_ETH_LENGTH_OF_ADDRESS;
38706621Sbt150084 	*upd_ptr = new_ptr;
38716621Sbt150084 	return (addr);
38726621Sbt150084 }
38736621Sbt150084 
38746621Sbt150084 /*
38756621Sbt150084  * FMA support
38766621Sbt150084  */
38776621Sbt150084 int
38786621Sbt150084 ixgbe_check_acc_handle(ddi_acc_handle_t handle)
38796621Sbt150084 {
38806621Sbt150084 	ddi_fm_error_t de;
38816621Sbt150084 
38826621Sbt150084 	ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
38836621Sbt150084 	ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
38846621Sbt150084 	return (de.fme_status);
38856621Sbt150084 }
38866621Sbt150084 
38876621Sbt150084 int
38886621Sbt150084 ixgbe_check_dma_handle(ddi_dma_handle_t handle)
38896621Sbt150084 {
38906621Sbt150084 	ddi_fm_error_t de;
38916621Sbt150084 
38926621Sbt150084 	ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
38936621Sbt150084 	return (de.fme_status);
38946621Sbt150084 }
38956621Sbt150084 
38966621Sbt150084 /*
38976621Sbt150084  * ixgbe_fm_error_cb - The IO fault service error handling callback function.
38986621Sbt150084  */
38996621Sbt150084 static int
39006621Sbt150084 ixgbe_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
39016621Sbt150084 {
39026621Sbt150084 	_NOTE(ARGUNUSED(impl_data));
39036621Sbt150084 	/*
39046621Sbt150084 	 * as the driver can always deal with an error in any dma or
39056621Sbt150084 	 * access handle, we can just return the fme_status value.
39066621Sbt150084 	 */
39076621Sbt150084 	pci_ereport_post(dip, err, NULL);
39086621Sbt150084 	return (err->fme_status);
39096621Sbt150084 }
39106621Sbt150084 
39116621Sbt150084 static void
39126621Sbt150084 ixgbe_fm_init(ixgbe_t *ixgbe)
39136621Sbt150084 {
39146621Sbt150084 	ddi_iblock_cookie_t iblk;
39156621Sbt150084 	int fma_acc_flag, fma_dma_flag;
39166621Sbt150084 
39176621Sbt150084 	/*
39186621Sbt150084 	 * Only register with IO Fault Services if we have some capability
39196621Sbt150084 	 */
39206621Sbt150084 	if (ixgbe->fm_capabilities & DDI_FM_ACCCHK_CAPABLE) {
39216621Sbt150084 		ixgbe_regs_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
39226621Sbt150084 		fma_acc_flag = 1;
39236621Sbt150084 	} else {
39246621Sbt150084 		ixgbe_regs_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
39256621Sbt150084 		fma_acc_flag = 0;
39266621Sbt150084 	}
39276621Sbt150084 
39286621Sbt150084 	if (ixgbe->fm_capabilities & DDI_FM_DMACHK_CAPABLE) {
39296621Sbt150084 		fma_dma_flag = 1;
39306621Sbt150084 	} else {
39316621Sbt150084 		fma_dma_flag = 0;
39326621Sbt150084 	}
39336621Sbt150084 
39346621Sbt150084 	ixgbe_set_fma_flags(fma_acc_flag, fma_dma_flag);
39356621Sbt150084 
39366621Sbt150084 	if (ixgbe->fm_capabilities) {
39376621Sbt150084 
39386621Sbt150084 		/*
39396621Sbt150084 		 * Register capabilities with IO Fault Services
39406621Sbt150084 		 */
39416621Sbt150084 		ddi_fm_init(ixgbe->dip, &ixgbe->fm_capabilities, &iblk);
39426621Sbt150084 
39436621Sbt150084 		/*
39446621Sbt150084 		 * Initialize pci ereport capabilities if ereport capable
39456621Sbt150084 		 */
39466621Sbt150084 		if (DDI_FM_EREPORT_CAP(ixgbe->fm_capabilities) ||
39476621Sbt150084 		    DDI_FM_ERRCB_CAP(ixgbe->fm_capabilities))
39486621Sbt150084 			pci_ereport_setup(ixgbe->dip);
39496621Sbt150084 
39506621Sbt150084 		/*
39516621Sbt150084 		 * Register error callback if error callback capable
39526621Sbt150084 		 */
39536621Sbt150084 		if (DDI_FM_ERRCB_CAP(ixgbe->fm_capabilities))
39546621Sbt150084 			ddi_fm_handler_register(ixgbe->dip,
39556621Sbt150084 			    ixgbe_fm_error_cb, (void*) ixgbe);
39566621Sbt150084 	}
39576621Sbt150084 }
39586621Sbt150084 
39596621Sbt150084 static void
39606621Sbt150084 ixgbe_fm_fini(ixgbe_t *ixgbe)
39616621Sbt150084 {
39626621Sbt150084 	/*
39636621Sbt150084 	 * Only unregister FMA capabilities if they are registered
39646621Sbt150084 	 */
39656621Sbt150084 	if (ixgbe->fm_capabilities) {
39666621Sbt150084 
39676621Sbt150084 		/*
39686621Sbt150084 		 * Release any resources allocated by pci_ereport_setup()
39696621Sbt150084 		 */
39706621Sbt150084 		if (DDI_FM_EREPORT_CAP(ixgbe->fm_capabilities) ||
39716621Sbt150084 		    DDI_FM_ERRCB_CAP(ixgbe->fm_capabilities))
39726621Sbt150084 			pci_ereport_teardown(ixgbe->dip);
39736621Sbt150084 
39746621Sbt150084 		/*
39756621Sbt150084 		 * Un-register error callback if error callback capable
39766621Sbt150084 		 */
39776621Sbt150084 		if (DDI_FM_ERRCB_CAP(ixgbe->fm_capabilities))
39786621Sbt150084 			ddi_fm_handler_unregister(ixgbe->dip);
39796621Sbt150084 
39806621Sbt150084 		/*
39816621Sbt150084 		 * Unregister from IO Fault Service
39826621Sbt150084 		 */
39836621Sbt150084 		ddi_fm_fini(ixgbe->dip);
39846621Sbt150084 	}
39856621Sbt150084 }
39866621Sbt150084 
39876621Sbt150084 void
39886621Sbt150084 ixgbe_fm_ereport(ixgbe_t *ixgbe, char *detail)
39896621Sbt150084 {
39906621Sbt150084 	uint64_t ena;
39916621Sbt150084 	char buf[FM_MAX_CLASS];
39926621Sbt150084 
39936621Sbt150084 	(void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
39946621Sbt150084 	ena = fm_ena_generate(0, FM_ENA_FMT1);
39956621Sbt150084 	if (DDI_FM_EREPORT_CAP(ixgbe->fm_capabilities)) {
39966621Sbt150084 		ddi_fm_ereport_post(ixgbe->dip, buf, ena, DDI_NOSLEEP,
39976621Sbt150084 		    FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
39986621Sbt150084 	}
39996621Sbt150084 }
4000