Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 14 Apr 2009 00:23:13 +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-7@freebsd.org
Subject:   svn commit: r191030 - stable/7/sys/dev/ixgbe
Message-ID:  <200904140023.n3E0NDiT088341@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jfv
Date: Tue Apr 14 00:23:13 2009
New Revision: 191030
URL: http://svn.freebsd.org/changeset/base/191030

Log:
  MFC ixgbe version 1.7.4 for FreeBSD 7.2, this is earlier
  than planned but coordinated with and approved by RE.
  
  Most important reason for this was so that FreeBSD 7.2
  will have native support for the 82599 controller which
  is part of the Nehalem launch.
  
  The driver now does pluggable optics, multispeed fiber,
  and header split. I am adding this to the GENERIC kernel
  only in the amd64 architecture since its where I expect
  most use and others were untested.
  
  Enjoy!
  
  Approved by: re

Added:
  stable/7/sys/dev/ixgbe/ixgbe_82599.c   (contents, props changed)
Modified:
  stable/7/sys/dev/ixgbe/LICENSE
  stable/7/sys/dev/ixgbe/ixgbe.c
  stable/7/sys/dev/ixgbe/ixgbe.h
  stable/7/sys/dev/ixgbe/ixgbe_82598.c
  stable/7/sys/dev/ixgbe/ixgbe_api.c
  stable/7/sys/dev/ixgbe/ixgbe_api.h
  stable/7/sys/dev/ixgbe/ixgbe_common.c
  stable/7/sys/dev/ixgbe/ixgbe_common.h
  stable/7/sys/dev/ixgbe/ixgbe_osdep.h
  stable/7/sys/dev/ixgbe/ixgbe_phy.c
  stable/7/sys/dev/ixgbe/ixgbe_phy.h
  stable/7/sys/dev/ixgbe/ixgbe_type.h

Modified: stable/7/sys/dev/ixgbe/LICENSE
==============================================================================
--- stable/7/sys/dev/ixgbe/LICENSE	Mon Apr 13 23:50:44 2009	(r191029)
+++ stable/7/sys/dev/ixgbe/LICENSE	Tue Apr 14 00:23:13 2009	(r191030)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 

Modified: stable/7/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- stable/7/sys/dev/ixgbe/ixgbe.c	Mon Apr 13 23:50:44 2009	(r191029)
+++ stable/7/sys/dev/ixgbe/ixgbe.c	Tue Apr 14 00:23:13 2009	(r191030)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, 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.6.2";
+char ixgbe_driver_version[] = "1.7.4";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -71,6 +71,8 @@ static ixgbe_vendor_info_t ixgbe_vendor_
 	{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_SFP, 0, 0, 0},
 	/* required last entry */
 	{0, 0, 0, 0, 0}
 };
@@ -104,7 +106,9 @@ static int      ixgbe_allocate_pci_resou
 static int      ixgbe_allocate_msix(struct adapter *);
 static int      ixgbe_allocate_legacy(struct adapter *);
 static int	ixgbe_allocate_queues(struct adapter *);
+#if __FreeBSD_version >= 602105
 static int	ixgbe_setup_msix(struct adapter *);
+#endif
 static void	ixgbe_free_pci_resources(struct adapter *);
 static void     ixgbe_local_timer(void *);
 static int      ixgbe_hardware_init(struct adapter *);
@@ -124,6 +128,7 @@ static void     ixgbe_initialize_receive
 static void     ixgbe_free_receive_structures(struct adapter *);
 static void     ixgbe_free_receive_buffers(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 *);
