net/octeontx2: introduce traffic manager
[dpdk.git] / drivers / net / octeontx2 / otx2_tm.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4
5 #include <rte_malloc.h>
6
7 #include "otx2_ethdev.h"
8 #include "otx2_tm.h"
9
10 /* Use last LVL_CNT nodes as default nodes */
11 #define NIX_DEFAULT_NODE_ID_START (RTE_TM_NODE_ID_NULL - NIX_TXSCH_LVL_CNT)
12
13 enum otx2_tm_node_level {
14         OTX2_TM_LVL_ROOT = 0,
15         OTX2_TM_LVL_SCH1,
16         OTX2_TM_LVL_SCH2,
17         OTX2_TM_LVL_SCH3,
18         OTX2_TM_LVL_SCH4,
19         OTX2_TM_LVL_QUEUE,
20         OTX2_TM_LVL_MAX,
21 };
22
23 static bool
24 nix_tm_have_tl1_access(struct otx2_eth_dev *dev)
25 {
26         bool is_lbk = otx2_dev_is_lbk(dev);
27         return otx2_dev_is_pf(dev) && !otx2_dev_is_A0(dev) &&
28                 !is_lbk && !dev->maxvf;
29 }
30
31 static struct otx2_nix_tm_shaper_profile *
32 nix_tm_shaper_profile_search(struct otx2_eth_dev *dev, uint32_t shaper_id)
33 {
34         struct otx2_nix_tm_shaper_profile *tm_shaper_profile;
35
36         TAILQ_FOREACH(tm_shaper_profile, &dev->shaper_profile_list, shaper) {
37                 if (tm_shaper_profile->shaper_profile_id == shaper_id)
38                         return tm_shaper_profile;
39         }
40         return NULL;
41 }
42
43 static struct otx2_nix_tm_node *
44 nix_tm_node_search(struct otx2_eth_dev *dev,
45                    uint32_t node_id, bool user)
46 {
47         struct otx2_nix_tm_node *tm_node;
48
49         TAILQ_FOREACH(tm_node, &dev->node_list, node) {
50                 if (tm_node->id == node_id &&
51                     (user == !!(tm_node->flags & NIX_TM_NODE_USER)))
52                         return tm_node;
53         }
54         return NULL;
55 }
56
57 static int
58 nix_tm_node_add_to_list(struct otx2_eth_dev *dev, uint32_t node_id,
59                         uint32_t parent_node_id, uint32_t priority,
60                         uint32_t weight, uint16_t hw_lvl_id,
61                         uint16_t level_id, bool user,
62                         struct rte_tm_node_params *params)
63 {
64         struct otx2_nix_tm_shaper_profile *shaper_profile;
65         struct otx2_nix_tm_node *tm_node, *parent_node;
66         uint32_t shaper_profile_id;
67
68         shaper_profile_id = params->shaper_profile_id;
69         shaper_profile = nix_tm_shaper_profile_search(dev, shaper_profile_id);
70
71         parent_node = nix_tm_node_search(dev, parent_node_id, user);
72
73         tm_node = rte_zmalloc("otx2_nix_tm_node",
74                               sizeof(struct otx2_nix_tm_node), 0);
75         if (!tm_node)
76                 return -ENOMEM;
77
78         tm_node->level_id = level_id;
79         tm_node->hw_lvl_id = hw_lvl_id;
80
81         tm_node->id = node_id;
82         tm_node->priority = priority;
83         tm_node->weight = weight;
84         tm_node->rr_prio = 0xf;
85         tm_node->max_prio = UINT32_MAX;
86         tm_node->hw_id = UINT32_MAX;
87         tm_node->flags = 0;
88         if (user)
89                 tm_node->flags = NIX_TM_NODE_USER;
90         rte_memcpy(&tm_node->params, params, sizeof(struct rte_tm_node_params));
91
92         if (shaper_profile)
93                 shaper_profile->reference_count++;
94         tm_node->parent = parent_node;
95         tm_node->parent_hw_id = UINT32_MAX;
96
97         TAILQ_INSERT_TAIL(&dev->node_list, tm_node, node);
98
99         return 0;
100 }
101
102 static int
103 nix_tm_clear_shaper_profiles(struct otx2_eth_dev *dev)
104 {
105         struct otx2_nix_tm_shaper_profile *shaper_profile;
106
107         while ((shaper_profile = TAILQ_FIRST(&dev->shaper_profile_list))) {
108                 if (shaper_profile->reference_count)
109                         otx2_tm_dbg("Shaper profile %u has non zero references",
110                                     shaper_profile->shaper_profile_id);
111                 TAILQ_REMOVE(&dev->shaper_profile_list, shaper_profile, shaper);
112                 rte_free(shaper_profile);
113         }
114
115         return 0;
116 }
117
118 static int
119 nix_tm_prepare_default_tree(struct rte_eth_dev *eth_dev)
120 {
121         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
122         uint32_t def = eth_dev->data->nb_tx_queues;
123         struct rte_tm_node_params params;
124         uint32_t leaf_parent, i;
125         int rc = 0;
126
127         /* Default params */
128         memset(&params, 0, sizeof(params));
129         params.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
130
131         if (nix_tm_have_tl1_access(dev)) {
132                 dev->otx2_tm_root_lvl = NIX_TXSCH_LVL_TL1;
133                 rc = nix_tm_node_add_to_list(dev, def, RTE_TM_NODE_ID_NULL, 0,
134                                              DEFAULT_RR_WEIGHT,
135                                              NIX_TXSCH_LVL_TL1,
136                                              OTX2_TM_LVL_ROOT, false, &params);
137                 if (rc)
138                         goto exit;
139                 rc = nix_tm_node_add_to_list(dev, def + 1, def, 0,
140                                              DEFAULT_RR_WEIGHT,
141                                              NIX_TXSCH_LVL_TL2,
142                                              OTX2_TM_LVL_SCH1, false, &params);
143                 if (rc)
144                         goto exit;
145
146                 rc = nix_tm_node_add_to_list(dev, def + 2, def + 1, 0,
147                                              DEFAULT_RR_WEIGHT,
148                                              NIX_TXSCH_LVL_TL3,
149                                              OTX2_TM_LVL_SCH2, false, &params);
150                 if (rc)
151                         goto exit;
152
153                 rc = nix_tm_node_add_to_list(dev, def + 3, def + 2, 0,
154                                              DEFAULT_RR_WEIGHT,
155                                              NIX_TXSCH_LVL_TL4,
156                                              OTX2_TM_LVL_SCH3, false, &params);
157                 if (rc)
158                         goto exit;
159
160                 rc = nix_tm_node_add_to_list(dev, def + 4, def + 3, 0,
161                                              DEFAULT_RR_WEIGHT,
162                                              NIX_TXSCH_LVL_SMQ,
163                                              OTX2_TM_LVL_SCH4, false, &params);
164                 if (rc)
165                         goto exit;
166
167                 leaf_parent = def + 4;
168         } else {
169                 dev->otx2_tm_root_lvl = NIX_TXSCH_LVL_TL2;
170                 rc = nix_tm_node_add_to_list(dev, def, RTE_TM_NODE_ID_NULL, 0,
171                                              DEFAULT_RR_WEIGHT,
172                                              NIX_TXSCH_LVL_TL2,
173                                              OTX2_TM_LVL_ROOT, false, &params);
174                 if (rc)
175                         goto exit;
176
177                 rc = nix_tm_node_add_to_list(dev, def + 1, def, 0,
178                                              DEFAULT_RR_WEIGHT,
179                                              NIX_TXSCH_LVL_TL3,
180                                              OTX2_TM_LVL_SCH1, false, &params);
181                 if (rc)
182                         goto exit;
183
184                 rc = nix_tm_node_add_to_list(dev, def + 2, def + 1, 0,
185                                              DEFAULT_RR_WEIGHT,
186                                              NIX_TXSCH_LVL_TL4,
187                                              OTX2_TM_LVL_SCH2, false, &params);
188                 if (rc)
189                         goto exit;
190
191                 rc = nix_tm_node_add_to_list(dev, def + 3, def + 2, 0,
192                                              DEFAULT_RR_WEIGHT,
193                                              NIX_TXSCH_LVL_SMQ,
194                                              OTX2_TM_LVL_SCH3, false, &params);
195                 if (rc)
196                         goto exit;
197
198                 leaf_parent = def + 3;
199         }
200
201         /* Add leaf nodes */
202         for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
203                 rc = nix_tm_node_add_to_list(dev, i, leaf_parent, 0,
204                                              DEFAULT_RR_WEIGHT,
205                                              NIX_TXSCH_LVL_CNT,
206                                              OTX2_TM_LVL_QUEUE, false, &params);
207                 if (rc)
208                         break;
209         }
210
211 exit:
212         return rc;
213 }
214
215 void otx2_nix_tm_conf_init(struct rte_eth_dev *eth_dev)
216 {
217         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
218
219         TAILQ_INIT(&dev->node_list);
220         TAILQ_INIT(&dev->shaper_profile_list);
221 }
222
223 int otx2_nix_tm_init_default(struct rte_eth_dev *eth_dev)
224 {
225         struct otx2_eth_dev  *dev = otx2_eth_pmd_priv(eth_dev);
226         uint16_t sq_cnt = eth_dev->data->nb_tx_queues;
227         int rc;
228
229         /* Clear shaper profiles */
230         nix_tm_clear_shaper_profiles(dev);
231         dev->tm_flags = NIX_TM_DEFAULT_TREE;
232
233         rc = nix_tm_prepare_default_tree(eth_dev);
234         if (rc != 0)
235                 return rc;
236
237         dev->tm_leaf_cnt = sq_cnt;
238
239         return 0;
240 }
241
242 int
243 otx2_nix_tm_fini(struct rte_eth_dev *eth_dev)
244 {
245         struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
246
247         /* Clear shaper profiles */
248         nix_tm_clear_shaper_profiles(dev);
249
250         dev->tm_flags = 0;
251         return 0;
252 }