net/iavf: cleanup Tx buffers
[dpdk.git] / drivers / net / iavf / iavf_ethdev.c
index d69e528..a65140d 100644 (file)
@@ -32,7 +32,7 @@
 static int iavf_dev_configure(struct rte_eth_dev *dev);
 static int iavf_dev_start(struct rte_eth_dev *dev);
 static void iavf_dev_stop(struct rte_eth_dev *dev);
-static void iavf_dev_close(struct rte_eth_dev *dev);
+static int iavf_dev_close(struct rte_eth_dev *dev);
 static int iavf_dev_reset(struct rte_eth_dev *dev);
 static int iavf_dev_info_get(struct rte_eth_dev *dev,
                             struct rte_eth_dev_info *dev_info);
@@ -73,6 +73,9 @@ static int iavf_dev_filter_ctrl(struct rte_eth_dev *dev,
                     enum rte_filter_type filter_type,
                     enum rte_filter_op filter_op,
                     void *arg);
+static int iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num);
 
 static const struct rte_pci_id pci_id_iavf_map[] = {
        { RTE_PCI_DEVICE(IAVF_INTEL_VENDOR_ID, IAVF_DEV_ID_ADAPTIVE_VF) },
@@ -96,6 +99,7 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .allmulticast_disable       = iavf_dev_allmulticast_disable,
        .mac_addr_add               = iavf_dev_add_mac_addr,
        .mac_addr_remove            = iavf_dev_del_mac_addr,
+       .set_mc_addr_list                       = iavf_set_mc_addr_list,
        .vlan_filter_set            = iavf_dev_vlan_filter_set,
        .vlan_offload_set           = iavf_dev_vlan_offload_set,
        .rx_queue_start             = iavf_dev_rx_queue_start,
@@ -113,40 +117,39 @@ static const struct eth_dev_ops iavf_eth_dev_ops = {
        .rss_hash_conf_get          = iavf_dev_rss_hash_conf_get,
        .rxq_info_get               = iavf_dev_rxq_info_get,
        .txq_info_get               = iavf_dev_txq_info_get,
-       .rx_queue_count             = iavf_dev_rxq_count,
-       .rx_descriptor_status       = iavf_dev_rx_desc_status,
-       .tx_descriptor_status       = iavf_dev_tx_desc_status,
        .mtu_set                    = iavf_dev_mtu_set,
        .rx_queue_intr_enable       = iavf_dev_rx_queue_intr_enable,
        .rx_queue_intr_disable      = iavf_dev_rx_queue_intr_disable,
        .filter_ctrl                = iavf_dev_filter_ctrl,
+       .tx_done_cleanup            = iavf_dev_tx_done_cleanup,
 };
 
 static int
-iavf_dev_configure(struct rte_eth_dev *dev)
+iavf_set_mc_addr_list(struct rte_eth_dev *dev,
+                       struct rte_ether_addr *mc_addrs,
+                       uint32_t mc_addrs_num)
 {
-       struct iavf_adapter *ad =
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+       struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
-       struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
-       struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+       int err;
 
-       ad->rx_bulk_alloc_allowed = true;
-       /* Initialize to TRUE. If any of Rx queues doesn't meet the
-        * vector Rx/Tx preconditions, it will be reset.
-        */
-       ad->rx_vec_allowed = true;
-       ad->tx_vec_allowed = true;
+       /* flush previous addresses */
+       err = iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                       false);
+       if (err)
+               return err;
 
-       if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
-               dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+       vf->mc_addrs_num = 0;
+
+       /* add new ones */
+       err = iavf_add_del_mc_addr_list(adapter, mc_addrs, mc_addrs_num, true);
+       if (err)
+               return err;
+
+       vf->mc_addrs_num = mc_addrs_num;
+       memcpy(vf->mc_addrs, mc_addrs, mc_addrs_num * sizeof(*mc_addrs));
 
-       /* Vlan stripping setting */
-       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
-               if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
-                       iavf_enable_vlan_strip(ad);
-               else
-                       iavf_disable_vlan_strip(ad);
-       }
        return 0;
 }
 
