Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 5 Apr 2010 18:46:29 +0000 (UTC)
From:      Jack F Vogel <jfv@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r206204 - stable/8/sys/dev/ixgbe
Message-ID:  <201004051846.o35IkTFB012966@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jfv
Date: Mon Apr  5 18:46:29 2010
New Revision: 206204
URL: http://svn.freebsd.org/changeset/base/206204

Log:
  MFC of version 2.1.7 of the ixgbe driver.

Modified:
  stable/8/sys/dev/ixgbe/LICENSE
  stable/8/sys/dev/ixgbe/ixgbe.c
  stable/8/sys/dev/ixgbe/ixgbe.h
  stable/8/sys/dev/ixgbe/ixgbe_82598.c
  stable/8/sys/dev/ixgbe/ixgbe_82599.c
  stable/8/sys/dev/ixgbe/ixgbe_api.c
  stable/8/sys/dev/ixgbe/ixgbe_api.h
  stable/8/sys/dev/ixgbe/ixgbe_common.c
  stable/8/sys/dev/ixgbe/ixgbe_common.h
  stable/8/sys/dev/ixgbe/ixgbe_osdep.h
  stable/8/sys/dev/ixgbe/ixgbe_phy.c
  stable/8/sys/dev/ixgbe/ixgbe_phy.h
  stable/8/sys/dev/ixgbe/ixgbe_type.h

Modified: stable/8/sys/dev/ixgbe/LICENSE
==============================================================================
--- stable/8/sys/dev/ixgbe/LICENSE	Mon Apr  5 18:38:18 2010	(r206203)
+++ stable/8/sys/dev/ixgbe/LICENSE	Mon Apr  5 18:46:29 2010	(r206204)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2010, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 

Modified: stable/8/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- stable/8/sys/dev/ixgbe/ixgbe.c	Mon Apr  5 18:38:18 2010	(r206203)
+++ stable/8/sys/dev/ixgbe/ixgbe.c	Mon Apr  5 18:46:29 2010	(r206204)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2010, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -46,7 +46,7 @@ int             ixgbe_display_debug_stat
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "1.8.9";
+char ixgbe_driver_version[] = "2.1.7";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -64,16 +64,20 @@ static ixgbe_vendor_info_t ixgbe_vendor_
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
-	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4_MEZZ, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
 	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
 	/* required last entry */
 	{0, 0, 0, 0, 0}
 };
