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

Jack F Vogel jfv at FreeBSD.org
Tue Jun 18 21:28:21 UTC 2013


Author: jfv
Date: Tue Jun 18 21:28:19 2013
New Revision: 251964
URL: http://svnweb.freebsd.org/changeset/base/251964

Log:
  Add quad port probe support, this gives the admin proper information about the slot
  (which should be a PCIE Gen 3 slot for this adapter) by looking back thru the PCI
  parent devices to the slot device.
  
  The fix above also corrects the bandwidth display to GT/s rather than the
  incorrect Gb/s
  
  Next, allow the use of ALTQ if you select the compile option IXGBE_LEGACY_TX.
  
  Allow the use of 'unsupported' optic modules by a compile option as well.
  
  Add a phy reset capability into the stop code, this is so a static configured
  driver will still behave properly when taken down (not being able to unload it).
  
  This revision synchronizes the shared code with Intel internal current code,
  and note that it now includes DCB supporting code, this was necessitated by
  some internal changes with the code, but it also will provide the opportunity
  to develop this feature in the core driver down the road.
  
  I have edited the README to get rid of some of the worse anachronisms in it
  as well, its by no means as robust as I might wish at this point however.
  
  Oh, I also have included some conditional stuff in the code so it will be
  compatible in both the 9.X and 10 environments.
  
  Performance has been a focus in recent changes and I believe this revision
  driver will perform very well in most workloads.
  
  MFC after: 2 weeks

Added:
  head/sys/dev/ixgbe/ixgbe_dcb.c   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_dcb.h   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_dcb_82598.c   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_dcb_82598.h   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_dcb_82599.c   (contents, props changed)
  head/sys/dev/ixgbe/ixgbe_dcb_82599.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/dev/ixgbe/README
  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/dev/ixgbe/ixgbe_vf.c
  head/sys/dev/ixgbe/ixgbe_x540.c
  head/sys/dev/ixgbe/ixgbe_x540.h
  head/sys/modules/ixgbe/Makefile

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Jun 18 21:24:07 2013	(r251963)
+++ head/sys/conf/files	Tue Jun 18 21:28:19 2013	(r251964)
@@ -1685,6 +1685,12 @@ dev/ixgbe/ixgbe_82599.c		optional ixgbe 
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/ixgbe/ixgbe_x540.c		optional ixgbe inet \
 	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_dcb.c		optional ixgbe inet \
+	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_dcb_82598.c	optional ixgbe inet \
+	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_dcb_82599.c	optional ixgbe inet \
+	compile-with "${NORMAL_C} -I$S/dev/ixgbe"
 dev/jme/if_jme.c		optional jme pci
 dev/joy/joy.c			optional joy
 dev/joy/joy_isa.c		optional joy isa

Modified: head/sys/dev/ixgbe/README
==============================================================================
--- head/sys/dev/ixgbe/README	Tue Jun 18 21:24:07 2013	(r251963)
+++ head/sys/dev/ixgbe/README	Tue Jun 18 21:28:19 2013	(r251964)
@@ -2,7 +2,7 @@ FreeBSD Driver for Intel(R) Ethernet 10 
 ============================================================================
 /*$FreeBSD$*/
 
-November 12, 2010
+Jun 18, 2013
 
 
 Contents
@@ -18,8 +18,8 @@ Contents
 Overview
 ========
 
-This file describes the FreeBSD* driver for the Intel(R) Ethernet 10 Gigabit 
-Family of Adapters.  Driver has been developed for use with FreeBSD 7.2 or later.
+This file describes the FreeBSD* driver for the
+Intel(R) Ethernet 10 Gigabit Family of Adapters.
 
 For questions related to hardware requirements, refer to the documentation
 supplied with your Intel 10GbE adapter.  All hardware requirements listed
@@ -42,7 +42,7 @@ optics, or is an Intel(R) Ethernet Serve
 Intel optics and/or the direct attach cables listed below.
 
 When 82599-based SFP+ devices are connected back to back, they should be set to
-the same Speed setting via Ethtool. Results may vary if you mix speed settings. 
+the same Speed setting. Results may vary if you mix speed settings. 
  
 Supplier    Type                                             Part Numbers
 