@@ -155,7 +158,7 @@ iavf_init_rss(struct iavf_adapter *adapter)
 {
        struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(adapter);
        struct rte_eth_rss_conf *rss_conf;
-       uint8_t i, j, nb_q;
+       uint16_t i, j, nb_q;
        int ret;
 
        rss_conf = &adapter->eth_dev->data->dev_conf.rx_adv_conf.rss_conf;
@@ -206,6 +209,41 @@ iavf_init_rss(struct iavf_adapter *adapter)
        return 0;
 }
 
+static int
+iavf_dev_configure(struct rte_eth_dev *dev)
+{
+       struct iavf_adapter *ad =
+               IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+       struct iavf_info *vf =  IAVF_DEV_PRIVATE_TO_VF(ad);
+       struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+
+       ad->rx_bulk_alloc_allowed = true;
+       /* Initialize to TRUE. If any of Rx queues doesn't meet the
+        * vector Rx/Tx preconditions, it will be reset.
+        */
+       ad->rx_vec_allowed = true;
+       ad->tx_vec_allowed = true;
+
+       if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
+               dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
+
+       /* Vlan stripping setting */
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN) {
+               if (dev_conf->rxmode.offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
+                       iavf_enable_vlan_strip(ad);
+               else
+                       iavf_disable_vlan_strip(ad);
+       }
+
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+               if (iavf_init_rss(ad) != 0) {
+                       PMD_DRV_LOG(ERR, "configure rss failed");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 static int
 iavf_init_rxq(struct rte_eth_dev *dev, struct iavf_rx_queue *rxq)
 {
@@ -246,7 +284,7 @@ iavf_init_rxq(struct rte_eth_dev *dev, struct iavf_rx_queue *rxq)
 
        rxq->max_pkt_len = max_pkt_len;
        if ((dev_data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_SCATTER) ||
-           (rxq->max_pkt_len + 2 * IAVF_VLAN_TAG_SIZE) > buf_size) {
+           rxq->max_pkt_len > buf_size) {
                dev_data->scattered_rx = 1;
        }
        IAVF_PCI_REG_WRITE(rxq->qrx_tail, rxq->nb_rx_desc - 1);
@@ -426,13 +464,6 @@ iavf_dev_start(struct rte_eth_dev *dev)
                return -1;
        }
 
-       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
-               if (iavf_init_rss(adapter) != 0) {
-                       PMD_DRV_LOG(ERR, "configure rss failed");
-                       goto err_rss;
-               }
-       }
-
        if (iavf_configure_queues(adapter) != 0) {
                PMD_DRV_LOG(ERR, "configure queues failed");
                goto err_queue;
@@ -451,6 +482,10 @@ iavf_dev_start(struct rte_eth_dev *dev)
        /* Set all mac addrs */
        iavf_add_del_all_mac_addr(adapter, true);
 
+       /* Set all multicast addresses */
+       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                 true);
+
        if (iavf_start_queues(dev) != 0) {
                PMD_DRV_LOG(ERR, "enable queues failed");
                goto err_mac;
@@ -461,13 +496,13 @@ iavf_dev_start(struct rte_eth_dev *dev)
 err_mac:
        iavf_add_del_all_mac_addr(adapter, false);
 err_queue:
-err_rss:
        return -1;
 }
 
 static void
 iavf_dev_stop(struct rte_eth_dev *dev)
 {
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct rte_intr_handle *intr_handle = dev->intr_handle;
@@ -489,6 +524,11 @@ iavf_dev_stop(struct rte_eth_dev *dev)
 
        /* remove all mac addrs */
        iavf_add_del_all_mac_addr(adapter, false);
+
+       /* remove all multicast addresses */
+       iavf_add_del_mc_addr_list(adapter, vf->mc_addrs, vf->mc_addrs_num,
+                                 false);
+
        adapter->stopped = 1;
 }
 
@@ -501,6 +541,8 @@ iavf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
        dev_info->max_tx_queues = vf->vsi_res->num_queue_pairs;
        dev_info->min_rx_bufsize = IAVF_BUF_SIZE_MIN;
        dev_info->max_rx_pktlen = IAVF_FRAME_SIZE_MAX;
+       dev_info->max_mtu = dev_info->max_rx_pktlen - IAVF_ETH_OVERHEAD;
+       dev_info->min_mtu = RTE_ETHER_MIN_MTU;
        dev_info->hash_key_size = vf->vf_res->rss_key_size;
        dev_info->reta_size = vf->vf_res->rss_lut_size;
        dev_info->flow_type_rss_offloads = IAVF_RSS_OFFLOAD_ALL;
@@ -582,6 +624,8 @@ iavf_dev_link_update(struct rte_eth_dev *dev,
        struct rte_eth_link new_link;
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
 
+       memset(&new_link, 0, sizeof(new_link));
+
        /* Only read status info stored in VF, and the info is updated
         *  when receive LINK_CHANGE evnet from PF by Virtchnnl.
         */
@@ -624,12 +668,7 @@ iavf_dev_link_update(struct rte_eth_dev *dev,
        new_link.link_autoneg = !(dev->data->dev_conf.link_speeds &
                                ETH_LINK_SPEED_FIXED);
 
-       if (rte_atomic64_cmpset((uint64_t *)&dev->data->dev_link,
-                               *(uint64_t *)&dev->data->dev_link,
-                               *(uint64_t *)&new_link) == 0)
-               return -1;
-
-       return 0;
+       return rte_eth_linkstatus_set(dev, &new_link);
 }
 
 static int
@@ -638,18 +677,9 @@ iavf_dev_promiscuous_enable(struct rte_eth_dev *dev)
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
-       int ret;
-
-       if (vf->promisc_unicast_enabled)
-               return 0;
 
-       ret = iavf_config_promisc(adapter, true, vf->promisc_multicast_enabled);
-       if (!ret)
-               vf->promisc_unicast_enabled = true;
-       else
-               ret = -EAGAIN;
-
-       return ret;
+       return iavf_config_promisc(adapter,
+                                 true, vf->promisc_multicast_enabled);
 }
 
 static int
@@ -658,19 +688,9 @@ iavf_dev_promiscuous_disable(struct rte_eth_dev *dev)
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
-       int ret;
 
-       if (!vf->promisc_unicast_enabled)
-               return 0;
-
-       ret = iavf_config_promisc(adapter, false,
-                                 vf->promisc_multicast_enabled);
-       if (!ret)
-               vf->promisc_unicast_enabled = false;
-       else
-               ret = -EAGAIN;
-
-       return ret;
+       return iavf_config_promisc(adapter,
+                                 false, vf->promisc_multicast_enabled);
 }
 
 static int
@@ -679,18 +699,9 @@ iavf_dev_allmulticast_enable(struct rte_eth_dev *dev)
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
-       int ret;
-
-       if (vf->promisc_multicast_enabled)
-               return 0;
-
-       ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, true);
-       if (!ret)
-               vf->promisc_multicast_enabled = true;
-       else
-               ret = -EAGAIN;
 
-       return ret;
+       return iavf_config_promisc(adapter,
+                                 vf->promisc_unicast_enabled, true);
 }
 
 static int
@@ -699,18 +710,9 @@ iavf_dev_allmulticast_disable(struct rte_eth_dev *dev)
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
        struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(adapter);
-       int ret;
-
-       if (!vf->promisc_multicast_enabled)
-               return 0;
 
-       ret = iavf_config_promisc(adapter, vf->promisc_unicast_enabled, false);
-       if (!ret)
-               vf->promisc_multicast_enabled = false;
-       else
-               ret = -EAGAIN;
-
-       return ret;
+       return iavf_config_promisc(adapter,
+                                 vf->promisc_unicast_enabled, false);
 }
 
 static int
@@ -968,9 +970,6 @@ iavf_dev_set_default_mac_addr(struct rte_eth_dev *dev,
        old_addr = (struct rte_ether_addr *)hw->mac.addr;
        perm_addr = (struct rte_ether_addr *)hw->mac.perm_addr;
 
-       if (rte_is_same_ether_addr(mac_addr, old_addr))
-               return 0;
-
        /* If the MAC address is configured by host, skip the setting */
        if (rte_is_valid_assigned_ether_addr(perm_addr))
                return -EPERM;
@@ -1334,6 +1333,9 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
 
        /* assign ops func pointer */
        eth_dev->dev_ops = &iavf_eth_dev_ops;
+       eth_dev->rx_queue_count = iavf_dev_rxq_count;
+       eth_dev->rx_descriptor_status = iavf_dev_rx_desc_status;
+       eth_dev->tx_descriptor_status = iavf_dev_tx_desc_status;
        eth_dev->rx_pkt_burst = &iavf_recv_pkts;
        eth_dev->tx_pkt_burst = &iavf_xmit_pkts;
        eth_dev->tx_pkt_prepare = &iavf_prep_pkts;
@@ -1407,7 +1409,7 @@ iavf_dev_init(struct rte_eth_dev *eth_dev)
        return 0;
 }
 
