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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to