@@ -146,7 +151,7 @@ static int	ixgbe_dma_malloc(struct adapt
 static void     ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
 static void	ixgbe_add_rx_process_limit(struct adapter *, const char *,
 		    const char *, int *, int);
-static boolean_t ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
+static int	ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
 static boolean_t ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
 static void	ixgbe_set_ivar(struct adapter *, u16, u8, s8);
 static void	ixgbe_configure_ivars(struct adapter *);
@@ -157,6 +162,12 @@ static void	ixgbe_register_vlan(void *, 
 static void	ixgbe_unregister_vlan(void *, struct ifnet *, u16);
 #endif
 
+#ifdef IXGBE_TIMESYNC
+/* Precision Time sync support */
+static int ixgbe_tsync_init(struct adapter *);
+static void ixgbe_tsync_disable(struct adapter *);
+#endif
+
 static void	ixgbe_update_aim(struct rx_ring *);
 
 /* Support for pluggable optic modules */
@@ -165,14 +176,19 @@ static bool	ixgbe_sfp_probe(struct adapt
 /* Legacy (single vector interrupt handler */
 static void	ixgbe_legacy_irq(void *);
 
+#if __FreeBSD_version >= 602105
 /* The MSI/X Interrupt handlers */
 static void	ixgbe_msix_tx(void *);
 static void	ixgbe_msix_rx(void *);
 static void	ixgbe_msix_link(void *);
+#endif
 
-/* Legacy interrupts use deferred handlers */
-static void	ixgbe_handle_tx(void *context, int pending);
-static void	ixgbe_handle_rx(void *context, int pending);
+/* Deferred interrupt tasklets */
+static void	ixgbe_handle_tx(void *, int);
+static void	ixgbe_handle_rx(void *, int);
+static void	ixgbe_handle_link(void *, int);
+static void	ixgbe_handle_msf(void *, int);
+static void	ixgbe_handle_mod(void *, int);
 
 
 /*********************************************************************
@@ -213,8 +229,8 @@ 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_LOW_LATENCY;
-TUNABLE_INT("hw.ixgbe.ave_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);
 
@@ -222,8 +238,8 @@ TUNABLE_INT("hw.ixgbe.bulk_latency", &ix
 static int ixgbe_rx_process_limit = 100;
 TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
 
-/* Flow control setting, default to full */
-static int ixgbe_flow_control = ixgbe_fc_none;
+/* Flow control setting, default to off */
+static int ixgbe_flow_control = ixgbe_fc_full;
 TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
 
 /*
@@ -239,11 +255,16 @@ TUNABLE_INT("hw.ixgbe.enable_lro", &ixgb
  * MSIX should be the default for best performance,
  * but this allows it to be forced off for testing.
  */
+#if __FreeBSD_version >= 602105
 static int ixgbe_enable_msix = 1;
+#else
+static int ixgbe_enable_msix = 0;
+#endif
 TUNABLE_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);
 
 /*
  * Enable RX Header Split
+ *   WARNING: disable this if bridging or forwarding!!
  */
 static int ixgbe_rx_hdr_split = 1;
 TUNABLE_INT("hw.ixgbe.rx_hdr_split", &ixgbe_rx_hdr_split);
@@ -268,6 +289,13 @@ TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
 /* Total number of Interfaces - need for config sanity check */
 static int ixgbe_total_ports;
 
+/*
+** The number of scatter-gather segments
+** differs for 82598 and 82599, default to
+** the former.
+*/
+static int ixgbe_num_segs = IXGBE_82598_SCATTER;
+
 /*********************************************************************
  *  Device identification routine
  *
@@ -312,6 +340,7 @@ ixgbe_probe(device_t dev)
 				ixgbe_strings[ent->index],
 				ixgbe_driver_version);
 			device_set_desc_copy(dev, adapter_name);
+			++ixgbe_total_ports;
 			return (0);
 		}
 		ent++;
@@ -333,6 +362,7 @@ static int
 ixgbe_attach(device_t dev)
 {
 	struct adapter *adapter;
+	struct ixgbe_hw *hw;
 	int             error = 0;
 	u16		pci_device_id;
 	u32		ctrl_ext;
@@ -342,37 +372,34 @@ ixgbe_attach(device_t dev)
 	/* Allocate, clear, and link in our adapter structure */
 	adapter = device_get_softc(dev);
 	adapter->dev = adapter->osdep.dev = dev;
+	hw = &adapter->hw;
 
 	/* Core Lock Init*/
 	IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
 
-	/* Keep track of number of ports and optics */
+	/* Keep track of optics */
 	pci_device_id = pci_get_device(dev);
 	switch (pci_device_id) {
 		case IXGBE_DEV_ID_82598_CX4_DUAL_PORT :
+		case IXGBE_DEV_ID_82598EB_CX4 :
 			adapter->optics = IFM_10G_CX4;
-			ixgbe_total_ports += 2;
 			break;
 		case IXGBE_DEV_ID_82598AF_DUAL_PORT :
-			adapter->optics = IFM_10G_SR;
-			ixgbe_total_ports += 2;
-			break;
+		case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
 		case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+		case IXGBE_DEV_ID_82598AT :
 			adapter->optics = IFM_10G_SR;
-			ixgbe_total_ports += 1;
 			break;
 		case IXGBE_DEV_ID_82598EB_XF_LR :
 			adapter->optics = IFM_10G_LR;
-			ixgbe_total_ports += 1;
 			break;
-		case IXGBE_DEV_ID_82598EB_CX4 :
-			adapter->optics = IFM_10G_CX4;
-			ixgbe_total_ports += 1;
+		case IXGBE_DEV_ID_82599_SFP :
+			adapter->optics = IFM_10G_SR;
+			ixgbe_num_segs = IXGBE_82599_SCATTER;
 			break;
-		case IXGBE_DEV_ID_82598AT :
-			ixgbe_total_ports += 1;
-		case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
-			ixgbe_total_ports += 2;
+		case IXGBE_DEV_ID_82599_KX4 :
+			adapter->optics = IFM_10G_CX4;
+			ixgbe_num_segs = IXGBE_82599_SCATTER;
 		default:
 			break;
 	}
@@ -474,7 +501,7 @@ ixgbe_attach(device_t dev)
 	}
 
 	/* Initialize the shared code */
-	error = ixgbe_init_shared_code(&adapter->hw);
+	error = ixgbe_init_shared_code(hw);
 	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
 		/*
 		** No optics in this port, set up
@@ -525,11 +552,11 @@ ixgbe_attach(device_t dev)
 	adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
 	    ixgbe_unregister_vlan, 0, EVENTHANDLER_PRI_FIRST);
 #endif
-                
+
 	/* let hardware know driver is loaded */
-	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
 	ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
+	IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
 
 	INIT_DEBUGOUT("ixgbe_attach: end");
 	return (0);
@@ -590,6 +617,14 @@ ixgbe_detach(device_t dev)
 		}
 	}
 