-static void
+static int
 iavf_dev_close(struct rte_eth_dev *dev)
 {
        struct iavf_hw *hw = IAVF_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1415,10 +1417,23 @@ iavf_dev_close(struct rte_eth_dev *dev)
        struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
        struct iavf_adapter *adapter =
                IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return 0;
 
        iavf_dev_stop(dev);
        iavf_flow_flush(dev, NULL);
        iavf_flow_uninit(adapter);
+
+       /*
+        * disable promiscuous mode before reset vf
+        * it is a workaround solution when work with kernel driver
+        * and it is not the normal way
+        */
+       if (vf->promisc_unicast_enabled || vf->promisc_multicast_enabled)
+               iavf_config_promisc(adapter, false, false);
+
        iavf_shutdown_adminq(hw);
        /* disable uio intr before callback unregister */
        rte_intr_disable(intr_handle);
@@ -1427,20 +1442,21 @@ iavf_dev_close(struct rte_eth_dev *dev)
        rte_intr_callback_unregister(intr_handle,
                                     iavf_dev_interrupt_handler, dev);
        iavf_disable_irq0(hw);
-}
-
-static int
-iavf_dev_uninit(struct rte_eth_dev *dev)
-{
-       struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
-
-       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
-               return -EPERM;
 
        dev->dev_ops = NULL;
        dev->rx_pkt_burst = NULL;
        dev->tx_pkt_burst = NULL;
-       iavf_dev_close(dev);
+
+       if (vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_RSS_PF) {
+               if (vf->rss_lut) {
+                       rte_free(vf->rss_lut);
+                       vf->rss_lut = NULL;
+               }
+               if (vf->rss_key) {
+                       rte_free(vf->rss_key);
+                       vf->rss_key = NULL;
+               }
+       }
 
        rte_free(vf->vf_res);
        vf->vsi_res = NULL;
@@ -1449,14 +1465,18 @@ iavf_dev_uninit(struct rte_eth_dev *dev)
        rte_free(vf->aq_resp);
        vf->aq_resp = NULL;
 
-       if (vf->rss_lut) {
-               rte_free(vf->rss_lut);
-               vf->rss_lut = NULL;
-       }
-       if (vf->rss_key) {
-               rte_free(vf->rss_key);
-               vf->rss_key = NULL;
-       }
+       vf->vf_reset = false;
+
+       return 0;
+}
+
+static int
+iavf_dev_uninit(struct rte_eth_dev *dev)
+{
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return -EPERM;
+
+       iavf_dev_close(dev);
 
        return 0;
 }