MLXSW_RES_ID_MAX_TRAP_GROUPS,
        MLXSW_RES_ID_COUNTER_POOL_SIZE,
        MLXSW_RES_ID_MAX_SPAN,
+       MLXSW_RES_ID_COUNTER_SIZE_PACKETS_BYTES,
        MLXSW_RES_ID_MAX_SYSTEM_PORT,
        MLXSW_RES_ID_MAX_LAG,
        MLXSW_RES_ID_MAX_LAG_MEMBERS,
        [MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
        [MLXSW_RES_ID_COUNTER_POOL_SIZE] = 0x2410,
        [MLXSW_RES_ID_MAX_SPAN] = 0x2420,
+       [MLXSW_RES_ID_COUNTER_SIZE_PACKETS_BYTES] = 0x2443,
        [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502,
        [MLXSW_RES_ID_MAX_LAG] = 0x2520,
        [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521,
 
  */
 MLXSW_ITEM32(tx, hdr, type, 0x0C, 0, 4);
 
+int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
+                             unsigned int counter_index, u64 *packets,
+                             u64 *bytes)
+{
+       char mgpc_pl[MLXSW_REG_MGPC_LEN];
+       int err;
+
+       mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_NOP,
+                           MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES);
+       err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
+       if (err)
+               return err;
+       *packets = mlxsw_reg_mgpc_packet_counter_get(mgpc_pl);
+       *bytes = mlxsw_reg_mgpc_byte_counter_get(mgpc_pl);
+       return 0;
+}
+
+static int mlxsw_sp_flow_counter_clear(struct mlxsw_sp *mlxsw_sp,
+                                      unsigned int counter_index)
+{
+       char mgpc_pl[MLXSW_REG_MGPC_LEN];
+
+       mlxsw_reg_mgpc_pack(mgpc_pl, counter_index, MLXSW_REG_MGPC_OPCODE_CLEAR,
+                           MLXSW_REG_MGPC_COUNTER_SET_TYPE_PACKETS_BYTES);
+       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mgpc), mgpc_pl);
+}
+
+int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp,
+                               unsigned int *p_counter_index)
+{
+       int err;
+
+       err = mlxsw_sp_counter_alloc(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
+                                    p_counter_index);
+       if (err)
+               return err;
+       err = mlxsw_sp_flow_counter_clear(mlxsw_sp, *p_counter_index);
+       if (err)
+               goto err_counter_clear;
+       return 0;
+
+err_counter_clear:
+       mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
+                             *p_counter_index);
+       return err;
+}
+
+void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
+                               unsigned int counter_index)
+{
+        mlxsw_sp_counter_free(mlxsw_sp, MLXSW_SP_COUNTER_SUB_POOL_FLOW,
+                              counter_index);
+}
+
 static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
                                     const struct mlxsw_tx_info *tx_info)
 {
 
                            __be16 protocol, struct tc_cls_flower_offload *f);
 void mlxsw_sp_flower_destroy(struct mlxsw_sp_port *mlxsw_sp_port, bool ingress,
                             struct tc_cls_flower_offload *f);
+int mlxsw_sp_flow_counter_get(struct mlxsw_sp *mlxsw_sp,
+                             unsigned int counter_index, u64 *packets,
+                             u64 *bytes);
+int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp,
+                               unsigned int *p_counter_index);
+void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
+                               unsigned int counter_index);
 
 #endif
 
        struct mlxsw_sp_counter_sub_pool *sub_pools;
 };
 
-static struct mlxsw_sp_counter_sub_pool mlxsw_sp_counter_sub_pools[] = {};
+static struct mlxsw_sp_counter_sub_pool mlxsw_sp_counter_sub_pools[] = {
+       [MLXSW_SP_COUNTER_SUB_POOL_FLOW] = {
+               .bank_count = 6,
+       },
+};
 
 static int mlxsw_sp_counter_pool_validate(struct mlxsw_sp *mlxsw_sp)
 {
        return 0;
 }
 
+static int mlxsw_sp_counter_sub_pools_prepare(struct mlxsw_sp *mlxsw_sp)
+{
+       struct mlxsw_sp_counter_sub_pool *sub_pool;
+
+       /* Prepare generic flow pool*/
+       sub_pool = &mlxsw_sp_counter_sub_pools[MLXSW_SP_COUNTER_SUB_POOL_FLOW];
+       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, COUNTER_SIZE_PACKETS_BYTES))
+               return -EIO;
+       sub_pool->entry_size = MLXSW_CORE_RES_GET(mlxsw_sp->core,
+                                                 COUNTER_SIZE_PACKETS_BYTES);
+       return 0;
+}
+
 int mlxsw_sp_counter_pool_init(struct mlxsw_sp *mlxsw_sp)
 {
        struct mlxsw_sp_counter_sub_pool *sub_pool;
        if (err)
                return err;
 
+       err = mlxsw_sp_counter_sub_pools_prepare(mlxsw_sp);
+       if (err)
+               return err;
+
        pool = kzalloc(sizeof(*pool), GFP_KERNEL);
        if (!pool)
                return -ENOMEM;
 
 #include "spectrum.h"
 
 enum mlxsw_sp_counter_sub_pool_id {
-       /* Placeholder before first pool registered */
-       MLXSW_SP_COUNTER_SUB_POOL_PLACEHOLDER,
+       MLXSW_SP_COUNTER_SUB_POOL_FLOW,
 };
 
 int mlxsw_sp_counter_alloc(struct mlxsw_sp *mlxsw_sp,