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