Author: jfv
Date: Thu Feb 28 21:55:57 2013
New Revision: 247501
URL: http://svnweb.freebsd.org/changeset/base/247501

Log:
  MFC of the ixgbe driver including revisions:
  
  217556,219902,228276,229767,229939,230572,231796,232238,
  234137,234229,235547,235964,236627,236729,238149,239940,
  240155,240366,240968,241037,241616,241646,241856,241885,
  242403,242421,243714,243716,243718,243721,243724,243725,
  243728,243729,243733,243735,243736,243741,243833,243857,
  244514,245952,246128,246482,247035,247056

Modified:
  stable/8/sys/dev/ixgbe/ixgbe.c   (contents, props changed)
  stable/8/sys/dev/ixgbe/ixgbe.h
  stable/8/sys/dev/ixgbe/ixgbe_82598.c
  stable/8/sys/dev/ixgbe/ixgbe_82598.h   (contents, props changed)
  stable/8/sys/dev/ixgbe/ixgbe_82599.c
  stable/8/sys/dev/ixgbe/ixgbe_api.c
  stable/8/sys/dev/ixgbe/ixgbe_api.h
  stable/8/sys/dev/ixgbe/ixgbe_common.c
  stable/8/sys/dev/ixgbe/ixgbe_common.h
  stable/8/sys/dev/ixgbe/ixgbe_osdep.h
  stable/8/sys/dev/ixgbe/ixgbe_phy.c
  stable/8/sys/dev/ixgbe/ixgbe_type.h
  stable/8/sys/dev/ixgbe/ixgbe_vf.c
  stable/8/sys/dev/ixgbe/ixgbe_x540.c   (contents, props changed)
  stable/8/sys/dev/ixgbe/ixv.c
Directory Properties:
  stable/8/sys/dev/ixgbe/   (props changed)
  stable/8/sys/dev/ixgbe/ixgbe_82599.h   (props changed)
  stable/8/sys/dev/ixgbe/ixgbe_x540.h   (props changed)

Modified: stable/8/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- stable/8/sys/dev/ixgbe/ixgbe.c      Thu Feb 28 21:32:47 2013        
(r247500)
+++ stable/8/sys/dev/ixgbe/ixgbe.c      Thu Feb 28 21:55:57 2013        
(r247501)
@@ -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 
@@ -47,7 +47,7 @@ int             ixgbe_display_debug_stat
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixgbe_driver_version[] = "2.4.5";
+char ixgbe_driver_version[] = "2.5.0 - 8";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -80,8 +80,10 @@ static ixgbe_vendor_info_t ixgbe_vendor_
        {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_SF2, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP_FCOE, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599EN_SFP, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T1, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_X540T, 0, 0, 0},
        /* required last entry */
        {0, 0, 0, 0, 0}
@@ -102,16 +104,16 @@ static int      ixgbe_probe(device_t);
 static int      ixgbe_attach(device_t);
 static int      ixgbe_detach(device_t);
 static int      ixgbe_shutdown(device_t);
-#if __FreeBSD_version >= 800000
+#ifdef IXGBE_LEGACY_TX
+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 void    ixgbe_qflush(struct ifnet *);
 static void    ixgbe_deferred_mq_start(void *, int);
-#else
-static void     ixgbe_start(struct ifnet *);
-static void     ixgbe_start_locked(struct tx_ring *, struct ifnet *);
-#endif
+#endif /* IXGBE_LEGACY_TX */
 static int      ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
 static void    ixgbe_init(void *);
 static void    ixgbe_init_locked(struct adapter *);
