#define MSCC_MIIM_CMD_REGAD_SHIFT              20
 #define MSCC_MIIM_CMD_PHYAD_SHIFT              25
 #define MSCC_MIIM_CMD_VLD                      BIT(31)
+#define VSC9953_VCAP_POLICER_BASE              11
+#define VSC9953_VCAP_POLICER_MAX               31
+#define VSC9953_VCAP_POLICER_BASE2             120
+#define VSC9953_VCAP_POLICER_MAX2              161
 
 static const u32 vsc9953_ana_regmap[] = {
        REG(ANA_ADVLEARN,                       0x00b500),
        .stats_layout           = vsc9953_stats_layout,
        .num_stats              = ARRAY_SIZE(vsc9953_stats_layout),
        .vcap                   = vsc9953_vcap_props,
+       .vcap_pol_base          = VSC9953_VCAP_POLICER_BASE,
+       .vcap_pol_max           = VSC9953_VCAP_POLICER_MAX,
+       .vcap_pol_base2         = VSC9953_VCAP_POLICER_BASE2,
+       .vcap_pol_max2          = VSC9953_VCAP_POLICER_MAX2,
        .num_mact_rows          = 2048,
        .num_ports              = 10,
        .num_tx_queues          = OCELOT_NUM_TC,
 
                return es0_entry_set(ocelot, ix, filter);
 }
 
-static int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
-                                  struct ocelot_policer *pol)
+struct vcap_policer_entry {
+       struct list_head list;
+       refcount_t refcount;
+       u32 pol_ix;
+};
+
+int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
+                           struct ocelot_policer *pol)
 {
        struct qos_policer_conf pp = { 0 };
+       struct vcap_policer_entry *tmp;
+       int ret;
 
        if (!pol)
                return -EINVAL;
        pp.pir = pol->rate;
        pp.pbs = pol->burst;
 
-       return qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
+       list_for_each_entry(tmp, &ocelot->vcap_pol.pol_list, list)
+               if (tmp->pol_ix == pol_ix) {
+                       refcount_inc(&tmp->refcount);
+                       return 0;
+               }
+
+       tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
+       if (!tmp)
+               return -ENOMEM;
+
+       ret = qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
+       if (ret) {
+               kfree(tmp);
+               return ret;
+       }
+
+       tmp->pol_ix = pol_ix;
+       refcount_set(&tmp->refcount, 1);
+       list_add_tail(&tmp->list, &ocelot->vcap_pol.pol_list);
+
+       return 0;
 }
+EXPORT_SYMBOL(ocelot_vcap_policer_add);
 
-static void ocelot_vcap_policer_del(struct ocelot *ocelot,
-                                   struct ocelot_vcap_block *block,
-                                   u32 pol_ix)
+int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix)
 {
-       struct ocelot_vcap_filter *filter;
        struct qos_policer_conf pp = {0};
-       int index = -1;
-
-       if (pol_ix < block->pol_lpr)
-               return;
-
-       list_for_each_entry(filter, &block->rules, list) {
-               index++;
-               if (filter->block_id == VCAP_IS2 &&
-                   filter->action.police_ena &&
-                   filter->action.pol_ix < pol_ix) {
-                       filter->action.pol_ix += 1;
-                       ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
-                                               &filter->action.pol);
-                       is2_entry_set(ocelot, index, filter);
+       struct vcap_policer_entry *tmp, *n;
+       u8 z = 0;
+
+       list_for_each_entry_safe(tmp, n, &ocelot->vcap_pol.pol_list, list)
+               if (tmp->pol_ix == pol_ix) {
+                       z = refcount_dec_and_test(&tmp->refcount);
+                       if (z) {
+                               list_del(&tmp->list);
+                               kfree(tmp);
+                       }
                }
-       }
 
-       pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
-       qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
+       if (z) {
+               pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
+               return qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
+       }
 
-       block->pol_lpr++;
+       return 0;
 }
+EXPORT_SYMBOL(ocelot_vcap_policer_del);
 
-static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot,
-                                           struct ocelot_vcap_block *block,
-                                           struct ocelot_vcap_filter *filter)
+static int ocelot_vcap_filter_add_to_block(struct ocelot *ocelot,
+                                          struct ocelot_vcap_block *block,
+                                          struct ocelot_vcap_filter *filter)
 {
        struct ocelot_vcap_filter *tmp;
        struct list_head *pos, *n;
+       int ret;
 
        if (filter->block_id == VCAP_IS2 && filter->action.police_ena) {
-               block->pol_lpr--;
-               filter->action.pol_ix = block->pol_lpr;
-               ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
-                                       &filter->action.pol);
+               ret = ocelot_vcap_policer_add(ocelot, filter->action.pol_ix,
+                                             &filter->action.pol);
+               if (ret)
+                       return ret;
        }
 
        block->count++;
 
        if (list_empty(&block->rules)) {
                list_add(&filter->list, &block->rules);
-               return;
+               return 0;
        }
 
        list_for_each_safe(pos, n, &block->rules) {
                        break;
        }
        list_add(&filter->list, pos->prev);
+
+       return 0;
 }
 
 static bool ocelot_vcap_filter_equal(const struct ocelot_vcap_filter *a,
                           struct netlink_ext_ack *extack)
 {
        struct ocelot_vcap_block *block = &ocelot->block[filter->block_id];
-       int i, index;
+       int i, index, ret;
 
        if (!ocelot_exclusive_mac_etype_filter_rules(ocelot, filter)) {
                NL_SET_ERR_MSG_MOD(extack,
        }
 
        /* Add filter to the linked list */
-       ocelot_vcap_filter_add_to_block(ocelot, block, filter);
+       ret = ocelot_vcap_filter_add_to_block(ocelot, block, filter);
+       if (ret)
+               return ret;
 
        /* Get the index of the inserted filter */
        index = ocelot_vcap_block_get_filter_index(block, filter);
                if (ocelot_vcap_filter_equal(filter, tmp)) {
                        if (tmp->block_id == VCAP_IS2 &&
                            tmp->action.police_ena)
-                               ocelot_vcap_policer_del(ocelot, block,
+                               ocelot_vcap_policer_del(ocelot,
                                                        tmp->action.pol_ix);
 
                        list_del(pos);
                struct vcap_props *vcap = &ocelot->vcap[i];
 
                INIT_LIST_HEAD(&block->rules);
-               block->pol_lpr = OCELOT_POLICER_DISCARD - 1;
 
                ocelot_vcap_detect_constants(ocelot, vcap);
                ocelot_vcap_init_one(ocelot, vcap);
        }
 
        INIT_LIST_HEAD(&ocelot->dummy_rules);
+       INIT_LIST_HEAD(&ocelot->vcap_pol.pol_list);
 
        return 0;
 }