act = mlx5e_tc_act_get(fl_act->id, ns_type);
        if (!act || !act->stats_action)
-               return -EOPNOTSUPP;
+               return mlx5e_tc_fill_action_stats(priv, fl_act);
 
        return act->stats_action(priv, fl_act);
 }
 
        struct mlx5e_tc_act_stats *act_stats;
        int i;
 
+       if (!flow_flag_test(flow, USE_ACT_STATS))
+               return;
+
        list_for_each_entry(attr, &flow->attrs, list) {
                for (i = 0; i < attr->tc_act_cookies_count; i++) {
                        struct rhashtable *ht = &handle->ht;
        int err;
        int i;
 
+       if (!flow_flag_test(flow, USE_ACT_STATS))
+               return 0;
+
        list_for_each_entry(attr, &flow->attrs, list) {
                if (attr->counter)
                        curr_counter = attr->counter;
        mlx5e_tc_act_stats_del_flow(handle, flow);
        return err;
 }
+
+int
+mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
+                             struct flow_offload_action *fl_act)
+{
+       struct rhashtable *ht = &handle->ht;
+       struct mlx5e_tc_act_stats *item;
+       struct mlx5e_tc_act_stats key;
+       u64 pkts, bytes, lastused;
+       int err = 0;
+
+       key.tc_act_cookie = fl_act->cookie;
+
+       rcu_read_lock();
+       item = rhashtable_lookup(ht, &key, act_counters_ht_params);
+       if (!item) {
+               rcu_read_unlock();
+               err = -ENOENT;
+               goto err_out;
+       }
+
+       mlx5_fc_query_cached_raw(item->counter,
+                                &bytes, &pkts, &lastused);
+
+       flow_stats_update(&fl_act->stats,
+                         bytes - item->lastbytes,
+                         pkts - item->lastpackets,
+                         0, lastused, FLOW_ACTION_HW_STATS_DELAYED);
+
+       item->lastpackets = pkts;
+       item->lastbytes = bytes;
+       rcu_read_unlock();
+
+       return 0;
+
+err_out:
+       return err;
+}
 
 mlx5e_tc_act_stats_del_flow(struct mlx5e_tc_act_stats_handle *handle,
                            struct mlx5e_tc_flow *flow);
 
+int
+mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle,
+                             struct flow_offload_action *fl_act);
+
 #endif /* __MLX5_EN_ACT_STATS_H__ */
 
        MLX5E_TC_FLOW_FLAG_TUN_RX                = MLX5E_TC_FLOW_BASE + 9,
        MLX5E_TC_FLOW_FLAG_FAILED                = MLX5E_TC_FLOW_BASE + 10,
        MLX5E_TC_FLOW_FLAG_SAMPLE                = MLX5E_TC_FLOW_BASE + 11,
+       MLX5E_TC_FLOW_FLAG_USE_ACT_STATS         = MLX5E_TC_FLOW_BASE + 12,
 };
 
 struct mlx5e_tc_flow_parse_attr {
 
 
        /* branching action requires its own counter */
        attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
+       flow_flag_set(flow, USE_ACT_STATS);
 
        return 0;
 
        return err;
 }
 
+int mlx5e_tc_fill_action_stats(struct mlx5e_priv *priv,
+                              struct flow_offload_action *fl_act)
+{
+       return mlx5e_tc_act_stats_fill_stats(get_act_stats_handle(priv), fl_act);
+}
+
 int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
                       struct flow_cls_offload *f, unsigned long flags)
 {
        }
 
        if (mlx5e_is_offloaded_flow(flow) || flow_flag_test(flow, CT)) {
-               counter = mlx5e_tc_get_counter(flow);
-               if (!counter)
-                       goto errout;
+               if (flow_flag_test(flow, USE_ACT_STATS)) {
+                       f->use_act_stats = true;
+               } else {
+                       counter = mlx5e_tc_get_counter(flow);
+                       if (!counter)
+                               goto errout;
 
-               mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+                       mlx5_fc_query_cached(counter, &bytes, &packets, &lastuse);
+               }
        }
 
        /* Under multipath it's possible for one rule to be currently
                u64 packets2;
                u64 lastuse2;
 
-               counter = mlx5e_tc_get_counter(flow->peer_flow);
-               if (!counter)
-                       goto no_peer_counter;
-               mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
-
-               bytes += bytes2;
-               packets += packets2;
-               lastuse = max_t(u64, lastuse, lastuse2);
+               if (flow_flag_test(flow, USE_ACT_STATS)) {
+                       f->use_act_stats = true;
+               } else {
+                       counter = mlx5e_tc_get_counter(flow->peer_flow);
+                       if (!counter)
+                               goto no_peer_counter;
+                       mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2);
+
+                       bytes += bytes2;
+                       packets += packets2;
+                       lastuse = max_t(u64, lastuse, lastuse2);
+               }
        }
 
 no_peer_counter:
 
 
 int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv,
                       struct flow_cls_offload *f, unsigned long flags);
+int mlx5e_tc_fill_action_stats(struct mlx5e_priv *priv,
+                              struct flow_offload_action *fl_act);
 
 int mlx5e_tc_configure_matchall(struct mlx5e_priv *priv,
                                struct tc_cls_matchall_offload *f);
 
        counter->lastpackets = c.packets;
 }
 
+void mlx5_fc_query_cached_raw(struct mlx5_fc *counter,
+                             u64 *bytes, u64 *packets, u64 *lastuse)
+{
+       struct mlx5_fc_cache c = counter->cache;
+
+       *bytes = c.bytes;
+       *packets = c.packets;
+       *lastuse = c.lastuse;
+}
+
 void mlx5_fc_queue_stats_work(struct mlx5_core_dev *dev,
                              struct delayed_work *dwork,
                              unsigned long delay)
 
 u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse);
+void mlx5_fc_query_cached_raw(struct mlx5_fc *counter,
+                             u64 *bytes, u64 *packets, u64 *lastuse);
 int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
                  u64 *packets, u64 *bytes);
 u32 mlx5_fc_id(struct mlx5_fc *counter);