1e952c44ef96130d2854d5f585f09abcc67d00c8
[dpdk.git] / drivers / common / cnxk / roc_nix_tm_ops.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2021 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 int
9 roc_nix_tm_sq_aura_fc(struct roc_nix_sq *sq, bool enable)
10 {
11         struct npa_aq_enq_req *req;
12         struct npa_aq_enq_rsp *rsp;
13         uint64_t aura_handle;
14         struct npa_lf *lf;
15         struct mbox *mbox;
16         int rc = -ENOSPC;
17
18         plt_tm_dbg("Setting SQ %u SQB aura FC to %s", sq->qid,
19                    enable ? "enable" : "disable");
20
21         lf = idev_npa_obj_get();
22         if (!lf)
23                 return NPA_ERR_DEVICE_NOT_BOUNDED;
24
25         mbox = lf->mbox;
26         /* Set/clear sqb aura fc_ena */
27         aura_handle = sq->aura_handle;
28         req = mbox_alloc_msg_npa_aq_enq(mbox);
29         if (req == NULL)
30                 return rc;
31
32         req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
33         req->ctype = NPA_AQ_CTYPE_AURA;
34         req->op = NPA_AQ_INSTOP_WRITE;
35         /* Below is not needed for aura writes but AF driver needs it */
36         /* AF will translate to associated poolctx */
37         req->aura.pool_addr = req->aura_id;
38
39         req->aura.fc_ena = enable;
40         req->aura_mask.fc_ena = 1;
41
42         rc = mbox_process(mbox);
43         if (rc)
44                 return rc;
45
46         /* Read back npa aura ctx */
47         req = mbox_alloc_msg_npa_aq_enq(mbox);
48         if (req == NULL)
49                 return -ENOSPC;
50
51         req->aura_id = roc_npa_aura_handle_to_aura(aura_handle);
52         req->ctype = NPA_AQ_CTYPE_AURA;
53         req->op = NPA_AQ_INSTOP_READ;
54
55         rc = mbox_process_msg(mbox, (void *)&rsp);
56         if (rc)
57                 return rc;
58
59         /* Init when enabled as there might be no triggers */
60         if (enable)
61                 *(volatile uint64_t *)sq->fc = rsp->aura.count;
62         else
63                 *(volatile uint64_t *)sq->fc = sq->nb_sqb_bufs;
64         /* Sync write barrier */
65         plt_wmb();
66         return 0;
67 }
68
69 int
70 roc_nix_tm_free_resources(struct roc_nix *roc_nix, bool hw_only)
71 {
72         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
73
74         if (nix->tm_flags & NIX_TM_HIERARCHY_ENA)
75                 return -EBUSY;
76
77         return nix_tm_free_resources(roc_nix, BIT(ROC_NIX_TM_USER), hw_only);
78 }
79
80 static int
81 nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
82                           struct nix_tm_shaper_profile *profile, int skip_ins)
83 {
84         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
85         uint64_t commit_rate, commit_sz;
86         uint64_t peak_rate, peak_sz;
87         uint32_t id;
88
89         id = profile->id;
90         commit_rate = profile->commit.rate;
91         commit_sz = profile->commit.size;
92         peak_rate = profile->peak.rate;
93         peak_sz = profile->peak.size;
94
95         if (nix_tm_shaper_profile_search(nix, id) && !skip_ins)
96                 return NIX_ERR_TM_SHAPER_PROFILE_EXISTS;
97
98         if (profile->pkt_len_adj < NIX_TM_LENGTH_ADJUST_MIN ||
99             profile->pkt_len_adj > NIX_TM_LENGTH_ADJUST_MAX)
100                 return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
101
102         /* We cannot support both pkt length adjust and pkt mode */
103         if (profile->pkt_mode && profile->pkt_len_adj)
104                 return NIX_ERR_TM_SHAPER_PKT_LEN_ADJUST;
105
106         /* commit rate and burst size can be enabled/disabled */
107         if (commit_rate || commit_sz) {
108                 if (commit_sz < NIX_TM_MIN_SHAPER_BURST ||
109                     commit_sz > NIX_TM_MAX_SHAPER_BURST)
110                         return NIX_ERR_TM_INVALID_COMMIT_SZ;
111                 else if (!nix_tm_shaper_rate_conv(commit_rate, NULL, NULL,
112                                                   NULL))
113                         return NIX_ERR_TM_INVALID_COMMIT_RATE;
114         }
115
116         /* Peak rate and burst size can be enabled/disabled */
117         if (peak_sz || peak_rate) {
118                 if (peak_sz < NIX_TM_MIN_SHAPER_BURST ||
119                     peak_sz > NIX_TM_MAX_SHAPER_BURST)
120                         return NIX_ERR_TM_INVALID_PEAK_SZ;
121                 else if (!nix_tm_shaper_rate_conv(peak_rate, NULL, NULL, NULL))
122                         return NIX_ERR_TM_INVALID_PEAK_RATE;
123         }
124
125         if (!skip_ins)
126                 TAILQ_INSERT_TAIL(&nix->shaper_profile_list, profile, shaper);
127
128         plt_tm_dbg("Added TM shaper profile %u, "
129                    " pir %" PRIu64 " , pbs %" PRIu64 ", cir %" PRIu64
130                    ", cbs %" PRIu64 " , adj %u, pkt_mode %u",
131                    id, profile->peak.rate, profile->peak.size,
132                    profile->commit.rate, profile->commit.size,
133                    profile->pkt_len_adj, profile->pkt_mode);
134
135         /* Always use PIR for single rate shaping */
136         if (!peak_rate && commit_rate) {
137                 profile->peak.rate = profile->commit.rate;
138                 profile->peak.size = profile->commit.size;
139                 profile->commit.rate = 0;
140                 profile->commit.size = 0;
141         }
142
143         /* update min rate */
144         nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
145         return 0;
146 }
147
148 int
149 roc_nix_tm_shaper_profile_add(struct roc_nix *roc_nix,
150                               struct roc_nix_tm_shaper_profile *roc_profile)
151 {
152         struct nix_tm_shaper_profile *profile;
153
154         profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
155
156         profile->ref_cnt = 0;
157         profile->id = roc_profile->id;
158         if (roc_profile->pkt_mode) {
159                 /* Each packet accomulate single count, whereas HW
160                  * considers each unit as Byte, so we need convert
161                  * user pps to bps
162                  */
163                 profile->commit.rate = roc_profile->commit_rate * 8;
164                 profile->peak.rate = roc_profile->peak_rate * 8;
165         } else {
166                 profile->commit.rate = roc_profile->commit_rate;
167                 profile->peak.rate = roc_profile->peak_rate;
168         }
169         profile->commit.size = roc_profile->commit_sz;
170         profile->peak.size = roc_profile->peak_sz;
171         profile->pkt_len_adj = roc_profile->pkt_len_adj;
172         profile->pkt_mode = roc_profile->pkt_mode;
173         profile->free_fn = roc_profile->free_fn;
174
175         return nix_tm_shaper_profile_add(roc_nix, profile, 0);
176 }
177
178 int
179 roc_nix_tm_shaper_profile_update(struct roc_nix *roc_nix,
180                                  struct roc_nix_tm_shaper_profile *roc_profile)
181 {
182         struct nix_tm_shaper_profile *profile;
183
184         profile = (struct nix_tm_shaper_profile *)roc_profile->reserved;
185
186         if (roc_profile->pkt_mode) {
187                 /* Each packet accomulate single count, whereas HW
188                  * considers each unit as Byte, so we need convert
189                  * user pps to bps
190                  */
191                 profile->commit.rate = roc_profile->commit_rate * 8;
192                 profile->peak.rate = roc_profile->peak_rate * 8;
193         } else {
194                 profile->commit.rate = roc_profile->commit_rate;
195                 profile->peak.rate = roc_profile->peak_rate;
196         }
197         profile->commit.size = roc_profile->commit_sz;
198         profile->peak.size = roc_profile->peak_sz;
199
200         return nix_tm_shaper_profile_add(roc_nix, profile, 1);
201 }
202
203 int
204 roc_nix_tm_shaper_profile_delete(struct roc_nix *roc_nix, uint32_t id)
205 {
206         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
207         struct nix_tm_shaper_profile *profile;
208
209         profile = nix_tm_shaper_profile_search(nix, id);
210         if (!profile)
211                 return NIX_ERR_TM_INVALID_SHAPER_PROFILE;
212
213         if (profile->ref_cnt)
214                 return NIX_ERR_TM_SHAPER_PROFILE_IN_USE;
215
216         plt_tm_dbg("Removing TM shaper profile %u", id);
217         TAILQ_REMOVE(&nix->shaper_profile_list, profile, shaper);
218         nix_tm_shaper_profile_free(profile);
219
220         /* update min rate */
221         nix->tm_rate_min = nix_tm_shaper_profile_rate_min(nix);
222         return 0;
223 }
224
225 int
226 roc_nix_tm_node_add(struct roc_nix *roc_nix, struct roc_nix_tm_node *roc_node)
227 {
228         struct nix_tm_node *node;
229
230         node = (struct nix_tm_node *)&roc_node->reserved;
231         node->id = roc_node->id;
232         node->priority = roc_node->priority;
233         node->weight = roc_node->weight;
234         node->lvl = roc_node->lvl;
235         node->parent_id = roc_node->parent_id;
236         node->shaper_profile_id = roc_node->shaper_profile_id;
237         node->pkt_mode = roc_node->pkt_mode;
238         node->pkt_mode_set = roc_node->pkt_mode_set;
239         node->free_fn = roc_node->free_fn;
240         node->tree = ROC_NIX_TM_USER;
241
242         return nix_tm_node_add(roc_nix, node);
243 }
244
245 int
246 roc_nix_tm_node_pkt_mode_update(struct roc_nix *roc_nix, uint32_t node_id,
247                                 bool pkt_mode)
248 {
249         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
250         struct nix_tm_node *node, *child;
251         struct nix_tm_node_list *list;
252         int num_children = 0;
253
254         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
255         if (!node)
256                 return NIX_ERR_TM_INVALID_NODE;
257
258         if (node->pkt_mode == pkt_mode) {
259                 node->pkt_mode_set = true;
260                 return 0;
261         }
262
263         /* Check for any existing children, if there are any,
264          * then we cannot update the pkt mode as children's quantum
265          * are already taken in.
266          */
267         list = nix_tm_node_list(nix, ROC_NIX_TM_USER);
268         TAILQ_FOREACH(child, list, node) {
269                 if (child->parent == node)
270                         num_children++;
271         }
272
273         /* Cannot update mode if it has children or tree is enabled */
274         if ((nix->tm_flags & NIX_TM_HIERARCHY_ENA) && num_children)
275                 return -EBUSY;
276
277         if (node->pkt_mode_set && num_children)
278                 return NIX_ERR_TM_PKT_MODE_MISMATCH;
279
280         node->pkt_mode = pkt_mode;
281         node->pkt_mode_set = true;
282
283         return 0;
284 }
285
286 int
287 roc_nix_tm_node_name_get(struct roc_nix *roc_nix, uint32_t node_id, char *buf,
288                          size_t buflen)
289 {
290         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
291         struct nix_tm_node *node;
292
293         node = nix_tm_node_search(nix, node_id, ROC_NIX_TM_USER);
294         if (!node) {
295                 plt_strlcpy(buf, "???", buflen);
296                 return NIX_ERR_TM_INVALID_NODE;
297         }
298
299         if (node->hw_lvl == NIX_TXSCH_LVL_CNT)
300                 snprintf(buf, buflen, "SQ_%d", node->id);
301         else
302                 snprintf(buf, buflen, "%s_%d", nix_tm_hwlvl2str(node->hw_lvl),
303                          node->hw_id);
304         return 0;
305 }
306
307 int
308 roc_nix_tm_node_delete(struct roc_nix *roc_nix, uint32_t node_id, bool free)
309 {
310         return nix_tm_node_delete(roc_nix, node_id, ROC_NIX_TM_USER, free);
311 }