net/mlx5: reorganize fate actions as union
[dpdk.git] / drivers / net / mlx5 / mlx5_flow_verbs.c
index ef4d7a3..931d547 100644 (file)
@@ -1505,6 +1505,7 @@ flow_verbs_prepare(struct rte_eth_dev *dev,
                   struct rte_flow_error *error)
 {
        size_t size = 0;
+       uint32_t handle_idx = 0;
        struct mlx5_flow *dev_flow;
        struct mlx5_flow_handle *dev_handle;
        struct mlx5_priv *priv = dev->data->dev_private;
@@ -1524,7 +1525,8 @@ flow_verbs_prepare(struct rte_eth_dev *dev,
                                   "not free temporary device flow");
                return NULL;
        }
-       dev_handle = rte_calloc(__func__, 1, MLX5_FLOW_HANDLE_VERBS_SIZE, 0);
+       dev_handle = mlx5_ipool_zmalloc(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
+                                  &handle_idx);
        if (!dev_handle) {
                rte_flow_error_set(error, ENOMEM,
                                   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -1534,6 +1536,7 @@ flow_verbs_prepare(struct rte_eth_dev *dev,
        /* No multi-thread supporting. */
        dev_flow = &((struct mlx5_flow *)priv->inter_flows)[priv->flow_idx++];
        dev_flow->handle = dev_handle;
+       dev_flow->handle_idx = handle_idx;
        /* Memcpy is used, only size needs to be cleared to 0. */
        dev_flow->verbs.size = 0;
        dev_flow->verbs.attr.num_of_specs = 0;
@@ -1739,21 +1742,29 @@ flow_verbs_translate(struct rte_eth_dev *dev,
 static void
 flow_verbs_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
 {
+       struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_flow_handle *handle;
+       uint32_t handle_idx;
 
        if (!flow)
                return;
-       LIST_FOREACH(handle, &flow->dev_handles, next) {
+       SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
+                      handle_idx, handle, next) {
                if (handle->ib_flow) {
                        claim_zero(mlx5_glue->destroy_flow(handle->ib_flow));
                        handle->ib_flow = NULL;
                }
+               /* hrxq is union, don't touch it only the flag is set. */
                if (handle->hrxq) {
-                       if (handle->act_flags & MLX5_FLOW_ACTION_DROP)
+                       if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
                                mlx5_hrxq_drop_release(dev);
-                       else
+                               handle->hrxq = 0;
+                       } else if (handle->act_flags &
+                                 (MLX5_FLOW_ACTION_QUEUE |
+                                 MLX5_FLOW_ACTION_RSS)) {
                                mlx5_hrxq_release(dev, handle->hrxq);
-                       handle->hrxq = NULL;
+                               handle->hrxq = 0;
+                       }
                }
                if (handle->vf_vlan.tag && handle->vf_vlan.created)
                        mlx5_vlan_vmwa_release(dev, &handle->vf_vlan);
@@ -1771,15 +1782,22 @@ flow_verbs_remove(struct rte_eth_dev *dev, struct rte_flow *flow)
 static void
 flow_verbs_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
 {
+       struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_flow_handle *handle;
 
        if (!flow)
                return;
        flow_verbs_remove(dev, flow);
-       while (!LIST_EMPTY(&flow->dev_handles)) {
-               handle = LIST_FIRST(&flow->dev_handles);
-               LIST_REMOVE(handle, next);
-               rte_free(handle);
+       while (flow->dev_handles) {
+               uint32_t tmp_idx = flow->dev_handles;
+
+               handle = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
+                                  tmp_idx);
+               if (!handle)
+                       return;
+               flow->dev_handles = handle->next.next;
+               mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW],
+                          tmp_idx);
        }
        if (flow->counter) {
                flow_verbs_counter_release(dev, flow->counter);
@@ -1807,6 +1825,8 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
        struct mlx5_priv *priv = dev->data->dev_private;
        struct mlx5_flow_handle *handle;
        struct mlx5_flow *dev_flow;
+       struct mlx5_hrxq *hrxq;
+       uint32_t dev_handles;
        int err;
        int idx;
 
@@ -1814,8 +1834,8 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
                dev_flow = &((struct mlx5_flow *)priv->inter_flows)[idx];
                handle = dev_flow->handle;
                if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
-                       handle->hrxq = mlx5_hrxq_drop_new(dev);
-                       if (!handle->hrxq) {
+                       hrxq = mlx5_hrxq_drop_new(dev);
+                       if (!hrxq) {
                                rte_flow_error_set
                                        (error, errno,
                                         RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
@@ -1823,22 +1843,24 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
                                goto error;
                        }
                } else {
-                       struct mlx5_hrxq *hrxq;
+                       uint32_t hrxq_idx;
 
                        MLX5_ASSERT(flow->rss.queue);
-                       hrxq = mlx5_hrxq_get(dev, flow->rss.key,
+                       hrxq_idx = mlx5_hrxq_get(dev, flow->rss.key,
                                             MLX5_RSS_HASH_KEY_LEN,
                                             dev_flow->hash_fields,
                                             (*flow->rss.queue),
                                             flow->rss.queue_num);
-                       if (!hrxq)
-                               hrxq = mlx5_hrxq_new(dev, flow->rss.key,
+                       if (!hrxq_idx)
+                               hrxq_idx = mlx5_hrxq_new(dev, flow->rss.key,
                                                MLX5_RSS_HASH_KEY_LEN,
                                                dev_flow->hash_fields,
                                                (*flow->rss.queue),
                                                flow->rss.queue_num,
                                                !!(handle->layers &
                                                MLX5_FLOW_LAYER_TUNNEL));
+                       hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ],
+                                        hrxq_idx);
                        if (!hrxq) {
                                rte_flow_error_set
                                        (error, rte_errno,
@@ -1846,9 +1868,10 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
                                         "cannot get hash queue");
                                goto error;
                        }
-                       handle->hrxq = hrxq;
+                       handle->hrxq = hrxq_idx;
                }
-               handle->ib_flow = mlx5_glue->create_flow(handle->hrxq->qp,
+               MLX5_ASSERT(hrxq);
+               handle->ib_flow = mlx5_glue->create_flow(hrxq->qp,
                                                     &dev_flow->verbs.attr);
                if (!handle->ib_flow) {
                        rte_flow_error_set(error, errno,
@@ -1871,13 +1894,19 @@ flow_verbs_apply(struct rte_eth_dev *dev, struct rte_flow *flow,
        return 0;
 error:
        err = rte_errno; /* Save rte_errno before cleanup. */
-       LIST_FOREACH(handle, &flow->dev_handles, next) {
+       SILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_MLX5_FLOW], flow->dev_handles,
+                      dev_handles, handle, next) {
+               /* hrxq is union, don't touch it only the flag is set. */
                if (handle->hrxq) {
-                       if (handle->act_flags & MLX5_FLOW_ACTION_DROP)
+                       if (handle->act_flags & MLX5_FLOW_ACTION_DROP) {
                                mlx5_hrxq_drop_release(dev);
-                       else
+                               handle->hrxq = 0;
+                       } else if (handle->act_flags &
+                                 (MLX5_FLOW_ACTION_QUEUE |
+                                 MLX5_FLOW_ACTION_RSS)) {
                                mlx5_hrxq_release(dev, handle->hrxq);
-                       handle->hrxq = NULL;
+                               handle->hrxq = 0;
+                       }
                }
                if (handle->vf_vlan.tag && handle->vf_vlan.created)
                        mlx5_vlan_vmwa_release(dev, &handle->vf_vlan);