Author: jfv
Date: Mon Apr  5 18:46:29 2010
New Revision: 206204
URL: http://svn.freebsd.org/changeset/base/206204

Log:
  MFC of version 2.1.7 of the ixgbe driver.

Modified:
  stable/8/sys/dev/ixgbe/LICENSE
  stable/8/sys/dev/ixgbe/ixgbe.c
  stable/8/sys/dev/ixgbe/ixgbe.h
  stable/8/sys/dev/ixgbe/ixgbe_82598.c
  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_phy.h
  stable/8/sys/dev/ixgbe/ixgbe_type.h

Modified: stable/8/sys/dev/ixgbe/LICENSE
==============================================================================
--- stable/8/sys/dev/ixgbe/LICENSE      Mon Apr  5 18:38:18 2010        
(r206203)
+++ stable/8/sys/dev/ixgbe/LICENSE      Mon Apr  5 18:46:29 2010        
(r206204)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2010, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 

Modified: stable/8/sys/dev/ixgbe/ixgbe.c
==============================================================================
--- stable/8/sys/dev/ixgbe/ixgbe.c      Mon Apr  5 18:38:18 2010        
(r206203)
+++ stable/8/sys/dev/ixgbe/ixgbe.c      Mon Apr  5 18:46:29 2010        
(r206204)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2009, Intel Corporation 
+  Copyright (c) 2001-2010, 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.8.9";
+char ixgbe_driver_version[] = "2.1.7";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -64,16 +64,20 @@ static ixgbe_vendor_info_t ixgbe_vendor_
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AF_SINGLE_PORT, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_CX4, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT2, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_DA_DUAL_PORT, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_CX4_DUAL_PORT, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_XF_LR, 0, 0, 0},
-       {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_KX4_MEZZ, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
        {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_XAUI_LOM, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_CX4, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_T3_LOM, 0, 0, 0},
+       {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_COMBO_BACKPLANE, 0, 0, 0},
        /* required last entry */
        {0, 0, 0, 0, 0}
 };