@@ -102,9 +106,8 @@ static int	ixgbe_mq_start_locked(struct 
 static void	ixgbe_qflush(struct ifnet *);
 #endif
 static int      ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
-static void     ixgbe_watchdog(struct adapter *);
-static void     ixgbe_init(void *);
-static void     ixgbe_init_locked(struct adapter *);
+static void	ixgbe_init(void *);
+static int	ixgbe_init_locked(struct adapter *);
 static void     ixgbe_stop(void *);
 static void     ixgbe_media_status(struct ifnet *, struct ifmediareq *);
 static int      ixgbe_media_change(struct ifnet *);
@@ -116,8 +119,8 @@ static int	ixgbe_allocate_queues(struct 
 static int	ixgbe_setup_msix(struct adapter *);
 static void	ixgbe_free_pci_resources(struct adapter *);
 static void     ixgbe_local_timer(void *);
-static int      ixgbe_hardware_init(struct adapter *);
 static void     ixgbe_setup_interface(device_t, struct adapter *);
+static void     ixgbe_config_link(struct adapter *);
 
 static int      ixgbe_allocate_transmit_buffers(struct tx_ring *);
 static int	ixgbe_setup_transmit_structures(struct adapter *);
@@ -132,21 +135,21 @@ static int	ixgbe_setup_receive_ring(stru
 static void     ixgbe_initialize_receive_units(struct adapter *);
 static void     ixgbe_free_receive_structures(struct adapter *);
 static void     ixgbe_free_receive_buffers(struct rx_ring *);
+static void	ixgbe_setup_hw_rsc(struct rx_ring *);
 
-static void	ixgbe_init_moderation(struct adapter *);
 static void     ixgbe_enable_intr(struct adapter *);
 static void     ixgbe_disable_intr(struct adapter *);
 static void     ixgbe_update_stats_counters(struct adapter *);
 static bool	ixgbe_txeof(struct tx_ring *);
-static bool	ixgbe_rxeof(struct rx_ring *, int);
-static void	ixgbe_rx_checksum(u32, struct mbuf *);
+static bool	ixgbe_rxeof(struct ix_queue *, int);
+static void	ixgbe_rx_checksum(u32, struct mbuf *, u32);
 static void     ixgbe_set_promisc(struct adapter *);
 static void     ixgbe_disable_promisc(struct adapter *);
 static void     ixgbe_set_multi(struct adapter *);
 static void     ixgbe_print_hw_stats(struct adapter *);
 static void	ixgbe_print_debug_info(struct adapter *);
 static void     ixgbe_update_link_status(struct adapter *);
-static int	ixgbe_get_buf(struct rx_ring *, int, u8);
+static void	ixgbe_refresh_mbufs(struct rx_ring *, int);
 static int      ixgbe_xmit(struct tx_ring *, struct mbuf **);
 static int      ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS);
 static int	ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS);
@@ -166,7 +169,9 @@ static void	ixgbe_setup_vlan_hw_support(
 static void	ixgbe_register_vlan(void *, struct ifnet *, u16);
 static void	ixgbe_unregister_vlan(void *, struct ifnet *, u16);
 
-static void	ixgbe_update_aim(struct rx_ring *);
+static __inline void ixgbe_rx_discard(struct rx_ring *, int);
+static __inline void ixgbe_rx_input(struct rx_ring *, struct ifnet *,
+		    struct mbuf *, u32);
 
 /* Support for pluggable optic modules */
 static bool	ixgbe_sfp_probe(struct adapter *);
@@ -175,17 +180,19 @@ static bool	ixgbe_sfp_probe(struct adapt
 static void	ixgbe_legacy_irq(void *);
 
 /* The MSI/X Interrupt handlers */
-static void	ixgbe_msix_tx(void *);
-static void	ixgbe_msix_rx(void *);
+static void	ixgbe_msix_que(void *);
 static void	ixgbe_msix_link(void *);
 
 /* Deferred interrupt tasklets */
-static void	ixgbe_handle_tx(void *, int);
-static void	ixgbe_handle_rx(void *, int);
+static void	ixgbe_handle_que(void *, int);
 static void	ixgbe_handle_link(void *, int);
 static void	ixgbe_handle_msf(void *, int);
 static void	ixgbe_handle_mod(void *, int);
 
+#ifdef IXGBE_FDIR
+static void	ixgbe_atr(struct tx_ring *, struct mbuf *);
+static void	ixgbe_reinit_fdir(void *, int);
+#endif
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
@@ -215,23 +222,16 @@ MODULE_DEPEND(ixgbe, ether, 1, 1, 1);
 */
 
 /*
-** These  parameters are used in Adaptive 
-** Interrupt Moderation. The value is set
-** into EITR and controls the interrupt
-** frequency. They can be modified but 
-** be careful in tuning them.
+** AIM: Adaptive Interrupt Moderation
+** which means that the interrupt rate
+** is varied over time based on the
+** traffic for that interrupt vector
 */
 static int ixgbe_enable_aim = TRUE;
 TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim);
-static int ixgbe_low_latency = IXGBE_LOW_LATENCY;
-TUNABLE_INT("hw.ixgbe.low_latency", &ixgbe_low_latency);
-static int ixgbe_ave_latency = IXGBE_AVE_LATENCY;
-TUNABLE_INT("hw.ixgbe.ave_latency", &ixgbe_ave_latency);
-static int ixgbe_bulk_latency = IXGBE_BULK_LATENCY;
-TUNABLE_INT("hw.ixgbe.bulk_latency", &ixgbe_bulk_latency);
 
 /* How many packets rxeof tries to clean at a time */
-static int ixgbe_rx_process_limit = 100;
+static int ixgbe_rx_process_limit = 128;
 TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
 
 /* Flow control setting, default to full */
@@ -239,6 +239,15 @@ static int ixgbe_flow_control = ixgbe_fc
 TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
 
 /*
+** Smart speed setting, default to on
+** this only works as a compile option
+** right now as its during attach, set
+** this to 'ixgbe_smart_speed_off' to
+** disable.
+*/
+static int ixgbe_smart_speed = ixgbe_smart_speed_on;
+
+/*
  * MSIX should be the default for best performance,
  * but this allows it to be forced off for testing.
  */
@@ -255,23 +264,27 @@ static bool ixgbe_header_split = TRUE;
 TUNABLE_INT("hw.ixgbe.hdr_split", &ixgbe_header_split);
 
 /*
- * Number of Queues, should normally
- * be left at 0, it then autoconfigures to
- * the number of cpus. Each queue is a pair
- * of RX and TX rings with a dedicated interrupt
+ * Number of Queues, can be set to 0,
+ * it then autoconfigures based on the
+ * number of cpus. Each queue is a pair
+ * of RX and TX rings with a msix vector
  */
 static int ixgbe_num_queues = 0;
 TUNABLE_INT("hw.ixgbe.num_queues", &ixgbe_num_queues);
 
-/* Number of TX descriptors per ring */
-static int ixgbe_txd = DEFAULT_TXD;
+/*
+** Number of TX descriptors per ring,
+** setting higher than RX as this seems
+** the better performing choice.
+*/
+static int ixgbe_txd = PERFORM_TXD;
 TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd);
 
 /* Number of RX descriptors per ring */
-static int ixgbe_rxd = DEFAULT_RXD;
+static int ixgbe_rxd = PERFORM_RXD;
 TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
 
-/* Total number of Interfaces - need for config sanity check */
+/* Keep running tab on them for sanity check */
 static int ixgbe_total_ports;
 
 /*
@@ -288,6 +301,27 @@ static u32 ixgbe_shadow_vfta[IXGBE_VFTA_
 */
 static int ixgbe_num_segs = IXGBE_82598_SCATTER;
 
+#ifdef IXGBE_FDIR
+/*
+** For Flow Director: this is the
+** number of TX packets we sample
+** for the filter pool, this means
+** every 20th packet will be probed.
+**
+** This feature can be disabled by 
+** setting this to 0.
+*/
+static int atr_sample_rate = 20;
+/* 
+** Flow Director actually 'steals'
+** part of the packet buffer as its
+** filter pool, this variable controls
+** how much it uses:
+**  0 = 64K, 1 = 128K, 2 = 256K
+*/
+static int fdir_pballoc = 1;
+#endif
+
 /*********************************************************************
  *  Device identification routine
  *
@@ -356,7 +390,7 @@ ixgbe_attach(device_t dev)
 	struct adapter *adapter;
 	struct ixgbe_hw *hw;
 	int             error = 0;
-	u16		pci_device_id;
+	u16		pci_device_id, csum;
 	u32		ctrl_ext;
 
 	INIT_DEBUGOUT("ixgbe_attach: begin");
@@ -376,12 +410,18 @@ ixgbe_attach(device_t dev)
 		case IXGBE_DEV_ID_82598EB_CX4 :
 			adapter->optics = IFM_10G_CX4;
 			break;
+		case IXGBE_DEV_ID_82598 :
 		case IXGBE_DEV_ID_82598AF_DUAL_PORT :
 		case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
 		case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+		case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM :
+		case IXGBE_DEV_ID_82598EB_SFP_LOM :
 		case IXGBE_DEV_ID_82598AT :
 			adapter->optics = IFM_10G_SR;
 			break;
+		case IXGBE_DEV_ID_82598AT2 :
+			adapter->optics = IFM_10G_T;
+			break;
 		case IXGBE_DEV_ID_82598EB_XF_LR :
 			adapter->optics = IFM_10G_LR;
 			break;
@@ -390,11 +430,18 @@ ixgbe_attach(device_t dev)
 			ixgbe_num_segs = IXGBE_82599_SCATTER;
 			break;
 		case IXGBE_DEV_ID_82599_KX4 :
+		case IXGBE_DEV_ID_82599_KX4_MEZZ:
+		case IXGBE_DEV_ID_82599_CX4 :
 			adapter->optics = IFM_10G_CX4;
 			ixgbe_num_segs = IXGBE_82599_SCATTER;
 			break;
 		case IXGBE_DEV_ID_82599_XAUI_LOM :
+		case IXGBE_DEV_ID_82599_COMBO_BACKPLANE :
+			ixgbe_num_segs = IXGBE_82599_SCATTER;
+			break;
+		case IXGBE_DEV_ID_82599_T3_LOM:
 			ixgbe_num_segs = IXGBE_82599_SCATTER;
+			adapter->optics = IFM_10G_T;
 		default:
 			break;
 	}
@@ -420,21 +467,6 @@ ixgbe_attach(device_t dev)
 			OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
 			&ixgbe_enable_aim, 1, "Interrupt Moderation");
 
-        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-			OID_AUTO, "low_latency", CTLTYPE_INT|CTLFLAG_RW,
-			&ixgbe_low_latency, 1, "Low Latency");
-
-        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-			OID_AUTO, "ave_latency", CTLTYPE_INT|CTLFLAG_RW,
-			&ixgbe_ave_latency, 1, "Average Latency");
-
-        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-			SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-			OID_AUTO, "bulk_latency", CTLTYPE_INT|CTLFLAG_RW,
-			&ixgbe_bulk_latency, 1, "Bulk Latency");
-
 	/* Set up the timer callout */
 	callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
 
@@ -504,10 +536,37 @@ ixgbe_attach(device_t dev)
 		goto err_late;
 	}
 
