xref: /dpdk/drivers/net/mvpp2/mrvl_tm.c (revision 3953323852dfe399c0e6bdf2d35f88005b8a2135)
1429c3944STomasz Duszynski /* SPDX-License-Identifier: BSD-3-Clause
2429c3944STomasz Duszynski  * Copyright(c) 2018 Marvell International Ltd.
3429c3944STomasz Duszynski  * Copyright(c) 2018 Semihalf.
4429c3944STomasz Duszynski  * All rights reserved.
5429c3944STomasz Duszynski  */
6429c3944STomasz Duszynski 
7429c3944STomasz Duszynski #include <rte_malloc.h>
8429c3944STomasz Duszynski 
9429c3944STomasz Duszynski #include <linux/ethtool.h>
10429c3944STomasz Duszynski #include <linux/sockios.h>
11429c3944STomasz Duszynski #include <net/if.h>
12429c3944STomasz Duszynski #include <sys/ioctl.h>
13429c3944STomasz Duszynski 
14429c3944STomasz Duszynski #include "mrvl_tm.h"
15429c3944STomasz Duszynski 
16429c3944STomasz Duszynski /** Minimum rate value in Bytes/s */
17429c3944STomasz Duszynski #define MRVL_RATE_MIN (PP2_PPIO_MIN_CIR * 1000 / 8)
18429c3944STomasz Duszynski 
19429c3944STomasz Duszynski /** Minimum burst size in Bytes */
20429c3944STomasz Duszynski #define MRVL_BURST_MIN (PP2_PPIO_MIN_CBS * 1000)
21429c3944STomasz Duszynski 
22429c3944STomasz Duszynski /** Maximum burst size in Bytes */
23429c3944STomasz Duszynski #define MRVL_BURST_MAX 256000000
24429c3944STomasz Duszynski 
25429c3944STomasz Duszynski /** Maximum WRR weight */
26429c3944STomasz Duszynski #define MRVL_WEIGHT_MAX 255
27429c3944STomasz Duszynski 
28429c3944STomasz Duszynski /**
29429c3944STomasz Duszynski  * Get maximum port rate in Bytes/s.
30429c3944STomasz Duszynski  *
31429c3944STomasz Duszynski  * @param dev Pointer to the device.
32429c3944STomasz Duszynski  * @param rate Pointer to the rate.
33429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
34429c3944STomasz Duszynski  */
35429c3944STomasz Duszynski static int
36429c3944STomasz Duszynski mrvl_get_max_rate(struct rte_eth_dev *dev, uint64_t *rate)
37429c3944STomasz Duszynski {
38429c3944STomasz Duszynski 	struct ethtool_cmd edata;
39429c3944STomasz Duszynski 	struct ifreq req;
40429c3944STomasz Duszynski 	int ret, fd;
41429c3944STomasz Duszynski 
42429c3944STomasz Duszynski 	memset(&edata, 0, sizeof(edata));
43429c3944STomasz Duszynski 	memset(&req, 0, sizeof(req));
44429c3944STomasz Duszynski 	edata.cmd = ETHTOOL_GSET;
45429c3944STomasz Duszynski 	strcpy(req.ifr_name, dev->data->name);
46429c3944STomasz Duszynski 	req.ifr_data = (void *)&edata;
47429c3944STomasz Duszynski 
48429c3944STomasz Duszynski 	fd = socket(AF_INET, SOCK_DGRAM, 0);
49429c3944STomasz Duszynski 	if (fd == -1)
50429c3944STomasz Duszynski 		return -1;
51429c3944STomasz Duszynski 
52429c3944STomasz Duszynski 	ret = ioctl(fd, SIOCETHTOOL, &req);
53429c3944STomasz Duszynski 	if (ret == -1) {
54429c3944STomasz Duszynski 		close(fd);
55429c3944STomasz Duszynski 		return -1;
56429c3944STomasz Duszynski 	}
57429c3944STomasz Duszynski 
58429c3944STomasz Duszynski 	close(fd);
59429c3944STomasz Duszynski 
608fa07a68SDana Vardi 	*rate = (uint64_t)ethtool_cmd_speed(&edata) * 1000 * 1000 / 8;
61429c3944STomasz Duszynski 
62429c3944STomasz Duszynski 	return 0;
63429c3944STomasz Duszynski }
64429c3944STomasz Duszynski 
65429c3944STomasz Duszynski /**
66429c3944STomasz Duszynski  * Initialize traffic manager related data.
67429c3944STomasz Duszynski  *
68429c3944STomasz Duszynski  * @param dev Pointer to the device.
69429c3944STomasz Duszynski  * @returns 0 on success, failure otherwise.
70429c3944STomasz Duszynski  */
71429c3944STomasz Duszynski int
72429c3944STomasz Duszynski mrvl_tm_init(struct rte_eth_dev *dev)
73429c3944STomasz Duszynski {
74429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
75429c3944STomasz Duszynski 
76429c3944STomasz Duszynski 	LIST_INIT(&priv->shaper_profiles);
77429c3944STomasz Duszynski 	LIST_INIT(&priv->nodes);
78429c3944STomasz Duszynski 
79429c3944STomasz Duszynski 	if (priv->rate_max)
80429c3944STomasz Duszynski 		return 0;
81429c3944STomasz Duszynski 
82429c3944STomasz Duszynski 	return mrvl_get_max_rate(dev, &priv->rate_max);
83429c3944STomasz Duszynski }
84429c3944STomasz Duszynski 
85429c3944STomasz Duszynski /**
86429c3944STomasz Duszynski  * Cleanup traffic manager related data.
87429c3944STomasz Duszynski  *
88429c3944STomasz Duszynski  * @param dev Pointer to the device.
89429c3944STomasz Duszynski  */
90429c3944STomasz Duszynski void mrvl_tm_deinit(struct rte_eth_dev *dev)
91429c3944STomasz Duszynski {
92429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
93429c3944STomasz Duszynski 	struct mrvl_tm_shaper_profile *profile =
94429c3944STomasz Duszynski 		LIST_FIRST(&priv->shaper_profiles);
95429c3944STomasz Duszynski 	struct mrvl_tm_node *node = LIST_FIRST(&priv->nodes);
96429c3944STomasz Duszynski 
97429c3944STomasz Duszynski 	while (profile) {
98429c3944STomasz Duszynski 		struct mrvl_tm_shaper_profile *next = LIST_NEXT(profile, next);
99429c3944STomasz Duszynski 
100429c3944STomasz Duszynski 		LIST_REMOVE(profile, next);
101429c3944STomasz Duszynski 		rte_free(profile);
102429c3944STomasz Duszynski 		profile = next;
103429c3944STomasz Duszynski 	}
104429c3944STomasz Duszynski 
105429c3944STomasz Duszynski 	while (node) {
106429c3944STomasz Duszynski 		struct mrvl_tm_node *next = LIST_NEXT(node, next);
107429c3944STomasz Duszynski 
108429c3944STomasz Duszynski 		LIST_REMOVE(node, next);
109429c3944STomasz Duszynski 		rte_free(node);
110429c3944STomasz Duszynski 		node = next;
111429c3944STomasz Duszynski 	}
112429c3944STomasz Duszynski }
113429c3944STomasz Duszynski 
114429c3944STomasz Duszynski /**
115429c3944STomasz Duszynski  * Get node using its id.
116429c3944STomasz Duszynski  *
117429c3944STomasz Duszynski  * @param priv Pointer to the port's private data.
118429c3944STomasz Duszynski  * @param node_id Id used by this node.
119429c3944STomasz Duszynski  * @returns Pointer to the node if exists, NULL otherwise.
120429c3944STomasz Duszynski  */
121429c3944STomasz Duszynski static struct mrvl_tm_node *
122429c3944STomasz Duszynski mrvl_node_from_id(struct mrvl_priv *priv, uint32_t node_id)
123429c3944STomasz Duszynski {
124429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
125429c3944STomasz Duszynski 
126429c3944STomasz Duszynski 	LIST_FOREACH(node, &priv->nodes, next)
127429c3944STomasz Duszynski 		if (node->id == node_id)
128429c3944STomasz Duszynski 			return node;
129429c3944STomasz Duszynski 
130429c3944STomasz Duszynski 	return NULL;
131429c3944STomasz Duszynski }
132429c3944STomasz Duszynski 
133429c3944STomasz Duszynski /**
134429c3944STomasz Duszynski  * Check whether node is leaf or root.
135429c3944STomasz Duszynski  *
136429c3944STomasz Duszynski  * @param dev Pointer to the device.
137429c3944STomasz Duszynski  * @param node_id Id used by this node.
138429c3944STomasz Duszynski  * @param is_leaf Pointer to flag indicating whether node is a leaf.
139429c3944STomasz Duszynski  * @param error Pointer to the error.
140429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
141429c3944STomasz Duszynski  */
142429c3944STomasz Duszynski static int
143429c3944STomasz Duszynski mrvl_node_type_get(struct rte_eth_dev *dev, uint32_t node_id, int *is_leaf,
144429c3944STomasz Duszynski 		   struct rte_tm_error *error)
145429c3944STomasz Duszynski {
146429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
147429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
148429c3944STomasz Duszynski 
149e622c1a8SDana Vardi 	if (!priv->configured)
150e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
151e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
152e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
153e622c1a8SDana Vardi 
154429c3944STomasz Duszynski 	if (!is_leaf)
155429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
156429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
157429c3944STomasz Duszynski 					 NULL, NULL);
158429c3944STomasz Duszynski 
159429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
160429c3944STomasz Duszynski 	if (!node)
161429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
162429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
163429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
164429c3944STomasz Duszynski 
165429c3944STomasz Duszynski 	*is_leaf = node->type == MRVL_NODE_QUEUE ? 1 : 0;
166429c3944STomasz Duszynski 
167429c3944STomasz Duszynski 	return 0;
168429c3944STomasz Duszynski }
169429c3944STomasz Duszynski 
170429c3944STomasz Duszynski /**
171429c3944STomasz Duszynski  * Get traffic manager capabilities.
172429c3944STomasz Duszynski  *
173429c3944STomasz Duszynski  * @param dev Pointer to the device (unused).
174429c3944STomasz Duszynski  * @param cap Pointer to the capabilities.
175429c3944STomasz Duszynski  * @param error Pointer to the error.
176429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
177429c3944STomasz Duszynski  */
178429c3944STomasz Duszynski static int
179429c3944STomasz Duszynski mrvl_capabilities_get(struct rte_eth_dev *dev,
180429c3944STomasz Duszynski 		      struct rte_tm_capabilities *cap,
181429c3944STomasz Duszynski 		      struct rte_tm_error *error)
182429c3944STomasz Duszynski {
183429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
184429c3944STomasz Duszynski 
185e622c1a8SDana Vardi 	if (!priv->configured)
186e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
187e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
188e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
189e622c1a8SDana Vardi 
190429c3944STomasz Duszynski 	if (!cap)
191429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
192429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
193429c3944STomasz Duszynski 					 NULL, "Capabilities are missing\n");
194429c3944STomasz Duszynski 
195429c3944STomasz Duszynski 	memset(cap, 0, sizeof(*cap));
196429c3944STomasz Duszynski 
197429c3944STomasz Duszynski 	cap->n_nodes_max = 1 + dev->data->nb_tx_queues; /* port + txqs number */
198429c3944STomasz Duszynski 	cap->n_levels_max = 2; /* port level + txqs level */
199429c3944STomasz Duszynski 	cap->non_leaf_nodes_identical = 1;
200429c3944STomasz Duszynski 	cap->leaf_nodes_identical = 1;
201429c3944STomasz Duszynski 
202429c3944STomasz Duszynski 	cap->shaper_n_max = cap->n_nodes_max;
203429c3944STomasz Duszynski 	cap->shaper_private_n_max = cap->shaper_n_max;
204429c3944STomasz Duszynski 	cap->shaper_private_rate_min = MRVL_RATE_MIN;
205429c3944STomasz Duszynski 	cap->shaper_private_rate_max = priv->rate_max;
20657fc9e47SNithin Dabilpuram 	cap->shaper_private_packet_mode_supported = 0;
20757fc9e47SNithin Dabilpuram 	cap->shaper_private_byte_mode_supported = 1;
208429c3944STomasz Duszynski 
209429c3944STomasz Duszynski 	cap->sched_n_children_max = dev->data->nb_tx_queues;
210429c3944STomasz Duszynski 	cap->sched_sp_n_priorities_max = dev->data->nb_tx_queues;
211429c3944STomasz Duszynski 	cap->sched_wfq_n_children_per_group_max = dev->data->nb_tx_queues;
212429c3944STomasz Duszynski 	cap->sched_wfq_n_groups_max = 1;
213429c3944STomasz Duszynski 	cap->sched_wfq_weight_max = MRVL_WEIGHT_MAX;
21457fc9e47SNithin Dabilpuram 	cap->sched_wfq_packet_mode_supported = 0;
21557fc9e47SNithin Dabilpuram 	cap->sched_wfq_byte_mode_supported = 1;
216429c3944STomasz Duszynski 
217429c3944STomasz Duszynski 	cap->dynamic_update_mask = RTE_TM_UPDATE_NODE_SUSPEND_RESUME |
218429c3944STomasz Duszynski 				   RTE_TM_UPDATE_NODE_STATS;
219429c3944STomasz Duszynski 	cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
220429c3944STomasz Duszynski 
221429c3944STomasz Duszynski 	return 0;
222429c3944STomasz Duszynski }
223429c3944STomasz Duszynski 
224429c3944STomasz Duszynski /**
225429c3944STomasz Duszynski  * Get traffic manager hierarchy level capabilities.
226429c3944STomasz Duszynski  *
227429c3944STomasz Duszynski  * @param dev Pointer to the device.
228429c3944STomasz Duszynski  * @param level_id Id of the level.
229429c3944STomasz Duszynski  * @param cap Pointer to the level capabilities.
230429c3944STomasz Duszynski  * @param error Pointer to the error.
231429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
232429c3944STomasz Duszynski  */
233429c3944STomasz Duszynski static int
234429c3944STomasz Duszynski mrvl_level_capabilities_get(struct rte_eth_dev *dev,
235429c3944STomasz Duszynski 			    uint32_t level_id,
236429c3944STomasz Duszynski 			    struct rte_tm_level_capabilities *cap,
237429c3944STomasz Duszynski 			    struct rte_tm_error *error)
238429c3944STomasz Duszynski {
239429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
240429c3944STomasz Duszynski 
241e622c1a8SDana Vardi 	if (!priv->configured)
242e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
243e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
244e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
245e622c1a8SDana Vardi 
246429c3944STomasz Duszynski 	if (!cap)
247429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
248429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
249429c3944STomasz Duszynski 					 NULL, NULL);
250429c3944STomasz Duszynski 
251429c3944STomasz Duszynski 	memset(cap, 0, sizeof(*cap));
252429c3944STomasz Duszynski 
253429c3944STomasz Duszynski 	if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE)
254429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
255429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_LEVEL_ID,
256429c3944STomasz Duszynski 					 NULL, "Wrong level id\n");
257429c3944STomasz Duszynski 
258429c3944STomasz Duszynski 	if (level_id == MRVL_NODE_PORT) {
259429c3944STomasz Duszynski 		cap->n_nodes_max = 1;
260429c3944STomasz Duszynski 		cap->n_nodes_nonleaf_max = 1;
261429c3944STomasz Duszynski 		cap->non_leaf_nodes_identical = 1;
262429c3944STomasz Duszynski 
263429c3944STomasz Duszynski 		cap->nonleaf.shaper_private_supported = 1;
264429c3944STomasz Duszynski 		cap->nonleaf.shaper_private_rate_min = MRVL_RATE_MIN;
265429c3944STomasz Duszynski 		cap->nonleaf.shaper_private_rate_max = priv->rate_max;
26657fc9e47SNithin Dabilpuram 		cap->nonleaf.shaper_private_packet_mode_supported = 0;
26757fc9e47SNithin Dabilpuram 		cap->nonleaf.shaper_private_byte_mode_supported = 1;
268429c3944STomasz Duszynski 
269429c3944STomasz Duszynski 		cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
270429c3944STomasz Duszynski 		cap->nonleaf.sched_sp_n_priorities_max = 1;
271429c3944STomasz Duszynski 		cap->nonleaf.sched_wfq_n_children_per_group_max =
272429c3944STomasz Duszynski 			dev->data->nb_tx_queues;
273429c3944STomasz Duszynski 		cap->nonleaf.sched_wfq_n_groups_max = 1;
274429c3944STomasz Duszynski 		cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX;
27557fc9e47SNithin Dabilpuram 		cap->nonleaf.sched_wfq_packet_mode_supported = 0;
27657fc9e47SNithin Dabilpuram 		cap->nonleaf.sched_wfq_byte_mode_supported = 1;
277429c3944STomasz Duszynski 		cap->nonleaf.stats_mask = RTE_TM_STATS_N_PKTS |
278429c3944STomasz Duszynski 					  RTE_TM_STATS_N_BYTES;
279429c3944STomasz Duszynski 	} else { /* level_id == MRVL_NODE_QUEUE */
280429c3944STomasz Duszynski 		cap->n_nodes_max = dev->data->nb_tx_queues;
281429c3944STomasz Duszynski 		cap->n_nodes_leaf_max = dev->data->nb_tx_queues;
282429c3944STomasz Duszynski 		cap->leaf_nodes_identical = 1;
283429c3944STomasz Duszynski 
284429c3944STomasz Duszynski 		cap->leaf.shaper_private_supported = 1;
285429c3944STomasz Duszynski 		cap->leaf.shaper_private_rate_min = MRVL_RATE_MIN;
286429c3944STomasz Duszynski 		cap->leaf.shaper_private_rate_max = priv->rate_max;
28757fc9e47SNithin Dabilpuram 		cap->leaf.shaper_private_packet_mode_supported = 0;
28857fc9e47SNithin Dabilpuram 		cap->leaf.shaper_private_byte_mode_supported = 1;
289429c3944STomasz Duszynski 		cap->leaf.stats_mask = RTE_TM_STATS_N_PKTS;
290429c3944STomasz Duszynski 	}
291429c3944STomasz Duszynski 
292429c3944STomasz Duszynski 	return 0;
293429c3944STomasz Duszynski }
294429c3944STomasz Duszynski 
295429c3944STomasz Duszynski /**
296429c3944STomasz Duszynski  * Get node capabilities.
297429c3944STomasz Duszynski  *
298429c3944STomasz Duszynski  * @param dev Pointer to the device.
299429c3944STomasz Duszynski  * @param node_id Id of the node.
300429c3944STomasz Duszynski  * @param cap Pointer to the capabilities.
301429c3944STomasz Duszynski  * @param error Pointer to the error.
302429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
303429c3944STomasz Duszynski  */
304429c3944STomasz Duszynski static int
305429c3944STomasz Duszynski mrvl_node_capabilities_get(struct rte_eth_dev *dev, uint32_t node_id,
306429c3944STomasz Duszynski 			   struct rte_tm_node_capabilities *cap,
307429c3944STomasz Duszynski 			   struct rte_tm_error *error)
308429c3944STomasz Duszynski {
309429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
310429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
311429c3944STomasz Duszynski 
312e622c1a8SDana Vardi 	if (!priv->configured)
313e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
314e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
315e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
316e622c1a8SDana Vardi 
317429c3944STomasz Duszynski 	if (!cap)
318429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
319429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
320429c3944STomasz Duszynski 					 NULL, NULL);
321429c3944STomasz Duszynski 
322429c3944STomasz Duszynski 	memset(cap, 0, sizeof(*cap));
323429c3944STomasz Duszynski 
324429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
325429c3944STomasz Duszynski 	if (!node)
326429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
327429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
328429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
329429c3944STomasz Duszynski 
330429c3944STomasz Duszynski 	cap->shaper_private_supported = 1;
331429c3944STomasz Duszynski 	cap->shaper_private_rate_min = MRVL_RATE_MIN;
332429c3944STomasz Duszynski 	cap->shaper_private_rate_max = priv->rate_max;
33357fc9e47SNithin Dabilpuram 	cap->shaper_private_packet_mode_supported = 0;
33457fc9e47SNithin Dabilpuram 	cap->shaper_private_byte_mode_supported = 1;
335429c3944STomasz Duszynski 
336429c3944STomasz Duszynski 	if (node->type == MRVL_NODE_PORT) {
337429c3944STomasz Duszynski 		cap->nonleaf.sched_n_children_max = dev->data->nb_tx_queues;
338429c3944STomasz Duszynski 		cap->nonleaf.sched_sp_n_priorities_max = 1;
339429c3944STomasz Duszynski 		cap->nonleaf.sched_wfq_n_children_per_group_max =
340429c3944STomasz Duszynski 			dev->data->nb_tx_queues;
341429c3944STomasz Duszynski 		cap->nonleaf.sched_wfq_n_groups_max = 1;
342429c3944STomasz Duszynski 		cap->nonleaf.sched_wfq_weight_max = MRVL_WEIGHT_MAX;
34357fc9e47SNithin Dabilpuram 		cap->nonleaf.sched_wfq_packet_mode_supported = 0;
34457fc9e47SNithin Dabilpuram 		cap->nonleaf.sched_wfq_byte_mode_supported = 1;
345429c3944STomasz Duszynski 		cap->stats_mask = RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES;
346429c3944STomasz Duszynski 	} else {
347429c3944STomasz Duszynski 		cap->stats_mask = RTE_TM_STATS_N_PKTS;
348429c3944STomasz Duszynski 	}
349429c3944STomasz Duszynski 
350429c3944STomasz Duszynski 	return 0;
351429c3944STomasz Duszynski }
352429c3944STomasz Duszynski 
353429c3944STomasz Duszynski /**
354429c3944STomasz Duszynski  * Get shaper profile using its id.
355429c3944STomasz Duszynski  *
356429c3944STomasz Duszynski  * @param priv Pointer to the port's private data.
357429c3944STomasz Duszynski  * @param shaper_profile_id Id used by the shaper.
358429c3944STomasz Duszynski  * @returns Pointer to the shaper profile if exists, NULL otherwise.
359429c3944STomasz Duszynski  */
360429c3944STomasz Duszynski static struct mrvl_tm_shaper_profile *
361429c3944STomasz Duszynski mrvl_shaper_profile_from_id(struct mrvl_priv *priv, uint32_t shaper_profile_id)
362429c3944STomasz Duszynski {
363429c3944STomasz Duszynski 	struct mrvl_tm_shaper_profile *profile;
364429c3944STomasz Duszynski 
365429c3944STomasz Duszynski 	LIST_FOREACH(profile, &priv->shaper_profiles, next)
366429c3944STomasz Duszynski 		if (profile->id == shaper_profile_id)
367429c3944STomasz Duszynski 			return profile;
368429c3944STomasz Duszynski 
369429c3944STomasz Duszynski 	return NULL;
370429c3944STomasz Duszynski }
371429c3944STomasz Duszynski 
372429c3944STomasz Duszynski /**
373429c3944STomasz Duszynski  * Add a new shaper profile.
374429c3944STomasz Duszynski  *
375429c3944STomasz Duszynski  * @param dev Pointer to the device.
376429c3944STomasz Duszynski  * @param shaper_profile_id Id of the new profile.
377429c3944STomasz Duszynski  * @param params Pointer to the shaper profile parameters.
378429c3944STomasz Duszynski  * @param error Pointer to the error.
379429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
380429c3944STomasz Duszynski  */
381429c3944STomasz Duszynski static int
382429c3944STomasz Duszynski mrvl_shaper_profile_add(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
383*39533238SBruce Richardson 			const struct rte_tm_shaper_params *params,
384429c3944STomasz Duszynski 			struct rte_tm_error *error)
385429c3944STomasz Duszynski {
386429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
387429c3944STomasz Duszynski 	struct mrvl_tm_shaper_profile *profile;
388429c3944STomasz Duszynski 
389e622c1a8SDana Vardi 	if (!priv->configured)
390e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
391e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
392e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
393e622c1a8SDana Vardi 
394429c3944STomasz Duszynski 	if (!params)
395429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
396429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
397429c3944STomasz Duszynski 					 NULL, NULL);
398429c3944STomasz Duszynski 
399429c3944STomasz Duszynski 	if (params->committed.rate)
400429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
401429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_RATE,
402429c3944STomasz Duszynski 				NULL, "Committed rate not supported\n");
403429c3944STomasz Duszynski 
404429c3944STomasz Duszynski 	if (params->committed.size)
405429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
406429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_SHAPER_PROFILE_COMMITTED_SIZE,
407429c3944STomasz Duszynski 				NULL, "Committed bucket size not supported\n");
408429c3944STomasz Duszynski 
409429c3944STomasz Duszynski 	if (params->peak.rate < MRVL_RATE_MIN ||
410429c3944STomasz Duszynski 	    params->peak.rate > priv->rate_max)
411429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
412429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_RATE,
413429c3944STomasz Duszynski 				NULL, "Peak rate is out of range\n");
414429c3944STomasz Duszynski 
415429c3944STomasz Duszynski 	if (params->peak.size < MRVL_BURST_MIN ||
416429c3944STomasz Duszynski 	    params->peak.size > MRVL_BURST_MAX)
417429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
418429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_SHAPER_PROFILE_PEAK_SIZE,
419429c3944STomasz Duszynski 				NULL, "Peak size is out of range\n");
420429c3944STomasz Duszynski 
421429c3944STomasz Duszynski 	if (shaper_profile_id == RTE_TM_SHAPER_PROFILE_ID_NONE)
422429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
423429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
424429c3944STomasz Duszynski 					 NULL, "Wrong shaper profile id\n");
425429c3944STomasz Duszynski 
426429c3944STomasz Duszynski 	profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
427429c3944STomasz Duszynski 	if (profile)
428429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EEXIST,
429429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
430429c3944STomasz Duszynski 					 NULL, "Profile id already exists\n");
431429c3944STomasz Duszynski 
432429c3944STomasz Duszynski 	profile = rte_zmalloc_socket(NULL, sizeof(*profile), 0,
433429c3944STomasz Duszynski 				     rte_socket_id());
434429c3944STomasz Duszynski 	if (!profile)
435429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENOMEM,
436429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
437429c3944STomasz Duszynski 					 NULL, NULL);
438429c3944STomasz Duszynski 
439429c3944STomasz Duszynski 	profile->id = shaper_profile_id;
440429c3944STomasz Duszynski 	rte_memcpy(&profile->params, params, sizeof(profile->params));
441429c3944STomasz Duszynski 
442429c3944STomasz Duszynski 	LIST_INSERT_HEAD(&priv->shaper_profiles, profile, next);
443429c3944STomasz Duszynski 
444429c3944STomasz Duszynski 	return 0;
445429c3944STomasz Duszynski }
446429c3944STomasz Duszynski 
447429c3944STomasz Duszynski /**
448429c3944STomasz Duszynski  * Remove a shaper profile.
449429c3944STomasz Duszynski  *
450429c3944STomasz Duszynski  * @param dev Pointer to the device.
451429c3944STomasz Duszynski  * @param shaper_profile_id Id of the shaper profile.
452429c3944STomasz Duszynski  * @param error Pointer to the error.
453429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
454429c3944STomasz Duszynski  */
455429c3944STomasz Duszynski static int
456429c3944STomasz Duszynski mrvl_shaper_profile_delete(struct rte_eth_dev *dev, uint32_t shaper_profile_id,
457429c3944STomasz Duszynski 			   struct rte_tm_error *error)
458429c3944STomasz Duszynski {
459429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
460429c3944STomasz Duszynski 	struct mrvl_tm_shaper_profile *profile;
461429c3944STomasz Duszynski 
462e622c1a8SDana Vardi 	if (!priv->configured)
463e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
464e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
465e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
466e622c1a8SDana Vardi 
467429c3944STomasz Duszynski 	profile = mrvl_shaper_profile_from_id(priv, shaper_profile_id);
468429c3944STomasz Duszynski 	if (!profile)
469429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
470429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
471429c3944STomasz Duszynski 					 NULL, "Profile id does not exist\n");
472429c3944STomasz Duszynski 
473429c3944STomasz Duszynski 	if (profile->refcnt)
474429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EPERM,
475429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
476429c3944STomasz Duszynski 					 NULL, "Profile is used\n");
477429c3944STomasz Duszynski 
478429c3944STomasz Duszynski 	LIST_REMOVE(profile, next);
479429c3944STomasz Duszynski 	rte_free(profile);
480429c3944STomasz Duszynski 
481429c3944STomasz Duszynski 	return 0;
482429c3944STomasz Duszynski }
483429c3944STomasz Duszynski 
484429c3944STomasz Duszynski /**
485429c3944STomasz Duszynski  * Check node parameters.
486429c3944STomasz Duszynski  *
487429c3944STomasz Duszynski  * @param dev Pointer to the device.
488429c3944STomasz Duszynski  * @param node_id Id used by the node.
489429c3944STomasz Duszynski  * @param priority Priority value.
490429c3944STomasz Duszynski  * @param weight Weight value.
491429c3944STomasz Duszynski  * @param level_id Id of the level.
492429c3944STomasz Duszynski  * @param params Pointer to the node parameters.
493429c3944STomasz Duszynski  * @param error Pointer to the error.
494429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
495429c3944STomasz Duszynski  */
496429c3944STomasz Duszynski static int
497429c3944STomasz Duszynski mrvl_node_check_params(struct rte_eth_dev *dev, uint32_t node_id,
498429c3944STomasz Duszynski 		       uint32_t priority, uint32_t weight, uint32_t level_id,
4995d49af62SBruce Richardson 		       const struct rte_tm_node_params *params,
500429c3944STomasz Duszynski 		       struct rte_tm_error *error)
501429c3944STomasz Duszynski {
502429c3944STomasz Duszynski 	if (node_id == RTE_TM_NODE_ID_NULL)
503429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL, RTE_TM_NODE_ID_NULL,
504429c3944STomasz Duszynski 					 NULL, "Node id is invalid\n");
505429c3944STomasz Duszynski 
506429c3944STomasz Duszynski 	if (priority)
507429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
508429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_PRIORITY,
509429c3944STomasz Duszynski 					 NULL, "Priority should be 0\n");
510429c3944STomasz Duszynski 
511429c3944STomasz Duszynski 	if (weight > MRVL_WEIGHT_MAX)
512429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
513429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_WEIGHT,
514429c3944STomasz Duszynski 					 NULL, "Weight is out of range\n");
515429c3944STomasz Duszynski 
516429c3944STomasz Duszynski 	if (level_id != MRVL_NODE_PORT && level_id != MRVL_NODE_QUEUE)
517429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
518429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_LEVEL_ID,
519429c3944STomasz Duszynski 					 NULL, "Wrong level id\n");
520429c3944STomasz Duszynski 
521429c3944STomasz Duszynski 	if (!params)
522429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
523429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
524429c3944STomasz Duszynski 					 NULL, NULL);
525429c3944STomasz Duszynski 
526429c3944STomasz Duszynski 	if (params->shared_shaper_id)
527429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
528429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_SHAPER_ID,
529429c3944STomasz Duszynski 				NULL, "Shared shaper is not supported\n");
530429c3944STomasz Duszynski 
531429c3944STomasz Duszynski 	if (params->n_shared_shapers)
532429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
533429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_SHAPERS,
534429c3944STomasz Duszynski 				NULL, "Shared shaper is not supported\n");
535429c3944STomasz Duszynski 
536429c3944STomasz Duszynski 	/* verify port (root node) settings */
537429c3944STomasz Duszynski 	if (node_id >= dev->data->nb_tx_queues) {
538429c3944STomasz Duszynski 		if (params->nonleaf.wfq_weight_mode)
539429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
540429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_WFQ_WEIGHT_MODE,
541429c3944STomasz Duszynski 				NULL, "WFQ is not supported\n");
542429c3944STomasz Duszynski 
543429c3944STomasz Duszynski 		if (params->nonleaf.n_sp_priorities != 1)
544429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
545429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SP_PRIORITIES,
546429c3944STomasz Duszynski 				NULL, "SP is not supported\n");
547429c3944STomasz Duszynski 
548429c3944STomasz Duszynski 		if (params->stats_mask & ~(RTE_TM_STATS_N_PKTS |
549429c3944STomasz Duszynski 					   RTE_TM_STATS_N_BYTES))
550429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
551429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
552429c3944STomasz Duszynski 				NULL,
553429c3944STomasz Duszynski 				"Requested port stats are not supported\n");
554429c3944STomasz Duszynski 
555429c3944STomasz Duszynski 		return 0;
556429c3944STomasz Duszynski 	}
557429c3944STomasz Duszynski 
558429c3944STomasz Duszynski 	/* verify txq (leaf node) settings */
559429c3944STomasz Duszynski 	if (params->leaf.cman)
560429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
561429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_PARAMS_CMAN,
562429c3944STomasz Duszynski 					 NULL,
563429c3944STomasz Duszynski 					 "Congestion mngmt is not supported\n");
564429c3944STomasz Duszynski 
565429c3944STomasz Duszynski 	if (params->leaf.wred.wred_profile_id)
566429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
567429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_WRED_PROFILE_ID,
568429c3944STomasz Duszynski 				NULL, "WRED is not supported\n");
569429c3944STomasz Duszynski 
570429c3944STomasz Duszynski 	if (params->leaf.wred.shared_wred_context_id)
571429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
572429c3944STomasz Duszynski 			RTE_TM_ERROR_TYPE_NODE_PARAMS_SHARED_WRED_CONTEXT_ID,
573429c3944STomasz Duszynski 			NULL, "WRED is not supported\n");
574429c3944STomasz Duszynski 
575429c3944STomasz Duszynski 	if (params->leaf.wred.n_shared_wred_contexts)
576429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
577429c3944STomasz Duszynski 			RTE_TM_ERROR_TYPE_NODE_PARAMS_N_SHARED_WRED_CONTEXTS,
578429c3944STomasz Duszynski 			NULL, "WRED is not supported\n");
579429c3944STomasz Duszynski 
580429c3944STomasz Duszynski 	if (params->stats_mask & ~RTE_TM_STATS_N_PKTS)
581429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EINVAL,
582429c3944STomasz Duszynski 			RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
583429c3944STomasz Duszynski 			NULL,
584429c3944STomasz Duszynski 			"Requested txq stats are not supported\n");
585429c3944STomasz Duszynski 
586429c3944STomasz Duszynski 	return 0;
587429c3944STomasz Duszynski }
588429c3944STomasz Duszynski 
589429c3944STomasz Duszynski /**
590429c3944STomasz Duszynski  * Add a new node.
591429c3944STomasz Duszynski  *
592429c3944STomasz Duszynski  * @param dev Pointer to the device.
593429c3944STomasz Duszynski  * @param node_id Id of the node.
594429c3944STomasz Duszynski  * @param parent_node_id Id of the parent node.
595429c3944STomasz Duszynski  * @param priority Priority value.
596429c3944STomasz Duszynski  * @param weight Weight value.
597429c3944STomasz Duszynski  * @param level_id Id of the level.
598429c3944STomasz Duszynski  * @param params Pointer to the node parameters.
599429c3944STomasz Duszynski  * @param error Pointer to the error.
600429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
601429c3944STomasz Duszynski  */
602429c3944STomasz Duszynski static int
603429c3944STomasz Duszynski mrvl_node_add(struct rte_eth_dev *dev, uint32_t node_id,
604429c3944STomasz Duszynski 	      uint32_t parent_node_id, uint32_t priority, uint32_t weight,
6055d49af62SBruce Richardson 	      uint32_t level_id, const struct rte_tm_node_params *params,
606429c3944STomasz Duszynski 	      struct rte_tm_error *error)
607429c3944STomasz Duszynski {
608429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
609429c3944STomasz Duszynski 	struct mrvl_tm_shaper_profile *profile = NULL;
610429c3944STomasz Duszynski 	struct mrvl_tm_node *node, *parent = NULL;
611429c3944STomasz Duszynski 	int ret;
612429c3944STomasz Duszynski 
613e622c1a8SDana Vardi 	if (!priv->configured)
614e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
615e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
616e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
617e622c1a8SDana Vardi 
618429c3944STomasz Duszynski 	if (priv->ppio)
619429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EPERM,
620429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
621429c3944STomasz Duszynski 					 NULL, "Port is already started\n");
622429c3944STomasz Duszynski 
623429c3944STomasz Duszynski 	ret = mrvl_node_check_params(dev, node_id, priority, weight, level_id,
624429c3944STomasz Duszynski 				     params, error);
625429c3944STomasz Duszynski 	if (ret)
626429c3944STomasz Duszynski 		return ret;
627429c3944STomasz Duszynski 
628429c3944STomasz Duszynski 	if (params->shaper_profile_id != RTE_TM_SHAPER_PROFILE_ID_NONE) {
629429c3944STomasz Duszynski 		profile = mrvl_shaper_profile_from_id(priv,
630429c3944STomasz Duszynski 						 params->shaper_profile_id);
631429c3944STomasz Duszynski 		if (!profile)
632429c3944STomasz Duszynski 			return -rte_tm_error_set(error, ENODEV,
633429c3944STomasz Duszynski 					RTE_TM_ERROR_TYPE_SHAPER_PROFILE_ID,
634429c3944STomasz Duszynski 					NULL, "Shaper id does not exist\n");
635429c3944STomasz Duszynski 	}
636429c3944STomasz Duszynski 
637429c3944STomasz Duszynski 	if (parent_node_id == RTE_TM_NODE_ID_NULL) {
638429c3944STomasz Duszynski 		LIST_FOREACH(node, &priv->nodes, next) {
639429c3944STomasz Duszynski 			if (node->type != MRVL_NODE_PORT)
640429c3944STomasz Duszynski 				continue;
641429c3944STomasz Duszynski 
642429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
643429c3944STomasz Duszynski 						 RTE_TM_ERROR_TYPE_UNSPECIFIED,
644429c3944STomasz Duszynski 						 NULL, "Root node exists\n");
645429c3944STomasz Duszynski 		}
646429c3944STomasz Duszynski 	} else {
647429c3944STomasz Duszynski 		parent = mrvl_node_from_id(priv, parent_node_id);
648429c3944STomasz Duszynski 		if (!parent)
649429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
650429c3944STomasz Duszynski 					RTE_TM_ERROR_TYPE_NODE_PARENT_NODE_ID,
651429c3944STomasz Duszynski 					NULL, "Node id does not exist\n");
652429c3944STomasz Duszynski 	}
653429c3944STomasz Duszynski 
654429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
655429c3944STomasz Duszynski 	if (node)
656429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
657429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
658429c3944STomasz Duszynski 					 NULL, "Node id already exists\n");
659429c3944STomasz Duszynski 
660429c3944STomasz Duszynski 	node = rte_zmalloc_socket(NULL, sizeof(*node), 0, rte_socket_id());
661429c3944STomasz Duszynski 	if (!node)
662429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENOMEM,
663429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
664429c3944STomasz Duszynski 					 NULL, NULL);
665429c3944STomasz Duszynski 
666429c3944STomasz Duszynski 	node->id = node_id;
667429c3944STomasz Duszynski 	node->type = parent_node_id == RTE_TM_NODE_ID_NULL ? MRVL_NODE_PORT :
668429c3944STomasz Duszynski 							     MRVL_NODE_QUEUE;
669429c3944STomasz Duszynski 
670429c3944STomasz Duszynski 	if (parent) {
671429c3944STomasz Duszynski 		node->parent = parent;
672429c3944STomasz Duszynski 		parent->refcnt++;
673429c3944STomasz Duszynski 	}
674429c3944STomasz Duszynski 
675429c3944STomasz Duszynski 	if (profile) {
676429c3944STomasz Duszynski 		node->profile = profile;
677429c3944STomasz Duszynski 		profile->refcnt++;
678429c3944STomasz Duszynski 	}
679429c3944STomasz Duszynski 
680429c3944STomasz Duszynski 	node->weight = weight;
681429c3944STomasz Duszynski 	node->stats_mask = params->stats_mask;
682429c3944STomasz Duszynski 
683429c3944STomasz Duszynski 	LIST_INSERT_HEAD(&priv->nodes, node, next);
684429c3944STomasz Duszynski 
685429c3944STomasz Duszynski 	return 0;
686429c3944STomasz Duszynski }
687429c3944STomasz Duszynski 
688429c3944STomasz Duszynski /**
689429c3944STomasz Duszynski  * Delete a node.
690429c3944STomasz Duszynski  *
691429c3944STomasz Duszynski  * @param dev Pointer to the device.
692429c3944STomasz Duszynski  * @param node_id Id of the node.
693429c3944STomasz Duszynski  * @param error Pointer to the error.
694429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
695429c3944STomasz Duszynski  */
696429c3944STomasz Duszynski static int
697429c3944STomasz Duszynski mrvl_node_delete(struct rte_eth_dev *dev, uint32_t node_id,
698429c3944STomasz Duszynski 		 struct rte_tm_error *error)
699429c3944STomasz Duszynski {
700429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
701429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
702429c3944STomasz Duszynski 
703e622c1a8SDana Vardi 	if (!priv->configured)
704e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
705e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
706e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
707e622c1a8SDana Vardi 
708429c3944STomasz Duszynski 	if (priv->ppio) {
709429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EPERM,
710429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
711429c3944STomasz Duszynski 					 NULL, "Port is already started\n");
712429c3944STomasz Duszynski 	}
713429c3944STomasz Duszynski 
714429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
715429c3944STomasz Duszynski 	if (!node)
716429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
717429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
718429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
719429c3944STomasz Duszynski 
720429c3944STomasz Duszynski 	if (node->refcnt)
721429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EPERM,
722429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
723429c3944STomasz Duszynski 					 NULL, "Node id is used\n");
724429c3944STomasz Duszynski 
725429c3944STomasz Duszynski 	if (node->parent)
726429c3944STomasz Duszynski 		node->parent->refcnt--;
727429c3944STomasz Duszynski 
728429c3944STomasz Duszynski 	if (node->profile)
729429c3944STomasz Duszynski 		node->profile->refcnt--;
730429c3944STomasz Duszynski 
731429c3944STomasz Duszynski 	LIST_REMOVE(node, next);
732429c3944STomasz Duszynski 	rte_free(node);
733429c3944STomasz Duszynski 
734429c3944STomasz Duszynski 	return 0;
735429c3944STomasz Duszynski }
736429c3944STomasz Duszynski 
737429c3944STomasz Duszynski /**
738429c3944STomasz Duszynski  * Helper for suspending specific tx queue.
739429c3944STomasz Duszynski  *
740429c3944STomasz Duszynski  * @param dev Pointer to the device.
741429c3944STomasz Duszynski  * @param node_id Id used by this node.
742429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
743429c3944STomasz Duszynski  */
744429c3944STomasz Duszynski static int mrvl_node_suspend_one(struct rte_eth_dev *dev, uint32_t node_id,
745429c3944STomasz Duszynski 				 struct rte_tm_error *error)
746429c3944STomasz Duszynski {
747429c3944STomasz Duszynski 	int ret = dev->dev_ops->tx_queue_stop(dev, node_id);
748429c3944STomasz Duszynski 	if (ret)
749429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ret,
750429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
751429c3944STomasz Duszynski 					 NULL, "Failed to suspend a txq\n");
752429c3944STomasz Duszynski 
753429c3944STomasz Duszynski 	return 0;
754429c3944STomasz Duszynski }
755429c3944STomasz Duszynski 
756429c3944STomasz Duszynski /**
757429c3944STomasz Duszynski  * Suspend a node.
758429c3944STomasz Duszynski  *
759429c3944STomasz Duszynski  * @param dev Pointer to the device.
760429c3944STomasz Duszynski  * @param node_id Id of the node.
761429c3944STomasz Duszynski  * @param error Pointer to the error.
762429c3944STomasz Duszynski  * returns 0 on success, negative value otherwise.
763429c3944STomasz Duszynski  */
764429c3944STomasz Duszynski static int
765429c3944STomasz Duszynski mrvl_node_suspend(struct rte_eth_dev *dev, uint32_t node_id,
766429c3944STomasz Duszynski 		  struct rte_tm_error *error)
767429c3944STomasz Duszynski {
768429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
769429c3944STomasz Duszynski 	struct mrvl_tm_node *node, *tmp;
770429c3944STomasz Duszynski 	int ret;
771429c3944STomasz Duszynski 
772e622c1a8SDana Vardi 	if (!priv->configured)
773e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
774e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
775e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
776e622c1a8SDana Vardi 
777429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
778429c3944STomasz Duszynski 	if (!node)
779429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
780429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
781429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
782429c3944STomasz Duszynski 
783429c3944STomasz Duszynski 	if (!node->parent) {
784429c3944STomasz Duszynski 		LIST_FOREACH(tmp, &priv->nodes, next) {
785429c3944STomasz Duszynski 			if (!tmp->parent)
786429c3944STomasz Duszynski 				continue;
787429c3944STomasz Duszynski 
788429c3944STomasz Duszynski 			if (node != tmp->parent)
789429c3944STomasz Duszynski 				continue;
790429c3944STomasz Duszynski 
791429c3944STomasz Duszynski 			ret = mrvl_node_suspend_one(dev, tmp->id, error);
792429c3944STomasz Duszynski 			if (ret)
793429c3944STomasz Duszynski 				return ret;
794429c3944STomasz Duszynski 		}
795429c3944STomasz Duszynski 
796429c3944STomasz Duszynski 		return 0;
797429c3944STomasz Duszynski 	}
798429c3944STomasz Duszynski 
799429c3944STomasz Duszynski 	return mrvl_node_suspend_one(dev, node_id, error);
800429c3944STomasz Duszynski }
801429c3944STomasz Duszynski 
802429c3944STomasz Duszynski /**
803429c3944STomasz Duszynski  * Resume a node.
804429c3944STomasz Duszynski  *
805429c3944STomasz Duszynski  * @param dev Pointer to the device.
806429c3944STomasz Duszynski  * @param node_id Id of the node.
807429c3944STomasz Duszynski  * @param error Pointer to the error.
808429c3944STomasz Duszynski  * returns 0 on success, negative value otherwise.
809429c3944STomasz Duszynski  */
810429c3944STomasz Duszynski static int
811429c3944STomasz Duszynski mrvl_node_resume(struct rte_eth_dev *dev, uint32_t node_id,
812429c3944STomasz Duszynski 		 struct rte_tm_error *error)
813429c3944STomasz Duszynski {
814429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
815429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
816429c3944STomasz Duszynski 	int ret;
817429c3944STomasz Duszynski 
818e622c1a8SDana Vardi 	if (!priv->configured)
819e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
820e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
821e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
822e622c1a8SDana Vardi 
823429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
824429c3944STomasz Duszynski 	if (!node)
825429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
826429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
827429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
828429c3944STomasz Duszynski 
829429c3944STomasz Duszynski 
830429c3944STomasz Duszynski 	if (!node->parent)
831429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EPERM,
832429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
833429c3944STomasz Duszynski 					 NULL, "Cannot suspend a port\n");
834429c3944STomasz Duszynski 
835429c3944STomasz Duszynski 	ret = dev->dev_ops->tx_queue_start(dev, node_id);
836429c3944STomasz Duszynski 	if (ret)
837429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ret,
838429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
839429c3944STomasz Duszynski 					 NULL, "Failed to resume a txq\n");
840429c3944STomasz Duszynski 	return 0;
841429c3944STomasz Duszynski }
842429c3944STomasz Duszynski 
843429c3944STomasz Duszynski /**
844429c3944STomasz Duszynski  * Apply traffic manager hierarchy.
845429c3944STomasz Duszynski  *
846429c3944STomasz Duszynski  * @param dev Pointer to the device.
847429c3944STomasz Duszynski  * @param clear_on_fail Flag indicating whether to do cleanup on the failure.
848429c3944STomasz Duszynski  * @param error Pointer to the error.
849429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
850429c3944STomasz Duszynski  */
851429c3944STomasz Duszynski static int
852429c3944STomasz Duszynski mrvl_hierarchy_commit(struct rte_eth_dev *dev, int clear_on_fail,
853429c3944STomasz Duszynski 		      struct rte_tm_error *error)
854429c3944STomasz Duszynski {
855429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
856429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
857429c3944STomasz Duszynski 	int ret;
858429c3944STomasz Duszynski 
859e622c1a8SDana Vardi 	if (!priv->configured)
860e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
861e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
862e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
863e622c1a8SDana Vardi 
864429c3944STomasz Duszynski 	if (priv->ppio) {
865429c3944STomasz Duszynski 		ret = -rte_tm_error_set(error, EPERM,
866429c3944STomasz Duszynski 					RTE_TM_ERROR_TYPE_UNSPECIFIED,
867429c3944STomasz Duszynski 					NULL, "Port is already started\n");
868429c3944STomasz Duszynski 		goto out;
869429c3944STomasz Duszynski 	}
870429c3944STomasz Duszynski 
871429c3944STomasz Duszynski 	LIST_FOREACH(node, &priv->nodes, next) {
872429c3944STomasz Duszynski 		struct pp2_ppio_outq_params *p;
873429c3944STomasz Duszynski 
874429c3944STomasz Duszynski 		if (node->type == MRVL_NODE_PORT) {
875429c3944STomasz Duszynski 			if (!node->profile)
876429c3944STomasz Duszynski 				continue;
877429c3944STomasz Duszynski 
878429c3944STomasz Duszynski 			priv->ppio_params.rate_limit_enable = 1;
879429c3944STomasz Duszynski 			priv->ppio_params.rate_limit_params.cir =
880429c3944STomasz Duszynski 				node->profile->params.peak.rate * 8 / 1000;
881429c3944STomasz Duszynski 			priv->ppio_params.rate_limit_params.cbs =
882429c3944STomasz Duszynski 				node->profile->params.peak.size / 1000;
883429c3944STomasz Duszynski 
884429c3944STomasz Duszynski 			MRVL_LOG(INFO,
885429c3944STomasz Duszynski 				"Port rate limit overrides txqs rate limit");
886429c3944STomasz Duszynski 
887429c3944STomasz Duszynski 			continue;
888429c3944STomasz Duszynski 		}
889429c3944STomasz Duszynski 
890429c3944STomasz Duszynski 		if (node->id >= dev->data->nb_tx_queues) {
891429c3944STomasz Duszynski 			ret = -rte_tm_error_set(error, EINVAL,
892429c3944STomasz Duszynski 					RTE_TM_ERROR_TYPE_NODE_ID, NULL,
893429c3944STomasz Duszynski 					"Not enough txqs are configured\n");
894429c3944STomasz Duszynski 			goto out;
895429c3944STomasz Duszynski 		}
896429c3944STomasz Duszynski 
897429c3944STomasz Duszynski 		p = &priv->ppio_params.outqs_params.outqs_params[node->id];
898429c3944STomasz Duszynski 
899429c3944STomasz Duszynski 		if (node->weight) {
900429c3944STomasz Duszynski 			p->sched_mode = PP2_PPIO_SCHED_M_WRR;
901429c3944STomasz Duszynski 			p->weight = node->weight;
902429c3944STomasz Duszynski 		} else {
903429c3944STomasz Duszynski 			p->sched_mode = PP2_PPIO_SCHED_M_SP;
904429c3944STomasz Duszynski 			p->weight = 0;
905429c3944STomasz Duszynski 		}
906429c3944STomasz Duszynski 
907429c3944STomasz Duszynski 		if (node->profile) {
908429c3944STomasz Duszynski 			p->rate_limit_enable = 1;
909429c3944STomasz Duszynski 			/* convert Bytes/s to kilo bits/s */
910429c3944STomasz Duszynski 			p->rate_limit_params.cir =
911429c3944STomasz Duszynski 				node->profile->params.peak.rate * 8 / 1000;
912429c3944STomasz Duszynski 			/* convert bits to kilo bits */
913429c3944STomasz Duszynski 			p->rate_limit_params.cbs =
914429c3944STomasz Duszynski 				node->profile->params.peak.size / 1000;
915429c3944STomasz Duszynski 		} else {
916429c3944STomasz Duszynski 			p->rate_limit_enable = 0;
917429c3944STomasz Duszynski 			p->rate_limit_params.cir = 0;
918429c3944STomasz Duszynski 			p->rate_limit_params.cbs = 0;
919429c3944STomasz Duszynski 		}
920429c3944STomasz Duszynski 	}
921429c3944STomasz Duszynski 
922429c3944STomasz Duszynski 	/* reset to defaults in case applied tm hierarchy is empty */
923429c3944STomasz Duszynski 	if (LIST_EMPTY(&priv->nodes)) {
924429c3944STomasz Duszynski 		int i;
925429c3944STomasz Duszynski 
926429c3944STomasz Duszynski 		for (i = 0; i < priv->ppio_params.outqs_params.num_outqs; i++) {
927429c3944STomasz Duszynski 			struct pp2_ppio_outq_params *p =
928429c3944STomasz Duszynski 				&priv->ppio_params.outqs_params.outqs_params[i];
929429c3944STomasz Duszynski 
930429c3944STomasz Duszynski 			p->sched_mode = PP2_PPIO_SCHED_M_WRR;
931429c3944STomasz Duszynski 			p->weight = 0;
932429c3944STomasz Duszynski 			p->rate_limit_enable = 0;
933429c3944STomasz Duszynski 			p->rate_limit_params.cir = 0;
934429c3944STomasz Duszynski 			p->rate_limit_params.cbs = 0;
935429c3944STomasz Duszynski 		}
936429c3944STomasz Duszynski 	}
937429c3944STomasz Duszynski 
938429c3944STomasz Duszynski 	return 0;
939429c3944STomasz Duszynski out:
940429c3944STomasz Duszynski 	if (clear_on_fail) {
941429c3944STomasz Duszynski 		mrvl_tm_deinit(dev);
942429c3944STomasz Duszynski 		mrvl_tm_init(dev);
943429c3944STomasz Duszynski 	}
944429c3944STomasz Duszynski 
945429c3944STomasz Duszynski 	return ret;
946429c3944STomasz Duszynski }
947429c3944STomasz Duszynski 
948429c3944STomasz Duszynski /**
949429c3944STomasz Duszynski  * Read statistics counters for current node.
950429c3944STomasz Duszynski  *
951429c3944STomasz Duszynski  * @param dev Pointer to the device.
952429c3944STomasz Duszynski  * @param node_id Id of the node.
953429c3944STomasz Duszynski  * @param stats Pointer to the statistics counters.
954429c3944STomasz Duszynski  * @param stats_mask Pointer to mask of enabled statistics counters
955429c3944STomasz Duszynski  *                   that are retrieved.
956429c3944STomasz Duszynski  * @param clear Flag indicating whether to clear statistics.
957429c3944STomasz Duszynski  *              Non-zero value clears statistics.
958429c3944STomasz Duszynski  * @param error Pointer to the error.
959429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
960429c3944STomasz Duszynski  */
961429c3944STomasz Duszynski static int
962429c3944STomasz Duszynski mrvl_node_stats_read(struct rte_eth_dev *dev, uint32_t node_id,
963429c3944STomasz Duszynski 		     struct rte_tm_node_stats *stats, uint64_t *stats_mask,
964429c3944STomasz Duszynski 		     int clear, struct rte_tm_error *error)
965429c3944STomasz Duszynski {
966429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
967429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
968429c3944STomasz Duszynski 	int ret;
969429c3944STomasz Duszynski 
970e622c1a8SDana Vardi 	if (!priv->configured)
971e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
972e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
973e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
974e622c1a8SDana Vardi 
975429c3944STomasz Duszynski 	if (!priv->ppio) {
976429c3944STomasz Duszynski 		return -rte_tm_error_set(error, EPERM,
977429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
978429c3944STomasz Duszynski 					 NULL, "Port is not started\n");
979429c3944STomasz Duszynski 	}
980429c3944STomasz Duszynski 
981429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
982429c3944STomasz Duszynski 	if (!node)
983429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
984429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
985429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
986429c3944STomasz Duszynski 
987429c3944STomasz Duszynski 	if (stats_mask)
988429c3944STomasz Duszynski 		*stats_mask = node->stats_mask;
989429c3944STomasz Duszynski 
990429c3944STomasz Duszynski 	if (!stats)
991429c3944STomasz Duszynski 		return 0;
992429c3944STomasz Duszynski 
993429c3944STomasz Duszynski 	memset(stats, 0, sizeof(*stats));
994429c3944STomasz Duszynski 
995429c3944STomasz Duszynski 	if (!node->parent) {
996429c3944STomasz Duszynski 		struct pp2_ppio_statistics s;
997429c3944STomasz Duszynski 
998429c3944STomasz Duszynski 		memset(&s, 0, sizeof(s));
999429c3944STomasz Duszynski 		ret = pp2_ppio_get_statistics(priv->ppio, &s, clear);
1000429c3944STomasz Duszynski 		if (ret)
1001429c3944STomasz Duszynski 			return -rte_tm_error_set(error, -ret,
1002429c3944STomasz Duszynski 					RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
1003429c3944STomasz Duszynski 					"Failed to read port statistics\n");
1004429c3944STomasz Duszynski 
1005429c3944STomasz Duszynski 		if (node->stats_mask & RTE_TM_STATS_N_PKTS)
1006429c3944STomasz Duszynski 			stats->n_pkts = s.tx_packets;
1007429c3944STomasz Duszynski 
1008429c3944STomasz Duszynski 		if (node->stats_mask & RTE_TM_STATS_N_BYTES)
1009429c3944STomasz Duszynski 			stats->n_bytes = s.tx_bytes;
1010429c3944STomasz Duszynski 	} else {
1011429c3944STomasz Duszynski 		struct pp2_ppio_outq_statistics s;
1012429c3944STomasz Duszynski 
1013429c3944STomasz Duszynski 		memset(&s, 0, sizeof(s));
1014429c3944STomasz Duszynski 		ret = pp2_ppio_outq_get_statistics(priv->ppio, node_id, &s,
1015429c3944STomasz Duszynski 						   clear);
1016429c3944STomasz Duszynski 		if (ret)
1017429c3944STomasz Duszynski 			return -rte_tm_error_set(error, -ret,
1018429c3944STomasz Duszynski 					RTE_TM_ERROR_TYPE_UNSPECIFIED, NULL,
1019429c3944STomasz Duszynski 					"Failed to read txq statistics\n");
1020429c3944STomasz Duszynski 
1021429c3944STomasz Duszynski 		if (node->stats_mask & RTE_TM_STATS_N_PKTS)
1022429c3944STomasz Duszynski 			stats->n_pkts = s.deq_desc;
1023429c3944STomasz Duszynski 	}
1024429c3944STomasz Duszynski 
1025429c3944STomasz Duszynski 	return 0;
1026429c3944STomasz Duszynski }
1027429c3944STomasz Duszynski 
1028429c3944STomasz Duszynski /**
1029429c3944STomasz Duszynski  * Update node statistics.
1030429c3944STomasz Duszynski  *
1031429c3944STomasz Duszynski  * @param dev Pointer to the device.
1032429c3944STomasz Duszynski  * @param node_id Id of the node.
1033429c3944STomasz Duszynski  * @param stats_mask Bitmask of statistics counters to be enabled.
1034429c3944STomasz Duszynski  * @param error Pointer to the error.
1035429c3944STomasz Duszynski  * @returns 0 on success, negative value otherwise.
1036429c3944STomasz Duszynski  */
1037429c3944STomasz Duszynski static int
1038429c3944STomasz Duszynski mrvl_node_stats_update(struct rte_eth_dev *dev, uint32_t node_id,
1039429c3944STomasz Duszynski 		       uint64_t stats_mask, struct rte_tm_error *error)
1040429c3944STomasz Duszynski {
1041429c3944STomasz Duszynski 	struct mrvl_priv *priv = dev->data->dev_private;
1042429c3944STomasz Duszynski 	struct mrvl_tm_node *node;
1043429c3944STomasz Duszynski 
1044e622c1a8SDana Vardi 	if (!priv->configured)
1045e622c1a8SDana Vardi 		return -rte_tm_error_set(error, ENODEV,
1046e622c1a8SDana Vardi 					 RTE_TM_ERROR_TYPE_UNSPECIFIED,
1047e622c1a8SDana Vardi 					 NULL, "Port didn't configured\n");
1048e622c1a8SDana Vardi 
1049429c3944STomasz Duszynski 	node = mrvl_node_from_id(priv, node_id);
1050429c3944STomasz Duszynski 	if (!node)
1051429c3944STomasz Duszynski 		return -rte_tm_error_set(error, ENODEV,
1052429c3944STomasz Duszynski 					 RTE_TM_ERROR_TYPE_NODE_ID,
1053429c3944STomasz Duszynski 					 NULL, "Node id does not exist\n");
1054429c3944STomasz Duszynski 
1055429c3944STomasz Duszynski 	if (!node->parent) {
1056429c3944STomasz Duszynski 		if (stats_mask & ~(RTE_TM_STATS_N_PKTS | RTE_TM_STATS_N_BYTES))
1057429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
1058429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
1059429c3944STomasz Duszynski 				NULL,
1060429c3944STomasz Duszynski 				"Requested port stats are not supported\n");
1061429c3944STomasz Duszynski 	} else {
1062429c3944STomasz Duszynski 		if (stats_mask & ~RTE_TM_STATS_N_PKTS)
1063429c3944STomasz Duszynski 			return -rte_tm_error_set(error, EINVAL,
1064429c3944STomasz Duszynski 				RTE_TM_ERROR_TYPE_NODE_PARAMS_STATS,
1065429c3944STomasz Duszynski 				NULL,
1066429c3944STomasz Duszynski 				"Requested txq stats are not supported\n");
1067429c3944STomasz Duszynski 	}
1068429c3944STomasz Duszynski 
1069429c3944STomasz Duszynski 	node->stats_mask = stats_mask;
1070429c3944STomasz Duszynski 
1071429c3944STomasz Duszynski 	return 0;
1072429c3944STomasz Duszynski }
1073429c3944STomasz Duszynski 
1074429c3944STomasz Duszynski const struct rte_tm_ops mrvl_tm_ops = {
1075429c3944STomasz Duszynski 	.node_type_get = mrvl_node_type_get,
1076429c3944STomasz Duszynski 	.capabilities_get = mrvl_capabilities_get,
1077429c3944STomasz Duszynski 	.level_capabilities_get = mrvl_level_capabilities_get,
1078429c3944STomasz Duszynski 	.node_capabilities_get = mrvl_node_capabilities_get,
1079429c3944STomasz Duszynski 	.shaper_profile_add = mrvl_shaper_profile_add,
1080429c3944STomasz Duszynski 	.shaper_profile_delete = mrvl_shaper_profile_delete,
1081429c3944STomasz Duszynski 	.node_add = mrvl_node_add,
1082429c3944STomasz Duszynski 	.node_delete = mrvl_node_delete,
1083429c3944STomasz Duszynski 	.node_suspend = mrvl_node_suspend,
1084429c3944STomasz Duszynski 	.node_resume = mrvl_node_resume,
1085429c3944STomasz Duszynski 	.hierarchy_commit = mrvl_hierarchy_commit,
1086429c3944STomasz Duszynski 	.node_stats_update = mrvl_node_stats_update,
1087429c3944STomasz Duszynski 	.node_stats_read = mrvl_node_stats_read,
1088429c3944STomasz Duszynski };
1089