+	/* Drain the Link queue */
+	if (adapter->tq) {
+		taskqueue_drain(adapter->tq, &adapter->link_task);
+		taskqueue_drain(adapter->tq, &adapter->mod_task);
+		taskqueue_drain(adapter->tq, &adapter->msf_task);
+		taskqueue_free(adapter->tq);
+	}
+
 	/* let hardware know driver is unloading */
 	ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
 	ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
@@ -662,6 +697,19 @@ ixgbe_start_locked(struct tx_ring *txr, 
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
 		if (m_head == NULL)
 			break;
+		/*
+		 * Force a cleanup if number of TX descriptors
+		 * available is below the threshold. If it fails
+		 * to get above, then abort transmit.
+		 */
+		if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) {
+			ixgbe_txeof(txr);
+			/* Make sure things have improved */
+			if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
+				txr->no_tx_desc_avail++;
+				break;
+			}
+		}
 
 		if (ixgbe_xmit(txr, &m_head)) {
 			if (m_head == NULL)
@@ -701,7 +749,8 @@ ixgbe_start(struct ifnet *ifp)
 	txr = &adapter->tx_rings[queue];
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-		IXGBE_TX_LOCK(txr);
+		if (IXGBE_TX_TRYLOCK(txr) == 0)
+			return;
 		ixgbe_start_locked(txr, ifp);
 		IXGBE_TX_UNLOCK(txr);
 	}
@@ -803,6 +852,67 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 #endif
 		break;
 	}
+#ifdef IXGBE_TIMESYNC
+	/*
+	** IOCTL support for Precision Time (IEEE 1588) Support
+	*/
+	case IXGBE_TIMESYNC_READTS:
+	    {
+		u32 rx_ctl, tx_ctl;
+		struct ixgbe_tsync_read *tdata;
+
+		tdata = (struct ixgbe_tsync_read *) ifr->ifr_data;
+
+		if (tdata->read_current_time) {
+                        getnanotime(&tdata->system_time);
+                        tdata->network_time = IXGBE_READ_REG(&adapter->hw,
+                            IXGBE_SYSTIML);
+                        tdata->network_time |=
+                            (u64)IXGBE_READ_REG(&adapter->hw,
+                            IXGBE_SYSTIMH ) << 32;
+		}
+  
+		rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+		tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+ 
+		if (rx_ctl & 0x1) {
+			u32 tmp;
+			unsigned char *tmp_cp;
+
+			tdata->rx_valid = 1;
+			tdata->rx_stamp = IXGBE_READ_REG(&adapter->hw,
+			    IXGBE_RXSTMPL);
+			tdata->rx_stamp |= (u64)IXGBE_READ_REG(&adapter->hw,
+                            IXGBE_RXSTMPH) << 32;
+
+			tmp = IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRL);
+			tmp_cp = (unsigned char *) &tmp;
+			tdata->srcid[0] = tmp_cp[0];
+			tdata->srcid[1] = tmp_cp[1];
+			tdata->srcid[2] = tmp_cp[2];
+			tdata->srcid[3] = tmp_cp[3];
+			tmp = IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRH);
+			tmp_cp = (unsigned char *) &tmp;
+			tdata->srcid[4] = tmp_cp[0];
+			tdata->srcid[5] = tmp_cp[1];
+			tdata->seqid = tmp >> 16;
+			tdata->seqid = htons(tdata->seqid);
+		} else
+                        tdata->rx_valid = 0;
+
+		if (tx_ctl & 0x1) {
+			tdata->tx_valid = 1;
+			tdata->tx_stamp = IXGBE_READ_REG(&adapter->hw,
+			    IXGBE_TXSTMPL);
+			tdata->tx_stamp |= (u64) IXGBE_READ_REG(&adapter->hw,
+			    IXGBE_TXSTMPH) << 32;
+		} else
+			tdata->tx_valid = 0;
+
+		return (0);
+	    }
+#endif  /* IXGBE_TIMESYNC */
+
 	default:
 		IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
 		error = ether_ioctl(ifp, command, data);