@@ -70,7 +70,12 @@ Finisar	   DUAL RATE 1G/10G SFP+ LR (No 
 Avago	   DUAL RATE 1G/10G SFP+ LR (No Bail)	             AFCT-701SDZ-IN1
 Finistar   1000BASE-T SFP                                    FCLF8522P2BTL
 Avago      1000BASE-T SFP                                    ABCU-5710RZ
-		
+
+NOTE: As of driver version 2.5.13 it is possible to allow the operation
+of unsupported modules by setting the static variable 'allow_unsupported_sfp'
+to TRUE and rebuilding the driver. If problems occur please assure that they
+can be reproduced with fully supported optics first.
+
 82599-based adapters support all passive and active limiting direct attach 
 cables that comply with SFF-8431 v4.1 and SFF-8472 v10.4 specifications.
 
@@ -224,14 +229,7 @@ all 10 Gigabit adapters. 
   When there is a choice run on a 64bit OS rather than 32, it makes a 
   significant difference in improvement.
   
-  The default scheduler SCHED_4BSD is not smart about SMP locality issues. 
-  Significant improvement can be achieved by switching to the ULE scheduler.
-
-  This is done by changing the entry in the config file from SCHED_4BSD to 
-  SCHED_ULE. Note that this is only advisable on FreeBSD 7, on 6.X there have
-  been stability problems with ULE.
-
-  The interface can generate high number of interrupts. To avoid running 
+  The interface can generate a high number of interrupts. To avoid running 
   into the limit set by the kernel, adjust hw.intr_storm_threshold 
   setting using sysctl:
  
@@ -242,12 +240,10 @@ all 10 Gigabit adapters. 
        hw.intr_storm_threshold=9000
 
   If you still see Interrupt Storm detected messages, increase the limit to a
-  higher number.
-
-  Best throughput results are seen with a large MTU; use 9000 if possible. 
+  higher number, or the detection can be disabled by setting it to 0.
 
-  The default number of descriptors is 1024, increasing this to 2K or even 
-  4K may improve performance in some workloads, but change carefully.
+  The default number of descriptors is 2048, increasing or descreasing
+  may improve performance in some workloads, but change carefully.
 
 
 Known Limitations
@@ -284,7 +280,7 @@ issues download your adapter's user guid
   ----------------------------------------------------------
   Some PCI-E x8 slots are actually configured as x4 slots. These slots have 
   insufficient bandwidth for full 10Gbe line rate with dual port 10GbE devices.
-  The driver can detect this situation and will write the following message in
+  The driver will detect this situation and will write the following message in
   the system log: "PCI-Express bandwidth available for this card is not 
   sufficient for optimal performance. For optimal performance a x8 PCI-Express 
   slot is required."

Modified: head/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- head/sys/dev/ixgbe/ixgbe.c	Tue Jun 18 21:24:07 2013	(r251963)
+++ head/sys/dev/ixgbe/ixgbe.c	Tue Jun 18 21:28:19 2013	(r251964)
@@ -32,6 +32,7 @@
 ******************************************************************************/
 /*$FreeBSD$*/
 
+
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -47,7 +48,7 @@ int             ixgbe_display_debug_stat
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "2.5.8 - HEAD";
+char ixgbe_driver_version[] = "2.5.13";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -109,8 +110,7 @@ static void     ixgbe_start(struct ifnet
 static void     ixgbe_start_locked(struct tx_ring *, struct ifnet *);
 #else /* ! IXGBE_LEGACY_TX */
 static int	ixgbe_mq_start(struct ifnet *, struct mbuf *);
-static int	ixgbe_mq_start_locked(struct ifnet *,
-                    struct tx_ring *, struct mbuf *);
+static int	ixgbe_mq_start_locked(struct ifnet *, struct tx_ring *);
 static void	ixgbe_qflush(struct ifnet *);
 static void	ixgbe_deferred_mq_start(void *, int);
 #endif /* IXGBE_LEGACY_TX */
@@ -122,6 +122,7 @@ static void     ixgbe_media_status(struc
 static int      ixgbe_media_change(struct ifnet *);
 static void     ixgbe_identify_hardware(struct adapter *);
 static int      ixgbe_allocate_pci_resources(struct adapter *);
+static void	ixgbe_get_slot_info(struct ixgbe_hw *);
 static int      ixgbe_allocate_msix(struct adapter *);
 static int      ixgbe_allocate_legacy(struct adapter *);
 static int	ixgbe_allocate_queues(struct adapter *);
@@ -149,7 +150,7 @@ static void	ixgbe_setup_hw_rsc(struct rx
 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 void	ixgbe_txeof(struct tx_ring *);
 static bool	ixgbe_rxeof(struct ix_queue *);
 static void	ixgbe_rx_checksum(u32, struct mbuf *, u32);
 static void     ixgbe_set_promisc(struct adapter *);
@@ -206,6 +207,9 @@ static void	ixgbe_atr(struct tx_ring *, 
 static void	ixgbe_reinit_fdir(void *, int);
 #endif
 
+/* Missing shared code prototype */
+extern void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw);
+
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
  *********************************************************************/
@@ -291,6 +295,13 @@ static int ixgbe_rxd = PERFORM_RXD;
 TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
 
 /*
+** Defining this on will allow the use
+** of unsupported SFP+ modules, note that
+** doing so you are on your own :)
+*/
+static int allow_unsupported_sfp = FALSE;
+
+/*
 ** HW RSC control: 
 **  this feature only works with
 **  IPv4, and only on 82599 and later.
@@ -507,6 +518,7 @@ ixgbe_attach(device_t dev)
 	}
 
 	/* Initialize the shared code */
+	hw->allow_unsupported_sfp = allow_unsupported_sfp;
 	error = ixgbe_init_shared_code(hw);
 	if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
 		/*
@@ -576,24 +588,10 @@ 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");
-        }
+        /*
+	** Check PCIE slot type/speed/width
+	*/
+	ixgbe_get_slot_info(hw);
 
 	/* Set an initial default flow control value */
 	adapter->fc =  ixgbe_fc_full;
@@ -797,7 +795,7 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 	struct adapter	*adapter = ifp->if_softc;
 	struct ix_queue	*que;
 	struct tx_ring	*txr;
-	int 		i = 0, err = 0;
+	int 		i, err = 0;
 
 	/* Which queue to use */
 	if ((m->m_flags & M_FLOWID) != 0)
@@ -808,40 +806,37 @@ ixgbe_mq_start(struct ifnet *ifp, struct
 	txr = &adapter->tx_rings[i];
 	que = &adapter->queues[i];
 
+	err = drbr_enqueue(ifp, txr->br, m);
+	if (err)
+		return (err);
 	if (IXGBE_TX_TRYLOCK(txr)) {
-		err = ixgbe_mq_start_locked(ifp, txr, m);
+		err = ixgbe_mq_start_locked(ifp, txr);
 		IXGBE_TX_UNLOCK(txr);
-	} else {
-		err = drbr_enqueue(ifp, txr->br, m);
+	} else
 		taskqueue_enqueue(que->tq, &txr->txq_task);
-	}
 
 	return (err);
 }
 
 static int
-ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr, struct mbuf *m)
+ixgbe_mq_start_locked(struct ifnet *ifp, struct tx_ring *txr)
 {
 	struct adapter  *adapter = txr->adapter;
         struct mbuf     *next;
-        int             enqueued, err = 0;
+        int             enqueued = 0, err = 0;
 
 	if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
-	    adapter->link_active == 0) {
-		if (m != NULL)
-			err = drbr_enqueue(ifp, txr->br, m);
-		return (err);
-	}
-
-	enqueued = 0;
-	if (m != NULL) {
-		err = drbr_enqueue(ifp, txr->br, m);
-		if (err) {
-			return (err);
-		}
-	}
+	    adapter->link_active == 0)
+		return (ENETDOWN);
 
 	/* Process the queue */
+#if __FreeBSD_version < 901504
+	next = drbr_dequeue(ifp, txr->br);
+	while (next != NULL) {
+		if ((err = ixgbe_xmit(txr, &next)) != 0) {
+			if (next != NULL)
+				err = drbr_enqueue(ifp, txr->br, next);
+#else
 	while ((next = drbr_peek(ifp, txr->br)) != NULL) {
 		if ((err = ixgbe_xmit(txr, &next)) != 0) {
 			if (next == NULL) {
@@ -849,16 +844,20 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 			} else {
 				drbr_putback(ifp, txr->br, next);
 			}
+#endif
 			break;
 		}
+#if __FreeBSD_version >= 901504
 		drbr_advance(ifp, txr->br);
+#endif
 		enqueued++;
 		/* 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 (txr->tx_avail < IXGBE_TX_OP_THRESHOLD)
-			ixgbe_txeof(txr);
+#if __FreeBSD_version < 901504
+		next = drbr_dequeue(ifp, txr->br);
+#endif
 	}
 
 	if (enqueued > 0) {
@@ -885,7 +884,7 @@ ixgbe_deferred_mq_start(void *arg, int p
 
 	IXGBE_TX_LOCK(txr);
 	if (!drbr_empty(ifp, txr->br))
-		ixgbe_mq_start_locked(ifp, txr, NULL);
+		ixgbe_mq_start_locked(ifp, txr);
 	IXGBE_TX_UNLOCK(txr);
 }
 
@@ -1418,20 +1417,19 @@ ixgbe_handle_que(void *context, int pend
 		ixgbe_txeof(txr);
 #ifndef IXGBE_LEGACY_TX
 		if (!drbr_empty(ifp, txr->br))
-			ixgbe_mq_start_locked(ifp, txr, NULL);
+			ixgbe_mq_start_locked(ifp, txr);
 #else
 		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
 			ixgbe_start_locked(txr, ifp);
 #endif
 		IXGBE_TX_UNLOCK(txr);
-		if (more) {
-			taskqueue_enqueue(que->tq, &que->que_task);
-			return;
-		}
 	}
 
 	/* Reenable this interrupt */
-	ixgbe_enable_queue(adapter, que->msix);
+	if (que->res != NULL)
+		ixgbe_enable_queue(adapter, que->msix);
+	else
+		ixgbe_enable_intr(adapter);
 	return;
 }
 
@@ -1448,9 +1446,10 @@ ixgbe_legacy_irq(void *arg)
 	struct ix_queue *que = arg;
 	struct adapter	*adapter = que->adapter;
 	struct ixgbe_hw	*hw = &adapter->hw;
+	struct ifnet    *ifp = adapter->ifp;
 	struct 		tx_ring *txr = adapter->tx_rings;
-	bool		more_tx, more_rx;
-	u32       	reg_eicr, loop = MAX_LOOP;
+	bool		more;
+	u32       	reg_eicr;
 
 
 	reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
@@ -1461,17 +1460,19 @@ ixgbe_legacy_irq(void *arg)
 		return;
 	}
 
-	more_rx = ixgbe_rxeof(que);
+	more = ixgbe_rxeof(que);
 
 	IXGBE_TX_LOCK(txr);
-	do {
-		more_tx = ixgbe_txeof(txr);
-	} while (loop-- && more_tx);
+	ixgbe_txeof(txr);
+#ifdef IXGBE_LEGACY_TX
+	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+		ixgbe_start_locked(txr, ifp);
+#else
+	if (!drbr_empty(ifp, txr->br))
+		ixgbe_mq_start_locked(ifp, txr);
+#endif
 	IXGBE_TX_UNLOCK(txr);
 
-	if (more_rx || more_tx)
-		taskqueue_enqueue(que->tq, &que->que_task);
-
 	/* Check for fan failure */
 	if ((hw->phy.media_type == ixgbe_media_type_copper) &&
 	    (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
@@ -1484,7 +1485,10 @@ ixgbe_legacy_irq(void *arg)
 	if (reg_eicr & IXGBE_EICR_LSC)
 		taskqueue_enqueue(adapter->tq, &adapter->link_task);
 
-	ixgbe_enable_intr(adapter);
+	if (more)
+		taskqueue_enqueue(que->tq, &que->que_task);
+	else
+		ixgbe_enable_intr(adapter);
 	return;
 }
 
@@ -1499,29 +1503,26 @@ ixgbe_msix_que(void *arg)
 {
 	struct ix_queue	*que = arg;
 	struct adapter  *adapter = que->adapter;
+	struct ifnet    *ifp = adapter->ifp;
 	struct tx_ring	*txr = que->txr;
 	struct rx_ring	*rxr = que->rxr;
-	bool		more_tx, more_rx;
+	bool		more;
 	u32		newitr = 0;
 
 	ixgbe_disable_queue(adapter, que->msix);
 	++que->irqs;
 
-	more_rx = ixgbe_rxeof(que);
+	more = ixgbe_rxeof(que);
 
 	IXGBE_TX_LOCK(txr);
-	more_tx = ixgbe_txeof(txr);
-	/*
-	** Make certain that if the stack 
-	** has anything queued the task gets
-	** scheduled to handle it.
-	*/
+	ixgbe_txeof(txr);
 #ifdef IXGBE_LEGACY_TX
-	if (!IFQ_DRV_IS_EMPTY(&adapter->ifp->if_snd))
+	if (!IFQ_DRV_IS_EMPTY(ifp->if_snd))
+		ixgbe_start_locked(txr, ifp);
 #else
-	if (!drbr_empty(adapter->ifp, txr->br))
+	if (!drbr_empty(ifp, txr->br))
+		ixgbe_mq_start_locked(ifp, txr);
 #endif
-		more_tx = 1;
 	IXGBE_TX_UNLOCK(txr);
 
 	/* Do AIM now? */
@@ -1575,9 +1576,9 @@ ixgbe_msix_que(void *arg)
         rxr->packets = 0;
 
 no_calc:
-	if (more_tx || more_rx)
+	if (more)
 		taskqueue_enqueue(que->tq, &que->que_task);
-	else /* Reenable this interrupt */
+	else
 		ixgbe_enable_queue(adapter, que->msix);
 	return;
 }
@@ -2062,7 +2063,7 @@ ixgbe_local_timer(void *arg)
 		    (paused == 0))
 			++hung;
 		else if (txr->queue_status == IXGBE_QUEUE_WORKING)
-			taskqueue_enqueue(que->tq, &que->que_task);
+			taskqueue_enqueue(que->tq, &txr->txq_task);
         }
 	/* Only truely watchdog if all queues show hung */
         if (hung == adapter->num_queues)
@@ -2149,9 +2150,14 @@ ixgbe_stop(void *arg)
 	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);
