xref: /dpdk/drivers/common/cnxk/roc_nix_tm_mark.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
10b7e667eSSatha Rao /* SPDX-License-Identifier: BSD-3-Clause
20b7e667eSSatha Rao  * Copyright(C) 2022 Marvell.
30b7e667eSSatha Rao  */
40b7e667eSSatha Rao 
50b7e667eSSatha Rao #include "roc_api.h"
60b7e667eSSatha Rao #include "roc_priv.h"
70b7e667eSSatha Rao 
80b7e667eSSatha Rao static const uint8_t y_mask_val[ROC_NIX_TM_MARK_MAX][2] = {
90b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_VLAN_DEI] = {0x0, 0x8},
100b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_DSCP] = {0x1, 0x2},
110b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_ECN] = {0x0, 0xc},
120b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_DSCP] = {0x1, 0x2},
130b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_ECN] = {0x0, 0x3},
140b7e667eSSatha Rao };
150b7e667eSSatha Rao 
160b7e667eSSatha Rao static const uint8_t r_mask_val[ROC_NIX_TM_MARK_MAX][2] = {
170b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_VLAN_DEI] = {0x0, 0x8},
180b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_DSCP] = {0x0, 0x3},
190b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_ECN] = {0x0, 0xc},
200b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_DSCP] = {0x0, 0x3},
210b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_ECN] = {0x0, 0x3},
220b7e667eSSatha Rao };
230b7e667eSSatha Rao 
240b7e667eSSatha Rao static const uint8_t mark_off[ROC_NIX_TM_MARK_MAX] = {
250b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_VLAN_DEI] = 0x3,  /* Byte 14 Bit[4:1] */
260b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_DSCP] = 0x1, /* Byte 1 Bit[6:3] */
270b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_ECN] = 0x6, /* Byte 1 Bit[1:0], Byte 2 Bit[7:6] */
280b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_DSCP] = 0x5, /* Byte 0 Bit[2:0], Byte 1 Bit[7] */
290b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_ECN] = 0x0,  /* Byte 1 Bit[7:4] */
300b7e667eSSatha Rao };
310b7e667eSSatha Rao 
320b7e667eSSatha Rao static const uint64_t mark_flag[ROC_NIX_TM_MARK_MAX] = {
330b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_VLAN_DEI] = NIX_TM_MARK_VLAN_DEI_EN,
340b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_DSCP] = NIX_TM_MARK_IP_DSCP_EN,
350b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV4_ECN] = NIX_TM_MARK_IP_ECN_EN,
360b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_DSCP] = NIX_TM_MARK_IP_DSCP_EN,
370b7e667eSSatha Rao 	[ROC_NIX_TM_MARK_IPV6_ECN] = NIX_TM_MARK_IP_ECN_EN,
380b7e667eSSatha Rao };
390b7e667eSSatha Rao 
400b7e667eSSatha Rao static uint8_t
410b7e667eSSatha Rao prepare_tm_shaper_red_algo(struct nix_tm_node *tm_node, volatile uint64_t *reg,
420b7e667eSSatha Rao 			   volatile uint64_t *regval,
430b7e667eSSatha Rao 			   volatile uint64_t *regval_mask)
440b7e667eSSatha Rao {
450b7e667eSSatha Rao 	uint32_t schq = tm_node->hw_id;
460b7e667eSSatha Rao 	uint8_t k = 0;
470b7e667eSSatha Rao 
480b7e667eSSatha Rao 	plt_tm_dbg("Shaper read alg node %s(%u) lvl %u id %u, red_alg %x (%p)",
490b7e667eSSatha Rao 		   nix_tm_hwlvl2str(tm_node->hw_lvl), schq, tm_node->lvl,
500b7e667eSSatha Rao 		   tm_node->id, tm_node->red_algo, tm_node);
510b7e667eSSatha Rao 
520b7e667eSSatha Rao 	/* Configure just RED algo */
530b7e667eSSatha Rao 	regval[k] = ((uint64_t)tm_node->red_algo << 9);
540b7e667eSSatha Rao 	regval_mask[k] = ~(BIT_ULL(10) | BIT_ULL(9));
550b7e667eSSatha Rao 
560b7e667eSSatha Rao 	switch (tm_node->hw_lvl) {
570b7e667eSSatha Rao 	case NIX_TXSCH_LVL_SMQ:
580b7e667eSSatha Rao 		reg[k] = NIX_AF_MDQX_SHAPE(schq);
590b7e667eSSatha Rao 		k++;
600b7e667eSSatha Rao 		break;
610b7e667eSSatha Rao 	case NIX_TXSCH_LVL_TL4:
620b7e667eSSatha Rao 		reg[k] = NIX_AF_TL4X_SHAPE(schq);
630b7e667eSSatha Rao 		k++;
640b7e667eSSatha Rao 		break;
650b7e667eSSatha Rao 	case NIX_TXSCH_LVL_TL3:
660b7e667eSSatha Rao 		reg[k] = NIX_AF_TL3X_SHAPE(schq);
670b7e667eSSatha Rao 		k++;
680b7e667eSSatha Rao 		break;
690b7e667eSSatha Rao 	case NIX_TXSCH_LVL_TL2:
700b7e667eSSatha Rao 		reg[k] = NIX_AF_TL2X_SHAPE(schq);
710b7e667eSSatha Rao 		k++;
720b7e667eSSatha Rao 		break;
730b7e667eSSatha Rao 	default:
740b7e667eSSatha Rao 		break;
750b7e667eSSatha Rao 	}
760b7e667eSSatha Rao 
770b7e667eSSatha Rao 	return k;
780b7e667eSSatha Rao }
790b7e667eSSatha Rao 
800b7e667eSSatha Rao /* Only called while device is stopped */
810b7e667eSSatha Rao static int
820b7e667eSSatha Rao nix_tm_update_red_algo(struct nix *nix, bool red_send)
830b7e667eSSatha Rao {
840b7e667eSSatha Rao 	struct mbox *mbox = (&nix->dev)->mbox;
850b7e667eSSatha Rao 	struct nix_txschq_config *req;
860b7e667eSSatha Rao 	struct nix_tm_node_list *list;
870b7e667eSSatha Rao 	struct nix_tm_node *tm_node;
880b7e667eSSatha Rao 	uint8_t k;
890b7e667eSSatha Rao 	int rc;
900b7e667eSSatha Rao 
910b7e667eSSatha Rao 	list = nix_tm_node_list(nix, nix->tm_tree);
920b7e667eSSatha Rao 	TAILQ_FOREACH(tm_node, list, node) {
930b7e667eSSatha Rao 		/* Skip leaf nodes */
940b7e667eSSatha Rao 		if (nix_tm_is_leaf(nix, tm_node->lvl))
950b7e667eSSatha Rao 			continue;
960b7e667eSSatha Rao 
970b7e667eSSatha Rao 		if (tm_node->hw_lvl == NIX_TXSCH_LVL_TL1)
980b7e667eSSatha Rao 			continue;
990b7e667eSSatha Rao 
1000b7e667eSSatha Rao 		/* Skip if no update of red_algo is needed */
1010b7e667eSSatha Rao 		if ((red_send && (tm_node->red_algo == NIX_REDALG_SEND)) ||
1020b7e667eSSatha Rao 		    (!red_send && (tm_node->red_algo != NIX_REDALG_SEND)))
1030b7e667eSSatha Rao 			continue;
1040b7e667eSSatha Rao 
1050b7e667eSSatha Rao 		/* Update Red algo */
1060b7e667eSSatha Rao 		if (red_send)
1070b7e667eSSatha Rao 			tm_node->red_algo = NIX_REDALG_SEND;
1080b7e667eSSatha Rao 		else
1090b7e667eSSatha Rao 			tm_node->red_algo = NIX_REDALG_STD;
1100b7e667eSSatha Rao 
1110b7e667eSSatha Rao 		/* Update txschq config  */
11244a9307cSRakesh Kudurumalla 		req = mbox_alloc_msg_nix_txschq_cfg(mbox_get(mbox));
11344a9307cSRakesh Kudurumalla 		if (req == NULL) {
11444a9307cSRakesh Kudurumalla 			mbox_put(mbox);
115e746aec1SSatha Rao 			return -ENOSPC;
11644a9307cSRakesh Kudurumalla 		}
117e746aec1SSatha Rao 
1180b7e667eSSatha Rao 		req->lvl = tm_node->hw_lvl;
1190b7e667eSSatha Rao 		k = prepare_tm_shaper_red_algo(tm_node, req->reg, req->regval,
1200b7e667eSSatha Rao 					       req->regval_mask);
1210b7e667eSSatha Rao 		req->num_regs = k;
1220b7e667eSSatha Rao 
1230b7e667eSSatha Rao 		rc = mbox_process(mbox);
12444a9307cSRakesh Kudurumalla 		if (rc) {
12544a9307cSRakesh Kudurumalla 			mbox_put(mbox);
1260b7e667eSSatha Rao 			return rc;
1270b7e667eSSatha Rao 		}
12844a9307cSRakesh Kudurumalla 		mbox_put(mbox);
12944a9307cSRakesh Kudurumalla 	}
1300b7e667eSSatha Rao 	return 0;
1310b7e667eSSatha Rao }
1320b7e667eSSatha Rao 
1330b7e667eSSatha Rao /* Return's true if queue reconfig is needed */
1340b7e667eSSatha Rao static bool
1350b7e667eSSatha Rao nix_tm_update_markfmt(struct nix *nix, enum roc_nix_tm_mark type,
1360b7e667eSSatha Rao 		      int mark_yellow, int mark_red)
1370b7e667eSSatha Rao {
1380b7e667eSSatha Rao 	uint64_t new_markfmt, old_markfmt;
1390b7e667eSSatha Rao 	uint8_t *tm_markfmt;
1400b7e667eSSatha Rao 	uint8_t en_shift;
1410b7e667eSSatha Rao 	uint64_t mask;
1420b7e667eSSatha Rao 
1430b7e667eSSatha Rao 	if (type >= ROC_NIX_TM_MARK_MAX)
1440b7e667eSSatha Rao 		return false;
1450b7e667eSSatha Rao 
1460b7e667eSSatha Rao 	/* Pre-allocated mark formats for type:color combinations */
1470b7e667eSSatha Rao 	tm_markfmt = nix->tm_markfmt[type];
1480b7e667eSSatha Rao 
1490b7e667eSSatha Rao 	if (!mark_yellow && !mark_red) {
1500b7e667eSSatha Rao 		/* Null format to disable */
1510b7e667eSSatha Rao 		new_markfmt = nix->tm_markfmt_null;
1520b7e667eSSatha Rao 	} else {
1530b7e667eSSatha Rao 		/* Marking enabled with combination of yellow and red */
1540b7e667eSSatha Rao 		if (mark_yellow && mark_red)
1550b7e667eSSatha Rao 			new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_Y_R];
1560b7e667eSSatha Rao 		else if (mark_yellow)
1570b7e667eSSatha Rao 			new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_Y];
1580b7e667eSSatha Rao 		else
1590b7e667eSSatha Rao 			new_markfmt = tm_markfmt[ROC_NIX_TM_MARK_COLOR_R];
1600b7e667eSSatha Rao 	}
1610b7e667eSSatha Rao 
1620b7e667eSSatha Rao 	mask = 0xFFull;
1630b7e667eSSatha Rao 	/* Format of fast path markfmt
1640b7e667eSSatha Rao 	 * ipv6_ecn[8]:ipv4_ecn[8]:ipv6_dscp[8]:ipv4_dscp[8]:vlan_dei[16]
1650b7e667eSSatha Rao 	 * fmt[7] = ptr offset for IPv4/IPv6 on l2_len.
1660b7e667eSSatha Rao 	 * fmt[6:0] = markfmt idx.
1670b7e667eSSatha Rao 	 */
1680b7e667eSSatha Rao 	switch (type) {
1690b7e667eSSatha Rao 	case ROC_NIX_TM_MARK_VLAN_DEI:
1700b7e667eSSatha Rao 		en_shift = NIX_TM_MARK_VLAN_DEI_SHIFT;
1710b7e667eSSatha Rao 		mask = 0xFFFFull;
1720b7e667eSSatha Rao 		new_markfmt |= new_markfmt << 8;
1730b7e667eSSatha Rao 		break;
1740b7e667eSSatha Rao 	case ROC_NIX_TM_MARK_IPV4_DSCP:
1750b7e667eSSatha Rao 		new_markfmt |= BIT_ULL(7);
1760b7e667eSSatha Rao 		en_shift = NIX_TM_MARK_IPV4_DSCP_SHIFT;
1770b7e667eSSatha Rao 		break;
1780b7e667eSSatha Rao 	case ROC_NIX_TM_MARK_IPV4_ECN:
1790b7e667eSSatha Rao 		new_markfmt |= BIT_ULL(7);
1800b7e667eSSatha Rao 		en_shift = NIX_TM_MARK_IPV4_ECN_SHIFT;
1810b7e667eSSatha Rao 		break;
1820b7e667eSSatha Rao 	case ROC_NIX_TM_MARK_IPV6_DSCP:
1830b7e667eSSatha Rao 		en_shift = NIX_TM_MARK_IPV6_DSCP_SHIFT;
1840b7e667eSSatha Rao 		break;
1850b7e667eSSatha Rao 	case ROC_NIX_TM_MARK_IPV6_ECN:
1860b7e667eSSatha Rao 		new_markfmt |= BIT_ULL(7);
1870b7e667eSSatha Rao 		en_shift = NIX_TM_MARK_IPV6_ECN_SHIFT;
1880b7e667eSSatha Rao 		break;
1890b7e667eSSatha Rao 	default:
1900b7e667eSSatha Rao 		return false;
1910b7e667eSSatha Rao 	}
1920b7e667eSSatha Rao 
1930b7e667eSSatha Rao 	/* Skip if same as old config */
1940b7e667eSSatha Rao 	old_markfmt = (nix->tm_markfmt_en >> en_shift) & mask;
1950b7e667eSSatha Rao 	if (old_markfmt == new_markfmt)
1960b7e667eSSatha Rao 		return false;
1970b7e667eSSatha Rao 
1980b7e667eSSatha Rao 	/* Need queue reconfig */
1990b7e667eSSatha Rao 	nix->tm_markfmt_en &= ~(mask << en_shift);
2000b7e667eSSatha Rao 	nix->tm_markfmt_en |= (new_markfmt << en_shift);
2010b7e667eSSatha Rao 
2020b7e667eSSatha Rao 	return true;
2030b7e667eSSatha Rao }
2040b7e667eSSatha Rao 
2050b7e667eSSatha Rao int
2060b7e667eSSatha Rao nix_tm_mark_init(struct nix *nix)
2070b7e667eSSatha Rao {
20844a9307cSRakesh Kudurumalla 	struct mbox *mbox = mbox_get((&nix->dev)->mbox);
2090b7e667eSSatha Rao 	struct nix_mark_format_cfg_rsp *rsp;
2100b7e667eSSatha Rao 	struct nix_mark_format_cfg *req;
2110b7e667eSSatha Rao 	int rc, i, j;
2120b7e667eSSatha Rao 
2130b7e667eSSatha Rao 	/* Check for supported revisions */
21444a9307cSRakesh Kudurumalla 	if (roc_model_is_cn96_ax() || roc_model_is_cn95_a0()) {
21544a9307cSRakesh Kudurumalla 		rc = 0;
21644a9307cSRakesh Kudurumalla 		goto exit;
21744a9307cSRakesh Kudurumalla 	}
2180b7e667eSSatha Rao 
2190b7e667eSSatha Rao 	/* Null mark format */
2200b7e667eSSatha Rao 	req = mbox_alloc_msg_nix_mark_format_cfg(mbox);
22144a9307cSRakesh Kudurumalla 	if (req == NULL) {
22244a9307cSRakesh Kudurumalla 		rc =  -ENOSPC;
22344a9307cSRakesh Kudurumalla 		goto exit;
22444a9307cSRakesh Kudurumalla 	}
225e746aec1SSatha Rao 
2260b7e667eSSatha Rao 	rc = mbox_process_msg(mbox, (void *)&rsp);
2270b7e667eSSatha Rao 	if (rc) {
2280b7e667eSSatha Rao 		plt_err("TM failed to alloc null mark format, rc=%d", rc);
2290b7e667eSSatha Rao 		goto exit;
2300b7e667eSSatha Rao 	}
2310b7e667eSSatha Rao 
2320b7e667eSSatha Rao 	nix->tm_markfmt_null = rsp->mark_format_idx;
2330b7e667eSSatha Rao 
2340b7e667eSSatha Rao 	/* Alloc vlan, dscp, ecn mark formats */
2350b7e667eSSatha Rao 	for (i = 0; i < ROC_NIX_TM_MARK_MAX; i++) {
2360b7e667eSSatha Rao 		for (j = 0; j < ROC_NIX_TM_MARK_COLOR_MAX; j++) {
2370b7e667eSSatha Rao 			req = mbox_alloc_msg_nix_mark_format_cfg(mbox);
238e746aec1SSatha Rao 			if (req == NULL)
239e746aec1SSatha Rao 				return -ENOSPC;
240e746aec1SSatha Rao 
2410b7e667eSSatha Rao 			req->offset = mark_off[i];
2420b7e667eSSatha Rao 
2430b7e667eSSatha Rao 			switch (j) {
2440b7e667eSSatha Rao 			case ROC_NIX_TM_MARK_COLOR_Y:
2450b7e667eSSatha Rao 				req->y_mask = y_mask_val[i][0];
2460b7e667eSSatha Rao 				req->y_val = y_mask_val[i][1];
2470b7e667eSSatha Rao 				break;
2480b7e667eSSatha Rao 			case ROC_NIX_TM_MARK_COLOR_R:
2490b7e667eSSatha Rao 				req->r_mask = r_mask_val[i][0];
2500b7e667eSSatha Rao 				req->r_val = r_mask_val[i][1];
2510b7e667eSSatha Rao 				break;
2520b7e667eSSatha Rao 			case ROC_NIX_TM_MARK_COLOR_Y_R:
2530b7e667eSSatha Rao 				req->y_mask = y_mask_val[i][0];
2540b7e667eSSatha Rao 				req->y_val = y_mask_val[i][1];
2550b7e667eSSatha Rao 				req->r_mask = r_mask_val[i][0];
2560b7e667eSSatha Rao 				req->r_val = r_mask_val[i][1];
2570b7e667eSSatha Rao 				break;
2580b7e667eSSatha Rao 			}
2590b7e667eSSatha Rao 
2600b7e667eSSatha Rao 			rc = mbox_process_msg(mbox, (void *)&rsp);
2610b7e667eSSatha Rao 			if (rc) {
2620b7e667eSSatha Rao 				plt_err("TM failed to alloc mark fmt "
2630b7e667eSSatha Rao 					"type %u color %u, rc=%d",
2640b7e667eSSatha Rao 					i, j, rc);
2650b7e667eSSatha Rao 				goto exit;
2660b7e667eSSatha Rao 			}
2670b7e667eSSatha Rao 
2680b7e667eSSatha Rao 			nix->tm_markfmt[i][j] = rsp->mark_format_idx;
269*f665790aSDavid Marchand 			plt_tm_dbg("Mark type: %u, Mark Color:%u, id:%u", i,
2700b7e667eSSatha Rao 				   j, nix->tm_markfmt[i][j]);
2710b7e667eSSatha Rao 		}
2720b7e667eSSatha Rao 	}
2730b7e667eSSatha Rao 	/* Update null mark format as default */
2740b7e667eSSatha Rao 	nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_VLAN_DEI, 0, 0);
2750b7e667eSSatha Rao 	nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV4_DSCP, 0, 0);
2760b7e667eSSatha Rao 	nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV4_ECN, 0, 0);
2770b7e667eSSatha Rao 	nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV6_DSCP, 0, 0);
2780b7e667eSSatha Rao 	nix_tm_update_markfmt(nix, ROC_NIX_TM_MARK_IPV6_ECN, 0, 0);
2790b7e667eSSatha Rao exit:
28044a9307cSRakesh Kudurumalla 	mbox_put(mbox);
2810b7e667eSSatha Rao 	return rc;
2820b7e667eSSatha Rao }
2830b7e667eSSatha Rao 
2840b7e667eSSatha Rao int
2850b7e667eSSatha Rao roc_nix_tm_mark_config(struct roc_nix *roc_nix, enum roc_nix_tm_mark type,
2860b7e667eSSatha Rao 		       int mark_yellow, int mark_red)
2870b7e667eSSatha Rao {
2880b7e667eSSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
2890b7e667eSSatha Rao 	int rc;
2900b7e667eSSatha Rao 
2910b7e667eSSatha Rao 	if (!(nix->tm_flags & NIX_TM_HIERARCHY_ENA))
2920b7e667eSSatha Rao 		return -EINVAL;
2930b7e667eSSatha Rao 
2940b7e667eSSatha Rao 	rc = nix_tm_update_markfmt(nix, type, mark_yellow, mark_red);
2950b7e667eSSatha Rao 	if (!rc)
2960b7e667eSSatha Rao 		return 0;
2970b7e667eSSatha Rao 
2980b7e667eSSatha Rao 	if (!mark_yellow && !mark_red)
2990b7e667eSSatha Rao 		nix->tm_flags &= ~mark_flag[type];
3000b7e667eSSatha Rao 	else
3010b7e667eSSatha Rao 		nix->tm_flags |= mark_flag[type];
3020b7e667eSSatha Rao 
3030b7e667eSSatha Rao 	/* Update red algo for change in mark_red */
3040b7e667eSSatha Rao 	return nix_tm_update_red_algo(nix, !!mark_red);
3050b7e667eSSatha Rao }
3060b7e667eSSatha Rao 
3070b7e667eSSatha Rao uint64_t
3080b7e667eSSatha Rao roc_nix_tm_mark_format_get(struct roc_nix *roc_nix, uint64_t *flags)
3090b7e667eSSatha Rao {
3100b7e667eSSatha Rao 	struct nix *nix = roc_nix_to_nix_priv(roc_nix);
3110b7e667eSSatha Rao 
3120b7e667eSSatha Rao 	*flags = ((nix->tm_flags & NIX_TM_MARK_EN_MASK) >> 3);
3130b7e667eSSatha Rao 	return nix->tm_markfmt_en;
3140b7e667eSSatha Rao }
315