@@ -905,13 +1015,12 @@ ixgbe_watchdog(struct adapter *adapter)
 static void
 ixgbe_init_locked(struct adapter *adapter)
 {
-	struct rx_ring *rxr = adapter->rx_rings;
-	struct tx_ring *txr = adapter->tx_rings;
 	struct ifnet   *ifp = adapter->ifp;
 	device_t 	dev = adapter->dev;
 	struct ixgbe_hw *hw;
 	u32		k, txdctl, mhadd, gpie;
 	u32		rxdctl, rxctrl;
+	int		err;
 
 	INIT_DEBUGOUT("ixgbe_init: begin");
 
@@ -951,13 +1060,6 @@ ixgbe_init_locked(struct adapter *adapte
 
 	ixgbe_initialize_transmit_units(adapter);
 
-	/* TX irq moderation rate is fixed */
-	for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
-		IXGBE_WRITE_REG(&adapter->hw,
-		    IXGBE_EITR(txr->msix), ixgbe_ave_latency);
-		txr->watchdog_timer = FALSE;
-	}
-
 	/* Setup Multicast table */
 	ixgbe_set_multi(adapter);
 
@@ -980,23 +1082,21 @@ ixgbe_init_locked(struct adapter *adapte
 	/* Configure RX settings */
 	ixgbe_initialize_receive_units(adapter);
 
-	/* RX moderation will be adapted over time, set default */
-	for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
-		IXGBE_WRITE_REG(&adapter->hw,
-		    IXGBE_EITR(rxr->msix), ixgbe_low_latency);
-	}
-
-	/* Set Link moderation */
-	IXGBE_WRITE_REG(&adapter->hw,
-	    IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR);
+	/* Configure Interrupt Moderation */
+	ixgbe_init_moderation(adapter);
 
 	gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
 
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		gpie |= IXGBE_SDP1_GPIEN;
+		gpie |= IXGBE_SDP2_GPIEN;
+	}
+
 	/* Enable Fan Failure Interrupt */
-	if (adapter->hw.phy.media_type == ixgbe_media_type_copper)
+	if (hw->device_id == IXGBE_DEV_ID_82598AT)
 		gpie |= IXGBE_SDP1_GPIEN;
 
