drivers/net: check process type in close operation
[dpdk.git] / drivers / net / igc / igc_ethdev.c
index 15b63d1..7f5066d 100644 (file)
@@ -15,6 +15,8 @@
 
 #include "igc_logs.h"
 #include "igc_txrx.h"
+#include "igc_filter.h"
+#include "igc_flow.h"
 
 #define IGC_INTEL_VENDOR_ID            0x8086
 
 /* External VLAN Enable bit mask */
 #define IGC_CTRL_EXT_EXT_VLAN          (1u << 26)
 
+/* Speed select */
+#define IGC_CTRL_SPEED_MASK            (7u << 8)
+#define IGC_CTRL_SPEED_2500            (6u << 8)
+
 /* External VLAN Ether Type bit mask and shift */
 #define IGC_VET_EXT                    0xFFFF0000
 #define IGC_VET_EXT_SHIFT              16
 
+/* Force EEE Auto-negotiation */
+#define IGC_EEER_EEE_FRC_AN            (1u << 28)
+
 /* Per Queue Good Packets Received Count */
 #define IGC_PQGPRC(idx)                (0x10010 + 0x100 * (idx))
 /* Per Queue Good Octets Received Count */
@@ -174,7 +183,7 @@ static void eth_igc_stop(struct rte_eth_dev *dev);
 static int eth_igc_start(struct rte_eth_dev *dev);
 static int eth_igc_set_link_up(struct rte_eth_dev *dev);
 static int eth_igc_set_link_down(struct rte_eth_dev *dev);
-static void eth_igc_close(struct rte_eth_dev *dev);
+static int eth_igc_close(struct rte_eth_dev *dev);
 static int eth_igc_reset(struct rte_eth_dev *dev);
 static int eth_igc_promiscuous_enable(struct rte_eth_dev *dev);
 static int eth_igc_promiscuous_disable(struct rte_eth_dev *dev);
@@ -263,10 +272,6 @@ static const struct eth_dev_ops eth_igc_ops = {
 
        .rx_queue_setup         = eth_igc_rx_queue_setup,
        .rx_queue_release       = eth_igc_rx_queue_release,
-       .rx_queue_count         = eth_igc_rx_queue_count,
-       .rx_descriptor_done     = eth_igc_rx_descriptor_done,
-       .rx_descriptor_status   = eth_igc_rx_descriptor_status,
-       .tx_descriptor_status   = eth_igc_tx_descriptor_status,
        .tx_queue_setup         = eth_igc_tx_queue_setup,
        .tx_queue_release       = eth_igc_tx_queue_release,
        .tx_done_cleanup        = eth_igc_tx_done_cleanup,
@@ -292,6 +297,7 @@ static const struct eth_dev_ops eth_igc_ops = {
        .vlan_offload_set       = eth_igc_vlan_offload_set,
        .vlan_tpid_set          = eth_igc_vlan_tpid_set,
        .vlan_strip_queue_set   = eth_igc_vlan_strip_queue_set,
+       .filter_ctrl            = eth_igc_filter_ctrl,
 };
 
 /*
@@ -534,8 +540,7 @@ eth_igc_interrupt_action(struct rte_eth_dev *dev)
                                pci_dev->addr.bus,
                                pci_dev->addr.devid,
                                pci_dev->addr.function);
-               _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC,
-                               NULL);
+               rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
        }
 }
 
@@ -635,6 +640,9 @@ eth_igc_stop(struct rte_eth_dev *dev)
        /* disable all wake up */
        IGC_WRITE_REG(hw, IGC_WUC, 0);
 
+       /* disable checking EEE operation in MAC loopback mode */
+       igc_read_reg_check_clear_bits(hw, IGC_EEER, IGC_EEER_EEE_FRC_AN);
+
        /* Set bit for Go Link disconnect */
        igc_read_reg_check_set_bits(hw, IGC_82580_PHY_POWER_MGMT,
                        IGC_82580_PM_GO_LINKD);
@@ -1060,6 +1068,19 @@ eth_igc_start(struct rte_eth_dev *dev)
        eth_igc_rxtx_control(dev, true);
        eth_igc_link_update(dev, 0);
 
+       /* configure MAC-loopback mode */
+       if (dev->data->dev_conf.lpbk_mode == 1) {
+               uint32_t reg_val;
+
+               reg_val = IGC_READ_REG(hw, IGC_CTRL);
+               reg_val &= ~IGC_CTRL_SPEED_MASK;
+               reg_val |= IGC_CTRL_SLU | IGC_CTRL_FRCSPD |
+                       IGC_CTRL_FRCDPX | IGC_CTRL_FD | IGC_CTRL_SPEED_2500;
+               IGC_WRITE_REG(hw, IGC_CTRL, reg_val);
+
+               igc_read_reg_check_set_bits(hw, IGC_EEER, IGC_EEER_EEE_FRC_AN);
+       }
+
        return 0;
 
 error_invalid_config:
@@ -1144,7 +1165,7 @@ igc_dev_free_queues(struct rte_eth_dev *dev)
        dev->data->nb_tx_queues = 0;
 }
 