@@ -102,9 +106,8 @@ static int  ixgbe_mq_start_locked(struct 
 static void    ixgbe_qflush(struct ifnet *);
 #endif
 static int      ixgbe_ioctl(struct ifnet *, u_long, caddr_t);
-static void     ixgbe_watchdog(struct adapter *);
-static void     ixgbe_init(void *);
-static void     ixgbe_init_locked(struct adapter *);
+static void    ixgbe_init(void *);
+static int     ixgbe_init_locked(struct adapter *);
 static void     ixgbe_stop(void *);
 static void     ixgbe_media_status(struct ifnet *, struct ifmediareq *);
 static int      ixgbe_media_change(struct ifnet *);
@@ -116,8 +119,8 @@ static int  ixgbe_allocate_queues(struct 
 static int     ixgbe_setup_msix(struct adapter *);
 static void    ixgbe_free_pci_resources(struct adapter *);
 static void     ixgbe_local_timer(void *);
-static int      ixgbe_hardware_init(struct adapter *);
 static void     ixgbe_setup_interface(device_t, struct adapter *);
+static void     ixgbe_config_link(struct adapter *);
 
 static int      ixgbe_allocate_transmit_buffers(struct tx_ring *);
 static int     ixgbe_setup_transmit_structures(struct adapter *);
@@ -132,21 +135,21 @@ static int        ixgbe_setup_receive_ring(stru
 static void     ixgbe_initialize_receive_units(struct adapter *);
 static void     ixgbe_free_receive_structures(struct adapter *);
 static void     ixgbe_free_receive_buffers(struct rx_ring *);
+static void    ixgbe_setup_hw_rsc(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 *);
 static bool    ixgbe_txeof(struct tx_ring *);
-static bool    ixgbe_rxeof(struct rx_ring *, int);
-static void    ixgbe_rx_checksum(u32, struct mbuf *);
+static bool    ixgbe_rxeof(struct ix_queue *, int);
+static void    ixgbe_rx_checksum(u32, struct mbuf *, u32);
 static void     ixgbe_set_promisc(struct adapter *);
 static void     ixgbe_disable_promisc(struct adapter *);
 static void     ixgbe_set_multi(struct adapter *);
 static void     ixgbe_print_hw_stats(struct adapter *);
 static void    ixgbe_print_debug_info(struct adapter *);
 static void     ixgbe_update_link_status(struct adapter *);
-static int     ixgbe_get_buf(struct rx_ring *, int, u8);
+static void    ixgbe_refresh_mbufs(struct rx_ring *, int);
 static int      ixgbe_xmit(struct tx_ring *, struct mbuf **);
 static int      ixgbe_sysctl_stats(SYSCTL_HANDLER_ARGS);
 static int     ixgbe_sysctl_debug(SYSCTL_HANDLER_ARGS);
@@ -166,7 +169,9 @@ static void ixgbe_setup_vlan_hw_support(
 static void    ixgbe_register_vlan(void *, struct ifnet *, u16);
 static void    ixgbe_unregister_vlan(void *, struct ifnet *, u16);
 
-static void    ixgbe_update_aim(struct rx_ring *);
+static __inline void ixgbe_rx_discard(struct rx_ring *, int);
+static __inline void ixgbe_rx_input(struct rx_ring *, struct ifnet *,
+                   struct mbuf *, u32);
 
 /* Support for pluggable optic modules */
 static bool    ixgbe_sfp_probe(struct adapter *);
@@ -175,17 +180,19 @@ static bool       ixgbe_sfp_probe(struct adapt
 static void    ixgbe_legacy_irq(void *);
 
 /* The MSI/X Interrupt handlers */
-static void    ixgbe_msix_tx(void *);
-static void    ixgbe_msix_rx(void *);
+static void    ixgbe_msix_que(void *);
 static void    ixgbe_msix_link(void *);
 
 /* Deferred interrupt tasklets */
-static void    ixgbe_handle_tx(void *, int);
-static void    ixgbe_handle_rx(void *, int);
+static void    ixgbe_handle_que(void *, int);
 static void    ixgbe_handle_link(void *, int);
 static void    ixgbe_handle_msf(void *, int);
 static void    ixgbe_handle_mod(void *, int);
 
+#ifdef IXGBE_FDIR
+static void    ixgbe_atr(struct tx_ring *, struct mbuf *);
+static void    ixgbe_reinit_fdir(void *, int);
+#endif
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
@@ -215,23 +222,16 @@ MODULE_DEPEND(ixgbe, ether, 1, 1, 1);
 */
 
 /*
-** These  parameters are used in Adaptive 
-** Interrupt Moderation. The value is set
-** into EITR and controls the interrupt
-** frequency. They can be modified but 
-** be careful in tuning them.
+** AIM: Adaptive Interrupt Moderation
+** which means that the interrupt rate
+** is varied over time based on the
+** traffic for that interrupt vector
 */
 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_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);
 
 /* How many packets rxeof tries to clean at a time */
-static int ixgbe_rx_process_limit = 100;
+static int ixgbe_rx_process_limit = 128;
 TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
 
 /* Flow control setting, default to full */
@@ -239,6 +239,15 @@ static int ixgbe_flow_control = ixgbe_fc
 TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
 
 /*
+** Smart speed setting, default to on
+** this only works as a compile option
+** right now as its during attach, set
+** this to 'ixgbe_smart_speed_off' to
+** disable.
+*/
+static int ixgbe_smart_speed = ixgbe_smart_speed_on;
+
+/*
  * MSIX should be the default for best performance,
  * but this allows it to be forced off for testing.
  */
@@ -255,23 +264,27 @@ static bool ixgbe_header_split = TRUE;
 TUNABLE_INT("hw.ixgbe.hdr_split", &ixgbe_header_split);
 
 /*
- * Number of Queues, should normally
- * be left at 0, it then autoconfigures to
- * the number of cpus. Each queue is a pair
- * of RX and TX rings with a dedicated interrupt
+ * Number of Queues, can be set to 0,
+ * it then autoconfigures based on the
+ * number of cpus. Each queue is a pair
+ * of RX and TX rings with a msix vector
  */
 static int ixgbe_num_queues = 0;
 TUNABLE_INT("hw.ixgbe.num_queues", &ixgbe_num_queues);
 
-/* Number of TX descriptors per ring */
-static int ixgbe_txd = DEFAULT_TXD;
+/*
+** Number of TX descriptors per ring,
+** setting higher than RX as this seems
+** the better performing choice.
+*/
+static int ixgbe_txd = PERFORM_TXD;
 TUNABLE_INT("hw.ixgbe.txd", &ixgbe_txd);
 
 /* Number of RX descriptors per ring */
-static int ixgbe_rxd = DEFAULT_RXD;
+static int ixgbe_rxd = PERFORM_RXD;
 TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
 
-/* Total number of Interfaces - need for config sanity check */
+/* Keep running tab on them for sanity check */
 static int ixgbe_total_ports;
 
 /*
@@ -288,6 +301,27 @@ static u32 ixgbe_shadow_vfta[IXGBE_VFTA_
 */
 static int ixgbe_num_segs = IXGBE_82598_SCATTER;
 
+#ifdef IXGBE_FDIR
+/*
+** For Flow Director: this is the
+** number of TX packets we sample
+** for the filter pool, this means
+** every 20th packet will be probed.
+**
+** This feature can be disabled by 
+** setting this to 0.
+*/
+static int atr_sample_rate = 20;
+/* 
+** Flow Director actually 'steals'
+** part of the packet buffer as its
+** filter pool, this variable controls
+** how much it uses:
+**  0 = 64K, 1 = 128K, 2 = 256K
+*/
+static int fdir_pballoc = 1;
+#endif
+
 /*********************************************************************
  *  Device identification routine
  *
@@ -356,7 +390,7 @@ ixgbe_attach(device_t dev)
        struct adapter *adapter;
        struct ixgbe_hw *hw;
        int             error = 0;
-       u16             pci_device_id;
+       u16             pci_device_id, csum;
        u32             ctrl_ext;
 
        INIT_DEBUGOUT("ixgbe_attach: begin");
@@ -376,12 +410,18 @@ ixgbe_attach(device_t dev)
                case IXGBE_DEV_ID_82598EB_CX4 :
                        adapter->optics = IFM_10G_CX4;
                        break;
+               case IXGBE_DEV_ID_82598 :
                case IXGBE_DEV_ID_82598AF_DUAL_PORT :
                case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
                case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+               case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM :
+               case IXGBE_DEV_ID_82598EB_SFP_LOM :
                case IXGBE_DEV_ID_82598AT :
                        adapter->optics = IFM_10G_SR;
                        break;
+               case IXGBE_DEV_ID_82598AT2 :
+                       adapter->optics = IFM_10G_T;
+                       break;
                case IXGBE_DEV_ID_82598EB_XF_LR :
                        adapter->optics = IFM_10G_LR;
                        break;
@@ -390,11 +430,18 @@ ixgbe_attach(device_t dev)
                        ixgbe_num_segs = IXGBE_82599_SCATTER;
                        break;
                case IXGBE_DEV_ID_82599_KX4 :
+               case IXGBE_DEV_ID_82599_KX4_MEZZ:
+               case IXGBE_DEV_ID_82599_CX4 :
                        adapter->optics = IFM_10G_CX4;
                        ixgbe_num_segs = IXGBE_82599_SCATTER;
                        break;
                case IXGBE_DEV_ID_82599_XAUI_LOM :
+               case IXGBE_DEV_ID_82599_COMBO_BACKPLANE :
+                       ixgbe_num_segs = IXGBE_82599_SCATTER;
+                       break;
+               case IXGBE_DEV_ID_82599_T3_LOM:
                        ixgbe_num_segs = IXGBE_82599_SCATTER;
+                       adapter->optics = IFM_10G_T;
                default:
                        break;
        }
@@ -420,21 +467,6 @@ ixgbe_attach(device_t dev)
                        OID_AUTO, "enable_aim", CTLTYPE_INT|CTLFLAG_RW,
                        &ixgbe_enable_aim, 1, "Interrupt Moderation");
 
-        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-                       SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-                       OID_AUTO, "low_latency", CTLTYPE_INT|CTLFLAG_RW,
-                       &ixgbe_low_latency, 1, "Low Latency");
-
-        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-                       SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-                       OID_AUTO, "ave_latency", CTLTYPE_INT|CTLFLAG_RW,
-                       &ixgbe_ave_latency, 1, "Average Latency");
-
-        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
-                       SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-                       OID_AUTO, "bulk_latency", CTLTYPE_INT|CTLFLAG_RW,
-                       &ixgbe_bulk_latency, 1, "Bulk Latency");
-
        /* Set up the timer callout */
        callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
 
@@ -504,10 +536,37 @@ ixgbe_attach(device_t dev)
                goto err_late;
        }
 
-       /* Initialize the hardware */
-       if (ixgbe_hardware_init(adapter)) {
-               device_printf(dev,"Unable to initialize the hardware\n");
+       /* Make sure we have a good EEPROM before we read from it */
+       if (ixgbe_validate_eeprom_checksum(&adapter->hw, &csum) < 0) {
+               device_printf(dev,"The EEPROM Checksum Is Not Valid\n");
+               error = EIO;
+               goto err_late;
+       }
+
+       /* Pick up the smart speed setting */
+       if (hw->mac.type == ixgbe_mac_82599EB)
+               hw->phy.smart_speed = ixgbe_smart_speed;
+
+       /* Get Hardware Flow Control setting */
+       hw->fc.requested_mode = ixgbe_fc_full;
+       hw->fc.pause_time = IXGBE_FC_PAUSE;
+       hw->fc.low_water = IXGBE_FC_LO;
+       hw->fc.high_water = IXGBE_FC_HI;
+       hw->fc.send_xon = TRUE;
+
+       error = ixgbe_init_hw(hw);
+       if (error == 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)
+               device_printf(dev,"Unsupported SFP+ Module\n");
+
+       if (error) {
                error = EIO;
+               device_printf(dev,"Hardware Initialization Failure\n");
                goto err_late;
        }
 
@@ -521,22 +580,6 @@ ixgbe_attach(device_t dev)
        /* Setup OS specific network interface */
        ixgbe_setup_interface(dev, adapter);
 
-#ifdef IXGBE_IEEE1588
-       /*
-       ** Setup the timer: IEEE 1588 support
-       */
-       adapter->cycles.read = ixgbe_read_clock;
-       adapter->cycles.mask = (u64)-1;
-       adapter->cycles.mult = 1;
-       adapter->cycles.shift = IXGBE_TSYNC_SHIFT;
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_TIMINCA, (1<<24) |
-           IXGBE_TSYNC_CYCLE_TIME * IXGBE_TSYNC_SHIFT);
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIML, 0x00000000);
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_SYSTIMH, 0xFF800000);
-
-        // JFV - this is not complete yet
-#endif
-
        /* 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,
@@ -551,6 +594,25 @@ 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");
+        }
+
        /* let hardware know driver is loaded */
        ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
        ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
@@ -581,8 +643,7 @@ static int
 ixgbe_detach(device_t dev)
 {
        struct adapter *adapter = device_get_softc(dev);
-       struct tx_ring *txr = adapter->tx_rings;
-       struct rx_ring *rxr = adapter->rx_rings;
+       struct ix_queue *que = adapter->queues;
        u32     ctrl_ext;
 
        INIT_DEBUGOUT("ixgbe_detach: begin");
@@ -597,17 +658,10 @@ ixgbe_detach(device_t dev)
        ixgbe_stop(adapter);
        IXGBE_CORE_UNLOCK(adapter);
 
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               if (txr->tq) {
-                       taskqueue_drain(txr->tq, &txr->tx_task);
-                       taskqueue_free(txr->tq);
-               }
-       }
-
-       for (int i = 0; i < adapter->num_queues; i++, rxr++) {
-               if (rxr->tq) {
-                       taskqueue_drain(rxr->tq, &rxr->rx_task);
-                       taskqueue_free(rxr->tq);
+       for (int i = 0; i < adapter->num_queues; i++, que++) {
+               if (que->tq) {
+                       taskqueue_drain(que->tq, &que->que_task);
+                       taskqueue_free(que->tq);
                }
        }
 
@@ -616,6 +670,9 @@ ixgbe_detach(device_t dev)
                taskqueue_drain(adapter->tq, &adapter->link_task);
                taskqueue_drain(adapter->tq, &adapter->mod_task);
                taskqueue_drain(adapter->tq, &adapter->msf_task);
+#ifdef IXGBE_FDIR
+               taskqueue_drain(adapter->tq, &adapter->fdir_task);
+#endif
                taskqueue_free(adapter->tq);
        }
 
@@ -700,8 +757,8 @@ ixgbe_start_locked(struct tx_ring *txr, 
                /* Send a copy of the frame to the BPF listener */
                ETHER_BPF_MTAP(ifp, m_head);
 
-               /* Set timeout in case hardware has problems transmitting */
-               txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+               /* Set watchdog on */
+               txr->watchdog_check = TRUE;
 
        }
        return;
@@ -741,6 +798,9 @@ ixgbe_mq_start(struct ifnet *ifp, struct
        /* Which queue to use */
        if ((m->m_flags & M_FLOWID) != 0)
                i = m->m_pkthdr.flowid % adapter->num_queues;
+       else    /* use the cpu we're on */
+               i = curcpu % adapter->num_queues;
+
        txr = &adapter->tx_rings[i];
 
        if (IXGBE_TX_TRYLOCK(txr)) {
@@ -757,53 +817,47 @@ ixgbe_mq_start_locked(struct ifnet *ifp,
 {
        struct adapter  *adapter = txr->adapter;
         struct mbuf     *next;
-        int             err = 0;
+        int             enqueued, err = 0;
 
-       if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
-               err = drbr_enqueue(ifp, txr->br, m);
+       if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
+           IFF_DRV_RUNNING || adapter->link_active == 0) {
+               if (m != NULL)
+                       err = drbr_enqueue(ifp, txr->br, m);
                return (err);
        }
 
-       if (m == NULL) /* Called by tasklet */
-               goto process;
-
-       /* If nothing queued go right to xmit */
-       if (!drbr_needs_enqueue(ifp, txr->br)) {
-               if (ixgbe_xmit(txr, &m)) {
-                       if (m && (err = drbr_enqueue(ifp, txr->br, m)) != 0)
-                                return (err);
-               } else {
-                       /* Success, update stats */
-                       drbr_stats_update(ifp, m->m_pkthdr.len, m->m_flags);
-                       /* Send a copy of the frame to the BPF listener */
-                       ETHER_BPF_MTAP(ifp, m);
-                       /* Set the watchdog */
-                       txr->watchdog_timer = IXGBE_TX_TIMEOUT;
-                }
-
-        } else if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
-               return (err);
-
-process:
-       if (drbr_empty(ifp, txr->br))
-               return (err);
+       enqueued = 0;
+       if (m == NULL) {
+               next = drbr_dequeue(ifp, txr->br);
+       } else if (drbr_needs_enqueue(ifp, txr->br)) {
+               if ((err = drbr_enqueue(ifp, txr->br, m)) != 0)
+                       return (err);
+               next = drbr_dequeue(ifp, txr->br);
+       } else
+               next = m;
 
        /* Process the queue */
-       while (TRUE) {
-               if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+       while (next != NULL) {
+               if ((err = ixgbe_xmit(txr, &next)) != 0) {
+                       if (next != NULL)
+                               err = drbr_enqueue(ifp, txr->br, next);
                        break;
-               next = drbr_dequeue(ifp, txr->br);
-               if (next == NULL)
+               }
+               enqueued++;
+               drbr_stats_update(ifp, next->m_pkthdr.len, next->m_flags);
+               /* 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 (ixgbe_xmit(txr, &next))
+               if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
+                       ifp->if_drv_flags |= IFF_DRV_OACTIVE;
                        break;
-               ETHER_BPF_MTAP(ifp, next);
-               /* Set the watchdog */
-               txr->watchdog_timer = IXGBE_TX_TIMEOUT;
+               }
+               next = drbr_dequeue(ifp, txr->br);
        }
-               
-       if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD)
-               ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+
+       if (enqueued > 0) 
+               txr->watchdog_check = TRUE;
 
        return (err);
 }
@@ -840,29 +894,12 @@ ixgbe_qflush(struct ifnet *ifp)
 static int
 ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
 {
-       struct adapter *adapter = ifp->if_softc;
-       struct ifreq   *ifr = (struct ifreq *) data;
-#ifdef INET
-       struct ifaddr   *ifa = (struct ifaddr *) data;
-#endif
+       struct adapter  *adapter = ifp->if_softc;
+       struct ifreq    *ifr = (struct ifreq *) data;
        int             error = 0;
 
        switch (command) {
-       case SIOCSIFADDR:
-#ifdef INET
-               IOCTL_DEBUGOUT("ioctl: SIOCxIFADDR (Get/Set Interface Addr)");
-               if (ifa->ifa_addr->sa_family == AF_INET) {
-                       ifp->if_flags |= IFF_UP;
-                       if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-                               IXGBE_CORE_LOCK(adapter);
-                               ixgbe_init_locked(adapter);
-                               IXGBE_CORE_UNLOCK(adapter);
-                       }
-                       arp_ifinit(ifp, ifa);
-                } else
-#endif
-                       ether_ioctl(ifp, command, data);
-               break;
+
        case SIOCSIFMTU:
                IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)");
                if (ifr->ifr_mtu > IXGBE_MAX_FRAME_SIZE - ETHER_HDR_LEN) {
@@ -872,7 +909,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
                        ifp->if_mtu = ifr->ifr_mtu;
                        adapter->max_frame_size =
                                ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN;
-                       ixgbe_init_locked(adapter);
+                       error = ixgbe_init_locked(adapter);
                        IXGBE_CORE_UNLOCK(adapter);
                }
                break;
@@ -887,7 +924,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
                                        ixgbe_set_promisc(adapter);
                                 }
                        } else
-                               ixgbe_init_locked(adapter);
+                               error = ixgbe_init_locked(adapter);
                } else
                        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
                                ixgbe_stop(adapter);