-	if (adapter->msix) {
+	if (adapter->msix > 2) {
 		/* Enable Enhanced MSIX mode */
 		gpie |= IXGBE_GPIE_MSIX_MODE;
 		gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
@@ -1058,9 +1158,40 @@ ixgbe_init_locked(struct adapter *adapte
 	/* Set up MSI/X routing */
 	if (ixgbe_enable_msix)
 		ixgbe_configure_ivars(adapter);
+	else {	/* Simple settings for Legacy/MSI */
+                ixgbe_set_ivar(adapter, 0, 0, 0);
+                ixgbe_set_ivar(adapter, 0, 0, 1);
+	}
 
 	ixgbe_enable_intr(adapter);
 
+	/*
+	** 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);
+
+
+#ifdef IXGBE_TIMESYNC
+	/* Initialize IEEE 1588 support */
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+		ixgbe_tsync_init(adapter);
+#endif
+
 	/* Now inform the stack we're ready */
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -1081,7 +1212,7 @@ ixgbe_init(void *arg)
 
 
 /*
-** MSIX Interrupt Handlers
+** MSIX Interrupt Tasklets
 */
 
 static void
@@ -1136,7 +1267,8 @@ ixgbe_legacy_irq(void *arg)
 	struct ixgbe_hw	*hw = &adapter->hw;
 	struct 		tx_ring *txr = adapter->tx_rings;
 	struct		rx_ring *rxr = adapter->rx_rings;
-	u32       	reg_eicr;
+	bool		more;
+	u32       	reg_eicr, loop = MAX_LOOP;
 
 
 	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
@@ -1148,7 +1280,15 @@ ixgbe_legacy_irq(void *arg)
 
 	if (ixgbe_rxeof(rxr, adapter->rx_process_limit))
 		taskqueue_enqueue(rxr->tq, &rxr->rx_task);
-	if (ixgbe_txeof(txr))
+
+	IXGBE_TX_LOCK(txr);
+	++txr->tx_irq;
+	do {
+		more = ixgbe_txeof(txr);
+	} while (loop-- && more);
+	IXGBE_TX_UNLOCK(txr);
+
+	if (more)
 		taskqueue_enqueue(txr->tq, &txr->tx_task);
 
 	/* Check for fan failure */
@@ -1160,20 +1300,27 @@ ixgbe_legacy_irq(void *arg)
 	}
 
 	/* Link status change */
-	if (reg_eicr & IXGBE_EICR_LSC)
+	if (reg_eicr & IXGBE_EICR_LSC) {
+		ixgbe_check_link(&adapter->hw,
+		    &adapter->link_speed, &adapter->link_up, 0);
         	ixgbe_update_link_status(adapter);
+	}
+
+	/* Update interrupt rate */
+	if (ixgbe_enable_aim == TRUE)
+		ixgbe_update_aim(rxr);
 
 	ixgbe_enable_intr(adapter);
 	return;
 }
 
 
+#if __FreeBSD_version >= 602105
 /*********************************************************************
  *
  *  MSI TX Interrupt Service routine
  *
  **********************************************************************/
-
 void
 ixgbe_msix_tx(void *arg)
 {
@@ -1181,6 +1328,8 @@ ixgbe_msix_tx(void *arg)
 	struct adapter  *adapter = txr->adapter;
 	bool		more;
 
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, txr->eims);
+
 	IXGBE_TX_LOCK(txr);
 	++txr->tx_irq;
 	more = ixgbe_txeof(txr);
@@ -1198,7 +1347,6 @@ ixgbe_msix_tx(void *arg)
  *  MSIX RX Interrupt Service routine
  *
  **********************************************************************/
-
 static void
 ixgbe_msix_rx(void *arg)
 {
@@ -1206,18 +1354,72 @@ ixgbe_msix_rx(void *arg)
 	struct adapter  *adapter = rxr->adapter;
 	bool		more;
 
+       	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims);
+
 	++rxr->rx_irq;
-	more = ixgbe_rxeof(rxr, -1);
+	more = ixgbe_rxeof(rxr, adapter->rx_process_limit);
+
+	/* Update interrupt rate */
+	if (ixgbe_enable_aim == TRUE)
+		ixgbe_update_aim(rxr);
+
 	if (more)
 		taskqueue_enqueue(rxr->tq, &rxr->rx_task);
 	else
         	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->eims);
-	/* Update interrupt rate */
-	if (ixgbe_enable_aim == TRUE)
-		ixgbe_update_aim(rxr);
 	return;
 }
 
+
+static void
+ixgbe_msix_link(void *arg)
+{
+	struct adapter	*adapter = arg;
+	struct ixgbe_hw *hw = &adapter->hw;
+	u32		reg_eicr;
+
+	++adapter->link_irq;
+
+	/* First get the cause */
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, IXGBE_EIMS_OTHER);
+	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+	/* Clear with write */
+	IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
+
+	/* Link status change */
+	if (reg_eicr & IXGBE_EICR_LSC)
+		taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+		if (reg_eicr & IXGBE_EICR_ECC) {
+                	device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
+			    "Please Reboot!!\n");
+			IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
+		}
+		if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
+                	/* Clear the interrupt */
+                	IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+        	} else if (reg_eicr & IXGBE_EICR_GPI_SDP2) {
+                	/* Clear the interrupt */
+                	IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+		}
+        } 
+
+	/* Check for fan failure */
+	if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
+	    (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
+                device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
+		    "REPLACE IMMEDIATELY!!\n");
+		IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+	}
+
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
+	return;
+}
+#endif /* FreeBSD_version >= 602105 */
+
 /*
 ** Routine to do adjust the RX EITR value based on traffic,
 ** its a simple three state model, but seems to help.
@@ -1267,33 +1469,36 @@ ixgbe_update_aim(struct rx_ring *rxr)
 	return;
 }
 
-
 static void
-ixgbe_msix_link(void *arg)
+ixgbe_init_moderation(struct adapter *adapter)
 {
-	struct adapter	*adapter = arg;
-	struct ixgbe_hw *hw = &adapter->hw;
-	u32		reg_eicr;
-
-	++adapter->link_irq;
+	struct rx_ring *rxr = adapter->rx_rings;
+	struct tx_ring *txr = adapter->tx_rings;
 
-	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+	/* Single interrupt - MSI or Legacy? */
+	if (adapter->msix < 2) {
+		IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(0), 100);
+		return;
+	}
 
