--- old/usr/src/uts/common/io/ixgbe/ixgbe_main.c	Mon Aug  5 17:28:54 2019
+++ new/usr/src/uts/common/io/ixgbe/ixgbe_main.c	Mon Aug  5 17:28:54 2019
@@ -26,7 +26,7 @@
 /*
  * 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 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.
@@ -493,14 +493,6 @@
 	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) {
@@ -650,6 +642,15 @@
 	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:
@@ -778,6 +779,12 @@
 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) {
@@ -1241,6 +1248,42 @@
 	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)
 {
@@ -1395,8 +1438,25 @@
 	 * 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;
+	{
+		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;
 
@@ -1428,6 +1488,11 @@
 		    "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;
 	}
@@ -1992,20 +2057,23 @@
 ixgbe_intr_adjust(ixgbe_t *ixgbe, ddi_cb_action_t cbaction, int count)
 {
 	int i, rc, actual;
+	uint32_t started;
 
-	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))
+	if (!(ixgbe->ixgbe_state & IXGBE_INITIALIZED)) {
 		return (DDI_FAILURE);
+	}
 
-	if (!(ixgbe->ixgbe_state & IXGBE_STARTED)) {
+	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++)
@@ -2012,12 +2080,14 @@
 		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);
 
-	ixgbe_stop(ixgbe, B_FALSE);
+	if (started)
+		ixgbe_stop(ixgbe, B_FALSE);
 	/*
 	 * Disable interrupts
 	 */
@@ -2112,13 +2182,14 @@
 		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;
-	}
+	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 |= IXGBE_STARTED;
+	ixgbe->ixgbe_state |= started;
 	mutex_exit(&ixgbe->gen_lock);
 
 	for (i = 0; i < ixgbe->num_rx_rings; i++) {
@@ -3677,13 +3748,14 @@
 	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) {
+
+			/* 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;
