return -EOPNOTSUPP;
 }
 
+static int sja1105_policer_validate(const struct flow_action *action,
+                                   const struct flow_action_entry *act,
+                                   struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.rate_pkt_ps) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "QoS offload not support packets per second");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 int sja1105_cls_flower_add(struct dsa_switch *ds, int port,
                           struct flow_cls_offload *cls, bool ingress)
 {
        flow_action_for_each(i, act, &rule->action) {
                switch (act->id) {
                case FLOW_ACTION_POLICE:
-                       if (act->police.rate_pkt_ps) {
-                               NL_SET_ERR_MSG_MOD(extack,
-                                                  "QoS offload not support packets per second");
-                               rc = -EOPNOTSUPP;
+                       rc = sja1105_policer_validate(&rule->action, act, extack);
+                       if (rc)
                                goto out;
-                       }
 
                        rc = sja1105_flower_policer(priv, port, extack, cookie,
                                                    &key,
 
 #include "cxgb4_filter.h"
 #include "cxgb4_tc_flower.h"
 
+static int cxgb4_policer_validate(const struct flow_action *action,
+                                 const struct flow_action_entry *act,
+                                 struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.rate_pkt_ps) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "QoS offload not support packets per second");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int cxgb4_matchall_egress_validate(struct net_device *dev,
                                          struct tc_cls_matchall_offload *cls)
 {
        flow_action_for_each(i, entry, actions) {
                switch (entry->id) {
                case FLOW_ACTION_POLICE:
-                       if (entry->police.rate_pkt_ps) {
-                               NL_SET_ERR_MSG_MOD(extack,
-                                                  "QoS offload not support packets per second");
-                               return -EOPNOTSUPP;
-                       }
+                       ret = cxgb4_policer_validate(actions, entry, extack);
+                       if (ret)
+                               return ret;
+
                        /* Convert bytes per second to bits per second */
                        if (entry->police.rate_bytes_ps * 8 > max_link_rate) {
                                NL_SET_ERR_MSG_MOD(extack,
        flow_action_for_each(i, entry, &cls->rule->action)
                if (entry->id == FLOW_ACTION_POLICE)
                        break;
-       if (entry->police.rate_pkt_ps) {
-               NL_SET_ERR_MSG_MOD(extack,
-                                  "QoS offload not support packets per second");
-               return -EOPNOTSUPP;
-       }
+
+       ret = cxgb4_policer_validate(&cls->rule->action, entry, extack);
+       if (ret)
+               return ret;
+
        /* Convert from bytes per second to Kbps */
        p.u.params.maxrate = div_u64(entry->police.rate_bytes_ps * 8, 1000);
        p.u.params.channel = pi->tx_chan;
 
        return NULL;
 }
 
+static int enetc_psfp_policer_validate(const struct flow_action *action,
+                                      const struct flow_action_entry *act,
+                                      struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.rate_pkt_ps) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "QoS offload not support packets per second");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int enetc_psfp_parse_clsflower(struct enetc_ndev_priv *priv,
                                      struct flow_cls_offload *f)
 {
 
        /* Flow meter and max frame size */
        if (entryp) {
-               if (entryp->police.rate_pkt_ps) {
-                       NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
-                       err = -EOPNOTSUPP;
+               err = enetc_psfp_policer_validate(&rule->action, entryp, extack);
+               if (err)
                        goto free_sfi;
-               }
+
                if (entryp->police.burst) {
                        fmi = kzalloc(sizeof(*fmi), GFP_KERNEL);
                        if (!fmi) {
 
        return 0;
 }
 
+static int otx2_policer_validate(const struct flow_action *action,
+                                const struct flow_action_entry *act,
+                                struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int otx2_tc_egress_matchall_install(struct otx2_nic *nic,
                                           struct tc_cls_matchall_offload *cls)
 {
        entry = &cls->rule->action.entries[0];
        switch (entry->id) {
        case FLOW_ACTION_POLICE:
+               err = otx2_policer_validate(&cls->rule->action, entry, extack);
+               if (err)
+                       return err;
+
                if (entry->police.rate_pkt_ps) {
                        NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
                        return -EOPNOTSUPP;
        u8 nr_police = 0;
        bool pps = false;
        u64 rate;
+       int err;
        int i;
 
        if (!flow_action_has_entries(flow_action)) {
                                return -EOPNOTSUPP;
                        }
 
+                       err = otx2_policer_validate(flow_action, act, extack);
+                       if (err)
+                               return err;
+
                        if (act->police.rate_bytes_ps > 0) {
                                rate = act->police.rate_bytes_ps * 8;
                                burst = act->police.burst;
 
        return err;
 }
 
+static int mlx5e_policer_validate(const struct flow_action *action,
+                                 const struct flow_action_entry *act,
+                                 struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.rate_pkt_ps) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "QoS offload not support packets per second");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int scan_tc_matchall_fdb_actions(struct mlx5e_priv *priv,
                                        struct flow_action *flow_action,
                                        struct netlink_ext_ack *extack)
        flow_action_for_each(i, act, flow_action) {
                switch (act->id) {
                case FLOW_ACTION_POLICE:
-                       if (act->police.rate_pkt_ps) {
-                               NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
-                               return -EOPNOTSUPP;
-                       }
+                       err = mlx5e_policer_validate(flow_action, act, extack);
+                       if (err)
+                               return err;
+
                        err = apply_police_params(priv, act->police.rate_bytes_ps, extack);
                        if (err)
                                return err;
 
 #include "spectrum.h"
 #include "core_acl_flex_keys.h"
 
+static int mlxsw_sp_policer_validate(const struct flow_action *action,
+                                    const struct flow_action_entry *act,
+                                    struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.rate_pkt_ps) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "QoS offload not support packets per second");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
                                         struct mlxsw_sp_flow_block *block,
                                         struct mlxsw_sp_acl_rule_info *rulei,
                                return -EOPNOTSUPP;
                        }
 
-                       if (act->police.rate_pkt_ps) {
-                               NL_SET_ERR_MSG_MOD(extack, "QoS offload not support packets per second");
-                               return -EOPNOTSUPP;
-                       }
+                       err = mlxsw_sp_policer_validate(flow_action, act, extack);
+                       if (err)
+                               return err;
 
                        /* The kernel might adjust the requested burst size so
                         * that it is not exactly a power of two. Re-adjust it
 
 #include <net/pkt_cls.h>
 #include <net/tc_act/tc_gact.h>
 #include <soc/mscc/ocelot_vcap.h>
+#include "ocelot_police.h"
 #include "ocelot_vcap.h"
 
 /* Arbitrarily chosen constants for encoding the VCAP block and lookup number
                                      bool ingress, struct flow_cls_offload *f,
                                      struct ocelot_vcap_filter *filter)
 {
+       const struct flow_action *action = &f->rule->action;
        struct netlink_ext_ack *extack = f->common.extack;
        bool allow_missing_goto_target = false;
        const struct flow_action_entry *a;
        filter->goto_target = -1;
        filter->type = OCELOT_VCAP_FILTER_DUMMY;
 
-       flow_action_for_each(i, a, &f->rule->action) {
+       flow_action_for_each(i, a, action) {
                switch (a->id) {
                case FLOW_ACTION_DROP:
                        if (filter->block_id != VCAP_IS2) {
                                                   "Last action must be GOTO");
                                return -EOPNOTSUPP;
                        }
-                       if (a->police.rate_pkt_ps) {
-                               NL_SET_ERR_MSG_MOD(extack,
-                                                  "QoS offload not support packets per second");
-                               return -EOPNOTSUPP;
-                       }
+
+                       err = ocelot_policer_validate(action, a, extack);
+                       if (err)
+                               return err;
+
                        filter->action.police_ena = true;
 
                        pol_ix = a->hw_index + ocelot->vcap_pol.base;
 
 #include <linux/phy/phy.h>
 #include <net/pkt_cls.h>
 #include "ocelot.h"
+#include "ocelot_police.h"
 #include "ocelot_vcap.h"
 #include "ocelot_fdma.h"
 
                        return -EEXIST;
                }
 
-               if (action->police.rate_pkt_ps) {
-                       NL_SET_ERR_MSG_MOD(extack,
-                                          "QoS offload not support packets per second");
-                       return -EOPNOTSUPP;
-               }
+               err = ocelot_policer_validate(&f->rule->action, action,
+                                             extack);
+               if (err)
+                       return err;
 
                pol.rate = (u32)div_u64(action->police.rate_bytes_ps, 1000) * 8;
                pol.burst = action->police.burst;
 
        return 0;
 }
 
+int ocelot_policer_validate(const struct flow_action *action,
+                           const struct flow_action_entry *a,
+                           struct netlink_ext_ack *extack)
+{
+       if (a->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (a->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           a->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (a->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, a)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but police action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (a->police.peakrate_bytes_ps ||
+           a->police.avrate || a->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       if (a->police.rate_pkt_ps) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload does not support packets per second");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(ocelot_policer_validate);
+
 int ocelot_port_policer_add(struct ocelot *ocelot, int port,
                            struct ocelot_policer *pol)
 {
 
 #define _MSCC_OCELOT_POLICE_H_
 
 #include "ocelot.h"
+#include <net/flow_offload.h>
 
 enum mscc_qos_rate_mode {
        MSCC_QOS_RATE_MODE_DISABLED, /* Policer/shaper disabled */
 int qos_policer_conf_set(struct ocelot *ocelot, int port, u32 pol_ix,
                         struct qos_policer_conf *conf);
 
+int ocelot_policer_validate(const struct flow_action *action,
+                           const struct flow_action_entry *a,
+                           struct netlink_ext_ack *extack);
+
 #endif /* _MSCC_OCELOT_POLICE_H_ */
 
        return 0;
 }
 
+static int nfp_policer_validate(const struct flow_action *action,
+                               const struct flow_action_entry *act,
+                               struct netlink_ext_ack *extack)
+{
+       if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when exceed action is not drop");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+           act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is not pipe or ok");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
+           !flow_action_is_last_entry(action, act)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when conform action is ok, but action is not last");
+               return -EOPNOTSUPP;
+       }
+
+       if (act->police.peakrate_bytes_ps ||
+           act->police.avrate || act->police.overhead) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Offload not supported when peakrate/avrate/overhead is configured");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
 static int
 nfp_flower_install_rate_limiter(struct nfp_app *app, struct net_device *netdev,
                                struct tc_cls_matchall_offload *flow,
        u32 burst;
        bool pps;
        u64 rate;
+       int err;
 
        if (!nfp_netdev_is_nfp_repr(netdev)) {
                NL_SET_ERR_MSG_MOD(extack, "unsupported offload: qos rate limit offload not supported on higher level port");
                                           "unsupported offload: qos rate limit offload requires police action");
                        return -EOPNOTSUPP;
                }
+
+               err = nfp_policer_validate(&flow->rule->action, action, extack);
+               if (err)
+                       return err;
+
                if (action->police.rate_bytes_ps > 0) {
                        if (bps_num++) {
                                NL_SET_ERR_MSG_MOD(extack,
 
        return action->num_entries == 1;
 }
 
+static inline bool flow_action_is_last_entry(const struct flow_action *action,
+                                            const struct flow_action_entry *entry)
+{
+       return entry == &action->entries[action->num_entries - 1];
+}
+
 #define flow_action_for_each(__i, __act, __actions)                    \
         for (__i = 0, __act = &(__actions)->entries[0];                        \
             __i < (__actions)->num_entries;                            \