@@ -922,21 +959,15 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
                        ifp->if_capenable ^= IFCAP_LRO;
                if (mask & IFCAP_VLAN_HWTAGGING)
                        ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
-               if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-                       ixgbe_init(adapter);
+               if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+                       IXGBE_CORE_LOCK(adapter);
+                       error = ixgbe_init_locked(adapter);
+                       IXGBE_CORE_UNLOCK(adapter);
+               }
                VLAN_CAPABILITIES(ifp);
                break;
        }
 
-#ifdef IXGBE_IEEE1588
-       /*
-       ** IOCTL support for Precision Time (IEEE 1588) Support
-       */
-       case SIOCSHWTSTAMP:
-               error = ixgbe_hwtstamp_ioctl(adapter, ifp);
-               break;
-#endif
-
        default:
                IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
                error = ether_ioctl(ifp, command, data);
@@ -947,84 +978,6 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c
 }
 
 /*********************************************************************
- *  Watchdog entry point
- *
- *  This routine is called by the local timer
- *  to detect hardware hangs .
- *
- **********************************************************************/
-
-static void
-ixgbe_watchdog(struct adapter *adapter)
-{
-       device_t        dev = adapter->dev;
-       struct tx_ring *txr = adapter->tx_rings;
-       struct ixgbe_hw *hw = &adapter->hw;
-       bool            tx_hang = FALSE;
-
-       IXGBE_CORE_LOCK_ASSERT(adapter);
-
-        /*
-         * The timer is set to 5 every time ixgbe_start() queues a packet.
-         * Then ixgbe_txeof() keeps resetting to 5 as long as it cleans at
-         * least one descriptor.
-         * Finally, anytime all descriptors are clean the timer is
-         * set to 0.
-         */
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               u32 head, tail;
-
-               IXGBE_TX_LOCK(txr);
-               if (txr->watchdog_timer == 0 || --txr->watchdog_timer) {
-                       IXGBE_TX_UNLOCK(txr);
-                       continue;
-               } else {
-                       head = IXGBE_READ_REG(hw, IXGBE_TDH(i));
-                       tail = IXGBE_READ_REG(hw, IXGBE_TDT(i));
-                       if (head == tail) { /* last minute check */
-                               IXGBE_TX_UNLOCK(txr);
-                               continue;
-                       }
-                       /* Well, seems something is really hung */
-                       tx_hang = TRUE;
-                       IXGBE_TX_UNLOCK(txr);
-                       break;
-               }
-       }
-       if (tx_hang == FALSE)
-               return;
-
-       /*
-        * If we are in this routine because of pause frames, then don't
-        * reset the hardware.
-        */
-       if (IXGBE_READ_REG(hw, IXGBE_TFCS) & IXGBE_TFCS_TXOFF) {
-               txr = adapter->tx_rings;        /* reset pointer */
-               for (int i = 0; i < adapter->num_queues; i++, txr++) {
-                       IXGBE_TX_LOCK(txr);
-                       txr->watchdog_timer = IXGBE_TX_TIMEOUT;
-                       IXGBE_TX_UNLOCK(txr);
-               }
-               return;
-       }
-
-
-       device_printf(adapter->dev, "Watchdog timeout -- resetting\n");
-       for (int i = 0; i < adapter->num_queues; i++, txr++) {
-               device_printf(dev,"Queue(%d) tdh = %d, hw tdt = %d\n", i,
-                   IXGBE_READ_REG(hw, IXGBE_TDH(i)),
-                   IXGBE_READ_REG(hw, IXGBE_TDT(i)));
-               device_printf(dev,"TX(%d) desc avail = %d,"
-                   "Next TX to Clean = %d\n",
-                   i, txr->tx_avail, txr->next_tx_to_clean);
-       }
-       adapter->ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-       adapter->watchdog_events++;
-
-       ixgbe_init_locked(adapter);
-}
-
-/*********************************************************************
  *  Init entry point
  *
  *  This routine is used in two ways. It is used by the stack as
@@ -1036,42 +989,39 @@ ixgbe_watchdog(struct adapter *adapter)
  **********************************************************************/
 #define IXGBE_MHADD_MFS_SHIFT 16
 
