1d71d8381SJian Shen // SPDX-License-Identifier: GPL-2.0+
2d71d8381SJian Shen // Copyright (c) 2016-2017 Hisilicon Limited.
384844054SSalil 
484844054SSalil #include <linux/etherdevice.h>
584844054SSalil 
684844054SSalil #include "hclge_cmd.h"
784844054SSalil #include "hclge_main.h"
884844054SSalil #include "hclge_tm.h"
984844054SSalil 
1084844054SSalil enum hclge_shaper_level {
1184844054SSalil 	HCLGE_SHAPER_LVL_PRI	= 0,
1284844054SSalil 	HCLGE_SHAPER_LVL_PG	= 1,
1384844054SSalil 	HCLGE_SHAPER_LVL_PORT	= 2,
1484844054SSalil 	HCLGE_SHAPER_LVL_QSET	= 3,
1584844054SSalil 	HCLGE_SHAPER_LVL_CNT	= 4,
1684844054SSalil 	HCLGE_SHAPER_LVL_VF	= 0,
1784844054SSalil 	HCLGE_SHAPER_LVL_PF	= 1,
1884844054SSalil };
1984844054SSalil 
2064fd2300SPeng Li #define HCLGE_TM_PFC_PKT_GET_CMD_NUM	3
2164fd2300SPeng Li #define HCLGE_TM_PFC_NUM_GET_PER_CMD	3
2264fd2300SPeng Li 
233a7d5958SPeng Li #define HCLGE_SHAPER_BS_U_DEF	5
243a7d5958SPeng Li #define HCLGE_SHAPER_BS_S_DEF	20
2584844054SSalil 
2684844054SSalil /* hclge_shaper_para_calc: calculate ir parameter for the shaper
2784844054SSalil  * @ir: Rate to be config, its unit is Mbps
2884844054SSalil  * @shaper_level: the shaper level. eg: port, pg, priority, queueset
2984844054SSalil  * @ir_b: IR_B parameter of IR shaper
3084844054SSalil  * @ir_u: IR_U parameter of IR shaper
3184844054SSalil  * @ir_s: IR_S parameter of IR shaper
32d9c7d20dSGuangbin Huang  * @max_tm_rate: max tm rate is available to config
3384844054SSalil  *
3484844054SSalil  * the formula:
3584844054SSalil  *
3684844054SSalil  *		IR_b * (2 ^ IR_u) * 8
3784844054SSalil  * IR(Mbps) = -------------------------  *  CLOCK(1000Mbps)
3884844054SSalil  *		Tick * (2 ^ IR_s)
3984844054SSalil  *
4084844054SSalil  * @return: 0: calculate sucessful, negative: fail
4184844054SSalil  */
4284844054SSalil static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
43d9c7d20dSGuangbin Huang 				  u8 *ir_b, u8 *ir_u, u8 *ir_s,
44d9c7d20dSGuangbin Huang 				  u32 max_tm_rate)
4584844054SSalil {
46b37ce587SYufeng Mo #define DIVISOR_CLK		(1000 * 8)
47b37ce587SYufeng Mo #define DIVISOR_IR_B_126	(126 * DIVISOR_CLK)
48b37ce587SYufeng Mo 
493ea7af9eSColin Ian King 	static const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
5084844054SSalil 		6 * 256,        /* Prioriy level */
5184844054SSalil 		6 * 32,         /* Prioriy group level */
5284844054SSalil 		6 * 8,          /* Port level */
5384844054SSalil 		6 * 256         /* Qset level */
5484844054SSalil 	};
559b2f3477SWeihang Li 	u8 ir_u_calc = 0;
569b2f3477SWeihang Li 	u8 ir_s_calc = 0;
5784844054SSalil 	u32 ir_calc;
5884844054SSalil 	u32 tick;
5984844054SSalil 
6084844054SSalil 	/* Calc tick */
6104f25edbSYunsheng Lin 	if (shaper_level >= HCLGE_SHAPER_LVL_CNT ||
62d9c7d20dSGuangbin Huang 	    ir > max_tm_rate)
6384844054SSalil 		return -EINVAL;
6484844054SSalil 
6584844054SSalil 	tick = tick_array[shaper_level];
6684844054SSalil 
6784844054SSalil 	/**
6884844054SSalil 	 * Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0
6984844054SSalil 	 * the formula is changed to:
7084844054SSalil 	 *		126 * 1 * 8
7184844054SSalil 	 * ir_calc = ---------------- * 1000
7284844054SSalil 	 *		tick * 1
7384844054SSalil 	 */
74b37ce587SYufeng Mo 	ir_calc = (DIVISOR_IR_B_126 + (tick >> 1) - 1) / tick;
7584844054SSalil 
7684844054SSalil 	if (ir_calc == ir) {
7784844054SSalil 		*ir_b = 126;
7884844054SSalil 		*ir_u = 0;
7984844054SSalil 		*ir_s = 0;
8084844054SSalil 
8184844054SSalil 		return 0;
8284844054SSalil 	} else if (ir_calc > ir) {
8384844054SSalil 		/* Increasing the denominator to select ir_s value */
841a92497dSYonglong Liu 		while (ir_calc >= ir && ir) {
8584844054SSalil 			ir_s_calc++;
86b37ce587SYufeng Mo 			ir_calc = DIVISOR_IR_B_126 / (tick * (1 << ir_s_calc));
8784844054SSalil 		}
8884844054SSalil 
891a92497dSYonglong Liu 		*ir_b = (ir * tick * (1 << ir_s_calc) + (DIVISOR_CLK >> 1)) /
901a92497dSYonglong Liu 			DIVISOR_CLK;
9184844054SSalil 	} else {
9284844054SSalil 		/* Increasing the numerator to select ir_u value */
9384844054SSalil 		u32 numerator;
9484844054SSalil 
9584844054SSalil 		while (ir_calc < ir) {
9684844054SSalil 			ir_u_calc++;
97b37ce587SYufeng Mo 			numerator = DIVISOR_IR_B_126 * (1 << ir_u_calc);
9884844054SSalil 			ir_calc = (numerator + (tick >> 1)) / tick;
9984844054SSalil 		}
10084844054SSalil 
10184844054SSalil 		if (ir_calc == ir) {
10284844054SSalil 			*ir_b = 126;
10384844054SSalil 		} else {
1041a92497dSYonglong Liu 			u32 denominator = DIVISOR_CLK * (1 << --ir_u_calc);
10584844054SSalil 			*ir_b = (ir * tick + (denominator >> 1)) / denominator;
10684844054SSalil 		}
10784844054SSalil 	}
10884844054SSalil 
10984844054SSalil 	*ir_u = ir_u_calc;
11084844054SSalil 	*ir_s = ir_s_calc;
11184844054SSalil 
11284844054SSalil 	return 0;
11384844054SSalil }
11484844054SSalil 
11564fd2300SPeng Li static int hclge_pfc_stats_get(struct hclge_dev *hdev,
11664fd2300SPeng Li 			       enum hclge_opcode_type opcode, u64 *stats)
11764fd2300SPeng Li {
11864fd2300SPeng Li 	struct hclge_desc desc[HCLGE_TM_PFC_PKT_GET_CMD_NUM];
11964fd2300SPeng Li 	int ret, i, j;
12064fd2300SPeng Li 
12164fd2300SPeng Li 	if (!(opcode == HCLGE_OPC_QUERY_PFC_RX_PKT_CNT ||
12264fd2300SPeng Li 	      opcode == HCLGE_OPC_QUERY_PFC_TX_PKT_CNT))
12364fd2300SPeng Li 		return -EINVAL;
12464fd2300SPeng Li 
12563cbf7a9SYufeng Mo 	for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM - 1; i++) {
12664fd2300SPeng Li 		hclge_cmd_setup_basic_desc(&desc[i], opcode, true);
12764fd2300SPeng Li 		desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
12864fd2300SPeng Li 	}
12964fd2300SPeng Li 
13063cbf7a9SYufeng Mo 	hclge_cmd_setup_basic_desc(&desc[i], opcode, true);
13163cbf7a9SYufeng Mo 
13264fd2300SPeng Li 	ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_TM_PFC_PKT_GET_CMD_NUM);
13320670328SYunsheng Lin 	if (ret)
13464fd2300SPeng Li 		return ret;
13564fd2300SPeng Li 
13664fd2300SPeng Li 	for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM; i++) {
13764fd2300SPeng Li 		struct hclge_pfc_stats_cmd *pfc_stats =
13864fd2300SPeng Li 				(struct hclge_pfc_stats_cmd *)desc[i].data;
13964fd2300SPeng Li 
14064fd2300SPeng Li 		for (j = 0; j < HCLGE_TM_PFC_NUM_GET_PER_CMD; j++) {
14164fd2300SPeng Li 			u32 index = i * HCLGE_TM_PFC_PKT_GET_CMD_NUM + j;
14264fd2300SPeng Li 
14364fd2300SPeng Li 			if (index < HCLGE_MAX_TC_NUM)
14464fd2300SPeng Li 				stats[index] =
14564fd2300SPeng Li 					le64_to_cpu(pfc_stats->pkt_num[j]);
14664fd2300SPeng Li 		}
14764fd2300SPeng Li 	}
14864fd2300SPeng Li 	return 0;
14964fd2300SPeng Li }
15064fd2300SPeng Li 
15164fd2300SPeng Li int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats)
15264fd2300SPeng Li {
15364fd2300SPeng Li 	return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_RX_PKT_CNT, stats);
15464fd2300SPeng Li }
15564fd2300SPeng Li 
15664fd2300SPeng Li int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats)
15764fd2300SPeng Li {
15864fd2300SPeng Li 	return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_TX_PKT_CNT, stats);
15964fd2300SPeng Li }
16064fd2300SPeng Li 
16161387774SPeng Li int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
16284844054SSalil {
16384844054SSalil 	struct hclge_desc desc;
16484844054SSalil 
16584844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PAUSE_EN, false);
16684844054SSalil 
16784844054SSalil 	desc.data[0] = cpu_to_le32((tx ? HCLGE_TX_MAC_PAUSE_EN_MSK : 0) |
16884844054SSalil 		(rx ? HCLGE_RX_MAC_PAUSE_EN_MSK : 0));
16984844054SSalil 
17084844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
17184844054SSalil }
17284844054SSalil 
1739dc2145dSYunsheng Lin static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap,
1749dc2145dSYunsheng Lin 				  u8 pfc_bitmap)
1759dc2145dSYunsheng Lin {
1769dc2145dSYunsheng Lin 	struct hclge_desc desc;
177d0d72bacSJian Shen 	struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)desc.data;
1789dc2145dSYunsheng Lin 
1799dc2145dSYunsheng Lin 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_PFC_PAUSE_EN, false);
1809dc2145dSYunsheng Lin 
1819dc2145dSYunsheng Lin 	pfc->tx_rx_en_bitmap = tx_rx_bitmap;
1829dc2145dSYunsheng Lin 	pfc->pri_en_bitmap = pfc_bitmap;
1839dc2145dSYunsheng Lin 
1849dc2145dSYunsheng Lin 	return hclge_cmd_send(&hdev->hw, &desc, 1);
1859dc2145dSYunsheng Lin }
1869dc2145dSYunsheng Lin 
187e98d7183SFuyun Liang static int hclge_pause_param_cfg(struct hclge_dev *hdev, const u8 *addr,
18818838d0cSFuyun Liang 				 u8 pause_trans_gap, u16 pause_trans_time)
18918838d0cSFuyun Liang {
19018838d0cSFuyun Liang 	struct hclge_cfg_pause_param_cmd *pause_param;
19118838d0cSFuyun Liang 	struct hclge_desc desc;
19218838d0cSFuyun Liang 
193d0d72bacSJian Shen 	pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data;
19418838d0cSFuyun Liang 
19518838d0cSFuyun Liang 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, false);
19618838d0cSFuyun Liang 
19718838d0cSFuyun Liang 	ether_addr_copy(pause_param->mac_addr, addr);
198cd2086bfSFuyun Liang 	ether_addr_copy(pause_param->mac_addr_extra, addr);
19918838d0cSFuyun Liang 	pause_param->pause_trans_gap = pause_trans_gap;
20018838d0cSFuyun Liang 	pause_param->pause_trans_time = cpu_to_le16(pause_trans_time);
20118838d0cSFuyun Liang 
20218838d0cSFuyun Liang 	return hclge_cmd_send(&hdev->hw, &desc, 1);
20318838d0cSFuyun Liang }
20418838d0cSFuyun Liang 
205e98d7183SFuyun Liang int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr)
20618838d0cSFuyun Liang {
20718838d0cSFuyun Liang 	struct hclge_cfg_pause_param_cmd *pause_param;
20818838d0cSFuyun Liang 	struct hclge_desc desc;
20918838d0cSFuyun Liang 	u16 trans_time;
21018838d0cSFuyun Liang 	u8 trans_gap;
21118838d0cSFuyun Liang 	int ret;
21218838d0cSFuyun Liang 
213d0d72bacSJian Shen 	pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data;
21418838d0cSFuyun Liang 
21518838d0cSFuyun Liang 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, true);
21618838d0cSFuyun Liang 
21718838d0cSFuyun Liang 	ret = hclge_cmd_send(&hdev->hw, &desc, 1);
21818838d0cSFuyun Liang 	if (ret)
21918838d0cSFuyun Liang 		return ret;
22018838d0cSFuyun Liang 
22118838d0cSFuyun Liang 	trans_gap = pause_param->pause_trans_gap;
22218838d0cSFuyun Liang 	trans_time = le16_to_cpu(pause_param->pause_trans_time);
22318838d0cSFuyun Liang 
2249b2f3477SWeihang Li 	return hclge_pause_param_cfg(hdev, mac_addr, trans_gap, trans_time);
22518838d0cSFuyun Liang }
22618838d0cSFuyun Liang 
22784844054SSalil static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id)
22884844054SSalil {
22984844054SSalil 	u8 tc;
23084844054SSalil 
231c5795c53SYunsheng Lin 	tc = hdev->tm_info.prio_tc[pri_id];
23284844054SSalil 
23384844054SSalil 	if (tc >= hdev->tm_info.num_tc)
23484844054SSalil 		return -EINVAL;
23584844054SSalil 
23684844054SSalil 	/**
23784844054SSalil 	 * the register for priority has four bytes, the first bytes includes
23884844054SSalil 	 *  priority0 and priority1, the higher 4bit stands for priority1
23984844054SSalil 	 *  while the lower 4bit stands for priority0, as below:
24084844054SSalil 	 * first byte:	| pri_1 | pri_0 |
24184844054SSalil 	 * second byte:	| pri_3 | pri_2 |
24284844054SSalil 	 * third byte:	| pri_5 | pri_4 |
24384844054SSalil 	 * fourth byte:	| pri_7 | pri_6 |
24484844054SSalil 	 */
24584844054SSalil 	pri[pri_id >> 1] |= tc << ((pri_id & 1) * 4);
24684844054SSalil 
24784844054SSalil 	return 0;
24884844054SSalil }
24984844054SSalil 
25084844054SSalil static int hclge_up_to_tc_map(struct hclge_dev *hdev)
25184844054SSalil {
25284844054SSalil 	struct hclge_desc desc;
25384844054SSalil 	u8 *pri = (u8 *)desc.data;
25484844054SSalil 	u8 pri_id;
25584844054SSalil 	int ret;
25684844054SSalil 
25784844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, false);
25884844054SSalil 
259c5795c53SYunsheng Lin 	for (pri_id = 0; pri_id < HNAE3_MAX_USER_PRIO; pri_id++) {
26084844054SSalil 		ret = hclge_fill_pri_array(hdev, pri, pri_id);
26184844054SSalil 		if (ret)
26284844054SSalil 			return ret;
26384844054SSalil 	}
26484844054SSalil 
26584844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
26684844054SSalil }
26784844054SSalil 
26884844054SSalil static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev,
26984844054SSalil 				      u8 pg_id, u8 pri_bit_map)
27084844054SSalil {
27184844054SSalil 	struct hclge_pg_to_pri_link_cmd *map;
27284844054SSalil 	struct hclge_desc desc;
27384844054SSalil 
27484844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_TO_PRI_LINK, false);
27584844054SSalil 
27684844054SSalil 	map = (struct hclge_pg_to_pri_link_cmd *)desc.data;
27784844054SSalil 
27884844054SSalil 	map->pg_id = pg_id;
27984844054SSalil 	map->pri_bit_map = pri_bit_map;
28084844054SSalil 
28184844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
28284844054SSalil }
28384844054SSalil 
28484844054SSalil static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev,
28584844054SSalil 				      u16 qs_id, u8 pri)
28684844054SSalil {
28784844054SSalil 	struct hclge_qs_to_pri_link_cmd *map;
28884844054SSalil 	struct hclge_desc desc;
28984844054SSalil 
29084844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_TO_PRI_LINK, false);
29184844054SSalil 
29284844054SSalil 	map = (struct hclge_qs_to_pri_link_cmd *)desc.data;
29384844054SSalil 
29484844054SSalil 	map->qs_id = cpu_to_le16(qs_id);
29584844054SSalil 	map->priority = pri;
29684844054SSalil 	map->link_vld = HCLGE_TM_QS_PRI_LINK_VLD_MSK;
29784844054SSalil 
29884844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
29984844054SSalil }
30084844054SSalil 
30184844054SSalil static int hclge_tm_q_to_qs_map_cfg(struct hclge_dev *hdev,
30232c7fbc8SJian Shen 				    u16 q_id, u16 qs_id)
30384844054SSalil {
30484844054SSalil 	struct hclge_nq_to_qs_link_cmd *map;
30584844054SSalil 	struct hclge_desc desc;
30684844054SSalil 
30784844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NQ_TO_QS_LINK, false);
30884844054SSalil 
30984844054SSalil 	map = (struct hclge_nq_to_qs_link_cmd *)desc.data;
31084844054SSalil 
31184844054SSalil 	map->nq_id = cpu_to_le16(q_id);
31284844054SSalil 	map->qset_id = cpu_to_le16(qs_id | HCLGE_TM_Q_QS_LINK_VLD_MSK);
31384844054SSalil 
31484844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
31584844054SSalil }
31684844054SSalil 
31784844054SSalil static int hclge_tm_pg_weight_cfg(struct hclge_dev *hdev, u8 pg_id,
31884844054SSalil 				  u8 dwrr)
31984844054SSalil {
32084844054SSalil 	struct hclge_pg_weight_cmd *weight;
32184844054SSalil 	struct hclge_desc desc;
32284844054SSalil 
32384844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_WEIGHT, false);
32484844054SSalil 
32584844054SSalil 	weight = (struct hclge_pg_weight_cmd *)desc.data;
32684844054SSalil 
32784844054SSalil 	weight->pg_id = pg_id;
32884844054SSalil 	weight->dwrr = dwrr;
32984844054SSalil 
33084844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
33184844054SSalil }
33284844054SSalil 
33384844054SSalil static int hclge_tm_pri_weight_cfg(struct hclge_dev *hdev, u8 pri_id,
33484844054SSalil 				   u8 dwrr)
33584844054SSalil {
33684844054SSalil 	struct hclge_priority_weight_cmd *weight;
33784844054SSalil 	struct hclge_desc desc;
33884844054SSalil 
33984844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_WEIGHT, false);
34084844054SSalil 
34184844054SSalil 	weight = (struct hclge_priority_weight_cmd *)desc.data;
34284844054SSalil 
34384844054SSalil 	weight->pri_id = pri_id;
34484844054SSalil 	weight->dwrr = dwrr;
34584844054SSalil 
34684844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
34784844054SSalil }
34884844054SSalil 
34984844054SSalil static int hclge_tm_qs_weight_cfg(struct hclge_dev *hdev, u16 qs_id,
35084844054SSalil 				  u8 dwrr)
35184844054SSalil {
35284844054SSalil 	struct hclge_qs_weight_cmd *weight;
35384844054SSalil 	struct hclge_desc desc;
35484844054SSalil 
35584844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_WEIGHT, false);
35684844054SSalil 
35784844054SSalil 	weight = (struct hclge_qs_weight_cmd *)desc.data;
35884844054SSalil 
35984844054SSalil 	weight->qs_id = cpu_to_le16(qs_id);
36084844054SSalil 	weight->dwrr = dwrr;
36184844054SSalil 
36284844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
36384844054SSalil }
36484844054SSalil 
36563cbf7a9SYufeng Mo static u32 hclge_tm_get_shapping_para(u8 ir_b, u8 ir_u, u8 ir_s,
36663cbf7a9SYufeng Mo 				      u8 bs_b, u8 bs_s)
36763cbf7a9SYufeng Mo {
36863cbf7a9SYufeng Mo 	u32 shapping_para = 0;
36963cbf7a9SYufeng Mo 
37063cbf7a9SYufeng Mo 	hclge_tm_set_field(shapping_para, IR_B, ir_b);
37163cbf7a9SYufeng Mo 	hclge_tm_set_field(shapping_para, IR_U, ir_u);
37263cbf7a9SYufeng Mo 	hclge_tm_set_field(shapping_para, IR_S, ir_s);
37363cbf7a9SYufeng Mo 	hclge_tm_set_field(shapping_para, BS_B, bs_b);
37463cbf7a9SYufeng Mo 	hclge_tm_set_field(shapping_para, BS_S, bs_s);
37563cbf7a9SYufeng Mo 
37663cbf7a9SYufeng Mo 	return shapping_para;
37763cbf7a9SYufeng Mo }
37863cbf7a9SYufeng Mo 
37984844054SSalil static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev,
38084844054SSalil 				    enum hclge_shap_bucket bucket, u8 pg_id,
38163cbf7a9SYufeng Mo 				    u32 shapping_para)
38284844054SSalil {
38384844054SSalil 	struct hclge_pg_shapping_cmd *shap_cfg_cmd;
38484844054SSalil 	enum hclge_opcode_type opcode;
38584844054SSalil 	struct hclge_desc desc;
38684844054SSalil 
38784844054SSalil 	opcode = bucket ? HCLGE_OPC_TM_PG_P_SHAPPING :
38884844054SSalil 		 HCLGE_OPC_TM_PG_C_SHAPPING;
38984844054SSalil 	hclge_cmd_setup_basic_desc(&desc, opcode, false);
39084844054SSalil 
39184844054SSalil 	shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data;
39284844054SSalil 
39384844054SSalil 	shap_cfg_cmd->pg_id = pg_id;
39484844054SSalil 
395a90bb9a5SYunsheng Lin 	shap_cfg_cmd->pg_shapping_para = cpu_to_le32(shapping_para);
39684844054SSalil 
39784844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
39884844054SSalil }
39984844054SSalil 
4000a5677d3SYunsheng Lin static int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev)
4010a5677d3SYunsheng Lin {
4020a5677d3SYunsheng Lin 	struct hclge_port_shapping_cmd *shap_cfg_cmd;
4030a5677d3SYunsheng Lin 	struct hclge_desc desc;
4040a5677d3SYunsheng Lin 	u8 ir_u, ir_b, ir_s;
405cdd332acSGuojia Liao 	u32 shapping_para;
4060a5677d3SYunsheng Lin 	int ret;
4070a5677d3SYunsheng Lin 
408d9ea1562SYunsheng Lin 	ret = hclge_shaper_para_calc(hdev->hw.mac.speed,
4090a5677d3SYunsheng Lin 				     HCLGE_SHAPER_LVL_PORT,
410d9c7d20dSGuangbin Huang 				     &ir_b, &ir_u, &ir_s,
411d9c7d20dSGuangbin Huang 				     hdev->ae_dev->dev_specs.max_tm_rate);
4120a5677d3SYunsheng Lin 	if (ret)
4130a5677d3SYunsheng Lin 		return ret;
4140a5677d3SYunsheng Lin 
4150a5677d3SYunsheng Lin 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PORT_SHAPPING, false);
4160a5677d3SYunsheng Lin 	shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data;
4170a5677d3SYunsheng Lin 
41863cbf7a9SYufeng Mo 	shapping_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s,
41963cbf7a9SYufeng Mo 						   HCLGE_SHAPER_BS_U_DEF,
42063cbf7a9SYufeng Mo 						   HCLGE_SHAPER_BS_S_DEF);
4210a5677d3SYunsheng Lin 
4220a5677d3SYunsheng Lin 	shap_cfg_cmd->port_shapping_para = cpu_to_le32(shapping_para);
4230a5677d3SYunsheng Lin 
4240a5677d3SYunsheng Lin 	return hclge_cmd_send(&hdev->hw, &desc, 1);
4250a5677d3SYunsheng Lin }
4260a5677d3SYunsheng Lin 
42784844054SSalil static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev,
42884844054SSalil 				     enum hclge_shap_bucket bucket, u8 pri_id,
42963cbf7a9SYufeng Mo 				     u32 shapping_para)
43084844054SSalil {
43184844054SSalil 	struct hclge_pri_shapping_cmd *shap_cfg_cmd;
43284844054SSalil 	enum hclge_opcode_type opcode;
43384844054SSalil 	struct hclge_desc desc;
43484844054SSalil 
43584844054SSalil 	opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING :
43684844054SSalil 		 HCLGE_OPC_TM_PRI_C_SHAPPING;
43784844054SSalil 
43884844054SSalil 	hclge_cmd_setup_basic_desc(&desc, opcode, false);
43984844054SSalil 
44084844054SSalil 	shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data;
44184844054SSalil 
44284844054SSalil 	shap_cfg_cmd->pri_id = pri_id;
44384844054SSalil 
444a90bb9a5SYunsheng Lin 	shap_cfg_cmd->pri_shapping_para = cpu_to_le32(shapping_para);
44584844054SSalil 
44684844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
44784844054SSalil }
44884844054SSalil 
44984844054SSalil static int hclge_tm_pg_schd_mode_cfg(struct hclge_dev *hdev, u8 pg_id)
45084844054SSalil {
45184844054SSalil 	struct hclge_desc desc;
45284844054SSalil 
45384844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, false);
45484844054SSalil 
45584844054SSalil 	if (hdev->tm_info.pg_info[pg_id].pg_sch_mode == HCLGE_SCH_MODE_DWRR)
45684844054SSalil 		desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
45784844054SSalil 	else
45884844054SSalil 		desc.data[1] = 0;
45984844054SSalil 
46084844054SSalil 	desc.data[0] = cpu_to_le32(pg_id);
46184844054SSalil 
46284844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
46384844054SSalil }
46484844054SSalil 
46584844054SSalil static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id)
46684844054SSalil {
46784844054SSalil 	struct hclge_desc desc;
46884844054SSalil 
46984844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, false);
47084844054SSalil 
47184844054SSalil 	if (hdev->tm_info.tc_info[pri_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR)
47284844054SSalil 		desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
47384844054SSalil 	else
47484844054SSalil 		desc.data[1] = 0;
47584844054SSalil 
47684844054SSalil 	desc.data[0] = cpu_to_le32(pri_id);
47784844054SSalil 
47884844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
47984844054SSalil }
48084844054SSalil 
481cc9bb43aSYunsheng Lin static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id, u8 mode)
48284844054SSalil {
48384844054SSalil 	struct hclge_desc desc;
48484844054SSalil 
48584844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false);
48684844054SSalil 
487cc9bb43aSYunsheng Lin 	if (mode == HCLGE_SCH_MODE_DWRR)
48884844054SSalil 		desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK);
48984844054SSalil 	else
49084844054SSalil 		desc.data[1] = 0;
49184844054SSalil 
49284844054SSalil 	desc.data[0] = cpu_to_le32(qs_id);
49384844054SSalil 
49484844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
49584844054SSalil }
49684844054SSalil 
49767bf2541SYunsheng Lin static int hclge_tm_qs_bp_cfg(struct hclge_dev *hdev, u8 tc, u8 grp_id,
49867bf2541SYunsheng Lin 			      u32 bit_map)
49984844054SSalil {
50084844054SSalil 	struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd;
50184844054SSalil 	struct hclge_desc desc;
50284844054SSalil 
50384844054SSalil 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_BP_TO_QSET_MAPPING,
50484844054SSalil 				   false);
50584844054SSalil 
50684844054SSalil 	bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data;
50784844054SSalil 
50884844054SSalil 	bp_to_qs_map_cmd->tc_id = tc;
50967bf2541SYunsheng Lin 	bp_to_qs_map_cmd->qs_group_id = grp_id;
51067bf2541SYunsheng Lin 	bp_to_qs_map_cmd->qs_bit_map = cpu_to_le32(bit_map);
51184844054SSalil 
51284844054SSalil 	return hclge_cmd_send(&hdev->hw, &desc, 1);
51384844054SSalil }
51484844054SSalil 
515ee9e4424SYonglong Liu int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate)
516ee9e4424SYonglong Liu {
517ee9e4424SYonglong Liu 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
518ee9e4424SYonglong Liu 	struct hclge_qs_shapping_cmd *shap_cfg_cmd;
519ee9e4424SYonglong Liu 	struct hclge_dev *hdev = vport->back;
520ee9e4424SYonglong Liu 	struct hclge_desc desc;
521ee9e4424SYonglong Liu 	u8 ir_b, ir_u, ir_s;
522ee9e4424SYonglong Liu 	u32 shaper_para;
523ee9e4424SYonglong Liu 	int ret, i;
524ee9e4424SYonglong Liu 
525ee9e4424SYonglong Liu 	if (!max_tx_rate)
526d9c7d20dSGuangbin Huang 		max_tx_rate = hdev->ae_dev->dev_specs.max_tm_rate;
527ee9e4424SYonglong Liu 
528ee9e4424SYonglong Liu 	ret = hclge_shaper_para_calc(max_tx_rate, HCLGE_SHAPER_LVL_QSET,
529d9c7d20dSGuangbin Huang 				     &ir_b, &ir_u, &ir_s,
530d9c7d20dSGuangbin Huang 				     hdev->ae_dev->dev_specs.max_tm_rate);
531ee9e4424SYonglong Liu 	if (ret)
532ee9e4424SYonglong Liu 		return ret;
533ee9e4424SYonglong Liu 
534ee9e4424SYonglong Liu 	shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s,
535ee9e4424SYonglong Liu 						 HCLGE_SHAPER_BS_U_DEF,
536ee9e4424SYonglong Liu 						 HCLGE_SHAPER_BS_S_DEF);
537ee9e4424SYonglong Liu 
538ee9e4424SYonglong Liu 	for (i = 0; i < kinfo->num_tc; i++) {
539ee9e4424SYonglong Liu 		hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG,
540ee9e4424SYonglong Liu 					   false);
541ee9e4424SYonglong Liu 
542ee9e4424SYonglong Liu 		shap_cfg_cmd = (struct hclge_qs_shapping_cmd *)desc.data;
543ee9e4424SYonglong Liu 		shap_cfg_cmd->qs_id = cpu_to_le16(vport->qs_offset + i);
544ee9e4424SYonglong Liu 		shap_cfg_cmd->qs_shapping_para = cpu_to_le32(shaper_para);
545ee9e4424SYonglong Liu 
546ee9e4424SYonglong Liu 		ret = hclge_cmd_send(&hdev->hw, &desc, 1);
547ee9e4424SYonglong Liu 		if (ret) {
548ee9e4424SYonglong Liu 			dev_err(&hdev->pdev->dev,
549adcf738bSGuojia Liao 				"vf%u, qs%u failed to set tx_rate:%d, ret=%d\n",
550ee9e4424SYonglong Liu 				vport->vport_id, shap_cfg_cmd->qs_id,
551ee9e4424SYonglong Liu 				max_tx_rate, ret);
552ee9e4424SYonglong Liu 			return ret;
553ee9e4424SYonglong Liu 		}
554ee9e4424SYonglong Liu 	}
555ee9e4424SYonglong Liu 
556ee9e4424SYonglong Liu 	return 0;
557ee9e4424SYonglong Liu }
558ee9e4424SYonglong Liu 
55984844054SSalil static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
56084844054SSalil {
56184844054SSalil 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
56284844054SSalil 	struct hclge_dev *hdev = vport->back;
563672ad0edSHuazhong Tan 	u16 max_rss_size;
56484844054SSalil 	u8 i;
56584844054SSalil 
566de67a690SYunsheng Lin 	/* TC configuration is shared by PF/VF in one port, only allow
567de67a690SYunsheng Lin 	 * one tc for VF for simplicity. VF's vport_id is non zero.
568de67a690SYunsheng Lin 	 */
569de67a690SYunsheng Lin 	kinfo->num_tc = vport->vport_id ? 1 :
570de67a690SYunsheng Lin 			min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc);
57119eb1123SYonglong Liu 	vport->qs_offset = (vport->vport_id ? HNAE3_MAX_TC : 0) +
572de67a690SYunsheng Lin 				(vport->vport_id ? (vport->vport_id - 1) : 0);
573de67a690SYunsheng Lin 
574672ad0edSHuazhong Tan 	max_rss_size = min_t(u16, hdev->rss_size_max,
575672ad0edSHuazhong Tan 			     vport->alloc_tqps / kinfo->num_tc);
576672ad0edSHuazhong Tan 
5779b2f3477SWeihang Li 	/* Set to user value, no larger than max_rss_size. */
578672ad0edSHuazhong Tan 	if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
579672ad0edSHuazhong Tan 	    kinfo->req_rss_size <= max_rss_size) {
580adcf738bSGuojia Liao 		dev_info(&hdev->pdev->dev, "rss changes from %u to %u\n",
581672ad0edSHuazhong Tan 			 kinfo->rss_size, kinfo->req_rss_size);
582672ad0edSHuazhong Tan 		kinfo->rss_size = kinfo->req_rss_size;
583672ad0edSHuazhong Tan 	} else if (kinfo->rss_size > max_rss_size ||
584672ad0edSHuazhong Tan 		   (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) {
585580a05f9SYonglong Liu 		/* if user not set rss, the rss_size should compare with the
586580a05f9SYonglong Liu 		 * valid msi numbers to ensure one to one map between tqp and
587580a05f9SYonglong Liu 		 * irq as default.
588580a05f9SYonglong Liu 		 */
589580a05f9SYonglong Liu 		if (!kinfo->req_rss_size)
590580a05f9SYonglong Liu 			max_rss_size = min_t(u16, max_rss_size,
591580a05f9SYonglong Liu 					     (hdev->num_nic_msi - 1) /
592580a05f9SYonglong Liu 					     kinfo->num_tc);
593580a05f9SYonglong Liu 
5949b2f3477SWeihang Li 		/* Set to the maximum specification value (max_rss_size). */
595672ad0edSHuazhong Tan 		kinfo->rss_size = max_rss_size;
596672ad0edSHuazhong Tan 	}
597672ad0edSHuazhong Tan 
598672ad0edSHuazhong Tan 	kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size;
59984844054SSalil 	vport->dwrr = 100;  /* 100 percent as init */
60068ece54eSYunsheng Lin 	vport->alloc_rss_size = kinfo->rss_size;
601de67a690SYunsheng Lin 	vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit;
60284844054SSalil 
603af958827SHuazhong Tan 	for (i = 0; i < HNAE3_MAX_TC; i++) {
604de67a690SYunsheng Lin 		if (hdev->hw_tc_map & BIT(i) && i < kinfo->num_tc) {
60584844054SSalil 			kinfo->tc_info[i].enable = true;
60684844054SSalil 			kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size;
60784844054SSalil 			kinfo->tc_info[i].tqp_count = kinfo->rss_size;
60884844054SSalil 			kinfo->tc_info[i].tc = i;
60984844054SSalil 		} else {
61084844054SSalil 			/* Set to default queue if TC is disable */
61184844054SSalil 			kinfo->tc_info[i].enable = false;
61284844054SSalil 			kinfo->tc_info[i].tqp_offset = 0;
61384844054SSalil 			kinfo->tc_info[i].tqp_count = 1;
61484844054SSalil 			kinfo->tc_info[i].tc = 0;
61584844054SSalil 		}
61684844054SSalil 	}
617c5795c53SYunsheng Lin 
618c5795c53SYunsheng Lin 	memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc,
619c593642cSPankaj Bharadiya 	       sizeof_field(struct hnae3_knic_private_info, prio_tc));
62084844054SSalil }
62184844054SSalil 
62284844054SSalil static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
62384844054SSalil {
62484844054SSalil 	struct hclge_vport *vport = hdev->vport;
62584844054SSalil 	u32 i;
62684844054SSalil 
62784844054SSalil 	for (i = 0; i < hdev->num_alloc_vport; i++) {
62884844054SSalil 		hclge_tm_vport_tc_info_update(vport);
62984844054SSalil 
63084844054SSalil 		vport++;
63184844054SSalil 	}
63284844054SSalil }
63384844054SSalil 
63484844054SSalil static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
63584844054SSalil {
63684844054SSalil 	u8 i;
63784844054SSalil 
63884844054SSalil 	for (i = 0; i < hdev->tm_info.num_tc; i++) {
63984844054SSalil 		hdev->tm_info.tc_info[i].tc_id = i;
64084844054SSalil 		hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR;
64184844054SSalil 		hdev->tm_info.tc_info[i].pgid = 0;
64284844054SSalil 		hdev->tm_info.tc_info[i].bw_limit =
64384844054SSalil 			hdev->tm_info.pg_info[0].bw_limit;
64484844054SSalil 	}
64584844054SSalil 
646c5795c53SYunsheng Lin 	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++)
647c5795c53SYunsheng Lin 		hdev->tm_info.prio_tc[i] =
648c5795c53SYunsheng Lin 			(i >= hdev->tm_info.num_tc) ? 0 : i;
649c5795c53SYunsheng Lin 
650ae179b2fSYunsheng Lin 	/* DCB is enabled if we have more than 1 TC or pfc_en is
651ae179b2fSYunsheng Lin 	 * non-zero.
652ae179b2fSYunsheng Lin 	 */
653ae179b2fSYunsheng Lin 	if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en)
6547979a223SYunsheng Lin 		hdev->flag |= HCLGE_FLAG_DCB_ENABLE;
6557979a223SYunsheng Lin 	else
65684844054SSalil 		hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
65784844054SSalil }
65884844054SSalil 
65984844054SSalil static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
66084844054SSalil {
661b37ce587SYufeng Mo #define BW_PERCENT	100
662b37ce587SYufeng Mo 
66384844054SSalil 	u8 i;
66484844054SSalil 
66584844054SSalil 	for (i = 0; i < hdev->tm_info.num_pg; i++) {
66684844054SSalil 		int k;
66784844054SSalil 
668b37ce587SYufeng Mo 		hdev->tm_info.pg_dwrr[i] = i ? 0 : BW_PERCENT;
66984844054SSalil 
67084844054SSalil 		hdev->tm_info.pg_info[i].pg_id = i;
67184844054SSalil 		hdev->tm_info.pg_info[i].pg_sch_mode = HCLGE_SCH_MODE_DWRR;
67284844054SSalil 
673d9c7d20dSGuangbin Huang 		hdev->tm_info.pg_info[i].bw_limit =
674d9c7d20dSGuangbin Huang 					hdev->ae_dev->dev_specs.max_tm_rate;
67584844054SSalil 
67684844054SSalil 		if (i != 0)
67784844054SSalil 			continue;
67884844054SSalil 
67984844054SSalil 		hdev->tm_info.pg_info[i].tc_bit_map = hdev->hw_tc_map;
68084844054SSalil 		for (k = 0; k < hdev->tm_info.num_tc; k++)
681b37ce587SYufeng Mo 			hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT;
68284844054SSalil 	}
68384844054SSalil }
68484844054SSalil 
6857979a223SYunsheng Lin static void hclge_pfc_info_init(struct hclge_dev *hdev)
6867979a223SYunsheng Lin {
6877979a223SYunsheng Lin 	if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) {
6887979a223SYunsheng Lin 		if (hdev->fc_mode_last_time == HCLGE_FC_PFC)
6897979a223SYunsheng Lin 			dev_warn(&hdev->pdev->dev,
6907979a223SYunsheng Lin 				 "DCB is disable, but last mode is FC_PFC\n");
6917979a223SYunsheng Lin 
6927979a223SYunsheng Lin 		hdev->tm_info.fc_mode = hdev->fc_mode_last_time;
6937979a223SYunsheng Lin 	} else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) {
6947979a223SYunsheng Lin 		/* fc_mode_last_time record the last fc_mode when
6957979a223SYunsheng Lin 		 * DCB is enabled, so that fc_mode can be set to
6967979a223SYunsheng Lin 		 * the correct value when DCB is disabled.
6977979a223SYunsheng Lin 		 */
6987979a223SYunsheng Lin 		hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
6997979a223SYunsheng Lin 		hdev->tm_info.fc_mode = HCLGE_FC_PFC;
7007979a223SYunsheng Lin 	}
7017979a223SYunsheng Lin }
7027979a223SYunsheng Lin 
703b6872fd3SYunsheng Lin static void hclge_tm_schd_info_init(struct hclge_dev *hdev)
70484844054SSalil {
70584844054SSalil 	hclge_tm_pg_info_init(hdev);
70684844054SSalil 
70784844054SSalil 	hclge_tm_tc_info_init(hdev);
70884844054SSalil 
70984844054SSalil 	hclge_tm_vport_info_update(hdev);
71084844054SSalil 
7117979a223SYunsheng Lin 	hclge_pfc_info_init(hdev);
71284844054SSalil }
71384844054SSalil 
71484844054SSalil static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev)
71584844054SSalil {
71684844054SSalil 	int ret;
71784844054SSalil 	u32 i;
71884844054SSalil 
71984844054SSalil 	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
72084844054SSalil 		return 0;
72184844054SSalil 
72284844054SSalil 	for (i = 0; i < hdev->tm_info.num_pg; i++) {
72384844054SSalil 		/* Cfg mapping */
72484844054SSalil 		ret = hclge_tm_pg_to_pri_map_cfg(
72584844054SSalil 			hdev, i, hdev->tm_info.pg_info[i].tc_bit_map);
72684844054SSalil 		if (ret)
72784844054SSalil 			return ret;
72884844054SSalil 	}
72984844054SSalil 
73084844054SSalil 	return 0;
73184844054SSalil }
73284844054SSalil 
73384844054SSalil static int hclge_tm_pg_shaper_cfg(struct hclge_dev *hdev)
73484844054SSalil {
735d9c7d20dSGuangbin Huang 	u32 max_tm_rate = hdev->ae_dev->dev_specs.max_tm_rate;
73684844054SSalil 	u8 ir_u, ir_b, ir_s;
73763cbf7a9SYufeng Mo 	u32 shaper_para;
73884844054SSalil 	int ret;
73984844054SSalil 	u32 i;
74084844054SSalil 
74184844054SSalil 	/* Cfg pg schd */
74284844054SSalil 	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
74384844054SSalil 		return 0;
74484844054SSalil 
74584844054SSalil 	/* Pg to pri */
74684844054SSalil 	for (i = 0; i < hdev->tm_info.num_pg; i++) {
74784844054SSalil 		/* Calc shaper para */
74884844054SSalil 		ret = hclge_shaper_para_calc(
74984844054SSalil 					hdev->tm_info.pg_info[i].bw_limit,
75084844054SSalil 					HCLGE_SHAPER_LVL_PG,
751d9c7d20dSGuangbin Huang 					&ir_b, &ir_u, &ir_s,
752d9c7d20dSGuangbin Huang 					max_tm_rate);
75384844054SSalil 		if (ret)
75484844054SSalil 			return ret;
75584844054SSalil 
75663cbf7a9SYufeng Mo 		shaper_para = hclge_tm_get_shapping_para(0, 0, 0,
75763cbf7a9SYufeng Mo 							 HCLGE_SHAPER_BS_U_DEF,
75863cbf7a9SYufeng Mo 							 HCLGE_SHAPER_BS_S_DEF);
75984844054SSalil 		ret = hclge_tm_pg_shapping_cfg(hdev,
76084844054SSalil 					       HCLGE_TM_SHAP_C_BUCKET, i,
76163cbf7a9SYufeng Mo 					       shaper_para);
76284844054SSalil 		if (ret)
76384844054SSalil 			return ret;
76484844054SSalil 
76563cbf7a9SYufeng Mo 		shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s,
76684844054SSalil 							 HCLGE_SHAPER_BS_U_DEF,
76784844054SSalil 							 HCLGE_SHAPER_BS_S_DEF);
76863cbf7a9SYufeng Mo 		ret = hclge_tm_pg_shapping_cfg(hdev,
76963cbf7a9SYufeng Mo 					       HCLGE_TM_SHAP_P_BUCKET, i,
77063cbf7a9SYufeng Mo 					       shaper_para);
77184844054SSalil 		if (ret)
77284844054SSalil 			return ret;
77384844054SSalil 	}
77484844054SSalil 
77584844054SSalil 	return 0;
77684844054SSalil }
77784844054SSalil 
77884844054SSalil static int hclge_tm_pg_dwrr_cfg(struct hclge_dev *hdev)
77984844054SSalil {
78084844054SSalil 	int ret;
78184844054SSalil 	u32 i;
78284844054SSalil 
78384844054SSalil 	/* cfg pg schd */
78484844054SSalil 	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE)
78584844054SSalil 		return 0;
78684844054SSalil 
78784844054SSalil 	/* pg to prio */
78884844054SSalil 	for (i = 0; i < hdev->tm_info.num_pg; i++) {
78984844054SSalil 		/* Cfg dwrr */
7909b2f3477SWeihang Li 		ret = hclge_tm_pg_weight_cfg(hdev, i, hdev->tm_info.pg_dwrr[i]);
79184844054SSalil 		if (ret)
79284844054SSalil 			return ret;
79384844054SSalil 	}
79484844054SSalil 
79584844054SSalil 	return 0;
79684844054SSalil }
79784844054SSalil 
79884844054SSalil static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev,
79984844054SSalil 				   struct hclge_vport *vport)
80084844054SSalil {
80184844054SSalil 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
80284844054SSalil 	struct hnae3_queue **tqp = kinfo->tqp;
80384844054SSalil 	struct hnae3_tc_info *v_tc_info;
80484844054SSalil 	u32 i, j;
80584844054SSalil 	int ret;
80684844054SSalil 
80784844054SSalil 	for (i = 0; i < kinfo->num_tc; i++) {
80884844054SSalil 		v_tc_info = &kinfo->tc_info[i];
80984844054SSalil 		for (j = 0; j < v_tc_info->tqp_count; j++) {
81084844054SSalil 			struct hnae3_queue *q = tqp[v_tc_info->tqp_offset + j];
81184844054SSalil 
81284844054SSalil 			ret = hclge_tm_q_to_qs_map_cfg(hdev,
81384844054SSalil 						       hclge_get_queue_id(q),
81484844054SSalil 						       vport->qs_offset + i);
81584844054SSalil 			if (ret)
81684844054SSalil 				return ret;
81784844054SSalil 		}
81884844054SSalil 	}
81984844054SSalil 
82084844054SSalil 	return 0;
82184844054SSalil }
82284844054SSalil 
82384844054SSalil static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev)
82484844054SSalil {
82584844054SSalil 	struct hclge_vport *vport = hdev->vport;
82684844054SSalil 	int ret;
827cc9bb43aSYunsheng Lin 	u32 i, k;
82884844054SSalil 
82984844054SSalil 	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
83084844054SSalil 		/* Cfg qs -> pri mapping, one by one mapping */
831de67a690SYunsheng Lin 		for (k = 0; k < hdev->num_alloc_vport; k++) {
832de67a690SYunsheng Lin 			struct hnae3_knic_private_info *kinfo =
833de67a690SYunsheng Lin 				&vport[k].nic.kinfo;
834de67a690SYunsheng Lin 
835de67a690SYunsheng Lin 			for (i = 0; i < kinfo->num_tc; i++) {
836cc9bb43aSYunsheng Lin 				ret = hclge_tm_qs_to_pri_map_cfg(
837cc9bb43aSYunsheng Lin 					hdev, vport[k].qs_offset + i, i);
83884844054SSalil 				if (ret)
83984844054SSalil 					return ret;
84084844054SSalil 			}
841de67a690SYunsheng Lin 		}
84284844054SSalil 	} else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) {
84384844054SSalil 		/* Cfg qs -> pri mapping,  qs = tc, pri = vf, 8 qs -> 1 pri */
84484844054SSalil 		for (k = 0; k < hdev->num_alloc_vport; k++)
84584844054SSalil 			for (i = 0; i < HNAE3_MAX_TC; i++) {
84684844054SSalil 				ret = hclge_tm_qs_to_pri_map_cfg(
84784844054SSalil 					hdev, vport[k].qs_offset + i, k);
84884844054SSalil 				if (ret)
84984844054SSalil 					return ret;
85084844054SSalil 			}
85184844054SSalil 	} else {
85284844054SSalil 		return -EINVAL;
85384844054SSalil 	}
85484844054SSalil 
85584844054SSalil 	/* Cfg q -> qs mapping */
85684844054SSalil 	for (i = 0; i < hdev->num_alloc_vport; i++) {
85784844054SSalil 		ret = hclge_vport_q_to_qs_map(hdev, vport);
85884844054SSalil 		if (ret)
85984844054SSalil 			return ret;
86084844054SSalil 
86184844054SSalil 		vport++;
86284844054SSalil 	}
86384844054SSalil 
86484844054SSalil 	return 0;
86584844054SSalil }
86684844054SSalil 
86784844054SSalil static int hclge_tm_pri_tc_base_shaper_cfg(struct hclge_dev *hdev)
86884844054SSalil {
869d9c7d20dSGuangbin Huang 	u32 max_tm_rate = hdev->ae_dev->dev_specs.max_tm_rate;
87084844054SSalil 	u8 ir_u, ir_b, ir_s;
87163cbf7a9SYufeng Mo 	u32 shaper_para;
87284844054SSalil 	int ret;
87384844054SSalil 	u32 i;
87484844054SSalil 
87584844054SSalil 	for (i = 0; i < hdev->tm_info.num_tc; i++) {
87684844054SSalil 		ret = hclge_shaper_para_calc(
87784844054SSalil 					hdev->tm_info.tc_info[i].bw_limit,
87884844054SSalil 					HCLGE_SHAPER_LVL_PRI,
879d9c7d20dSGuangbin Huang 					&ir_b, &ir_u, &ir_s,
880d9c7d20dSGuangbin Huang 					max_tm_rate);
88184844054SSalil 		if (ret)
88284844054SSalil 			return ret;
88384844054SSalil 
88463cbf7a9SYufeng Mo 		shaper_para = hclge_tm_get_shapping_para(0, 0, 0,
88563cbf7a9SYufeng Mo 							 HCLGE_SHAPER_BS_U_DEF,
88684844054SSalil 							 HCLGE_SHAPER_BS_S_DEF);
88763cbf7a9SYufeng Mo 		ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, i,
88863cbf7a9SYufeng Mo 						shaper_para);
88984844054SSalil 		if (ret)
89084844054SSalil 			return ret;
89184844054SSalil 
89263cbf7a9SYufeng Mo 		shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s,
89363cbf7a9SYufeng Mo 							 HCLGE_SHAPER_BS_U_DEF,
89484844054SSalil 							 HCLGE_SHAPER_BS_S_DEF);
89563cbf7a9SYufeng Mo 		ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, i,
89663cbf7a9SYufeng Mo 						shaper_para);
89784844054SSalil 		if (ret)
89884844054SSalil 			return ret;
89984844054SSalil 	}
90084844054SSalil 
90184844054SSalil 	return 0;
90284844054SSalil }
90384844054SSalil 
90484844054SSalil static int hclge_tm_pri_vnet_base_shaper_pri_cfg(struct hclge_vport *vport)
90584844054SSalil {
90684844054SSalil 	struct hclge_dev *hdev = vport->back;
90784844054SSalil 	u8 ir_u, ir_b, ir_s;
90863cbf7a9SYufeng Mo 	u32 shaper_para;
90984844054SSalil 	int ret;
91084844054SSalil 
91184844054SSalil 	ret = hclge_shaper_para_calc(vport->bw_limit, HCLGE_SHAPER_LVL_VF,
912d9c7d20dSGuangbin Huang 				     &ir_b, &ir_u, &ir_s,
913d9c7d20dSGuangbin Huang 				     hdev->ae_dev->dev_specs.max_tm_rate);
91484844054SSalil 	if (ret)
91584844054SSalil 		return ret;
91684844054SSalil 
91763cbf7a9SYufeng Mo 	shaper_para = hclge_tm_get_shapping_para(0, 0, 0,
91863cbf7a9SYufeng Mo 						 HCLGE_SHAPER_BS_U_DEF,
91984844054SSalil 						 HCLGE_SHAPER_BS_S_DEF);
92063cbf7a9SYufeng Mo 	ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET,
92163cbf7a9SYufeng Mo 					vport->vport_id, shaper_para);
92284844054SSalil 	if (ret)
92384844054SSalil 		return ret;
92484844054SSalil 
92563cbf7a9SYufeng Mo 	shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s,
92684844054SSalil 						 HCLGE_SHAPER_BS_U_DEF,
92784844054SSalil 						 HCLGE_SHAPER_BS_S_DEF);
92863cbf7a9SYufeng Mo 	ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET,
92963cbf7a9SYufeng Mo 					vport->vport_id, shaper_para);
93084844054SSalil 	if (ret)
93184844054SSalil 		return ret;
93284844054SSalil 
93384844054SSalil 	return 0;
93484844054SSalil }
93584844054SSalil 
93684844054SSalil static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport)
93784844054SSalil {
93884844054SSalil 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
93984844054SSalil 	struct hclge_dev *hdev = vport->back;
940d9c7d20dSGuangbin Huang 	u32 max_tm_rate = hdev->ae_dev->dev_specs.max_tm_rate;
94184844054SSalil 	u8 ir_u, ir_b, ir_s;
94284844054SSalil 	u32 i;
94384844054SSalil 	int ret;
94484844054SSalil 
94584844054SSalil 	for (i = 0; i < kinfo->num_tc; i++) {
94684844054SSalil 		ret = hclge_shaper_para_calc(
94784844054SSalil 					hdev->tm_info.tc_info[i].bw_limit,
94884844054SSalil 					HCLGE_SHAPER_LVL_QSET,
949d9c7d20dSGuangbin Huang 					&ir_b, &ir_u, &ir_s,
950d9c7d20dSGuangbin Huang 					max_tm_rate);
95184844054SSalil 		if (ret)
95284844054SSalil 			return ret;
95384844054SSalil 	}
95484844054SSalil 
95584844054SSalil 	return 0;
95684844054SSalil }
95784844054SSalil 
95884844054SSalil static int hclge_tm_pri_vnet_base_shaper_cfg(struct hclge_dev *hdev)
95984844054SSalil {
96084844054SSalil 	struct hclge_vport *vport = hdev->vport;
96184844054SSalil 	int ret;
96284844054SSalil 	u32 i;
96384844054SSalil 
96484844054SSalil 	/* Need config vport shaper */
96584844054SSalil 	for (i = 0; i < hdev->num_alloc_vport; i++) {
96684844054SSalil 		ret = hclge_tm_pri_vnet_base_shaper_pri_cfg(vport);
96784844054SSalil 		if (ret)
96884844054SSalil 			return ret;
96984844054SSalil 
97084844054SSalil 		ret = hclge_tm_pri_vnet_base_shaper_qs_cfg(vport);
97184844054SSalil 		if (ret)
97284844054SSalil 			return ret;
97384844054SSalil 
97484844054SSalil 		vport++;
97584844054SSalil 	}
97684844054SSalil 
97784844054SSalil 	return 0;
97884844054SSalil }
97984844054SSalil 
98084844054SSalil static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev)
98184844054SSalil {
98284844054SSalil 	int ret;
98384844054SSalil 
98484844054SSalil 	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
98584844054SSalil 		ret = hclge_tm_pri_tc_base_shaper_cfg(hdev);
98684844054SSalil 		if (ret)
98784844054SSalil 			return ret;
98884844054SSalil 	} else {
98984844054SSalil 		ret = hclge_tm_pri_vnet_base_shaper_cfg(hdev);
99084844054SSalil 		if (ret)
99184844054SSalil 			return ret;
99284844054SSalil 	}
99384844054SSalil 
99484844054SSalil 	return 0;
99584844054SSalil }
99684844054SSalil 
99784844054SSalil static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev)
99884844054SSalil {
999cc9bb43aSYunsheng Lin 	struct hclge_vport *vport = hdev->vport;
100084844054SSalil 	struct hclge_pg_info *pg_info;
100184844054SSalil 	u8 dwrr;
100284844054SSalil 	int ret;
1003cc9bb43aSYunsheng Lin 	u32 i, k;
100484844054SSalil 
100584844054SSalil 	for (i = 0; i < hdev->tm_info.num_tc; i++) {
100684844054SSalil 		pg_info =
100784844054SSalil 			&hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
100884844054SSalil 		dwrr = pg_info->tc_dwrr[i];
100984844054SSalil 
101084844054SSalil 		ret = hclge_tm_pri_weight_cfg(hdev, i, dwrr);
101184844054SSalil 		if (ret)
101284844054SSalil 			return ret;
101384844054SSalil 
1014cc9bb43aSYunsheng Lin 		for (k = 0; k < hdev->num_alloc_vport; k++) {
1015cc9bb43aSYunsheng Lin 			ret = hclge_tm_qs_weight_cfg(
1016cc9bb43aSYunsheng Lin 				hdev, vport[k].qs_offset + i,
1017cc9bb43aSYunsheng Lin 				vport[k].dwrr);
101884844054SSalil 			if (ret)
101984844054SSalil 				return ret;
102084844054SSalil 		}
1021cc9bb43aSYunsheng Lin 	}
102284844054SSalil 
102384844054SSalil 	return 0;
102484844054SSalil }
102584844054SSalil 
1026330baff5SYunsheng Lin static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev)
1027330baff5SYunsheng Lin {
1028330baff5SYunsheng Lin #define DEFAULT_TC_WEIGHT	1
1029330baff5SYunsheng Lin #define DEFAULT_TC_OFFSET	14
1030330baff5SYunsheng Lin 
1031330baff5SYunsheng Lin 	struct hclge_ets_tc_weight_cmd *ets_weight;
1032330baff5SYunsheng Lin 	struct hclge_desc desc;
1033ebaf1908SWeihang Li 	unsigned int i;
1034330baff5SYunsheng Lin 
1035330baff5SYunsheng Lin 	hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, false);
1036330baff5SYunsheng Lin 	ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data;
1037330baff5SYunsheng Lin 
1038330baff5SYunsheng Lin 	for (i = 0; i < HNAE3_MAX_TC; i++) {
1039330baff5SYunsheng Lin 		struct hclge_pg_info *pg_info;
1040330baff5SYunsheng Lin 
1041330baff5SYunsheng Lin 		ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT;
1042330baff5SYunsheng Lin 
1043330baff5SYunsheng Lin 		if (!(hdev->hw_tc_map & BIT(i)))
1044330baff5SYunsheng Lin 			continue;
1045330baff5SYunsheng Lin 
1046330baff5SYunsheng Lin 		pg_info =
1047330baff5SYunsheng Lin 			&hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid];
1048330baff5SYunsheng Lin 		ets_weight->tc_weight[i] = pg_info->tc_dwrr[i];
1049330baff5SYunsheng Lin 	}
1050330baff5SYunsheng Lin 
1051330baff5SYunsheng Lin 	ets_weight->weight_offset = DEFAULT_TC_OFFSET;
1052330baff5SYunsheng Lin 
1053330baff5SYunsheng Lin 	return hclge_cmd_send(&hdev->hw, &desc, 1);
1054330baff5SYunsheng Lin }
1055330baff5SYunsheng Lin 
105684844054SSalil static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport)
105784844054SSalil {
105884844054SSalil 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
105984844054SSalil 	struct hclge_dev *hdev = vport->back;
106084844054SSalil 	int ret;
106184844054SSalil 	u8 i;
106284844054SSalil 
106384844054SSalil 	/* Vf dwrr */
106484844054SSalil 	ret = hclge_tm_pri_weight_cfg(hdev, vport->vport_id, vport->dwrr);
106584844054SSalil 	if (ret)
106684844054SSalil 		return ret;
106784844054SSalil 
106884844054SSalil 	/* Qset dwrr */
106984844054SSalil 	for (i = 0; i < kinfo->num_tc; i++) {
107084844054SSalil 		ret = hclge_tm_qs_weight_cfg(
107184844054SSalil 			hdev, vport->qs_offset + i,
107284844054SSalil 			hdev->tm_info.pg_info[0].tc_dwrr[i]);
107384844054SSalil 		if (ret)
107484844054SSalil 			return ret;
107584844054SSalil 	}
107684844054SSalil 
107784844054SSalil 	return 0;
107884844054SSalil }
107984844054SSalil 
108084844054SSalil static int hclge_tm_pri_vnet_base_dwrr_cfg(struct hclge_dev *hdev)
108184844054SSalil {
108284844054SSalil 	struct hclge_vport *vport = hdev->vport;
108384844054SSalil 	int ret;
108484844054SSalil 	u32 i;
108584844054SSalil 
108684844054SSalil 	for (i = 0; i < hdev->num_alloc_vport; i++) {
108784844054SSalil 		ret = hclge_tm_pri_vnet_base_dwrr_pri_cfg(vport);
108884844054SSalil 		if (ret)
108984844054SSalil 			return ret;
109084844054SSalil 
109184844054SSalil 		vport++;
109284844054SSalil 	}
109384844054SSalil 
109484844054SSalil 	return 0;
109584844054SSalil }
109684844054SSalil 
109784844054SSalil static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev)
109884844054SSalil {
109984844054SSalil 	int ret;
110084844054SSalil 
110184844054SSalil 	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
110284844054SSalil 		ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev);
110384844054SSalil 		if (ret)
110484844054SSalil 			return ret;
1105330baff5SYunsheng Lin 
1106330baff5SYunsheng Lin 		if (!hnae3_dev_dcb_supported(hdev))
1107330baff5SYunsheng Lin 			return 0;
1108330baff5SYunsheng Lin 
1109330baff5SYunsheng Lin 		ret = hclge_tm_ets_tc_dwrr_cfg(hdev);
1110330baff5SYunsheng Lin 		if (ret == -EOPNOTSUPP) {
1111330baff5SYunsheng Lin 			dev_warn(&hdev->pdev->dev,
1112330baff5SYunsheng Lin 				 "fw %08x does't support ets tc weight cmd\n",
1113330baff5SYunsheng Lin 				 hdev->fw_version);
1114330baff5SYunsheng Lin 			ret = 0;
1115330baff5SYunsheng Lin 		}
1116330baff5SYunsheng Lin 
1117330baff5SYunsheng Lin 		return ret;
111884844054SSalil 	} else {
111984844054SSalil 		ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev);
112084844054SSalil 		if (ret)
112184844054SSalil 			return ret;
112284844054SSalil 	}
112384844054SSalil 
112484844054SSalil 	return 0;
112584844054SSalil }
112684844054SSalil 
11279e5157baSYunsheng Lin static int hclge_tm_map_cfg(struct hclge_dev *hdev)
112884844054SSalil {
112984844054SSalil 	int ret;
113084844054SSalil 
113177f255c1SYunsheng Lin 	ret = hclge_up_to_tc_map(hdev);
113277f255c1SYunsheng Lin 	if (ret)
113377f255c1SYunsheng Lin 		return ret;
113477f255c1SYunsheng Lin 
113584844054SSalil 	ret = hclge_tm_pg_to_pri_map(hdev);
113684844054SSalil 	if (ret)
113784844054SSalil 		return ret;
113884844054SSalil 
113984844054SSalil 	return hclge_tm_pri_q_qs_cfg(hdev);
114084844054SSalil }
114184844054SSalil 
114284844054SSalil static int hclge_tm_shaper_cfg(struct hclge_dev *hdev)
114384844054SSalil {
114484844054SSalil 	int ret;
114584844054SSalil 
11460a5677d3SYunsheng Lin 	ret = hclge_tm_port_shaper_cfg(hdev);
11470a5677d3SYunsheng Lin 	if (ret)
11480a5677d3SYunsheng Lin 		return ret;
11490a5677d3SYunsheng Lin 
115084844054SSalil 	ret = hclge_tm_pg_shaper_cfg(hdev);
115184844054SSalil 	if (ret)
115284844054SSalil 		return ret;
115384844054SSalil 
115484844054SSalil 	return hclge_tm_pri_shaper_cfg(hdev);
115584844054SSalil }
115684844054SSalil 
115784844054SSalil int hclge_tm_dwrr_cfg(struct hclge_dev *hdev)
115884844054SSalil {
115984844054SSalil 	int ret;
116084844054SSalil 
116184844054SSalil 	ret = hclge_tm_pg_dwrr_cfg(hdev);
116284844054SSalil 	if (ret)
116384844054SSalil 		return ret;
116484844054SSalil 
116584844054SSalil 	return hclge_tm_pri_dwrr_cfg(hdev);
116684844054SSalil }
116784844054SSalil 
116884844054SSalil static int hclge_tm_lvl2_schd_mode_cfg(struct hclge_dev *hdev)
116984844054SSalil {
117084844054SSalil 	int ret;
117184844054SSalil 	u8 i;
117284844054SSalil 
117384844054SSalil 	/* Only being config on TC-Based scheduler mode */
117484844054SSalil 	if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE)
117584844054SSalil 		return 0;
117684844054SSalil 
117784844054SSalil 	for (i = 0; i < hdev->tm_info.num_pg; i++) {
117884844054SSalil 		ret = hclge_tm_pg_schd_mode_cfg(hdev, i);
117984844054SSalil 		if (ret)
118084844054SSalil 			return ret;
118184844054SSalil 	}
118284844054SSalil 
118384844054SSalil 	return 0;
118484844054SSalil }
118584844054SSalil 
118684844054SSalil static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport)
118784844054SSalil {
118884844054SSalil 	struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo;
118984844054SSalil 	struct hclge_dev *hdev = vport->back;
119084844054SSalil 	int ret;
119184844054SSalil 	u8 i;
119284844054SSalil 
119304f25edbSYunsheng Lin 	if (vport->vport_id >= HNAE3_MAX_TC)
119404f25edbSYunsheng Lin 		return -EINVAL;
119504f25edbSYunsheng Lin 
119684844054SSalil 	ret = hclge_tm_pri_schd_mode_cfg(hdev, vport->vport_id);
119784844054SSalil 	if (ret)
119884844054SSalil 		return ret;
119984844054SSalil 
120084844054SSalil 	for (i = 0; i < kinfo->num_tc; i++) {
1201cc9bb43aSYunsheng Lin 		u8 sch_mode = hdev->tm_info.tc_info[i].tc_sch_mode;
1202cc9bb43aSYunsheng Lin 
1203cc9bb43aSYunsheng Lin 		ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i,
1204cc9bb43aSYunsheng Lin 						sch_mode);
120584844054SSalil 		if (ret)
120684844054SSalil 			return ret;
120784844054SSalil 	}
120884844054SSalil 
120984844054SSalil 	return 0;
121084844054SSalil }
121184844054SSalil 
121284844054SSalil static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev)
121384844054SSalil {
121484844054SSalil 	struct hclge_vport *vport = hdev->vport;
121584844054SSalil 	int ret;
1216cc9bb43aSYunsheng Lin 	u8 i, k;
121784844054SSalil 
121884844054SSalil 	if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) {
121984844054SSalil 		for (i = 0; i < hdev->tm_info.num_tc; i++) {
122084844054SSalil 			ret = hclge_tm_pri_schd_mode_cfg(hdev, i);
122184844054SSalil 			if (ret)
122284844054SSalil 				return ret;
122384844054SSalil 
1224cc9bb43aSYunsheng Lin 			for (k = 0; k < hdev->num_alloc_vport; k++) {
1225cc9bb43aSYunsheng Lin 				ret = hclge_tm_qs_schd_mode_cfg(
1226cc9bb43aSYunsheng Lin 					hdev, vport[k].qs_offset + i,
1227cc9bb43aSYunsheng Lin 					HCLGE_SCH_MODE_DWRR);
122884844054SSalil 				if (ret)
122984844054SSalil 					return ret;
123084844054SSalil 			}
1231cc9bb43aSYunsheng Lin 		}
123284844054SSalil 	} else {
123384844054SSalil 		for (i = 0; i < hdev->num_alloc_vport; i++) {
123484844054SSalil 			ret = hclge_tm_schd_mode_vnet_base_cfg(vport);
123584844054SSalil 			if (ret)
123684844054SSalil 				return ret;
123784844054SSalil 
123884844054SSalil 			vport++;
123984844054SSalil 		}
124084844054SSalil 	}
124184844054SSalil 
124284844054SSalil 	return 0;
124384844054SSalil }
124484844054SSalil 
12459e5157baSYunsheng Lin static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev)
124684844054SSalil {
124784844054SSalil 	int ret;
124884844054SSalil 
124984844054SSalil 	ret = hclge_tm_lvl2_schd_mode_cfg(hdev);
125084844054SSalil 	if (ret)
125184844054SSalil 		return ret;
125284844054SSalil 
125384844054SSalil 	return hclge_tm_lvl34_schd_mode_cfg(hdev);
125484844054SSalil }
125584844054SSalil 
12569e5157baSYunsheng Lin int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
125784844054SSalil {
125884844054SSalil 	int ret;
125984844054SSalil 
126084844054SSalil 	/* Cfg tm mapping  */
126184844054SSalil 	ret = hclge_tm_map_cfg(hdev);
126284844054SSalil 	if (ret)
126384844054SSalil 		return ret;
126484844054SSalil 
126584844054SSalil 	/* Cfg tm shaper */
126684844054SSalil 	ret = hclge_tm_shaper_cfg(hdev);
126784844054SSalil 	if (ret)
126884844054SSalil 		return ret;
126984844054SSalil 
127084844054SSalil 	/* Cfg dwrr */
127184844054SSalil 	ret = hclge_tm_dwrr_cfg(hdev);
127284844054SSalil 	if (ret)
127384844054SSalil 		return ret;
127484844054SSalil 
127584844054SSalil 	/* Cfg schd mode for each level schd */
127684844054SSalil 	return hclge_tm_schd_mode_hw(hdev);
127784844054SSalil }
127884844054SSalil 
1279e98d7183SFuyun Liang static int hclge_pause_param_setup_hw(struct hclge_dev *hdev)
128018838d0cSFuyun Liang {
128118838d0cSFuyun Liang 	struct hclge_mac *mac = &hdev->hw.mac;
128218838d0cSFuyun Liang 
1283e98d7183SFuyun Liang 	return hclge_pause_param_cfg(hdev, mac->mac_addr,
128418838d0cSFuyun Liang 				     HCLGE_DEFAULT_PAUSE_TRANS_GAP,
128518838d0cSFuyun Liang 				     HCLGE_DEFAULT_PAUSE_TRANS_TIME);
128618838d0cSFuyun Liang }
128718838d0cSFuyun Liang 
12889dc2145dSYunsheng Lin static int hclge_pfc_setup_hw(struct hclge_dev *hdev)
12899dc2145dSYunsheng Lin {
12909dc2145dSYunsheng Lin 	u8 enable_bitmap = 0;
12919dc2145dSYunsheng Lin 
12929dc2145dSYunsheng Lin 	if (hdev->tm_info.fc_mode == HCLGE_FC_PFC)
12939dc2145dSYunsheng Lin 		enable_bitmap = HCLGE_TX_MAC_PAUSE_EN_MSK |
12949dc2145dSYunsheng Lin 				HCLGE_RX_MAC_PAUSE_EN_MSK;
12959dc2145dSYunsheng Lin 
12969dc2145dSYunsheng Lin 	return hclge_pfc_pause_en_cfg(hdev, enable_bitmap,
1297d3ad430aSYunsheng Lin 				      hdev->tm_info.pfc_en);
12989dc2145dSYunsheng Lin }
12999dc2145dSYunsheng Lin 
130067bf2541SYunsheng Lin /* Each Tc has a 1024 queue sets to backpress, it divides to
130167bf2541SYunsheng Lin  * 32 group, each group contains 32 queue sets, which can be
130267bf2541SYunsheng Lin  * represented by u32 bitmap.
130367bf2541SYunsheng Lin  */
130467bf2541SYunsheng Lin static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)
130567bf2541SYunsheng Lin {
1306e8ccbb7dSYunsheng Lin 	int i;
130767bf2541SYunsheng Lin 
130867bf2541SYunsheng Lin 	for (i = 0; i < HCLGE_BP_GRP_NUM; i++) {
1309e8ccbb7dSYunsheng Lin 		u32 qs_bitmap = 0;
1310e8ccbb7dSYunsheng Lin 		int k, ret;
131167bf2541SYunsheng Lin 
131267bf2541SYunsheng Lin 		for (k = 0; k < hdev->num_alloc_vport; k++) {
1313e8ccbb7dSYunsheng Lin 			struct hclge_vport *vport = &hdev->vport[k];
131467bf2541SYunsheng Lin 			u16 qs_id = vport->qs_offset + tc;
131567bf2541SYunsheng Lin 			u8 grp, sub_grp;
131667bf2541SYunsheng Lin 
1317e4e87715SPeng Li 			grp = hnae3_get_field(qs_id, HCLGE_BP_GRP_ID_M,
131867bf2541SYunsheng Lin 					      HCLGE_BP_GRP_ID_S);
1319e4e87715SPeng Li 			sub_grp = hnae3_get_field(qs_id, HCLGE_BP_SUB_GRP_ID_M,
132067bf2541SYunsheng Lin 						  HCLGE_BP_SUB_GRP_ID_S);
132167bf2541SYunsheng Lin 			if (i == grp)
132267bf2541SYunsheng Lin 				qs_bitmap |= (1 << sub_grp);
132367bf2541SYunsheng Lin 		}
132467bf2541SYunsheng Lin 
132567bf2541SYunsheng Lin 		ret = hclge_tm_qs_bp_cfg(hdev, tc, i, qs_bitmap);
132667bf2541SYunsheng Lin 		if (ret)
132767bf2541SYunsheng Lin 			return ret;
132867bf2541SYunsheng Lin 	}
132967bf2541SYunsheng Lin 
133067bf2541SYunsheng Lin 	return 0;
133167bf2541SYunsheng Lin }
133267bf2541SYunsheng Lin 
13339dc2145dSYunsheng Lin static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev)
13349dc2145dSYunsheng Lin {
13359dc2145dSYunsheng Lin 	bool tx_en, rx_en;
13369dc2145dSYunsheng Lin 
13379dc2145dSYunsheng Lin 	switch (hdev->tm_info.fc_mode) {
13389dc2145dSYunsheng Lin 	case HCLGE_FC_NONE:
13399dc2145dSYunsheng Lin 		tx_en = false;
13409dc2145dSYunsheng Lin 		rx_en = false;
13419dc2145dSYunsheng Lin 		break;
13429dc2145dSYunsheng Lin 	case HCLGE_FC_RX_PAUSE:
13439dc2145dSYunsheng Lin 		tx_en = false;
13449dc2145dSYunsheng Lin 		rx_en = true;
13459dc2145dSYunsheng Lin 		break;
13469dc2145dSYunsheng Lin 	case HCLGE_FC_TX_PAUSE:
13479dc2145dSYunsheng Lin 		tx_en = true;
13489dc2145dSYunsheng Lin 		rx_en = false;
13499dc2145dSYunsheng Lin 		break;
13509dc2145dSYunsheng Lin 	case HCLGE_FC_FULL:
13519dc2145dSYunsheng Lin 		tx_en = true;
13529dc2145dSYunsheng Lin 		rx_en = true;
13539dc2145dSYunsheng Lin 		break;
13546d0ec65cSYunsheng Lin 	case HCLGE_FC_PFC:
13556d0ec65cSYunsheng Lin 		tx_en = false;
13566d0ec65cSYunsheng Lin 		rx_en = false;
13576d0ec65cSYunsheng Lin 		break;
13589dc2145dSYunsheng Lin 	default:
13599dc2145dSYunsheng Lin 		tx_en = true;
13609dc2145dSYunsheng Lin 		rx_en = true;
13619dc2145dSYunsheng Lin 	}
13629dc2145dSYunsheng Lin 
13639dc2145dSYunsheng Lin 	return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en);
13649dc2145dSYunsheng Lin }
13659dc2145dSYunsheng Lin 
136673fc9c48SHuazhong Tan static int hclge_tm_bp_setup(struct hclge_dev *hdev)
136773fc9c48SHuazhong Tan {
13689d8d5a36SYufeng Mo 	int ret;
136973fc9c48SHuazhong Tan 	int i;
137073fc9c48SHuazhong Tan 
137173fc9c48SHuazhong Tan 	for (i = 0; i < hdev->tm_info.num_tc; i++) {
137273fc9c48SHuazhong Tan 		ret = hclge_bp_setup_hw(hdev, i);
137373fc9c48SHuazhong Tan 		if (ret)
137473fc9c48SHuazhong Tan 			return ret;
137573fc9c48SHuazhong Tan 	}
137673fc9c48SHuazhong Tan 
137773fc9c48SHuazhong Tan 	return ret;
137873fc9c48SHuazhong Tan }
137973fc9c48SHuazhong Tan 
138044e59e37SYunsheng Lin int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init)
138184844054SSalil {
138284844054SSalil 	int ret;
138384844054SSalil 
1384e98d7183SFuyun Liang 	ret = hclge_pause_param_setup_hw(hdev);
138518838d0cSFuyun Liang 	if (ret)
138618838d0cSFuyun Liang 		return ret;
138718838d0cSFuyun Liang 
13886d0ec65cSYunsheng Lin 	ret = hclge_mac_pause_setup_hw(hdev);
13896d0ec65cSYunsheng Lin 	if (ret)
13906d0ec65cSYunsheng Lin 		return ret;
139184844054SSalil 
13929dc2145dSYunsheng Lin 	/* Only DCB-supported dev supports qset back pressure and pfc cmd */
13932daf4a65SYunsheng Lin 	if (!hnae3_dev_dcb_supported(hdev))
13942daf4a65SYunsheng Lin 		return 0;
13952daf4a65SYunsheng Lin 
139644e59e37SYunsheng Lin 	/* GE MAC does not support PFC, when driver is initializing and MAC
139744e59e37SYunsheng Lin 	 * is in GE Mode, ignore the error here, otherwise initialization
139844e59e37SYunsheng Lin 	 * will fail.
139944e59e37SYunsheng Lin 	 */
14009dc2145dSYunsheng Lin 	ret = hclge_pfc_setup_hw(hdev);
140144e59e37SYunsheng Lin 	if (init && ret == -EOPNOTSUPP)
140244e59e37SYunsheng Lin 		dev_warn(&hdev->pdev->dev, "GE MAC does not support pfc\n");
1403fba2efdaSHuazhong Tan 	else if (ret) {
1404fba2efdaSHuazhong Tan 		dev_err(&hdev->pdev->dev, "config pfc failed! ret = %d\n",
1405fba2efdaSHuazhong Tan 			ret);
140644e59e37SYunsheng Lin 		return ret;
1407fba2efdaSHuazhong Tan 	}
14089dc2145dSYunsheng Lin 
140973fc9c48SHuazhong Tan 	return hclge_tm_bp_setup(hdev);
141077f255c1SYunsheng Lin }
141177f255c1SYunsheng Lin 
1412e432abfbSYunsheng Lin void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc)
141377f255c1SYunsheng Lin {
141477f255c1SYunsheng Lin 	struct hclge_vport *vport = hdev->vport;
141577f255c1SYunsheng Lin 	struct hnae3_knic_private_info *kinfo;
141677f255c1SYunsheng Lin 	u32 i, k;
141777f255c1SYunsheng Lin 
141877f255c1SYunsheng Lin 	for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) {
141977f255c1SYunsheng Lin 		hdev->tm_info.prio_tc[i] = prio_tc[i];
142077f255c1SYunsheng Lin 
142177f255c1SYunsheng Lin 		for (k = 0;  k < hdev->num_alloc_vport; k++) {
142277f255c1SYunsheng Lin 			kinfo = &vport[k].nic.kinfo;
142377f255c1SYunsheng Lin 			kinfo->prio_tc[i] = prio_tc[i];
142477f255c1SYunsheng Lin 		}
142577f255c1SYunsheng Lin 	}
142677f255c1SYunsheng Lin }
142777f255c1SYunsheng Lin 
1428e432abfbSYunsheng Lin void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
142977f255c1SYunsheng Lin {
14309b2f3477SWeihang Li 	u8 bit_map = 0;
14319b2f3477SWeihang Li 	u8 i;
143277f255c1SYunsheng Lin 
143377f255c1SYunsheng Lin 	hdev->tm_info.num_tc = num_tc;
143477f255c1SYunsheng Lin 
143577f255c1SYunsheng Lin 	for (i = 0; i < hdev->tm_info.num_tc; i++)
143677f255c1SYunsheng Lin 		bit_map |= BIT(i);
143777f255c1SYunsheng Lin 
143877f255c1SYunsheng Lin 	if (!bit_map) {
143977f255c1SYunsheng Lin 		bit_map = 1;
144077f255c1SYunsheng Lin 		hdev->tm_info.num_tc = 1;
144177f255c1SYunsheng Lin 	}
144277f255c1SYunsheng Lin 
144377f255c1SYunsheng Lin 	hdev->hw_tc_map = bit_map;
144477f255c1SYunsheng Lin 
144577f255c1SYunsheng Lin 	hclge_tm_schd_info_init(hdev);
144684844054SSalil }
144784844054SSalil 
1448ae179b2fSYunsheng Lin void hclge_tm_pfc_info_update(struct hclge_dev *hdev)
1449ae179b2fSYunsheng Lin {
1450ae179b2fSYunsheng Lin 	/* DCB is enabled if we have more than 1 TC or pfc_en is
1451ae179b2fSYunsheng Lin 	 * non-zero.
1452ae179b2fSYunsheng Lin 	 */
1453ae179b2fSYunsheng Lin 	if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en)
1454ae179b2fSYunsheng Lin 		hdev->flag |= HCLGE_FLAG_DCB_ENABLE;
1455ae179b2fSYunsheng Lin 	else
1456ae179b2fSYunsheng Lin 		hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;
1457ae179b2fSYunsheng Lin 
1458ae179b2fSYunsheng Lin 	hclge_pfc_info_init(hdev);
1459ae179b2fSYunsheng Lin }
1460ae179b2fSYunsheng Lin 
146144e59e37SYunsheng Lin int hclge_tm_init_hw(struct hclge_dev *hdev, bool init)
146284844054SSalil {
146384844054SSalil 	int ret;
146484844054SSalil 
146584844054SSalil 	if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) &&
146684844054SSalil 	    (hdev->tx_sch_mode != HCLGE_FLAG_VNET_BASE_SCH_MODE))
146784844054SSalil 		return -ENOTSUPP;
146884844054SSalil 
146984844054SSalil 	ret = hclge_tm_schd_setup_hw(hdev);
147084844054SSalil 	if (ret)
147184844054SSalil 		return ret;
147284844054SSalil 
147344e59e37SYunsheng Lin 	ret = hclge_pause_setup_hw(hdev, init);
147484844054SSalil 	if (ret)
147584844054SSalil 		return ret;
147684844054SSalil 
147784844054SSalil 	return 0;
147884844054SSalil }
147984844054SSalil 
148084844054SSalil int hclge_tm_schd_init(struct hclge_dev *hdev)
148184844054SSalil {
14827979a223SYunsheng Lin 	/* fc_mode is HCLGE_FC_FULL on reset */
14837979a223SYunsheng Lin 	hdev->tm_info.fc_mode = HCLGE_FC_FULL;
14847979a223SYunsheng Lin 	hdev->fc_mode_last_time = hdev->tm_info.fc_mode;
14857979a223SYunsheng Lin 
1486b6872fd3SYunsheng Lin 	if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE &&
1487b6872fd3SYunsheng Lin 	    hdev->tm_info.num_pg != 1)
1488b6872fd3SYunsheng Lin 		return -EINVAL;
1489b6872fd3SYunsheng Lin 
1490b6872fd3SYunsheng Lin 	hclge_tm_schd_info_init(hdev);
149184844054SSalil 
149244e59e37SYunsheng Lin 	return hclge_tm_init_hw(hdev, true);
149384844054SSalil }
1494672ad0edSHuazhong Tan 
1495672ad0edSHuazhong Tan int hclge_tm_vport_map_update(struct hclge_dev *hdev)
1496672ad0edSHuazhong Tan {
1497672ad0edSHuazhong Tan 	struct hclge_vport *vport = hdev->vport;
1498672ad0edSHuazhong Tan 	int ret;
1499672ad0edSHuazhong Tan 
1500672ad0edSHuazhong Tan 	hclge_tm_vport_tc_info_update(vport);
1501672ad0edSHuazhong Tan 
1502672ad0edSHuazhong Tan 	ret = hclge_vport_q_to_qs_map(hdev, vport);
1503672ad0edSHuazhong Tan 	if (ret)
1504672ad0edSHuazhong Tan 		return ret;
1505672ad0edSHuazhong Tan 
1506672ad0edSHuazhong Tan 	if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE))
1507672ad0edSHuazhong Tan 		return 0;
1508672ad0edSHuazhong Tan 
1509672ad0edSHuazhong Tan 	return hclge_tm_bp_setup(hdev);
1510672ad0edSHuazhong Tan }
1511