@@ -148,7 +150,7 @@ static void     ixgbe_enable_intr(struct
 static void     ixgbe_disable_intr(struct adapter *);
 static void     ixgbe_update_stats_counters(struct adapter *);
 static bool    ixgbe_txeof(struct tx_ring *);
-static bool    ixgbe_rxeof(struct ix_queue *, int);
+static bool    ixgbe_rxeof(struct ix_queue *);
 static void    ixgbe_rx_checksum(u32, struct mbuf *, u32);
 static void     ixgbe_set_promisc(struct adapter *);
 static void     ixgbe_set_multi(struct adapter *);
@@ -161,10 +163,10 @@ static int        ixgbe_set_thermal_test(SYSCTL
 static int     ixgbe_dma_malloc(struct adapter *, bus_size_t,
                    struct ixgbe_dma_alloc *, int);
 static void     ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
-static void    ixgbe_add_rx_process_limit(struct adapter *, const char *,
-                   const char *, int *, int);
-static bool    ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
-static bool    ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
+static int     ixgbe_tx_ctx_setup(struct tx_ring *,
+                   struct mbuf *, u32 *, u32 *);
+static int     ixgbe_tso_setup(struct tx_ring *,
+                   struct mbuf *, u32 *, u32 *);
 static void    ixgbe_set_ivar(struct adapter *, u8, u8, s8);
 static void    ixgbe_configure_ivars(struct adapter *);
 static u8 *    ixgbe_mc_array_itr(struct ixgbe_hw *, u8 **, u32 *);
@@ -179,6 +181,9 @@ static __inline void ixgbe_rx_discard(st
 static __inline void ixgbe_rx_input(struct rx_ring *, struct ifnet *,
                    struct mbuf *, u32);
 
+static void    ixgbe_enable_rx_drop(struct adapter *);
+static void    ixgbe_disable_rx_drop(struct adapter *);
+
 /* Support for pluggable optic modules */
 static bool    ixgbe_sfp_probe(struct adapter *);
 static void    ixgbe_setup_optics(struct adapter *);
@@ -211,7 +216,8 @@ static device_method_t ixgbe_methods[] =
        DEVMETHOD(device_attach, ixgbe_attach),
        DEVMETHOD(device_detach, ixgbe_detach),
        DEVMETHOD(device_shutdown, ixgbe_shutdown),
-       {0, 0}
+
+       DEVMETHOD_END
 };
 
 static driver_t ixgbe_driver = {
@@ -237,16 +243,16 @@ MODULE_DEPEND(ixgbe, ether, 1, 1, 1);
 static int ixgbe_enable_aim = TRUE;
 TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim);
 
-static int ixgbe_max_interrupt_rate = (8000000 / IXGBE_LOW_LATENCY);
+static int ixgbe_max_interrupt_rate = (4000000 / IXGBE_LOW_LATENCY);
 TUNABLE_INT("hw.ixgbe.max_interrupt_rate", &ixgbe_max_interrupt_rate);
 
 /* How many packets rxeof tries to clean at a time */
-static int ixgbe_rx_process_limit = 128;
+static int ixgbe_rx_process_limit = 256;
 TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
 
-/* Flow control setting, default to full */
-static int ixgbe_flow_control = ixgbe_fc_full;
-TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
+/* How many packets txeof tries to clean at a time */
+static int ixgbe_tx_process_limit = 256;
+TUNABLE_INT("hw.ixgbe.tx_process_limit", &ixgbe_tx_process_limit);
 
 /*
 ** Smart speed setting, default to on
@@ -265,15 +271,6 @@ static int ixgbe_enable_msix = 1;
 TUNABLE_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);
 
 /*
- * Header split: this causes the hardware to DMA
- * the header into a separate mbuf from the payload,
- * it can be a performance win in some workloads, but
- * in others it actually hurts, its off by default. 
- */
-static int ixgbe_header_split = FALSE;
-TUNABLE_INT("hw.ixgbe.hdr_split", &ixgbe_header_split);
-
-/*
  * Number of Queues, can be set to 0,
  * it then autoconfigures based on the
  * number of cpus with a max of 8. This
@@ -294,6 +291,20 @@ TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd);
 static int ixgbe_rxd = PERFORM_RXD;
 TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
 
+/*
+** HW RSC control: 
+**  this feature only works with
+**  IPv4, and only on 82599 and later.
+**  Also this will cause IP forwarding to
+**  fail and that can't be controlled by
+**  the stack as LRO can. For all these
+**  reasons I've deemed it best to leave
+**  this off and not bother with a tuneable
+**  interface, this would need to be compiled
+**  to enable.
+*/
+static bool ixgbe_rsc_enable = FALSE;
+
 /* Keep running tab on them for sanity check */
 static int ixgbe_total_ports;
 
@@ -318,6 +329,18 @@ static int atr_sample_rate = 20;
 static int fdir_pballoc = 1;
 #endif
 
+#ifdef DEV_NETMAP
+/*
+ * The #ifdef DEV_NETMAP / #endif blocks in this file are meant to
+ * be a reference on how to implement netmap support in a driver.
+ * Additional comments are in ixgbe_netmap.h .
+ *
+ * <dev/netmap/ixgbe_netmap.h> contains functions for netmap support
+ * that extend the standard driver.
+ */
+#include <dev/netmap/ixgbe_netmap.h>
+#endif /* DEV_NETMAP */
+
 /*********************************************************************
  *  Device identification routine
  *
@@ -406,11 +429,6 @@ ixgbe_attach(device_t dev)
                        OID_AUTO, "fc", CTLTYPE_INT | CTLFLAG_RW,
                        adapter, 0, ixgbe_set_flowcntl, "I", "Flow Control");
 
-       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
-                       SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-                       OID_AUTO, "advertise_gig", CTLTYPE_INT | CTLFLAG_RW,
-                       adapter, 0, ixgbe_set_advertise, "I", "1G Link");
-
         SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
                        SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
                        OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
@@ -516,28 +534,24 @@ ixgbe_attach(device_t dev)
                goto err_late;
        }
 
-       /* Get Hardware Flow Control setting */
-       hw->fc.requested_mode = ixgbe_fc_full;
-       adapter->fc = hw->fc.requested_mode;
-       hw->fc.pause_time = IXGBE_FC_PAUSE;
-       hw->fc.low_water = IXGBE_FC_LO;
-       hw->fc.high_water[0] = IXGBE_FC_HI;
-       hw->fc.send_xon = TRUE;
-
        error = ixgbe_init_hw(hw);
-       if (error == IXGBE_ERR_EEPROM_VERSION) {
+       switch (error) {
+       case IXGBE_ERR_EEPROM_VERSION:
                device_printf(dev, "This device is a pre-production adapter/"
                    "LOM.  Please be aware there may be issues associated "
                    "with your hardware.\n If you are experiencing problems "
                    "please contact your Intel or hardware representative "
                    "who provided you with this hardware.\n");
-       } else if (error == IXGBE_ERR_SFP_NOT_SUPPORTED)
+               break;
+       case IXGBE_ERR_SFP_NOT_SUPPORTED:
                device_printf(dev,"Unsupported SFP+ Module\n");
-
-       if (error) {
                error = EIO;
-               device_printf(dev,"Hardware Initialization Failure\n");
                goto err_late;
+       case IXGBE_ERR_SFP_NOT_PRESENT:
+               device_printf(dev,"No SFP+ Module found\n");
+               /* falls thru */
+       default:
+               break;
        }
 
        /* Detect and set physical type */
@@ -554,11 +568,6 @@ ixgbe_attach(device_t dev)
        if (ixgbe_setup_interface(dev, adapter) != 0)
                goto err_late;
 
-       /* Sysctl for limiting the amount of work done in the taskqueue */
-       ixgbe_add_rx_process_limit(adapter, "rx_processing_limit",
-           "max number of rx packets to process", &adapter->rx_process_limit,
-           ixgbe_rx_process_limit);
-
        /* Initialize statistics */
        ixgbe_update_stats_counters(adapter);
 
@@ -594,6 +603,9 @@ ixgbe_attach(device_t dev)
 
        ixgbe_add_hw_stats(adapter);
 
+#ifdef DEV_NETMAP
+       ixgbe_netmap_attach(adapter);
+#endif /* DEV_NETMAP */
        INIT_DEBUGOUT("ixgbe_attach: end");
        return (0);
 err_late:
@@ -640,7 +652,7 @@ ixgbe_detach(device_t dev)
 
        for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
                if (que->tq) {
-#if __FreeBSD_version >= 800000
+#ifdef IXGBE_LEGACY_TX
                        taskqueue_drain(que->tq, &txr->txq_task);
 #endif
                        taskqueue_drain(que->tq, &que->que_task);
@@ -672,6 +684,9 @@ ixgbe_detach(device_t dev)
 
        ether_ifdetach(adapter->ifp);
        callout_drain(&adapter->timer);
+#ifdef DEV_NETMAP
+       netmap_detach(adapter->ifp);
+#endif /* DEV_NETMAP */
        ixgbe_free_pci_resources(adapter);
        bus_generic_detach(dev);
        if_free(adapter->ifp);
@@ -701,7 +716,7 @@ ixgbe_shutdown(device_t dev)
 }
 
 
-#if __FreeBSD_version < 800000
+#ifdef IXGBE_LEGACY_TX
 /*********************************************************************
  *  Transmit entry point
  *
@@ -720,17 +735,14 @@ ixgbe_start_locked(struct tx_ring *txr, 
 
        IXGBE_TX_LOCK_ASSERT(txr);
 
-       if ((ifp->if_drv_flags & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
-           IFF_DRV_RUNNING)
+       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
                return;
        if (!adapter->link_active)
                return;
 
        while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
-               if (txr->tx_avail <= IXGBE_QUEUE_MIN_FREE) {
-                       txr->queue_status |= IXGBE_QUEUE_DEPLETED;
+               if (txr->tx_avail <= IXGBE_QUEUE_MIN_FREE)
                        break;
-                }
 
                IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
                if (m_head == NULL)
@@ -739,8 +751,6 @@ ixgbe_start_locked(struct tx_ring *txr, 
                if (ixgbe_xmit(txr, &m_head)) {
                        if (m_head != NULL)
                                IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
-                       if (txr->tx_avail <= IXGBE_QUEUE_MIN_FREE)
-                               txr->queue_status |= IXGBE_QUEUE_DEPLETED;
                        break;
                }
                /* Send a copy of the frame to the BPF listener */
@@ -773,7 +783,8 @@ ixgbe_start(struct ifnet *ifp)
        return;
 }
 
-#else
+#else /* ! IXGBE_LEGACY_TX */
+
 /*
 ** Multiqueue Transmit driver
 **
@@ -795,8 +806,7 @@ ixgbe_mq_start(struct ifnet *ifp, struct
        txr = &adapter->tx_rings[i];
        que = &adapter->queues[i];
 
-       if (((txr->queue_status & IXGBE_QUEUE_DEPLETED) == 0) &&
-           IXGBE_TX_TRYLOCK(txr)) {
+       if (IXGBE_TX_TRYLOCK(txr)) {
                err = ixgbe_mq_start_locked(ifp, txr, m);
                IXGBE_TX_UNLOCK(txr);
        } else {
@@ -815,17 +825,12 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
         int             enqueued, err = 0;
 
        if (((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) ||
-           (txr->queue_status == IXGBE_QUEUE_DEPLETED) ||
            adapter->link_active == 0) {
                if (m != NULL)
                        err = drbr_enqueue(ifp, txr->br, m);
                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);
@@ -844,23 +849,21 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
                        break;
                }
                enqueued++;
-               drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
+               ifp->if_obytes += next->m_pkthdr.len;
+               if (next->m_flags & M_MCAST)
+                       ifp->if_omcasts++;
                /* 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 (txr->tx_avail < IXGBE_TX_OP_THRESHOLD) {
-                       txr->queue_status |= IXGBE_QUEUE_DEPLETED;
-                       break;
-               }
                next = drbr_dequeue(ifp, txr->br);
        }
 
        if (enqueued > 0) {
                /* Set watchdog on */
-               txr->queue_status |= IXGBE_QUEUE_WORKING;
+               txr->queue_status = IXGBE_QUEUE_WORKING;
                txr->watchdog_time = ticks;
        }
 
@@ -904,7 +907,7 @@ ixgbe_qflush(struct ifnet *ifp)
        }
        if_qflush(ifp);
 }