-static void
+static int
 ixgbe_init_locked(struct adapter *adapter)
 {
        struct ifnet   *ifp = adapter->ifp;
        device_t        dev = adapter->dev;
-       struct ixgbe_hw *hw;
+       struct ixgbe_hw *hw = &adapter->hw;
        u32             k, txdctl, mhadd, gpie;
        u32             rxdctl, rxctrl;
-       int             err;
-
-       INIT_DEBUGOUT("ixgbe_init: begin");
 
-       hw = &adapter->hw;
        mtx_assert(&adapter->core_mtx, MA_OWNED);
+       INIT_DEBUGOUT("ixgbe_init: begin");
+       ixgbe_reset_hw(hw);
+       hw->adapter_stopped = FALSE;
+       ixgbe_stop_adapter(hw);
+        callout_stop(&adapter->timer);
 
-       ixgbe_stop(adapter);
+        /* reprogram the RAR[0] in case user changed it. */
+        ixgbe_set_rar(hw, 0, adapter->hw.mac.addr, 0, IXGBE_RAH_AV);
 
        /* Get the latest mac address, User can use a LAA */
-       bcopy(IF_LLADDR(adapter->ifp), adapter->hw.mac.addr,
+       bcopy(IF_LLADDR(adapter->ifp), hw->mac.addr,
              IXGBE_ETH_LENGTH_OF_ADDRESS);
-       ixgbe_set_rar(&adapter->hw, 0, adapter->hw.mac.addr, 0, 1);
-       adapter->hw.addr_ctrl.rar_used_count = 1;
-
-       /* Initialize the hardware */
-       if (ixgbe_hardware_init(adapter)) {
-               device_printf(dev, "Unable to initialize the hardware\n");
-               return;
-       }
+       ixgbe_set_rar(hw, 0, hw->mac.addr, 0, 1);
+       hw->addr_ctrl.rar_used_count = 1;
 
        /* Prepare transmit descriptors and buffers */
        if (ixgbe_setup_transmit_structures(adapter)) {
                device_printf(dev,"Could not setup transmit structures\n");
                ixgbe_stop(adapter);
-               return;
+               return (ENOMEM);
        }
 
+       ixgbe_init_hw(hw);
        ixgbe_initialize_transmit_units(adapter);
 
        /* Setup Multicast table */
@@ -1090,18 +1040,15 @@ ixgbe_init_locked(struct adapter *adapte
        if (ixgbe_setup_receive_structures(adapter)) {
                device_printf(dev,"Could not setup receive structures\n");
                ixgbe_stop(adapter);
-               return;
+               return (ENOMEM);
        }
 
        /* Configure RX settings */
        ixgbe_initialize_receive_units(adapter);
 
-       /* Configure Interrupt Moderation */
-       ixgbe_init_moderation(adapter);
-
        gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
 
-       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+       if (hw->mac.type == ixgbe_mac_82599EB) {
                gpie |= IXGBE_SDP1_GPIEN;
                gpie |= IXGBE_SDP2_GPIEN;
        }
@@ -1116,39 +1063,49 @@ ixgbe_init_locked(struct adapter *adapte
                gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
                    IXGBE_GPIE_OCD;
        }
-       IXGBE_WRITE_REG(&adapter->hw, IXGBE_GPIE, gpie);
+       IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
 
        /* Set the various hardware offload abilities */
        ifp->if_hwassist = 0;
        if (ifp->if_capenable & IFCAP_TSO4)
                ifp->if_hwassist |= CSUM_TSO;
        if (ifp->if_capenable & IFCAP_TXCSUM)
-               ifp->if_hwassist = (CSUM_TCP | CSUM_UDP);
-
+               ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+#if __FreeBSD_version >= 800000
+       if (hw->mac.type == ixgbe_mac_82599EB)
+               ifp->if_hwassist |= CSUM_SCTP;
+#endif
        /* Set MTU size */
        if (ifp->if_mtu > ETHERMTU) {
-               mhadd = IXGBE_READ_REG(&adapter->hw, IXGBE_MHADD);
+               mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
                mhadd &= ~IXGBE_MHADD_MFS_MASK;
                mhadd |= adapter->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
-               IXGBE_WRITE_REG(&adapter->hw, IXGBE_MHADD, mhadd);
+               IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
        }
        
        /* Now enable all the queues */
 
        for (int i = 0; i < adapter->num_queues; i++) {
-               txdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TXDCTL(i));
+               txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(i));
                txdctl |= IXGBE_TXDCTL_ENABLE;
                /* Set WTHRESH to 8, burst writeback */
                txdctl |= (8 << 16);
-               IXGBE_WRITE_REG(&adapter->hw, IXGBE_TXDCTL(i), txdctl);
+               IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(i), txdctl);
        }
 
        for (int i = 0; i < adapter->num_queues; i++) {
-               rxdctl = IXGBE_READ_REG(&adapter->hw, IXGBE_RXDCTL(i));
-               /* PTHRESH set to 32 */
-               rxdctl |= 0x0020;
+               rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(i));
+               if (hw->mac.type == ixgbe_mac_82598EB) {
+                       /*
+                       ** PTHRESH = 21
+                       ** HTHRESH = 4
+                       ** WTHRESH = 8
+                       */
+                       rxdctl &= ~0x3FFFFF;
+                       rxdctl |= 0x080420;
+               }
                rxdctl |= IXGBE_RXDCTL_ENABLE;
