svn commit: r215911 - in head/sys: conf dev/ixgbe modules/ixgbe

Jack F Vogel jfv at FreeBSD.org
Fri Nov 26 22:46:33 UTC 2010


Author: jfv
Date: Fri Nov 26 22:46:32 2010
New Revision: 215911
URL: http://svn.freebsd.org/changeset/base/215911

Log:
  Update ixgbe driver to verion 2.3.6
  	- This adds a VM SRIOV interface, ixv, it is however
  	  transparent to the user, it links with the ixgbe.ko,
  	  but when ixgbe is loaded in a virtualized guest with
  	  SRIOV configured this will be detected.
  	- Sync shared code to latest
  	- Many bug fixes and improvements, thanks to everyone
  	  who has been using the driver and reporting issues.

Added:
  head/sys/dev/ixgbe/ixgbe_mbx.c   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_mbx.h   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_vf.c   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_vf.h   (contents, props changed)
  head/sys/dev/ixgbe/ixv.c   (contents, props changed)
  head/sys/dev/ixgbe/ixv.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/ixgbe/ixgbe.c
  head/sys/dev/ixgbe/ixgbe.h
  head/sys/dev/ixgbe/ixgbe_82598.c
  head/sys/dev/ixgbe/ixgbe_82599.c
  head/sys/dev/ixgbe/ixgbe_api.c
  head/sys/dev/ixgbe/ixgbe_api.h
  head/sys/dev/ixgbe/ixgbe_common.c
  head/sys/dev/ixgbe/ixgbe_common.h
  head/sys/dev/ixgbe/ixgbe_osdep.h
  head/sys/dev/ixgbe/ixgbe_phy.c
  head/sys/dev/ixgbe/ixgbe_phy.h
  head/sys/dev/ixgbe/ixgbe_type.h
  head/sys/modules/ixgbe/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Fri Nov 26 22:36:47 2010	(r215910)
+++ head/sys/conf/files	Fri Nov 26 22:46:32 2010	(r215911)
@@ -1252,12 +1252,18 @@ dev/ixgb/ixgb_ee.c		optional ixgb
 dev/ixgb/ixgb_hw.c		optional ixgb
 dev/ixgbe/ixgbe.c		optional ixgbe inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixv.c			optional ixgbe inet \
+	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_phy.c		optional ixgbe inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_api.c		optional ixgbe inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_common.c	optional ixgbe inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_mbx.c		optional ixgbe inet \
+	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_vf.c		optional ixgbe inet \
+	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_82598.c		optional ixgbe inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_82599.c		optional ixgbe inet \

Modified: head/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- head/sys/dev/ixgbe/ixgbe.c	Fri Nov 26 22:36:47 2010	(r215910)
+++ head/sys/dev/ixgbe/ixgbe.c	Fri Nov 26 22:46:32 2010	(r215911)
@@ -46,7 +46,7 @@ int             ixgbe_display_debug_stat
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "2.2.3";
+char ixgbe_driver_version[] = "2.3.6";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -78,6 +78,8 @@ static ixgbe_vendor_info_t ixgbe_vendor_
 	{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},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_BACKPLANE_FCOE, 0, 0, 0},
+	{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
 	/* required last entry */
 	{0, 0, 0, 0, 0}
 };
@@ -119,7 +121,7 @@ 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_setup_interface(device_t, 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 *);
@@ -144,7 +146,6 @@ static bool	ixgbe_txeof(struct tx_ring *
 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 *);
@@ -212,7 +213,7 @@ static driver_t ixgbe_driver = {
 	"ix", ixgbe_methods, sizeof(struct adapter),
 };
 
-static devclass_t ixgbe_devclass;
+devclass_t ixgbe_devclass;
 DRIVER_MODULE(ixgbe, pci, ixgbe_driver, ixgbe_devclass, 0, 0);
 
 MODULE_DEPEND(ixgbe, pci, 1, 1, 1);
