1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(C) 2022 Marvell.
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},
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},
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] */
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,
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)
45 uint32_t schq = tm_node->hw_id;
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);
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));
56 switch (tm_node->hw_lvl) {
57 case NIX_TXSCH_LVL_SMQ:
58 reg[k] = NIX_AF_MDQX_SHAPE(schq);
61 case NIX_TXSCH_LVL_TL4:
62 reg[k] = NIX_AF_TL4X_SHAPE(schq);
65 case NIX_TXSCH_LVL_TL3:
66 reg[k] = NIX_AF_TL3X_SHAPE(schq);
69 case NIX_TXSCH_LVL_TL2:
70 reg[k] = NIX_AF_TL2X_SHAPE(schq);
80 /* Only called while device is stopped */
82 nix_tm_update_red_algo(struct nix *nix, bool red_send)
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;
91 list = nix_tm_node_list(nix, nix->tm_tree);
92 TAILQ_FOREACH(tm_node, list, node) {
94 if (nix_tm_is_leaf(nix, tm_node->lvl))
97 if (tm_node->hw_lvl == NIX_TXSCH_LVL_TL1)
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)))
105 /* Update Red algo */
107 tm_node->red_algo = NIX_REDALG_SEND;
109 tm_node->red_algo = NIX_REDALG_STD;
111 /* Update txschq config */
112 req = mbox_alloc_msg_nix_txschq_cfg(mbox);
116 req->lvl = tm_node->hw_lvl;
117 k = prepare_tm_shaper_red_algo(tm_node, req->reg, req->regval,
121 rc = mbox_process(mbox);
128 /* Return's true if queue reconfig is needed */
130 nix_tm_update_markfmt(struct nix *nix, enum roc_nix_tm_mark type,
131 int mark_yellow, int mark_red)
133 uint64_t new_markfmt, old_markfmt;
138 if (type >= ROC_NIX_TM_MARK_MAX)
141 /* Pre-allocated mark formats for type:color combinations */
142 tm_markfmt = nix->tm_markfmt[type];
144 if (!mark_yellow && !mark_red) {
145 /* Null format to disable */
146 new_markfmt = nix->tm_markfmt_null;
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];
154 new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_R];
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.
164 case ROC_NIX_TM_MARK_VLAN_DEI:
165 en_shift = NIX_TM_MARK_VLAN_DEI_SHIFT;
167 new_markfmt |= new_markfmt << 8;
169 case ROC_NIX_TM_MARK_IPV4_DSCP:
170 new_markfmt |= BIT_ULL(7);
171 en_shift = NIX_TM_MARK_IPV4_DSCP_SHIFT;
173 case ROC_NIX_TM_MARK_IPV4_ECN:
174 new_markfmt |= BIT_ULL(7);
175 en_shift = NIX_TM_MARK_IPV4_ECN_SHIFT;
177 case ROC_NIX_TM_MARK_IPV6_DSCP:
178 en_shift = NIX_TM_MARK_IPV6_DSCP_SHIFT;
180 case ROC_NIX_TM_MARK_IPV6_ECN:
181 new_markfmt |= BIT_ULL(7);
182 en_shift = NIX_TM_MARK_IPV6_ECN_SHIFT;
188 /* Skip if same as old config */
189 old_markfmt = (nix->tm_markfmt_en >> en_shift) & mask;
190 if (old_markfmt == new_markfmt)
193 /* Need queue reconfig */
194 nix->tm_markfmt_en &= ~(mask << en_shift);
195 nix->tm_markfmt_en |= (new_markfmt << en_shift);
201 nix_tm_mark_init(struct nix *nix)
203 struct mbox *mbox = (&nix->dev)->mbox;
204 struct nix_mark_format_cfg_rsp *rsp;
205 struct nix_mark_format_cfg *req;
208 /* Check for supported revisions */
209 if (roc_model_is_cn96_ax() || roc_model_is_cn95_a0())
212 /* Null mark format */
213 req = mbox_alloc_msg_nix_mark_format_cfg(mbox);
217 rc = mbox_process_msg(mbox, (void *)&rsp);
219 plt_err("TM failed to alloc null mark format, rc=%d", rc);
223 nix->tm_markfmt_null = rsp->mark_format_idx;
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);
232 req->offset = mark_off[i];
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];
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];
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];
251 rc = mbox_process_msg(mbox, (void *)&rsp);
253 plt_err("TM failed to alloc mark fmt "
254 "type %u color %u, rc=%d",
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]);
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);
275 roc_nix_tm_mark_config(struct roc_nix *roc_nix, enum roc_nix_tm_mark type,
276 int mark_yellow, int mark_red)
278 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
281 if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
284 rc = nix_tm_update_markfmt(nix, type, mark_yellow, mark_red);
288 if (!mark_yellow && !mark_red)
289 nix->tm_flags &= ~mark_flag[type];
291 nix->tm_flags |= mark_flag[type];
293 /* Update red algo for change in mark_red */
294 return nix_tm_update_red_algo(nix, !!mark_red);
298 roc_nix_tm_mark_format_get(struct roc_nix *roc_nix, uint64_t *flags)
300 struct nix *nix = roc_nix_to_nix_priv(roc_nix);
302 *flags = ((nix->tm_flags & NIX_TM_MARK_EN_MASK) >> 3);
303 return nix->tm_markfmt_en;