+	if (hw->mac.type == ixgbe_mac_82599EB)
+		ixgbe_stop_mac_link_on_d3_82599(hw);
+	/* Turn off the laser - noop with no optics */
+	ixgbe_disable_tx_laser(hw);
+
+	/* Update the stack */
+	adapter->link_up = FALSE;
+       	ixgbe_update_link_status(adapter);
 
 	/* reprogram the RAR[0] in case user changed it. */
 	ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
@@ -2603,7 +2609,11 @@ ixgbe_setup_interface(device_t dev, stru
 		return (-1);
 	}
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
+#if __FreeBSD_version < 1000025
+	ifp->if_baudrate = 1000000000;
+#else
 	if_initbaudrate(ifp, IF_Gbps(10));
+#endif
 	ifp->if_init = ixgbe_init;
 	ifp->if_softc = adapter;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
@@ -2614,6 +2624,8 @@ ixgbe_setup_interface(device_t dev, stru
 #else
 	ifp->if_start = ixgbe_start;
 	IFQ_SET_MAXLEN(&ifp->if_snd, adapter->num_tx_desc - 2);
+	ifp->if_snd.ifq_drv_maxlen = adapter->num_tx_desc - 2;
+	IFQ_SET_READY(&ifp->if_snd);
 #endif
 
 	ether_ifattach(ifp, adapter->hw.mac.addr);
@@ -3557,7 +3569,7 @@ ixgbe_atr(struct tx_ring *txr, struct mb
  *  tx_buffer is put back on the free queue.
  *
  **********************************************************************/
-static bool
+static void
 ixgbe_txeof(struct tx_ring *txr)
 {
 	struct adapter		*adapter = txr->adapter;
@@ -3600,13 +3612,13 @@ ixgbe_txeof(struct tx_ring *txr)
 			netmap_tx_irq(ifp, txr->me |
 			    (NETMAP_LOCKED_ENTER|NETMAP_LOCKED_EXIT));
 		}
-		return FALSE;
+		return;
 	}
 #endif /* DEV_NETMAP */
 
 	if (txr->tx_avail == txr->num_desc) {
 		txr->queue_status = IXGBE_QUEUE_IDLE;
-		return FALSE;
+		return;
 	}
 
 	/* Get work starting point */
@@ -3700,12 +3712,10 @@ ixgbe_txeof(struct tx_ring *txr)
 	if ((!processed) && ((ticks - txr->watchdog_time) > IXGBE_WATCHDOG))
 		txr->queue_status = IXGBE_QUEUE_HUNG;
 
-	if (txr->tx_avail == txr->num_desc) {
+	if (txr->tx_avail == txr->num_desc)
 		txr->queue_status = IXGBE_QUEUE_IDLE;
-		return (FALSE);
-	}
 
-	return TRUE;
+	return;
 }
 
 /*********************************************************************
@@ -4387,6 +4397,7 @@ ixgbe_rxeof(struct ix_queue *que)
 	if (netmap_rx_irq(ifp, rxr->me | NETMAP_LOCKED_ENTER, &processed))
 		return (FALSE);
 #endif /* DEV_NETMAP */