-#endif /* __FreeBSD_version >= 800000 */
+#endif /* IXGBE_LEGACY_TX */
 
 /*********************************************************************
  *  Ioctl entry point
@@ -919,6 +922,7 @@ static int
 ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
 {
        struct adapter  *adapter = ifp->if_softc;
+       struct ixgbe_hw *hw = &adapter->hw;
        struct ifreq    *ifr = (struct ifreq *) data;
 #if defined(INET) || defined(INET6)
        struct ifaddr *ifa = (struct ifaddr *)data;
@@ -1006,6 +1010,8 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
                        ifp->if_capenable ^= IFCAP_HWCSUM;
                if (mask & IFCAP_TSO4)
                        ifp->if_capenable ^= IFCAP_TSO4;
+               if (mask & IFCAP_TSO6)
+                       ifp->if_capenable ^= IFCAP_TSO6;
                if (mask & IFCAP_LRO)
                        ifp->if_capenable ^= IFCAP_LRO;
                if (mask & IFCAP_VLAN_HWTAGGING)
@@ -1022,7 +1028,22 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
                VLAN_CAPABILITIES(ifp);
                break;
        }
-
+       case SIOCGI2C:
+       {
+               struct ixgbe_i2c_req    i2c;
+               IOCTL_DEBUGOUT("ioctl: SIOCGI2C (Get I2C Data)");
+               error = copyin(ifr->ifr_data, &i2c, sizeof(i2c));
+               if (error)
+                       break;
+               if ((i2c.dev_addr != 0xA0) || (i2c.dev_addr != 0xA2)){
+                       error = EINVAL;
+                       break;
+               }
+               hw->phy.ops.read_i2c_byte(hw, i2c.offset,
+                   i2c.dev_addr, i2c.data);
+               error = copyout(&i2c, ifr->ifr_data, sizeof(i2c));
+               break;
+       }
        default:
                IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
                error = ether_ioctl(ifp, command, data);
@@ -1070,7 +1091,7 @@ ixgbe_init_locked(struct adapter *adapte
 
        /* Set the various hardware offload abilities */
        ifp->if_hwassist = 0;
