timer: fix pending counter
[dpdk.git] / lib / librte_pmd_e1000 / igb_ethdev.c
index bcb2176..044eac3 100644 (file)
@@ -51,6 +51,7 @@
 #include <rte_eal.h>
 #include <rte_atomic.h>
 #include <rte_malloc.h>
+#include <rte_dev.h>
 
 #include "e1000_logs.h"
 #include "e1000/e1000_api.h"
@@ -319,6 +320,61 @@ igb_identify_hardware(struct rte_eth_dev *dev)
        /* need to check if it is a vf device below */
 }
 
+static int
+igb_reset_swfw_lock(struct e1000_hw *hw)
+{
+       int ret_val;
+
+       /*
+        * Do mac ops initialization manually here, since we will need
+        * some function pointers set by this call.
+        */
+       ret_val = e1000_init_mac_params(hw);
+       if (ret_val)
+               return ret_val;
+
+       /*
+        * SMBI lock should not fail in this early stage. If this is the case,
+        * it is due to an improper exit of the application.
+        * So force the release of the faulty lock.
+        */
+       if (e1000_get_hw_semaphore_generic(hw) < 0) {
+               DEBUGOUT("SMBI lock released");
+       }
+       e1000_put_hw_semaphore_generic(hw);
+
+       if (hw->mac.ops.acquire_swfw_sync != NULL) {
+               uint16_t mask;
+
+               /*
+                * Phy lock should not fail in this early stage. If this is the case,
+                * it is due to an improper exit of the application.
+                * So force the release of the faulty lock.
+                */
+               mask = E1000_SWFW_PHY0_SM << hw->bus.func;
+               if (hw->bus.func > E1000_FUNC_1)
+                       mask <<= 2;
+               if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) {
+                       DEBUGOUT1("SWFW phy%d lock released", hw->bus.func);
+               }
+               hw->mac.ops.release_swfw_sync(hw, mask);
+
+               /*
+                * This one is more tricky since it is common to all ports; but
+                * swfw_sync retries last long enough (1s) to be almost sure that if
+                * lock can not be taken it is due to an improper lock of the
+                * semaphore.
+                */
+               mask = E1000_SWFW_EEP_SM;
+               if (hw->mac.ops.acquire_swfw_sync(hw, mask) < 0) {
+                       DEBUGOUT("SWFW common locks released");
+               }
+               hw->mac.ops.release_swfw_sync(hw, mask);
+       }
+
+       return E1000_SUCCESS;
+}
+
 static int
 eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
                   struct rte_eth_dev *eth_dev)
