--- v5
+++ v3
@@ -1,182 +1,115 @@
-This patch adds stream gate settings for PSFP. Use SGI table to store
-stream gate entries. Disable the gate entry when it is not used by any
-stream.
+Policer was previously automatically assigned from the highest index to
+the lowest index from policer pool. But police action of tc flower now
+uses index to set an police entry. This patch uses the police index to
+set vcap policers, so that one policer can be shared by multiple rules.
Signed-off-by: Xiaoliang Yang <xiaoliang.yang_1@nxp.com>
---
- drivers/net/dsa/ocelot/felix_vsc9959.c | 217 ++++++++++++++++++++++++-
- 1 file changed, 213 insertions(+), 4 deletions(-)
+ drivers/net/dsa/ocelot/felix.c | 2 +
+ drivers/net/dsa/ocelot/felix.h | 2 +
+ drivers/net/dsa/ocelot/felix_vsc9959.c | 4 +
+ drivers/net/ethernet/mscc/ocelot_flower.c | 5 +
+ drivers/net/ethernet/mscc/ocelot_vcap.c | 103 +++++++++++++--------
+ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 7 ++
+ include/soc/mscc/ocelot.h | 11 ++-
+ 7 files changed, 96 insertions(+), 38 deletions(-)
+diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
+index 3656e67af789..1505ef2016da 100644
+--- a/drivers/net/dsa/ocelot/felix.c
++++ b/drivers/net/dsa/ocelot/felix.c
+@@ -984,6 +984,8 @@ static int felix_init_structs(struct felix *felix, int num_phys_ports)
+ ocelot->num_stats = felix->info->num_stats;
+ ocelot->num_mact_rows = felix->info->num_mact_rows;
+ ocelot->vcap = felix->info->vcap;
++ ocelot->vcap_pol.base = felix->info->vcap_pol_base;
++ ocelot->vcap_pol.max = felix->info->vcap_pol_max;
+ ocelot->ops = felix->info->ops;
+ ocelot->npi_inj_prefix = OCELOT_TAG_PREFIX_SHORT;
+ ocelot->npi_xtr_prefix = OCELOT_TAG_PREFIX_SHORT;
+diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
+index 5854bab43327..1a299717b8d1 100644
+--- a/drivers/net/dsa/ocelot/felix.h
++++ b/drivers/net/dsa/ocelot/felix.h
+@@ -21,6 +21,8 @@ struct felix_info {
+ int num_ports;
+ int num_tx_queues;
+ struct vcap_props *vcap;
++ u16 vcap_pol_base;
++ u16 vcap_pol_max;
+ int switch_pci_bar;
+ int imdio_pci_bar;
+ const struct ptp_clock_info *ptp_caps;
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
-index e2601b27484c..6c7d3f3b2a78 100644
+index 103f67736638..c409f0860f92 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
-@@ -8,6 +8,7 @@
- #include <soc/mscc/ocelot_ana.h>
- #include <soc/mscc/ocelot_ptp.h>
- #include <soc/mscc/ocelot_sys.h>
-+#include <net/tc_act/tc_gate.h>
- #include <soc/mscc/ocelot.h>
- #include <linux/dsa/ocelot.h>
- #include <linux/pcs-lynx.h>
-@@ -1341,6 +1342,8 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
- #define VSC9959_PSFP_SFID_MAX 175
- #define VSC9959_PSFP_GATE_ID_MAX 183
- #define VSC9959_PSFP_POLICER_MAX 383
-+#define VSC9959_PSFP_GATE_LIST_NUM 4
-+#define VSC9959_PSFP_GATE_CYCLETIME_MIN 5000
-
- struct felix_stream {
- struct list_head list;
-@@ -1376,6 +1379,24 @@ struct felix_stream_filter_counters {
- u32 red;
- };
-
-+struct felix_stream_gate {
-+ u32 index;
-+ u8 enable;
-+ u8 ipv_valid;
-+ u8 init_ipv;
-+ u64 basetime;
-+ u64 cycletime;
-+ u64 cycletime_ext;
-+ u32 num_entries;
-+ struct action_gate_entry entries[0];
-+};
-+
-+struct felix_stream_gate_entry {
+@@ -19,6 +19,8 @@
+ #include "felix.h"
+
+ #define VSC9959_TAS_GCL_ENTRY_MAX 63
++#define VSC9959_VCAP_POLICER_BASE 63
++#define VSC9959_VCAP_POLICER_MAX 383
+
+ static const u32 vsc9959_ana_regmap[] = {
+ REG(ANA_ADVLEARN, 0x0089a0),
+@@ -1988,6 +1990,8 @@ static const struct felix_info felix_info_vsc9959 = {
+ .stats_layout = vsc9959_stats_layout,
+ .num_stats = ARRAY_SIZE(vsc9959_stats_layout),
+ .vcap = vsc9959_vcap_props,
++ .vcap_pol_base = VSC9959_VCAP_POLICER_BASE,
++ .vcap_pol_max = VSC9959_VCAP_POLICER_MAX,
+ .num_mact_rows = 2048,
+ .num_ports = 6,
+ .num_tx_queues = OCELOT_NUM_TC,
+diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c
+index daeaee99933d..bc8a65c227ca 100644
+--- a/drivers/net/ethernet/mscc/ocelot_flower.c
++++ b/drivers/net/ethernet/mscc/ocelot_flower.c
+@@ -241,6 +241,11 @@ static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
+ return -EOPNOTSUPP;
+ }
+ filter->action.police_ena = true;
++ filter->action.pol_ix = a->police.index +
++ ocelot->vcap_pol.base;
++ if (filter->action.pol_ix > ocelot->vcap_pol.max)
++ return -EINVAL;
++
+ rate = a->police.rate_bytes_ps;
+ filter->action.pol.rate = div_u64(rate, 1000) * 8;
+ filter->action.pol.burst = a->police.burst;
+diff --git a/drivers/net/ethernet/mscc/ocelot_vcap.c b/drivers/net/ethernet/mscc/ocelot_vcap.c
+index 7945393a0655..1639c2780343 100644
+--- a/drivers/net/ethernet/mscc/ocelot_vcap.c
++++ b/drivers/net/ethernet/mscc/ocelot_vcap.c
+@@ -887,10 +887,18 @@ static void vcap_entry_set(struct ocelot *ocelot, int ix,
+ 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 index;
++ u32 pol_ix;
+};
+
- static int vsc9959_stream_identify(struct flow_cls_offload *f,
- struct felix_stream *stream)
++int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
++ struct ocelot_policer *pol)
{
-@@ -1619,6 +1640,18 @@ static int vsc9959_psfp_sfi_table_add(struct ocelot *ocelot,
- return 0;
- }
-
-+static struct felix_stream_filter *
-+vsc9959_psfp_sfi_table_get(struct list_head *sfi_list, u32 index)
-+{
-+ struct felix_stream_filter *tmp;
-+
-+ list_for_each_entry(tmp, sfi_list, list)
-+ if (tmp->index == index)
-+ return tmp;
-+
-+ return NULL;
-+}
-+
- static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index)
- {
- struct felix_stream_filter *tmp, *n;
-@@ -1640,6 +1673,152 @@ static void vsc9959_psfp_sfi_table_del(struct ocelot *ocelot, u32 index)
- }
- }
-
-+static void vsc9959_psfp_parse_gate(const struct flow_action_entry *entry,
-+ struct felix_stream_gate *sgi)
-+{
-+ sgi->index = entry->gate.index;
-+ sgi->ipv_valid = (entry->gate.prio < 0) ? 0 : 1;
-+ sgi->init_ipv = (sgi->ipv_valid) ? entry->gate.prio : 0;
-+ sgi->basetime = entry->gate.basetime;
-+ sgi->cycletime = entry->gate.cycletime;
-+ sgi->num_entries = entry->gate.num_entries;
-+ sgi->enable = 1;
-+
-+ memcpy(sgi->entries, entry->gate.entries,
-+ entry->gate.num_entries * sizeof(struct action_gate_entry));
-+}
-+
-+static u32 vsc9959_sgi_cfg_status(struct ocelot *ocelot)
-+{
-+ return ocelot_read(ocelot, ANA_SG_ACCESS_CTRL);
-+}
-+
-+static int vsc9959_psfp_sgi_set(struct ocelot *ocelot,
-+ struct felix_stream_gate *sgi)
-+{
-+ struct action_gate_entry *e;
-+ struct timespec64 base_ts;
-+ u32 interval_sum = 0;
-+ u32 val;
-+ int i;
-+
-+ if (sgi->index > VSC9959_PSFP_GATE_ID_MAX)
-+ return -EINVAL;
-+
-+ ocelot_write(ocelot, ANA_SG_ACCESS_CTRL_SGID(sgi->index),
-+ ANA_SG_ACCESS_CTRL);
-+
-+ if (!sgi->enable) {
-+ ocelot_rmw(ocelot, ANA_SG_CONFIG_REG_3_INIT_GATE_STATE,
-+ ANA_SG_CONFIG_REG_3_INIT_GATE_STATE |
-+ ANA_SG_CONFIG_REG_3_GATE_ENABLE,
-+ ANA_SG_CONFIG_REG_3);
-+
-+ return 0;
-+ }
-+
-+ if (sgi->cycletime < VSC9959_PSFP_GATE_CYCLETIME_MIN ||
-+ sgi->cycletime > NSEC_PER_SEC)
-+ return -EINVAL;
-+
-+ if (sgi->num_entries > VSC9959_PSFP_GATE_LIST_NUM)
-+ return -EINVAL;
-+
-+ vsc9959_new_base_time(ocelot, sgi->basetime, sgi->cycletime, &base_ts);
-+ ocelot_write(ocelot, base_ts.tv_nsec, ANA_SG_CONFIG_REG_1);
-+ val = lower_32_bits(base_ts.tv_sec);
-+ ocelot_write(ocelot, val, ANA_SG_CONFIG_REG_2);
-+
-+ val = upper_32_bits(base_ts.tv_sec);
-+ ocelot_write(ocelot,
-+ (sgi->ipv_valid ? ANA_SG_CONFIG_REG_3_IPV_VALID : 0) |
-+ ANA_SG_CONFIG_REG_3_INIT_IPV(sgi->init_ipv) |
-+ ANA_SG_CONFIG_REG_3_GATE_ENABLE |
-+ ANA_SG_CONFIG_REG_3_LIST_LENGTH(sgi->num_entries) |
-+ ANA_SG_CONFIG_REG_3_INIT_GATE_STATE |
-+ ANA_SG_CONFIG_REG_3_BASE_TIME_SEC_MSB(val),
-+ ANA_SG_CONFIG_REG_3);
-+
-+ ocelot_write(ocelot, sgi->cycletime, ANA_SG_CONFIG_REG_4);
-+
-+ e = sgi->entries;
-+ for (i = 0; i < sgi->num_entries; i++) {
-+ u32 ips = (e[i].ipv < 0) ? 0 : (e[i].ipv + 8);
-+
-+ ocelot_write_rix(ocelot, ANA_SG_GCL_GS_CONFIG_IPS(ips) |
-+ (e[i].gate_state ?
-+ ANA_SG_GCL_GS_CONFIG_GATE_STATE : 0),
-+ ANA_SG_GCL_GS_CONFIG, i);
-+
-+ interval_sum += e[i].interval;
-+ ocelot_write_rix(ocelot, interval_sum, ANA_SG_GCL_TI_CONFIG, i);
-+ }
-+
-+ ocelot_rmw(ocelot, ANA_SG_ACCESS_CTRL_CONFIG_CHANGE,
-+ ANA_SG_ACCESS_CTRL_CONFIG_CHANGE,
-+ ANA_SG_ACCESS_CTRL);
-+
-+ return readx_poll_timeout(vsc9959_sgi_cfg_status, ocelot, val,
-+ (!(ANA_SG_ACCESS_CTRL_CONFIG_CHANGE & val)),
-+ 10, 100000);
-+}
-+
-+static int vsc9959_psfp_sgi_table_add(struct ocelot *ocelot,
-+ struct felix_stream_gate *sgi)
-+{
-+ struct felix_stream_gate_entry *tmp;
-+ struct ocelot_psfp_list *psfp;
+ struct qos_policer_conf pp = { 0 };
++ struct vcap_policer_entry *tmp;
+ int ret;
-+
-+ psfp = &ocelot->psfp;
-+
-+ list_for_each_entry(tmp, &psfp->sgi_list, list)
-+ if (tmp->index == sgi->index) {
+
+ if (!pol)
+ return -EINVAL;
+@@ -899,57 +907,74 @@ static int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
+ 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;
+ }
@@ -185,133 +118,214 @@
+ if (!tmp)
+ return -ENOMEM;
+
-+ ret = vsc9959_psfp_sgi_set(ocelot, sgi);
++ ret = qos_policer_conf_set(ocelot, 0, pol_ix, &pp);
+ if (ret) {
+ kfree(tmp);
+ return ret;
+ }
+
-+ tmp->index = sgi->index;
++ tmp->pol_ix = pol_ix;
+ refcount_set(&tmp->refcount, 1);
-+ list_add_tail(&tmp->list, &psfp->sgi_list);
++ list_add_tail(&tmp->list, &ocelot->vcap_pol.pol_list);
+
+ return 0;
-+}
-+
-+static void vsc9959_psfp_sgi_table_del(struct ocelot *ocelot,
-+ u32 index)
-+{
-+ struct felix_stream_gate_entry *tmp, *n;
-+ struct felix_stream_gate sgi = {0};
-+ struct ocelot_psfp_list *psfp;
-+ u8 z;
-+
-+ psfp = &ocelot->psfp;
-+
-+ list_for_each_entry_safe(tmp, n, &psfp->sgi_list, list)
-+ if (tmp->index == index) {
+ }
++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) {
-+ sgi.index = index;
-+ sgi.enable = 0;
-+ vsc9959_psfp_sgi_set(ocelot, &sgi);
+ list_del(&tmp->list);
+ kfree(tmp);
+ }
-+ break;
-+ }
-+}
-+
- static void vsc9959_psfp_counters_get(struct ocelot *ocelot, u32 index,
- struct felix_stream_filter_counters *counters)
+ }
+- }
+
+- 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)
{
-@@ -1667,8 +1846,9 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot,
- const struct flow_action_entry *a;
- struct felix_stream *stream_entry;
- struct felix_stream stream = {0};
-+ struct felix_stream_gate *sgi;
- struct ocelot_psfp_list *psfp;
-- int ret, i;
-+ int ret, i, size;
-
- psfp = &ocelot->psfp;
-
-@@ -1681,6 +1861,18 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot,
- flow_action_for_each(i, a, &f->rule->action) {
- switch (a->id) {
- case FLOW_ACTION_GATE:
-+ size = struct_size(sgi, entries, a->gate.num_entries);
-+ sgi = kzalloc(size, GFP_KERNEL);
-+ vsc9959_psfp_parse_gate(a, sgi);
-+ ret = vsc9959_psfp_sgi_table_add(ocelot, sgi);
-+ if (ret) {
-+ kfree(sgi);
-+ return ret;
-+ }
-+ sfi.sg_valid = 1;
-+ sfi.sgid = sgi->index;
-+ kfree(sgi);
-+ break;
- case FLOW_ACTION_POLICE:
- default:
- return -EOPNOTSUPP;
-@@ -1691,7 +1883,8 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot,
- stream_entry = vsc9959_stream_table_lookup(&psfp->stream_list, &stream);
- if (stream_entry) {
- NL_SET_ERR_MSG_MOD(extack, "This stream is already added");
-- return -EEXIST;
-+ ret = -EEXIST;
-+ goto err;
- }
-
- sfi.prio_valid = (stream.prio < 0 ? 0 : 1);
-@@ -1700,14 +1893,22 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot,
-
- ret = vsc9959_psfp_sfi_table_add(ocelot, &sfi);
- if (ret)
-- return ret;
-+ goto err;
-
- stream.sfid = sfi.index;
- stream.sfid_valid = 1;
- ret = vsc9959_stream_table_add(ocelot, &psfp->stream_list,
- &stream, extack);
-- if (ret)
-+ if (ret) {
- vsc9959_psfp_sfi_table_del(ocelot, stream.sfid);
-+ goto err;
-+ }
+ 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) {
+@@ -958,6 +983,8 @@ static void ocelot_vcap_filter_add_to_block(struct ocelot *ocelot,
+ break;
+ }
+ list_add(&filter->list, pos->prev);
+
+ return 0;
-+
-+err:
-+ if (sfi.sg_valid)
-+ vsc9959_psfp_sgi_table_del(ocelot, sfi.sgid);
-
- return ret;
- }
-@@ -1715,6 +1916,7 @@ static int vsc9959_psfp_filter_add(struct ocelot *ocelot,
- static int vsc9959_psfp_filter_del(struct ocelot *ocelot,
- struct flow_cls_offload *f)
+ }
+
+ static bool ocelot_vcap_filter_equal(const struct ocelot_vcap_filter *a,
+@@ -1132,7 +1159,7 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot,
+ struct netlink_ext_ack *extack)
{
-+ static struct felix_stream_filter *sfi;
- struct ocelot_psfp_list *psfp;
- struct felix_stream *stream;
-
-@@ -1724,6 +1926,13 @@ static int vsc9959_psfp_filter_del(struct ocelot *ocelot,
- if (!stream)
- return -ENOMEM;
-
-+ sfi = vsc9959_psfp_sfi_table_get(&psfp->sfi_list, stream->sfid);
-+ if (!sfi)
-+ return -ENOMEM;
-+
-+ if (sfi->sg_valid)
-+ vsc9959_psfp_sgi_table_del(ocelot, sfi->sgid);
-+
- vsc9959_psfp_sfi_table_del(ocelot, stream->sfid);
-
- stream->sfid_valid = 0;
+ 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,
+@@ -1141,7 +1168,9 @@ int ocelot_vcap_filter_add(struct ocelot *ocelot,
+ }
+
+ /* 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);
+@@ -1174,7 +1203,7 @@ static void ocelot_vcap_block_remove_filter(struct ocelot *ocelot,
+ 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);
+@@ -1350,13 +1379,13 @@ int ocelot_vcap_init(struct ocelot *ocelot)
+ 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;
+ }
+diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+index 291ae6817c26..403c47d05304 100644
+--- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c
++++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c
+@@ -20,6 +20,9 @@
+ #include <soc/mscc/ocelot_hsio.h>
+ #include "ocelot.h"
+
++#define VSC7514_VCAP_POLICER_BASE 128
++#define VSC7514_VCAP_POLICER_MAX 191
++
+ static const u32 ocelot_ana_regmap[] = {
+ REG(ANA_ADVLEARN, 0x009000),
+ REG(ANA_VLANMASK, 0x009004),
+@@ -1128,6 +1131,10 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
+ ocelot->num_flooding_pgids = 1;
+
+ ocelot->vcap = vsc7514_vcap_props;
++
++ ocelot->vcap_pol.base = VSC7514_VCAP_POLICER_BASE;
++ ocelot->vcap_pol.max = VSC7514_VCAP_POLICER_MAX;
++
+ ocelot->npi = -1;
+
+ err = ocelot_init(ocelot);
+diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
+index a611f9cd5935..fa006168e7fe 100644
+--- a/include/soc/mscc/ocelot.h
++++ b/include/soc/mscc/ocelot.h
+@@ -571,10 +571,15 @@ struct ocelot_ops {
+ struct flow_stats *stats);
+ };
+
++struct ocelot_vcap_policer {
++ struct list_head pol_list;
++ u16 base;
++ u16 max;
++};
++
+ struct ocelot_vcap_block {
+ struct list_head rules;
+ int count;
+- int pol_lpr;
+ };
+
+ struct ocelot_vlan {
+@@ -677,6 +682,7 @@ struct ocelot {
+
+ struct list_head dummy_rules;
+ struct ocelot_vcap_block block[3];
++ struct ocelot_vcap_policer vcap_pol;
+ struct vcap_props *vcap;
+
+ struct ocelot_psfp_list psfp;
+@@ -941,6 +947,9 @@ int ocelot_mact_lookup(struct ocelot *ocelot, const unsigned char mac[ETH_ALEN],
+ void ocelot_mact_write(struct ocelot *ocelot, int port,
+ const struct ocelot_mact_entry *entry,
+ int row, int col);
++int ocelot_vcap_policer_add(struct ocelot *ocelot, u32 pol_ix,
++ struct ocelot_policer *pol);
++int ocelot_vcap_policer_del(struct ocelot *ocelot, u32 pol_ix);
+
+ #if IS_ENABLED(CONFIG_BRIDGE_MRP)
+ int ocelot_mrp_add(struct ocelot *ocelot, int port,
--
2.17.1