1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
4 * Copyright (c) 2019 Microsemi Corporation
7 #include "ocelot_police.h"
9 enum mscc_qos_rate_mode
{
10 MSCC_QOS_RATE_MODE_DISABLED
, /* Policer/shaper disabled */
11 MSCC_QOS_RATE_MODE_LINE
, /* Measure line rate in kbps incl. IPG */
12 MSCC_QOS_RATE_MODE_DATA
, /* Measures data rate in kbps excl. IPG */
13 MSCC_QOS_RATE_MODE_FRAME
, /* Measures frame rate in fps */
14 __MSCC_QOS_RATE_MODE_END
,
15 NUM_MSCC_QOS_RATE_MODE
= __MSCC_QOS_RATE_MODE_END
,
16 MSCC_QOS_RATE_MODE_MAX
= __MSCC_QOS_RATE_MODE_END
- 1,
19 /* Types for ANA:POL[0-192]:POL_MODE_CFG.FRM_MODE */
20 #define POL_MODE_LINERATE 0 /* Incl IPG. Unit: 33 1/3 kbps, 4096 bytes */
21 #define POL_MODE_DATARATE 1 /* Excl IPG. Unit: 33 1/3 kbps, 4096 bytes */
22 #define POL_MODE_FRMRATE_HI 2 /* Unit: 33 1/3 fps, 32.8 frames */
23 #define POL_MODE_FRMRATE_LO 3 /* Unit: 1/3 fps, 0.3 frames */
26 #define POL_IX_PORT 0 /* 0-11 : Port policers */
27 #define POL_IX_QUEUE 32 /* 32-127 : Queue policers */
29 /* Default policer order */
30 #define POL_ORDER 0x1d3 /* Ocelot policer order: Serial (QoS -> Port -> VCAP) */
32 struct qos_policer_conf
{
33 enum mscc_qos_rate_mode mode
;
34 bool dlb
; /* Enable DLB (dual leaky bucket mode */
35 bool cf
; /* Coupling flag (ignored in SLB mode) */
36 u32 cir
; /* CIR in kbps/fps (ignored in SLB mode) */
37 u32 cbs
; /* CBS in bytes/frames (ignored in SLB mode) */
38 u32 pir
; /* PIR in kbps/fps */
39 u32 pbs
; /* PBS in bytes/frames */
40 u8 ipg
; /* Size of IPG when MSCC_QOS_RATE_MODE_LINE is chosen */
43 static int qos_policer_conf_set(struct ocelot
*ocelot
, int port
, u32 pol_ix
,
44 struct qos_policer_conf
*conf
)
46 u32 cf
= 0, cir_ena
= 0, frm_mode
= POL_MODE_LINERATE
;
47 u32 cir
= 0, cbs
= 0, pir
= 0, pbs
= 0;
48 bool cir_discard
= 0, pir_discard
= 0;
49 u32 pbs_max
= 0, cbs_max
= 0;
57 case MSCC_QOS_RATE_MODE_LINE
:
58 case MSCC_QOS_RATE_MODE_DATA
:
59 if (conf
->mode
== MSCC_QOS_RATE_MODE_LINE
) {
60 frm_mode
= POL_MODE_LINERATE
;
61 ipg
= min_t(u8
, GENMASK(4, 0), conf
->ipg
);
63 frm_mode
= POL_MODE_DATARATE
;
69 if (cir
== 0 && cbs
== 0) {
70 /* Discard cir frames */
73 cir
= DIV_ROUND_UP(cir
, 100);
74 cir
*= 3; /* 33 1/3 kbps */
75 cbs
= DIV_ROUND_UP(cbs
, 4096);
76 cbs
= (cbs
? cbs
: 1); /* No zero burst size */
77 cbs_max
= 60; /* Limit burst size */
83 if (pir
== 0 && pbs
== 0) {
84 /* Discard PIR frames */
87 pir
= DIV_ROUND_UP(pir
, 100);
88 pir
*= 3; /* 33 1/3 kbps */
89 pbs
= DIV_ROUND_UP(pbs
, 4096);
90 pbs
= (pbs
? pbs
: 1); /* No zero burst size */
91 pbs_max
= 60; /* Limit burst size */
94 case MSCC_QOS_RATE_MODE_FRAME
:
96 frm_mode
= POL_MODE_FRMRATE_HI
;
97 pir
= DIV_ROUND_UP(pir
, 100);
98 pir
*= 3; /* 33 1/3 fps */
99 pbs
= (pbs
* 10) / 328; /* 32.8 frames */
100 pbs
= (pbs
? pbs
: 1); /* No zero burst size */
101 pbs_max
= GENMASK(6, 0); /* Limit burst size */
103 frm_mode
= POL_MODE_FRMRATE_LO
;
104 if (pir
== 0 && pbs
== 0) {
105 /* Discard all frames */
109 pir
*= 3; /* 1/3 fps */
110 pbs
= (pbs
* 10) / 3; /* 0.3 frames */
111 pbs
= (pbs
? pbs
: 1); /* No zero burst size */
112 pbs_max
= 61; /* Limit burst size */
116 default: /* MSCC_QOS_RATE_MODE_DISABLED */
117 /* Disable policer using maximum rate and zero burst */
118 pir
= GENMASK(15, 0);
124 if (pir
> GENMASK(15, 0)) {
125 dev_err(ocelot
->dev
, "Invalid pir for port %d: %u (max %lu)\n",
126 port
, pir
, GENMASK(15, 0));
130 if (cir
> GENMASK(15, 0)) {
131 dev_err(ocelot
->dev
, "Invalid cir for port %d: %u (max %lu)\n",
132 port
, cir
, GENMASK(15, 0));
137 dev_err(ocelot
->dev
, "Invalid pbs for port %d: %u (max %u)\n",
143 dev_err(ocelot
->dev
, "Invalid cbs for port %d: %u (max %u)\n",
148 value
= (ANA_POL_MODE_CFG_IPG_SIZE(ipg
) |
149 ANA_POL_MODE_CFG_FRM_MODE(frm_mode
) |
150 (cf
? ANA_POL_MODE_CFG_DLB_COUPLED
: 0) |
151 (cir_ena
? ANA_POL_MODE_CFG_CIR_ENA
: 0) |
152 ANA_POL_MODE_CFG_OVERSHOOT_ENA
);
154 ocelot_write_gix(ocelot
, value
, ANA_POL_MODE_CFG
, pol_ix
);
156 ocelot_write_gix(ocelot
,
157 ANA_POL_PIR_CFG_PIR_RATE(pir
) |
158 ANA_POL_PIR_CFG_PIR_BURST(pbs
),
159 ANA_POL_PIR_CFG
, pol_ix
);
161 ocelot_write_gix(ocelot
,
162 (pir_discard
? GENMASK(22, 0) : 0),
163 ANA_POL_PIR_STATE
, pol_ix
);
165 ocelot_write_gix(ocelot
,
166 ANA_POL_CIR_CFG_CIR_RATE(cir
) |
167 ANA_POL_CIR_CFG_CIR_BURST(cbs
),
168 ANA_POL_CIR_CFG
, pol_ix
);
170 ocelot_write_gix(ocelot
,
171 (cir_discard
? GENMASK(22, 0) : 0),
172 ANA_POL_CIR_STATE
, pol_ix
);
177 int ocelot_port_policer_add(struct ocelot
*ocelot
, int port
,
178 struct ocelot_policer
*pol
)
180 struct qos_policer_conf pp
= { 0 };
186 pp
.mode
= MSCC_QOS_RATE_MODE_DATA
;
190 dev_dbg(ocelot
->dev
, "%s: port %u pir %u kbps, pbs %u bytes\n",
191 __func__
, port
, pp
.pir
, pp
.pbs
);
193 err
= qos_policer_conf_set(ocelot
, port
, POL_IX_PORT
+ port
, &pp
);
197 ocelot_rmw_gix(ocelot
,
198 ANA_PORT_POL_CFG_PORT_POL_ENA
|
199 ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER
),
200 ANA_PORT_POL_CFG_PORT_POL_ENA
|
201 ANA_PORT_POL_CFG_POL_ORDER_M
,
202 ANA_PORT_POL_CFG
, port
);
207 int ocelot_port_policer_del(struct ocelot
*ocelot
, int port
)
209 struct qos_policer_conf pp
= { 0 };
212 dev_dbg(ocelot
->dev
, "%s: port %u\n", __func__
, port
);
214 pp
.mode
= MSCC_QOS_RATE_MODE_DISABLED
;
216 err
= qos_policer_conf_set(ocelot
, port
, POL_IX_PORT
+ port
, &pp
);
220 ocelot_rmw_gix(ocelot
,
221 ANA_PORT_POL_CFG_POL_ORDER(POL_ORDER
),
222 ANA_PORT_POL_CFG_PORT_POL_ENA
|
223 ANA_PORT_POL_CFG_POL_ORDER_M
,
224 ANA_PORT_POL_CFG
, port
);