-	if (reg_eicr & IXGBE_EICR_LSC)
-        	ixgbe_update_link_status(adapter);
+	/* TX irq moderation rate is fixed */
+	for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
+		IXGBE_WRITE_REG(&adapter->hw,
+		    IXGBE_EITR(txr->msix), ixgbe_ave_latency);
+		txr->watchdog_timer = FALSE;
+	}
 
-	/* Check for fan failure */
-	if ((hw->phy.media_type == ixgbe_media_type_copper) &&
-	    (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
-                device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
-		    "REPLACE IMMEDIATELY!!\n");
-		IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1);
+	/* RX moderation will be adapted over time, set default */
+	for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
+		IXGBE_WRITE_REG(&adapter->hw,
+		    IXGBE_EITR(rxr->msix), ixgbe_low_latency);
 	}
 
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
-	return;
-}
+	/* Set Link moderation */
+	IXGBE_WRITE_REG(&adapter->hw,
+	    IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR);
 
+}
 
 /*********************************************************************
  *
@@ -1382,12 +1587,12 @@ static int
 ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
 {
 	struct adapter  *adapter = txr->adapter;
-	u32		olinfo_status = 0, cmd_type_len = 0;
+	u32		olinfo_status = 0, cmd_type_len;
 	u32		paylen = 0;
 	int             i, j, error, nsegs;
-	int		first, last = 0;
+	int		first, last = 0, offload = 0;
 	struct mbuf	*m_head;
-	bus_dma_segment_t segs[IXGBE_MAX_SCATTER];
+	bus_dma_segment_t segs[ixgbe_num_segs];
 	bus_dmamap_t	map;
 	struct ixgbe_tx_buf *txbuf, *txbuf_mapped;
 	union ixgbe_adv_tx_desc *txd = NULL;
@@ -1395,26 +1600,12 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 	m_head = *m_headp;
 
 	/* Basic descriptor defines */
-        cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA;
-        cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT;
+        cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA |
+	    IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
 
 	if (m_head->m_flags & M_VLANTAG)
         	cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
 
-	/*
-	 * Force a cleanup if number of TX descriptors
-	 * available is below the threshold. If it fails
-	 * to get above, then abort transmit.
-	 */
-	if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) {
-		ixgbe_txeof(txr);
-		/* Make sure things have improved */
-		if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
-			txr->no_tx_desc_avail++;
-			return (ENOBUFS);
-		}
-	}
-
         /*
          * Important to capture the first descriptor
          * used because it will contain the index of
@@ -1475,19 +1666,27 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 	m_head = *m_headp;
 
 	/*
-	** Set the appropriate offload context
+	** Set up the appropriate offload context
 	** this becomes the first descriptor of 
 	** a packet.
 	*/
-	if (ixgbe_tso_setup(txr, m_head, &paylen)) {
-		cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
-		olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
-		olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-		olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
-		++adapter->tso_tx;
-	} else if (ixgbe_tx_ctx_setup(txr, m_head))
+	if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+		if (ixgbe_tso_setup(txr, m_head, &paylen)) {
+			cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+			olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
 			olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-
+			olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
+			++adapter->tso_tx;
+		} else
+			return (ENXIO);
+	} else /* Offloads other than TSO */
+		offload = ixgbe_tx_ctx_setup(txr, m_head);
+	if (offload == TRUE)
+		olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
+#ifdef IXGBE_TIMESYNC
+	if (offload == IXGBE_TIMESTAMP)
+		cmd_type_len |= IXGBE_ADVTXD_TSTAMP;
+#endif
         /* Record payload length */
 	if (paylen == 0)
         	olinfo_status |= m_head->m_pkthdr.len <<
@@ -1513,6 +1712,7 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 			i = 0;
 
 		txbuf->m_head = NULL;
+		txbuf->eop_index = -1;
 	}
 
 	txd->read.cmd_type_len |=
