net/i40e: re-program promiscuous mode on VF interface
[dpdk.git] / drivers / net / i40e / i40e_ethdev_vf.c
index 7b1d485..43f7ab5 100644 (file)
@@ -75,8 +75,8 @@ enum i40evf_aq_result {
 static int i40evf_dev_configure(struct rte_eth_dev *dev);
 static int i40evf_dev_start(struct rte_eth_dev *dev);
 static void i40evf_dev_stop(struct rte_eth_dev *dev);
-static void i40evf_dev_info_get(struct rte_eth_dev *dev,
-                               struct rte_eth_dev_info *dev_info);
+static int i40evf_dev_info_get(struct rte_eth_dev *dev,
+                              struct rte_eth_dev_info *dev_info);
 static int i40evf_dev_link_update(struct rte_eth_dev *dev,
                                  int wait_to_complete);
 static int i40evf_dev_stats_get(struct rte_eth_dev *dev,
@@ -86,16 +86,16 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
                                       struct rte_eth_xstat_name *xstats_names,
                                       unsigned limit);
-static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
+static int i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
                                  uint16_t vlan_id, int on);
 static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
 static void i40evf_dev_close(struct rte_eth_dev *dev);
 static int  i40evf_dev_reset(struct rte_eth_dev *dev);
-static void i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev);
-static void i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev);
-static void i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev);
-static void i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev);
+static int i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev);
+static int i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev);
+static int i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev);
+static int i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev);
 static int i40evf_init_vlan(struct rte_eth_dev *dev);
 static int i40evf_dev_rx_queue_start(struct rte_eth_dev *dev,
                                     uint16_t rx_queue_id);
@@ -950,7 +950,7 @@ i40evf_update_stats(struct i40e_vsi *vsi,
        i40evf_stat_update_32(&oes->tx_discards, &nes->tx_discards);
 }
 
-static void
+static int
 i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
 {
        int ret;
@@ -963,6 +963,8 @@ i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
        /* set stats offset base on current values */
        if (ret == 0)
                vf->vsi.eth_stats_offset = *pstats;
+
+       return ret;
 }
 
 static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
@@ -1310,17 +1312,12 @@ err:
 static int
 i40evf_uninit_vf(struct rte_eth_dev *dev)
 {
-       struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 
        PMD_INIT_FUNC_TRACE();
 
        if (hw->adapter_closed == 0)
                i40evf_dev_close(dev);
-       rte_free(vf->vf_res);
-       vf->vf_res = NULL;
-       rte_free(vf->aq_resp);
-       vf->aq_resp = NULL;
 
        return 0;
 }
@@ -1498,6 +1495,11 @@ i40evf_dev_init(struct rte_eth_dev *eth_dev)
        hw->adapter_stopped = 0;
        hw->adapter_closed = 0;
 
+       /* Pass the information to the rte_eth_dev_close() that it should also
+        * release the private port resources.
+        */
+       eth_dev->data->dev_flags |= RTE_ETH_DEV_CLOSE_REMOVE;
+
        if(i40evf_init_vf(eth_dev) != 0) {
                PMD_INIT_LOG(ERR, "Init vf failed");
                return -1;
@@ -1534,10 +1536,6 @@ i40evf_dev_uninit(struct rte_eth_dev *eth_dev)
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return -EPERM;
 
-       eth_dev->dev_ops = NULL;
-       eth_dev->rx_pkt_burst = NULL;
-       eth_dev->tx_pkt_burst = NULL;
-
        if (i40evf_uninit_vf(eth_dev) != 0) {
                PMD_INIT_LOG(ERR, "i40evf_uninit_vf failed");
                return -1;
@@ -2143,80 +2141,82 @@ i40evf_dev_link_update(struct rte_eth_dev *dev,
                new_link.link_speed = ETH_SPEED_NUM_40G;
                break;
        default:
-               new_link.link_speed = ETH_SPEED_NUM_100M;
+               new_link.link_speed = ETH_SPEED_NUM_NONE;
                break;
        }
        /* full duplex only */
        new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
-       new_link.link_status = vf->link_up ? ETH_LINK_UP :
-                                            ETH_LINK_DOWN;
+       new_link.link_status = vf->link_up &&
+                               new_link.link_speed != ETH_SPEED_NUM_NONE
+                               ? ETH_LINK_UP
+                               : ETH_LINK_DOWN;
        new_link.link_autoneg =
                !(dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED);
 
        return rte_eth_linkstatus_set(dev, &new_link);
 }
 
-static void
+static int
 i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev)
 {
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        int ret;
 
-       /* If enabled, just return */
-       if (vf->promisc_unicast_enabled)
-               return;
-
        ret = i40evf_config_promisc(dev, 1, vf->promisc_multicast_enabled);
        if (ret == 0)
                vf->promisc_unicast_enabled = TRUE;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 i40evf_dev_promiscuous_disable(struct rte_eth_dev *dev)
 {
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        int ret;
 
-       /* If disabled, just return */
-       if (!vf->promisc_unicast_enabled)
-               return;
-
        ret = i40evf_config_promisc(dev, 0, vf->promisc_multicast_enabled);
        if (ret == 0)
                vf->promisc_unicast_enabled = FALSE;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 i40evf_dev_allmulticast_enable(struct rte_eth_dev *dev)
 {
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        int ret;
 
-       /* If enabled, just return */
-       if (vf->promisc_multicast_enabled)
-               return;
-
        ret = i40evf_config_promisc(dev, vf->promisc_unicast_enabled, 1);
        if (ret == 0)
                vf->promisc_multicast_enabled = TRUE;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 i40evf_dev_allmulticast_disable(struct rte_eth_dev *dev)
 {
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        int ret;
 
-       /* If enabled, just return */
-       if (!vf->promisc_multicast_enabled)
-               return;
-
        ret = i40evf_config_promisc(dev, vf->promisc_unicast_enabled, 0);
        if (ret == 0)
                vf->promisc_multicast_enabled = FALSE;
+       else
+               ret = -EAGAIN;
+
+       return ret;
 }
 
-static void
+static int
 i40evf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 {
        struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
@@ -2292,6 +2292,8 @@ i40evf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
                .nb_min = I40E_MIN_RING_DESC,
                .nb_align = I40E_ALIGN_RING_DESC,
        };
+
+       return 0;
 }
 
 static int
@@ -2324,6 +2326,7 @@ static void
 i40evf_dev_close(struct rte_eth_dev *dev)
 {
        struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+       struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
        i40evf_dev_stop(dev);
        i40e_dev_free_queues(dev);
@@ -2339,6 +2342,16 @@ i40evf_dev_close(struct rte_eth_dev *dev)
        i40evf_reset_vf(dev);
        i40e_shutdown_adminq(hw);
        i40evf_disable_irq0(hw);
+
+       dev->dev_ops = NULL;
+       dev->rx_pkt_burst = NULL;
+       dev->tx_pkt_burst = NULL;
+
+       rte_free(vf->vf_res);
+       vf->vf_res = NULL;
+       rte_free(vf->aq_resp);
+       vf->aq_resp = NULL;
+
        hw->adapter_closed = 1;
 }