1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
4 * Copyright (c) 2019 Microsemi Corporation
7 #include <soc/mscc/ocelot.h>
8 #include "ocelot_police.h"
10 /* Types for ANA:POL[0-192]:POL_MODE_CFG.FRM_MODE */
11 #define POL_MODE_LINERATE 0 /* Incl IPG. Unit: 33 1/3 kbps, 4096 bytes */
12 #define POL_MODE_DATARATE 1 /* Excl IPG. Unit: 33 1/3 kbps, 4096 bytes */
13 #define POL_MODE_FRMRATE_HI 2 /* Unit: 33 1/3 fps, 32.8 frames */
14 #define POL_MODE_FRMRATE_LO 3 /* Unit: 1/3 fps, 0.3 frames */
17 #define POL_IX_PORT 0 /* 0-11 : Port policers */
18 #define POL_IX_QUEUE 32 /* 32-127 : Queue policers */
20 /* Default policer order */
21 #define POL_ORDER 0x1d3 /* Ocelot policer order: Serial (QoS -> Port -> VCAP) */
23 int qos_policer_conf_set(struct ocelot *ocelot, u32 pol_ix,
24 struct qos_policer_conf *conf)
26 u32 cf = 0, cir_ena = 0, frm_mode = POL_MODE_LINERATE;
27 u32 cir = 0, cbs = 0, pir = 0, pbs = 0;
28 bool cir_discard = 0, pir_discard = 0;
29 u32 pbs_max = 0, cbs_max = 0;
37 case MSCC_QOS_RATE_MODE_LINE:
38 case MSCC_QOS_RATE_MODE_DATA:
39 if (conf->mode == MSCC_QOS_RATE_MODE_LINE) {
40 frm_mode = POL_MODE_LINERATE;
41 ipg = min_t(u8, GENMASK(4, 0), conf->ipg);
43 frm_mode = POL_MODE_DATARATE;
49 if (cir == 0 && cbs == 0) {
50 /* Discard cir frames */
53 cir = DIV_ROUND_UP(cir, 100);
54 cir *= 3; /* 33 1/3 kbps */
55 cbs = DIV_ROUND_UP(cbs, 4096);
56 cbs = (cbs ? cbs : 1); /* No zero burst size */
57 cbs_max = 60; /* Limit burst size */
63 if (pir == 0 && pbs == 0) {
64 /* Discard PIR frames */
67 pir = DIV_ROUND_UP(pir, 100);
68 pir *= 3; /* 33 1/3 kbps */
69 pbs = DIV_ROUND_UP(pbs, 4096);
70 pbs = (pbs ? pbs : 1); /* No zero burst size */
71 pbs_max = 60; /* Limit burst size */
74 case MSCC_QOS_RATE_MODE_FRAME:
76 frm_mode = POL_MODE_FRMRATE_HI;
77 pir = DIV_ROUND_UP(pir, 100);
78 pir *= 3; /* 33 1/3 fps */
79 pbs = (pbs * 10) / 328; /* 32.8 frames */
80 pbs = (pbs ? pbs : 1); /* No zero burst size */
81 pbs_max = GENMASK(6, 0); /* Limit burst size */
83 frm_mode = POL_MODE_FRMRATE_LO;
84 if (pir == 0 && pbs == 0) {
85 /* Discard all frames */
89 pir *= 3; /* 1/3 fps */
90 pbs = (pbs * 10) / 3; /* 0.3 frames */
91 pbs = (pbs ? pbs : 1); /* No zero burst size */
92 pbs_max = 61; /* Limit burst size */
96 default: /* MSCC_QOS_RATE_MODE_DISABLED */
97 /* Disable policer using maximum rate and zero burst */
104 if (pir > GENMASK(15, 0)) {
106 "Invalid pir for policer %u: %u (max %lu)\n",
107 pol_ix, pir, GENMASK(15, 0));
111 if (cir > GENMASK(15, 0)) {
113 "Invalid cir for policer %u: %u (max %lu)\n",
114 pol_ix, cir, GENMASK(15, 0));
120 "Invalid pbs for policer %u: %u (max %u)\n",
121 pol_ix, pbs, pbs_max);
127 "Invalid cbs for policer %u: %u (max %u)\n",
128 pol_ix, cbs, cbs_max);
132 value = (ANA_POL_MODE_CFG_IPG_SIZE(ipg) |
133 ANA_POL_MODE_CFG_FRM_MODE(frm_mode) |
134 (cf ? ANA_POL_MODE_CFG_DLB_COUPLED : 0) |
135 (cir_ena ? ANA_POL_MODE_CFG_CIR_ENA : 0) |
136 ANA_POL_MODE_CFG_OVERSHOOT_ENA);
138 ocelot_write_gix(ocelot, value, ANA_POL_MODE_CFG, pol_ix);
140 ocelot_write_gix(ocelot,
141 ANA_POL_PIR_CFG_PIR_RATE(pir) |
142 ANA_POL_PIR_CFG_PIR_BURST(pbs),
143 ANA_POL_PIR_CFG, pol_ix);
145 ocelot_write_gix(ocelot,
146 (pir_discard ? GENMASK(22, 0) : 0),
147 ANA_POL_PIR_STATE, pol_ix);
149 ocelot_write_gix(ocelot,
150 ANA_POL_CIR_CFG_CIR_RATE(cir) |
151 ANA_POL_CIR_CFG_CIR_BURST(cbs),
152 ANA_POL_CIR_CFG, pol_ix);
154 ocelot_write_gix(ocelot,
155 (cir_discard ? GENMASK(22, 0) : 0),
156 ANA_POL_CIR_STATE, pol_ix);
161 int ocelot_policer_validate(const struct flow_action *action,
162 const struct flow_action_entry *a,
163 struct netlink_ext_ack *extack)
165 if (a->police.exceed.act_id != FLOW_ACTION_DROP) {
166 NL_SET_ERR_MSG_MOD(extack,
167 "Offload not supported when exceed action is not drop");
171 if (a->police.notexceed.act_id != FLOW_ACTION_PIPE &&
172 a->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
173 NL_SET_ERR_MSG_MOD(extack,
174 "Offload not supported when conform action is not pipe or ok");
178 if (a->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
179 !flow_action_is_last_entry(action, a)) {
180 NL_SET_ERR_MSG_MOD(extack,
181 "Offload not supported when conform action is ok, but police action is not last");
185 if (a->police.peakrate_bytes_ps ||
186 a->police.avrate || a->police.overhead) {
187 NL_SET_ERR_MSG_MOD(extack,
188 "Offload not supported when peakrate/avrate/overhead is configured");
192 if (a->police.rate_pkt_ps) {
193 NL_SET_ERR_MSG_MOD(extack,
194 "Offload does not support packets per second");
200 EXPORT_SYMBOL(ocelot_policer_validate);
202 int ocelot_port_policer_add(struct ocelot *ocelot, int port,
203 struct ocelot_policer *pol)
205 struct qos_policer_conf pp = { 0 };
211 pp.mode = MSCC_QOS_RATE_MODE_DATA;
215 dev_dbg(ocelot->dev, "%s: port %u pir %u kbps, pbs %u bytes\n",
216 __func__, port, pp.pir, pp.pbs);
218 err = qos_policer_conf_set(ocelot, POL_IX_PORT + port, &pp);
222 ocelot_rmw_gix(ocelot,
223 ANA_PORT_POL_CFG_PORT_POL_ENA |
224 ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
225 ANA_PORT_POL_CFG_PORT_POL_ENA |
226 ANA_PORT_POL_CFG_POL_ORDER_M,
227 ANA_PORT_POL_CFG, port);
231 EXPORT_SYMBOL(ocelot_port_policer_add);
233 int ocelot_port_policer_del(struct ocelot *ocelot, int port)
235 struct qos_policer_conf pp = { 0 };
238 dev_dbg(ocelot->dev, "%s: port %u\n", __func__, port);
240 pp.mode = MSCC_QOS_RATE_MODE_DISABLED;
242 err = qos_policer_conf_set(ocelot, POL_IX_PORT + port, &pp);
246 ocelot_rmw_gix(ocelot,
247 ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER),
248 ANA_PORT_POL_CFG_PORT_POL_ENA |
249 ANA_PORT_POL_CFG_POL_ORDER_M,
250 ANA_PORT_POL_CFG, port);
254 EXPORT_SYMBOL(ocelot_port_policer_del);