u32 hairpin_tirn;
        u8 match_level;
        struct mlx5_flow_table  *hairpin_ft;
+       struct mlx5_fc          *counter;
 };
 
 #define MLX5E_TC_FLOW_BASE (MLX5E_TC_LAST_EXPORTED_BIT + 1)
                dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
                dest[dest_ix].counter = counter;
                dest_ix++;
+               attr->counter = counter;
        }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
        struct mlx5_nic_flow_attr *attr = flow->nic_attr;
        struct mlx5_fc *counter = NULL;
 
-       counter = mlx5_flow_rule_counter(flow->rule[0]);
+       counter = attr->counter;
        mlx5_del_flow_rules(flow->rule[0]);
        mlx5_fc_destroy(priv->mdev, counter);
 
        struct mlx5_esw_flow_attr *attr = flow->esw_attr;
        struct net_device *out_dev, *encap_dev = NULL;
        struct mlx5_flow_handle *rule = NULL;
+       struct mlx5_fc *counter = NULL;
        struct mlx5e_rep_priv *rpriv;
        struct mlx5e_priv *out_priv;
        int err;
                }
        }
 
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+               counter = mlx5_fc_create(esw->dev, true);
+               if (IS_ERR(counter)) {
+                       rule = ERR_CAST(counter);
+                       goto err_create_counter;
+               }
+
+               attr->counter = counter;
+       }
+
        /* we get here if (1) there's no error (rule being null) or when
         * (2) there's an encap action and we're on -EAGAIN (no valid neigh)
         */
        mlx5_eswitch_del_offloaded_rule(esw, rule, attr);
        rule = flow->rule[1];
 err_add_rule:
+       mlx5_fc_destroy(esw->dev, counter);
+err_create_counter:
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                mlx5e_detach_mod_hdr(priv, flow);
 err_mod_hdr:
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                mlx5e_detach_mod_hdr(priv, flow);
+
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
+               mlx5_fc_destroy(esw->dev, attr->counter);
 }
 
 void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
        }
 }
 
+static struct mlx5_fc *mlx5e_tc_get_counter(struct mlx5e_tc_flow *flow)
+{
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+               return flow->esw_attr->counter;
+       else
+               return flow->nic_attr->counter;
+}
+
 void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
 {
        struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
                        continue;
                list_for_each_entry(flow, &e->flows, encap) {
                        if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
-                               counter = mlx5_flow_rule_counter(flow->rule[0]);
+                               counter = mlx5e_tc_get_counter(flow);
                                mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
                                if (time_after((unsigned long)lastuse, nhe->reported_lastuse)) {
                                        neigh_used = true;
        if (!(flow->flags & MLX5E_TC_FLOW_OFFLOADED))
                return 0;
 
-       counter = mlx5_flow_rule_counter(flow->rule[0]);
+       counter = mlx5e_tc_get_counter(flow);
        if (!counter)
                return 0;
 
 
        struct mlx5_flow_destination dest[MLX5_MAX_FLOW_FWD_VPORTS + 1] = {};
        struct mlx5_flow_act flow_act = {0};
        struct mlx5_flow_table *ft = NULL;
-       struct mlx5_fc *counter = NULL;
        struct mlx5_flow_handle *rule;
        int j, i = 0;
        void *misc;
                }
        }
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
-               counter = mlx5_fc_create(esw->dev, true);
-               if (IS_ERR(counter)) {
-                       rule = ERR_CAST(counter);
-                       goto err_counter_alloc;
-               }
                dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
-               dest[i].counter = counter;
+               dest[i].counter = attr->counter;
                i++;
        }
 
 
        rule = mlx5_add_flow_rules(ft, spec, &flow_act, dest, i);
        if (IS_ERR(rule))
-               goto err_add_rule;
+               goto out;
        else
                esw->offloads.num_flows++;
 
-       return rule;
-
-err_add_rule:
-       mlx5_fc_destroy(esw->dev, counter);
-err_counter_alloc:
+out:
        return rule;
 }
 
                                struct mlx5_flow_handle *rule,
                                struct mlx5_esw_flow_attr *attr)
 {
-       struct mlx5_fc *counter = NULL;
-
-       counter = mlx5_flow_rule_counter(rule);
        mlx5_del_flow_rules(rule);
-       mlx5_fc_destroy(esw->dev, counter);
        esw->offloads.num_flows--;
 }