-       if (ifp->if_capenable & IFCAP_TSO4)
+       if (ifp->if_capenable & IFCAP_TSO)
                ifp->if_hwassist |= CSUM_TSO;
        if (ifp->if_capenable & IFCAP_TXCSUM) {
                ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
@@ -1095,7 +1116,7 @@ ixgbe_init_locked(struct adapter *adapte
 
        /*
        ** Determine the correct mbuf pool
-       ** for doing jumbo/headersplit
+       ** for doing jumbo frames
        */
        if (adapter->max_frame_size <= 2048)
                adapter->rx_mbuf_sz = MCLBYTES;
@@ -1152,6 +1173,14 @@ ixgbe_init_locked(struct adapter *adapte
                txdctl |= IXGBE_TXDCTL_ENABLE;
                /* Set WTHRESH to 8, burst writeback */
                txdctl |= (8 << 16);
+               /*
+                * When the internal queue falls below PTHRESH (32),
+                * start prefetching as long as there are at least
+                * HTHRESH (1) buffers ready. The values are taken
+                * from the Intel linux driver 3.8.21.
+                * Prefetching enables tx line rate even with 1 queue.
+                */
+               txdctl |= (32 << 0) | (1 << 8);
                IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl);
        }
 
@@ -1176,6 +1205,31 @@ ixgbe_init_locked(struct adapter *adapte
                                msec_delay(1);
                }
                wmb();
+#ifdef DEV_NETMAP
+               /*
+                * In netmap mode, we must preserve the buffers made
+                * available to userspace before the if_init()
+                * (this is true by default on the TX side, because
+                * init makes all buffers available to userspace).
+                *
+                * netmap_reset() and the device specific routines
+                * (e.g. ixgbe_setup_receive_rings()) map these
+                * buffers at the end of the NIC ring, so here we
+                * must set the RDT (tail) register to make sure
+                * they are not overwritten.
+                *
+                * In this driver the NIC ring starts at RDH = 0,
+                * RDT points to the last slot available for reception (?),
+                * so RDT = num_rx_desc - 1 means the whole ring is available.
+                */
+               if (ifp->if_capenable & IFCAP_NETMAP) {
+                       struct netmap_adapter *na = NA(adapter->ifp);
+                       struct netmap_kring *kring = &na->rx_rings[i];
+                       int t = na->num_rx_desc - 1 - kring->nr_hwavail;
+
+                       IXGBE_WRITE_REG(hw, IXGBE_RDT(i), t);
+               } else
+#endif /* DEV_NETMAP */
                IXGBE_WRITE_REG(hw, IXGBE_RDT(i), adapter->num_rx_desc - 1);
        }
 