-	/* Initialize the hardware */
-	if (ixgbe_hardware_init(adapter)) {
-		device_printf(dev,"Unable to initialize the hardware\n");
+	/* Make sure we have a good EEPROM before we read from it */
+	if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) {
+		device_printf(dev,"The EEPROM Checksum Is Not Valid\n");
+		error = EIO;
+		goto err_late;
+	}
+
+	/* Pick up the smart speed setting */
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		hw->phy.smart_speed = ixgbe_smart_speed;
+
+	/* Get Hardware Flow Control setting */
+	hw->fc.requested_mode = ixgbe_fc_full;
+	hw->fc.pause_time = IXGBE_FC_PAUSE;
+	hw->fc.low_water = IXGBE_FC_LO;
+	hw->fc.high_water = IXGBE_FC_HI;
+	hw->fc.send_xon = TRUE;
+
+	error = ixgbe_init_hw(hw);
+	if (error == IXGBE_ERR_EEPROM_VERSION) {
+		device_printf(dev, "This device is a pre-production adapter/"
+		    "LOM.  Please be aware there may be issues associated "
+		    "with your hardware.\n If you are experiencing problems "
+		    "please contact your Intel or hardware representative "
+		    "who provided you with this hardware.\n");
+	} else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED)
+		device_printf(dev,"Unsupported SFP+ Module\n");
+
+	if (error) {
 		error = EIO;
+		device_printf(dev,"Hardware Initialization Failure\n");
 		goto err_late;
 	}
 
