xref: /dpdk/drivers/net/mvpp2/mrvl_qos.c (revision 41c60f74d85f2e889dfdd155bc4e30cf00913914)
1fe939687SNatalie Samsonov /* SPDX-License-Identifier: BSD-3-Clause
2fe939687SNatalie Samsonov  * Copyright(c) 2017 Marvell International Ltd.
3fe939687SNatalie Samsonov  * Copyright(c) 2017 Semihalf.
4fe939687SNatalie Samsonov  * All rights reserved.
5fe939687SNatalie Samsonov  */
6fe939687SNatalie Samsonov 
7fe939687SNatalie Samsonov #include <stdint.h>
8fe939687SNatalie Samsonov #include <stdlib.h>
9fe939687SNatalie Samsonov #include <string.h>
10fe939687SNatalie Samsonov 
11fe939687SNatalie Samsonov #include <rte_common.h>
12fe939687SNatalie Samsonov #include <rte_cfgfile.h>
13fe939687SNatalie Samsonov #include <rte_log.h>
14fe939687SNatalie Samsonov #include <rte_lcore.h>
15fe939687SNatalie Samsonov #include <rte_malloc.h>
16fe939687SNatalie Samsonov #include <rte_string_fns.h>
17fe939687SNatalie Samsonov 
18fe939687SNatalie Samsonov #include "mrvl_qos.h"
19fe939687SNatalie Samsonov 
20fe939687SNatalie Samsonov /* Parsing tokens. Defined conveniently, so that any correction is easy. */
21fe939687SNatalie Samsonov #define MRVL_TOK_DEFAULT "default"
22c2b5ae61SLiron Himi #define MRVL_TOK_DSA_MODE "dsa_mode"
236000b5beSDana Vardi #define MRVL_TOK_START_HDR "start_hdr"
246000b5beSDana Vardi #define MRVL_TOK_START_HDR_NONE "none"
256000b5beSDana Vardi #define MRVL_TOK_START_HDR_DSA "dsa"
2621aa25e0SDana Vardi #define MRVL_TOK_START_HDR_CUSTOM "custom"
276000b5beSDana Vardi #define MRVL_TOK_START_HDR_EXT_DSA "ext_dsa"
28fe939687SNatalie Samsonov #define MRVL_TOK_DEFAULT_TC "default_tc"
29fe939687SNatalie Samsonov #define MRVL_TOK_DSCP "dscp"
30fe939687SNatalie Samsonov #define MRVL_TOK_MAPPING_PRIORITY "mapping_priority"
31fe939687SNatalie Samsonov #define MRVL_TOK_IP "ip"
32fe939687SNatalie Samsonov #define MRVL_TOK_IP_VLAN "ip/vlan"
33fe939687SNatalie Samsonov #define MRVL_TOK_PCP "pcp"
34fe939687SNatalie Samsonov #define MRVL_TOK_PORT "port"
35fe939687SNatalie Samsonov #define MRVL_TOK_RXQ "rxq"
36fe939687SNatalie Samsonov #define MRVL_TOK_TC "tc"
37fe939687SNatalie Samsonov #define MRVL_TOK_TXQ "txq"
38fe939687SNatalie Samsonov #define MRVL_TOK_VLAN "vlan"
39fe939687SNatalie Samsonov #define MRVL_TOK_VLAN_IP "vlan/ip"
403e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF "parser udf"
41fe939687SNatalie Samsonov 
42fe939687SNatalie Samsonov /* egress specific configuration tokens */
43fe939687SNatalie Samsonov #define MRVL_TOK_BURST_SIZE "burst_size"
44fe939687SNatalie Samsonov #define MRVL_TOK_RATE_LIMIT "rate_limit"
45fe939687SNatalie Samsonov #define MRVL_TOK_RATE_LIMIT_ENABLE "rate_limit_enable"
46fe939687SNatalie Samsonov #define MRVL_TOK_SCHED_MODE "sched_mode"
47fe939687SNatalie Samsonov #define MRVL_TOK_SCHED_MODE_SP "sp"
48fe939687SNatalie Samsonov #define MRVL_TOK_SCHED_MODE_WRR "wrr"
49fe939687SNatalie Samsonov #define MRVL_TOK_WRR_WEIGHT "wrr_weight"
50fe939687SNatalie Samsonov 
51fe939687SNatalie Samsonov /* policer specific configuration tokens */
52e97d8874STomasz Duszynski #define MRVL_TOK_PLCR "policer"
53e97d8874STomasz Duszynski #define MRVL_TOK_PLCR_DEFAULT "default_policer"
54fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_UNIT "token_unit"
55fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_UNIT_BYTES "bytes"
56fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_UNIT_PACKETS "packets"
57fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_COLOR "color_mode"
58fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_COLOR_BLIND "blind"
59fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_COLOR_AWARE "aware"
60fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_CIR "cir"
61fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_CBS "cbs"
62fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_EBS "ebs"
63fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR "default_color"
64fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN "green"
65fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW "yellow"
66fe939687SNatalie Samsonov #define MRVL_TOK_PLCR_DEFAULT_COLOR_RED "red"
67fe939687SNatalie Samsonov 
683e09b2a7SLiron Himi /* parser udf specific configuration tokens */
693e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_PROTO "proto"
703e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_FIELD "field"
713e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_KEY "key"
723e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_MASK "mask"
733e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_OFFSET "offset"
743e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_PROTO_ETH "eth"
753e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE "type"
763e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_PROTO_UDP "udp"
773e09b2a7SLiron Himi #define MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT "dport"
783e09b2a7SLiron Himi 
79ef08031fSDana Vardi /* parser forward bad frames tokens */
80ef08031fSDana Vardi #define MRVL_TOK_FWD_BAD_FRAMES "forward_bad_frames"
813e09b2a7SLiron Himi 
82fe939687SNatalie Samsonov /** Number of tokens in range a-b = 2. */
83fe939687SNatalie Samsonov #define MAX_RNG_TOKENS 2
84fe939687SNatalie Samsonov 
85fe939687SNatalie Samsonov /** Maximum possible value of PCP. */
86fe939687SNatalie Samsonov #define MAX_PCP 7
87fe939687SNatalie Samsonov 
88fe939687SNatalie Samsonov /** Maximum possible value of DSCP. */
89fe939687SNatalie Samsonov #define MAX_DSCP 63
90fe939687SNatalie Samsonov 
91d7eb4fb2SLiron Himi /** Global configuration. */
92d7eb4fb2SLiron Himi struct mrvl_cfg *mrvl_cfg;
93fe939687SNatalie Samsonov 
94fe939687SNatalie Samsonov /**
95fe939687SNatalie Samsonov  * Read out-queue configuration from file.
96fe939687SNatalie Samsonov  *
97fe939687SNatalie Samsonov  * @param file Path to the configuration file.
98fe939687SNatalie Samsonov  * @param port Port number.
99fe939687SNatalie Samsonov  * @param outq Out queue number.
100d7eb4fb2SLiron Himi  * @param cfg Pointer to the Marvell configuration structure.
101fe939687SNatalie Samsonov  * @returns 0 in case of success, negative value otherwise.
102fe939687SNatalie Samsonov  */
103fe939687SNatalie Samsonov static int
104fe939687SNatalie Samsonov get_outq_cfg(struct rte_cfgfile *file, int port, int outq,
105d7eb4fb2SLiron Himi 		struct mrvl_cfg *cfg)
106fe939687SNatalie Samsonov {
107fe939687SNatalie Samsonov 	char sec_name[32];
108fe939687SNatalie Samsonov 	const char *entry;
109fe939687SNatalie Samsonov 	uint32_t val;
110fe939687SNatalie Samsonov 
111fe939687SNatalie Samsonov 	snprintf(sec_name, sizeof(sec_name), "%s %d %s %d",
112fe939687SNatalie Samsonov 		MRVL_TOK_PORT, port, MRVL_TOK_TXQ, outq);
113fe939687SNatalie Samsonov 
114fe939687SNatalie Samsonov 	/* Skip non-existing */
115fe939687SNatalie Samsonov 	if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0)
116fe939687SNatalie Samsonov 		return 0;
117fe939687SNatalie Samsonov 
118fe939687SNatalie Samsonov 	/* Read scheduling mode */
119fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_SCHED_MODE);
120fe939687SNatalie Samsonov 	if (entry) {
121fe939687SNatalie Samsonov 		if (!strncmp(entry, MRVL_TOK_SCHED_MODE_SP,
122fe939687SNatalie Samsonov 					strlen(MRVL_TOK_SCHED_MODE_SP))) {
123fe939687SNatalie Samsonov 			cfg->port[port].outq[outq].sched_mode =
124fe939687SNatalie Samsonov 				PP2_PPIO_SCHED_M_SP;
125fe939687SNatalie Samsonov 		} else if (!strncmp(entry, MRVL_TOK_SCHED_MODE_WRR,
126fe939687SNatalie Samsonov 					strlen(MRVL_TOK_SCHED_MODE_WRR))) {
127fe939687SNatalie Samsonov 			cfg->port[port].outq[outq].sched_mode =
128fe939687SNatalie Samsonov 				PP2_PPIO_SCHED_M_WRR;
129fe939687SNatalie Samsonov 		} else {
130acab7d58STomasz Duszynski 			MRVL_LOG(ERR, "Unknown token: %s", entry);
131fe939687SNatalie Samsonov 			return -1;
132fe939687SNatalie Samsonov 		}
133fe939687SNatalie Samsonov 	}
134fe939687SNatalie Samsonov 
135fe939687SNatalie Samsonov 	/* Read wrr weight */
136fe939687SNatalie Samsonov 	if (cfg->port[port].outq[outq].sched_mode == PP2_PPIO_SCHED_M_WRR) {
137fe939687SNatalie Samsonov 		entry = rte_cfgfile_get_entry(file, sec_name,
138fe939687SNatalie Samsonov 				MRVL_TOK_WRR_WEIGHT);
139fe939687SNatalie Samsonov 		if (entry) {
140fe939687SNatalie Samsonov 			if (get_val_securely(entry, &val) < 0)
141fe939687SNatalie Samsonov 				return -1;
142fe939687SNatalie Samsonov 			cfg->port[port].outq[outq].weight = val;
143fe939687SNatalie Samsonov 		}
144fe939687SNatalie Samsonov 	}
145fe939687SNatalie Samsonov 
146fe939687SNatalie Samsonov 	/*
147fe939687SNatalie Samsonov 	 * There's no point in setting rate limiting for specific outq as
148fe939687SNatalie Samsonov 	 * global port rate limiting has priority.
149fe939687SNatalie Samsonov 	 */
150fe939687SNatalie Samsonov 	if (cfg->port[port].rate_limit_enable) {
151acab7d58STomasz Duszynski 		MRVL_LOG(WARNING, "Port %d rate limiting already enabled",
152fe939687SNatalie Samsonov 			port);
153fe939687SNatalie Samsonov 		return 0;
154fe939687SNatalie Samsonov 	}
155fe939687SNatalie Samsonov 
156fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name,
157fe939687SNatalie Samsonov 			MRVL_TOK_RATE_LIMIT_ENABLE);
158fe939687SNatalie Samsonov 	if (entry) {
159fe939687SNatalie Samsonov 		if (get_val_securely(entry, &val) < 0)
160fe939687SNatalie Samsonov 			return -1;
161fe939687SNatalie Samsonov 		cfg->port[port].outq[outq].rate_limit_enable = val;
162fe939687SNatalie Samsonov 	}
163fe939687SNatalie Samsonov 
164fe939687SNatalie Samsonov 	if (!cfg->port[port].outq[outq].rate_limit_enable)
165fe939687SNatalie Samsonov 		return 0;
166fe939687SNatalie Samsonov 
167fe939687SNatalie Samsonov 	/* Read CBS (in kB) */
168fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_BURST_SIZE);
169fe939687SNatalie Samsonov 	if (entry) {
170fe939687SNatalie Samsonov 		if (get_val_securely(entry, &val) < 0)
171fe939687SNatalie Samsonov 			return -1;
172fe939687SNatalie Samsonov 		cfg->port[port].outq[outq].rate_limit_params.cbs = val;
173fe939687SNatalie Samsonov 	}
174fe939687SNatalie Samsonov 
175fe939687SNatalie Samsonov 	/* Read CIR (in kbps) */
176fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RATE_LIMIT);
177fe939687SNatalie Samsonov 	if (entry) {
178fe939687SNatalie Samsonov 		if (get_val_securely(entry, &val) < 0)
179fe939687SNatalie Samsonov 			return -1;
180fe939687SNatalie Samsonov 		cfg->port[port].outq[outq].rate_limit_params.cir = val;
181fe939687SNatalie Samsonov 	}
182fe939687SNatalie Samsonov 
183fe939687SNatalie Samsonov 	return 0;
184fe939687SNatalie Samsonov }
185fe939687SNatalie Samsonov 
186fe939687SNatalie Samsonov /**
187fe939687SNatalie Samsonov  * Gets multiple-entry values and places them in table.
188fe939687SNatalie Samsonov  *
189fe939687SNatalie Samsonov  * Entry can be anything, e.g. "1 2-3 5 6 7-9". This needs to be converted to
190fe939687SNatalie Samsonov  * table entries, respectively: {1, 2, 3, 5, 6, 7, 8, 9}.
191fe939687SNatalie Samsonov  * As all result table's elements are always 1-byte long, we
192fe939687SNatalie Samsonov  * won't overcomplicate the function, but we'll keep API generic,
193fe939687SNatalie Samsonov  * check if someone hasn't changed element size and make it simple
194fe939687SNatalie Samsonov  * to extend to other sizes.
195fe939687SNatalie Samsonov  *
196fe939687SNatalie Samsonov  * This function is purely utilitary, it does not print any error, only returns
197fe939687SNatalie Samsonov  * different error numbers.
198fe939687SNatalie Samsonov  *
199fe939687SNatalie Samsonov  * @param entry[in] Values string to parse.
200fe939687SNatalie Samsonov  * @param tab[out] Results table.
201fe939687SNatalie Samsonov  * @param elem_sz[in] Element size (in bytes).
202fe939687SNatalie Samsonov  * @param max_elems[in] Number of results table elements available.
203fe939687SNatalie Samsonov  * @param max val[in] Maximum value allowed.
204fe939687SNatalie Samsonov  * @returns Number of correctly parsed elements in case of success.
205fe939687SNatalie Samsonov  * @retval -1 Wrong element size.
206fe939687SNatalie Samsonov  * @retval -2 More tokens than result table allows.
207fe939687SNatalie Samsonov  * @retval -3 Wrong range syntax.
208fe939687SNatalie Samsonov  * @retval -4 Wrong range values.
209fe939687SNatalie Samsonov  * @retval -5 Maximum value exceeded.
210fe939687SNatalie Samsonov  */
211fe939687SNatalie Samsonov static int
212fe939687SNatalie Samsonov get_entry_values(const char *entry, uint8_t *tab,
213fe939687SNatalie Samsonov 	size_t elem_sz, uint8_t max_elems, uint8_t max_val)
214fe939687SNatalie Samsonov {
215fe939687SNatalie Samsonov 	/* There should not be more tokens than max elements.
216fe939687SNatalie Samsonov 	 * Add 1 for error trap.
217fe939687SNatalie Samsonov 	 */
218fe939687SNatalie Samsonov 	char *tokens[max_elems + 1];
219fe939687SNatalie Samsonov 
220fe939687SNatalie Samsonov 	/* Begin, End + error trap = 3. */
221fe939687SNatalie Samsonov 	char *rng_tokens[MAX_RNG_TOKENS + 1];
222fe939687SNatalie Samsonov 	long beg, end;
223fe939687SNatalie Samsonov 	uint32_t token_val;
224fe939687SNatalie Samsonov 	int nb_tokens, nb_rng_tokens;
225fe939687SNatalie Samsonov 	int i;
226fe939687SNatalie Samsonov 	int values = 0;
227fe939687SNatalie Samsonov 	char val;
228fe939687SNatalie Samsonov 	char entry_cpy[CFG_VALUE_LEN];
229fe939687SNatalie Samsonov 
230fe939687SNatalie Samsonov 	if (elem_sz != 1)
231fe939687SNatalie Samsonov 		return -1;
232fe939687SNatalie Samsonov 
233fe939687SNatalie Samsonov 	/* Copy the entry to safely use rte_strsplit(). */
234c022cb40SBruce Richardson 	strlcpy(entry_cpy, entry, RTE_DIM(entry_cpy));
235fe939687SNatalie Samsonov 
236fe939687SNatalie Samsonov 	/*
237fe939687SNatalie Samsonov 	 * If there are more tokens than array size, rte_strsplit will
238fe939687SNatalie Samsonov 	 * not return error, just array size.
239fe939687SNatalie Samsonov 	 */
240fe939687SNatalie Samsonov 	nb_tokens = rte_strsplit(entry_cpy, strlen(entry_cpy),
241fe939687SNatalie Samsonov 		tokens, max_elems + 1, ' ');
242fe939687SNatalie Samsonov 
243fe939687SNatalie Samsonov 	/* Quick check, will be refined later. */
244fe939687SNatalie Samsonov 	if (nb_tokens > max_elems)
245fe939687SNatalie Samsonov 		return -2;
246fe939687SNatalie Samsonov 
247fe939687SNatalie Samsonov 	for (i = 0; i < nb_tokens; ++i) {
248fe939687SNatalie Samsonov 		if (strchr(tokens[i], '-') != NULL) {
249fe939687SNatalie Samsonov 			/*
250fe939687SNatalie Samsonov 			 * Split to begin and end tokens.
251fe939687SNatalie Samsonov 			 * We want to catch error cases too, thus we leave
252fe939687SNatalie Samsonov 			 * option for number of tokens to be more than 2.
253fe939687SNatalie Samsonov 			 */
254fe939687SNatalie Samsonov 			nb_rng_tokens = rte_strsplit(tokens[i],
255fe939687SNatalie Samsonov 					strlen(tokens[i]), rng_tokens,
256fe939687SNatalie Samsonov 					RTE_DIM(rng_tokens), '-');
257fe939687SNatalie Samsonov 			if (nb_rng_tokens != 2)
258fe939687SNatalie Samsonov 				return -3;
259fe939687SNatalie Samsonov 
260fe939687SNatalie Samsonov 			/* Range and sanity checks. */
261fe939687SNatalie Samsonov 			if (get_val_securely(rng_tokens[0], &token_val) < 0)
262fe939687SNatalie Samsonov 				return -4;
263fe939687SNatalie Samsonov 			beg = (char)token_val;
264fe939687SNatalie Samsonov 			if (get_val_securely(rng_tokens[1], &token_val) < 0)
265fe939687SNatalie Samsonov 				return -4;
266fe939687SNatalie Samsonov 			end = (char)token_val;
267fe939687SNatalie Samsonov 			if (beg < 0 || beg > UCHAR_MAX ||
268fe939687SNatalie Samsonov 				end < 0 || end > UCHAR_MAX || end < beg)
269fe939687SNatalie Samsonov 				return -4;
270fe939687SNatalie Samsonov 
271fe939687SNatalie Samsonov 			for (val = beg; val <= end; ++val) {
272fe939687SNatalie Samsonov 				if (val > max_val)
273fe939687SNatalie Samsonov 					return -5;
274fe939687SNatalie Samsonov 
275fe939687SNatalie Samsonov 				*tab = val;
276fe939687SNatalie Samsonov 				tab = RTE_PTR_ADD(tab, elem_sz);
277fe939687SNatalie Samsonov 				++values;
278fe939687SNatalie Samsonov 				if (values >= max_elems)
279fe939687SNatalie Samsonov 					return -2;
280fe939687SNatalie Samsonov 			}
281fe939687SNatalie Samsonov 		} else {
282fe939687SNatalie Samsonov 			/* Single values. */
283fe939687SNatalie Samsonov 			if (get_val_securely(tokens[i], &token_val) < 0)
284fe939687SNatalie Samsonov 				return -5;
285fe939687SNatalie Samsonov 			val = (char)token_val;
286fe939687SNatalie Samsonov 			if (val > max_val)
287fe939687SNatalie Samsonov 				return -5;
288fe939687SNatalie Samsonov 
289fe939687SNatalie Samsonov 			*tab = val;
290fe939687SNatalie Samsonov 			tab = RTE_PTR_ADD(tab, elem_sz);
291fe939687SNatalie Samsonov 			++values;
292fe939687SNatalie Samsonov 			if (values >= max_elems)
293fe939687SNatalie Samsonov 				return -2;
294fe939687SNatalie Samsonov 		}
295fe939687SNatalie Samsonov 	}
296fe939687SNatalie Samsonov 
297fe939687SNatalie Samsonov 	return values;
298fe939687SNatalie Samsonov }
299fe939687SNatalie Samsonov 
300fe939687SNatalie Samsonov /**
301fe939687SNatalie Samsonov  * Parse Traffic Class'es mapping configuration.
302fe939687SNatalie Samsonov  *
303fe939687SNatalie Samsonov  * @param file Config file handle.
304fe939687SNatalie Samsonov  * @param port Which port to look for.
305fe939687SNatalie Samsonov  * @param tc Which Traffic Class to look for.
306fe939687SNatalie Samsonov  * @param cfg[out] Parsing results.
307fe939687SNatalie Samsonov  * @returns 0 in case of success, negative value otherwise.
308fe939687SNatalie Samsonov  */
309fe939687SNatalie Samsonov static int
310fe939687SNatalie Samsonov parse_tc_cfg(struct rte_cfgfile *file, int port, int tc,
311d7eb4fb2SLiron Himi 		struct mrvl_cfg *cfg)
312fe939687SNatalie Samsonov {
313fe939687SNatalie Samsonov 	char sec_name[32];
314fe939687SNatalie Samsonov 	const char *entry;
315fe939687SNatalie Samsonov 	int n;
316fe939687SNatalie Samsonov 
317fe939687SNatalie Samsonov 	snprintf(sec_name, sizeof(sec_name), "%s %d %s %d",
318fe939687SNatalie Samsonov 		MRVL_TOK_PORT, port, MRVL_TOK_TC, tc);
319fe939687SNatalie Samsonov 
320fe939687SNatalie Samsonov 	/* Skip non-existing */
321fe939687SNatalie Samsonov 	if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0)
322fe939687SNatalie Samsonov 		return 0;
323fe939687SNatalie Samsonov 
324*41c60f74SDana Vardi 	cfg->port[port].use_qos_global_defaults = 0;
325fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RXQ);
326fe939687SNatalie Samsonov 	if (entry) {
327fe939687SNatalie Samsonov 		n = get_entry_values(entry,
328fe939687SNatalie Samsonov 			cfg->port[port].tc[tc].inq,
329fe939687SNatalie Samsonov 			sizeof(cfg->port[port].tc[tc].inq[0]),
330fe939687SNatalie Samsonov 			RTE_DIM(cfg->port[port].tc[tc].inq),
331fe939687SNatalie Samsonov 			MRVL_PP2_RXQ_MAX);
332fe939687SNatalie Samsonov 		if (n < 0) {
333acab7d58STomasz Duszynski 			MRVL_LOG(ERR, "Error %d while parsing: %s",
334fe939687SNatalie Samsonov 				n, entry);
335fe939687SNatalie Samsonov 			return n;
336fe939687SNatalie Samsonov 		}
337fe939687SNatalie Samsonov 		cfg->port[port].tc[tc].inqs = n;
338fe939687SNatalie Samsonov 	}
339fe939687SNatalie Samsonov 
340fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PCP);
341fe939687SNatalie Samsonov 	if (entry) {
342fe939687SNatalie Samsonov 		n = get_entry_values(entry,
343fe939687SNatalie Samsonov 			cfg->port[port].tc[tc].pcp,
344fe939687SNatalie Samsonov 			sizeof(cfg->port[port].tc[tc].pcp[0]),
345fe939687SNatalie Samsonov 			RTE_DIM(cfg->port[port].tc[tc].pcp),
346fe939687SNatalie Samsonov 			MAX_PCP);
347fe939687SNatalie Samsonov 		if (n < 0) {
348acab7d58STomasz Duszynski 			MRVL_LOG(ERR, "Error %d while parsing: %s",
349fe939687SNatalie Samsonov 				n, entry);
350fe939687SNatalie Samsonov 			return n;
351fe939687SNatalie Samsonov 		}
352fe939687SNatalie Samsonov 		cfg->port[port].tc[tc].pcps = n;
353fe939687SNatalie Samsonov 	}
354fe939687SNatalie Samsonov 
355fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_DSCP);
356fe939687SNatalie Samsonov 	if (entry) {
357fe939687SNatalie Samsonov 		n = get_entry_values(entry,
358fe939687SNatalie Samsonov 			cfg->port[port].tc[tc].dscp,
359fe939687SNatalie Samsonov 			sizeof(cfg->port[port].tc[tc].dscp[0]),
360fe939687SNatalie Samsonov 			RTE_DIM(cfg->port[port].tc[tc].dscp),
361fe939687SNatalie Samsonov 			MAX_DSCP);
362fe939687SNatalie Samsonov 		if (n < 0) {
363acab7d58STomasz Duszynski 			MRVL_LOG(ERR, "Error %d while parsing: %s",
364fe939687SNatalie Samsonov 				n, entry);
365fe939687SNatalie Samsonov 			return n;
366fe939687SNatalie Samsonov 		}
367fe939687SNatalie Samsonov 		cfg->port[port].tc[tc].dscps = n;
368fe939687SNatalie Samsonov 	}
369fe939687SNatalie Samsonov 
370e97d8874STomasz Duszynski 	if (!cfg->port[port].setup_policer)
371e97d8874STomasz Duszynski 		return 0;
372e97d8874STomasz Duszynski 
373fe939687SNatalie Samsonov 	entry = rte_cfgfile_get_entry(file, sec_name,
374fe939687SNatalie Samsonov 			MRVL_TOK_PLCR_DEFAULT_COLOR);
375fe939687SNatalie Samsonov 	if (entry) {
376fe939687SNatalie Samsonov 		if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN,
377fe939687SNatalie Samsonov 				sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN))) {
378fe939687SNatalie Samsonov 			cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_GREEN;
379fe939687SNatalie Samsonov 		} else if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW,
380fe939687SNatalie Samsonov 				sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW))) {
381fe939687SNatalie Samsonov 			cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_YELLOW;
382fe939687SNatalie Samsonov 		} else if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_RED,
383fe939687SNatalie Samsonov 				sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_RED))) {
384fe939687SNatalie Samsonov 			cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_RED;
385fe939687SNatalie Samsonov 		} else {
386acab7d58STomasz Duszynski 			MRVL_LOG(ERR, "Error while parsing: %s", entry);
387fe939687SNatalie Samsonov 			return -1;
388fe939687SNatalie Samsonov 		}
389fe939687SNatalie Samsonov 	}
390fe939687SNatalie Samsonov 
391fe939687SNatalie Samsonov 	return 0;
392fe939687SNatalie Samsonov }
393fe939687SNatalie Samsonov 
394fe939687SNatalie Samsonov /**
395e97d8874STomasz Duszynski  * Parse default port policer.
396e97d8874STomasz Duszynski  *
397e97d8874STomasz Duszynski  * @param file Config file handle.
398e97d8874STomasz Duszynski  * @param sec_name Section name with policer configuration
399e97d8874STomasz Duszynski  * @param port Port number.
400e97d8874STomasz Duszynski  * @param cfg[out] Parsing results.
401e97d8874STomasz Duszynski  * @returns 0 in case of success, negative value otherwise.
402e97d8874STomasz Duszynski  */
403e97d8874STomasz Duszynski static int
404e97d8874STomasz Duszynski parse_policer(struct rte_cfgfile *file, int port, const char *sec_name,
405d7eb4fb2SLiron Himi 		struct mrvl_cfg *cfg)
406e97d8874STomasz Duszynski {
407e97d8874STomasz Duszynski 	const char *entry;
408e97d8874STomasz Duszynski 	uint32_t val;
409e97d8874STomasz Duszynski 
410e97d8874STomasz Duszynski 	/* Read policer token unit */
411e97d8874STomasz Duszynski 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_UNIT);
412e97d8874STomasz Duszynski 	if (entry) {
413e97d8874STomasz Duszynski 		if (!strncmp(entry, MRVL_TOK_PLCR_UNIT_BYTES,
414e97d8874STomasz Duszynski 					sizeof(MRVL_TOK_PLCR_UNIT_BYTES))) {
415e97d8874STomasz Duszynski 			cfg->port[port].policer_params.token_unit =
416e97d8874STomasz Duszynski 				PP2_CLS_PLCR_BYTES_TOKEN_UNIT;
417e97d8874STomasz Duszynski 		} else if (!strncmp(entry, MRVL_TOK_PLCR_UNIT_PACKETS,
418e97d8874STomasz Duszynski 					sizeof(MRVL_TOK_PLCR_UNIT_PACKETS))) {
419e97d8874STomasz Duszynski 			cfg->port[port].policer_params.token_unit =
420e97d8874STomasz Duszynski 				PP2_CLS_PLCR_PACKETS_TOKEN_UNIT;
421e97d8874STomasz Duszynski 		} else {
422406aeb15SYuval Caduri 			MRVL_LOG(ERR, "Unknown token: %s", entry);
423e97d8874STomasz Duszynski 			return -1;
424e97d8874STomasz Duszynski 		}
425e97d8874STomasz Duszynski 	}
426e97d8874STomasz Duszynski 
427e97d8874STomasz Duszynski 	/* Read policer color mode */
428e97d8874STomasz Duszynski 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_COLOR);
429e97d8874STomasz Duszynski 	if (entry) {
430e97d8874STomasz Duszynski 		if (!strncmp(entry, MRVL_TOK_PLCR_COLOR_BLIND,
431e97d8874STomasz Duszynski 					sizeof(MRVL_TOK_PLCR_COLOR_BLIND))) {
432e97d8874STomasz Duszynski 			cfg->port[port].policer_params.color_mode =
433e97d8874STomasz Duszynski 				PP2_CLS_PLCR_COLOR_BLIND_MODE;
434e97d8874STomasz Duszynski 		} else if (!strncmp(entry, MRVL_TOK_PLCR_COLOR_AWARE,
435e97d8874STomasz Duszynski 					sizeof(MRVL_TOK_PLCR_COLOR_AWARE))) {
436e97d8874STomasz Duszynski 			cfg->port[port].policer_params.color_mode =
437e97d8874STomasz Duszynski 				PP2_CLS_PLCR_COLOR_AWARE_MODE;
438e97d8874STomasz Duszynski 		} else {
439406aeb15SYuval Caduri 			MRVL_LOG(ERR, "Error in parsing: %s", entry);
440e97d8874STomasz Duszynski 			return -1;
441e97d8874STomasz Duszynski 		}
442e97d8874STomasz Duszynski 	}
443e97d8874STomasz Duszynski 
444e97d8874STomasz Duszynski 	/* Read policer cir */
445e97d8874STomasz Duszynski 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_CIR);
446e97d8874STomasz Duszynski 	if (entry) {
447e97d8874STomasz Duszynski 		if (get_val_securely(entry, &val) < 0)
448e97d8874STomasz Duszynski 			return -1;
449e97d8874STomasz Duszynski 		cfg->port[port].policer_params.cir = val;
450e97d8874STomasz Duszynski 	}
451e97d8874STomasz Duszynski 
452e97d8874STomasz Duszynski 	/* Read policer cbs */
453e97d8874STomasz Duszynski 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_CBS);
454e97d8874STomasz Duszynski 	if (entry) {
455e97d8874STomasz Duszynski 		if (get_val_securely(entry, &val) < 0)
456e97d8874STomasz Duszynski 			return -1;
457e97d8874STomasz Duszynski 		cfg->port[port].policer_params.cbs = val;
458e97d8874STomasz Duszynski 	}
459e97d8874STomasz Duszynski 
460e97d8874STomasz Duszynski 	/* Read policer ebs */
461e97d8874STomasz Duszynski 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_EBS);
462e97d8874STomasz Duszynski 	if (entry) {
463e97d8874STomasz Duszynski 		if (get_val_securely(entry, &val) < 0)
464e97d8874STomasz Duszynski 			return -1;
465e97d8874STomasz Duszynski 		cfg->port[port].policer_params.ebs = val;
466e97d8874STomasz Duszynski 	}
467e97d8874STomasz Duszynski 
468e97d8874STomasz Duszynski 	cfg->port[port].setup_policer = 1;
469e97d8874STomasz Duszynski 
470e97d8874STomasz Duszynski 	return 0;
471e97d8874STomasz Duszynski }
472e97d8874STomasz Duszynski 
473e97d8874STomasz Duszynski /**
4743e09b2a7SLiron Himi  * Parse parser udf.
4753e09b2a7SLiron Himi  *
4763e09b2a7SLiron Himi  * @param file Config file handle.
4773e09b2a7SLiron Himi  * @param sec_name section name
4783e09b2a7SLiron Himi  * @param udf udf index
4793e09b2a7SLiron Himi  * @param cfg[out] Parsing results.
4803e09b2a7SLiron Himi  * @returns 0 in case of success, negative value otherwise.
4813e09b2a7SLiron Himi  */
4823e09b2a7SLiron Himi static int
4833e09b2a7SLiron Himi parse_udf(struct rte_cfgfile *file, const char *sec_name, int udf,
4843e09b2a7SLiron Himi 	  struct mrvl_cfg *cfg)
4853e09b2a7SLiron Himi {
4863e09b2a7SLiron Himi 	struct pp2_parse_udf_params *udf_params;
4873e09b2a7SLiron Himi 	const char *entry, *entry_field;
4883e09b2a7SLiron Himi 	uint32_t val, i;
4893e09b2a7SLiron Himi 	uint8_t field_size;
4903e09b2a7SLiron Himi 	char malloc_name[32], tmp_arr[3];
4913e09b2a7SLiron Himi 	/* field len in chars equal to '0x' + rest of data */
4923e09b2a7SLiron Himi #define FIELD_LEN_IN_CHARS(field_size)	(uint32_t)(2 + (field_size) * 2)
4933e09b2a7SLiron Himi 
4943e09b2a7SLiron Himi 	udf_params = &cfg->pp2_cfg.prs_udfs.udfs[udf];
4953e09b2a7SLiron Himi 
4963e09b2a7SLiron Himi 	/* Read 'proto' field */
4973e09b2a7SLiron Himi 	entry = rte_cfgfile_get_entry(file, sec_name,
4983e09b2a7SLiron Himi 				      MRVL_TOK_PARSER_UDF_PROTO);
4993e09b2a7SLiron Himi 	if (!entry) {
5003e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
5013e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_PROTO);
5023e09b2a7SLiron Himi 		return -1;
5033e09b2a7SLiron Himi 	}
5043e09b2a7SLiron Himi 
5053e09b2a7SLiron Himi 	/* Read 'field' field */
5063e09b2a7SLiron Himi 	entry_field = rte_cfgfile_get_entry(file, sec_name,
5073e09b2a7SLiron Himi 				       MRVL_TOK_PARSER_UDF_FIELD);
5083e09b2a7SLiron Himi 	if (!entry_field) {
5093e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
5103e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_FIELD);
5113e09b2a7SLiron Himi 		return -1;
5123e09b2a7SLiron Himi 	}
5133e09b2a7SLiron Himi 
5143e09b2a7SLiron Himi 	if (!strncmp(entry, MRVL_TOK_PARSER_UDF_PROTO_ETH,
5153e09b2a7SLiron Himi 				sizeof(MRVL_TOK_PARSER_UDF_PROTO_ETH))) {
5163e09b2a7SLiron Himi 		udf_params->match_proto = MV_NET_PROTO_ETH;
5173e09b2a7SLiron Himi 		if (!strncmp(entry_field, MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE,
5183e09b2a7SLiron Himi 			     sizeof(MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE))) {
5193e09b2a7SLiron Himi 			udf_params->match_field.eth = MV_NET_ETH_F_TYPE;
5203e09b2a7SLiron Himi 			field_size = 2;
5213e09b2a7SLiron Himi 		} else {
5223e09b2a7SLiron Himi 			MRVL_LOG(ERR, "UDF[%d]: mismatch between '%s' proto "
5233e09b2a7SLiron Himi 				 "and '%s' field\n", udf,
5243e09b2a7SLiron Himi 				 MRVL_TOK_PARSER_UDF_PROTO_ETH,
5253e09b2a7SLiron Himi 				 entry_field);
5263e09b2a7SLiron Himi 			return -1;
5273e09b2a7SLiron Himi 		}
5283e09b2a7SLiron Himi 	} else if (!strncmp(entry, MRVL_TOK_PARSER_UDF_PROTO_UDP,
5293e09b2a7SLiron Himi 				sizeof(MRVL_TOK_PARSER_UDF_PROTO_UDP))) {
5303e09b2a7SLiron Himi 		udf_params->match_proto = MV_NET_PROTO_UDP;
5313e09b2a7SLiron Himi 		if (!strncmp(entry_field, MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT,
5323e09b2a7SLiron Himi 			     sizeof(MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT))) {
5333e09b2a7SLiron Himi 			udf_params->match_field.udp = MV_NET_UDP_F_DP;
5343e09b2a7SLiron Himi 			field_size = 2;
5353e09b2a7SLiron Himi 		} else {
5363e09b2a7SLiron Himi 			MRVL_LOG(ERR, "UDF[%d]: mismatch between '%s' proto "
5373e09b2a7SLiron Himi 				 "and '%s' field\n", udf,
5383e09b2a7SLiron Himi 				 MRVL_TOK_PARSER_UDF_PROTO_UDP,
5393e09b2a7SLiron Himi 				 entry_field);
5403e09b2a7SLiron Himi 			return -1;
5413e09b2a7SLiron Himi 		}
5423e09b2a7SLiron Himi 	} else {
5433e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: Unsupported '%s' proto\n", udf, entry);
5443e09b2a7SLiron Himi 		return -1;
5453e09b2a7SLiron Himi 	}
5463e09b2a7SLiron Himi 
5473e09b2a7SLiron Himi 	snprintf(malloc_name, sizeof(malloc_name), "mrvl_udf_%d_key", udf);
5483e09b2a7SLiron Himi 	udf_params->match_key = rte_zmalloc(malloc_name, field_size, 0);
5493e09b2a7SLiron Himi 	if (udf_params->match_key == NULL) {
5503e09b2a7SLiron Himi 		MRVL_LOG(ERR, "Cannot allocate udf %d key\n", udf);
5513e09b2a7SLiron Himi 		return -1;
5523e09b2a7SLiron Himi 	}
5533e09b2a7SLiron Himi 	snprintf(malloc_name, sizeof(malloc_name), "mrvl_udf_%d_mask", udf);
5543e09b2a7SLiron Himi 	udf_params->match_mask = rte_zmalloc(malloc_name, field_size, 0);
5553e09b2a7SLiron Himi 	if (udf_params->match_mask == NULL) {
5563e09b2a7SLiron Himi 		MRVL_LOG(ERR, "Cannot allocate udf %d mask\n", udf);
5573e09b2a7SLiron Himi 		return -1;
5583e09b2a7SLiron Himi 	}
5593e09b2a7SLiron Himi 
5603e09b2a7SLiron Himi 	/* Read 'key' field */
5613e09b2a7SLiron Himi 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PARSER_UDF_KEY);
5623e09b2a7SLiron Himi 	if (!entry) {
5633e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
5643e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_KEY);
5653e09b2a7SLiron Himi 		return -1;
5663e09b2a7SLiron Himi 	}
5673e09b2a7SLiron Himi 
5683e09b2a7SLiron Himi 	if (strncmp(entry, "0x", 2) != 0)  {
5693e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must start with '0x'\n",
5703e09b2a7SLiron Himi 			 udf, MRVL_TOK_PARSER_UDF_KEY);
5713e09b2a7SLiron Himi 		return -EINVAL;
5723e09b2a7SLiron Himi 	}
5733e09b2a7SLiron Himi 
5743e09b2a7SLiron Himi 	if (strlen(entry) != FIELD_LEN_IN_CHARS(field_size)) {
5753e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field's len must be %d\n", udf,
5763e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_KEY,
5773e09b2a7SLiron Himi 			 FIELD_LEN_IN_CHARS(field_size));
5783e09b2a7SLiron Himi 		return -EINVAL;
5793e09b2a7SLiron Himi 	}
5803e09b2a7SLiron Himi 
5813e09b2a7SLiron Himi 	entry += 2; /* skip the '0x' */
5823e09b2a7SLiron Himi 	for (i = 0; i < field_size; i++) {
5833e09b2a7SLiron Himi 		strncpy(tmp_arr, entry, 2);
5843e09b2a7SLiron Himi 		tmp_arr[2] = '\0';
5853e09b2a7SLiron Himi 		if (get_val_securely8(tmp_arr, 16,
5863e09b2a7SLiron Himi 				      &udf_params->match_key[i]) < 0) {
5873e09b2a7SLiron Himi 			MRVL_LOG(ERR, "UDF[%d]: '%s' field's value is not in "
5883e09b2a7SLiron Himi 				"hex format\n", udf, MRVL_TOK_PARSER_UDF_KEY);
5893e09b2a7SLiron Himi 			return -EINVAL;
5903e09b2a7SLiron Himi 		}
5913e09b2a7SLiron Himi 		entry += 2;
5923e09b2a7SLiron Himi 	}
5933e09b2a7SLiron Himi 
5943e09b2a7SLiron Himi 	/* Read 'mask' field */
5953e09b2a7SLiron Himi 	entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PARSER_UDF_MASK);
5963e09b2a7SLiron Himi 	if (!entry) {
5973e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
5983e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_MASK);
5993e09b2a7SLiron Himi 		return -1;
6003e09b2a7SLiron Himi 	}
6013e09b2a7SLiron Himi 	if (strncmp(entry, "0x", 2) != 0) {
6023e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must start with '0x'\n",
6033e09b2a7SLiron Himi 			 udf, MRVL_TOK_PARSER_UDF_MASK);
6043e09b2a7SLiron Himi 		return -EINVAL;
6053e09b2a7SLiron Himi 	}
6063e09b2a7SLiron Himi 
6073e09b2a7SLiron Himi 	if (strlen(entry) != FIELD_LEN_IN_CHARS(field_size)) {
6083e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field's len must be %d\n", udf,
6093e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_MASK,
6103e09b2a7SLiron Himi 			 FIELD_LEN_IN_CHARS(field_size));
6113e09b2a7SLiron Himi 		return -EINVAL;
6123e09b2a7SLiron Himi 	}
6133e09b2a7SLiron Himi 
6143e09b2a7SLiron Himi 	entry += 2; /* skip the '0x' */
6153e09b2a7SLiron Himi 	for (i = 0; i < field_size; i++) {
6163e09b2a7SLiron Himi 		strncpy(tmp_arr, entry, 2);
6173e09b2a7SLiron Himi 		tmp_arr[2] = '\0';
6183e09b2a7SLiron Himi 		if (get_val_securely8(tmp_arr, 16,
6193e09b2a7SLiron Himi 				      &udf_params->match_mask[i]) < 0) {
6203e09b2a7SLiron Himi 			MRVL_LOG(ERR, "UDF[%d]: '%s' field's value is not in "
6213e09b2a7SLiron Himi 				"hex format\n", udf, MRVL_TOK_PARSER_UDF_MASK);
6223e09b2a7SLiron Himi 			return -EINVAL;
6233e09b2a7SLiron Himi 		}
6243e09b2a7SLiron Himi 		entry += 2;
6253e09b2a7SLiron Himi 	}
6263e09b2a7SLiron Himi 
6273e09b2a7SLiron Himi 	/* Read offset */
6283e09b2a7SLiron Himi 	entry = rte_cfgfile_get_entry(file, sec_name,
6293e09b2a7SLiron Himi 				      MRVL_TOK_PARSER_UDF_OFFSET);
6303e09b2a7SLiron Himi 	if (!entry) {
6313e09b2a7SLiron Himi 		MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
6323e09b2a7SLiron Himi 			 MRVL_TOK_PARSER_UDF_OFFSET);
6333e09b2a7SLiron Himi 		return -1;
6343e09b2a7SLiron Himi 	}
6353e09b2a7SLiron Himi 	if (get_val_securely(entry, &val) < 0)
6363e09b2a7SLiron Himi 		return -1;
6373e09b2a7SLiron Himi 	udf_params->offset = val;
6383e09b2a7SLiron Himi 
6393e09b2a7SLiron Himi 	return 0;
6403e09b2a7SLiron Himi }
6413e09b2a7SLiron Himi 
6423e09b2a7SLiron Himi /**
643d7eb4fb2SLiron Himi  * Parse configuration - rte_kvargs_process handler.
644fe939687SNatalie Samsonov  *
645fe939687SNatalie Samsonov  * Opens configuration file and parses its content.
646fe939687SNatalie Samsonov  *
647fe939687SNatalie Samsonov  * @param key Unused.
648fe939687SNatalie Samsonov  * @param path Path to config file.
649fe939687SNatalie Samsonov  * @param extra_args Pointer to configuration structure.
650fe939687SNatalie Samsonov  * @returns 0 in case of success, exits otherwise.
651fe939687SNatalie Samsonov  */
652fe939687SNatalie Samsonov int
653d7eb4fb2SLiron Himi mrvl_get_cfg(const char *key __rte_unused, const char *path, void *extra_args)
654fe939687SNatalie Samsonov {
655d7eb4fb2SLiron Himi 	struct mrvl_cfg **cfg = extra_args;
656fe939687SNatalie Samsonov 	struct rte_cfgfile *file = rte_cfgfile_load(path, 0);
657fe939687SNatalie Samsonov 	uint32_t val;
658fe939687SNatalie Samsonov 	int n, i, ret;
659fe939687SNatalie Samsonov 	const char *entry;
660fe939687SNatalie Samsonov 	char sec_name[32];
661fe939687SNatalie Samsonov 
662c2b5ae61SLiron Himi 	if (file == NULL) {
663c2b5ae61SLiron Himi 		MRVL_LOG(ERR, "Cannot load configuration %s\n", path);
664c2b5ae61SLiron Himi 		return -1;
665c2b5ae61SLiron Himi 	}
666fe939687SNatalie Samsonov 
667fe939687SNatalie Samsonov 	/* Create configuration. This is never accessed on the fast path,
668fe939687SNatalie Samsonov 	 * so we can ignore socket.
669fe939687SNatalie Samsonov 	 */
670d7eb4fb2SLiron Himi 	*cfg = rte_zmalloc("mrvl_cfg", sizeof(struct mrvl_cfg), 0);
671c2b5ae61SLiron Himi 	if (*cfg == NULL) {
672c2b5ae61SLiron Himi 		MRVL_LOG(ERR, "Cannot allocate configuration %s\n", path);
673c2b5ae61SLiron Himi 		return -1;
674c2b5ae61SLiron Himi 	}
675fe939687SNatalie Samsonov 
6763e09b2a7SLiron Himi 	/* PP2 configuration */
6773e09b2a7SLiron Himi 	n = rte_cfgfile_num_sections(file, MRVL_TOK_PARSER_UDF,
6783e09b2a7SLiron Himi 		sizeof(MRVL_TOK_PARSER_UDF) - 1);
6793e09b2a7SLiron Himi 
6803e09b2a7SLiron Himi 	if (n && n > PP2_MAX_UDFS_SUPPORTED) {
6813e09b2a7SLiron Himi 		MRVL_LOG(ERR, "found %d udf sections, but only %d are supported\n",
6823e09b2a7SLiron Himi 			 n, PP2_MAX_UDFS_SUPPORTED);
6833e09b2a7SLiron Himi 		return -1;
6843e09b2a7SLiron Himi 	}
6853e09b2a7SLiron Himi 	(*cfg)->pp2_cfg.prs_udfs.num_udfs = n;
6863e09b2a7SLiron Himi 	for (i = 0; i < n; i++) {
6873e09b2a7SLiron Himi 		snprintf(sec_name, sizeof(sec_name), "%s %d",
6883e09b2a7SLiron Himi 				MRVL_TOK_PARSER_UDF, i);
6893e09b2a7SLiron Himi 
6903e09b2a7SLiron Himi 		/* udf sections must be sequential. */
6913e09b2a7SLiron Himi 		if (rte_cfgfile_num_sections(file, sec_name,
6923e09b2a7SLiron Himi 				strlen(sec_name)) <= 0) {
6933e09b2a7SLiron Himi 			MRVL_LOG(ERR, "udf sections must be sequential (0 - %d)\n",
6943e09b2a7SLiron Himi 				 PP2_MAX_UDFS_SUPPORTED - 1);
6953e09b2a7SLiron Himi 			return -1;
6963e09b2a7SLiron Himi 		}
6973e09b2a7SLiron Himi 
6983e09b2a7SLiron Himi 		ret = parse_udf(file, sec_name, i, *cfg);
6993e09b2a7SLiron Himi 		if (ret) {
7003e09b2a7SLiron Himi 			MRVL_LOG(ERR, "Error in parsing %s!\n", sec_name);
7013e09b2a7SLiron Himi 			return -1;
7023e09b2a7SLiron Himi 		}
7033e09b2a7SLiron Himi 	}
7043e09b2a7SLiron Himi 
7053e09b2a7SLiron Himi 	/* PP2 Ports configuration */
706fe939687SNatalie Samsonov 	n = rte_cfgfile_num_sections(file, MRVL_TOK_PORT,
707fe939687SNatalie Samsonov 		sizeof(MRVL_TOK_PORT) - 1);
708fe939687SNatalie Samsonov 
709fe939687SNatalie Samsonov 	if (n == 0) {
710fe939687SNatalie Samsonov 		/* This is weird, but not bad. */
711acab7d58STomasz Duszynski 		MRVL_LOG(WARNING, "Empty configuration file?");
712fe939687SNatalie Samsonov 		return 0;
713fe939687SNatalie Samsonov 	}
714fe939687SNatalie Samsonov 
715fe939687SNatalie Samsonov 	/* Use the number of ports given as vdev parameters. */
716fe939687SNatalie Samsonov 	for (n = 0; n < (PP2_NUM_ETH_PPIO * PP2_NUM_PKT_PROC); ++n) {
717fe939687SNatalie Samsonov 		snprintf(sec_name, sizeof(sec_name), "%s %d %s",
718fe939687SNatalie Samsonov 			MRVL_TOK_PORT, n, MRVL_TOK_DEFAULT);
719fe939687SNatalie Samsonov 
720406aeb15SYuval Caduri 		/* Use global defaults, unless an override occurs */
721*41c60f74SDana Vardi 		(*cfg)->port[n].use_qos_global_defaults = 1;
722406aeb15SYuval Caduri 
723fe939687SNatalie Samsonov 		/* Skip ports non-existing in configuration. */
724fe939687SNatalie Samsonov 		if (rte_cfgfile_num_sections(file, sec_name,
725fe939687SNatalie Samsonov 				strlen(sec_name)) <= 0) {
726fe939687SNatalie Samsonov 			continue;
727fe939687SNatalie Samsonov 		}
728fe939687SNatalie Samsonov 
7296000b5beSDana Vardi 		/* MRVL_TOK_START_HDR replaces MRVL_TOK_DSA_MODE parameter.
7306000b5beSDana Vardi 		 * MRVL_TOK_DSA_MODE will be supported for backward
7316000b5beSDana Vardi 		 * compatibillity.
7326000b5beSDana Vardi 		 */
7336000b5beSDana Vardi 		entry = rte_cfgfile_get_entry(file, sec_name,
7346000b5beSDana Vardi 				MRVL_TOK_START_HDR);
7356000b5beSDana Vardi 		/* if start_hsr is missing, check if dsa_mode exist instead */
7366000b5beSDana Vardi 		if (entry == NULL)
737c2b5ae61SLiron Himi 			entry = rte_cfgfile_get_entry(file, sec_name,
738c2b5ae61SLiron Himi 				MRVL_TOK_DSA_MODE);
739c2b5ae61SLiron Himi 		if (entry) {
7406000b5beSDana Vardi 			if (!strncmp(entry, MRVL_TOK_START_HDR_NONE,
7416000b5beSDana Vardi 				sizeof(MRVL_TOK_START_HDR_NONE)))
742c2b5ae61SLiron Himi 				(*cfg)->port[n].eth_start_hdr =
743c2b5ae61SLiron Himi 				PP2_PPIO_HDR_ETH;
7446000b5beSDana Vardi 			else if (!strncmp(entry, MRVL_TOK_START_HDR_DSA,
7456000b5beSDana Vardi 				sizeof(MRVL_TOK_START_HDR_DSA)))
746c2b5ae61SLiron Himi 				(*cfg)->port[n].eth_start_hdr =
747c2b5ae61SLiron Himi 				PP2_PPIO_HDR_ETH_DSA;
74821aa25e0SDana Vardi 			else if (!strncmp(entry, MRVL_TOK_START_HDR_CUSTOM,
74921aa25e0SDana Vardi 				sizeof(MRVL_TOK_START_HDR_CUSTOM)))
75021aa25e0SDana Vardi 				(*cfg)->port[n].eth_start_hdr =
75121aa25e0SDana Vardi 				PP2_PPIO_HDR_ETH_CUSTOM;
7526000b5beSDana Vardi 			else if (!strncmp(entry, MRVL_TOK_START_HDR_EXT_DSA,
7536000b5beSDana Vardi 				sizeof(MRVL_TOK_START_HDR_EXT_DSA))) {
754c2b5ae61SLiron Himi 				(*cfg)->port[n].eth_start_hdr =
755c2b5ae61SLiron Himi 				PP2_PPIO_HDR_ETH_EXT_DSA;
756c2b5ae61SLiron Himi 			} else {
757c2b5ae61SLiron Himi 				MRVL_LOG(ERR,
758c2b5ae61SLiron Himi 					"Error in parsing %s value (%s)!\n",
7596000b5beSDana Vardi 					MRVL_TOK_START_HDR, entry);
760c2b5ae61SLiron Himi 				return -1;
761c2b5ae61SLiron Himi 			}
762c2b5ae61SLiron Himi 		} else {
763c2b5ae61SLiron Himi 			(*cfg)->port[n].eth_start_hdr = PP2_PPIO_HDR_ETH;
764c2b5ae61SLiron Himi 		}
765c2b5ae61SLiron Himi 
766fe939687SNatalie Samsonov 		/*
767fe939687SNatalie Samsonov 		 * Read per-port rate limiting. Setting that will
768fe939687SNatalie Samsonov 		 * disable per-queue rate limiting.
769fe939687SNatalie Samsonov 		 */
770fe939687SNatalie Samsonov 		entry = rte_cfgfile_get_entry(file, sec_name,
771fe939687SNatalie Samsonov 				MRVL_TOK_RATE_LIMIT_ENABLE);
772fe939687SNatalie Samsonov 		if (entry) {
773fe939687SNatalie Samsonov 			if (get_val_securely(entry, &val) < 0)
774fe939687SNatalie Samsonov 				return -1;
775fe939687SNatalie Samsonov 			(*cfg)->port[n].rate_limit_enable = val;
776fe939687SNatalie Samsonov 		}
777fe939687SNatalie Samsonov 
778fe939687SNatalie Samsonov 		if ((*cfg)->port[n].rate_limit_enable) {
779fe939687SNatalie Samsonov 			entry = rte_cfgfile_get_entry(file, sec_name,
780fe939687SNatalie Samsonov 					MRVL_TOK_BURST_SIZE);
781fe939687SNatalie Samsonov 			if (entry) {
782fe939687SNatalie Samsonov 				if (get_val_securely(entry, &val) < 0)
783fe939687SNatalie Samsonov 					return -1;
784fe939687SNatalie Samsonov 				(*cfg)->port[n].rate_limit_params.cbs = val;
785fe939687SNatalie Samsonov 			}
786fe939687SNatalie Samsonov 
787fe939687SNatalie Samsonov 			entry = rte_cfgfile_get_entry(file, sec_name,
788fe939687SNatalie Samsonov 					MRVL_TOK_RATE_LIMIT);
789fe939687SNatalie Samsonov 			if (entry) {
790fe939687SNatalie Samsonov 				if (get_val_securely(entry, &val) < 0)
791fe939687SNatalie Samsonov 					return -1;
792fe939687SNatalie Samsonov 				(*cfg)->port[n].rate_limit_params.cir = val;
793fe939687SNatalie Samsonov 			}
794fe939687SNatalie Samsonov 		}
795fe939687SNatalie Samsonov 
796fe939687SNatalie Samsonov 		entry = rte_cfgfile_get_entry(file, sec_name,
797fe939687SNatalie Samsonov 				MRVL_TOK_MAPPING_PRIORITY);
798fe939687SNatalie Samsonov 		if (entry) {
799*41c60f74SDana Vardi 			(*cfg)->port[n].use_qos_global_defaults = 0;
800fe939687SNatalie Samsonov 			if (!strncmp(entry, MRVL_TOK_VLAN_IP,
801fe939687SNatalie Samsonov 				sizeof(MRVL_TOK_VLAN_IP)))
802fe939687SNatalie Samsonov 				(*cfg)->port[n].mapping_priority =
803fe939687SNatalie Samsonov 					PP2_CLS_QOS_TBL_VLAN_IP_PRI;
804fe939687SNatalie Samsonov 			else if (!strncmp(entry, MRVL_TOK_IP_VLAN,
805fe939687SNatalie Samsonov 				sizeof(MRVL_TOK_IP_VLAN)))
806fe939687SNatalie Samsonov 				(*cfg)->port[n].mapping_priority =
807fe939687SNatalie Samsonov 					PP2_CLS_QOS_TBL_IP_VLAN_PRI;
808fe939687SNatalie Samsonov 			else if (!strncmp(entry, MRVL_TOK_IP,
809fe939687SNatalie Samsonov 				sizeof(MRVL_TOK_IP)))
810fe939687SNatalie Samsonov 				(*cfg)->port[n].mapping_priority =
811fe939687SNatalie Samsonov 					PP2_CLS_QOS_TBL_IP_PRI;
812fe939687SNatalie Samsonov 			else if (!strncmp(entry, MRVL_TOK_VLAN,
813c2b5ae61SLiron Himi 				sizeof(MRVL_TOK_VLAN))) {
814fe939687SNatalie Samsonov 				(*cfg)->port[n].mapping_priority =
815fe939687SNatalie Samsonov 					PP2_CLS_QOS_TBL_VLAN_PRI;
816c2b5ae61SLiron Himi 			} else {
817c2b5ae61SLiron Himi 				MRVL_LOG(ERR,
818fe939687SNatalie Samsonov 					"Error in parsing %s value (%s)!\n",
819fe939687SNatalie Samsonov 					MRVL_TOK_MAPPING_PRIORITY, entry);
820c2b5ae61SLiron Himi 				return -1;
821c2b5ae61SLiron Himi 			}
822fe939687SNatalie Samsonov 		} else {
823fe939687SNatalie Samsonov 			(*cfg)->port[n].mapping_priority =
82455e429acSLiron Himi 				PP2_CLS_QOS_TBL_NONE;
825fe939687SNatalie Samsonov 		}
826fe939687SNatalie Samsonov 
827e97d8874STomasz Duszynski 		/* Parse policer configuration (if any) */
828e97d8874STomasz Duszynski 		entry = rte_cfgfile_get_entry(file, sec_name,
829e97d8874STomasz Duszynski 				MRVL_TOK_PLCR_DEFAULT);
830e97d8874STomasz Duszynski 		if (entry) {
831*41c60f74SDana Vardi 			(*cfg)->port[n].use_qos_global_defaults = 0;
832e97d8874STomasz Duszynski 			if (get_val_securely(entry, &val) < 0)
833e97d8874STomasz Duszynski 				return -1;
834e97d8874STomasz Duszynski 
835e97d8874STomasz Duszynski 			snprintf(sec_name, sizeof(sec_name), "%s %d",
836e97d8874STomasz Duszynski 					MRVL_TOK_PLCR, val);
837e97d8874STomasz Duszynski 			ret = parse_policer(file, n, sec_name, *cfg);
838e97d8874STomasz Duszynski 			if (ret)
839e97d8874STomasz Duszynski 				return -1;
840e97d8874STomasz Duszynski 		}
841e97d8874STomasz Duszynski 
842fe939687SNatalie Samsonov 		for (i = 0; i < MRVL_PP2_RXQ_MAX; ++i) {
843fe939687SNatalie Samsonov 			ret = get_outq_cfg(file, n, i, *cfg);
844c2b5ae61SLiron Himi 			if (ret < 0) {
845c2b5ae61SLiron Himi 				MRVL_LOG(ERR,
846fe939687SNatalie Samsonov 					"Error %d parsing port %d outq %d!\n",
847fe939687SNatalie Samsonov 					ret, n, i);
848c2b5ae61SLiron Himi 				return -1;
849c2b5ae61SLiron Himi 			}
850fe939687SNatalie Samsonov 		}
851fe939687SNatalie Samsonov 
852fe939687SNatalie Samsonov 		for (i = 0; i < MRVL_PP2_TC_MAX; ++i) {
853fe939687SNatalie Samsonov 			ret = parse_tc_cfg(file, n, i, *cfg);
854c2b5ae61SLiron Himi 			if (ret < 0) {
855c2b5ae61SLiron Himi 				MRVL_LOG(ERR,
856fe939687SNatalie Samsonov 					"Error %d parsing port %d tc %d!\n",
857fe939687SNatalie Samsonov 					ret, n, i);
858c2b5ae61SLiron Himi 				return -1;
859c2b5ae61SLiron Himi 			}
860fe939687SNatalie Samsonov 		}
861406aeb15SYuval Caduri 
862406aeb15SYuval Caduri 		entry = rte_cfgfile_get_entry(file, sec_name,
863406aeb15SYuval Caduri 					      MRVL_TOK_DEFAULT_TC);
864406aeb15SYuval Caduri 		if (entry) {
865406aeb15SYuval Caduri 			if (get_val_securely(entry, &val) < 0 ||
866406aeb15SYuval Caduri 			    val > USHRT_MAX)
867406aeb15SYuval Caduri 				return -1;
868406aeb15SYuval Caduri 			(*cfg)->port[n].default_tc = (uint8_t)val;
869406aeb15SYuval Caduri 		} else {
870*41c60f74SDana Vardi 			if ((*cfg)->port[n].use_qos_global_defaults == 0) {
871406aeb15SYuval Caduri 				MRVL_LOG(ERR,
872c2b5ae61SLiron Himi 					 "Default Traffic Class required in "
873c2b5ae61SLiron Himi 					 "custom configuration!");
874406aeb15SYuval Caduri 				return -1;
875406aeb15SYuval Caduri 			}
876406aeb15SYuval Caduri 		}
877ef08031fSDana Vardi 
878ef08031fSDana Vardi 		/* Parse forward bad frames option */
879ef08031fSDana Vardi 		entry = rte_cfgfile_get_entry(file, sec_name,
880ef08031fSDana Vardi 				MRVL_TOK_FWD_BAD_FRAMES);
881ef08031fSDana Vardi 		if (entry) {
882ef08031fSDana Vardi 			if (get_val_securely(entry, &val) < 0) {
883ef08031fSDana Vardi 				MRVL_LOG(ERR,
884ef08031fSDana Vardi 					"Error in parsing %s value (%s)!\n",
885ef08031fSDana Vardi 					MRVL_TOK_FWD_BAD_FRAMES, entry);
886ef08031fSDana Vardi 				return -1;
887ef08031fSDana Vardi 			}
888ef08031fSDana Vardi 			(*cfg)->port[n].forward_bad_frames = (uint8_t)val;
889ef08031fSDana Vardi 		} else {
890ef08031fSDana Vardi 			(*cfg)->port[n].forward_bad_frames = 0;
891ef08031fSDana Vardi 		}
892fe939687SNatalie Samsonov 	}
893fe939687SNatalie Samsonov 
894fe939687SNatalie Samsonov 	return 0;
895fe939687SNatalie Samsonov }
896fe939687SNatalie Samsonov 
897fe939687SNatalie Samsonov /**
898fe939687SNatalie Samsonov  * Setup Traffic Class.
899fe939687SNatalie Samsonov  *
900fe939687SNatalie Samsonov  * Fill in TC parameters in single MUSDK TC config entry.
901fe939687SNatalie Samsonov  * @param param TC parameters entry.
902fe939687SNatalie Samsonov  * @param inqs Number of MUSDK in-queues in this TC.
903fe939687SNatalie Samsonov  * @param bpool Bpool for this TC.
904fe939687SNatalie Samsonov  * @param color Default color for this TC.
905fe939687SNatalie Samsonov  * @returns 0 in case of success, exits otherwise.
906fe939687SNatalie Samsonov  */
907fe939687SNatalie Samsonov static int
908fe939687SNatalie Samsonov setup_tc(struct pp2_ppio_tc_params *param, uint8_t inqs,
909fe939687SNatalie Samsonov 	struct pp2_bpool *bpool, enum pp2_ppio_color color)
910fe939687SNatalie Samsonov {
911fe939687SNatalie Samsonov 	struct pp2_ppio_inq_params *inq_params;
912fe939687SNatalie Samsonov 
913fe939687SNatalie Samsonov 	param->pkt_offset = MRVL_PKT_OFFS;
914e04ec42aSTomasz Duszynski 	param->pools[0][0] = bpool;
91530d30720SLiron Himi 	param->pools[0][1] = dummy_pool[bpool->pp2_id];
916fe939687SNatalie Samsonov 	param->default_color = color;
917fe939687SNatalie Samsonov 
918fe939687SNatalie Samsonov 	inq_params = rte_zmalloc_socket("inq_params",
919fe939687SNatalie Samsonov 		inqs * sizeof(*inq_params),
920fe939687SNatalie Samsonov 		0, rte_socket_id());
921fe939687SNatalie Samsonov 	if (!inq_params)
922fe939687SNatalie Samsonov 		return -ENOMEM;
923fe939687SNatalie Samsonov 
924fe939687SNatalie Samsonov 	param->num_in_qs = inqs;
925fe939687SNatalie Samsonov 
926fe939687SNatalie Samsonov 	/* Release old config if necessary. */
927fe939687SNatalie Samsonov 	if (param->inqs_params)
928fe939687SNatalie Samsonov 		rte_free(param->inqs_params);
929fe939687SNatalie Samsonov 
930fe939687SNatalie Samsonov 	param->inqs_params = inq_params;
931fe939687SNatalie Samsonov 
932fe939687SNatalie Samsonov 	return 0;
933fe939687SNatalie Samsonov }
934fe939687SNatalie Samsonov 
935fe939687SNatalie Samsonov /**
936fe939687SNatalie Samsonov  * Setup ingress policer.
937fe939687SNatalie Samsonov  *
938fe939687SNatalie Samsonov  * @param priv Port's private data.
939fe939687SNatalie Samsonov  * @param params Pointer to the policer's configuration.
940e97d8874STomasz Duszynski  * @param plcr_id Policer id.
941fe939687SNatalie Samsonov  * @returns 0 in case of success, negative values otherwise.
942fe939687SNatalie Samsonov  */
943fe939687SNatalie Samsonov static int
944fe939687SNatalie Samsonov setup_policer(struct mrvl_priv *priv, struct pp2_cls_plcr_params *params)
945fe939687SNatalie Samsonov {
946fe939687SNatalie Samsonov 	char match[16];
947fe939687SNatalie Samsonov 	int ret;
948fe939687SNatalie Samsonov 
949e97d8874STomasz Duszynski 	/*
950e97d8874STomasz Duszynski 	 * At this point no other policers are used which means
951e97d8874STomasz Duszynski 	 * any policer can be picked up and used as a default one.
952e97d8874STomasz Duszynski 	 *
953e97d8874STomasz Duszynski 	 * Lets use 0th then.
954e97d8874STomasz Duszynski 	 */
955e97d8874STomasz Duszynski 	sprintf(match, "policer-%d:%d\n", priv->pp_id, 0);
956fe939687SNatalie Samsonov 	params->match = match;
957fe939687SNatalie Samsonov 
958e97d8874STomasz Duszynski 	ret = pp2_cls_plcr_init(params, &priv->default_policer);
959fe939687SNatalie Samsonov 	if (ret) {
960acab7d58STomasz Duszynski 		MRVL_LOG(ERR, "Failed to setup %s", match);
961fe939687SNatalie Samsonov 		return -1;
962fe939687SNatalie Samsonov 	}
963fe939687SNatalie Samsonov 
964e97d8874STomasz Duszynski 	priv->ppio_params.inqs_params.plcr = priv->default_policer;
965e97d8874STomasz Duszynski 	priv->used_plcrs = BIT(0);
966fe939687SNatalie Samsonov 
967fe939687SNatalie Samsonov 	return 0;
968fe939687SNatalie Samsonov }
969fe939687SNatalie Samsonov 
970fe939687SNatalie Samsonov /**
971fe939687SNatalie Samsonov  * Configure RX Queues in a given port.
972fe939687SNatalie Samsonov  *
973fe939687SNatalie Samsonov  * Sets up RX queues, their Traffic Classes and DPDK rxq->(TC,inq) mapping.
974fe939687SNatalie Samsonov  *
975fe939687SNatalie Samsonov  * @param priv Port's private data
976fe939687SNatalie Samsonov  * @param portid DPDK port ID
977fe939687SNatalie Samsonov  * @param max_queues Maximum number of queues to configure.
978fe939687SNatalie Samsonov  * @returns 0 in case of success, negative value otherwise.
979fe939687SNatalie Samsonov  */
980fe939687SNatalie Samsonov int
981fe939687SNatalie Samsonov mrvl_configure_rxqs(struct mrvl_priv *priv, uint16_t portid,
982fe939687SNatalie Samsonov 	uint16_t max_queues)
983fe939687SNatalie Samsonov {
984fe939687SNatalie Samsonov 	size_t i, tc;
985fe939687SNatalie Samsonov 
986d7eb4fb2SLiron Himi 	if (mrvl_cfg == NULL ||
987*41c60f74SDana Vardi 		mrvl_cfg->port[portid].use_qos_global_defaults) {
988fe939687SNatalie Samsonov 		/*
989fe939687SNatalie Samsonov 		 * No port configuration, use default: 1 TC, no QoS,
990fe939687SNatalie Samsonov 		 * TC color set to green.
991fe939687SNatalie Samsonov 		 */
992fe939687SNatalie Samsonov 		priv->ppio_params.inqs_params.num_tcs = 1;
993fe939687SNatalie Samsonov 		setup_tc(&priv->ppio_params.inqs_params.tcs_params[0],
994fe939687SNatalie Samsonov 			max_queues, priv->bpool, PP2_PPIO_COLOR_GREEN);
995fe939687SNatalie Samsonov 
996fe939687SNatalie Samsonov 		/* Direct mapping of queues i.e. 0->0, 1->1 etc. */
997fe939687SNatalie Samsonov 		for (i = 0; i < max_queues; ++i) {
998fe939687SNatalie Samsonov 			priv->rxq_map[i].tc = 0;
999fe939687SNatalie Samsonov 			priv->rxq_map[i].inq = i;
1000fe939687SNatalie Samsonov 		}
1001fe939687SNatalie Samsonov 		return 0;
1002fe939687SNatalie Samsonov 	}
1003fe939687SNatalie Samsonov 
1004fe939687SNatalie Samsonov 	/* We need only a subset of configuration. */
1005d7eb4fb2SLiron Himi 	struct port_cfg *port_cfg = &mrvl_cfg->port[portid];
1006fe939687SNatalie Samsonov 
1007fe939687SNatalie Samsonov 	priv->qos_tbl_params.type = port_cfg->mapping_priority;
1008fe939687SNatalie Samsonov 
1009fe939687SNatalie Samsonov 	/*
1010fe939687SNatalie Samsonov 	 * We need to reverse mapping, from tc->pcp (better from usability
1011fe939687SNatalie Samsonov 	 * point of view) to pcp->tc (configurable in MUSDK).
1012fe939687SNatalie Samsonov 	 * First, set all map elements to "default".
1013fe939687SNatalie Samsonov 	 */
1014fe939687SNatalie Samsonov 	for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i)
1015fe939687SNatalie Samsonov 		priv->qos_tbl_params.pcp_cos_map[i].tc = port_cfg->default_tc;
1016fe939687SNatalie Samsonov 
1017fe939687SNatalie Samsonov 	/* Then, fill in all known values. */
1018fe939687SNatalie Samsonov 	for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
1019fe939687SNatalie Samsonov 		if (port_cfg->tc[tc].pcps > RTE_DIM(port_cfg->tc[0].pcp)) {
1020fe939687SNatalie Samsonov 			/* Better safe than sorry. */
1021acab7d58STomasz Duszynski 			MRVL_LOG(ERR,
1022acab7d58STomasz Duszynski 				"Too many PCPs configured in TC %zu!", tc);
1023fe939687SNatalie Samsonov 			return -1;
1024fe939687SNatalie Samsonov 		}
1025fe939687SNatalie Samsonov 		for (i = 0; i < port_cfg->tc[tc].pcps; ++i) {
1026fe939687SNatalie Samsonov 			priv->qos_tbl_params.pcp_cos_map[
1027fe939687SNatalie Samsonov 			  port_cfg->tc[tc].pcp[i]].tc = tc;
1028fe939687SNatalie Samsonov 		}
1029fe939687SNatalie Samsonov 	}
1030fe939687SNatalie Samsonov 
1031fe939687SNatalie Samsonov 	/*
1032fe939687SNatalie Samsonov 	 * The same logic goes with DSCP.
1033fe939687SNatalie Samsonov 	 * First, set all map elements to "default".
1034fe939687SNatalie Samsonov 	 */
1035fe939687SNatalie Samsonov 	for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i)
1036fe939687SNatalie Samsonov 		priv->qos_tbl_params.dscp_cos_map[i].tc =
1037fe939687SNatalie Samsonov 			port_cfg->default_tc;
1038fe939687SNatalie Samsonov 
1039fe939687SNatalie Samsonov 	/* Fill in all known values. */
1040fe939687SNatalie Samsonov 	for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
1041fe939687SNatalie Samsonov 		if (port_cfg->tc[tc].dscps > RTE_DIM(port_cfg->tc[0].dscp)) {
1042fe939687SNatalie Samsonov 			/* Better safe than sorry. */
1043acab7d58STomasz Duszynski 			MRVL_LOG(ERR,
1044acab7d58STomasz Duszynski 				"Too many DSCPs configured in TC %zu!", tc);
1045fe939687SNatalie Samsonov 			return -1;
1046fe939687SNatalie Samsonov 		}
1047fe939687SNatalie Samsonov 		for (i = 0; i < port_cfg->tc[tc].dscps; ++i) {
1048fe939687SNatalie Samsonov 			priv->qos_tbl_params.dscp_cos_map[
1049fe939687SNatalie Samsonov 			  port_cfg->tc[tc].dscp[i]].tc = tc;
1050fe939687SNatalie Samsonov 		}
1051fe939687SNatalie Samsonov 	}
1052fe939687SNatalie Samsonov 
1053fe939687SNatalie Samsonov 	/*
1054fe939687SNatalie Samsonov 	 * Surprisingly, similar logic goes with queue mapping.
1055fe939687SNatalie Samsonov 	 * We need only to store qid->tc mapping,
1056fe939687SNatalie Samsonov 	 * to know TC when queue is read.
1057fe939687SNatalie Samsonov 	 */
1058fe939687SNatalie Samsonov 	for (i = 0; i < RTE_DIM(priv->rxq_map); ++i)
1059fe939687SNatalie Samsonov 		priv->rxq_map[i].tc = MRVL_UNKNOWN_TC;
1060fe939687SNatalie Samsonov 
1061fe939687SNatalie Samsonov 	/* Set up DPDKq->(TC,inq) mapping. */
1062fe939687SNatalie Samsonov 	for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
1063fe939687SNatalie Samsonov 		if (port_cfg->tc[tc].inqs > RTE_DIM(port_cfg->tc[0].inq)) {
1064fe939687SNatalie Samsonov 			/* Overflow. */
1065acab7d58STomasz Duszynski 			MRVL_LOG(ERR,
1066acab7d58STomasz Duszynski 				"Too many RX queues configured per TC %zu!",
1067fe939687SNatalie Samsonov 				tc);
1068fe939687SNatalie Samsonov 			return -1;
1069fe939687SNatalie Samsonov 		}
1070fe939687SNatalie Samsonov 		for (i = 0; i < port_cfg->tc[tc].inqs; ++i) {
1071fe939687SNatalie Samsonov 			uint8_t idx = port_cfg->tc[tc].inq[i];
1072fe939687SNatalie Samsonov 
1073fe939687SNatalie Samsonov 			if (idx > RTE_DIM(priv->rxq_map)) {
1074acab7d58STomasz Duszynski 				MRVL_LOG(ERR, "Bad queue index %d!", idx);
1075fe939687SNatalie Samsonov 				return -1;
1076fe939687SNatalie Samsonov 			}
1077fe939687SNatalie Samsonov 
1078fe939687SNatalie Samsonov 			priv->rxq_map[idx].tc = tc;
1079fe939687SNatalie Samsonov 			priv->rxq_map[idx].inq = i;
1080fe939687SNatalie Samsonov 		}
1081fe939687SNatalie Samsonov 	}
1082fe939687SNatalie Samsonov 
1083fe939687SNatalie Samsonov 	/*
1084fe939687SNatalie Samsonov 	 * Set up TC configuration. TCs need to be sequenced: 0, 1, 2
1085fe939687SNatalie Samsonov 	 * with no gaps. Empty TC means end of processing.
1086fe939687SNatalie Samsonov 	 */
1087fe939687SNatalie Samsonov 	for (i = 0; i < MRVL_PP2_TC_MAX; ++i) {
1088fe939687SNatalie Samsonov 		if (port_cfg->tc[i].inqs == 0)
1089fe939687SNatalie Samsonov 			break;
1090fe939687SNatalie Samsonov 		setup_tc(&priv->ppio_params.inqs_params.tcs_params[i],
1091fe939687SNatalie Samsonov 				port_cfg->tc[i].inqs,
1092fe939687SNatalie Samsonov 				priv->bpool, port_cfg->tc[i].color);
1093fe939687SNatalie Samsonov 	}
1094fe939687SNatalie Samsonov 
1095fe939687SNatalie Samsonov 	priv->ppio_params.inqs_params.num_tcs = i;
1096fe939687SNatalie Samsonov 
1097e97d8874STomasz Duszynski 	if (port_cfg->setup_policer)
1098fe939687SNatalie Samsonov 		return setup_policer(priv, &port_cfg->policer_params);
1099fe939687SNatalie Samsonov 
1100fe939687SNatalie Samsonov 	return 0;
1101fe939687SNatalie Samsonov }
1102fe939687SNatalie Samsonov 
1103fe939687SNatalie Samsonov /**
1104fe939687SNatalie Samsonov  * Configure TX Queues in a given port.
1105fe939687SNatalie Samsonov  *
1106fe939687SNatalie Samsonov  * Sets up TX queues egress scheduler and limiter.
1107fe939687SNatalie Samsonov  *
1108fe939687SNatalie Samsonov  * @param priv Port's private data
1109fe939687SNatalie Samsonov  * @param portid DPDK port ID
1110fe939687SNatalie Samsonov  * @param max_queues Maximum number of queues to configure.
1111fe939687SNatalie Samsonov  * @returns 0 in case of success, negative value otherwise.
1112fe939687SNatalie Samsonov  */
1113fe939687SNatalie Samsonov int
1114fe939687SNatalie Samsonov mrvl_configure_txqs(struct mrvl_priv *priv, uint16_t portid,
1115fe939687SNatalie Samsonov 		uint16_t max_queues)
1116fe939687SNatalie Samsonov {
1117fe939687SNatalie Samsonov 	/* We need only a subset of configuration. */
1118d7eb4fb2SLiron Himi 	struct port_cfg *port_cfg = &mrvl_cfg->port[portid];
1119fe939687SNatalie Samsonov 	int i;
1120fe939687SNatalie Samsonov 
1121d7eb4fb2SLiron Himi 	if (mrvl_cfg == NULL)
1122fe939687SNatalie Samsonov 		return 0;
1123fe939687SNatalie Samsonov 
1124fe939687SNatalie Samsonov 	priv->ppio_params.rate_limit_enable = port_cfg->rate_limit_enable;
1125fe939687SNatalie Samsonov 	if (port_cfg->rate_limit_enable)
1126fe939687SNatalie Samsonov 		priv->ppio_params.rate_limit_params =
1127fe939687SNatalie Samsonov 			port_cfg->rate_limit_params;
1128fe939687SNatalie Samsonov 
1129fe939687SNatalie Samsonov 	for (i = 0; i < max_queues; i++) {
1130fe939687SNatalie Samsonov 		struct pp2_ppio_outq_params *params =
1131fe939687SNatalie Samsonov 			&priv->ppio_params.outqs_params.outqs_params[i];
1132fe939687SNatalie Samsonov 
1133fe939687SNatalie Samsonov 		params->sched_mode = port_cfg->outq[i].sched_mode;
1134fe939687SNatalie Samsonov 		params->weight = port_cfg->outq[i].weight;
1135fe939687SNatalie Samsonov 		params->rate_limit_enable = port_cfg->outq[i].rate_limit_enable;
1136fe939687SNatalie Samsonov 		params->rate_limit_params = port_cfg->outq[i].rate_limit_params;
1137fe939687SNatalie Samsonov 	}
1138fe939687SNatalie Samsonov 
1139fe939687SNatalie Samsonov 	return 0;
1140fe939687SNatalie Samsonov }
1141fe939687SNatalie Samsonov 
1142fe939687SNatalie Samsonov /**
1143fe939687SNatalie Samsonov  * Start QoS mapping.
1144fe939687SNatalie Samsonov  *
1145fe939687SNatalie Samsonov  * Finalize QoS table configuration and initialize it in SDK. It can be done
1146fe939687SNatalie Samsonov  * only after port is started, so we have a valid ppio reference.
1147fe939687SNatalie Samsonov  *
1148fe939687SNatalie Samsonov  * @param priv Port's private (configuration) data.
1149fe939687SNatalie Samsonov  * @returns 0 in case of success, exits otherwise.
1150fe939687SNatalie Samsonov  */
1151fe939687SNatalie Samsonov int
1152fe939687SNatalie Samsonov mrvl_start_qos_mapping(struct mrvl_priv *priv)
1153fe939687SNatalie Samsonov {
1154fe939687SNatalie Samsonov 	size_t i;
1155fe939687SNatalie Samsonov 
115655e429acSLiron Himi 	if (priv->qos_tbl_params.type == PP2_CLS_QOS_TBL_NONE)
115755e429acSLiron Himi 		return 0;
115855e429acSLiron Himi 
1159fe939687SNatalie Samsonov 	if (priv->ppio == NULL) {
1160acab7d58STomasz Duszynski 		MRVL_LOG(ERR, "ppio must not be NULL here!");
1161fe939687SNatalie Samsonov 		return -1;
1162fe939687SNatalie Samsonov 	}
1163fe939687SNatalie Samsonov 
1164fe939687SNatalie Samsonov 	for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i)
1165fe939687SNatalie Samsonov 		priv->qos_tbl_params.pcp_cos_map[i].ppio = priv->ppio;
1166fe939687SNatalie Samsonov 
1167fe939687SNatalie Samsonov 	for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i)
1168fe939687SNatalie Samsonov 		priv->qos_tbl_params.dscp_cos_map[i].ppio = priv->ppio;
1169fe939687SNatalie Samsonov 
1170fe939687SNatalie Samsonov 	/* Initialize Classifier QoS table. */
1171fe939687SNatalie Samsonov 
1172fe939687SNatalie Samsonov 	return pp2_cls_qos_tbl_init(&priv->qos_tbl_params, &priv->qos_tbl);
1173fe939687SNatalie Samsonov }
1174