@@ -1210,7 +1264,7 @@ ixgbe_init_locked(struct adapter *adapte
 #ifdef IXGBE_FDIR
        /* Init Flow director */
        if (hw->mac.type != ixgbe_mac_82598EB) {
-               u32 hdrm = 64 << fdir_pballoc;
+               u32 hdrm = 32 << fdir_pballoc;
 
                hw->mac.ops.setup_rxpba(hw, 0, hdrm, PBA_STRATEGY_EQUAL);
                ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
@@ -1236,12 +1290,40 @@ ixgbe_init_locked(struct adapter *adapte
        /* Config/Enable Link */
        ixgbe_config_link(adapter);
 
+       /* Hardware Packet Buffer & Flow Control setup */
+       {
+               u32 rxpb, frame, size, tmp;
+
+               frame = adapter->max_frame_size;
+
+               /* Calculate High Water */
+               if (hw->mac.type == ixgbe_mac_X540)
+                       tmp = IXGBE_DV_X540(frame, frame);
+               else
+                       tmp = IXGBE_DV(frame, frame);
+               size = IXGBE_BT2KB(tmp);
+               rxpb = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) >> 10;
+               hw->fc.high_water[0] = rxpb - size;
+
+               /* Now calculate Low Water */
+               if (hw->mac.type == ixgbe_mac_X540)
+                       tmp = IXGBE_LOW_DV_X540(frame);
+               else
+                       tmp = IXGBE_LOW_DV(frame);
+               hw->fc.low_water[0] = IXGBE_BT2KB(tmp);
+               
+               adapter->fc = hw->fc.requested_mode = ixgbe_fc_full;
+               hw->fc.pause_time = IXGBE_FC_PAUSE;
+               hw->fc.send_xon = TRUE;
+       }
+       /* Initialize the FC settings */
+       ixgbe_start_hw(hw);
+
        /* And now turn on interrupts */
        ixgbe_enable_intr(adapter);
 
        /* Now inform the stack we're ready */
        ifp->if_drv_flags |= IFF_DRV_RUNNING;
-       ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
        return;
 }
@@ -1331,10 +1413,10 @@ ixgbe_handle_que(void *context, int pend
        bool            more;
 
        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-               more = ixgbe_rxeof(que, adapter->rx_process_limit);
+               more = ixgbe_rxeof(que);
                IXGBE_TX_LOCK(txr);
                ixgbe_txeof(txr);
-#if __FreeBSD_version >= 800000
+#ifndef IXGBE_LEGACY_TX
                if (!drbr_empty(ifp, txr->br))
                        ixgbe_mq_start_locked(ifp, txr, NULL);
 #else
@@ -1342,7 +1424,7 @@ ixgbe_handle_que(void *context, int pend
                        ixgbe_start_locked(txr, ifp);
 #endif
                IXGBE_TX_UNLOCK(txr);
-               if (more || (ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
+               if (more) {
                        taskqueue_enqueue(que->tq, &que->que_task);
                        return;
                }
@@ -1379,7 +1461,7 @@ ixgbe_legacy_irq(void *arg)
                return;
        }
 
-       more_rx = ixgbe_rxeof(que, adapter->rx_process_limit);
+       more_rx = ixgbe_rxeof(que);
 
        IXGBE_TX_LOCK(txr);
        do {
@@ -1425,7 +1507,7 @@ ixgbe_msix_que(void *arg)
        ixgbe_disable_queue(adapter, que->msix);
        ++que->irqs;
 
-       more_rx = ixgbe_rxeof(que, adapter->rx_process_limit);
+       more_rx = ixgbe_rxeof(que);
 
        IXGBE_TX_LOCK(txr);
        more_tx = ixgbe_txeof(txr);
@@ -1434,7 +1516,7 @@ ixgbe_msix_que(void *arg)
        ** has anything queued the task gets
        ** scheduled to handle it.
        */
-#if __FreeBSD_version < 800000
+#ifdef IXGBE_LEGACY_TX
        if (!IFQ_DRV_IS_EMPTY(&adapter->ifp->if_snd))
 #else
        if (!drbr_empty(adapter->ifp, txr->br))
@@ -1525,10 +1607,8 @@ ixgbe_msix_link(void *arg)
                        /* This is probably overkill :) */
                        if (!atomic_cmpset_int(&adapter->fdir_reinit, 0, 1))
                                return;
-                       /* Clear the interrupt */
-                       IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_FLOW_DIR);
-                       /* Turn off the interface */
-                       adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+                       /* Disable the interrupt */
+                       IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR);
                        taskqueue_enqueue(adapter->tq, &adapter->fdir_task);
                } else
 #endif
@@ -1602,7 +1682,7 @@ ixgbe_media_status(struct ifnet * ifp, s
                        ifmr->ifm_active |= IFM_100_TX | IFM_FDX;
                        break;
                case IXGBE_LINK_SPEED_1GB_FULL:
-                       ifmr->ifm_active |= IFM_1000_T | IFM_FDX;
+                       ifmr->ifm_active |= adapter->optics | IFM_FDX;
                        break;
                case IXGBE_LINK_SPEED_10GB_FULL:
                        ifmr->ifm_active |= adapter->optics | IFM_FDX;
@@ -1661,9 +1741,9 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 {
        struct adapter  *adapter = txr->adapter;
        u32             olinfo_status = 0, cmd_type_len;
-       u32             paylen = 0;
        int             i, j, error, nsegs;
-       int             first, last = 0;
+       int             first;
+       bool            remap = TRUE;
        struct mbuf     *m_head;
        bus_dma_segment_t segs[adapter->num_segs];
        bus_dmamap_t    map;
@@ -1691,74 +1771,58 @@ ixgbe_xmit(struct tx_ring *txr, struct m
        /*
         * Map the packet for DMA.
         */
+retry:
        error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
            *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
 
-       if (error == EFBIG) {
+       if (__predict_false(error)) {
                struct mbuf *m;
 
-               m = m_defrag(*m_headp, M_DONTWAIT);
-               if (m == NULL) {
-                       adapter->mbuf_defrag_failed++;
-                       m_freem(*m_headp);
-                       *m_headp = NULL;
-                       return (ENOBUFS);
-               }
-               *m_headp = m;
-
-               /* Try it again */
-               error = bus_dmamap_load_mbuf_sg(txr->txtag, map,
-                   *m_headp, segs, &nsegs, BUS_DMA_NOWAIT);
-
-               if (error == ENOMEM) {
-                       adapter->no_tx_dma_setup++;
+               switch (error) {
+               case EFBIG:
+                       /* Try it again? - one try */
+                       if (remap == TRUE) {
+                               remap = FALSE;
+                               m = m_defrag(*m_headp, M_NOWAIT);
+                               if (m == NULL) {
+                                       adapter->mbuf_defrag_failed++;
+                                       m_freem(*m_headp);
+                                       *m_headp = NULL;
+                                       return (ENOBUFS);
+                               }
+                               *m_headp = m;
+                               goto retry;
+                       } else
+                               return (error);
+               case ENOMEM:
+                       txr->no_tx_dma_setup++;
                        return (error);
-               } else if (error != 0) {
-                       adapter->no_tx_dma_setup++;
+               default:
+                       txr->no_tx_dma_setup++;
                        m_freem(*m_headp);
                        *m_headp = NULL;
                        return (error);
                }
-       } else if (error == ENOMEM) {
-               adapter->no_tx_dma_setup++;
-               return (error);
-       } else if (error != 0) {
-               adapter->no_tx_dma_setup++;
-               m_freem(*m_headp);
-               *m_headp = NULL;
-               return (error);
        }
 
        /* Make certain there are enough descriptors */
        if (nsegs > txr->tx_avail - 2) {
                txr->no_desc_avail++;
-               error = ENOBUFS;
-               goto xmit_fail;
+               bus_dmamap_unload(txr->txtag, map);
+               return (ENOBUFS);
        }
        m_head = *m_headp;
 
        /*
        ** Set up the appropriate offload context
-       ** this becomes the first descriptor of 
-       ** a packet.
+       ** this will consume the first descriptor
        */
-       if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
-               if (ixgbe_tso_setup(txr, m_head, &paylen)) {
-                       cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
-                       olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
-                       olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-                       olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
-                       ++adapter->tso_tx;
-               } else
-                       return (ENXIO);
-       } else if (ixgbe_tx_ctx_setup(txr, m_head))
-               olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-
-#ifdef IXGBE_IEEE1588
-        /* This is changing soon to an mtag detection */
-        if (we detect this mbuf has a TSTAMP mtag)
-                cmd_type_len |= IXGBE_ADVTXD_MAC_TSTAMP;
-#endif
+       error = ixgbe_tx_ctx_setup(txr, m_head, &cmd_type_len, &olinfo_status);
+       if (__predict_false(error)) {
+               if (error == ENOBUFS)
+                       *m_headp = NULL;
+               return (error);
+       }
 
 #ifdef IXGBE_FDIR
        /* Do the flow director magic */
@@ -1770,10 +1834,6 @@ ixgbe_xmit(struct tx_ring *txr, struct m
                }
        }
 #endif
-        /* Record payload length */
-       if (paylen == 0)
-               olinfo_status |= m_head->m_pkthdr.len <<
-                   IXGBE_ADVTXD_PAYLEN_SHIFT;
 
        i = txr->next_avail_desc;
        for (j = 0; j < nsegs; j++) {
@@ -1789,13 +1849,9 @@ ixgbe_xmit(struct tx_ring *txr, struct m
                txd->read.cmd_type_len = htole32(txr->txd_cmd |
                    cmd_type_len |seglen);
                txd->read.olinfo_status = htole32(olinfo_status);
-               last = i; /* descriptor that will get completion IRQ */
 
-               if (++i == adapter->num_tx_desc)
+               if (++i == txr->num_desc)
                        i = 0;
-
-               txbuf->m_head = NULL;
-               txbuf->eop_index = -1;
        }
 
        txd->read.cmd_type_len |=
@@ -1804,14 +1860,19 @@ ixgbe_xmit(struct tx_ring *txr, struct m
        txr->next_avail_desc = i;
 
        txbuf->m_head = m_head;
-       /* Swap the dma map between the first and last descriptor */
+       /*
+       ** Here we swap the map so the last descriptor,
+       ** which gets the completion interrupt has the
+       ** real map, and the first descriptor gets the
+       ** unused map from this descriptor.
+       */
        txr->tx_buffers[first].map = txbuf->map;
        txbuf->map = map;
        bus_dmamap_sync(txr->txtag, map, BUS_DMASYNC_PREWRITE);
 
-        /* Set the index of the descriptor that will be marked done */
+        /* Set the EOP descriptor that will be marked done */
         txbuf = &txr->tx_buffers[first];
-       txbuf->eop_index = last;
+       txbuf->eop = txd;
 
         bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1824,10 +1885,6 @@ ixgbe_xmit(struct tx_ring *txr, struct m
 
        return (0);
 
-xmit_fail:
-       bus_dmamap_unload(txr->txtag, txbuf->map);
-       return (error);
-
 }
 
 static void
@@ -1946,13 +2003,11 @@ ixgbe_local_timer(void *arg)
 {
        struct adapter  *adapter = arg;
        device_t        dev = adapter->dev;
-       struct ifnet    *ifp = adapter->ifp;
        struct ix_queue *que = adapter->queues;
        struct tx_ring  *txr = adapter->tx_rings;
-       int             hung, busy, paused;
+       int             hung = 0, paused = 0;
 
        mtx_assert(&adapter->core_mtx, MA_OWNED);
-       hung = busy = paused = 0;
 
        /* Check for pluggable optics */
        if (adapter->sfp_probe)
@@ -1971,27 +2026,18 @@ ixgbe_local_timer(void *arg)
 
        /*
        ** Check the TX queues status
-       **      - central locked handling of OACTIVE
        **      - watchdog only if all queues show hung
        */          
        for (int i = 0; i < adapter->num_queues; i++, que++, txr++) {
-               if ((txr->queue_status & IXGBE_QUEUE_HUNG) &&
+               if ((txr->queue_status == IXGBE_QUEUE_HUNG) &&
                    (paused == 0))
                        ++hung;
-               if (txr->queue_status & IXGBE_QUEUE_DEPLETED)
-                       ++busy;
-               if ((txr->queue_status & IXGBE_QUEUE_IDLE) == 0)
+               else if (txr->queue_status == IXGBE_QUEUE_WORKING)
                        taskqueue_enqueue(que->tq, &que->que_task);
         }
        /* Only truely watchdog if all queues show hung */
         if (hung == adapter->num_queues)
                 goto watchdog;
-       /* Only turn off the stack flow when ALL are depleted */
-        if (busy == adapter->num_queues)
-                ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-        else if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) &&
-            (busy < adapter->num_queues))
-                ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
 out:
        ixgbe_rearm_queues(adapter, adapter->que_mask);
@@ -2020,7 +2066,6 @@ static void
 ixgbe_update_link_status(struct adapter *adapter)
 {
        struct ifnet    *ifp = adapter->ifp;
-       struct tx_ring *txr = adapter->tx_rings;
        device_t dev = adapter->dev;
 
 
@@ -2031,6 +2076,8 @@ ixgbe_update_link_status(struct adapter 
                                    ((adapter->link_speed == 128)? 10:1),
                                    "Full Duplex");
                        adapter->link_active = TRUE;
+                       /* Update any Flow Control changes */
+                       ixgbe_fc_enable(&adapter->hw);
                        if_link_state_change(ifp, LINK_STATE_UP);
                }
        } else { /* Link down */
@@ -2039,9 +2086,6 @@ ixgbe_update_link_status(struct adapter 
                                device_printf(dev,"Link is Down\n");
                        if_link_state_change(ifp, LINK_STATE_DOWN);
                        adapter->link_active = FALSE;
-                       for (int i = 0; i < adapter->num_queues;
-                           i++, txr++)
-                               txr->queue_status = IXGBE_QUEUE_IDLE;
                }
        }
 
@@ -2072,7 +2116,6 @@ ixgbe_stop(void *arg)
 
        /* Let the stack know...*/
        ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-       ifp->if_drv_flags |= IFF_DRV_OACTIVE;
 
        ixgbe_reset_hw(hw);
        hw->adapter_stopped = FALSE;
@@ -2144,6 +2187,11 @@ ixgbe_setup_optics(struct adapter *adapt
                return;
        }
 
+       if (layer & IXGBE_PHYSICAL_LAYER_1000BASE_SX) {
+               adapter->optics = IFM_1000_SX;
+               return;
+       }
+
        if (layer & (IXGBE_PHYSICAL_LAYER_10GBASE_LR |
            IXGBE_PHYSICAL_LAYER_10GBASE_LRM)) {
                adapter->optics = IFM_10G_LR;
@@ -2179,12 +2227,12 @@ ixgbe_setup_optics(struct adapter *adapt
 static int
 ixgbe_allocate_legacy(struct adapter *adapter)
 {
-       device_t dev = adapter->dev;
+       device_t        dev = adapter->dev;
        struct          ix_queue *que = adapter->queues;
-#if __FreeBSD_version >= 800000
+#ifndef IXGBE_LEGACY_TX
        struct tx_ring          *txr = adapter->tx_rings;
 #endif
-       int error, rid = 0;
+       int             error, rid = 0;
 
        /* MSI RID at 1 */
        if (adapter->msix == 1)
@@ -2203,7 +2251,7 @@ ixgbe_allocate_legacy(struct adapter *ad
         * Try allocating a fast interrupt and the associated deferred
         * processing contexts.
         */
-#if __FreeBSD_version >= 800000
+#ifndef IXGBE_LEGACY_TX
        TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
 #endif
        TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
@@ -2285,7 +2333,7 @@ ixgbe_allocate_msix(struct adapter *adap
                if (adapter->num_queues > 1)
                        bus_bind_intr(dev, que->res, i);
 
-#if __FreeBSD_version >= 800000
+#ifndef IXGBE_LEGACY_TX
                TASK_INIT(&txr->txq_task, 0, ixgbe_deferred_mq_start, txr);
 #endif
                TASK_INIT(&que->que_task, 0, ixgbe_handle_que, que);
@@ -2526,13 +2574,12 @@ ixgbe_setup_interface(device_t dev, stru
                return (-1);
        }
        if_initname(ifp, device_get_name(dev), device_get_unit(dev));
-       ifp->if_mtu = ETHERMTU;
        ifp->if_baudrate = 1000000000;
        ifp->if_init = ixgbe_init;
        ifp->if_softc = adapter;
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        ifp->if_ioctl = ixgbe_ioctl;
-#if __FreeBSD_version >= 800000
+#ifndef IXGBE_LEGACY_TX
        ifp->if_transmit = ixgbe_mq_start;
        ifp->if_qflush = ixgbe_qflush;
 #else
@@ -2550,16 +2597,14 @@ ixgbe_setup_interface(device_t dev, stru
         */
        ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
 
-       ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4 | IFCAP_VLAN_HWCSUM;
+       ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO | IFCAP_VLAN_HWCSUM;
        ifp->if_capabilities |= IFCAP_JUMBO_MTU;
+       ifp->if_capabilities |= IFCAP_LRO;
        ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING
                             |  IFCAP_VLAN_HWTSO
                             |  IFCAP_VLAN_MTU;
        ifp->if_capenable = ifp->if_capabilities;
 
-       /* Don't enable LRO by default */
-       ifp->if_capabilities |= IFCAP_LRO;
-
        /*
        ** Don't turn this on by default, if vlans are
        ** created on another pseudo device (eg. lagg)
@@ -2759,6 +2804,7 @@ ixgbe_allocate_queues(struct adapter *ad
                txr = &adapter->tx_rings[i];
                txr->adapter = adapter;
                txr->me = i;
+               txr->num_desc = adapter->num_tx_desc;
 
                /* Initialize the TX side lock */
                snprintf(txr->mtx_name, sizeof(txr->mtx_name), "%s:tx(%d)",
@@ -2782,7 +2828,7 @@ ixgbe_allocate_queues(struct adapter *ad
                        error = ENOMEM;
                        goto err_tx_desc;
                }
-#if __FreeBSD_version >= 800000
+#ifndef IXGBE_LEGACY_TX
                /* Allocate a buf ring */
                txr->br = buf_ring_alloc(IXGBE_BR_SIZE, M_DEVBUF,
                    M_WAITOK, &txr->tx_mtx);
@@ -2805,6 +2851,7 @@ ixgbe_allocate_queues(struct adapter *ad
                /* Set up some basics */
                rxr->adapter = adapter;
                rxr->me = i;
+               rxr->num_desc = adapter->num_rx_desc;
 
                /* Initialize the RX side lock */
                snprintf(rxr->mtx_name, sizeof(rxr->mtx_name), "%s:rx(%d)",
@@ -2928,9 +2975,20 @@ ixgbe_setup_transmit_ring(struct tx_ring
        struct adapter *adapter = txr->adapter;
        struct ixgbe_tx_buf *txbuf;
        int i;
+#ifdef DEV_NETMAP
+       struct netmap_adapter *na = NA(adapter->ifp);
+       struct netmap_slot *slot;
+#endif /* DEV_NETMAP */
 
        /* Clear the old ring contents */
        IXGBE_TX_LOCK(txr);
+#ifdef DEV_NETMAP
+       /*
+        * (under lock): if in netmap mode, do some consistency
+        * checks and set slot to entry 0 of the netmap ring.
+        */
+       slot = netmap_reset(na, NR_TX, txr->me, 0);
+#endif /* DEV_NETMAP */
        bzero((void *)txr->tx_base,
              (sizeof(union ixgbe_adv_tx_desc)) * adapter->num_tx_desc);
        /* Reset indices */
@@ -2939,7 +2997,7 @@ ixgbe_setup_transmit_ring(struct tx_ring
 
        /* Free any existing tx buffers. */
         txbuf = txr->tx_buffers;
-       for (i = 0; i < adapter->num_tx_desc; i++, txbuf++) {
+       for (i = 0; i < txr->num_desc; i++, txbuf++) {
                if (txbuf->m_head != NULL) {
                        bus_dmamap_sync(txr->txtag, txbuf->map,
                            BUS_DMASYNC_POSTWRITE);
@@ -2947,8 +3005,24 @@ ixgbe_setup_transmit_ring(struct tx_ring

*** 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