@@ -521,22 +580,6 @@ ixgbe_attach(device_t dev)
 	/* Setup OS specific network interface */
 	ixgbe_setup_interface(dev, adapter);
 
-#ifdef IXGBE_IEEE1588
-	/*
-	** Setup the timer: IEEE 1588 support
-	*/
-	adapter->cycles.read = ixgbe_read_clock;
-	adapter->cycles.mask = (u64)-1;
-	adapter->cycles.mult = 1;
-	adapter->cycles.shift = IXGBE_TSYNC_SHIFT;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TIMINCA, (1<<24) |
-	    IXGBE_TSYNC_CYCLE_TIME * IXGBE_TSYNC_SHIFT);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIML, 0x00000000);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIMH, 0xFF800000);
-
-        // JFV - this is not complete yet
-#endif
-
 	/* Sysctl for limiting the amount of work done in the taskqueue */
 	ixgbe_add_rx_process_limit(adapter, "rx_processing_limit",
 	    "max number of rx packets to process", &adapter->rx_process_limit,
@@ -551,6 +594,25 @@ ixgbe_attach(device_t dev)
 	adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
 	    ixgbe_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
 
+        /* Print PCIE bus type/speed/width info */
+	ixgbe_get_bus_info(hw);
+	device_printf(dev,"PCI Express Bus: Speed %s %s\n",
+	    ((hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0Gb/s":
+	    (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5Gb/s":"Unknown"),
+	    (hw->bus.width == ixgbe_bus_width_pcie_x8) ? "Width x8" :
+	    (hw->bus.width == ixgbe_bus_width_pcie_x4) ? "Width x4" :
+	    (hw->bus.width == ixgbe_bus_width_pcie_x1) ? "Width x1" :
+	    ("Unknown"));
+
+	if ((hw->bus.width <= ixgbe_bus_width_pcie_x4) &&
+	    (hw->bus.speed == ixgbe_bus_speed_2500)) {
+		device_printf(dev, "PCI-Express bandwidth available"
+		    " for this card\n     is not sufficient for"
+		    " optimal performance.\n");
+		device_printf(dev, "For optimal performance a x8 "
+		    "PCIE, or x4 PCIE 2 slot is required.\n");
+        }
+
 	/* let hardware know driver is loaded */
 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
 	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
@@ -581,8 +643,7 @@ static int
 ixgbe_detach(device_t dev)
 {
 	struct adapter *adapter = device_get_softc(dev);
-	struct tx_ring *txr = adapter->tx_rings;
-	struct rx_ring *rxr = adapter->rx_rings;
+	struct ix_queue *que = adapter->queues;
 	u32	ctrl_ext;
 
 	INIT_DEBUGOUT("ixgbe_detach: begin");
@@ -597,17 +658,10 @@ ixgbe_detach(device_t dev)
 	ixgbe_stop(adapter);
 	IXGBE_CORE_UNLOCK(adapter);
 
-	for (int i = 0; i < adapter->num_queues; i++, txr++) {
-		if (txr->tq) {
-			taskqueue_drain(txr->tq, &txr->tx_task);
-			taskqueue_free(txr->tq);
-		}
-	}
-
-	for (int i = 0; i < adapter->num_queues; i++, rxr++) {
-		if (rxr->tq) {
-			taskqueue_drain(rxr->tq, &rxr->rx_task);
-			taskqueue_free(rxr->tq);
+	for (int i = 0; i < adapter->num_queues; i++, que++) {
+		if (que->tq) {
+			taskqueue_drain(que->tq, &que->que_task);
+			taskqueue_free(que->tq);
 		}
 	}
 
@@ -616,6 +670,9 @@ ixgbe_detach(device_t dev)
 		taskqueue_drain(adapter->tq, &adapter->link_task);
 		taskqueue_drain(adapter->tq, &adapter->mod_task);
 		taskqueue_drain(adapter->tq, &adapter->msf_task);
+#ifdef IXGBE_FDIR
+		taskqueue_drain(adapter->tq, &adapter->fdir_task);
+#endif
 		taskqueue_free(adapter->tq);
 	}
 
@@ -700,8 +757,8 @@ ixgbe_start_locked(struct tx_ring *txr, 
 		/* Send a copy of the frame to the BPF listener */
 		ETHER_BPF_MTAP(ifp, m_head);
 
-		/* Set timeout in case hardware has problems transmitting */
-		txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+		/* Set watchdog on */
+		txr->watchdog_check = TRUE;
 
 	}
 	return;
@@ -741,6 +798,9 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 	/* Which queue to use */
 	if ((m->m_flags & M_FLOWID) != 0)
 		i = m->m_pkthdr.flowid % adapter->num_queues;
+	else	/* use the cpu we're on */
+		i = curcpu % adapter->num_queues;
+
 	txr = &adapter->tx_rings[i];
 
 	if (IXGBE_TX_TRYLOCK(txr)) {
@@ -757,53 +817,47 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 {
 	struct adapter  *adapter = txr->adapter;
         struct mbuf     *next;
-        int             err = 0;
+        int             enqueued, err = 0;
 
-	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
-		err = drbr_enqueue(ifp, txr->br, m);
+	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+	    IFF_DRV_RUNNING || adapter->link_active == 0) {
+		if (m != NULL)
+			err = drbr_enqueue(ifp, txr->br, m);
 		return (err);
 	}
 
-	if (m == NULL) /* Called by tasklet */
-		goto process;
-
-	/* If nothing queued go right to xmit */
-	if (!drbr_needs_enqueue(ifp, txr->br)) {
-		if (ixgbe_xmit(txr, &m)) {
-			if (m && (err = drbr_enqueue(ifp, txr->br, m)) != 0)
-                                return (err);
-		} else {
-			/* Success, update stats */
-			drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags);
-			/* Send a copy of the frame to the BPF listener */
-			ETHER_BPF_MTAP(ifp, m);
-			/* Set the watchdog */
-			txr->watchdog_timer = IXGBE_TX_TIMEOUT;
-                }
-
-        } else if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
-		return (err);
-
-process:
-	if (drbr_empty(ifp, txr->br))
-		return (err);
+	enqueued = 0;
+	if (m == NULL) {
+		next = drbr_dequeue(ifp, txr->br);
+	} else if (drbr_needs_enqueue(ifp, txr->br)) {
+		if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+			return (err);
+		next = drbr_dequeue(ifp, txr->br);
+	} else
+		next = m;
 
 	/* Process the queue */
-	while (TRUE) {
-		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+	while (next != NULL) {
+		if ((err = ixgbe_xmit(txr, &next)) != 0) {
+			if (next != NULL)
+				err = drbr_enqueue(ifp, txr->br, next);
 			break;
-		next = drbr_dequeue(ifp, txr->br);
-		if (next == NULL)
+		}
+		enqueued++;
+		drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
+		/* Send a copy of the frame to the BPF listener */
+		ETHER_BPF_MTAP(ifp, next);
+		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
 			break;
-		if (ixgbe_xmit(txr, &next))
+		if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 			break;
-		ETHER_BPF_MTAP(ifp, next);
-		/* Set the watchdog */
-		txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+		}
+		next = drbr_dequeue(ifp, txr->br);
 	}
-		
-	if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD)
-		ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+
+	if (enqueued > 0) 
+		txr->watchdog_check = TRUE;
 
 	return (err);
 }
@@ -840,29 +894,12 @@ ixgbe_qflush(struct ifnet *ifp)
 static int
 ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
 {
-	struct adapter *adapter = ifp->if_softc;
-	struct ifreq   *ifr = (struct ifreq *) data;
-#ifdef INET
-	struct ifaddr   *ifa = (struct ifaddr *) data;
-#endif
+	struct adapter	*adapter = ifp->if_softc;
+	struct ifreq	*ifr = (struct ifreq *) data;
 	int             error = 0;
 
 	switch (command) {
-	case SIOCSIFADDR:
-#ifdef INET
-		IOCTL_DEBUGOUT("ioctl: SIOCxIFADDR (Get/Set Interface Addr)");
-		if (ifa->ifa_addr->sa_family == AF_INET) {
-			ifp->if_flags |= IFF_UP;
-			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-				IXGBE_CORE_LOCK(adapter);
-				ixgbe_init_locked(adapter);
-				IXGBE_CORE_UNLOCK(adapter);
-			}
-			arp_ifinit(ifp, ifa);
-                } else
-#endif
-			ether_ioctl(ifp, command, data);
-		break;
+
 	case SIOCSIFMTU:
 		IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
 		if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
@@ -872,7 +909,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 			ifp->if_mtu = ifr->ifr_mtu;
 			adapter->max_frame_size =
 				ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
-			ixgbe_init_locked(adapter);
+			error = ixgbe_init_locked(adapter);
 			IXGBE_CORE_UNLOCK(adapter);
 		}
 		break;
@@ -887,7 +924,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 					ixgbe_set_promisc(adapter);
                                 }
 			} else
-				ixgbe_init_locked(adapter);
+				error = ixgbe_init_locked(adapter);
 		} else
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 				ixgbe_stop(adapter);
@@ -922,21 +959,15 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 			ifp->if_capenable ^= IFCAP_LRO;
 		if (mask & IFCAP_VLAN_HWTAGGING)
 			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
-		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-			ixgbe_init(adapter);
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+			IXGBE_CORE_LOCK(adapter);
+			error = ixgbe_init_locked(adapter);
+			IXGBE_CORE_UNLOCK(adapter);
+		}
 		VLAN_CAPABILITIES(ifp);
 		break;
 	}
 
-#ifdef IXGBE_IEEE1588
-	/*
-	** IOCTL support for Precision Time (IEEE 1588) Support
-	*/
-	case SIOCSHWTSTAMP:
-		error = ixgbe_hwtstamp_ioctl(adapter, ifp);
-		break;
-#endif
-
 	default:
 		IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
 		error = ether_ioctl(ifp, command, data);
@@ -947,84 +978,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 }
 
 /*********************************************************************
- *  Watchdog entry point
- *
- *  This routine is called by the local timer
- *  to detect hardware hangs .
- *
- **********************************************************************/
-
-static void
-ixgbe_watchdog(struct adapter *adapter)
-{
-	device_t 	dev = adapter->dev;
-	struct tx_ring *txr = adapter->tx_rings;
-	struct ixgbe_hw *hw = &adapter->hw;
-	bool		tx_hang = FALSE;
-
-	IXGBE_CORE_LOCK_ASSERT(adapter);
-
-        /*
-         * The timer is set to 5 every time ixgbe_start() queues a packet.
-         * Then ixgbe_txeof() keeps resetting to 5 as long as it cleans at
-         * least one descriptor.
-         * Finally, anytime all descriptors are clean the timer is
-         * set to 0.
-         */
-	for (int i = 0; i < adapter->num_queues; i++, txr++) {
-		u32 head, tail;
-
-		IXGBE_TX_LOCK(txr);
-        	if (txr->watchdog_timer == 0 || --txr->watchdog_timer) {
-			IXGBE_TX_UNLOCK(txr);
-                	continue;
-		} else {
-			head = IXGBE_READ_REG(hw, IXGBE_TDH(i));
-			tail = IXGBE_READ_REG(hw, IXGBE_TDT(i));
-			if (head == tail) { /* last minute check */
-				IXGBE_TX_UNLOCK(txr);
-				continue;
-			}
-			/* Well, seems something is really hung */
-			tx_hang = TRUE;
-			IXGBE_TX_UNLOCK(txr);
-			break;
-		}
-	}
-	if (tx_hang == FALSE)
-		return;
-
-	/*
-	 * If we are in this routine because of pause frames, then don't
-	 * reset the hardware.
-	 */
-	if (IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) {
-		txr = adapter->tx_rings;	/* reset pointer */
-		for (int i = 0; i < adapter->num_queues; i++, txr++) {
-			IXGBE_TX_LOCK(txr);
-			txr->watchdog_timer = IXGBE_TX_TIMEOUT;
-			IXGBE_TX_UNLOCK(txr);
-		}
-		return;
-	}
-
-
-	device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
-	for (int i = 0; i < adapter->num_queues; i++, txr++) {
-		device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", i,
-		    IXGBE_READ_REG(hw, IXGBE_TDH(i)),
-		    IXGBE_READ_REG(hw, IXGBE_TDT(i)));
-		device_printf(dev,"TX(%d) desc avail = %d,"
-		    "Next TX to Clean = %d\n",
-		    i, txr->tx_avail, txr->next_tx_to_clean);
-	}
-	adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-	adapter->watchdog_events++;
-
-	ixgbe_init_locked(adapter);
-}
-
-/*********************************************************************
  *  Init entry point
  *
  *  This routine is used in two ways. It is used by the stack as
@@ -1036,42 +989,39 @@ ixgbe_watchdog(struct adapter *adapter)
  **********************************************************************/
 #define IXGBE_MHADD_MFS_SHIFT 16
 
-static void
+static int
 ixgbe_init_locked(struct adapter *adapter)
 {
 	struct ifnet   *ifp = adapter->ifp;
 	device_t 	dev = adapter->dev;
-	struct ixgbe_hw *hw;
+	struct ixgbe_hw *hw = &adapter->hw;
 	u32		k, txdctl, mhadd, gpie;
 	u32		rxdctl, rxctrl;
-	int		err;
-
-	INIT_DEBUGOUT("ixgbe_init: begin");
 
-	hw = &adapter->hw;
 	mtx_assert(&adapter->core_mtx, MA_OWNED);
+	INIT_DEBUGOUT("ixgbe_init: begin");
+	ixgbe_reset_hw(hw);
+	hw->adapter_stopped = FALSE;
+	ixgbe_stop_adapter(hw);
+        callout_stop(&adapter->timer);
 
-	ixgbe_stop(adapter);
+        /* reprogram the RAR[0] in case user changed it. */
+        ixgbe_set_rar(hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
 
 	/* Get the latest mac address, User can use a LAA */
-	bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr,
+	bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr,
 	      IXGBE_ETH_LENGTH_OF_ADDRESS);
-	ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, 1);
-	adapter->hw.addr_ctrl.rar_used_count = 1;
-
-	/* Initialize the hardware */
-	if (ixgbe_hardware_init(adapter)) {
-		device_printf(dev, "Unable to initialize the hardware\n");
-		return;
-	}
+	ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
+	hw->addr_ctrl.rar_used_count = 1;
 
 	/* Prepare transmit descriptors and buffers */
 	if (ixgbe_setup_transmit_structures(adapter)) {
 		device_printf(dev,"Could not setup transmit structures\n");
 		ixgbe_stop(adapter);
-		return;
+		return (ENOMEM);
 	}
 
+	ixgbe_init_hw(hw);
 	ixgbe_initialize_transmit_units(adapter);
 
 	/* Setup Multicast table */
@@ -1090,18 +1040,15 @@ ixgbe_init_locked(struct adapter *adapte
 	if (ixgbe_setup_receive_structures(adapter)) {
 		device_printf(dev,"Could not setup receive structures\n");
 		ixgbe_stop(adapter);
-		return;
+		return (ENOMEM);
 	}
 
 	/* Configure RX settings */
 	ixgbe_initialize_receive_units(adapter);
 
-	/* Configure Interrupt Moderation */
-	ixgbe_init_moderation(adapter);
-
 	gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
 
-	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+	if (hw->mac.type == ixgbe_mac_82599EB) {
 		gpie |= IXGBE_SDP1_GPIEN;
 		gpie |= IXGBE_SDP2_GPIEN;
 	}
@@ -1116,39 +1063,49 @@ ixgbe_init_locked(struct adapter *adapte
 		gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
 		    IXGBE_GPIE_OCD;
 	}
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie);
+	IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
 
 	/* Set the various hardware offload abilities */
 	ifp->if_hwassist = 0;
 	if (ifp->if_capenable & IFCAP_TSO4)
 		ifp->if_hwassist |= CSUM_TSO;
 	if (ifp->if_capenable & IFCAP_TXCSUM)
-		ifp->if_hwassist = (CSUM_TCP | CSUM_UDP);
-
+		ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+#if __FreeBSD_version >= 800000
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		ifp->if_hwassist |= CSUM_SCTP;
+#endif
 	/* Set MTU size */
 	if (ifp->if_mtu > ETHERMTU) {
-		mhadd = IXGBE_READ_REG(&adapter->hw, IXGBE_MHADD);
+		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
 		mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_MHADD, mhadd);
+		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
 	}
 	
 	/* Now enable all the queues */
 
 	for (int i = 0; i < adapter->num_queues; i++) {
-		txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i));
+		txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
 		txdctl |= IXGBE_TXDCTL_ENABLE;
 		/* Set WTHRESH to 8, burst writeback */
 		txdctl |= (8 << 16);
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl);
+		IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl);
 	}
 
 	for (int i = 0; i < adapter->num_queues; i++) {
-		rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(i));
-		/* PTHRESH set to 32 */
-		rxdctl |= 0x0020;
+		rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+		if (hw->mac.type == ixgbe_mac_82598EB) {
+			/*
+			** PTHRESH = 21
+			** HTHRESH = 4
+			** WTHRESH = 8
+			*/
+			rxdctl &= ~0x3FFFFF;
+			rxdctl |= 0x080420;
+		}
 		rxdctl |= IXGBE_RXDCTL_ENABLE;
-		IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(i), rxdctl);
+		IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), rxdctl);
 		for (k = 0; k < 10; k++) {
 			if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)) &
 			    IXGBE_RXDCTL_ENABLE)
