Print this page
9095 ixgbe MAC_CAPAB_LED support
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Sebastian Wiedenroth <sebastian.wiedenroth@skylime.net>
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Dan McDonald <danmcd@joyent.com>
NEX-2081 ixgbe triggers warning when receiving too many interrupt vectors from DDI
SUP-479 10 Gigabit CX4 Dual Port Server Adapter EXPX9502CX4 unresponsive to external pings after upgrade from 3.1.2 to 3.1.3.5

*** 24,34 **** */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Joyent, Inc. ! * Copyright 2012 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2013 OSN Online Service Nuernberg GmbH. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. */ --- 24,34 ---- */ /* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, Joyent, Inc. ! * Copyright 2013 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2013 Saso Kiselkov. All rights reserved. * Copyright (c) 2013 OSN Online Service Nuernberg GmbH. All rights reserved. * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. */
*** 491,508 **** */ ixgbe_init_properties(ixgbe); ixgbe->attach_progress |= ATTACH_PROGRESS_PROPS; /* - * Register interrupt callback - */ - if (ixgbe_intr_cb_register(ixgbe) != IXGBE_SUCCESS) { - ixgbe_error(ixgbe, "Failed to register interrupt callback"); - goto attach_fail; - } - - /* * Allocate interrupts */ if (ixgbe_alloc_intrs(ixgbe) != IXGBE_SUCCESS) { ixgbe_error(ixgbe, "Failed to allocate interrupts"); goto attach_fail; --- 491,500 ----
*** 648,657 **** --- 640,658 ---- ixgbe->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; ixgbe_log(ixgbe, "%s", ixgbe_ident); atomic_or_32(&ixgbe->ixgbe_state, IXGBE_INITIALIZED); + /* + * Register interrupt callback + */ + if (ixgbe->intr_type == DDI_INTR_TYPE_MSIX) + if (ixgbe_intr_cb_register(ixgbe) != IXGBE_SUCCESS) { + ixgbe_error(ixgbe, + "Failed to register interrupt callback"); + } + return (DDI_SUCCESS); attach_fail: ixgbe_unconfigure(devinfo, ixgbe); return (DDI_FAILURE);
*** 776,785 **** --- 777,792 ---- static void ixgbe_unconfigure(dev_info_t *devinfo, ixgbe_t *ixgbe) { /* + * Unregister interrupt callback handler + */ + if (ixgbe->cb_hdl != NULL) + (void) ddi_cb_unregister(ixgbe->cb_hdl); + + /* * Disable interrupt */ if (ixgbe->attach_progress & ATTACH_PROGRESS_ENABLE_INTR) { (void) ixgbe_disable_intrs(ixgbe); }
*** 1239,1248 **** --- 1246,1291 ---- mutex_destroy(&ixgbe->gen_lock); mutex_destroy(&ixgbe->watchdog_lock); } + /* + * We need to try and determine which LED index in hardware corresponds to the + * link/activity LED. This is the one that'll be overwritten when we perform + * GLDv3 LED activity. + */ + static void + ixgbe_led_init(ixgbe_t *ixgbe) + { + uint32_t reg, i; + struct ixgbe_hw *hw = &ixgbe->hw; + + reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL); + for (i = 0; i < 4; i++) { + if (((reg >> IXGBE_LED_MODE_SHIFT(i)) & + IXGBE_LED_MODE_MASK_BASE) == IXGBE_LED_LINK_ACTIVE) { + ixgbe->ixgbe_led_index = i; + return; + } + } + + /* + * If we couldn't determine this, we use the default for various MACs + * based on information Intel has inserted into other drivers over the + * years. Note, when we have support for the X553 which should add the + * ixgbe_x550_em_a mac type, that should be at index 0. + */ + switch (hw->mac.type) { + case ixgbe_mac_X550EM_x: + ixgbe->ixgbe_led_index = 1; + break; + default: + ixgbe->ixgbe_led_index = 2; + break; + } + } + static int ixgbe_resume(dev_info_t *devinfo) { ixgbe_t *ixgbe; int i;
*** 1393,1404 **** /* * Setup default flow control thresholds - enable/disable * & flow control type is controlled by ixgbe.conf */ ! hw->fc.high_water[0] = DEFAULT_FCRTH; ! hw->fc.low_water[0] = DEFAULT_FCRTL; hw->fc.pause_time = DEFAULT_FCPAUSE; hw->fc.send_xon = B_TRUE; /* * Initialize flow control --- 1436,1464 ---- /* * Setup default flow control thresholds - enable/disable * & flow control type is controlled by ixgbe.conf */ ! { ! uint32_t rxpb, frame, size, hitmp, lotmp; ! ! frame = ixgbe->max_frame_size; ! ! /* Calculate High and Low Water */ ! if (hw->mac.type == ixgbe_mac_X540) { ! hitmp = IXGBE_DV_X540(frame, frame); ! lotmp = IXGBE_LOW_DV_X540(frame); ! } else { ! hitmp = IXGBE_DV(frame, frame); ! lotmp = IXGBE_LOW_DV(frame); ! } ! size = IXGBE_BT2KB(hitmp); ! rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10; ! hw->fc.high_water[0] = rxpb - size; ! hw->fc.low_water[0] = IXGBE_BT2KB(lotmp); ! } ! hw->fc.pause_time = DEFAULT_FCPAUSE; hw->fc.send_xon = B_TRUE; /* * Initialize flow control
*** 1426,1435 **** --- 1486,1500 ---- if (*pbanum != '\0') { (void) ddi_prop_update_string(DDI_DEV_T_NONE, ixgbe->dip, "printed-board-assembly", (char *)pbanum); } + /* + * Determine LED index. + */ + ixgbe_led_init(ixgbe); + if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) { goto init_fail; } mutex_exit(&ixgbe->gen_lock);
*** 1990,2024 **** */ static int ixgbe_intr_adjust(ixgbe_t *ixgbe, ddi_cb_action_t cbaction, int count) { int i, rc, actual; ! if (count == 0) ! return (DDI_SUCCESS); ! ! if ((cbaction == DDI_CB_INTR_ADD && ! ixgbe->intr_cnt + count > ixgbe->intr_cnt_max) || ! (cbaction == DDI_CB_INTR_REMOVE && ! ixgbe->intr_cnt - count < ixgbe->intr_cnt_min)) return (DDI_FAILURE); ! if (!(ixgbe->ixgbe_state & IXGBE_STARTED)) { return (DDI_FAILURE); - } for (i = 0; i < ixgbe->num_rx_rings; i++) mac_ring_intr_set(ixgbe->rx_rings[i].ring_handle, NULL); for (i = 0; i < ixgbe->num_tx_rings; i++) mac_ring_intr_set(ixgbe->tx_rings[i].ring_handle, NULL); mutex_enter(&ixgbe->gen_lock); ixgbe->ixgbe_state &= ~IXGBE_STARTED; ixgbe->ixgbe_state |= IXGBE_INTR_ADJUST; ixgbe->ixgbe_state |= IXGBE_SUSPENDED; mac_link_update(ixgbe->mac_hdl, LINK_STATE_UNKNOWN); ixgbe_stop(ixgbe, B_FALSE); /* * Disable interrupts */ if (ixgbe->attach_progress & ATTACH_PROGRESS_ENABLE_INTR) { --- 2055,2094 ---- */ static int ixgbe_intr_adjust(ixgbe_t *ixgbe, ddi_cb_action_t cbaction, int count) { int i, rc, actual; + uint32_t started; ! if (!(ixgbe->ixgbe_state & IXGBE_INITIALIZED)) { return (DDI_FAILURE); + } ! if (cbaction == DDI_CB_INTR_REMOVE && ! ixgbe->intr_cnt - count < ixgbe->intr_cnt_min) return (DDI_FAILURE); + if (cbaction == DDI_CB_INTR_ADD && + ixgbe->intr_cnt + count > ixgbe->intr_cnt_max) + count = ixgbe->intr_cnt_max - ixgbe->intr_cnt; + + if (count == 0) + return (DDI_SUCCESS); + for (i = 0; i < ixgbe->num_rx_rings; i++) mac_ring_intr_set(ixgbe->rx_rings[i].ring_handle, NULL); for (i = 0; i < ixgbe->num_tx_rings; i++) mac_ring_intr_set(ixgbe->tx_rings[i].ring_handle, NULL); mutex_enter(&ixgbe->gen_lock); + started = ixgbe->ixgbe_state & IXGBE_STARTED; ixgbe->ixgbe_state &= ~IXGBE_STARTED; ixgbe->ixgbe_state |= IXGBE_INTR_ADJUST; ixgbe->ixgbe_state |= IXGBE_SUSPENDED; mac_link_update(ixgbe->mac_hdl, LINK_STATE_UNKNOWN); + if (started) ixgbe_stop(ixgbe, B_FALSE); /* * Disable interrupts */ if (ixgbe->attach_progress & ATTACH_PROGRESS_ENABLE_INTR) {
*** 2110,2126 **** if (ixgbe_enable_intrs(ixgbe) != IXGBE_SUCCESS) { ixgbe_error(ixgbe, "IRM CB: Failed to enable DDI interrupts"); goto intr_adjust_fail; } ixgbe->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; if (ixgbe_start(ixgbe, B_FALSE) != IXGBE_SUCCESS) { ixgbe_error(ixgbe, "IRM CB: Failed to start"); goto intr_adjust_fail; } ixgbe->ixgbe_state &= ~IXGBE_INTR_ADJUST; ixgbe->ixgbe_state &= ~IXGBE_SUSPENDED; ! ixgbe->ixgbe_state |= IXGBE_STARTED; mutex_exit(&ixgbe->gen_lock); for (i = 0; i < ixgbe->num_rx_rings; i++) { mac_ring_intr_set(ixgbe->rx_rings[i].ring_handle, ixgbe->htable[ixgbe->rx_rings[i].intr_vector]); --- 2180,2197 ---- if (ixgbe_enable_intrs(ixgbe) != IXGBE_SUCCESS) { ixgbe_error(ixgbe, "IRM CB: Failed to enable DDI interrupts"); goto intr_adjust_fail; } ixgbe->attach_progress |= ATTACH_PROGRESS_ENABLE_INTR; + if (started) if (ixgbe_start(ixgbe, B_FALSE) != IXGBE_SUCCESS) { ixgbe_error(ixgbe, "IRM CB: Failed to start"); goto intr_adjust_fail; } ixgbe->ixgbe_state &= ~IXGBE_INTR_ADJUST; ixgbe->ixgbe_state &= ~IXGBE_SUSPENDED; ! ixgbe->ixgbe_state |= started; mutex_exit(&ixgbe->gen_lock); for (i = 0; i < ixgbe->num_rx_rings; i++) { mac_ring_intr_set(ixgbe->rx_rings[i].ring_handle, ixgbe->htable[ixgbe->rx_rings[i].intr_vector]);
*** 3675,3691 **** (void) ixgbe_check_link(hw, &speed, &link_up, B_FALSE); if (link_up) { ixgbe->link_check_complete = B_TRUE; - /* Link is up, enable flow control settings */ - (void) ixgbe_fc_enable(hw); - /* * The Link is up, check whether it was marked as down earlier */ if (ixgbe->link_state != LINK_STATE_UP) { switch (speed) { case IXGBE_LINK_SPEED_10GB_FULL: ixgbe->link_speed = SPEED_10GB; break; case IXGBE_LINK_SPEED_5GB_FULL: --- 3746,3763 ---- (void) ixgbe_check_link(hw, &speed, &link_up, B_FALSE); if (link_up) { ixgbe->link_check_complete = B_TRUE; /* * The Link is up, check whether it was marked as down earlier */ if (ixgbe->link_state != LINK_STATE_UP) { + + /* Link is up, enable flow control settings */ + (void) ixgbe_fc_enable(hw); + switch (speed) { case IXGBE_LINK_SPEED_10GB_FULL: ixgbe->link_speed = SPEED_10GB; break; case IXGBE_LINK_SPEED_5GB_FULL: