net/mlx5: clean meter resources
[dpdk.git] / drivers / net / mlx5 / mlx5.c
index 1f1ce7a..9a2c711 100644 (file)
@@ -1016,6 +1016,7 @@ mlx5_dev_close(struct rte_eth_dev *dev)
        mlx5_dev_interrupt_handler_devx_uninstall(dev);
        mlx5_traffic_disable(dev);
        mlx5_flow_flush(dev, NULL);
+       mlx5_flow_meter_flush(dev, NULL);
        /* Prevent crashes when queues are still in use. */
        dev->rx_pkt_burst = removed_rx_burst;
        dev->tx_pkt_burst = removed_tx_burst;
@@ -1039,6 +1040,8 @@ mlx5_dev_close(struct rte_eth_dev *dev)
                priv->txqs = NULL;
        }
        mlx5_proc_priv_uninit(dev);
+       if (priv->mreg_cp_tbl)
+               mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL);
        mlx5_mprq_free_mp(dev);
        mlx5_free_shared_dr(priv);
        if (priv->rss_conf.rss_key != NULL)
@@ -1171,6 +1174,7 @@ const struct eth_dev_ops mlx5_dev_ops = {
        .get_module_info = mlx5_get_module_info,
        .get_module_eeprom = mlx5_get_module_eeprom,
        .hairpin_cap_get = mlx5_hairpin_cap_get,
+       .mtr_ops_get = mlx5_flow_meter_ops_get,
 };
 
 /* Available operations from secondary process. */
@@ -1234,6 +1238,7 @@ const struct eth_dev_ops mlx5_dev_ops_isolate = {
        .get_module_info = mlx5_get_module_info,
        .get_module_eeprom = mlx5_get_module_eeprom,
        .hairpin_cap_get = mlx5_hairpin_cap_get,
+       .mtr_ops_get = mlx5_flow_meter_ops_get,
 };
 
 /**
@@ -2286,6 +2291,30 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                        DRV_LOG(DEBUG, "LRO session timeout set to %d usec",
                                config.lro.timeout);
                }
+#if defined(HAVE_MLX5DV_DR) && defined(HAVE_MLX5_DR_CREATE_ACTION_FLOW_METER)
+               if (config.hca_attr.qos.sup && config.hca_attr.qos.srtcm_sup &&
+                   config.dv_flow_en) {
+                       uint8_t reg_c_mask =
+                               config.hca_attr.qos.flow_meter_reg_c_ids;
+                       /*
+                        * Meter needs two REG_C's for color match and pre-sfx
+                        * flow match. Here get the REG_C for color match.
+                        * REG_C_0 and REG_C_1 is reserved for metadata feature.
+                        */
+                       reg_c_mask &= 0xfc;
+                       if (__builtin_popcount(reg_c_mask) < 1) {
+                               priv->mtr_en = 0;
+                               DRV_LOG(WARNING, "No available register for"
+                                       " meter.");
+                       } else {
+                               priv->mtr_color_reg = ffs(reg_c_mask) - 1 +
+                                                     REG_C_0;
+                               priv->mtr_en = 1;
+                               DRV_LOG(DEBUG, "The REG_C meter uses is %d",
+                                       priv->mtr_color_reg);
+                       }
+               }
+#endif
        }
        if (config.mprq.enabled && mprq) {
                if (config.mprq.stride_num_n > mprq_max_stride_num_n ||
@@ -2375,6 +2404,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                mlx5_nl_mac_addr_sync(eth_dev);
        TAILQ_INIT(&priv->flows);
        TAILQ_INIT(&priv->ctrl_flows);
+       TAILQ_INIT(&priv->flow_meters);
+       TAILQ_INIT(&priv->flow_meter_profiles);
        /* Hint libmlx5 to use PMD allocator for data plane resources */
        struct mlx5dv_ctx_allocators alctr = {
                .alloc = &mlx5_alloc_verbs_buf,
@@ -2411,6 +2442,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                err = mlx5_alloc_shared_dr(priv);
                if (err)
                        goto error;
+               priv->qrss_id_pool = mlx5_flow_id_pool_alloc();
+               if (!priv->qrss_id_pool) {
+                       DRV_LOG(ERR, "can't create flow id pool");
+                       err = ENOMEM;
+                       goto error;
+               }
        }
        /* Supported Verbs flow priority number detection. */
        err = mlx5_flow_discover_priorities(eth_dev);
@@ -2452,9 +2489,22 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
                        goto error;
                }
        }
+       if (priv->config.dv_flow_en &&
+           priv->config.dv_xmeta_en != MLX5_XMETA_MODE_LEGACY &&
+           mlx5_flow_ext_mreg_supported(eth_dev) &&
+           priv->sh->dv_regc0_mask) {
+               priv->mreg_cp_tbl = mlx5_hlist_create(MLX5_FLOW_MREG_HNAME,
+                                                     MLX5_FLOW_MREG_HTABLE_SZ);
+               if (!priv->mreg_cp_tbl) {
+                       err = ENOMEM;
+                       goto error;
+               }
+       }
        return eth_dev;
 error:
        if (priv) {
+               if (priv->mreg_cp_tbl)
+                       mlx5_hlist_destroy(priv->mreg_cp_tbl, NULL, NULL);
                if (priv->sh)
                        mlx5_free_shared_dr(priv);
                if (priv->nl_socket_route >= 0)
@@ -2463,6 +2513,8 @@ error:
                        close(priv->nl_socket_rdma);
                if (priv->vmwa_context)
                        mlx5_vlan_vmwa_exit(priv->vmwa_context);
+               if (priv->qrss_id_pool)
+                       mlx5_flow_id_pool_release(priv->qrss_id_pool);
                if (own_domain_id)
                        claim_zero(rte_eth_switch_domain_free(priv->domain_id));
                rte_free(priv);