blob: 74a6eb23d0a07b44bad44798cc26ef2c3d232ea4 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15#include <string.h>
16#include <stddef.h>
17#include <stdio.h>
18#include <assert.h>
19#include <math.h>
Damjan Marione936bbe2016-02-25 23:17:38 +010020#include <stdint.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070021
22#include <vlib/vlib.h>
23#include <vnet/vnet.h>
24
25#include <vnet/policer/xlate.h>
26#include <vnet/policer/police.h>
27
28#define INTERNAL_SS 1
29
30/* debugs */
31#define SSE2_QOS_DEBUG_ERROR(msg, args...) \
32 fformat(stderr, msg "\n", ##args);
33
34#define SSE2_QOS_DEBUG_INFO(msg, args...) \
35 fformat(stderr, msg "\n", ##args);
36
37
38#define SSE2_QOS_TR_ERR(TpParms...)
39// {
40// }
41
42#define SSE2_QOS_TR_INFO(TpParms...)
43
44#ifndef MIN
45#define MIN(x,y) (((x)<(y))?(x):(y))
46#endif
47
48#ifndef MAX
49#define MAX(x,y) (((x)>(y))?(x):(y))
50#endif
51
52#define IPE_POLICER_FULL_WRITE_REQUEST_M40AH_OFFSET 0
53#define IPE_POLICER_FULL_WRITE_REQUEST_M40AH_MASK 8
54#define IPE_POLICER_FULL_WRITE_REQUEST_M40AH_SHIFT 24
55
56#define IPE_POLICER_FULL_WRITE_REQUEST_TYPE_OFFSET 2
57#define IPE_POLICER_FULL_WRITE_REQUEST_TYPE_MASK 2
58#define IPE_POLICER_FULL_WRITE_REQUEST_TYPE_SHIFT 10
59
60#define IPE_POLICER_FULL_WRITE_REQUEST_CMD_OFFSET 3
61#define IPE_POLICER_FULL_WRITE_REQUEST_CMD_MASK 2
62#define IPE_POLICER_FULL_WRITE_REQUEST_CMD_SHIFT 0
63
64#define IPE_POLICER_FULL_WRITE_REQUEST_M40AL_OFFSET 4
65#define IPE_POLICER_FULL_WRITE_REQUEST_M40AL_MASK 32
66#define IPE_POLICER_FULL_WRITE_REQUEST_M40AL_SHIFT 0
67
68#define IPE_POLICER_FULL_WRITE_REQUEST_RFC_OFFSET 8
69#define IPE_POLICER_FULL_WRITE_REQUEST_RFC_MASK 2
70#define IPE_POLICER_FULL_WRITE_REQUEST_RFC_SHIFT 30
71
72#define IPE_POLICER_FULL_WRITE_REQUEST_AN_OFFSET 8
73#define IPE_POLICER_FULL_WRITE_REQUEST_AN_MASK 1
74#define IPE_POLICER_FULL_WRITE_REQUEST_AN_SHIFT 29
75
76#define IPE_POLICER_FULL_WRITE_REQUEST_REXP_OFFSET 8
77#define IPE_POLICER_FULL_WRITE_REQUEST_REXP_MASK 4
78#define IPE_POLICER_FULL_WRITE_REQUEST_REXP_SHIFT 22
79
80#define IPE_POLICER_FULL_WRITE_REQUEST_ARM_OFFSET 9
81#define IPE_POLICER_FULL_WRITE_REQUEST_ARM_MASK 11
82#define IPE_POLICER_FULL_WRITE_REQUEST_ARM_SHIFT 11
83
84#define IPE_POLICER_FULL_WRITE_REQUEST_PRM_OFFSET 10
85#define IPE_POLICER_FULL_WRITE_REQUEST_PRM_MASK 11
86#define IPE_POLICER_FULL_WRITE_REQUEST_PRM_SHIFT 0
87
88#define IPE_POLICER_FULL_WRITE_REQUEST_CBLE_OFFSET 12
89#define IPE_POLICER_FULL_WRITE_REQUEST_CBLE_MASK 5
90#define IPE_POLICER_FULL_WRITE_REQUEST_CBLE_SHIFT 27
91
92#define IPE_POLICER_FULL_WRITE_REQUEST_CBLM_OFFSET 12
93#define IPE_POLICER_FULL_WRITE_REQUEST_CBLM_MASK 7
94#define IPE_POLICER_FULL_WRITE_REQUEST_CBLM_SHIFT 20
95
96#define IPE_POLICER_FULL_WRITE_REQUEST_EBLE_OFFSET 13
97#define IPE_POLICER_FULL_WRITE_REQUEST_EBLE_MASK 5
98#define IPE_POLICER_FULL_WRITE_REQUEST_EBLE_SHIFT 15
99
100#define IPE_POLICER_FULL_WRITE_REQUEST_EBLM_OFFSET 14
101#define IPE_POLICER_FULL_WRITE_REQUEST_EBLM_MASK 7
102#define IPE_POLICER_FULL_WRITE_REQUEST_EBLM_SHIFT 8
103
104#define IPE_POLICER_FULL_WRITE_REQUEST_CB_OFFSET 16
105#define IPE_POLICER_FULL_WRITE_REQUEST_CB_MASK 31
106#define IPE_POLICER_FULL_WRITE_REQUEST_CB_SHIFT 0
107
108#define IPE_POLICER_FULL_WRITE_REQUEST_EB_OFFSET 20
109#define IPE_POLICER_FULL_WRITE_REQUEST_EB_MASK 31
110#define IPE_POLICER_FULL_WRITE_REQUEST_EB_SHIFT 0
111
112#define IPE_RFC_RFC2697 0x00000000
113#define IPE_RFC_RFC2698 0x00000001
114#define IPE_RFC_RFC4115 0x00000002
115#define IPE_RFC_MEF5CF1 0x00000003
116
117/* End of constants copied from sse_ipe_desc_fmt.h */
118
119/* Misc Policer specific definitions */
120#define SSE2_QOS_POLICER_FIXED_PKT_SIZE 256
121
122// TODO check what can be provided by hw macro based on ASIC
Damjan Marion3891cd82016-10-27 10:27:00 +0200123#define SSE2_QOS_POL_TICKS_PER_SEC 1000LL /* 1 tick = 1 ms */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124
125/*
126 * Default burst, in ms (byte format)
127 */
128#define SSE2_QOS_POL_DEF_BURST_BYTE 100
129
130/*
131 * Minimum burst needs to be such that the largest packet size is accomodated
132 */
133// Do we need to get it from some lib?
134#define SSE2_QOS_POL_MIN_BURST_BYTE 9*1024
135
136
137/*
138 * Flag to indicate if AN is employed or not
139 * 1 - TRUE, 0 - FALSE
140 */
141#define SSE2_QOS_POL_ALLOW_NEGATIVE 1
142
143// Various Macros to take care of policer calculations
144
145#define SSE2_QOS_POL_COMM_BKT_MAX \
146 (1<<IPE_POLICER_FULL_WRITE_REQUEST_CB_MASK)
147#define SSE2_QOS_POL_EXTD_BKT_MAX \
148 (1<<IPE_POLICER_FULL_WRITE_REQUEST_EB_MASK)
149
150#define SSE2_QOS_POL_RATE_EXP_SIZE \
151 (IPE_POLICER_FULL_WRITE_REQUEST_REXP_MASK)
152#define SSE2_QOS_POL_RATE_EXP_MAX ((1<<SSE2_QOS_POL_RATE_EXP_SIZE) - 1)
153#define SSE2_QOS_POL_AVG_RATE_MANT_SIZE \
154 (IPE_POLICER_FULL_WRITE_REQUEST_ARM_MASK)
155#define SSE2_QOS_POL_AVG_RATE_MANT_MAX \
Damjan Marion3891cd82016-10-27 10:27:00 +0200156 ((1<< SSE2_QOS_POL_AVG_RATE_MANT_SIZE) - 1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700157#define SSE2_QOS_POL_AVG_RATE_MAX \
158 (SSE2_QOS_POL_AVG_RATE_MANT_MAX << \
159 SSE2_QOS_POL_RATE_EXP_MAX)
160
161#define SSE2_QOS_POL_PEAK_RATE_MANT_SIZE \
162 (IPE_POLICER_FULL_WRITE_REQUEST_PRM_MASK)
163#define SSE2_QOS_POL_PEAK_RATE_MANT_MAX \
Damjan Marion3891cd82016-10-27 10:27:00 +0200164 ((1<<SSE2_QOS_POL_PEAK_RATE_MANT_SIZE) - 1)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700165#define SSE2_QOS_POL_PEAK_RATE_MAX \
166 (SSE2_QOS_POL_PEAK_RATE_MANT_MAX << \
167 SSE2_QOS_POL_RATE_EXP_MAX)
168
169#define SSE2_QOS_POL_COMM_BKT_LIMIT_MANT_SIZE \
170 (IPE_POLICER_FULL_WRITE_REQUEST_CBLM_MASK)
171#define SSE2_QOS_POL_COMM_BKT_LIMIT_MANT_MAX \
172 ((1<<SSE2_QOS_POL_COMM_BKT_LIMIT_MANT_SIZE) - 1)
173#define SSE2_QOS_POL_COMM_BKT_LIMIT_EXP_SIZE \
174 (IPE_POLICER_FULL_WRITE_REQUEST_CBLE_MASK)
175#define SSE2_QOS_POL_COMM_BKT_LIMIT_EXP_MAX \
176 ((1<<SSE2_QOS_POL_COMM_BKT_LIMIT_EXP_SIZE) - 1)
177#define SSE2_QOS_POL_COMM_BKT_LIMIT_MAX \
Damjan Marion3891cd82016-10-27 10:27:00 +0200178 ((u64)SSE2_QOS_POL_COMM_BKT_LIMIT_MANT_MAX << \
179 (u64)SSE2_QOS_POL_COMM_BKT_LIMIT_EXP_MAX)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700180
181#define SSE2_QOS_POL_EXTD_BKT_LIMIT_MANT_SIZE \
182 (IPE_POLICER_FULL_WRITE_REQUEST_EBLM_MASK)
183#define SSE2_QOS_POL_EXTD_BKT_LIMIT_MANT_MAX \
184 ((1<<SSE2_QOS_POL_EXTD_BKT_LIMIT_MANT_SIZE) - 1)
185#define SSE2_QOS_POL_EXTD_BKT_LIMIT_EXP_SIZE \
186 (IPE_POLICER_FULL_WRITE_REQUEST_EBLE_MASK)
187#define SSE2_QOS_POL_EXTD_BKT_LIMIT_EXP_MAX \
188 ((1<<SSE2_QOS_POL_EXTD_BKT_LIMIT_EXP_SIZE) - 1)
189#define SSE2_QOS_POL_EXT_BKT_LIMIT_MAX \
Damjan Marion3891cd82016-10-27 10:27:00 +0200190 ((u64)SSE2_QOS_POL_EXTD_BKT_LIMIT_MANT_MAX << \
191 (u64)SSE2_QOS_POL_EXTD_BKT_LIMIT_EXP_MAX)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192
193/*
194 * Rates determine the units of the bucket
195 * 256.114688 Gbps < Rate 8 byte units
196 * 128.057344 Gbps < Rate <= 256.114688 Gbps 4 byte units
197 * 64.028672 Gbps < Rate <= 128.057344 Gbps 2 byte units
198 * Rate <= 64.028672 Gbps 1 byte units
199 *
200 * The code uses bytes per tick as oppose to Gigabits per second.
201 */
202#define RATE256 (256114688000LL / 8LL / SSE2_QOS_POL_TICKS_PER_SEC)
203#define RATE128 (128057344000LL / 8LL / SSE2_QOS_POL_TICKS_PER_SEC)
204#define RATE64 ( 64028672000LL / 8LL / SSE2_QOS_POL_TICKS_PER_SEC)
205
206#define RATE_OVER256_UNIT 8LL
207#define RATE_128TO256_UNIT 4LL
208#define RATE_64TO128_UNIT 2LL
209
Damjan Marion3891cd82016-10-27 10:27:00 +0200210static int
211sse2_qos_pol_round (u64 numerator,
212 u64 denominator,
213 u64 * rounded_value, sse2_qos_round_type_en round_type)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700214{
Damjan Marion3891cd82016-10-27 10:27:00 +0200215 int rc = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216
Damjan Marion3891cd82016-10-27 10:27:00 +0200217 if (denominator == 0)
218 {
219 SSE2_QOS_DEBUG_ERROR ("Illegal denominator");
220 SSE2_QOS_TR_ERR (SSE2_QOSRM_TP_ERR_59);
221 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222 }
223
Damjan Marion3891cd82016-10-27 10:27:00 +0200224 switch (round_type)
225 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700226 case SSE2_QOS_ROUND_TO_CLOSEST:
Damjan Marion3891cd82016-10-27 10:27:00 +0200227 *rounded_value = ((numerator + (denominator >> 1)) / denominator);
228 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229
230 case SSE2_QOS_ROUND_TO_UP:
Damjan Marion3891cd82016-10-27 10:27:00 +0200231 *rounded_value = (numerator / denominator);
232 if ((*rounded_value * denominator) < numerator)
233 {
234 *rounded_value += 1;
235 }
236 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700237
238 case SSE2_QOS_ROUND_TO_DOWN:
Damjan Marion3891cd82016-10-27 10:27:00 +0200239 *rounded_value = (numerator / denominator);
240 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
242 case SSE2_QOS_ROUND_INVALID:
243 default:
Damjan Marion3891cd82016-10-27 10:27:00 +0200244 SSE2_QOS_DEBUG_ERROR ("Illegal round type");
245 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_60, round_type);
246 rc = EINVAL;
247 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200249 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700250}
251
252
Damjan Marion3891cd82016-10-27 10:27:00 +0200253static int
254sse2_pol_validate_cfg_params (sse2_qos_pol_cfg_params_st * cfg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700255{
Damjan Marion3891cd82016-10-27 10:27:00 +0200256 u64 numer, denom, rnd_value;
257 u32 cir_hw, eir_hw;
258 int rc = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259
Damjan Marion3891cd82016-10-27 10:27:00 +0200260 if ((cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698) &&
261 (cfg->rb.kbps.eir_kbps < cfg->rb.kbps.cir_kbps))
262 {
263 SSE2_QOS_DEBUG_ERROR ("CIR (%u kbps) is greater than PIR (%u kbps)",
264 cfg->rb.kbps.cir_kbps, cfg->rb.kbps.eir_kbps);
265 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_39, cfg->rb.kbps.cir_kbps,
266 cfg->rb.kbps.eir_kbps);
267 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700268 }
269
Damjan Marion3891cd82016-10-27 10:27:00 +0200270 /*
271 * convert rates to bytes-per-tick
272 */
273 numer = (u64) (cfg->rb.kbps.cir_kbps);
274 denom = (u64) (8 * SSE2_QOS_POL_TICKS_PER_SEC) / 1000;
275 rc = sse2_qos_pol_round (numer, denom, &rnd_value,
276 (sse2_qos_round_type_en) cfg->rnd_type);
277 if (rc != 0)
278 {
279 SSE2_QOS_DEBUG_ERROR ("Unable to convert CIR to bytes/tick format");
280 // Error traced
281 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200283 cir_hw = (u32) rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700284
Damjan Marion3891cd82016-10-27 10:27:00 +0200285 numer = (u64) (cfg->rb.kbps.eir_kbps);
286 rc = sse2_qos_pol_round (numer, denom, &rnd_value,
287 (sse2_qos_round_type_en) cfg->rnd_type);
288 if (rc != 0)
289 {
290 SSE2_QOS_DEBUG_ERROR ("Unable to convert EIR to bytes/tick format");
291 // Error traced
292 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700293 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200294 eir_hw = (u32) rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700295
Damjan Marion3891cd82016-10-27 10:27:00 +0200296 if (cir_hw > SSE2_QOS_POL_AVG_RATE_MAX)
297 {
298 SSE2_QOS_DEBUG_ERROR ("hw cir (%u bytes/tick) is greater than the "
299 "max supported value (%u)", cir_hw,
300 SSE2_QOS_POL_AVG_RATE_MAX);
301 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_84, cir_hw, SSE2_QOS_POL_AVG_RATE_MAX);
302 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700303 }
304
Damjan Marion3891cd82016-10-27 10:27:00 +0200305 if (eir_hw > SSE2_QOS_POL_PEAK_RATE_MAX)
306 {
307 SSE2_QOS_DEBUG_ERROR ("hw eir (%u bytes/tick) is greater than the "
308 "max supported value (%u). Capping it to the max. "
309 "supported value", eir_hw,
310 SSE2_QOS_POL_PEAK_RATE_MAX);
311 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_85, eir_hw,
312 SSE2_QOS_POL_PEAK_RATE_MAX);
313 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700314 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200315 /*
316 * CIR = 0, with bc != 0 is not allowed
317 */
318 if ((cfg->rb.kbps.cir_kbps == 0) && cfg->rb.kbps.cb_bytes)
319 {
320 SSE2_QOS_DEBUG_ERROR ("CIR = 0 with bc != 0");
321 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_55);
322 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700323 }
324
Damjan Marion3891cd82016-10-27 10:27:00 +0200325 if ((cfg->rb.kbps.eir_kbps == 0) &&
326 (cfg->rfc > SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697))
327 {
328 SSE2_QOS_DEBUG_ERROR ("EIR = 0 for a 2R3C policer (rfc: %u)", cfg->rfc);
329 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_23, cfg->rb.kbps.eir_kbps, cfg->rfc);
330 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331 }
332
Damjan Marion3891cd82016-10-27 10:27:00 +0200333 if (cfg->rb.kbps.eir_kbps &&
334 (cfg->rfc < SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698))
335 {
336 SSE2_QOS_DEBUG_ERROR ("EIR: %u kbps for a 1-rate policer (rfc: %u)",
337 cfg->rb.kbps.eir_kbps, cfg->rfc);
338 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_23, cfg->rb.kbps.eir_kbps, cfg->rfc);
339 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340 }
341
Damjan Marion3891cd82016-10-27 10:27:00 +0200342 if ((cfg->rfc == SSE2_QOS_POLICER_TYPE_1R2C) && cfg->rb.kbps.eb_bytes)
343 {
344 SSE2_QOS_DEBUG_ERROR ("For a 1R1B policer, EB burst cannot be > 0");
345 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_56);
346 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700347 }
348
Damjan Marion3891cd82016-10-27 10:27:00 +0200349 return (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350}
351
352static void
Damjan Marion3891cd82016-10-27 10:27:00 +0200353sse2_qos_convert_value_to_exp_mant_fmt (u64 value,
354 u16 max_exp_value,
355 u16 max_mant_value,
356 sse2_qos_round_type_en type,
357 u8 * exp, u32 * mant)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358{
Damjan Marion3891cd82016-10-27 10:27:00 +0200359 u64 rnd_value;
360 u64 temp_mant;
361 u8 temp_exp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700362
Damjan Marion3891cd82016-10-27 10:27:00 +0200363 /*
364 * Select the lowest possible exp, and the largest possible mant
365 */
366 temp_exp = 0;
367 temp_mant = value;
368 while (temp_exp <= max_exp_value)
369 {
370 if (temp_mant <= max_mant_value)
371 {
372 break;
373 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700374
Damjan Marion3891cd82016-10-27 10:27:00 +0200375 temp_exp++;
376 rnd_value = 0;
377 (void) sse2_qos_pol_round ((u64) value, (u64) (1 << temp_exp),
378 &rnd_value, type);
379 temp_mant = rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380 }
381
Damjan Marion3891cd82016-10-27 10:27:00 +0200382 if (temp_exp > max_exp_value)
383 {
384 /*
385 * CAP mant to its max value, and decrement exp
386 */
387 temp_exp--;
388 temp_mant = max_mant_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389 }
390
Damjan Marion3891cd82016-10-27 10:27:00 +0200391 *exp = temp_exp;
392 *mant = (u32) temp_mant;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393
Damjan Marion3891cd82016-10-27 10:27:00 +0200394 SSE2_QOS_DEBUG_INFO ("value: 0x%llx, mant: %u, exp: %u", value, *mant,
395 *exp);
396 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397}
398
Damjan Marion3891cd82016-10-27 10:27:00 +0200399static int
400sse2_pol_convert_cfg_rates_to_hw (sse2_qos_pol_cfg_params_st * cfg,
401 sse2_qos_pol_hw_params_st * hw)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402{
Damjan Marion3891cd82016-10-27 10:27:00 +0200403 int rc = 0;
404 u32 cir_hw, eir_hw, hi_mant, hi_rate, cir_rnded, eir_rnded, eir_kbps;
405 u64 numer, denom, rnd_value;
406 u8 exp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700407
Damjan Marion3891cd82016-10-27 10:27:00 +0200408 /*
409 * convert rates to bytes-per-tick (tick is 1ms)
410 * For rate conversion, the denominator is gonna be the same
411 */
412 denom = (u64) ((SSE2_QOS_POL_TICKS_PER_SEC * 8) / 1000);
413 numer = (u64) (cfg->rb.kbps.cir_kbps);
414 rc = sse2_qos_pol_round (numer, denom, &rnd_value,
415 (sse2_qos_round_type_en) cfg->rnd_type);
416 if (rc != 0)
417 {
418 SSE2_QOS_DEBUG_ERROR
419 ("Rounding error, rate: %d kbps, rounding_type: %d",
420 cfg->rb.kbps.cir_kbps, cfg->rnd_type);
421 // Error is traced
422 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700423 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200424 cir_hw = (u32) rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700425
Damjan Marion3891cd82016-10-27 10:27:00 +0200426 if (cfg->rb.kbps.cir_kbps && (cir_hw == 0))
427 {
428 /*
429 * After rounding, cir_hw = 0. Bump it up
430 */
431 cir_hw = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432 }
433
Damjan Marion3891cd82016-10-27 10:27:00 +0200434 if (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R2C)
435 {
436 eir_kbps = 0;
437 }
438 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
439 {
440 eir_kbps = cfg->rb.kbps.cir_kbps;
441 }
442 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
443 {
444 eir_kbps = cfg->rb.kbps.eir_kbps - cfg->rb.kbps.cir_kbps;
445 }
446 else
447 {
448 eir_kbps = cfg->rb.kbps.eir_kbps;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449 }
450
Damjan Marion3891cd82016-10-27 10:27:00 +0200451 numer = (u64) eir_kbps;
452 rc = sse2_qos_pol_round (numer, denom, &rnd_value,
453 (sse2_qos_round_type_en) cfg->rnd_type);
454 if (rc != 0)
455 {
456 SSE2_QOS_DEBUG_ERROR
457 ("Rounding error, rate: %d kbps, rounding_type: %d", eir_kbps,
458 cfg->rnd_type);
459 // Error is traced
460 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700461 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200462 eir_hw = (u32) rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463
Damjan Marion3891cd82016-10-27 10:27:00 +0200464 if (eir_kbps && (eir_hw == 0))
465 {
466 /*
467 * After rounding, eir_hw = 0. Bump it up
468 */
469 eir_hw = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700470 }
471
Damjan Marion3891cd82016-10-27 10:27:00 +0200472 SSE2_QOS_DEBUG_INFO ("cir_hw: %u bytes/tick, eir_hw: %u bytes/tick", cir_hw,
473 eir_hw);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700474
Damjan Marion3891cd82016-10-27 10:27:00 +0200475 if (cir_hw > eir_hw)
476 {
477 hi_rate = cir_hw;
478 }
479 else
480 {
481 hi_rate = eir_hw;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700482 }
483
Damjan Marion3891cd82016-10-27 10:27:00 +0200484 if ((cir_hw == 0) && (eir_hw == 0))
485 {
486 /*
487 * Both the rates are 0. Use exp = 15, and set the RFC to 4115. Also
488 * set AN = 0
489 */
490 exp = (u8) SSE2_QOS_POL_RATE_EXP_MAX;
491 hi_mant = 0;
492 hw->rfc = IPE_RFC_RFC4115;
493 hw->allow_negative = 0;
494 }
495 else
496 {
497 sse2_qos_convert_value_to_exp_mant_fmt (hi_rate,
498 (u16) SSE2_QOS_POL_RATE_EXP_MAX,
499 (u16)
500 SSE2_QOS_POL_AVG_RATE_MANT_MAX,
501 (sse2_qos_round_type_en)
502 cfg->rnd_type, &exp, &hi_mant);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700503 }
504
Damjan Marion3891cd82016-10-27 10:27:00 +0200505 denom = (1ULL << exp);
506 if (hi_rate == eir_hw)
507 {
508 hw->peak_rate_man = (u16) hi_mant;
509 rc = sse2_qos_pol_round ((u64) cir_hw, denom, &rnd_value,
510 (sse2_qos_round_type_en) cfg->rnd_type);
511 hw->avg_rate_man = (u16) rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700512 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200513 else
514 {
515 hw->avg_rate_man = (u16) hi_mant;
516 rc = sse2_qos_pol_round ((u64) eir_hw, denom, &rnd_value,
517 (sse2_qos_round_type_en) cfg->rnd_type);
518 hw->peak_rate_man = (u16) rnd_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700519 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200520 if (rc != 0)
521 {
522 SSE2_QOS_DEBUG_ERROR ("Rounding error");
523 // Error is traced
524 return (rc);
525 }
526 hw->rate_exp = exp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700527
Damjan Marion3891cd82016-10-27 10:27:00 +0200528 if ((hw->avg_rate_man == 0) && (cfg->rb.kbps.cir_kbps))
529 {
530 /*
531 * cir was reduced to 0 during rounding. Bump it up
532 */
533 hw->avg_rate_man = 1;
534 SSE2_QOS_DEBUG_INFO ("CIR = 0 during rounding. Bump it up to %u "
535 "bytes/tick", (hw->avg_rate_man << hw->rate_exp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700536 }
537
Damjan Marion3891cd82016-10-27 10:27:00 +0200538 if ((hw->peak_rate_man == 0) && eir_kbps)
539 {
540 /*
541 * eir was reduced to 0 during rounding. Bump it up
542 */
543 hw->peak_rate_man = 1;
544 SSE2_QOS_DEBUG_INFO ("EIR = 0 during rounding. Bump it up to %u "
545 "bytes/tick", (hw->peak_rate_man << hw->rate_exp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700546 }
547
Damjan Marion3891cd82016-10-27 10:27:00 +0200548 cir_rnded = (hw->avg_rate_man << hw->rate_exp);
549 eir_rnded = (hw->peak_rate_man << hw->rate_exp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700550
Damjan Marion3891cd82016-10-27 10:27:00 +0200551 SSE2_QOS_DEBUG_INFO ("Configured(rounded) values, cir: %u "
552 "kbps (mant: %u, exp: %u, rate: %u bytes/tick)",
553 cfg->rb.kbps.cir_kbps, hw->avg_rate_man,
554 hw->rate_exp, cir_rnded);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700555
Damjan Marion3891cd82016-10-27 10:27:00 +0200556 SSE2_QOS_DEBUG_INFO ("Configured(rounded) values, eir: %u "
557 "kbps (mant: %u, exp: %u, rate: %u bytes/tick)",
558 cfg->rb.kbps.eir_kbps, hw->peak_rate_man,
559 hw->rate_exp, eir_rnded);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560
Damjan Marion3891cd82016-10-27 10:27:00 +0200561 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700562}
563
564/*****
565 * NAME
566 * sse2_pol_get_bkt_max
567 *
568 * PARAMETERS
569 * rate_hw - either the averate rate or peak rate
570 * bkt_max - bit width in the current bucket or extended bucket
571 *
572 * RETURNS
Damjan Marion3891cd82016-10-27 10:27:00 +0200573 * u64 - maximum token bytes for the current or extended bucket
Ed Warnickecb9cada2015-12-08 15:45:58 -0700574 *
575 * DESCRIPTION
576 * The current bucket or extended bucket fields are in units of either
577 * 1,2,4,8 bytes based on the average or peak rate respective to current
578 * or extended bucket.
579 *
580 * To get the actual maximum number of bytes that can be stored in the
581 * field, the value must be multiplied by the units of either 1,2,4,8
582 * bytes based on the rate.
583 *****/
Damjan Marion3891cd82016-10-27 10:27:00 +0200584u64
585sse2_pol_get_bkt_max (u64 rate_hw, u64 bkt_max)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700586{
Damjan Marion3891cd82016-10-27 10:27:00 +0200587 if (rate_hw <= RATE64)
588 {
589 return (bkt_max - 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700590 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200591 else if (rate_hw <= RATE128)
592 {
593 return ((bkt_max * RATE_64TO128_UNIT) - RATE_64TO128_UNIT);
594 }
595 else if (rate_hw <= RATE256)
596 {
597 return ((bkt_max * RATE_128TO256_UNIT) - RATE_128TO256_UNIT);
598 }
599 /* rate must be over 256 */
600 return ((bkt_max * RATE_OVER256_UNIT) - RATE_OVER256_UNIT);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601}
602
603/*****
604 * NAME
605 * sse2_pol_get_bkt_value
606 *
607 * PARAMETERS
608 * rate_hw - either the averate rate or peak rate
609 * byte_value - bytes for this token bucket
610 *
611 * RETURNS
Damjan Marion3891cd82016-10-27 10:27:00 +0200612 * u64 - unit value for the current or extended bucket field
Ed Warnickecb9cada2015-12-08 15:45:58 -0700613 *
614 * DESCRIPTION
615 * The current bucket or extended bucket fields are in units of either
616 * 1,2,4,8 bytes based on the average or peak rate respective to current
617 * or extended bucket.
618 *
619 * To get the units that can be stored in the field, the byte value must
620 * be divided by the units of either 1,2,4,8 bytes based on the rate.
621 *****/
Damjan Marion3891cd82016-10-27 10:27:00 +0200622u64
623sse2_pol_get_bkt_value (u64 rate_hw, u64 byte_value)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700624{
Damjan Marion3891cd82016-10-27 10:27:00 +0200625 if (rate_hw <= RATE64)
626 {
627 return (byte_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700628 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200629 else if (rate_hw <= RATE128)
630 {
631 return (byte_value / RATE_64TO128_UNIT);
632 }
633 else if (rate_hw <= RATE256)
634 {
635 return (byte_value / RATE_128TO256_UNIT);
636 }
637 /* rate must be over 256 */
638 return (byte_value / RATE_OVER256_UNIT);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639}
640
641static void
Damjan Marion3891cd82016-10-27 10:27:00 +0200642sse2_pol_rnd_burst_byte_fmt (u64 cfg_burst,
643 u16 max_exp_value,
644 u16 max_mant_value,
645 u32 max_bkt_value,
646 u32 rate_hw,
647 u8 * exp, u32 * mant, u32 * bkt_value)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700648{
Damjan Marion3891cd82016-10-27 10:27:00 +0200649 u64 bkt_max = max_bkt_value;
650 u64 bkt_limit_max;
651 u64 rnd_burst;
652 u64 temp_bkt_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653
Damjan Marion3891cd82016-10-27 10:27:00 +0200654 bkt_limit_max = ((u64) max_mant_value << (u64) max_exp_value);
655 bkt_max = sse2_pol_get_bkt_max (rate_hw, bkt_max);
656 bkt_max = MIN (bkt_max, bkt_limit_max);
657 if (!cfg_burst)
658 {
659 /*
660 * If configured burst = 0, compute the burst to be 100ms at a given
661 * rate. Note that for rate_hw = 0, exp = mant = 0.
662 */
663 cfg_burst = (u64) rate_hw *(u64) SSE2_QOS_POL_DEF_BURST_BYTE;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700664 }
665
Damjan Marion3891cd82016-10-27 10:27:00 +0200666 if (cfg_burst > bkt_max)
667 {
668 SSE2_QOS_DEBUG_ERROR ("burst 0x%llx bytes is greater than the max. "
669 "supported value 0x%llx bytes. Capping it to the "
670 "max", cfg_burst, bkt_max);
671 SSE2_QOS_TR_INFO (SSE2_QOS_TP_INFO_38,
672 (uint) cfg_burst, (uint) bkt_max);
673 cfg_burst = bkt_max;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674 }
675
Damjan Marion3891cd82016-10-27 10:27:00 +0200676 if (cfg_burst < SSE2_QOS_POL_MIN_BURST_BYTE)
677 {
678 /*
679 * Bump up the burst value ONLY if the cfg_burst is non-zero AND
680 * less than the min. supported value
681 */
682 SSE2_QOS_DEBUG_INFO ("burst 0x%llx bytes is less than the min "
683 "supported value %u bytes. Rounding it up to "
684 "the min", cfg_burst, SSE2_QOS_POL_MIN_BURST_BYTE);
685 SSE2_QOS_TR_INFO (SSE2_QOS_TP_INFO_39, (uint) cfg_burst,
686 SSE2_QOS_POL_MIN_BURST_BYTE);
687 cfg_burst = SSE2_QOS_POL_MIN_BURST_BYTE;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700688 }
689
Damjan Marion3891cd82016-10-27 10:27:00 +0200690 sse2_qos_convert_value_to_exp_mant_fmt (cfg_burst,
691 max_exp_value,
692 max_mant_value,
693 SSE2_QOS_ROUND_TO_DOWN, exp, mant);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694
Damjan Marion3891cd82016-10-27 10:27:00 +0200695 /* Bucket value is based on rate. */
696 rnd_burst = ((u64) (*mant) << (u64) (*exp));
697 temp_bkt_value = sse2_pol_get_bkt_value (rate_hw, rnd_burst);
698 *bkt_value = (u32) temp_bkt_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700699}
700
Damjan Marion3891cd82016-10-27 10:27:00 +0200701static int
702sse2_pol_convert_cfg_burst_to_hw (sse2_qos_pol_cfg_params_st * cfg,
703 sse2_qos_pol_hw_params_st * hw)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700704{
Damjan Marion3891cd82016-10-27 10:27:00 +0200705 u8 temp_exp;
706 u32 temp_mant, rate_hw;
707 u64 eb_bytes;
708 u32 bkt_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700709
Damjan Marion3891cd82016-10-27 10:27:00 +0200710 /*
711 * compute Committed Burst
712 */
713 SSE2_QOS_DEBUG_INFO ("Compute commit burst ...");
714 rate_hw = (hw->avg_rate_man) << (hw->rate_exp);
715 sse2_pol_rnd_burst_byte_fmt (cfg->rb.kbps.cb_bytes,
716 (u16) SSE2_QOS_POL_COMM_BKT_LIMIT_EXP_MAX,
717 (u16) SSE2_QOS_POL_COMM_BKT_LIMIT_MANT_MAX,
718 (u32) SSE2_QOS_POL_COMM_BKT_MAX,
719 rate_hw, &temp_exp, &temp_mant, &bkt_value);
720 SSE2_QOS_DEBUG_INFO ("Committed burst, burst_limit: 0x%llx mant : %u, "
721 "exp: %u, rnded: 0x%llx cb:%u bytes",
722 cfg->rb.kbps.cb_bytes, temp_mant, temp_exp,
723 ((u64) temp_mant << (u64) temp_exp), bkt_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700724
Damjan Marion3891cd82016-10-27 10:27:00 +0200725 hw->comm_bkt_limit_exp = temp_exp;
726 hw->comm_bkt_limit_man = (u8) temp_mant;
727 hw->comm_bkt = bkt_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700728
Damjan Marion3891cd82016-10-27 10:27:00 +0200729 /*
730 * compute Exceed Burst
731 */
732 SSE2_QOS_DEBUG_INFO ("Compute exceed burst ...");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700733
Damjan Marion3891cd82016-10-27 10:27:00 +0200734 if (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R2C)
735 {
736 /*
737 * For 1R2C, hw uses 2R3C (RFC-4115). As such, the Exceed Bucket
738 * params are set to 0. Recommendation is to use EB_exp = max_exp (=15)
739 * and EB_mant = 0
740 */
741 hw->extd_bkt_limit_exp = (u8) SSE2_QOS_POL_EXTD_BKT_LIMIT_EXP_MAX;
742 hw->extd_bkt_limit_man = 0;
743 SSE2_QOS_DEBUG_INFO ("Excess burst, burst: 0x%llx mant: %u, "
744 "exp: %u, rnded: 0x%llx bytes",
745 cfg->rb.kbps.eb_bytes, hw->extd_bkt_limit_man,
746 hw->extd_bkt_limit_exp,
747 ((u64) hw->extd_bkt_limit_man <<
748 (u64) hw->extd_bkt_limit_exp));
749 SSE2_QOS_TR_INFO (SSE2_QOS_TP_INFO_20, (uint) cfg->rb.kbps.eb_bytes,
750 hw->extd_bkt_limit_man, hw->extd_bkt_limit_exp);
751 return (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752 }
753
Damjan Marion3891cd82016-10-27 10:27:00 +0200754 if (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
755 {
756 eb_bytes = cfg->rb.kbps.cb_bytes + cfg->rb.kbps.eb_bytes;
757 }
758 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
759 {
760 eb_bytes = cfg->rb.kbps.eb_bytes - cfg->rb.kbps.cb_bytes;
761 }
762 else
763 {
764 eb_bytes = cfg->rb.kbps.eb_bytes;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700765 }
766
Damjan Marion3891cd82016-10-27 10:27:00 +0200767 rate_hw = (hw->peak_rate_man) << (hw->rate_exp);
768 sse2_pol_rnd_burst_byte_fmt (eb_bytes,
769 (u16) SSE2_QOS_POL_EXTD_BKT_LIMIT_EXP_MAX,
770 (u16) SSE2_QOS_POL_EXTD_BKT_LIMIT_MANT_MAX,
771 (u32) SSE2_QOS_POL_EXTD_BKT_MAX,
772 rate_hw, &temp_exp, &temp_mant, &bkt_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700773
Damjan Marion3891cd82016-10-27 10:27:00 +0200774 SSE2_QOS_DEBUG_INFO ("Excess burst, burst_limit: 0x%llx mant: %u, "
775 "exp: %u, rnded: 0x%llx eb:%u bytes",
776 cfg->rb.kbps.eb_bytes, temp_mant, temp_exp,
777 ((u64) temp_mant << (u64) temp_exp), bkt_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700778
Damjan Marion3891cd82016-10-27 10:27:00 +0200779 hw->extd_bkt_limit_exp = (u8) temp_exp;
780 hw->extd_bkt_limit_man = (u8) temp_mant;
781 hw->extd_bkt = bkt_value;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700782
Damjan Marion3891cd82016-10-27 10:27:00 +0200783 return (0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784}
785
786
787/*
788 * Input: configured parameter values in 'cfg'.
789 * Output: h/w programmable parameter values in 'hw'.
790 * Return: success or failure code.
791 */
Damjan Marion3891cd82016-10-27 10:27:00 +0200792static int
793sse2_pol_convert_cfg_to_hw_params (sse2_qos_pol_cfg_params_st * cfg,
794 sse2_qos_pol_hw_params_st * hw)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795{
Damjan Marion3891cd82016-10-27 10:27:00 +0200796 int rc = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700797
Damjan Marion3891cd82016-10-27 10:27:00 +0200798 /*
799 * clear the hw_params
800 */
801 memset (hw, 0, sizeof (sse2_qos_pol_hw_params_st));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700802
Damjan Marion3891cd82016-10-27 10:27:00 +0200803 hw->allow_negative = SSE2_QOS_POL_ALLOW_NEGATIVE;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700804
Damjan Marion3891cd82016-10-27 10:27:00 +0200805 if ((cfg->rfc == SSE2_QOS_POLICER_TYPE_1R2C) ||
806 (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115))
807 {
808 hw->rfc = IPE_RFC_RFC4115;
809 }
810 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
811 {
812 hw->rfc = IPE_RFC_RFC2697;
813 }
814 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698)
815 {
816 hw->rfc = IPE_RFC_RFC2698;
817 }
818 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1)
819 {
820 hw->rfc = IPE_RFC_MEF5CF1;
821 }
822 else
823 {
824 SSE2_QOS_DEBUG_ERROR ("Invalid RFC type %d\n", cfg->rfc);
825 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_61, cfg->rfc);
826 return (EINVAL);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700827 }
828
Damjan Marion3891cd82016-10-27 10:27:00 +0200829 rc = sse2_pol_convert_cfg_rates_to_hw (cfg, hw);
830 if (rc != 0)
831 {
832 SSE2_QOS_DEBUG_ERROR ("Unable to convert config rates to hw. Error: %d",
833 rc);
834 // Error is traced
835 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836 }
837
Damjan Marion3891cd82016-10-27 10:27:00 +0200838 rc = sse2_pol_convert_cfg_burst_to_hw (cfg, hw);
839 if (rc != 0)
840 {
841 SSE2_QOS_DEBUG_ERROR ("Unable to convert config burst to hw. Error: %d",
842 rc);
843 // Error is traced
844 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700845 }
846
Damjan Marion3891cd82016-10-27 10:27:00 +0200847 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700848}
849
850
Damjan Marion3891cd82016-10-27 10:27:00 +0200851u32
852sse2_qos_convert_pps_to_kbps (u32 rate_pps)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700853{
Damjan Marion3891cd82016-10-27 10:27:00 +0200854 // sse2_qos_ship_inc_counter(SSE2_QOS_SHIP_COUNTER_TYPE_API_CNT,
855 // SSE2_QOS_SHIP_CNT_POL_CONV_PPS_TO_KBPS);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700856
Damjan Marion3891cd82016-10-27 10:27:00 +0200857 u64 numer, rnd_value = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700858
Damjan Marion3891cd82016-10-27 10:27:00 +0200859 numer = (u64) ((u64) rate_pps *
860 (u64) SSE2_QOS_POLICER_FIXED_PKT_SIZE * 8LL);
861 (void) sse2_qos_pol_round (numer, 1000LL, &rnd_value,
862 SSE2_QOS_ROUND_TO_CLOSEST);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700863
Damjan Marion3891cd82016-10-27 10:27:00 +0200864 return ((u32) rnd_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865}
866
Damjan Marion3891cd82016-10-27 10:27:00 +0200867u32
868sse2_qos_convert_burst_ms_to_bytes (u32 burst_ms, u32 rate_kbps)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700869{
Damjan Marion3891cd82016-10-27 10:27:00 +0200870 u64 numer, rnd_value = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700871
Damjan Marion3891cd82016-10-27 10:27:00 +0200872 //sse2_qos_ship_inc_counter(SSE2_QOS_SHIP_COUNTER_TYPE_API_CNT,
873 // SSE2_QOS_SHIP_CNT_POL_CONV_BURST_MS_TO_BYTES);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874
Damjan Marion3891cd82016-10-27 10:27:00 +0200875 numer = (u64) ((u64) burst_ms * (u64) rate_kbps);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876
Damjan Marion3891cd82016-10-27 10:27:00 +0200877 (void) sse2_qos_pol_round (numer, 8LL, &rnd_value,
878 SSE2_QOS_ROUND_TO_CLOSEST);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700879
Damjan Marion3891cd82016-10-27 10:27:00 +0200880 return ((u32) rnd_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700881}
882
883
884/*
885 * Input: configured parameters in 'cfg'.
886 * Output: h/w parameters are returned in 'hw',
887 * Return: Status, success or failure code.
888 */
Damjan Marion3891cd82016-10-27 10:27:00 +0200889int
890sse2_pol_compute_hw_params (sse2_qos_pol_cfg_params_st * cfg,
891 sse2_qos_pol_hw_params_st * hw)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892{
Damjan Marion3891cd82016-10-27 10:27:00 +0200893 int rc = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894
Damjan Marion3891cd82016-10-27 10:27:00 +0200895 if (!cfg || !hw)
896 {
897 SSE2_QOS_DEBUG_ERROR ("Illegal parameters");
898 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700899 }
900
Damjan Marion3891cd82016-10-27 10:27:00 +0200901 /*
902 * Validate the police config params being presented to RM
903 */
904 rc = sse2_pol_validate_cfg_params (cfg);
905 if (rc != 0)
906 {
907 SSE2_QOS_DEBUG_ERROR ("Config parameter validation failed. Error: %d",
908 rc);
909 // Error is traced
910 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700911 }
912
Damjan Marion3891cd82016-10-27 10:27:00 +0200913 /*
914 * first round configured values to h/w supported values. This func
915 * also determines whether 'tick' or 'byte' format
916 */
917 rc = sse2_pol_convert_cfg_to_hw_params (cfg, hw);
918 if (rc != 0)
919 {
920 SSE2_QOS_DEBUG_ERROR ("Unable to convert config params to hw params. "
921 "Error: %d", rc);
922 SSE2_QOS_TR_ERR (SSE2_QOS_TP_ERR_53, rc);
923 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700924 }
925
Damjan Marion3891cd82016-10-27 10:27:00 +0200926 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700927}
928
929
930#if defined (INTERNAL_SS) || defined (X86)
931
932// For initializing the x86 policer format
933
934/*
935 * Return the number of hardware TSC timer ticks per second for the dataplane.
936 * This is approximately, but not exactly, the clock speed.
937 */
Damjan Marion3891cd82016-10-27 10:27:00 +0200938static u64
939get_tsc_hz (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700940{
Damjan Marion3891cd82016-10-27 10:27:00 +0200941 f64 cpu_freq;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942
Damjan Marion3891cd82016-10-27 10:27:00 +0200943 cpu_freq = os_cpu_clock_frequency ();
944 return (u64) cpu_freq;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700945}
946
947/*
948 * Convert rates into bytes_per_period and scale.
949 * Return 0 if ok or 1 if error.
950 */
Damjan Marion3891cd82016-10-27 10:27:00 +0200951static int
952compute_policer_params (u64 hz, // CPU speed in clocks per second
953 u64 cir_rate, // in bytes per second
954 u64 pir_rate, // in bytes per second
955 u32 * current_limit, // in bytes, output may scale the input
956 u32 * extended_limit, // in bytes, output may scale the input
957 u32 * cir_bytes_per_period,
958 u32 * pir_bytes_per_period, u32 * scale)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700959{
Damjan Marion3891cd82016-10-27 10:27:00 +0200960 double period;
961 double internal_cir_bytes_per_period;
962 double internal_pir_bytes_per_period;
963 u32 max;
964 u32 scale_shift;
965 u32 scale_amount;
966 u32 __attribute__ ((unused)) orig_current_limit = *current_limit;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700967
Damjan Marion3891cd82016-10-27 10:27:00 +0200968 // Compute period. For 1Ghz-to-8Ghz CPUs, the period will be in
969 // the range of 16 to 116 usec.
970 period = ((double) hz) / ((double) POLICER_TICKS_PER_PERIOD);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700971
Damjan Marion3891cd82016-10-27 10:27:00 +0200972 // Determine bytes per period for each rate
973 internal_cir_bytes_per_period = (double) cir_rate / period;
974 internal_pir_bytes_per_period = (double) pir_rate / period;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700975
Damjan Marion3891cd82016-10-27 10:27:00 +0200976 // Scale if possible. Scaling helps rate accuracy, but is contrained
977 // by the scaled rates and limits fitting in 32-bits.
978 // In addition, we need to insure the scaled rate is no larger than
979 // 2^22 tokens per period. This allows the dataplane to ignore overflow
980 // in the tokens-per-period multiplication since it could only
981 // happen if the policer were idle for more than a year.
982 // This is not really a constraint because 100Gbps at 1Ghz is only
983 // 1.6M tokens per period.
Ed Warnickecb9cada2015-12-08 15:45:58 -0700984#define MAX_RATE_SHIFT 10
Damjan Marion3891cd82016-10-27 10:27:00 +0200985 max = MAX (*current_limit, *extended_limit);
986 max = MAX (max, (u32) internal_cir_bytes_per_period << MAX_RATE_SHIFT);
987 max = MAX (max, (u32) internal_pir_bytes_per_period << MAX_RATE_SHIFT);
988 scale_shift = __builtin_clz (max);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989
Damjan Marion3891cd82016-10-27 10:27:00 +0200990 scale_amount = 1 << scale_shift;
991 *scale = scale_shift;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992
Damjan Marion3891cd82016-10-27 10:27:00 +0200993 // Scale the limits
994 *current_limit = *current_limit << scale_shift;
995 *extended_limit = *extended_limit << scale_shift;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700996
Damjan Marion3891cd82016-10-27 10:27:00 +0200997 // Scale the rates
998 internal_cir_bytes_per_period =
999 internal_cir_bytes_per_period * ((double) scale_amount);
1000 internal_pir_bytes_per_period =
1001 internal_pir_bytes_per_period * ((double) scale_amount);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001002
Damjan Marion3891cd82016-10-27 10:27:00 +02001003 // Make sure the new rates are reasonable
1004 // Only needed for very low rates with large bursts
1005 if (internal_cir_bytes_per_period < 1.0)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001006 {
Damjan Marion3891cd82016-10-27 10:27:00 +02001007 internal_cir_bytes_per_period = 1.0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001008 }
Damjan Marion3891cd82016-10-27 10:27:00 +02001009 if (internal_pir_bytes_per_period < 1.0)
1010 {
1011 internal_pir_bytes_per_period = 1.0;
1012 }
1013
1014 *cir_bytes_per_period = (u32) internal_cir_bytes_per_period;
1015 *pir_bytes_per_period = (u32) internal_pir_bytes_per_period;
1016
1017// #define PRINT_X86_POLICE_PARAMS
1018#ifdef PRINT_X86_POLICE_PARAMS
1019 {
1020 u64 effective_BPS;
1021
1022 // This value actually slightly conservative because it doesn't take into account
1023 // the partial period at the end of a second. This really matters only for very low
1024 // rates.
1025 effective_BPS =
1026 (((u64) (*cir_bytes_per_period * (u64) period)) >> *scale);
1027
1028 printf ("hz=%llu, cir_rate=%llu, limit=%u => "
1029 "periods-per-sec=%d usec-per-period=%d => "
1030 "scale=%d cir_BPP=%u, scaled_limit=%u => "
1031 "effective BPS=%llu, accuracy=%f\n",
1032 // input values
1033 (unsigned long long) hz,
1034 (unsigned long long) cir_rate, orig_current_limit,
1035 // computed values
1036 (u32) (period), // periods per second
1037 (u32) (1000.0 * 1000.0 / period), // in usec
1038 *scale, *cir_bytes_per_period, *current_limit,
1039 // accuracy
1040 (unsigned long long) effective_BPS,
1041 (double) cir_rate / (double) effective_BPS);
1042 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001043#endif
1044
Damjan Marion3891cd82016-10-27 10:27:00 +02001045 return 0; // ok
Ed Warnickecb9cada2015-12-08 15:45:58 -07001046}
1047
1048
1049/*
1050 * Input: configured parameters in 'cfg'.
1051 * Output: h/w parameters are returned in 'hw',
1052 * Return: Status, success or failure code.
1053 */
Damjan Marion3891cd82016-10-27 10:27:00 +02001054int
1055x86_pol_compute_hw_params (sse2_qos_pol_cfg_params_st * cfg,
1056 policer_read_response_type_st * hw)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001057{
Damjan Marion3891cd82016-10-27 10:27:00 +02001058 const int BYTES_PER_KBIT = (1000 / 8);
1059 u64 hz;
1060 u32 cap;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001061
Damjan Marion3891cd82016-10-27 10:27:00 +02001062 if (!cfg || !hw)
1063 {
1064 SSE2_QOS_DEBUG_ERROR ("Illegal parameters");
1065 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001066 }
1067
Damjan Marion3891cd82016-10-27 10:27:00 +02001068 hz = get_tsc_hz ();
1069 hw->last_update_time = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001070
Damjan Marion3891cd82016-10-27 10:27:00 +02001071 // Cap the bursts to 32-bits. This allows up to almost one second of
1072 // burst on a 40GE interface, which should be fine for x86.
1073 cap =
1074 (cfg->rb.kbps.cb_bytes > 0xFFFFFFFF) ? 0xFFFFFFFF : cfg->rb.kbps.cb_bytes;
1075 hw->current_limit = cap;
1076 cap =
1077 (cfg->rb.kbps.eb_bytes > 0xFFFFFFFF) ? 0xFFFFFFFF : cfg->rb.kbps.eb_bytes;
1078 hw->extended_limit = cap;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001079
Damjan Marion3891cd82016-10-27 10:27:00 +02001080 if ((cfg->rb.kbps.cir_kbps == 0) && (cfg->rb.kbps.cb_bytes == 0)
1081 && (cfg->rb.kbps.eb_bytes == 0))
1082 {
1083 // This is a uninitialized, always-violate policer
1084 hw->single_rate = 1;
1085 hw->cir_tokens_per_period = 0;
1086 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001087 }
1088
Damjan Marion3891cd82016-10-27 10:27:00 +02001089 if ((cfg->rfc == SSE2_QOS_POLICER_TYPE_1R2C) ||
1090 (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697))
1091 {
1092 // Single-rate policer
Ed Warnickecb9cada2015-12-08 15:45:58 -07001093
Damjan Marion3891cd82016-10-27 10:27:00 +02001094 hw->single_rate = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001095
Damjan Marion3891cd82016-10-27 10:27:00 +02001096 if ((cfg->rfc == SSE2_QOS_POLICER_TYPE_1R2C) && cfg->rb.kbps.eb_bytes)
1097 {
1098 SSE2_QOS_DEBUG_ERROR
1099 ("Policer parameter validation failed -- 1R2C.");
1100 return (-1);
1101 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001102
Damjan Marion3891cd82016-10-27 10:27:00 +02001103 if ((cfg->rb.kbps.cir_kbps == 0) ||
1104 (cfg->rb.kbps.eir_kbps != 0) ||
1105 ((cfg->rb.kbps.cb_bytes == 0) && (cfg->rb.kbps.eb_bytes == 0)))
1106 {
1107 SSE2_QOS_DEBUG_ERROR ("Policer parameter validation failed -- 1R.");
1108 return (-1);
1109 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001110
Damjan Marion3891cd82016-10-27 10:27:00 +02001111 if (compute_policer_params (hz,
1112 (u64) cfg->rb.kbps.cir_kbps *
1113 BYTES_PER_KBIT, 0, &hw->current_limit,
1114 &hw->extended_limit,
1115 &hw->cir_tokens_per_period,
1116 &hw->pir_tokens_per_period, &hw->scale))
1117 {
1118 SSE2_QOS_DEBUG_ERROR ("Policer parameter computation failed.");
1119 return (-1);
1120 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001121
Damjan Marion3891cd82016-10-27 10:27:00 +02001122 }
1123 else if ((cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698) ||
1124 (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115))
1125 {
1126 // Two-rate policer
Ed Warnickecb9cada2015-12-08 15:45:58 -07001127
Damjan Marion3891cd82016-10-27 10:27:00 +02001128 if ((cfg->rb.kbps.cir_kbps == 0) || (cfg->rb.kbps.eir_kbps == 0)
1129 || (cfg->rb.kbps.eir_kbps < cfg->rb.kbps.cir_kbps)
1130 || (cfg->rb.kbps.cb_bytes == 0) || (cfg->rb.kbps.eb_bytes == 0))
1131 {
1132 SSE2_QOS_DEBUG_ERROR ("Config parameter validation failed.");
1133 return (-1);
1134 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001135
Damjan Marion3891cd82016-10-27 10:27:00 +02001136 if (compute_policer_params (hz,
1137 (u64) cfg->rb.kbps.cir_kbps *
1138 BYTES_PER_KBIT,
1139 (u64) cfg->rb.kbps.eir_kbps *
1140 BYTES_PER_KBIT, &hw->current_limit,
1141 &hw->extended_limit,
1142 &hw->cir_tokens_per_period,
1143 &hw->pir_tokens_per_period, &hw->scale))
1144 {
1145 SSE2_QOS_DEBUG_ERROR ("Policer parameter computation failed.");
1146 return (-1);
1147 }
Ed Warnickecb9cada2015-12-08 15:45:58 -07001148
Damjan Marion3891cd82016-10-27 10:27:00 +02001149 }
1150 else
1151 {
1152 SSE2_QOS_DEBUG_ERROR
1153 ("Config parameter validation failed. RFC not supported");
1154 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001155 }
1156
Damjan Marion3891cd82016-10-27 10:27:00 +02001157 hw->current_bucket = hw->current_limit;
1158 hw->extended_bucket = hw->extended_limit;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001159
Damjan Marion3891cd82016-10-27 10:27:00 +02001160 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001161}
1162#endif
1163
1164
1165/*
1166 * Input: configured parameters in 'cfg'.
1167 * Output: physical structure is returned in 'phys',
1168 * Return: Status, success or failure code.
1169 */
Damjan Marion3891cd82016-10-27 10:27:00 +02001170int
1171sse2_pol_logical_2_physical (sse2_qos_pol_cfg_params_st * cfg,
1172 policer_read_response_type_st * phys)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001173{
Damjan Marion3891cd82016-10-27 10:27:00 +02001174 int rc;
1175 sse2_qos_pol_hw_params_st pol_hw;
1176 sse2_qos_pol_cfg_params_st kbps_cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001177
Damjan Marion3891cd82016-10-27 10:27:00 +02001178 memset (phys, 0, sizeof (policer_read_response_type_st));
1179 memset (&kbps_cfg, 0, sizeof (sse2_qos_pol_cfg_params_st));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001180
Damjan Marion3891cd82016-10-27 10:27:00 +02001181 if (!cfg)
1182 {
1183 SSE2_QOS_DEBUG_ERROR ("Illegal parameters");
1184 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001185 }
1186
Damjan Marion3891cd82016-10-27 10:27:00 +02001187 switch (cfg->rate_type)
1188 {
Ed Warnickecb9cada2015-12-08 15:45:58 -07001189 case SSE2_QOS_RATE_KBPS:
Damjan Marion3891cd82016-10-27 10:27:00 +02001190 /* copy all the data into kbps_cfg */
1191 kbps_cfg.rb.kbps.cir_kbps = cfg->rb.kbps.cir_kbps;
1192 kbps_cfg.rb.kbps.eir_kbps = cfg->rb.kbps.eir_kbps;
1193 kbps_cfg.rb.kbps.cb_bytes = cfg->rb.kbps.cb_bytes;
1194 kbps_cfg.rb.kbps.eb_bytes = cfg->rb.kbps.eb_bytes;
1195 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001196 case SSE2_QOS_RATE_PPS:
Damjan Marion3891cd82016-10-27 10:27:00 +02001197 kbps_cfg.rb.kbps.cir_kbps =
1198 sse2_qos_convert_pps_to_kbps (cfg->rb.pps.cir_pps);
1199 kbps_cfg.rb.kbps.eir_kbps =
1200 sse2_qos_convert_pps_to_kbps (cfg->rb.pps.eir_pps);
1201 kbps_cfg.rb.kbps.cb_bytes = sse2_qos_convert_burst_ms_to_bytes ((u32)
1202 cfg->
1203 rb.pps.cb_ms,
1204 kbps_cfg.rb.
1205 kbps.cir_kbps);
1206 kbps_cfg.rb.kbps.eb_bytes =
1207 sse2_qos_convert_burst_ms_to_bytes ((u32) cfg->rb.pps.eb_ms,
1208 kbps_cfg.rb.kbps.eir_kbps);
1209 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001210 default:
Damjan Marion3891cd82016-10-27 10:27:00 +02001211 SSE2_QOS_DEBUG_ERROR ("Illegal rate type");
1212 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001213 }
1214
Damjan Marion3891cd82016-10-27 10:27:00 +02001215 /* rate type is now converted to kbps */
1216 kbps_cfg.rate_type = SSE2_QOS_RATE_KBPS;
1217 kbps_cfg.rnd_type = cfg->rnd_type;
1218 kbps_cfg.rfc = cfg->rfc;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001219
Damjan Marion3891cd82016-10-27 10:27:00 +02001220 phys->action[POLICE_CONFORM] = cfg->conform_action.action_type;
1221 phys->mark_dscp[POLICE_CONFORM] = cfg->conform_action.dscp;
1222 phys->action[POLICE_EXCEED] = cfg->exceed_action.action_type;
1223 phys->mark_dscp[POLICE_EXCEED] = cfg->exceed_action.dscp;
1224 phys->action[POLICE_VIOLATE] = cfg->violate_action.action_type;
1225 phys->mark_dscp[POLICE_VIOLATE] = cfg->violate_action.dscp;
Matus Fabian4ac74c92016-05-31 07:33:29 -07001226
Damjan Marion3891cd82016-10-27 10:27:00 +02001227 phys->color_aware = cfg->color_aware;
Matus Fabian70e6a8d2016-06-20 08:10:42 -07001228
Ed Warnickecb9cada2015-12-08 15:45:58 -07001229#if !defined (INTERNAL_SS) && !defined (X86)
Damjan Marion3891cd82016-10-27 10:27:00 +02001230 // convert logical into hw params which involves qos calculations
1231 rc = sse2_pol_compute_hw_params (&kbps_cfg, &pol_hw);
1232 if (rc == -1)
1233 {
1234 SSE2_QOS_DEBUG_ERROR ("Unable to compute hw param. Error: %d", rc);
1235 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001236 }
1237
Damjan Marion3891cd82016-10-27 10:27:00 +02001238 // convert hw params into the physical
1239 phys->rfc = pol_hw.rfc;
1240 phys->an = pol_hw.allow_negative;
1241 phys->rexp = pol_hw.rate_exp;
1242 phys->arm = pol_hw.avg_rate_man;
1243 phys->prm = pol_hw.peak_rate_man;
1244 phys->cble = pol_hw.comm_bkt_limit_exp;
1245 phys->cblm = pol_hw.comm_bkt_limit_man;
1246 phys->eble = pol_hw.extd_bkt_limit_exp;
1247 phys->eblm = pol_hw.extd_bkt_limit_man;
1248 phys->cb = pol_hw.comm_bkt;
1249 phys->eb = pol_hw.extd_bkt;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001250
Damjan Marion3891cd82016-10-27 10:27:00 +02001251 /* for debugging purposes, the bucket token values can be overwritten */
1252 if (cfg->overwrite_bucket)
1253 {
1254 phys->cb = cfg->current_bucket;
1255 phys->eb = cfg->extended_bucket;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001256 }
1257#else
Damjan Marion3891cd82016-10-27 10:27:00 +02001258 // convert logical into hw params which involves qos calculations
1259 rc = x86_pol_compute_hw_params (&kbps_cfg, phys);
1260 if (rc == -1)
1261 {
1262 SSE2_QOS_DEBUG_ERROR ("Unable to compute hw param. Error: %d", rc);
1263 return (rc);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001264 }
1265
Damjan Marion3891cd82016-10-27 10:27:00 +02001266 /* for debugging purposes, the bucket token values can be overwritten */
1267 if (cfg->overwrite_bucket)
1268 {
1269 phys->current_bucket = cfg->current_bucket;
1270 phys->extended_bucket = cfg->extended_bucket;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001271 }
1272
Damjan Marion3891cd82016-10-27 10:27:00 +02001273 // Touch to avoid compiler warning for X86
1274 pol_hw.allow_negative = pol_hw.allow_negative;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001275
1276#endif // if !defined (INTERNAL_SS) && !defined (X86)
1277
Damjan Marion3891cd82016-10-27 10:27:00 +02001278 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001279}
1280
1281
1282static void
Damjan Marion3891cd82016-10-27 10:27:00 +02001283sse2_qos_convert_pol_bucket_to_hw_fmt (policer_read_response_type_st * bkt,
1284 sse2_qos_pol_hw_params_st * hw_fmt)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001285{
Damjan Marion3891cd82016-10-27 10:27:00 +02001286 memset (hw_fmt, 0, sizeof (sse2_qos_pol_hw_params_st));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001287#if !defined (INTERNAL_SS) && !defined (X86)
Damjan Marion3891cd82016-10-27 10:27:00 +02001288 hw_fmt->rfc = (u8) bkt->rfc;
1289 hw_fmt->allow_negative = (u8) bkt->an;
1290 hw_fmt->rate_exp = (u8) bkt->rexp;
1291 hw_fmt->avg_rate_man = (u16) bkt->arm;
1292 hw_fmt->peak_rate_man = (u16) bkt->prm;
1293 hw_fmt->comm_bkt_limit_man = (u8) bkt->cblm;
1294 hw_fmt->comm_bkt_limit_exp = (u8) bkt->cble;
1295 hw_fmt->extd_bkt_limit_man = (u8) bkt->eblm;
1296 hw_fmt->extd_bkt_limit_exp = (u8) bkt->eble;
1297 hw_fmt->extd_bkt = bkt->eb;
1298 hw_fmt->comm_bkt = bkt->cb;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001299#endif // if !defined (INTERNAL_SS) && !defined (X86)
1300}
1301
1302/*
1303 * Input: h/w programmable parameter values in 'hw'
1304 * Output: configured parameter values in 'cfg'
1305 * Return: Status, success or failure code.
1306 */
Damjan Marion3891cd82016-10-27 10:27:00 +02001307static int
1308sse2_pol_convert_hw_to_cfg_params (sse2_qos_pol_hw_params_st * hw,
1309 sse2_qos_pol_cfg_params_st * cfg)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001310{
Damjan Marion3891cd82016-10-27 10:27:00 +02001311 u64 temp_rate;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001312
Damjan Marion3891cd82016-10-27 10:27:00 +02001313 if ((hw == NULL) || (cfg == NULL))
1314 {
1315 return EINVAL;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001316 }
1317
Damjan Marion3891cd82016-10-27 10:27:00 +02001318 if ((hw->rfc == IPE_RFC_RFC4115) &&
1319 !(hw->peak_rate_man << hw->rate_exp) && !(hw->extd_bkt_limit_man))
1320 {
1321 /*
1322 * For a 1R2C, we set EIR = 0, EB = 0
1323 */
1324 cfg->rfc = SSE2_QOS_POLICER_TYPE_1R2C;
1325 }
1326 else if (hw->rfc == IPE_RFC_RFC2697)
1327 {
1328 cfg->rfc = SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697;
1329 }
1330 else if (hw->rfc == IPE_RFC_RFC2698)
1331 {
1332 cfg->rfc = SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698;
1333 }
1334 else if (hw->rfc == IPE_RFC_RFC4115)
1335 {
1336 cfg->rfc = SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115;
1337 }
1338 else if (hw->rfc == IPE_RFC_MEF5CF1)
1339 {
1340 cfg->rfc = SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1;
1341 }
1342 else
1343 {
1344 return EINVAL;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001345 }
1346
Damjan Marion3891cd82016-10-27 10:27:00 +02001347 temp_rate = (((u64) hw->avg_rate_man << hw->rate_exp) * 8LL *
1348 SSE2_QOS_POL_TICKS_PER_SEC) / 1000;
1349 cfg->rb.kbps.cir_kbps = (u32) temp_rate;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001350
Damjan Marion3891cd82016-10-27 10:27:00 +02001351 temp_rate = (((u64) hw->peak_rate_man << hw->rate_exp) * 8LL *
1352 SSE2_QOS_POL_TICKS_PER_SEC) / 1000;
1353 cfg->rb.kbps.eir_kbps = (u32) temp_rate;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001354
Damjan Marion3891cd82016-10-27 10:27:00 +02001355 cfg->rb.kbps.cb_bytes = ((u64) hw->comm_bkt_limit_man <<
1356 (u64) hw->comm_bkt_limit_exp);
1357 cfg->rb.kbps.eb_bytes = ((u64) hw->extd_bkt_limit_man <<
1358 (u64) hw->extd_bkt_limit_exp);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001359
Damjan Marion3891cd82016-10-27 10:27:00 +02001360 if (cfg->rfc == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697)
1361 {
1362 /*
1363 * For 1R3C in the hardware, EB = sum(CB, EB). Also, EIR = CIR. Restore
1364 * values such that the configured params don't reflect this adjustment
1365 */
1366 cfg->rb.kbps.eb_bytes = (cfg->rb.kbps.eb_bytes - cfg->rb.kbps.cb_bytes);
1367 cfg->rb.kbps.eir_kbps = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001368 }
Damjan Marion3891cd82016-10-27 10:27:00 +02001369 else if (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)
1370 {
1371 /*
1372 * For 4115 in the hardware is excess rate and burst, but EA provides
1373 * peak-rate, so adjust it to be eir
1374 */
1375 cfg->rb.kbps.eir_kbps += cfg->rb.kbps.cir_kbps;
1376 cfg->rb.kbps.eb_bytes += cfg->rb.kbps.cb_bytes;
1377 }
1378 /* h/w conversion to cfg is in kbps */
1379 cfg->rate_type = SSE2_QOS_RATE_KBPS;
1380 cfg->overwrite_bucket = 0;
1381 cfg->current_bucket = hw->comm_bkt;
1382 cfg->extended_bucket = hw->extd_bkt;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001383
Damjan Marion3891cd82016-10-27 10:27:00 +02001384 SSE2_QOS_DEBUG_INFO ("configured params, cir: %u kbps, eir: %u kbps, cb "
1385 "burst: 0x%llx bytes, eb burst: 0x%llx bytes",
1386 cfg->rb.kbps.cir_kbps, cfg->rb.kbps.eir_kbps,
1387 cfg->rb.kbps.cb_bytes, cfg->rb.kbps.eb_bytes);
1388 SSE2_QOS_TR_INFO (SSE2_QOS_TP_INFO_22, cfg->rb.kbps.cir_kbps,
1389 cfg->rb.kbps.eir_kbps,
1390 (uint) cfg->rb.kbps.cb_bytes,
1391 (uint) cfg->rb.kbps.eb_bytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001392
Damjan Marion3891cd82016-10-27 10:27:00 +02001393 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001394}
1395
Damjan Marion3891cd82016-10-27 10:27:00 +02001396u32
1397sse2_qos_convert_kbps_to_pps (u32 rate_kbps)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001398{
Damjan Marion3891cd82016-10-27 10:27:00 +02001399 u64 numer, denom, rnd_value = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001400
Damjan Marion3891cd82016-10-27 10:27:00 +02001401 // sse_qosrm_ship_inc_counter(SSE2_QOS_SHIP_COUNTER_TYPE_API_CNT,
1402 // SSE2_QOS_SHIP_CNT_POL_CONV_KBPS_TO_PPS);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001403
Damjan Marion3891cd82016-10-27 10:27:00 +02001404 numer = (u64) ((u64) rate_kbps * 1000LL);
1405 denom = (u64) ((u64) SSE2_QOS_POLICER_FIXED_PKT_SIZE * 8LL);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001406
Damjan Marion3891cd82016-10-27 10:27:00 +02001407 (void) sse2_qos_pol_round (numer, denom, &rnd_value,
1408 SSE2_QOS_ROUND_TO_CLOSEST);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001409
Damjan Marion3891cd82016-10-27 10:27:00 +02001410 return ((u32) rnd_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001411}
1412
Damjan Marion3891cd82016-10-27 10:27:00 +02001413u32
1414sse2_qos_convert_burst_bytes_to_ms (u64 burst_bytes, u32 rate_kbps)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001415{
Damjan Marion3891cd82016-10-27 10:27:00 +02001416 u64 numer, denom, rnd_value = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001417
Damjan Marion3891cd82016-10-27 10:27:00 +02001418 //sse_qosrm_ship_inc_counter(SSE2_QOS_SHIP_COUNTER_TYPE_API_CNT,
1419 // SSE2_QOS_SHIP_CNT_POL_CONV_BYTES_TO_BURST_MS);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001420
Damjan Marion3891cd82016-10-27 10:27:00 +02001421 numer = burst_bytes * 8LL;
1422 denom = (u64) rate_kbps;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001423
Damjan Marion3891cd82016-10-27 10:27:00 +02001424 (void) sse2_qos_pol_round (numer, denom, &rnd_value,
1425 SSE2_QOS_ROUND_TO_CLOSEST);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001426
Damjan Marion3891cd82016-10-27 10:27:00 +02001427 return ((u32) rnd_value);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001428}
1429
1430/*
1431 * Input: physical structure in 'phys', rate_type in cfg
1432 * Output: configured parameters in 'cfg'.
1433 * Return: Status, success or failure code.
1434 */
Damjan Marion3891cd82016-10-27 10:27:00 +02001435int
1436sse2_pol_physical_2_logical (policer_read_response_type_st * phys,
1437 sse2_qos_pol_cfg_params_st * cfg)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001438{
Damjan Marion3891cd82016-10-27 10:27:00 +02001439 int rc;
1440 sse2_qos_pol_hw_params_st pol_hw;
1441 sse2_qos_pol_cfg_params_st kbps_cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001442
Damjan Marion3891cd82016-10-27 10:27:00 +02001443 memset (&pol_hw, 0, sizeof (sse2_qos_pol_hw_params_st));
1444 memset (&kbps_cfg, 0, sizeof (sse2_qos_pol_cfg_params_st));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001445
Damjan Marion3891cd82016-10-27 10:27:00 +02001446 if (!phys)
1447 {
1448 SSE2_QOS_DEBUG_ERROR ("Illegal parameters");
1449 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001450 }
1451
Damjan Marion3891cd82016-10-27 10:27:00 +02001452 sse2_qos_convert_pol_bucket_to_hw_fmt (phys, &pol_hw);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001453
Damjan Marion3891cd82016-10-27 10:27:00 +02001454 rc = sse2_pol_convert_hw_to_cfg_params (&pol_hw, &kbps_cfg);
1455 if (rc != 0)
1456 {
1457 SSE2_QOS_DEBUG_ERROR ("Unable to convert hw params to config params. "
1458 "Error: %d", rc);
1459 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001460 }
1461
Damjan Marion3891cd82016-10-27 10:27:00 +02001462 /* check what rate type is required */
1463 switch (cfg->rate_type)
1464 {
Ed Warnickecb9cada2015-12-08 15:45:58 -07001465 case SSE2_QOS_RATE_KBPS:
Damjan Marion3891cd82016-10-27 10:27:00 +02001466 /* copy all the data into kbps_cfg */
1467 cfg->rb.kbps.cir_kbps = kbps_cfg.rb.kbps.cir_kbps;
1468 cfg->rb.kbps.eir_kbps = kbps_cfg.rb.kbps.eir_kbps;
1469 cfg->rb.kbps.cb_bytes = kbps_cfg.rb.kbps.cb_bytes;
1470 cfg->rb.kbps.eb_bytes = kbps_cfg.rb.kbps.eb_bytes;
1471 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001472 case SSE2_QOS_RATE_PPS:
Damjan Marion3891cd82016-10-27 10:27:00 +02001473 cfg->rb.pps.cir_pps =
1474 sse2_qos_convert_kbps_to_pps (kbps_cfg.rb.kbps.cir_kbps);
1475 cfg->rb.pps.eir_pps =
1476 sse2_qos_convert_kbps_to_pps (kbps_cfg.rb.kbps.eir_kbps);
1477 cfg->rb.pps.cb_ms =
1478 sse2_qos_convert_burst_bytes_to_ms (kbps_cfg.rb.kbps.cb_bytes,
1479 kbps_cfg.rb.kbps.cir_kbps);
1480 cfg->rb.pps.eb_ms =
1481 sse2_qos_convert_burst_bytes_to_ms (kbps_cfg.rb.kbps.eb_bytes,
1482 kbps_cfg.rb.kbps.eir_kbps);
1483 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001484 default:
Damjan Marion3891cd82016-10-27 10:27:00 +02001485 SSE2_QOS_DEBUG_ERROR ("Illegal rate type");
1486 return (-1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001487 }
1488
Damjan Marion3891cd82016-10-27 10:27:00 +02001489 /* cfg->rate_type remains what it was */
1490 cfg->rnd_type = kbps_cfg.rnd_type;
1491 cfg->rfc = kbps_cfg.rfc;
1492 cfg->overwrite_bucket = kbps_cfg.overwrite_bucket;
1493 cfg->current_bucket = kbps_cfg.current_bucket;
1494 cfg->extended_bucket = kbps_cfg.extended_bucket;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001495
Damjan Marion3891cd82016-10-27 10:27:00 +02001496 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001497}
Damjan Marion3891cd82016-10-27 10:27:00 +02001498
1499/*
1500 * fd.io coding-style-patch-verification: ON
1501 *
1502 * Local Variables:
1503 * eval: (c-set-style "gnu")
1504 * End:
1505 */