@@ -257,7 +258,7 @@ TUNABLE_INT("hw.ixgbe.enable_msix", &ixg
 
 /*
  * Header split: this causes the hardware to DMA
- * the header into a separate mbuf from the payload,
+ * the header into a seperate mbuf from the payload,
  * it can be a performance win in some workloads, but
  * in others it actually hurts, its off by default. 
  */
@@ -289,13 +290,6 @@ TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
 static int ixgbe_total_ports;
 
 /*
-** Shadow VFTA table, this is needed because
-** the real filter table gets cleared during
-** a soft reset and we need to repopulate it.
-*/
-static u32 ixgbe_shadow_vfta[IXGBE_VFTA_SIZE];
-
-/*
 ** The number of scatter-gather segments
 ** differs for 82598 and 82599, default to
 ** the former.
@@ -446,6 +440,7 @@ ixgbe_attach(device_t dev)
 			ixgbe_num_segs = IXGBE_82599_SCATTER;
 			adapter->optics = IFM_10G_T;
 		default:
+			ixgbe_num_segs = IXGBE_82599_SCATTER;
 			break;
 	}
 
@@ -524,15 +519,6 @@ ixgbe_attach(device_t dev)
 		goto err_out;
 	}
 
-	/* Allocate multicast array memory. */
-	adapter->mta = malloc(sizeof(u8) * IXGBE_ETH_LENGTH_OF_ADDRESS *
-	    MAX_NUM_MULTICAST_ADDRESSES, M_DEVBUF, M_NOWAIT);
-	if (adapter->mta == NULL) {
-		device_printf(dev, "Can not allocate multicast setup array\n");
-		error = ENOMEM;
-		goto err_late;
-	}
-
 	/* Initialize the shared code */
 	error = ixgbe_init_shared_code(hw);
 	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
@@ -595,8 +581,7 @@ ixgbe_attach(device_t dev)
 		goto err_late;
 
 	/* Setup OS specific network interface */
-	if (ixgbe_setup_interface(dev, adapter) != 0)
-		goto err_late;
+	ixgbe_setup_interface(dev, adapter);
 
 	/* Sysctl for limiting the amount of work done in the taskqueue */
 	ixgbe_add_rx_process_limit(adapter, "rx_processing_limit",
@@ -642,10 +627,7 @@ err_late:
 	ixgbe_free_transmit_structures(adapter);
 	ixgbe_free_receive_structures(adapter);
 err_out:
-	if (adapter->ifp != NULL)
-		if_free(adapter->ifp);
 	ixgbe_free_pci_resources(adapter);
-	free(adapter->mta, M_DEVBUF);
 	return (error);
 
 }
@@ -716,7 +698,6 @@ ixgbe_detach(device_t dev)
 
 	ixgbe_free_transmit_structures(adapter);
 	ixgbe_free_receive_structures(adapter);
-	free(adapter->mta, M_DEVBUF);
 
 	IXGBE_CORE_LOCK_DESTROY(adapter);
 	return (0);
@@ -780,8 +761,8 @@ ixgbe_start_locked(struct tx_ring *txr, 
 		ETHER_BPF_MTAP(ifp, m_head);
 
 		/* Set watchdog on */
-		txr->watchdog_check = TRUE;
 		txr->watchdog_time = ticks;
+		txr->queue_status = IXGBE_QUEUE_WORKING;
 
 	}
 	return;
@@ -851,6 +832,10 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 		return (err);
 	}
 
+	/* Call cleanup if number of TX descriptors low */
+	if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD)
+		ixgbe_txeof(txr);
+
 	enqueued = 0;
 	if (m == NULL) {
 		next = drbr_dequeue(ifp, txr->br);
@@ -883,7 +868,7 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 
 	if (enqueued > 0) {
 		/* Set watchdog on */
-		txr->watchdog_check = TRUE;
+		txr->queue_status = IXGBE_QUEUE_WORKING;
 		txr->watchdog_time = ticks;
 	}
 
@@ -948,7 +933,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 			if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
 				if ((ifp->if_flags ^ adapter->if_flags) &
 				    (IFF_PROMISC | IFF_ALLMULTI)) {
-					ixgbe_disable_promisc(adapter);
 					ixgbe_set_promisc(adapter);
                                 }
 			} else
@@ -987,6 +971,8 @@ 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 (mask & IFCAP_VLAN_HWFILTER)
+			ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
 		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 			IXGBE_CORE_LOCK(adapter);
 			ixgbe_init_locked(adapter);
