net/bonding: fix race condition
[dpdk.git] / drivers / net / enic / enic_ethdev.c
index 111bdc8..b3d5777 100644 (file)
 int enicpmd_logtype_init;
 int enicpmd_logtype_flow;
 
-#define PMD_INIT_LOG(level, fmt, args...) \
-       rte_log(RTE_LOG_ ## level, enicpmd_logtype_init, \
-               "%s" fmt "\n", __func__, ##args)
-
 #define ENICPMD_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>")
 
 /*
@@ -43,9 +39,7 @@ static const struct rte_pci_id pci_id_enic_map[] = {
 #define ENIC_DEVARG_DISABLE_OVERLAY "disable-overlay"
 #define ENIC_DEVARG_IG_VLAN_REWRITE "ig-vlan-rewrite"
 
-RTE_INIT(enicpmd_init_log);
-static void
-enicpmd_init_log(void)
+RTE_INIT(enicpmd_init_log)
 {
        enicpmd_logtype_init = rte_log_register("pmd.net.enic.init");
        if (enicpmd_logtype_init >= 0)
@@ -185,17 +179,21 @@ static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
        uint16_t queue_idx,
        uint16_t nb_desc,
        unsigned int socket_id,
-       __rte_unused const struct rte_eth_txconf *tx_conf)
+       const struct rte_eth_txconf *tx_conf)
 {
        int ret;
        struct enic *enic = pmd_priv(eth_dev);
+       struct vnic_wq *wq;
 
        if (rte_eal_process_type() != RTE_PROC_PRIMARY)
                return -E_RTE_SECONDARY;
 
        ENICPMD_FUNC_TRACE();
        RTE_ASSERT(queue_idx < enic->conf_wq_count);
-       eth_dev->data->tx_queues[queue_idx] = (void *)&enic->wq[queue_idx];
+       wq = &enic->wq[queue_idx];
+       wq->offloads = tx_conf->offloads |
+               eth_dev->data->dev_conf.txmode.offloads;
+       eth_dev->data->tx_queues[queue_idx] = (void *)wq;
 
        ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc);
        if (ret) {
@@ -477,6 +475,7 @@ static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev,
        device_info->max_mac_addrs = ENIC_MAX_MAC_ADDR;
        device_info->rx_offload_capa = enic->rx_offload_capa;
        device_info->tx_offload_capa = enic->tx_offload_capa;
+       device_info->tx_queue_offload_capa = enic->tx_queue_offload_capa;
        device_info->default_rxconf = (struct rte_eth_rxconf) {
                .rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH
        };
@@ -523,7 +522,8 @@ static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
                RTE_PTYPE_UNKNOWN
        };
 
-       if (dev->rx_pkt_burst == enic_recv_pkts)
+       if (dev->rx_pkt_burst == enic_recv_pkts ||
+           dev->rx_pkt_burst == enic_noscatter_recv_pkts)
                return ptypes;
        return NULL;
 }
@@ -765,7 +765,7 @@ static void enicpmd_dev_txq_info_get(struct rte_eth_dev *dev,
        ENICPMD_FUNC_TRACE();
        qinfo->nb_desc = wq->ring.desc_count;
        memset(&qinfo->conf, 0, sizeof(qinfo->conf));
-       qinfo->conf.offloads = enic->tx_offload_capa;
+       qinfo->conf.offloads = wq->offloads;
        /* tx_thresh, and all the other fields are not applicable for enic */
 }
 
@@ -789,6 +789,79 @@ static int enicpmd_dev_rx_queue_intr_disable(struct rte_eth_dev *eth_dev,
        return 0;
 }
 
+static int udp_tunnel_common_check(struct enic *enic,
+                                  struct rte_eth_udp_tunnel *tnl)
+{
+       if (tnl->prot_type != RTE_TUNNEL_TYPE_VXLAN)
+               return -ENOTSUP;
+       if (!enic->overlay_offload) {
+               PMD_INIT_LOG(DEBUG, " vxlan (overlay offload) is not "
+                            "supported\n");
+               return -ENOTSUP;
+       }
+       return 0;
+}
+
+static int update_vxlan_port(struct enic *enic, uint16_t port)
+{
+       if (vnic_dev_overlay_offload_cfg(enic->vdev,
+                                        OVERLAY_CFG_VXLAN_PORT_UPDATE,
+                                        port)) {
+               PMD_INIT_LOG(DEBUG, " failed to update vxlan port\n");
+               return -EINVAL;
+       }
+       PMD_INIT_LOG(DEBUG, " updated vxlan port to %u\n", port);
+       enic->vxlan_port = port;
+       return 0;
+}
+
+static int enicpmd_dev_udp_tunnel_port_add(struct rte_eth_dev *eth_dev,
+                                          struct rte_eth_udp_tunnel *tnl)
+{
+       struct enic *enic = pmd_priv(eth_dev);
+       int ret;
+
+       ENICPMD_FUNC_TRACE();
+       ret = udp_tunnel_common_check(enic, tnl);
+       if (ret)
+               return ret;
+       /*
+        * The NIC has 1 configurable VXLAN port number. "Adding" a new port
+        * number replaces it.
+        */
+       if (tnl->udp_port == enic->vxlan_port || tnl->udp_port == 0) {
+               PMD_INIT_LOG(DEBUG, " %u is already configured or invalid\n",
+                            tnl->udp_port);
+               return -EINVAL;
+       }
+       return update_vxlan_port(enic, tnl->udp_port);
+}
+
+static int enicpmd_dev_udp_tunnel_port_del(struct rte_eth_dev *eth_dev,
+                                          struct rte_eth_udp_tunnel *tnl)
+{
+       struct enic *enic = pmd_priv(eth_dev);
+       int ret;
+
+       ENICPMD_FUNC_TRACE();
+       ret = udp_tunnel_common_check(enic, tnl);
+       if (ret)
+               return ret;
+       /*
+        * Clear the previously set port number and restore the
+        * hardware default port number. Some drivers disable VXLAN
+        * offloads when there are no configured port numbers. But
+        * enic does not do that as VXLAN is part of overlay offload,
+        * which is tied to inner RSS and TSO.
+        */
+       if (tnl->udp_port != enic->vxlan_port) {
+               PMD_INIT_LOG(DEBUG, " %u is not a configured vxlan port\n",
+                            tnl->udp_port);
+               return -EINVAL;
+       }
+       return update_vxlan_port(enic, ENIC_DEFAULT_VXLAN_PORT);
+}
+
 static const struct eth_dev_ops enicpmd_eth_dev_ops = {
        .dev_configure        = enicpmd_dev_configure,
        .dev_start            = enicpmd_dev_start,
@@ -838,6 +911,8 @@ static const struct eth_dev_ops enicpmd_eth_dev_ops = {
        .reta_update          = enicpmd_dev_rss_reta_update,
        .rss_hash_conf_get    = enicpmd_dev_rss_hash_conf_get,
        .rss_hash_update      = enicpmd_dev_rss_hash_update,
+       .udp_tunnel_port_add  = enicpmd_dev_udp_tunnel_port_add,
+       .udp_tunnel_port_del  = enicpmd_dev_udp_tunnel_port_del,
 };
 
 static int enic_parse_disable_overlay(__rte_unused const char *key,