@@ -348,13 +404,25 @@ eth_igb_dev_init(__attribute__((unused)) struct eth_driver *eth_drv,
        hw->hw_addr= (void *)pci_dev->mem_resource[0].addr;
 
        igb_identify_hardware(eth_dev);
-       if (e1000_setup_init_funcs(hw, TRUE) != E1000_SUCCESS) {
+       if (e1000_setup_init_funcs(hw, FALSE) != E1000_SUCCESS) {
                error = -EIO;
                goto err_late;
        }
 
        e1000_get_bus_info(hw);
 
+       /* Reset any pending lock */
+       if (igb_reset_swfw_lock(hw) != E1000_SUCCESS) {
+               error = -EIO;
+               goto err_late;
+       }
+
+       /* Finish initialization */
+       if (e1000_setup_init_funcs(hw, TRUE) != E1000_SUCCESS) {
+               error = -EIO;
+               goto err_late;
+       }
+
        hw->mac.autoneg = 1;
        hw->phy.autoneg_wait_to_complete = 0;
        hw->phy.autoneg_advertised = E1000_ALL_SPEED_DUPLEX;
@@ -533,9 +601,7 @@ static struct eth_driver rte_igb_pmd = {
        {
                .name = "rte_igb_pmd",
                .id_table = pci_id_igb_map,
-#ifdef RTE_EAL_UNBIND_PORTS
                .drv_flags = RTE_PCI_DRV_NEED_IGB_UIO,
-#endif
        },
        .eth_dev_init = eth_igb_dev_init,
        .dev_private_size = sizeof(struct e1000_adapter),
@@ -548,16 +614,14 @@ static struct eth_driver rte_igbvf_pmd = {
        {
                .name = "rte_igbvf_pmd",
                .id_table = pci_id_igbvf_map,
-#ifdef RTE_EAL_UNBIND_PORTS
                .drv_flags = RTE_PCI_DRV_NEED_IGB_UIO,
-#endif
        },
        .eth_dev_init = eth_igbvf_dev_init,
        .dev_private_size = sizeof(struct e1000_adapter),
 };
 
-int
-rte_igb_pmd_init(void)
+static int
+rte_igb_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
 {
        rte_eth_driver_register(&rte_igb_pmd);
        return 0;
@@ -579,8 +643,8 @@ igb_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev)
  * Invoked one at EAL init time.
  * Register itself as the [Virtual Poll Mode] Driver of PCI IGB devices.
  */
-int
-rte_igbvf_pmd_init(void)
+static int
+rte_igbvf_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
 {
        DEBUGFUNC("rte_igbvf_pmd_init");
 
@@ -871,7 +935,7 @@ igb_hardware_init(struct e1000_hw *hw)
         *   frames to be received after sending an XOFF.
         * - Low water mark works best when it is very near the high water mark.
         *   This allows the receiver to restart by sending XON when it has
-        *   drained a bit. Here we use an arbitary value of 1500 which will
+        *   drained a bit. Here we use an arbitrary value of 1500 which will
         *   restart after one full frame is pulled from the buffer. There
         *   could be several smaller frames in the buffer and if so they will
         *   not trigger the XON until their total number reduces the buffer
@@ -1027,6 +1091,12 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
        /* Tx Errors */
        rte_stats->oerrors = stats->ecol + stats->latecol;
 
+       /* XON/XOFF pause frames */
+       rte_stats->tx_pause_xon  = stats->xontxc;
+       rte_stats->rx_pause_xon  = stats->xonrxc;
+       rte_stats->tx_pause_xoff = stats->xofftxc;
+       rte_stats->rx_pause_xoff = stats->xoffrxc;
+
        rte_stats->ipackets = stats->gprc;
        rte_stats->opackets = stats->gptc;
        rte_stats->ibytes   = stats->gorc;
@@ -1129,6 +1199,17 @@ eth_igb_infos_get(struct rte_eth_dev *dev,
        dev_info->min_rx_bufsize = 256; /* See BSIZE field of RCTL register. */
        dev_info->max_rx_pktlen  = 0x3FFF; /* See RLPML register. */
        dev_info->max_mac_addrs = hw->mac.rar_entry_count;
+       dev_info->rx_offload_capa =
+               DEV_RX_OFFLOAD_VLAN_STRIP |
+               DEV_RX_OFFLOAD_IPV4_CKSUM |
+               DEV_RX_OFFLOAD_UDP_CKSUM  |
+               DEV_RX_OFFLOAD_TCP_CKSUM;
+       dev_info->tx_offload_capa =
+               DEV_TX_OFFLOAD_VLAN_INSERT |
+               DEV_TX_OFFLOAD_IPV4_CKSUM  |
+               DEV_TX_OFFLOAD_UDP_CKSUM   |
+               DEV_TX_OFFLOAD_TCP_CKSUM   |
+               DEV_TX_OFFLOAD_SCTP_CKSUM;
 
        switch (hw->mac.type) {
        case e1000_82575:
@@ -2102,3 +2183,16 @@ eth_igb_rss_reta_query(struct rte_eth_dev *dev,
  
        return 0;
 }
+
+static struct rte_driver pmd_igb_drv = {
+       .type = PMD_PDEV,
+       .init = rte_igb_pmd_init,
+};
+
+static struct rte_driver pmd_igbvf_drv = {
+       .type = PMD_PDEV,
+       .init = rte_igbvf_pmd_init,
+};
+
+PMD_REGISTER_DRIVER(pmd_igb_drv);
+PMD_REGISTER_DRIVER(pmd_igbvf_drv);