@@ -1041,6 +1027,18 @@ ixgbe_init_locked(struct adapter *adapte
 	ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
 	hw->addr_ctrl.rar_used_count = 1;
 
+	/* 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);
+#if __FreeBSD_version >= 800000
+		if (hw->mac.type == ixgbe_mac_82599EB)
+			ifp->if_hwassist |= CSUM_SCTP;
+#endif
+	}
+
 	/* Prepare transmit descriptors and buffers */
 	if (ixgbe_setup_transmit_structures(adapter)) {
 		device_printf(dev,"Could not setup transmit structures\n");
@@ -1058,10 +1056,12 @@ ixgbe_init_locked(struct adapter *adapte
 	** Determine the correct mbuf pool
 	** for doing jumbo/headersplit
 	*/
-	if (ifp->if_mtu > ETHERMTU)
+	if (adapter->max_frame_size <= 2048)
+		adapter->rx_mbuf_sz = MCLBYTES;
+	else if (adapter->max_frame_size <= 4096)
 		adapter->rx_mbuf_sz = MJUMPAGESIZE;
 	else
-		adapter->rx_mbuf_sz = MCLBYTES;
+		adapter->rx_mbuf_sz = MJUM9BYTES;
 
 	/* Prepare receive descriptors and buffers */
 	if (ixgbe_setup_receive_structures(adapter)) {
@@ -1092,18 +1092,6 @@ ixgbe_init_locked(struct adapter *adapte
 	}
 	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);
-#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(hw, IXGBE_MHADD);
@@ -1146,7 +1134,7 @@ ixgbe_init_locked(struct adapter *adapte
 		IXGBE_WRITE_REG(hw, IXGBE_RDT(i), adapter->num_rx_desc - 1);
 	}
 
-	/* Set up VLAN offloads and filter */
+	/* Set up VLAN support and filter */
 	ixgbe_setup_vlan_hw_support(adapter);
 
 	/* Enable Receive engine */
@@ -1760,10 +1748,6 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 	++txr->total_packets;
 	IXGBE_WRITE_REG(&adapter->hw, IXGBE_TDT(txr->me), i);
 
-	/* Do a clean if descriptors are low */
-	if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD)
-		ixgbe_txeof(txr);
-
 	return (0);
 
 xmit_fail:
@@ -1775,11 +1759,13 @@ xmit_fail:
 static void
 ixgbe_set_promisc(struct adapter *adapter)
 {
-
 	u_int32_t       reg_rctl;
 	struct ifnet   *ifp = adapter->ifp;
 
 	reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
+	reg_rctl &= (~IXGBE_FCTRL_UPE);
+	reg_rctl &= (~IXGBE_FCTRL_MPE);
+	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
 
 	if (ifp->if_flags & IFF_PROMISC) {
 		reg_rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
@@ -1792,20 +1778,6 @@ ixgbe_set_promisc(struct adapter *adapte
 	return;
 }
 
-static void
-ixgbe_disable_promisc(struct adapter * adapter)
-{
-	u_int32_t       reg_rctl;
-
-	reg_rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
-
-	reg_rctl &= (~IXGBE_FCTRL_UPE);
-	reg_rctl &= (~IXGBE_FCTRL_MPE);
-	IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_rctl);
-
-	return;
-}
-
 
 /*********************************************************************
  *  Multicast Update
@@ -1819,7 +1791,7 @@ static void
 ixgbe_set_multi(struct adapter *adapter)
 {
 	u32	fctrl;
-	u8	*mta;
+	u8	mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS];
 	u8	*update_ptr;
 	struct	ifmultiaddr *ifma;
 	int	mcnt = 0;
@@ -1827,10 +1799,6 @@ ixgbe_set_multi(struct adapter *adapter)
 
 	IOCTL_DEBUGOUT("ixgbe_set_multi: begin");
 
-	mta = adapter->mta;
-	bzero(mta, sizeof(u8) * IXGBE_ETH_LENGTH_OF_ADDRESS *
-	    MAX_NUM_MULTICAST_ADDRESSES);
-
 	fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL);
 	fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE);
 	if (ifp->if_flags & IFF_PROMISC)
@@ -1923,19 +1891,14 @@ ixgbe_local_timer(void *arg)
 	 */
 	if (IXGBE_READ_REG(&adapter->hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF)
 		goto out;
+
 	/*
-	** Check for time since any descriptor was cleaned
+	** Check status on the TX queues for a hang
 	*/
-        for (int i = 0; i < adapter->num_queues; i++, txr++) {
-		IXGBE_TX_LOCK(txr);
-		if (txr->watchdog_check == FALSE) {
-			IXGBE_TX_UNLOCK(txr);
-			continue;
-		}
-		if ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG)
+        for (int i = 0; i < adapter->num_queues; i++, txr++)
+		if (txr->queue_status == IXGBE_QUEUE_HUNG)
 			goto hung;
-		IXGBE_TX_UNLOCK(txr);
-	}
+
 out:
        	ixgbe_rearm_queues(adapter, adapter->que_mask);
 	callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
@@ -1985,7 +1948,7 @@ ixgbe_update_link_status(struct adapter 
 			adapter->link_active = FALSE;
 			for (int i = 0; i < adapter->num_queues;
 			    i++, txr++)
-				txr->watchdog_check = FALSE;
+				txr->queue_status = IXGBE_QUEUE_IDLE;
 		}
 	}
 
@@ -2005,6 +1968,7 @@ ixgbe_stop(void *arg)
 {
 	struct ifnet   *ifp;
 	struct adapter *adapter = arg;
+	struct ixgbe_hw *hw = &adapter->hw;
 	ifp = adapter->ifp;
 
 	mtx_assert(&adapter->core_mtx, MA_OWNED);
@@ -2015,9 +1979,12 @@ ixgbe_stop(void *arg)
 	/* Tell the stack that the interface is no longer active */
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
 
-	ixgbe_reset_hw(&adapter->hw);
-	adapter->hw.adapter_stopped = FALSE;
-	ixgbe_stop_adapter(&adapter->hw);
+	ixgbe_reset_hw(hw);
+	hw->adapter_stopped = FALSE;
+	ixgbe_stop_adapter(hw);
+	/* Turn off the laser */
+	if (hw->phy.multispeed_fiber)
+		ixgbe_disable_tx_laser(hw);
 	callout_stop(&adapter->timer);
 
 	/* reprogram the RAR[0] in case user changed it. */
@@ -2242,6 +2209,9 @@ ixgbe_setup_msix(struct adapter *adapter
 
 	if (ixgbe_num_queues != 0)
 		queues = ixgbe_num_queues;
+	/* Set max queues to 8 */
+	else if (queues > 8)
+		queues = 8;
 
 	/*
 	** Want one vector (RX/TX pair) per queue
@@ -2375,7 +2345,7 @@ mem:
  *  Setup networking device structure and register an interface.
  *
  **********************************************************************/
-static int
+static void
 ixgbe_setup_interface(device_t dev, struct adapter *adapter)
 {
 	struct ixgbe_hw *hw = &adapter->hw;
@@ -2384,10 +2354,8 @@ ixgbe_setup_interface(device_t dev, stru
 	INIT_DEBUGOUT("ixgbe_setup_interface: begin");
 
 	ifp = adapter->ifp = if_alloc(IFT_ETHER);
-	if (ifp == NULL) {
-		device_printf(dev, "can not allocate ifnet structure\n");
-		return (-1);
-	}
+	if (ifp == NULL)
+		panic("%s: can not if_alloc()\n", device_get_nameunit(dev));
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_mtu = ETHERMTU;
 	ifp->if_baudrate = 1000000000;
@@ -2414,10 +2382,22 @@ ixgbe_setup_interface(device_t dev, stru
 
 	ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
 	ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
-	ifp->if_capabilities |= IFCAP_JUMBO_MTU | IFCAP_LRO;
-
+	ifp->if_capabilities |= IFCAP_JUMBO_MTU;
 	ifp->if_capenable = ifp->if_capabilities;
 
+	/* Don't enable LRO by default */
+	ifp->if_capabilities |= IFCAP_LRO;
+
+	/*
+	** Dont turn this on by default, if vlans are
+	** created on another pseudo device (eg. lagg)
+	** then vlan events are not passed thru, breaking
+	** operation, but with HW FILTER off it works. If
+	** using vlans directly on the em driver you can
+	** enable this and get full hardware tag filtering.
+	*/
+	ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
+
 	/*
 	 * Specify the media types supported by this adapter and register
 	 * callbacks to update media and link information
@@ -2435,7 +2415,7 @@ ixgbe_setup_interface(device_t dev, stru
 	ifmedia_add(&adapter->media, IFM_ETHER | IFM_AUTO, 0, NULL);
 	ifmedia_set(&adapter->media, IFM_ETHER | IFM_AUTO);
 
-	return (0);
+	return;
 }
 
 static void
@@ -2450,6 +2430,7 @@ ixgbe_config_link(struct adapter *adapte
 	if (sfp) { 
 		if (hw->phy.multispeed_fiber) {
 			hw->mac.ops.setup_sfp(hw);
+			ixgbe_enable_tx_laser(hw);
 			taskqueue_enqueue(adapter->tq, &adapter->msf_task);
 		} else
 			taskqueue_enqueue(adapter->tq, &adapter->mod_task);
@@ -2856,7 +2837,7 @@ ixgbe_initialize_transmit_units(struct a
 
 		/* Setup Transmit Descriptor Cmd Settings */
 		txr->txd_cmd = IXGBE_TXD_CMD_IFCS;
-		txr->watchdog_check = FALSE;
+		txr->queue_status = IXGBE_QUEUE_IDLE;
 
 		/* Disable Head Writeback */
 		switch (hw->mac.type) {
@@ -3195,7 +3176,7 @@ ixgbe_atr(struct tx_ring *txr, struct mb
 {
 	struct adapter			*adapter = txr->adapter;
 	struct ix_queue			*que;
-	struct ixgbe_atr_input		atr_input;
+	union ixgbe_atr_input		atr_input;
 	struct ip			*ip;
 	struct tcphdr			*th;
 	struct udphdr			*uh;
@@ -3239,7 +3220,7 @@ ixgbe_atr(struct tx_ring *txr, struct mb
 		return;
 	}
 
-	memset(&atr_input, 0, sizeof(struct ixgbe_atr_input));
+	memset(&atr_input, 0, sizeof(union ixgbe_atr_input));
 
 	vlan_id = htole16(mp->m_pkthdr.ether_vtag);
 	src_ipv4_addr = ip->ip_src.s_addr;
@@ -3274,15 +3255,18 @@ ixgbe_txeof(struct tx_ring *txr)
 {
 	struct adapter	*adapter = txr->adapter;
 	struct ifnet	*ifp = adapter->ifp;
-	u32	first, last, done;
+	u32	first, last, done, processed;
 	struct ixgbe_tx_buf *tx_buffer;
 	struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc;
 
 	mtx_assert(&txr->tx_mtx, MA_OWNED);
 
-	if (txr->tx_avail == adapter->num_tx_desc)
+	if (txr->tx_avail == adapter->num_tx_desc) {
+		txr->queue_status = IXGBE_QUEUE_IDLE;
 		return FALSE;
+	}
 
+	processed = 0;
 	first = txr->next_to_clean;
 	tx_buffer = &txr->tx_buffers[first];
 	/* For cleanup we just use legacy struct */
@@ -3314,6 +3298,7 @@ ixgbe_txeof(struct tx_ring *txr)
 			tx_desc->lower.data = 0;
 			tx_desc->buffer_addr = 0;
 			++txr->tx_avail;
+			++processed;
 
 			if (tx_buffer->m_head) {
 				txr->bytes +=
@@ -3356,6 +3341,15 @@ ixgbe_txeof(struct tx_ring *txr)
 	txr->next_to_clean = first;
 
 	/*
+	** Watchdog calculation, we know there's
+	** work outstanding or the first return
+	** would have been taken, so none processed
+	** for too long indicates a hang.
+	*/
+	if ((!processed) && ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG))
+		txr->queue_status = IXGBE_QUEUE_HUNG;
+
+	/*
 	 * If we have enough room, clear IFF_DRV_OACTIVE to tell the stack that
 	 * it is OK to send packets. If there are no pending descriptors,
 	 * clear the timeout. Otherwise, if some descriptors have been freed,
@@ -3364,7 +3358,7 @@ ixgbe_txeof(struct tx_ring *txr)
 	if (txr->tx_avail > IXGBE_TX_CLEANUP_THRESHOLD) {
 		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 		if (txr->tx_avail == adapter->num_tx_desc) {
-			txr->watchdog_check = FALSE;
+			txr->queue_status = IXGBE_QUEUE_IDLE;
 			return FALSE;
 		}
 	}
@@ -3395,51 +3389,59 @@ ixgbe_refresh_mbufs(struct rx_ring *rxr,
 	cleaned = -1; /* Signify no completions */
 	while (i != limit) {
 		rxbuf = &rxr->rx_buffers[i];
-		if ((rxbuf->m_head == NULL) && (rxr->hdr_split)) {
+		if (rxr->hdr_split == FALSE)
+			goto no_split;
+
+		if (rxbuf->m_head == NULL) {
 			mh = m_gethdr(M_DONTWAIT, MT_DATA);
 			if (mh == NULL)
 				goto update;
-			mh->m_pkthdr.len = mh->m_len = MHLEN;
-			mh->m_len = MHLEN;
-			mh->m_flags |= M_PKTHDR;
-			m_adj(mh, ETHER_ALIGN);
-			/* Get the memory mapping */
-			error = bus_dmamap_load_mbuf_sg(rxr->htag,
-			    rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
-			if (error != 0) {
-				printf("GET BUF: dmamap load"
-				    " failure - %d\n", error);
-				m_free(mh);
-				goto update;
-			}
-			rxbuf->m_head = mh;
-			bus_dmamap_sync(rxr->htag, rxbuf->hmap,
-			    BUS_DMASYNC_PREREAD);
-			rxr->rx_base[i].read.hdr_addr =
-			    htole64(hseg[0].ds_addr);
+		} else
+			mh = rxbuf->m_head;
+
+		mh->m_pkthdr.len = mh->m_len = MHLEN;
+		mh->m_len = MHLEN;
+		mh->m_flags |= M_PKTHDR;
+		/* Get the memory mapping */
+		error = bus_dmamap_load_mbuf_sg(rxr->htag,
+		    rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
+		if (error != 0) {
+			printf("Refresh mbufs: hdr dmamap load"
+			    " failure - %d\n", error);
+			m_free(mh);
+			rxbuf->m_head = NULL;
+			goto update;
 		}
+		rxbuf->m_head = mh;
+		bus_dmamap_sync(rxr->htag, rxbuf->hmap,
+		    BUS_DMASYNC_PREREAD);
+		rxr->rx_base[i].read.hdr_addr = htole64(hseg[0].ds_addr);
 
+no_split:
 		if (rxbuf->m_pack == NULL) {
 			mp = m_getjcl(M_DONTWAIT, MT_DATA,
 			    M_PKTHDR, adapter->rx_mbuf_sz);
 			if (mp == NULL)
 				goto update;
-			mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
-			/* Get the memory mapping */
-			error = bus_dmamap_load_mbuf_sg(rxr->ptag,
-			    rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
-			if (error != 0) {
-				printf("GET BUF: dmamap load"
-				    " failure - %d\n", error);
-				m_free(mp);
-				goto update;
-			}
-			rxbuf->m_pack = mp;
-			bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
-			    BUS_DMASYNC_PREREAD);
-			rxr->rx_base[i].read.pkt_addr =
-			    htole64(pseg[0].ds_addr);
+		} else
+			mp = rxbuf->m_pack;
+
+		mp->m_pkthdr.len = mp->m_len = adapter->rx_mbuf_sz;
+		/* Get the memory mapping */
+		error = bus_dmamap_load_mbuf_sg(rxr->ptag,
+		    rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
+		if (error != 0) {
+			printf("Refresh mbufs: payload dmamap load"
+			    " failure - %d\n", error);
+			m_free(mp);
+			rxbuf->m_pack = NULL;
+			goto update;
 		}
+		rxbuf->m_pack = mp;
+		bus_dmamap_sync(rxr->ptag, rxbuf->pmap,
+		    BUS_DMASYNC_PREREAD);
+		rxr->rx_base[i].read.pkt_addr =
+		    htole64(pseg[0].ds_addr);
 
 		cleaned = i;
 		/* Calculate next index */
@@ -3501,9 +3503,9 @@ ixgbe_allocate_receive_buffers(struct rx
 				   BUS_SPACE_MAXADDR,	/* lowaddr */
 				   BUS_SPACE_MAXADDR,	/* highaddr */
 				   NULL, NULL,		/* filter, filterarg */
-				   MJUMPAGESIZE,	/* maxsize */
+				   MJUM9BYTES,		/* maxsize */
 				   1,			/* nsegments */
-				   MJUMPAGESIZE,	/* maxsegsize */
+				   MJUM9BYTES,		/* maxsegsize */
 				   0,			/* flags */
 				   NULL,		/* lockfunc */
 				   NULL,		/* lockfuncarg */
@@ -3661,7 +3663,7 @@ ixgbe_setup_receive_ring(struct rx_ring 
 
 		rxbuf = &rxr->rx_buffers[j];
 		/*
-		** Don't allocate mbufs if not
+		** Dont allocate mbufs if not
 		** doing header split, its wasteful
 		*/ 
 		if (rxr->hdr_split == FALSE)
@@ -4027,25 +4029,33 @@ ixgbe_rx_input(struct rx_ring *rxr, stru
 static __inline void
 ixgbe_rx_discard(struct rx_ring *rxr, int i)
 {
-	struct adapter		*adapter = rxr->adapter;
 	struct ixgbe_rx_buf	*rbuf;
-	struct mbuf		*mh, *mp;
 
 	rbuf = &rxr->rx_buffers[i];
-        if (rbuf->fmp != NULL) /* Partial chain ? */
+
+        if (rbuf->fmp != NULL) {/* Partial chain ? */
+		rbuf->fmp->m_flags |= M_PKTHDR;
                 m_freem(rbuf->fmp);
+                rbuf->fmp = NULL;
+	}
 
-	mh = rbuf->m_head;
-	mp = rbuf->m_pack;
+	/*
+	** With advanced descriptors the writeback
+	** clobbers the buffer addrs, so its easier
+	** to just free the existing mbufs and take
+	** the normal refresh path to get new buffers
+	** and mapping.
+	*/
+	if (rbuf->m_head) {
+		m_free(rbuf->m_head);
+		rbuf->m_head = NULL;
+	}
+ 
+	if (rbuf->m_pack) {
+		m_free(rbuf->m_pack);
+		rbuf->m_pack = NULL;
+	}
 
-	/* Reuse loaded DMA map and just update mbuf chain */
-	mh->m_len = MHLEN;
-	mh->m_flags |= M_PKTHDR;
-	mh->m_next = NULL;
-
-	mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz;
-	mp->m_data = mp->m_ext.ext_buf;
-	mp->m_next = NULL;
 	return;
 }
 
@@ -4110,15 +4120,15 @@ ixgbe_rxeof(struct ix_queue *que, int co
 		vtag = le16toh(cur->wb.upper.vlan);
 		eop = ((staterr & IXGBE_RXD_STAT_EOP) != 0);
 
-		/* Make sure all parts of a bad packet are discarded */
+		/* Make sure bad packets are discarded */
 		if (((staterr & IXGBE_RXDADV_ERR_FRAME_ERR_MASK) != 0) ||
 		    (rxr->discard)) {
 			ifp->if_ierrors++;
 			rxr->rx_discarded++;
-			if (!eop)
-				rxr->discard = TRUE;
-			else
+			if (eop)
 				rxr->discard = FALSE;
+			else
+				rxr->discard = TRUE;
 			ixgbe_rx_discard(rxr, i);
 			goto next_desc;
 		}
@@ -4129,7 +4139,7 @@ ixgbe_rxeof(struct ix_queue *que, int co
 		** not be fragmented across sequential
 		** descriptors, rather the next descriptor
 		** is indicated in bits of the descriptor.
-		** This also means that we might process
+		** This also means that we might proceses
 		** more than one packet at a time, something
 		** that has never been true before, it
 		** required eliminating global chain pointers
@@ -4210,7 +4220,8 @@ ixgbe_rxeof(struct ix_queue *que, int co
                         } else {
 				/* Singlet, prepare to send */
                                 sendmp = mh;
-                                if (staterr & IXGBE_RXD_STAT_VP) {
+                                if ((adapter->num_vlans) &&
+				  (staterr & IXGBE_RXD_STAT_VP)) {
                                         sendmp->m_pkthdr.ether_vtag = vtag;
                                         sendmp->m_flags |= M_VLANTAG;
                                 }
@@ -4376,12 +4387,13 @@ ixgbe_register_vlan(void *arg, struct if
 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
 		return;
 
+	IXGBE_CORE_LOCK(adapter);
 	index = (vtag >> 5) & 0x7F;
 	bit = vtag & 0x1F;
-	ixgbe_shadow_vfta[index] |= (1 << bit);
+	adapter->shadow_vfta[index] |= (1 << bit);
 	++adapter->num_vlans;
-	/* Re-init to load the changes */
-	ixgbe_init(adapter);
+	ixgbe_init_locked(adapter);
+	IXGBE_CORE_UNLOCK(adapter);
 }
 
 /*
@@ -4401,17 +4413,20 @@ ixgbe_unregister_vlan(void *arg, struct 
 	if ((vtag == 0) || (vtag > 4095))	/* Invalid */
 		return;
 
+	IXGBE_CORE_LOCK(adapter);
 	index = (vtag >> 5) & 0x7F;
 	bit = vtag & 0x1F;
-	ixgbe_shadow_vfta[index] &= ~(1 << bit);
+	adapter->shadow_vfta[index] &= ~(1 << bit);
 	--adapter->num_vlans;
 	/* Re-init to load the changes */
-	ixgbe_init(adapter);
+	ixgbe_init_locked(adapter);
+	IXGBE_CORE_UNLOCK(adapter);
 }
 
 static void
 ixgbe_setup_vlan_hw_support(struct adapter *adapter)
 {
+	struct ifnet 	*ifp = adapter->ifp;
 	struct ixgbe_hw *hw = &adapter->hw;
 	u32		ctrl;
 
@@ -4430,14 +4445,16 @@ ixgbe_setup_vlan_hw_support(struct adapt
 	** we need to repopulate it now.
 	*/
 	for (int i = 0; i < IXGBE_VFTA_SIZE; i++)
-		if (ixgbe_shadow_vfta[i] != 0)
+		if (adapter->shadow_vfta[i] != 0)
 			IXGBE_WRITE_REG(hw, IXGBE_VFTA(i),
-			    ixgbe_shadow_vfta[i]);
+			    adapter->shadow_vfta[i]);
 
-	/* Enable the Filter Table */
 	ctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
-	ctrl &= ~IXGBE_VLNCTRL_CFIEN;
-	ctrl |= IXGBE_VLNCTRL_VFE;
+	/* Enable the Filter Table if enabled */
+	if (ifp->if_capenable & IFCAP_VLAN_HWFILTER) {
+		ctrl &= ~IXGBE_VLNCTRL_CFIEN;
+		ctrl |= IXGBE_VLNCTRL_VFE;
+	}
 	if (hw->mac.type == ixgbe_mac_82598EB)
 		ctrl |= IXGBE_VLNCTRL_VME;
 	IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, ctrl);
@@ -4478,14 +4495,14 @@ ixgbe_enable_intr(struct adapter *adapte
 	/* With RSS we use auto clear */
 	if (adapter->msix_mem) {
 		mask = IXGBE_EIMS_ENABLE_MASK;
-		/* Don't autoclear Link */
+		/* Dont autoclear Link */
 		mask &= ~IXGBE_EIMS_OTHER;
 		mask &= ~IXGBE_EIMS_LSC;
 		IXGBE_WRITE_REG(hw, IXGBE_EIAC, mask);
 	}
 
 	/*
-	** Now enable all queues, this is done separately to
+	** Now enable all queues, this is done seperately to
 	** allow for handling the extended (beyond 32) MSIX
 	** vectors that can be used by 82599
 	*/

Modified: head/sys/dev/ixgbe/ixgbe.h
==============================================================================
--- head/sys/dev/ixgbe/ixgbe.h	Fri Nov 26 22:36:47 2010	(r215910)
+++ head/sys/dev/ixgbe/ixgbe.h	Fri Nov 26 22:46:32 2010	(r215911)
@@ -179,6 +179,9 @@
 #define IXGBE_RX_HDR			128
 #define IXGBE_VFTA_SIZE			128
 #define IXGBE_BR_SIZE			4096
+#define IXGBE_QUEUE_IDLE		0
+#define IXGBE_QUEUE_WORKING		1
+#define IXGBE_QUEUE_HUNG		2
 
 /* Offload bits in mbuf flag */
 #if __FreeBSD_version >= 800000
@@ -205,11 +208,6 @@
 #define IXGBE_BULK_LATENCY	1200
 #define IXGBE_LINK_ITR		2000
 
-/* Header split args for get_bug */
-#define IXGBE_CLEAN_HDR		1
-#define IXGBE_CLEAN_PKT		2
-#define IXGBE_CLEAN_ALL		3
-
 /*
  *****************************************************************************
  * vendor_info_array
@@ -280,7 +278,7 @@ struct tx_ring {
         struct adapter		*adapter;
 	struct mtx		tx_mtx;
 	u32			me;
-	bool			watchdog_check;
+	int			queue_status;
 	int			watchdog_time;
 	union ixgbe_adv_tx_desc	*tx_base;
 	struct ixgbe_dma_alloc	txdma;
@@ -374,7 +372,15 @@ struct adapter {
 	u16			num_vlans;
 	u16			num_queues;
 
-	/* Info about the board itself */
+	/*
+	** Shadow VFTA table, this is needed because
+	** the real vlan filter table gets cleared during
+	** a soft reset and the driver needs to be able
+	** to repopulate it.
+	*/
+	u32			shadow_vfta[IXGBE_VFTA_SIZE];
+
+	/* Info about the interface */
 	u32			optics;
 	int			advertise;  /* link speeds */
 	bool			link_active;
@@ -421,8 +427,6 @@ struct adapter {
 	u64			que_mask;
 	u32			rx_process_limit;
 
-	/* Multicast array memory */
-	u8			*mta;
 	/* Misc stats maintained by the driver */
 	unsigned long   	dropped_pkts;
 	unsigned long   	mbuf_defrag_failed;

Modified: head/sys/dev/ixgbe/ixgbe_82598.c
==============================================================================
--- head/sys/dev/ixgbe/ixgbe_82598.c	Fri Nov 26 22:36:47 2010	(r215910)
+++ head/sys/dev/ixgbe/ixgbe_82598.c	Fri Nov 26 22:46:32 2010	(r215911)
@@ -73,7 +73,6 @@ u32 ixgbe_get_supported_physical_layer_8
 s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
 void ixgbe_set_lan_id_multi_port_pcie_82598(struct ixgbe_hw *hw);
 void ixgbe_set_pcie_completion_timeout(struct ixgbe_hw *hw);
-static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw);
 
 /**
  *  ixgbe_set_pcie_completion_timeout - set pci-e completion timeout
@@ -186,6 +185,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw
 	mac->mcft_size       = 128;
 	mac->vft_size        = 128;
 	mac->num_rar_entries = 16;
+	mac->rx_pb_size      = 512;
 	mac->max_tx_queues   = 32;
 	mac->max_rx_queues   = 64;
 	mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
@@ -196,6 +196,7 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw
 	/* Link */
 	mac->ops.check_link = &ixgbe_check_mac_link_82598;
 	mac->ops.setup_link = &ixgbe_setup_mac_link_82598;
+	mac->ops.flap_tx_laser = NULL;
 	mac->ops.get_link_capabilities =
 	                       &ixgbe_get_link_capabilities_82598;
 
@@ -385,11 +386,14 @@ static enum ixgbe_media_type ixgbe_get_m
 	DEBUGFUNC("ixgbe_get_media_type_82598");
 
 	/* Detect if there is a copper PHY attached. */
-	if (hw->phy.type == ixgbe_phy_cu_unknown ||
-	    hw->phy.type == ixgbe_phy_tn ||
-	    hw->phy.type == ixgbe_phy_aq) {
+	switch (hw->phy.type) {
+	case ixgbe_phy_cu_unknown:
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
 		media_type = ixgbe_media_type_copper;
 		goto out;
+	default:
+		break;
 	}
 
 	/* Media type for I82598 is based on device ID */
@@ -436,6 +440,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h
 	u32 fctrl_reg;
 	u32 rmcs_reg;
 	u32 reg;
+	u32 rx_pba_size;
 	u32 link_speed = 0;
 	bool link_up;
 
@@ -463,7 +468,7 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h
 
 	/* Negotiate the fc mode to use */
 	ret_val = ixgbe_fc_autoneg(hw);
-	if (ret_val)
+	if (ret_val == IXGBE_ERR_FLOW_CONTROL)
 		goto out;
 
 	/* Disable any previous flow control settings */
@@ -485,7 +490,8 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h
 	 */
 	switch (hw->fc.current_mode) {
 	case ixgbe_fc_none:
-		/* Flow control is disabled by software override or autoneg.
+		/*
+		 * Flow control is disabled by software override or autoneg.
 		 * The code below will actually disable it in the HW.
 		 */
 		break;
@@ -526,16 +532,19 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_h
 
 	/* Set up and enable Rx high/low water mark thresholds, enable XON. */
 	if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
-		if (hw->fc.send_xon) {
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
-			                (hw->fc.low_water | IXGBE_FCRTL_XONE));
-		} else {
-			IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num),
-			                hw->fc.low_water);
-		}
+		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(packetbuf_num));
+		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
+
+		reg = (rx_pba_size - hw->fc.low_water) << 6;
+		if (hw->fc.send_xon)
+			reg |= IXGBE_FCRTL_XONE;
+
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
 
-		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num),
-		                (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+		reg = (rx_pba_size - hw->fc.high_water) << 6;
+		reg |= IXGBE_FCRTH_FCEN;
+
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
 	}
 
 	/* Configure pause time (2 TCs per register) */
@@ -560,7 +569,7 @@ out:
  *  Restarts the link.  Performs autonegotiation if needed.
  **/
 static s32 ixgbe_start_mac_link_82598(struct ixgbe_hw *hw,
-	                               bool autoneg_wait_to_complete)
+                                      bool autoneg_wait_to_complete)
 {
 	u32 autoc_reg;
 	u32 links_reg;
@@ -601,6 +610,41 @@ static s32 ixgbe_start_mac_link_82598(st
 }
 
 /**
+ *  ixgbe_validate_link_ready - Function looks for phy link
+ *  @hw: pointer to hardware structure
+ *
+ *  Function indicates success when phy link is available. If phy is not ready
+ *  within 5 seconds of MAC indicating link, the function returns error.
+ **/
+static s32 ixgbe_validate_link_ready(struct ixgbe_hw *hw)
+{
+	u32 timeout;
+	u16 an_reg;
+
+	if (hw->device_id != IXGBE_DEV_ID_82598AT2)
+		return IXGBE_SUCCESS;
+
+	for (timeout = 0;
+	     timeout < IXGBE_VALIDATE_LINK_READY_TIMEOUT; timeout++) {

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


More information about the svn-src-all mailing list