Author: jfv
Date: Fri Apr 10 00:22:48 2009
New Revision: 190873
URL: http://svn.freebsd.org/changeset/base/190873

Log:
  Update the ixgbe driver to 1.7.4, this includes support
  for the new 82599 adapter family, adds header split, and
  many small fixes. The driver should now be added to the
  GENERIC kernel.
  
  MFC after: 2 weeks

Modified:
  head/sys/dev/ixgbe/LICENSE
  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_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

Modified: head/sys/dev/ixgbe/LICENSE
==============================================================================
--- head/sys/dev/ixgbe/LICENSE  Fri Apr 10 00:05:46 2009        (r190872)
+++ head/sys/dev/ixgbe/LICENSE  Fri Apr 10 00:22:48 2009        (r190873)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2008, Intel Corporation 
+  Copyright (c) 2001-2009, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 

Modified: head/sys/dev/ixgbe/README
==============================================================================
--- head/sys/dev/ixgbe/README   Fri Apr 10 00:05:46 2009        (r190872)
+++ head/sys/dev/ixgbe/README   Fri Apr 10 00:22:48 2009        (r190873)
@@ -1,6 +1,8 @@
 FreeBSD Driver for 10 Gigabit PCI Express Server Adapters
 =============================================
-$FreeBSD$
+/*$FreeBSD$*/
+
+May 14, 2008
 
 
 Contents
@@ -258,7 +260,7 @@ For general information and support, go 
 
 If an issue is identified with the released source code on the supported
 kernel with a supported adapter, email the specific information related to 
-the issue to freebsd...@mailbox.intel.com.
+the issue to free...@intel.com.
 
 
 

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

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