@@ -1526,6 +1726,7 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 
         /* Set the index of the descriptor that will be marked done */
         txbuf = &txr->tx_buffers[first];
+	txbuf->eop_index = last;
 
         bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1685,17 +1886,20 @@ out:
 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
 }
 
+/*
+** Note: this routine updates the OS on the link state
+**	the real check of the hardware only happens with
+**	a link interrupt.
+*/
 static void
 ixgbe_update_link_status(struct adapter *adapter)
 {
-	boolean_t link_up = FALSE;
 	struct ifnet	*ifp = adapter->ifp;
 	struct tx_ring *txr = adapter->tx_rings;
 	device_t dev = adapter->dev;
 
-	ixgbe_check_link(&adapter->hw, &adapter->link_speed, &link_up, 0);
 
-	if (link_up){ 
+	if (adapter->link_up){ 
 		if (adapter->link_active == FALSE) {
 			if (bootverbose)
 				device_printf(dev,"Link is up %d Gbps %s \n",
@@ -1720,7 +1924,6 @@ ixgbe_update_link_status(struct adapter 
 }
 
 
-
 /*********************************************************************
  *
  *  This routine disables all traffic on the adapter by issuing a
@@ -1743,6 +1946,11 @@ ixgbe_stop(void *arg)
 	/* Tell the stack that the interface is no longer active */
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
+#ifdef IXGBE_TIMESYNC
+	/* Disable IEEE 1588 support */
+	if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+		ixgbe_tsync_disable(adapter);
+#endif
 	ixgbe_reset_hw(&adapter->hw);
 	adapter->hw.adapter_stopped = FALSE;
 	ixgbe_stop_adapter(&adapter->hw);
@@ -1817,8 +2025,13 @@ ixgbe_allocate_legacy(struct adapter *ad
             device_get_nameunit(adapter->dev));
 	taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq",
             device_get_nameunit(adapter->dev));
+
 	if ((error = bus_setup_intr(dev, adapter->res[0],
+#if __FreeBSD_version >= 700000
             INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq,
+#else
+            INTR_TYPE_NET | INTR_MPSAFE, ixgbe_legacy_irq,
+#endif
             adapter, &adapter->tag[0])) != 0) {
 		device_printf(dev, "Failed to register fast interrupt "
 		    "handler: %d\n", error);
@@ -1833,6 +2046,7 @@ ixgbe_allocate_legacy(struct adapter *ad
 }
 
 
+#if __FreeBSD_version >= 602105
 /*********************************************************************
  *
  *  Setup MSIX Interrupt resources and handlers 
@@ -1859,7 +2073,10 @@ ixgbe_allocate_msix(struct adapter *adap
 		}
 		/* Set the handler function */
 		error = bus_setup_intr(dev, adapter->res[vector],
-		    INTR_TYPE_NET | INTR_MPSAFE, NULL,
+		    INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+		    NULL,
+#endif
 		    ixgbe_msix_tx, txr, &adapter->tag[vector]);
 		if (error) {
 			adapter->res[vector] = NULL;
@@ -1867,7 +2084,7 @@ ixgbe_allocate_msix(struct adapter *adap
 			return (error);
 		}
 		txr->msix = vector;
-		txr->eims = IXGBE_IVAR_TX_QUEUE(vector);
+		txr->eims = 1 << vector;
 		TASK_INIT(&txr->tx_task, 0, ixgbe_handle_tx, txr);
 		txr->tq = taskqueue_create_fast("ixgbe_txq", M_NOWAIT,
 		    taskqueue_thread_enqueue, &txr->tq);
@@ -1888,15 +2105,18 @@ ixgbe_allocate_msix(struct adapter *adap
 		}
 		/* Set the handler function */
 		error = bus_setup_intr(dev, adapter->res[vector],
-		    INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_rx,
-		    rxr, &adapter->tag[vector]);
+		    INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+		    NULL,
+#endif
+		    ixgbe_msix_rx, rxr, &adapter->tag[vector]);
 		if (error) {
 			adapter->res[vector] = NULL;
 			device_printf(dev, "Failed to register RX handler");
 			return (error);
 		}
 		rxr->msix = vector;
-		rxr->eims = IXGBE_IVAR_RX_QUEUE(vector);
+		rxr->eims = 1 << vector;
 		/* used in local timer */
 		adapter->rx_mask |= rxr->eims;
 		TASK_INIT(&rxr->rx_task, 0, ixgbe_handle_rx, rxr);
@@ -1916,19 +2136,37 @@ ixgbe_allocate_msix(struct adapter *adap
 	}
 	/* Set the link handler function */
 	error = bus_setup_intr(dev, adapter->res[vector],
-	    INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_link,
-	    adapter, &adapter->tag[vector]);
+	    INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+		    NULL,
+#endif
+	    ixgbe_msix_link, adapter, &adapter->tag[vector]);
 	if (error) {
 		adapter->res[vector] = NULL;
 		device_printf(dev, "Failed to register LINK handler");
 		return (error);
 	}
 	adapter->linkvec = vector;
+	/* Tasklets for Link, SFP and Multispeed Fiber */
+	TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
+	TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
+	TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
+	adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
+	    taskqueue_thread_enqueue, &adapter->tq);
+	taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
+	    device_get_nameunit(adapter->dev));
 
 	return (0);
 }
+#else  /* Freebsd 6.1/2 */
+static int
+ixgbe_allocate_msix(struct adapter *adapter)
+{
+	return (1);
+}
+#endif
 
-
+#if __FreeBSD_version >= 602105
 /*
  * Setup Either MSI/X or MSI
  */
@@ -1996,6 +2234,7 @@ msi:
                	device_printf(adapter->dev,"Using MSI interrupt\n");
 	return (msgs);
 }
