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