+
 	for (i = rxr->next_to_check; count != 0;) {
 		struct mbuf	*sendmp, *mp;
 		u32		rsc, ptype;
@@ -4576,15 +4587,12 @@ next_desc:
 	IXGBE_RX_UNLOCK(rxr);
 
 	/*
-	** We still have cleaning to do?
-	** Schedule another interrupt if so.
+	** Still have cleaning to do?
 	*/
-	if ((staterr & IXGBE_RXD_STAT_DD) != 0) {
-		ixgbe_rearm_queues(adapter, (u64)(1 << que->msix));
+	if ((staterr & IXGBE_RXD_STAT_DD) != 0)
 		return (TRUE);
-	}
-
-	return (FALSE);
+	else
+		return (FALSE);
 }
 
 
@@ -4833,6 +4841,111 @@ ixgbe_write_pci_cfg(struct ixgbe_hw *hw,
 }
 
 /*
+** Get the width and transaction speed of
+** the slot this adapter is plugged into.
+*/
+static void
+ixgbe_get_slot_info(struct ixgbe_hw *hw)
+{
+	device_t		dev = ((struct ixgbe_osdep *)hw->back)->dev;
+	struct ixgbe_mac_info	*mac = &hw->mac;
+	u16			link;
+	u32			offset;
+
+	/* For most devices simply call the shared code routine */
+	if (hw->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) {
+		ixgbe_get_bus_info(hw);
+		goto display;
+	}
+
+	/*
+	** For the Quad port adapter we need to parse back
+	** up the PCI tree to find the speed of the expansion
+	** slot into which this adapter is plugged. A bit more work.
+	*/
+	dev = device_get_parent(device_get_parent(dev));
+#ifdef IXGBE_DEBUG
+	device_printf(dev, "parent pcib = %x,%x,%x\n",
+	    pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
+#endif
+	dev = device_get_parent(device_get_parent(dev));
+#ifdef IXGBE_DEBUG
+	device_printf(dev, "slot pcib = %x,%x,%x\n",
+	    pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev));
+#endif
+	/* Now get the PCI Express Capabilities offset */
+	pci_find_cap(dev, PCIY_EXPRESS, &offset);
+	/* ...and read the Link Status Register */
+	link = pci_read_config(dev, offset + PCIER_LINK_STA, 2);
+	switch (link & IXGBE_PCI_LINK_WIDTH) {
+	case IXGBE_PCI_LINK_WIDTH_1:
+		hw->bus.width = ixgbe_bus_width_pcie_x1;
+		break;
+	case IXGBE_PCI_LINK_WIDTH_2:
+		hw->bus.width = ixgbe_bus_width_pcie_x2;
+		break;
+	case IXGBE_PCI_LINK_WIDTH_4:
+		hw->bus.width = ixgbe_bus_width_pcie_x4;
+		break;
+	case IXGBE_PCI_LINK_WIDTH_8:
+		hw->bus.width = ixgbe_bus_width_pcie_x8;
+		break;
+	default:
+		hw->bus.width = ixgbe_bus_width_unknown;
+		break;
+	}
+
+	switch (link & IXGBE_PCI_LINK_SPEED) {
+	case IXGBE_PCI_LINK_SPEED_2500:
+		hw->bus.speed = ixgbe_bus_speed_2500;
+		break;
+	case IXGBE_PCI_LINK_SPEED_5000:
+		hw->bus.speed = ixgbe_bus_speed_5000;
+		break;
+	case IXGBE_PCI_LINK_SPEED_8000:
+		hw->bus.speed = ixgbe_bus_speed_8000;
+		break;
+	default:
+		hw->bus.speed = ixgbe_bus_speed_unknown;
+		break;
+	}
+
+	mac->ops.set_lan_id(hw);
+
+display:
+	device_printf(dev,"PCI Express Bus: Speed %s %s\n",
+	    ((hw->bus.speed == ixgbe_bus_speed_8000) ? "8.0GT/s":
+	    (hw->bus.speed == ixgbe_bus_speed_5000) ? "5.0GT/s":
+	    (hw->bus.speed == ixgbe_bus_speed_2500) ? "2.5GT/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->device_id != IXGBE_DEV_ID_82599_SFP_SF_QP) &&
+	    ((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 Gen2 slot is required.\n");
+        }
+	if ((hw->device_id == IXGBE_DEV_ID_82599_SFP_SF_QP) &&
+	    ((hw->bus.width <= ixgbe_bus_width_pcie_x8) &&
+	    (hw->bus.speed < ixgbe_bus_speed_8000))) {
+		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 Gen3 slot is required.\n");
+        }
+
+	return;
+}
+
+
+/*
 ** Setup the correct IVAR register for a particular MSIX interrupt
 **   (yes this is all very magic and confusing :)
 **  - entry is the register array entry
@@ -5633,6 +5746,7 @@ ixgbe_set_advertise(SYSCTL_HANDLER_ARGS)
 /*
 ** Thermal Shutdown Trigger
 **   - cause a Thermal Overtemp IRQ
+**   - this now requires firmware enabling
 */
 static int
 ixgbe_set_thermal_test(SYSCTL_HANDLER_ARGS)

Modified: head/sys/dev/ixgbe/ixgbe.h
==============================================================================
--- head/sys/dev/ixgbe/ixgbe.h	Tue Jun 18 21:24:07 2013	(r251963)
+++ head/sys/dev/ixgbe/ixgbe.h	Tue Jun 18 21:28:19 2013	(r251964)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2012, Intel Corporation 
+  Copyright (c) 2001-2013, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -213,6 +213,7 @@
 #define IXGBE_BULK_LATENCY	1200
 #define IXGBE_LINK_ITR		2000
 
+
 /*
  *****************************************************************************
  * vendor_info_array
@@ -230,6 +231,7 @@ typedef struct _ixgbe_vendor_info_t {
 	unsigned int    index;
 } ixgbe_vendor_info_t;
 
+
 /* This is used to get SFP+ module data */
 struct ixgbe_i2c_req {
         u8 dev_addr;
@@ -456,6 +458,7 @@ struct adapter {
 	/* Multicast array memory */
 	u8			*mta;
 
+
 	/* Misc stats maintained by the driver */
 	unsigned long   	dropped_pkts;
 	unsigned long   	mbuf_defrag_failed;
@@ -467,6 +470,7 @@ struct adapter {
 	struct ixgbe_hw_stats 	stats;
 };
 
+
 /* Precision Time Sync (IEEE 1588) defines */
 #define ETHERTYPE_IEEE1588      0x88F7
 #define PICOSECS_PER_TICK       20833
@@ -489,6 +493,10 @@ struct adapter {
 #define IXGBE_CORE_LOCK_ASSERT(_sc)       mtx_assert(&(_sc)->core_mtx, MA_OWNED)
 #define IXGBE_TX_LOCK_ASSERT(_sc)         mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
 
+/* For backward compatibility */
+#if !defined(PCIER_LINK_STA)
+#define PCIER_LINK_STA PCIR_EXPRESS_LINK_STA
+#endif
 
 static inline bool
 ixgbe_is_sfp(struct ixgbe_hw *hw)

Modified: head/sys/dev/ixgbe/ixgbe_82598.c
==============================================================================
--- head/sys/dev/ixgbe/ixgbe_82598.c	Tue Jun 18 21:24:07 2013	(r251963)
+++ head/sys/dev/ixgbe/ixgbe_82598.c	Tue Jun 18 21:28:19 2013	(r251964)
@@ -166,6 +166,8 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw
 	/* Manageability interface */
 	mac->ops.set_fw_drv_ver = NULL;
 
+	mac->ops.get_rtrup2tc = NULL;
+
 	return ret_val;
 }
 
@@ -1115,10 +1117,19 @@ static s32 ixgbe_read_i2c_phy_82598(stru
 	u16 sfp_addr = 0;
 	u16 sfp_data = 0;
 	u16 sfp_stat = 0;
+	u16 gssr;
 	u32 i;
 
 	DEBUGFUNC("ixgbe_read_i2c_phy_82598");
 
+	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+		gssr = IXGBE_GSSR_PHY1_SM;
+	else
+		gssr = IXGBE_GSSR_PHY0_SM;
+
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
+		return IXGBE_ERR_SWFW_SYNC;
+
 	if (hw->phy.type == ixgbe_phy_nl) {
 		/*
 		 * NetLogic phy SDA/SCL registers are at addresses 0xC30A to
@@ -1127,17 +1138,17 @@ static s32 ixgbe_read_i2c_phy_82598(stru
 		 */
 		sfp_addr = (dev_addr << 8) + byte_offset;
 		sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
-		hw->phy.ops.write_reg(hw,
-				      IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
-				      IXGBE_MDIO_PMA_PMD_DEV_TYPE,
-				      sfp_addr);
+		hw->phy.ops.write_reg_mdi(hw,
+					  IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
+					  IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+					  sfp_addr);
 
 		/* Poll status */
 		for (i = 0; i < 100; i++) {
-			hw->phy.ops.read_reg(hw,
-					     IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
-					     IXGBE_MDIO_PMA_PMD_DEV_TYPE,
-					     &sfp_stat);
+			hw->phy.ops.read_reg_mdi(hw,
+						IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
+						IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+						&sfp_stat);
 			sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
 			if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
 				break;
@@ -1151,8 +1162,8 @@ static s32 ixgbe_read_i2c_phy_82598(stru
 		}
 
 		/* Read data */
-		hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
-				     IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
+		hw->phy.ops.read_reg_mdi(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
+					IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
 
 		*eeprom_data = (u8)(sfp_data >> 8);
 	} else {
@@ -1160,6 +1171,7 @@ static s32 ixgbe_read_i2c_phy_82598(stru
 	}
 
 out:
+	hw->mac.ops.release_swfw_sync(hw, gssr);
 	return status;
 }
 

Modified: head/sys/dev/ixgbe/ixgbe_82599.c
==============================================================================
--- head/sys/dev/ixgbe/ixgbe_82599.c	Tue Jun 18 21:24:07 2013	(r251963)
+++ head/sys/dev/ixgbe/ixgbe_82599.c	Tue Jun 18 21:28:19 2013	(r251964)
@@ -77,7 +77,7 @@ void ixgbe_init_mac_link_ops_82599(struc
 	 * and MNG not enabled
 	 */
 	if ((mac->ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-	    !(ixgbe_mng_enabled(hw))) {
+	    !hw->mng_fw_enabled) {
 		mac->ops.disable_tx_laser =
 				       &ixgbe_disable_tx_laser_multispeed_fiber;
 		mac->ops.enable_tx_laser =
@@ -180,11 +180,13 @@ s32 ixgbe_setup_sfp_modules_82599(struct
 			goto setup_sfp_out;
 		}
 
-		hw->eeprom.ops.read(hw, ++data_offset, &data_value);
+		if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
+			goto setup_sfp_err;
 		while (data_value != 0xffff) {
 			IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
 			IXGBE_WRITE_FLUSH(hw);
-			hw->eeprom.ops.read(hw, ++data_offset, &data_value);
+			if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
+				goto setup_sfp_err;
 		}
 
 		/* Release the semaphore */
@@ -229,6 +231,15 @@ s32 ixgbe_setup_sfp_modules_82599(struct
 
 setup_sfp_out:
 	return ret_val;
+
+setup_sfp_err:
+	/* Release the semaphore */
+	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+	/* Delay obtaining semaphore again to allow FW access */
+	msec_delay(hw->eeprom.semaphore_delay);
+	ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+		      "eeprom read at offset %d failed", data_offset);
+	return IXGBE_ERR_PHY;
 }
 
 /**
@@ -314,6 +325,11 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw
 	mac->ops.set_fw_drv_ver = &ixgbe_set_fw_drv_ver_generic;
 
 
+	mac->ops.get_rtrup2tc = &ixgbe_dcb_get_rtrup2tc_generic;
+
+	/* Cache if MNG FW is up */
+	hw->mng_fw_enabled = ixgbe_mng_enabled(hw);
+
 	return ret_val;
 }
 
@@ -479,6 +495,29 @@ out:
 }
 
 /**
+ *  ixgbe_stop_mac_link_on_d3_82599 - Disables link on D3
+ *  @hw: pointer to hardware structure
+ *
+ *  Disables link during D3 power down sequence.
+ *
+ **/
+void ixgbe_stop_mac_link_on_d3_82599(struct ixgbe_hw *hw)
+{
+	u32 autoc2_reg;
+	u16 ee_ctrl_2 = 0;
+
+	DEBUGFUNC("ixgbe_stop_mac_link_on_d3_82599");
+	ixgbe_read_eeprom(hw, IXGBE_EEPROM_CTRL_2, &ee_ctrl_2);
+
+	if (!hw->mng_fw_enabled && !hw->wol_enabled &&
+		ee_ctrl_2 & IXGBE_EEPROM_CCD_BIT) {
+		autoc2_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+		autoc2_reg |= IXGBE_AUTOC2_LINK_DISABLE_ON_D3_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2_reg);
+	}
+}
+
+/**
  *  ixgbe_start_mac_link_82599 - Setup MAC link settings
  *  @hw: pointer to hardware structure
  *  @autoneg_wait_to_complete: TRUE when waiting for completion is needed
@@ -1122,7 +1161,8 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw
 {
 	ixgbe_link_speed link_speed;
 	s32 status;
-	u32 ctrl, i, autoc, autoc2;
+	u32 ctrl, i, autoc2;
+	u32 curr_lms;
 	bool link_up = FALSE;
 
 	DEBUGFUNC("ixgbe_reset_hw_82599");
@@ -1156,6 +1196,13 @@ s32 ixgbe_reset_hw_82599(struct ixgbe_hw
 	if (hw->phy.reset_disable == FALSE && hw->phy.ops.reset != NULL)
 		hw->phy.ops.reset(hw);
 
+	/* remember AUTOC from before we reset */
+	if (hw->mac.cached_autoc)
+		curr_lms = hw->mac.cached_autoc & IXGBE_AUTOC_LMS_MASK;
+	else
+		curr_lms = IXGBE_READ_REG(hw, IXGBE_AUTOC) &
+					  IXGBE_AUTOC_LMS_MASK;
+
 mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
@@ -1204,7 +1251,7 @@ mac_reset_top:
 	 * stored off yet.  Otherwise restore the stored original
 	 * values since the reset operation sets back to defaults.
 	 */
-	autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	hw->mac.cached_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
 	autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
 
 	/* Enable link if disabled in NVM */
@@ -1215,12 +1262,24 @@ mac_reset_top:
 	}
 
 	if (hw->mac.orig_link_settings_stored == FALSE) {
-		hw->mac.orig_autoc = autoc;
+		hw->mac.orig_autoc = hw->mac.cached_autoc;
 		hw->mac.orig_autoc2 = autoc2;
-		hw->mac.cached_autoc = autoc;
 		hw->mac.orig_link_settings_stored = TRUE;
 	} else {
-		if (autoc != hw->mac.orig_autoc) {
+
+		/* If MNG FW is running on a multi-speed device that
+		 * doesn't autoneg with out driver support we need to
+		 * leave LMS in the state it was before we MAC reset.
+		 * Likewise if we support WoL we don't want change the
+		 * LMS state.
+		 */
+		if ((hw->phy.multispeed_fiber && hw->mng_fw_enabled) ||
+		    hw->wol_enabled)
+			hw->mac.orig_autoc =
+				(hw->mac.orig_autoc & ~IXGBE_AUTOC_LMS_MASK) |
+				curr_lms;
+
+		if (hw->mac.cached_autoc != hw->mac.orig_autoc) {
 			/* Need SW/FW semaphore around AUTOC writes if LESM is
 			 * on, likewise reset_pipeline requires us to hold
 			 * this lock as it also writes to AUTOC.
@@ -2275,11 +2334,11 @@ s32 ixgbe_enable_rx_dma_82599(struct ixg
  *  Returns IXGBE_ERR_EEPROM_VERSION if the FW is not present or
  *  if the FW version is not supported.
  **/
-s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
+static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
 {
 	s32 status = IXGBE_ERR_EEPROM_VERSION;
 	u16 fw_offset, fw_ptp_cfg_offset;
-	u16 fw_version = 0;
+	u16 fw_version;
 
 	DEBUGFUNC("ixgbe_verify_fw_version_82599");
 
@@ -2290,22 +2349,37 @@ s32 ixgbe_verify_fw_version_82599(struct
 	}
 
 	/* get the offset to the Firmware Module block */
-	hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
+	if (hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset)) {
+		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+			      "eeprom read at offset %d failed", IXGBE_FW_PTR);
+		return IXGBE_ERR_EEPROM_VERSION;
+	}
 
 	if ((fw_offset == 0) || (fw_offset == 0xFFFF))
 		goto fw_version_out;
 
 	/* get the offset to the Pass Through Patch Configuration block */
-	hw->eeprom.ops.read(hw, (fw_offset +
+	if (hw->eeprom.ops.read(hw, (fw_offset +
 				 IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR),
-				 &fw_ptp_cfg_offset);
+				 &fw_ptp_cfg_offset)) {
+		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+			      "eeprom read at offset %d failed",
+			      fw_offset +
+			      IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR);
+		return IXGBE_ERR_EEPROM_VERSION;
+	}
 
 	if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
 		goto fw_version_out;
 
 	/* get the firmware version */
-	hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
-			    IXGBE_FW_PATCH_VERSION_4), &fw_version);
+	if (hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
+			    IXGBE_FW_PATCH_VERSION_4), &fw_version)) {
+		ERROR_REPORT2(IXGBE_ERROR_INVALID_STATE,
+			      "eeprom read at offset %d failed",
+			      fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4);
+		return IXGBE_ERR_EEPROM_VERSION;
+	}
 

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


More information about the svn-src-head mailing list