+#endif /* FreeBSD_version >= 602105 */
 
 static int
 ixgbe_allocate_pci_resources(struct adapter *adapter)
@@ -2031,9 +2270,10 @@ ixgbe_allocate_pci_resources(struct adap
 	adapter->num_tx_queues = 1;
 	adapter->num_rx_queues = 1;
 
+#if __FreeBSD_version >= 602105
 	/* Now setup MSI or MSI/X */
 	adapter->msix = ixgbe_setup_msix(adapter);
-
+#endif
 	adapter->hw.back = &adapter->osdep;
 	return (0);
 }
@@ -2051,7 +2291,10 @@ ixgbe_free_pci_resources(struct adapter 
 	if (adapter->msix == 0)
 		adapter->msix = 1;
 
-	rid = PCIR_BAR(MSIX_82598_BAR);
+	if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+		rid = PCIR_BAR(MSIX_82598_BAR);
+	else
+		rid = PCIR_BAR(MSIX_82599_BAR);
 
 	/*
 	 * First release all the interrupt resources:
@@ -2071,12 +2314,14 @@ ixgbe_free_pci_resources(struct adapter 
 		}
 	}
 
+#if __FreeBSD_version >= 602105
 	if (adapter->msix)
 		pci_release_msi(dev);
 
 	if (adapter->msix_mem != NULL)
 		bus_release_resource(dev, SYS_RES_MEMORY,
 		    rid, adapter->msix_mem);
+#endif
 
 	if (adapter->pci_mem != NULL)
 		bus_release_resource(dev, SYS_RES_MEMORY,
@@ -2215,7 +2460,7 @@ ixgbe_dma_malloc(struct adapter *adapter
 	int             r;
 
 	r = bus_dma_tag_create(NULL,	/* parent */
-			       PAGE_SIZE, 0,	/* alignment, bounds */
+			       1, 0,	/* alignment, bounds */
 			       BUS_SPACE_MAXADDR,	/* lowaddr */
 			       BUS_SPACE_MAXADDR,	/* highaddr */
 			       NULL, NULL,	/* filter, filterarg */
@@ -2415,12 +2660,12 @@ ixgbe_allocate_transmit_buffers(struct t
 	 * Setup DMA descriptor areas.
 	 */
 	if ((error = bus_dma_tag_create(NULL,		/* parent */
-			       PAGE_SIZE, 0,		/* alignment, bounds */
+			       1, 0,		/* alignment, bounds */
 			       BUS_SPACE_MAXADDR,	/* lowaddr */
 			       BUS_SPACE_MAXADDR,	/* highaddr */
 			       NULL, NULL,		/* filter, filterarg */
 			       IXGBE_TSO_SIZE,		/* maxsize */
-			       IXGBE_MAX_SCATTER,	/* nsegments */
+			       ixgbe_num_segs,		/* nsegments */
 			       PAGE_SIZE,		/* maxsegsize */
 			       0,			/* flags */
 			       NULL,			/* lockfunc */
@@ -2484,6 +2729,8 @@ ixgbe_setup_transmit_ring(struct tx_ring
 			m_freem(txbuf->m_head);
 			txbuf->m_head = NULL;
 		}
+		/* Clear the EOP index */
+		txbuf->eop_index = -1;

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



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