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