-               IXGBE_WRITE_REG(&adapter->hw, IXGBE_RXDCTL(i), rxdctl);
+               IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(i), rxdctl);
                for (k = 0; k < 10; k++) {
                        if (IXGBE_READ_REG(hw, IXGBE_RXDCTL(i)) &
                            IXGBE_RXDCTL_ENABLE)
@@ -1165,10 +1122,10 @@ ixgbe_init_locked(struct adapter *adapte
 
        /* Enable Receive engine */
        rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
-       if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+       if (hw->mac.type == ixgbe_mac_82598EB)
                rxctrl |= IXGBE_RXCTRL_DMBYPS;
        rxctrl |= IXGBE_RXCTRL_RXEN;
-       IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
+       ixgbe_enable_rx_dma(hw, rxctrl);
 
        callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
 
@@ -1180,33 +1137,36 @@ ixgbe_init_locked(struct adapter *adapte
                 ixgbe_set_ivar(adapter, 0, 0, 1);
        }
 
-       ixgbe_enable_intr(adapter);
+#ifdef IXGBE_FDIR
+       /* Init Flow director */
+       if (hw->mac.type == ixgbe_mac_82599EB)
+               ixgbe_init_fdir_signature_82599(&adapter->hw, fdir_pballoc);
+#endif
 
        /*
        ** 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);
+       if (hw->phy.type == ixgbe_phy_none) {
+               int err = hw->phy.ops.identify(hw);
+               if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+                       device_printf(dev,
+                           "Unsupported SFP+ module type was detected.\n");
+                       return (EIO);
+               }
+       }
+
+       /* Config/Enable Link */
+       ixgbe_config_link(adapter);
+
+       /* 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;
+       return (0);
 }
 
 static void
@@ -1268,7 +1228,7 @@ ixgbe_disable_queue(struct adapter *adap
 }
 
 static inline void
-ixgbe_rearm_rx_queues(struct adapter *adapter, u64 queues)
+ixgbe_rearm_queues(struct adapter *adapter, u64 queues)
 {
        u32 mask;
 
@@ -1283,34 +1243,22 @@ ixgbe_rearm_rx_queues(struct adapter *ad
        }
 }
 
-static void
-ixgbe_handle_rx(void *context, int pending)
-{
-       struct rx_ring  *rxr = context;
-       struct adapter  *adapter = rxr->adapter;
-       u32             loop = MAX_LOOP;
-       bool            more;
-
-       do {
-               more = ixgbe_rxeof(rxr, -1);
-       } while (loop-- && more);
-        /* Reenable this interrupt */
-       ixgbe_enable_queue(adapter, rxr->msix);
-}
 
 static void
-ixgbe_handle_tx(void *context, int pending)
+ixgbe_handle_que(void *context, int pending)
 {
-       struct tx_ring  *txr = context;
-       struct adapter  *adapter = txr->adapter;
+       struct ix_queue *que = context;
+       struct adapter  *adapter = que->adapter;
+       struct tx_ring  *txr = que->txr;
        struct ifnet    *ifp = adapter->ifp;
        u32             loop = MAX_LOOP;
-       bool            more;
+       bool            more_rx, more_tx;
 
        IXGBE_TX_LOCK(txr);
        do {
-               more = ixgbe_txeof(txr);
-       } while (loop-- && more);
+               more_rx = ixgbe_rxeof(que, adapter->rx_process_limit);
+               more_tx = ixgbe_txeof(txr);
+       } while (loop-- && (more_rx || more_tx));
 
        if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 #if __FreeBSD_version >= 800000
@@ -1324,7 +1272,7 @@ ixgbe_handle_tx(void *context, int pendi
 
        IXGBE_TX_UNLOCK(txr);
        /* Reenable this interrupt */
-       ixgbe_enable_queue(adapter, txr->msix);
+       ixgbe_enable_queue(adapter, que->msix);
 }
 
 
@@ -1337,33 +1285,32 @@ ixgbe_handle_tx(void *context, int pendi
 static void
 ixgbe_legacy_irq(void *arg)
 {
-       struct adapter  *adapter = arg;
+       struct ix_queue *que = arg;
+       struct adapter  *adapter = que->adapter;
        struct ixgbe_hw *hw = &adapter->hw;
        struct          tx_ring *txr = adapter->tx_rings;
-       struct          rx_ring *rxr = adapter->rx_rings;
-       bool            more;
+       bool            more_tx, more_rx;
        u32             reg_eicr, loop = MAX_LOOP;
 
 
        reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
 
+       ++que->irqs;
        if (reg_eicr == 0) {
                ixgbe_enable_intr(adapter);

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