crypto/cnxk: move IPsec SA creation to common
[dpdk.git] / drivers / common / cnxk / roc_nix_tm_mark.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2022 Marvell.
3  */
4
5 #include "roc_api.h"
6 #include "roc_priv.h"
7
8 static const uint8_t y_mask_val[ROC_NIX_TM_MARK_MAX][2] = {
9         [ROC_NIX_TM_MARK_VLAN_DEI] = {0x0, 0x8},
10         [ROC_NIX_TM_MARK_IPV4_DSCP] = {0x1, 0x2},
11         [ROC_NIX_TM_MARK_IPV4_ECN] = {0x0, 0xc},
12         [ROC_NIX_TM_MARK_IPV6_DSCP] = {0x1, 0x2},
13         [ROC_NIX_TM_MARK_IPV6_ECN] = {0x0, 0x3},
14 };
15
16 static const uint8_t r_mask_val[ROC_NIX_TM_MARK_MAX][2] = {
17         [ROC_NIX_TM_MARK_VLAN_DEI] = {0x0, 0x8},
18         [ROC_NIX_TM_MARK_IPV4_DSCP] = {0x0, 0x3},
19         [ROC_NIX_TM_MARK_IPV4_ECN] = {0x0, 0xc},
20         [ROC_NIX_TM_MARK_IPV6_DSCP] = {0x0, 0x3},
21         [ROC_NIX_TM_MARK_IPV6_ECN] = {0x0, 0x3},
22 };
23
24 static const uint8_t mark_off[ROC_NIX_TM_MARK_MAX] = {
25         [ROC_NIX_TM_MARK_VLAN_DEI] = 0x3,  /* Byte 14 Bit[4:1] */
26         [ROC_NIX_TM_MARK_IPV4_DSCP] = 0x1, /* Byte 1 Bit[6:3] */
27         [ROC_NIX_TM_MARK_IPV4_ECN] = 0x6, /* Byte 1 Bit[1:0], Byte 2 Bit[7:6] */
28         [ROC_NIX_TM_MARK_IPV6_DSCP] = 0x5, /* Byte 0 Bit[2:0], Byte 1 Bit[7] */
29         [ROC_NIX_TM_MARK_IPV6_ECN] = 0x0,  /* Byte 1 Bit[7:4] */
30 };
31
32 static const uint64_t mark_flag[ROC_NIX_TM_MARK_MAX] = {
33         [ROC_NIX_TM_MARK_VLAN_DEI] = NIX_TM_MARK_VLAN_DEI_EN,
34         [ROC_NIX_TM_MARK_IPV4_DSCP] = NIX_TM_MARK_IP_DSCP_EN,
35         [ROC_NIX_TM_MARK_IPV4_ECN] = NIX_TM_MARK_IP_ECN_EN,
36         [ROC_NIX_TM_MARK_IPV6_DSCP] = NIX_TM_MARK_IP_DSCP_EN,
37         [ROC_NIX_TM_MARK_IPV6_ECN] = NIX_TM_MARK_IP_ECN_EN,
38 };
39
40 static uint8_t
41 prepare_tm_shaper_red_algo(struct nix_tm_node *tm_node, volatile uint64_t *reg,
42                            volatile uint64_t *regval,
43                            volatile uint64_t *regval_mask)
44 {
45         uint32_t schq = tm_node->hw_id;
46         uint8_t k = 0;
47
48         plt_tm_dbg("Shaper read alg node %s(%u) lvl %u id %u, red_alg %x (%p)",
49                    nix_tm_hwlvl2str(tm_node->hw_lvl), schq, tm_node->lvl,
50                    tm_node->id, tm_node->red_algo, tm_node);
51
52         /* Configure just RED algo */
53         regval[k] = ((uint64_t)tm_node->red_algo << 9);
54         regval_mask[k] = ~(BIT_ULL(10) | BIT_ULL(9));
55
56         switch (tm_node->hw_lvl) {
57         case NIX_TXSCH_LVL_SMQ:
58                 reg[k] = NIX_AF_MDQX_SHAPE(schq);
59                 k++;
60                 break;
61         case NIX_TXSCH_LVL_TL4:
62                 reg[k] = NIX_AF_TL4X_SHAPE(schq);
63                 k++;
64                 break;
65         case NIX_TXSCH_LVL_TL3:
66                 reg[k] = NIX_AF_TL3X_SHAPE(schq);
67                 k++;
68                 break;
69         case NIX_TXSCH_LVL_TL2:
70                 reg[k] = NIX_AF_TL2X_SHAPE(schq);
71                 k++;
72                 break;
73         default:
74                 break;
75         }
76
77         return k;
78 }
79
80 /* Only called while device is stopped */
81 static int
82 nix_tm_update_red_algo(struct nix *nix, bool red_send)
83 {
84         struct mbox *mbox = (&nix->dev)->mbox;
85         struct nix_txschq_config *req;
86         struct nix_tm_node_list *list;
87         struct nix_tm_node *tm_node;
88         uint8_t k;
89         int rc;
90
91         list = nix_tm_node_list(nix, nix->tm_tree);
92         TAILQ_FOREACH(tm_node, list, node) {
93                 /* Skip leaf nodes */
94                 if (nix_tm_is_leaf(nix, tm_node->lvl))
95                         continue;
96
97                 if (tm_node->hw_lvl == NIX_TXSCH_LVL_TL1)
98                         continue;
99
100                 /* Skip if no update of red_algo is needed */
101                 if ((red_send && (tm_node->red_algo == NIX_REDALG_SEND)) ||
102                     (!red_send && (tm_node->red_algo != NIX_REDALG_SEND)))
103                         continue;
104
105                 /* Update Red algo */
106                 if (red_send)
107                         tm_node->red_algo = NIX_REDALG_SEND;
108                 else
109                         tm_node->red_algo = NIX_REDALG_STD;
110
111                 /* Update txschq config  */
112                 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
113                 if (req == NULL)
114                         return -ENOSPC;
115
116                 req->lvl = tm_node->hw_lvl;
117                 k = prepare_tm_shaper_red_algo(tm_node, req->reg, req->regval,
118                                                req->regval_mask);
119                 req->num_regs = k;
120
121                 rc = mbox_process(mbox);
122                 if (rc)
123                         return rc;
124         }
125         return 0;
126 }
127
128 /* Return's true if queue reconfig is needed */
129 static bool
130 nix_tm_update_markfmt(struct nix *nix, enum roc_nix_tm_mark type,
131                       int mark_yellow, int mark_red)
132 {
133         uint64_t new_markfmt, old_markfmt;
134         uint8_t *tm_markfmt;
135         uint8_t en_shift;
136         uint64_t mask;
137
138         if (type >= ROC_NIX_TM_MARK_MAX)
139                 return false;
140
141         /* Pre-allocated mark formats for type:color combinations */
142         tm_markfmt = nix->tm_markfmt[type];
143
144         if (!mark_yellow && !mark_red) {
145                 /* Null format to disable */
146                 new_markfmt = nix->tm_markfmt_null;
147         } else {
148                 /* Marking enabled with combination of yellow and red */
149                 if (mark_yellow && mark_red)
150                         new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_Y_R];
151                 else if (mark_yellow)
152                         new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_Y];
153                 else
154                         new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_R];
155         }
156
157         mask = 0xFFull;
158         /* Format of fast path markfmt
159          * ipv6_ecn[8]:ipv4_ecn[8]:ipv6_dscp[8]:ipv4_dscp[8]:vlan_dei[16]
160          * fmt[7] = ptr offset for IPv4/IPv6 on l2_len.
161          * fmt[6:0] = markfmt idx.
162          */
163         switch (type) {
164         case ROC_NIX_TM_MARK_VLAN_DEI:
165                 en_shift = NIX_TM_MARK_VLAN_DEI_SHIFT;
166                 mask = 0xFFFFull;
167                 new_markfmt |= new_markfmt << 8;
168                 break;
169         case ROC_NIX_TM_MARK_IPV4_DSCP:
170                 new_markfmt |= BIT_ULL(7);
171                 en_shift = NIX_TM_MARK_IPV4_DSCP_SHIFT;
172                 break;
173         case ROC_NIX_TM_MARK_IPV4_ECN:
174                 new_markfmt |= BIT_ULL(7);
175                 en_shift = NIX_TM_MARK_IPV4_ECN_SHIFT;
176                 break;
177         case ROC_NIX_TM_MARK_IPV6_DSCP:
178                 en_shift = NIX_TM_MARK_IPV6_DSCP_SHIFT;
179                 break;
180         case ROC_NIX_TM_MARK_IPV6_ECN:
181                 new_markfmt |= BIT_ULL(7);
182                 en_shift = NIX_TM_MARK_IPV6_ECN_SHIFT;
183                 break;
184         default:
185                 return false;
186         }
187
188         /* Skip if same as old config */
189         old_markfmt = (nix->tm_markfmt_en >> en_shift) & mask;
190         if (old_markfmt == new_markfmt)
191                 return false;
192
193         /* Need queue reconfig */
194         nix->tm_markfmt_en &= ~(mask << en_shift);
195         nix->tm_markfmt_en |= (new_markfmt << en_shift);
196
197         return true;
198 }
199
200 int
201 nix_tm_mark_init(struct nix *nix)
202 {
203         struct mbox *mbox = (&nix->dev)->mbox;
204         struct nix_mark_format_cfg_rsp *rsp;
205         struct nix_mark_format_cfg *req;
206         int rc, i, j;
207
208         /* Check for supported revisions */
209         if (roc_model_is_cn96_ax() || roc_model_is_cn95_a0())
210                 return 0;
211
212         /* Null mark format */
213         req = mbox_alloc_msg_nix_mark_format_cfg(mbox);
214         if (req == NULL)
215                 return -ENOSPC;
216
217         rc = mbox_process_msg(mbox, (void *)&rsp);
218         if (rc) {
219                 plt_err("TM failed to alloc null mark format, rc=%d", rc);
220                 goto exit;
221         }
222
223         nix->tm_markfmt_null = rsp->mark_format_idx;
224
225         /* Alloc vlan, dscp, ecn mark formats */
226         for (i = 0; i < ROC_NIX_TM_MARK_MAX; i++) {
227                 for (j = 0; j < ROC_NIX_TM_MARK_COLOR_MAX; j++) {
228                         req = mbox_alloc_msg_nix_mark_format_cfg(mbox);
229                         if (req == NULL)
230                                 return -ENOSPC;
231
232                         req->offset = mark_off[i];
233
234                         switch (j) {
235                         case ROC_NIX_TM_MARK_COLOR_Y:
236                                 req->y_mask = y_mask_val[i][0];
237                                 req->y_val = y_mask_val[i][1];
238                                 break;
239                         case ROC_NIX_TM_MARK_COLOR_R:
240                                 req->r_mask = r_mask_val[i][0];
241                                 req->r_val = r_mask_val[i][1];
242                                 break;
243                         case ROC_NIX_TM_MARK_COLOR_Y_R:
244                                 req->y_mask = y_mask_val[i][0];
245                                 req->y_val = y_mask_val[i][1];
246                                 req->r_mask = r_mask_val[i][0];
247                                 req->r_val = r_mask_val[i][1];
248                                 break;
249                         }
250
251                         rc = mbox_process_msg(mbox, (void *)&rsp);
252                         if (rc) {
253                                 plt_err("TM failed to alloc mark fmt "
254                                         "type %u color %u, rc=%d",
255                                         i, j, rc);
256                                 goto exit;
257                         }
258
259                         nix->tm_markfmt[i][j] = rsp->mark_format_idx;
260                         plt_tm_dbg("Mark type: %u, Mark Color:%u, id:%u\n", i,
261                                    j, nix->tm_markfmt[i][j]);
262                 }
263         }
264         /* Update null mark format as default */
265         nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_VLAN_DEI, 0, 0);
266         nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV4_DSCP, 0, 0);
267         nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV4_ECN, 0, 0);
268         nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV6_DSCP, 0, 0);
269         nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV6_ECN, 0, 0);
270 exit:
271         return rc;
272 }
273
274 int
275 roc_nix_tm_mark_config(struct roc_nix *roc_nix, enum roc_nix_tm_mark type,
276                        int mark_yellow, int mark_red)
277 {
278         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
279         int rc;
280
281         if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
282                 return -EINVAL;
283
284         rc = nix_tm_update_markfmt(nix, type, mark_yellow, mark_red);
285         if (!rc)
286                 return 0;
287
288         if (!mark_yellow && !mark_red)
289                 nix->tm_flags &= ~mark_flag[type];
290         else
291                 nix->tm_flags |= mark_flag[type];
292
293         /* Update red algo for change in mark_red */
294         return nix_tm_update_red_algo(nix, !!mark_red);
295 }
296
297 uint64_t
298 roc_nix_tm_mark_format_get(struct roc_nix *roc_nix, uint64_t *flags)
299 {
300         struct nix *nix = roc_nix_to_nix_priv(roc_nix);
301
302         *flags = ((nix->tm_flags & NIX_TM_MARK_EN_MASK) >> 3);
303         return nix->tm_markfmt_en;
304 }