@@ -1165,10 +1122,10 @@ ixgbe_init_locked(struct adapter *adapte
 
 	/* Enable Receive engine */
 	rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
-	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+	if (hw->mac.type == ixgbe_mac_82598EB)
 		rxctrl |= IXGBE_RXCTRL_DMBYPS;
 	rxctrl |= IXGBE_RXCTRL_RXEN;
-	IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
+	ixgbe_enable_rx_dma(hw, rxctrl);
 
 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
 
@@ -1180,33 +1137,36 @@ ixgbe_init_locked(struct adapter *adapte
                 ixgbe_set_ivar(adapter, 0, 0, 1);
 	}
 
-	ixgbe_enable_intr(adapter);
+#ifdef IXGBE_FDIR
+	/* Init Flow director */
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
+#endif
 
 	/*
 	** Check on any SFP devices that
 	** need to be kick-started
 	*/
-	err = hw->phy.ops.identify(hw);
-	if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
-                device_printf(dev,
-		    "Unsupported SFP+ module type was detected.\n");
-		ixgbe_detach(dev);
-		return;
-        }
-	if (ixgbe_is_sfp(hw)) { 
-		if (hw->phy.multispeed_fiber) {
-			hw->mac.ops.setup_sfp(hw);
-			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
-		} else
-			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
-	} else
-		taskqueue_enqueue(adapter->tq, &adapter->link_task);
+	if (hw->phy.type == ixgbe_phy_none) {
+		int err = hw->phy.ops.identify(hw);
+		if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+                	device_printf(dev,
+			    "Unsupported SFP+ module type was detected.\n");
+			return (EIO);
+        	}
+	}
+
+	/* Config/Enable Link */
+	ixgbe_config_link(adapter);
+
+	/* And now turn on interrupts */
+	ixgbe_enable_intr(adapter);
 
 	/* Now inform the stack we're ready */
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
-	return;
+	return (0);
 }
 
 static void
@@ -1268,7 +1228,7 @@ ixgbe_disable_queue(struct adapter *adap
 }
 
 static inline void
-ixgbe_rearm_rx_queues(struct adapter *adapter, u64 queues)
+ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
 {
 	u32 mask;
 
@@ -1283,34 +1243,22 @@ ixgbe_rearm_rx_queues(struct adapter *ad
 	}
 }
 
-static void
-ixgbe_handle_rx(void *context, int pending)
-{
-	struct rx_ring  *rxr = context;
-	struct adapter  *adapter = rxr->adapter;
-	u32		loop = MAX_LOOP;
-	bool		more;
-
-	do {
-		more = ixgbe_rxeof(rxr, -1);
-	} while (loop-- && more);
-        /* Reenable this interrupt */
-	ixgbe_enable_queue(adapter, rxr->msix);
-}
 
 static void
-ixgbe_handle_tx(void *context, int pending)
+ixgbe_handle_que(void *context, int pending)
 {
-	struct tx_ring  *txr = context;
-	struct adapter  *adapter = txr->adapter;
+	struct ix_queue *que = context;
+	struct adapter  *adapter = que->adapter;
+	struct tx_ring  *txr = que->txr;
 	struct ifnet    *ifp = adapter->ifp;
 	u32		loop = MAX_LOOP;
-	bool		more;
+	bool		more_rx, more_tx;
 
 	IXGBE_TX_LOCK(txr);
 	do {
-		more = ixgbe_txeof(txr);
-	} while (loop-- && more);
+		more_rx = ixgbe_rxeof(que, adapter->rx_process_limit);
+		more_tx = ixgbe_txeof(txr);
+	} while (loop-- && (more_rx || more_tx));
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 #if __FreeBSD_version >= 800000
@@ -1324,7 +1272,7 @@ ixgbe_handle_tx(void *context, int pendi
 
 	IXGBE_TX_UNLOCK(txr);
 	/* Reenable this interrupt */
-	ixgbe_enable_queue(adapter, txr->msix);
+	ixgbe_enable_queue(adapter, que->msix);
 }
 
 
@@ -1337,33 +1285,32 @@ ixgbe_handle_tx(void *context, int pendi
 static void
 ixgbe_legacy_irq(void *arg)
 {
-	struct adapter	*adapter = arg;
+	struct ix_queue *que = arg;
+	struct adapter	*adapter = que->adapter;
 	struct ixgbe_hw	*hw = &adapter->hw;
 	struct 		tx_ring *txr = adapter->tx_rings;
-	struct		rx_ring *rxr = adapter->rx_rings;
-	bool		more;
+	bool		more_tx, more_rx;
 	u32       	reg_eicr, loop = MAX_LOOP;
 
 
 	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
 
+	++que->irqs;
 	if (reg_eicr == 0) {
 		ixgbe_enable_intr(adapter);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004051846.o35IkTFB012966>