-static void
+static int
 eth_igc_close(struct rte_eth_dev *dev)
 {
        struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
@@ -1154,10 +1175,15 @@ eth_igc_close(struct rte_eth_dev *dev)
        int retry = 0;
 
        PMD_INIT_FUNC_TRACE();
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return 0;
 
        if (!adapter->stopped)
                eth_igc_stop(dev);
 
+       igc_flow_flush(dev, NULL);
+       igc_clear_all_filter(dev);
+
        igc_intr_other_disable(dev);
        do {
                int ret = rte_intr_callback_unregister(intr_handle,
@@ -1175,6 +1201,8 @@ eth_igc_close(struct rte_eth_dev *dev)
 
        /* Reset any pending lock */
        igc_reset_swfw_lock(hw);
+
+       return 0;
 }
 
 static void
@@ -1198,6 +1226,10 @@ eth_igc_dev_init(struct rte_eth_dev *dev)
 
        PMD_INIT_FUNC_TRACE();
        dev->dev_ops = &eth_igc_ops;
+       dev->rx_descriptor_done = eth_igc_rx_descriptor_done;
+       dev->rx_queue_count = eth_igc_rx_queue_count;
+       dev->rx_descriptor_status = eth_igc_rx_descriptor_status;
+       dev->tx_descriptor_status = eth_igc_tx_descriptor_status;
 
        /*
         * for secondary processes, we don't initialize any further as primary
@@ -1293,11 +1325,6 @@ eth_igc_dev_init(struct rte_eth_dev *dev)
                goto err_late;
        }
 
-       /* Pass the information to the rte_eth_dev_close() that it should also
-        * release the private port resources.
-        */
-       dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
-
        hw->mac.get_link_status = 1;
        igc->stopped = 0;
 
@@ -1325,6 +1352,8 @@ eth_igc_dev_init(struct rte_eth_dev *dev)
                igc->rxq_stats_map[i] = -1;
        }
 
+       igc_flow_init(dev);
+       igc_clear_all_filter(dev);
        return 0;
 
 err_late:
@@ -1336,10 +1365,6 @@ static int
 eth_igc_dev_uninit(__rte_unused struct rte_eth_dev *eth_dev)
 {
        PMD_INIT_FUNC_TRACE();
-
-       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-               return 0;
-
        eth_igc_close(eth_dev);
        return 0;
 }
@@ -2235,6 +2260,8 @@ eth_igc_rss_reta_update(struct rte_eth_dev *dev,
                return -EINVAL;
        }
 
+       RTE_BUILD_BUG_ON(ETH_RSS_RETA_SIZE_128 % IGC_RSS_RDT_REG_SIZE);
+
        /* set redirection table */
        for (i = 0; i < ETH_RSS_RETA_SIZE_128; i += IGC_RSS_RDT_REG_SIZE) {
                union igc_rss_reta_reg reta, reg;
@@ -2247,7 +2274,8 @@ eth_igc_rss_reta_update(struct rte_eth_dev *dev,
                                IGC_RSS_RDT_REG_SIZE_MASK);
 
                /* if no need to update the register */
-               if (!mask)
+               if (!mask ||
+                   shift > (RTE_RETA_GROUP_SIZE - IGC_RSS_RDT_REG_SIZE))
                        continue;
 
                /* check mask whether need to read the register value first */
@@ -2258,6 +2286,7 @@ eth_igc_rss_reta_update(struct rte_eth_dev *dev,
                                        IGC_RETA(i / IGC_RSS_RDT_REG_SIZE));
 
                /* update the register */
+               RTE_BUILD_BUG_ON(sizeof(reta.bytes) != IGC_RSS_RDT_REG_SIZE);
                for (j = 0; j < IGC_RSS_RDT_REG_SIZE; j++) {
                        if (mask & (1u << j))
                                reta.bytes[j] =
@@ -2287,6 +2316,8 @@ eth_igc_rss_reta_query(struct rte_eth_dev *dev,
                return -EINVAL;
        }
 
+       RTE_BUILD_BUG_ON(ETH_RSS_RETA_SIZE_128 % IGC_RSS_RDT_REG_SIZE);
+
        /* read redirection table */
        for (i = 0; i < ETH_RSS_RETA_SIZE_128; i += IGC_RSS_RDT_REG_SIZE) {
                union igc_rss_reta_reg reta;
@@ -2299,10 +2330,12 @@ eth_igc_rss_reta_query(struct rte_eth_dev *dev,
                                IGC_RSS_RDT_REG_SIZE_MASK);
 
                /* if no need to read register */
-               if (!mask)
+               if (!mask ||
+                   shift > (RTE_RETA_GROUP_SIZE - IGC_RSS_RDT_REG_SIZE))
                        continue;
 
                /* read register and get the queue index */
+               RTE_BUILD_BUG_ON(sizeof(reta.bytes) != IGC_RSS_RDT_REG_SIZE);
                reta.dword = IGC_READ_REG_LE_VALUE(hw,
                                IGC_RETA(i / IGC_RSS_RDT_REG_SIZE));
                for (j = 0; j < IGC_RSS_RDT_REG_SIZE; j++) {