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 #define HCLGE_ETHER_MAX_RATE 100000 2784844054SSalil 2884844054SSalil /* hclge_shaper_para_calc: calculate ir parameter for the shaper 2984844054SSalil * @ir: Rate to be config, its unit is Mbps 3084844054SSalil * @shaper_level: the shaper level. eg: port, pg, priority, queueset 3184844054SSalil * @ir_b: IR_B parameter of IR shaper 3284844054SSalil * @ir_u: IR_U parameter of IR shaper 3384844054SSalil * @ir_s: IR_S parameter of IR shaper 3484844054SSalil * 3584844054SSalil * the formula: 3684844054SSalil * 3784844054SSalil * IR_b * (2 ^ IR_u) * 8 3884844054SSalil * IR(Mbps) = ------------------------- * CLOCK(1000Mbps) 3984844054SSalil * Tick * (2 ^ IR_s) 4084844054SSalil * 4184844054SSalil * @return: 0: calculate sucessful, negative: fail 4284844054SSalil */ 4384844054SSalil static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, 4484844054SSalil u8 *ir_b, u8 *ir_u, u8 *ir_s) 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 || 6204f25edbSYunsheng Lin ir > HCLGE_ETHER_MAX_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, 4100a5677d3SYunsheng Lin &ir_b, &ir_u, &ir_s); 4110a5677d3SYunsheng Lin if (ret) 4120a5677d3SYunsheng Lin return ret; 4130a5677d3SYunsheng Lin 4140a5677d3SYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PORT_SHAPPING, false); 4150a5677d3SYunsheng Lin shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data; 4160a5677d3SYunsheng Lin 41763cbf7a9SYufeng Mo shapping_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 41863cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 41963cbf7a9SYufeng Mo HCLGE_SHAPER_BS_S_DEF); 4200a5677d3SYunsheng Lin 4210a5677d3SYunsheng Lin shap_cfg_cmd->port_shapping_para = cpu_to_le32(shapping_para); 4220a5677d3SYunsheng Lin 4230a5677d3SYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 4240a5677d3SYunsheng Lin } 4250a5677d3SYunsheng Lin 42684844054SSalil static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev, 42784844054SSalil enum hclge_shap_bucket bucket, u8 pri_id, 42863cbf7a9SYufeng Mo u32 shapping_para) 42984844054SSalil { 43084844054SSalil struct hclge_pri_shapping_cmd *shap_cfg_cmd; 43184844054SSalil enum hclge_opcode_type opcode; 43284844054SSalil struct hclge_desc desc; 43384844054SSalil 43484844054SSalil opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING : 43584844054SSalil HCLGE_OPC_TM_PRI_C_SHAPPING; 43684844054SSalil 43784844054SSalil hclge_cmd_setup_basic_desc(&desc, opcode, false); 43884844054SSalil 43984844054SSalil shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data; 44084844054SSalil 44184844054SSalil shap_cfg_cmd->pri_id = pri_id; 44284844054SSalil 443a90bb9a5SYunsheng Lin shap_cfg_cmd->pri_shapping_para = cpu_to_le32(shapping_para); 44484844054SSalil 44584844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 44684844054SSalil } 44784844054SSalil 44884844054SSalil static int hclge_tm_pg_schd_mode_cfg(struct hclge_dev *hdev, u8 pg_id) 44984844054SSalil { 45084844054SSalil struct hclge_desc desc; 45184844054SSalil 45284844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, false); 45384844054SSalil 45484844054SSalil if (hdev->tm_info.pg_info[pg_id].pg_sch_mode == HCLGE_SCH_MODE_DWRR) 45584844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 45684844054SSalil else 45784844054SSalil desc.data[1] = 0; 45884844054SSalil 45984844054SSalil desc.data[0] = cpu_to_le32(pg_id); 46084844054SSalil 46184844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 46284844054SSalil } 46384844054SSalil 46484844054SSalil static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id) 46584844054SSalil { 46684844054SSalil struct hclge_desc desc; 46784844054SSalil 46884844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, false); 46984844054SSalil 47084844054SSalil if (hdev->tm_info.tc_info[pri_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR) 47184844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 47284844054SSalil else 47384844054SSalil desc.data[1] = 0; 47484844054SSalil 47584844054SSalil desc.data[0] = cpu_to_le32(pri_id); 47684844054SSalil 47784844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 47884844054SSalil } 47984844054SSalil 480cc9bb43aSYunsheng Lin static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id, u8 mode) 48184844054SSalil { 48284844054SSalil struct hclge_desc desc; 48384844054SSalil 48484844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false); 48584844054SSalil 486cc9bb43aSYunsheng Lin if (mode == HCLGE_SCH_MODE_DWRR) 48784844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 48884844054SSalil else 48984844054SSalil desc.data[1] = 0; 49084844054SSalil 49184844054SSalil desc.data[0] = cpu_to_le32(qs_id); 49284844054SSalil 49384844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 49484844054SSalil } 49584844054SSalil 49667bf2541SYunsheng Lin static int hclge_tm_qs_bp_cfg(struct hclge_dev *hdev, u8 tc, u8 grp_id, 49767bf2541SYunsheng Lin u32 bit_map) 49884844054SSalil { 49984844054SSalil struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd; 50084844054SSalil struct hclge_desc desc; 50184844054SSalil 50284844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_BP_TO_QSET_MAPPING, 50384844054SSalil false); 50484844054SSalil 50584844054SSalil bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data; 50684844054SSalil 50784844054SSalil bp_to_qs_map_cmd->tc_id = tc; 50867bf2541SYunsheng Lin bp_to_qs_map_cmd->qs_group_id = grp_id; 50967bf2541SYunsheng Lin bp_to_qs_map_cmd->qs_bit_map = cpu_to_le32(bit_map); 51084844054SSalil 51184844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 51284844054SSalil } 51384844054SSalil 514ee9e4424SYonglong Liu int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate) 515ee9e4424SYonglong Liu { 516ee9e4424SYonglong Liu struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 517ee9e4424SYonglong Liu struct hclge_qs_shapping_cmd *shap_cfg_cmd; 518ee9e4424SYonglong Liu struct hclge_dev *hdev = vport->back; 519ee9e4424SYonglong Liu struct hclge_desc desc; 520ee9e4424SYonglong Liu u8 ir_b, ir_u, ir_s; 521ee9e4424SYonglong Liu u32 shaper_para; 522ee9e4424SYonglong Liu int ret, i; 523ee9e4424SYonglong Liu 524ee9e4424SYonglong Liu if (!max_tx_rate) 525ee9e4424SYonglong Liu max_tx_rate = HCLGE_ETHER_MAX_RATE; 526ee9e4424SYonglong Liu 527ee9e4424SYonglong Liu ret = hclge_shaper_para_calc(max_tx_rate, HCLGE_SHAPER_LVL_QSET, 528ee9e4424SYonglong Liu &ir_b, &ir_u, &ir_s); 529ee9e4424SYonglong Liu if (ret) 530ee9e4424SYonglong Liu return ret; 531ee9e4424SYonglong Liu 532ee9e4424SYonglong Liu shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 533ee9e4424SYonglong Liu HCLGE_SHAPER_BS_U_DEF, 534ee9e4424SYonglong Liu HCLGE_SHAPER_BS_S_DEF); 535ee9e4424SYonglong Liu 536ee9e4424SYonglong Liu for (i = 0; i < kinfo->num_tc; i++) { 537ee9e4424SYonglong Liu hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QCN_SHAPPING_CFG, 538ee9e4424SYonglong Liu false); 539ee9e4424SYonglong Liu 540ee9e4424SYonglong Liu shap_cfg_cmd = (struct hclge_qs_shapping_cmd *)desc.data; 541ee9e4424SYonglong Liu shap_cfg_cmd->qs_id = cpu_to_le16(vport->qs_offset + i); 542ee9e4424SYonglong Liu shap_cfg_cmd->qs_shapping_para = cpu_to_le32(shaper_para); 543ee9e4424SYonglong Liu 544ee9e4424SYonglong Liu ret = hclge_cmd_send(&hdev->hw, &desc, 1); 545ee9e4424SYonglong Liu if (ret) { 546ee9e4424SYonglong Liu dev_err(&hdev->pdev->dev, 547adcf738bSGuojia Liao "vf%u, qs%u failed to set tx_rate:%d, ret=%d\n", 548ee9e4424SYonglong Liu vport->vport_id, shap_cfg_cmd->qs_id, 549ee9e4424SYonglong Liu max_tx_rate, ret); 550ee9e4424SYonglong Liu return ret; 551ee9e4424SYonglong Liu } 552ee9e4424SYonglong Liu } 553ee9e4424SYonglong Liu 554ee9e4424SYonglong Liu return 0; 555ee9e4424SYonglong Liu } 556ee9e4424SYonglong Liu 55784844054SSalil static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) 55884844054SSalil { 55984844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 56084844054SSalil struct hclge_dev *hdev = vport->back; 561672ad0edSHuazhong Tan u16 max_rss_size; 56284844054SSalil u8 i; 56384844054SSalil 564de67a690SYunsheng Lin /* TC configuration is shared by PF/VF in one port, only allow 565de67a690SYunsheng Lin * one tc for VF for simplicity. VF's vport_id is non zero. 566de67a690SYunsheng Lin */ 567de67a690SYunsheng Lin kinfo->num_tc = vport->vport_id ? 1 : 568de67a690SYunsheng Lin min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); 569de67a690SYunsheng Lin vport->qs_offset = (vport->vport_id ? hdev->tm_info.num_tc : 0) + 570de67a690SYunsheng Lin (vport->vport_id ? (vport->vport_id - 1) : 0); 571de67a690SYunsheng Lin 572672ad0edSHuazhong Tan max_rss_size = min_t(u16, hdev->rss_size_max, 573672ad0edSHuazhong Tan vport->alloc_tqps / kinfo->num_tc); 574672ad0edSHuazhong Tan 5759b2f3477SWeihang Li /* Set to user value, no larger than max_rss_size. */ 576672ad0edSHuazhong Tan if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size && 577672ad0edSHuazhong Tan kinfo->req_rss_size <= max_rss_size) { 578adcf738bSGuojia Liao dev_info(&hdev->pdev->dev, "rss changes from %u to %u\n", 579672ad0edSHuazhong Tan kinfo->rss_size, kinfo->req_rss_size); 580672ad0edSHuazhong Tan kinfo->rss_size = kinfo->req_rss_size; 581672ad0edSHuazhong Tan } else if (kinfo->rss_size > max_rss_size || 582672ad0edSHuazhong Tan (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) { 583580a05f9SYonglong Liu /* if user not set rss, the rss_size should compare with the 584580a05f9SYonglong Liu * valid msi numbers to ensure one to one map between tqp and 585580a05f9SYonglong Liu * irq as default. 586580a05f9SYonglong Liu */ 587580a05f9SYonglong Liu if (!kinfo->req_rss_size) 588580a05f9SYonglong Liu max_rss_size = min_t(u16, max_rss_size, 589580a05f9SYonglong Liu (hdev->num_nic_msi - 1) / 590580a05f9SYonglong Liu kinfo->num_tc); 591580a05f9SYonglong Liu 5929b2f3477SWeihang Li /* Set to the maximum specification value (max_rss_size). */ 593672ad0edSHuazhong Tan kinfo->rss_size = max_rss_size; 594672ad0edSHuazhong Tan } 595672ad0edSHuazhong Tan 596672ad0edSHuazhong Tan kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size; 59784844054SSalil vport->dwrr = 100; /* 100 percent as init */ 59868ece54eSYunsheng Lin vport->alloc_rss_size = kinfo->rss_size; 599de67a690SYunsheng Lin vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit; 60084844054SSalil 601af958827SHuazhong Tan for (i = 0; i < HNAE3_MAX_TC; i++) { 602de67a690SYunsheng Lin if (hdev->hw_tc_map & BIT(i) && i < kinfo->num_tc) { 60384844054SSalil kinfo->tc_info[i].enable = true; 60484844054SSalil kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size; 60584844054SSalil kinfo->tc_info[i].tqp_count = kinfo->rss_size; 60684844054SSalil kinfo->tc_info[i].tc = i; 60784844054SSalil } else { 60884844054SSalil /* Set to default queue if TC is disable */ 60984844054SSalil kinfo->tc_info[i].enable = false; 61084844054SSalil kinfo->tc_info[i].tqp_offset = 0; 61184844054SSalil kinfo->tc_info[i].tqp_count = 1; 61284844054SSalil kinfo->tc_info[i].tc = 0; 61384844054SSalil } 61484844054SSalil } 615c5795c53SYunsheng Lin 616c5795c53SYunsheng Lin memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc, 617c5795c53SYunsheng Lin FIELD_SIZEOF(struct hnae3_knic_private_info, prio_tc)); 61884844054SSalil } 61984844054SSalil 62084844054SSalil static void hclge_tm_vport_info_update(struct hclge_dev *hdev) 62184844054SSalil { 62284844054SSalil struct hclge_vport *vport = hdev->vport; 62384844054SSalil u32 i; 62484844054SSalil 62584844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 62684844054SSalil hclge_tm_vport_tc_info_update(vport); 62784844054SSalil 62884844054SSalil vport++; 62984844054SSalil } 63084844054SSalil } 63184844054SSalil 63284844054SSalil static void hclge_tm_tc_info_init(struct hclge_dev *hdev) 63384844054SSalil { 63484844054SSalil u8 i; 63584844054SSalil 63684844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 63784844054SSalil hdev->tm_info.tc_info[i].tc_id = i; 63884844054SSalil hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR; 63984844054SSalil hdev->tm_info.tc_info[i].pgid = 0; 64084844054SSalil hdev->tm_info.tc_info[i].bw_limit = 64184844054SSalil hdev->tm_info.pg_info[0].bw_limit; 64284844054SSalil } 64384844054SSalil 644c5795c53SYunsheng Lin for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) 645c5795c53SYunsheng Lin hdev->tm_info.prio_tc[i] = 646c5795c53SYunsheng Lin (i >= hdev->tm_info.num_tc) ? 0 : i; 647c5795c53SYunsheng Lin 648ae179b2fSYunsheng Lin /* DCB is enabled if we have more than 1 TC or pfc_en is 649ae179b2fSYunsheng Lin * non-zero. 650ae179b2fSYunsheng Lin */ 651ae179b2fSYunsheng Lin if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en) 6527979a223SYunsheng Lin hdev->flag |= HCLGE_FLAG_DCB_ENABLE; 6537979a223SYunsheng Lin else 65484844054SSalil hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; 65584844054SSalil } 65684844054SSalil 65784844054SSalil static void hclge_tm_pg_info_init(struct hclge_dev *hdev) 65884844054SSalil { 659b37ce587SYufeng Mo #define BW_PERCENT 100 660b37ce587SYufeng Mo 66184844054SSalil u8 i; 66284844054SSalil 66384844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 66484844054SSalil int k; 66584844054SSalil 666b37ce587SYufeng Mo hdev->tm_info.pg_dwrr[i] = i ? 0 : BW_PERCENT; 66784844054SSalil 66884844054SSalil hdev->tm_info.pg_info[i].pg_id = i; 66984844054SSalil hdev->tm_info.pg_info[i].pg_sch_mode = HCLGE_SCH_MODE_DWRR; 67084844054SSalil 67184844054SSalil hdev->tm_info.pg_info[i].bw_limit = HCLGE_ETHER_MAX_RATE; 67284844054SSalil 67384844054SSalil if (i != 0) 67484844054SSalil continue; 67584844054SSalil 67684844054SSalil hdev->tm_info.pg_info[i].tc_bit_map = hdev->hw_tc_map; 67784844054SSalil for (k = 0; k < hdev->tm_info.num_tc; k++) 678b37ce587SYufeng Mo hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT; 67984844054SSalil } 68084844054SSalil } 68184844054SSalil 6827979a223SYunsheng Lin static void hclge_pfc_info_init(struct hclge_dev *hdev) 6837979a223SYunsheng Lin { 6847979a223SYunsheng Lin if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) { 6857979a223SYunsheng Lin if (hdev->fc_mode_last_time == HCLGE_FC_PFC) 6867979a223SYunsheng Lin dev_warn(&hdev->pdev->dev, 6877979a223SYunsheng Lin "DCB is disable, but last mode is FC_PFC\n"); 6887979a223SYunsheng Lin 6897979a223SYunsheng Lin hdev->tm_info.fc_mode = hdev->fc_mode_last_time; 6907979a223SYunsheng Lin } else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) { 6917979a223SYunsheng Lin /* fc_mode_last_time record the last fc_mode when 6927979a223SYunsheng Lin * DCB is enabled, so that fc_mode can be set to 6937979a223SYunsheng Lin * the correct value when DCB is disabled. 6947979a223SYunsheng Lin */ 6957979a223SYunsheng Lin hdev->fc_mode_last_time = hdev->tm_info.fc_mode; 6967979a223SYunsheng Lin hdev->tm_info.fc_mode = HCLGE_FC_PFC; 6977979a223SYunsheng Lin } 6987979a223SYunsheng Lin } 6997979a223SYunsheng Lin 700b6872fd3SYunsheng Lin static void hclge_tm_schd_info_init(struct hclge_dev *hdev) 70184844054SSalil { 70284844054SSalil hclge_tm_pg_info_init(hdev); 70384844054SSalil 70484844054SSalil hclge_tm_tc_info_init(hdev); 70584844054SSalil 70684844054SSalil hclge_tm_vport_info_update(hdev); 70784844054SSalil 7087979a223SYunsheng Lin hclge_pfc_info_init(hdev); 70984844054SSalil } 71084844054SSalil 71184844054SSalil static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev) 71284844054SSalil { 71384844054SSalil int ret; 71484844054SSalil u32 i; 71584844054SSalil 71684844054SSalil if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) 71784844054SSalil return 0; 71884844054SSalil 71984844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 72084844054SSalil /* Cfg mapping */ 72184844054SSalil ret = hclge_tm_pg_to_pri_map_cfg( 72284844054SSalil hdev, i, hdev->tm_info.pg_info[i].tc_bit_map); 72384844054SSalil if (ret) 72484844054SSalil return ret; 72584844054SSalil } 72684844054SSalil 72784844054SSalil return 0; 72884844054SSalil } 72984844054SSalil 73084844054SSalil static int hclge_tm_pg_shaper_cfg(struct hclge_dev *hdev) 73184844054SSalil { 73284844054SSalil u8 ir_u, ir_b, ir_s; 73363cbf7a9SYufeng Mo u32 shaper_para; 73484844054SSalil int ret; 73584844054SSalil u32 i; 73684844054SSalil 73784844054SSalil /* Cfg pg schd */ 73884844054SSalil if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) 73984844054SSalil return 0; 74084844054SSalil 74184844054SSalil /* Pg to pri */ 74284844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 74384844054SSalil /* Calc shaper para */ 74484844054SSalil ret = hclge_shaper_para_calc( 74584844054SSalil hdev->tm_info.pg_info[i].bw_limit, 74684844054SSalil HCLGE_SHAPER_LVL_PG, 74784844054SSalil &ir_b, &ir_u, &ir_s); 74884844054SSalil if (ret) 74984844054SSalil return ret; 75084844054SSalil 75163cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 75263cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 75363cbf7a9SYufeng Mo HCLGE_SHAPER_BS_S_DEF); 75484844054SSalil ret = hclge_tm_pg_shapping_cfg(hdev, 75584844054SSalil HCLGE_TM_SHAP_C_BUCKET, i, 75663cbf7a9SYufeng Mo shaper_para); 75784844054SSalil if (ret) 75884844054SSalil return ret; 75984844054SSalil 76063cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 76184844054SSalil HCLGE_SHAPER_BS_U_DEF, 76284844054SSalil HCLGE_SHAPER_BS_S_DEF); 76363cbf7a9SYufeng Mo ret = hclge_tm_pg_shapping_cfg(hdev, 76463cbf7a9SYufeng Mo HCLGE_TM_SHAP_P_BUCKET, i, 76563cbf7a9SYufeng Mo shaper_para); 76684844054SSalil if (ret) 76784844054SSalil return ret; 76884844054SSalil } 76984844054SSalil 77084844054SSalil return 0; 77184844054SSalil } 77284844054SSalil 77384844054SSalil static int hclge_tm_pg_dwrr_cfg(struct hclge_dev *hdev) 77484844054SSalil { 77584844054SSalil int ret; 77684844054SSalil u32 i; 77784844054SSalil 77884844054SSalil /* cfg pg schd */ 77984844054SSalil if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) 78084844054SSalil return 0; 78184844054SSalil 78284844054SSalil /* pg to prio */ 78384844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 78484844054SSalil /* Cfg dwrr */ 7859b2f3477SWeihang Li ret = hclge_tm_pg_weight_cfg(hdev, i, hdev->tm_info.pg_dwrr[i]); 78684844054SSalil if (ret) 78784844054SSalil return ret; 78884844054SSalil } 78984844054SSalil 79084844054SSalil return 0; 79184844054SSalil } 79284844054SSalil 79384844054SSalil static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev, 79484844054SSalil struct hclge_vport *vport) 79584844054SSalil { 79684844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 79784844054SSalil struct hnae3_queue **tqp = kinfo->tqp; 79884844054SSalil struct hnae3_tc_info *v_tc_info; 79984844054SSalil u32 i, j; 80084844054SSalil int ret; 80184844054SSalil 80284844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 80384844054SSalil v_tc_info = &kinfo->tc_info[i]; 80484844054SSalil for (j = 0; j < v_tc_info->tqp_count; j++) { 80584844054SSalil struct hnae3_queue *q = tqp[v_tc_info->tqp_offset + j]; 80684844054SSalil 80784844054SSalil ret = hclge_tm_q_to_qs_map_cfg(hdev, 80884844054SSalil hclge_get_queue_id(q), 80984844054SSalil vport->qs_offset + i); 81084844054SSalil if (ret) 81184844054SSalil return ret; 81284844054SSalil } 81384844054SSalil } 81484844054SSalil 81584844054SSalil return 0; 81684844054SSalil } 81784844054SSalil 81884844054SSalil static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev) 81984844054SSalil { 82084844054SSalil struct hclge_vport *vport = hdev->vport; 82184844054SSalil int ret; 822cc9bb43aSYunsheng Lin u32 i, k; 82384844054SSalil 82484844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 82584844054SSalil /* Cfg qs -> pri mapping, one by one mapping */ 826de67a690SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 827de67a690SYunsheng Lin struct hnae3_knic_private_info *kinfo = 828de67a690SYunsheng Lin &vport[k].nic.kinfo; 829de67a690SYunsheng Lin 830de67a690SYunsheng Lin for (i = 0; i < kinfo->num_tc; i++) { 831cc9bb43aSYunsheng Lin ret = hclge_tm_qs_to_pri_map_cfg( 832cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, i); 83384844054SSalil if (ret) 83484844054SSalil return ret; 83584844054SSalil } 836de67a690SYunsheng Lin } 83784844054SSalil } else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) { 83884844054SSalil /* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */ 83984844054SSalil for (k = 0; k < hdev->num_alloc_vport; k++) 84084844054SSalil for (i = 0; i < HNAE3_MAX_TC; i++) { 84184844054SSalil ret = hclge_tm_qs_to_pri_map_cfg( 84284844054SSalil hdev, vport[k].qs_offset + i, k); 84384844054SSalil if (ret) 84484844054SSalil return ret; 84584844054SSalil } 84684844054SSalil } else { 84784844054SSalil return -EINVAL; 84884844054SSalil } 84984844054SSalil 85084844054SSalil /* Cfg q -> qs mapping */ 85184844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 85284844054SSalil ret = hclge_vport_q_to_qs_map(hdev, vport); 85384844054SSalil if (ret) 85484844054SSalil return ret; 85584844054SSalil 85684844054SSalil vport++; 85784844054SSalil } 85884844054SSalil 85984844054SSalil return 0; 86084844054SSalil } 86184844054SSalil 86284844054SSalil static int hclge_tm_pri_tc_base_shaper_cfg(struct hclge_dev *hdev) 86384844054SSalil { 86484844054SSalil u8 ir_u, ir_b, ir_s; 86563cbf7a9SYufeng Mo u32 shaper_para; 86684844054SSalil int ret; 86784844054SSalil u32 i; 86884844054SSalil 86984844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 87084844054SSalil ret = hclge_shaper_para_calc( 87184844054SSalil hdev->tm_info.tc_info[i].bw_limit, 87284844054SSalil HCLGE_SHAPER_LVL_PRI, 87384844054SSalil &ir_b, &ir_u, &ir_s); 87484844054SSalil if (ret) 87584844054SSalil return ret; 87684844054SSalil 87763cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 87863cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 87984844054SSalil HCLGE_SHAPER_BS_S_DEF); 88063cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, i, 88163cbf7a9SYufeng Mo shaper_para); 88284844054SSalil if (ret) 88384844054SSalil return ret; 88484844054SSalil 88563cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 88663cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 88784844054SSalil HCLGE_SHAPER_BS_S_DEF); 88863cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, i, 88963cbf7a9SYufeng Mo shaper_para); 89084844054SSalil if (ret) 89184844054SSalil return ret; 89284844054SSalil } 89384844054SSalil 89484844054SSalil return 0; 89584844054SSalil } 89684844054SSalil 89784844054SSalil static int hclge_tm_pri_vnet_base_shaper_pri_cfg(struct hclge_vport *vport) 89884844054SSalil { 89984844054SSalil struct hclge_dev *hdev = vport->back; 90084844054SSalil u8 ir_u, ir_b, ir_s; 90163cbf7a9SYufeng Mo u32 shaper_para; 90284844054SSalil int ret; 90384844054SSalil 90484844054SSalil ret = hclge_shaper_para_calc(vport->bw_limit, HCLGE_SHAPER_LVL_VF, 90584844054SSalil &ir_b, &ir_u, &ir_s); 90684844054SSalil if (ret) 90784844054SSalil return ret; 90884844054SSalil 90963cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 91063cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 91184844054SSalil HCLGE_SHAPER_BS_S_DEF); 91263cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, 91363cbf7a9SYufeng Mo vport->vport_id, shaper_para); 91484844054SSalil if (ret) 91584844054SSalil return ret; 91684844054SSalil 91763cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 91884844054SSalil HCLGE_SHAPER_BS_U_DEF, 91984844054SSalil HCLGE_SHAPER_BS_S_DEF); 92063cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, 92163cbf7a9SYufeng Mo vport->vport_id, shaper_para); 92284844054SSalil if (ret) 92384844054SSalil return ret; 92484844054SSalil 92584844054SSalil return 0; 92684844054SSalil } 92784844054SSalil 92884844054SSalil static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport) 92984844054SSalil { 93084844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 93184844054SSalil struct hclge_dev *hdev = vport->back; 93284844054SSalil u8 ir_u, ir_b, ir_s; 93384844054SSalil u32 i; 93484844054SSalil int ret; 93584844054SSalil 93684844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 93784844054SSalil ret = hclge_shaper_para_calc( 93884844054SSalil hdev->tm_info.tc_info[i].bw_limit, 93984844054SSalil HCLGE_SHAPER_LVL_QSET, 94084844054SSalil &ir_b, &ir_u, &ir_s); 94184844054SSalil if (ret) 94284844054SSalil return ret; 94384844054SSalil } 94484844054SSalil 94584844054SSalil return 0; 94684844054SSalil } 94784844054SSalil 94884844054SSalil static int hclge_tm_pri_vnet_base_shaper_cfg(struct hclge_dev *hdev) 94984844054SSalil { 95084844054SSalil struct hclge_vport *vport = hdev->vport; 95184844054SSalil int ret; 95284844054SSalil u32 i; 95384844054SSalil 95484844054SSalil /* Need config vport shaper */ 95584844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 95684844054SSalil ret = hclge_tm_pri_vnet_base_shaper_pri_cfg(vport); 95784844054SSalil if (ret) 95884844054SSalil return ret; 95984844054SSalil 96084844054SSalil ret = hclge_tm_pri_vnet_base_shaper_qs_cfg(vport); 96184844054SSalil if (ret) 96284844054SSalil return ret; 96384844054SSalil 96484844054SSalil vport++; 96584844054SSalil } 96684844054SSalil 96784844054SSalil return 0; 96884844054SSalil } 96984844054SSalil 97084844054SSalil static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev) 97184844054SSalil { 97284844054SSalil int ret; 97384844054SSalil 97484844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 97584844054SSalil ret = hclge_tm_pri_tc_base_shaper_cfg(hdev); 97684844054SSalil if (ret) 97784844054SSalil return ret; 97884844054SSalil } else { 97984844054SSalil ret = hclge_tm_pri_vnet_base_shaper_cfg(hdev); 98084844054SSalil if (ret) 98184844054SSalil return ret; 98284844054SSalil } 98384844054SSalil 98484844054SSalil return 0; 98584844054SSalil } 98684844054SSalil 98784844054SSalil static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) 98884844054SSalil { 989cc9bb43aSYunsheng Lin struct hclge_vport *vport = hdev->vport; 99084844054SSalil struct hclge_pg_info *pg_info; 99184844054SSalil u8 dwrr; 99284844054SSalil int ret; 993cc9bb43aSYunsheng Lin u32 i, k; 99484844054SSalil 99584844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 99684844054SSalil pg_info = 99784844054SSalil &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; 99884844054SSalil dwrr = pg_info->tc_dwrr[i]; 99984844054SSalil 100084844054SSalil ret = hclge_tm_pri_weight_cfg(hdev, i, dwrr); 100184844054SSalil if (ret) 100284844054SSalil return ret; 100384844054SSalil 1004cc9bb43aSYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1005cc9bb43aSYunsheng Lin ret = hclge_tm_qs_weight_cfg( 1006cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, 1007cc9bb43aSYunsheng Lin vport[k].dwrr); 100884844054SSalil if (ret) 100984844054SSalil return ret; 101084844054SSalil } 1011cc9bb43aSYunsheng Lin } 101284844054SSalil 101384844054SSalil return 0; 101484844054SSalil } 101584844054SSalil 1016330baff5SYunsheng Lin static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) 1017330baff5SYunsheng Lin { 1018330baff5SYunsheng Lin #define DEFAULT_TC_WEIGHT 1 1019330baff5SYunsheng Lin #define DEFAULT_TC_OFFSET 14 1020330baff5SYunsheng Lin 1021330baff5SYunsheng Lin struct hclge_ets_tc_weight_cmd *ets_weight; 1022330baff5SYunsheng Lin struct hclge_desc desc; 1023ebaf1908SWeihang Li unsigned int i; 1024330baff5SYunsheng Lin 1025330baff5SYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, false); 1026330baff5SYunsheng Lin ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data; 1027330baff5SYunsheng Lin 1028330baff5SYunsheng Lin for (i = 0; i < HNAE3_MAX_TC; i++) { 1029330baff5SYunsheng Lin struct hclge_pg_info *pg_info; 1030330baff5SYunsheng Lin 1031330baff5SYunsheng Lin ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT; 1032330baff5SYunsheng Lin 1033330baff5SYunsheng Lin if (!(hdev->hw_tc_map & BIT(i))) 1034330baff5SYunsheng Lin continue; 1035330baff5SYunsheng Lin 1036330baff5SYunsheng Lin pg_info = 1037330baff5SYunsheng Lin &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; 1038330baff5SYunsheng Lin ets_weight->tc_weight[i] = pg_info->tc_dwrr[i]; 1039330baff5SYunsheng Lin } 1040330baff5SYunsheng Lin 1041330baff5SYunsheng Lin ets_weight->weight_offset = DEFAULT_TC_OFFSET; 1042330baff5SYunsheng Lin 1043330baff5SYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 1044330baff5SYunsheng Lin } 1045330baff5SYunsheng Lin 104684844054SSalil static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport) 104784844054SSalil { 104884844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 104984844054SSalil struct hclge_dev *hdev = vport->back; 105084844054SSalil int ret; 105184844054SSalil u8 i; 105284844054SSalil 105384844054SSalil /* Vf dwrr */ 105484844054SSalil ret = hclge_tm_pri_weight_cfg(hdev, vport->vport_id, vport->dwrr); 105584844054SSalil if (ret) 105684844054SSalil return ret; 105784844054SSalil 105884844054SSalil /* Qset dwrr */ 105984844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 106084844054SSalil ret = hclge_tm_qs_weight_cfg( 106184844054SSalil hdev, vport->qs_offset + i, 106284844054SSalil hdev->tm_info.pg_info[0].tc_dwrr[i]); 106384844054SSalil if (ret) 106484844054SSalil return ret; 106584844054SSalil } 106684844054SSalil 106784844054SSalil return 0; 106884844054SSalil } 106984844054SSalil 107084844054SSalil static int hclge_tm_pri_vnet_base_dwrr_cfg(struct hclge_dev *hdev) 107184844054SSalil { 107284844054SSalil struct hclge_vport *vport = hdev->vport; 107384844054SSalil int ret; 107484844054SSalil u32 i; 107584844054SSalil 107684844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 107784844054SSalil ret = hclge_tm_pri_vnet_base_dwrr_pri_cfg(vport); 107884844054SSalil if (ret) 107984844054SSalil return ret; 108084844054SSalil 108184844054SSalil vport++; 108284844054SSalil } 108384844054SSalil 108484844054SSalil return 0; 108584844054SSalil } 108684844054SSalil 108784844054SSalil static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev) 108884844054SSalil { 108984844054SSalil int ret; 109084844054SSalil 109184844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 109284844054SSalil ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev); 109384844054SSalil if (ret) 109484844054SSalil return ret; 1095330baff5SYunsheng Lin 1096330baff5SYunsheng Lin if (!hnae3_dev_dcb_supported(hdev)) 1097330baff5SYunsheng Lin return 0; 1098330baff5SYunsheng Lin 1099330baff5SYunsheng Lin ret = hclge_tm_ets_tc_dwrr_cfg(hdev); 1100330baff5SYunsheng Lin if (ret == -EOPNOTSUPP) { 1101330baff5SYunsheng Lin dev_warn(&hdev->pdev->dev, 1102330baff5SYunsheng Lin "fw %08x does't support ets tc weight cmd\n", 1103330baff5SYunsheng Lin hdev->fw_version); 1104330baff5SYunsheng Lin ret = 0; 1105330baff5SYunsheng Lin } 1106330baff5SYunsheng Lin 1107330baff5SYunsheng Lin return ret; 110884844054SSalil } else { 110984844054SSalil ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev); 111084844054SSalil if (ret) 111184844054SSalil return ret; 111284844054SSalil } 111384844054SSalil 111484844054SSalil return 0; 111584844054SSalil } 111684844054SSalil 11179e5157baSYunsheng Lin static int hclge_tm_map_cfg(struct hclge_dev *hdev) 111884844054SSalil { 111984844054SSalil int ret; 112084844054SSalil 112177f255c1SYunsheng Lin ret = hclge_up_to_tc_map(hdev); 112277f255c1SYunsheng Lin if (ret) 112377f255c1SYunsheng Lin return ret; 112477f255c1SYunsheng Lin 112584844054SSalil ret = hclge_tm_pg_to_pri_map(hdev); 112684844054SSalil if (ret) 112784844054SSalil return ret; 112884844054SSalil 112984844054SSalil return hclge_tm_pri_q_qs_cfg(hdev); 113084844054SSalil } 113184844054SSalil 113284844054SSalil static int hclge_tm_shaper_cfg(struct hclge_dev *hdev) 113384844054SSalil { 113484844054SSalil int ret; 113584844054SSalil 11360a5677d3SYunsheng Lin ret = hclge_tm_port_shaper_cfg(hdev); 11370a5677d3SYunsheng Lin if (ret) 11380a5677d3SYunsheng Lin return ret; 11390a5677d3SYunsheng Lin 114084844054SSalil ret = hclge_tm_pg_shaper_cfg(hdev); 114184844054SSalil if (ret) 114284844054SSalil return ret; 114384844054SSalil 114484844054SSalil return hclge_tm_pri_shaper_cfg(hdev); 114584844054SSalil } 114684844054SSalil 114784844054SSalil int hclge_tm_dwrr_cfg(struct hclge_dev *hdev) 114884844054SSalil { 114984844054SSalil int ret; 115084844054SSalil 115184844054SSalil ret = hclge_tm_pg_dwrr_cfg(hdev); 115284844054SSalil if (ret) 115384844054SSalil return ret; 115484844054SSalil 115584844054SSalil return hclge_tm_pri_dwrr_cfg(hdev); 115684844054SSalil } 115784844054SSalil 115884844054SSalil static int hclge_tm_lvl2_schd_mode_cfg(struct hclge_dev *hdev) 115984844054SSalil { 116084844054SSalil int ret; 116184844054SSalil u8 i; 116284844054SSalil 116384844054SSalil /* Only being config on TC-Based scheduler mode */ 116484844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) 116584844054SSalil return 0; 116684844054SSalil 116784844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 116884844054SSalil ret = hclge_tm_pg_schd_mode_cfg(hdev, i); 116984844054SSalil if (ret) 117084844054SSalil return ret; 117184844054SSalil } 117284844054SSalil 117384844054SSalil return 0; 117484844054SSalil } 117584844054SSalil 117684844054SSalil static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport) 117784844054SSalil { 117884844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 117984844054SSalil struct hclge_dev *hdev = vport->back; 118084844054SSalil int ret; 118184844054SSalil u8 i; 118284844054SSalil 118304f25edbSYunsheng Lin if (vport->vport_id >= HNAE3_MAX_TC) 118404f25edbSYunsheng Lin return -EINVAL; 118504f25edbSYunsheng Lin 118684844054SSalil ret = hclge_tm_pri_schd_mode_cfg(hdev, vport->vport_id); 118784844054SSalil if (ret) 118884844054SSalil return ret; 118984844054SSalil 119084844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 1191cc9bb43aSYunsheng Lin u8 sch_mode = hdev->tm_info.tc_info[i].tc_sch_mode; 1192cc9bb43aSYunsheng Lin 1193cc9bb43aSYunsheng Lin ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i, 1194cc9bb43aSYunsheng Lin sch_mode); 119584844054SSalil if (ret) 119684844054SSalil return ret; 119784844054SSalil } 119884844054SSalil 119984844054SSalil return 0; 120084844054SSalil } 120184844054SSalil 120284844054SSalil static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) 120384844054SSalil { 120484844054SSalil struct hclge_vport *vport = hdev->vport; 120584844054SSalil int ret; 1206cc9bb43aSYunsheng Lin u8 i, k; 120784844054SSalil 120884844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 120984844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 121084844054SSalil ret = hclge_tm_pri_schd_mode_cfg(hdev, i); 121184844054SSalil if (ret) 121284844054SSalil return ret; 121384844054SSalil 1214cc9bb43aSYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1215cc9bb43aSYunsheng Lin ret = hclge_tm_qs_schd_mode_cfg( 1216cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, 1217cc9bb43aSYunsheng Lin HCLGE_SCH_MODE_DWRR); 121884844054SSalil if (ret) 121984844054SSalil return ret; 122084844054SSalil } 1221cc9bb43aSYunsheng Lin } 122284844054SSalil } else { 122384844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 122484844054SSalil ret = hclge_tm_schd_mode_vnet_base_cfg(vport); 122584844054SSalil if (ret) 122684844054SSalil return ret; 122784844054SSalil 122884844054SSalil vport++; 122984844054SSalil } 123084844054SSalil } 123184844054SSalil 123284844054SSalil return 0; 123384844054SSalil } 123484844054SSalil 12359e5157baSYunsheng Lin static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) 123684844054SSalil { 123784844054SSalil int ret; 123884844054SSalil 123984844054SSalil ret = hclge_tm_lvl2_schd_mode_cfg(hdev); 124084844054SSalil if (ret) 124184844054SSalil return ret; 124284844054SSalil 124384844054SSalil return hclge_tm_lvl34_schd_mode_cfg(hdev); 124484844054SSalil } 124584844054SSalil 12469e5157baSYunsheng Lin int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) 124784844054SSalil { 124884844054SSalil int ret; 124984844054SSalil 125084844054SSalil /* Cfg tm mapping */ 125184844054SSalil ret = hclge_tm_map_cfg(hdev); 125284844054SSalil if (ret) 125384844054SSalil return ret; 125484844054SSalil 125584844054SSalil /* Cfg tm shaper */ 125684844054SSalil ret = hclge_tm_shaper_cfg(hdev); 125784844054SSalil if (ret) 125884844054SSalil return ret; 125984844054SSalil 126084844054SSalil /* Cfg dwrr */ 126184844054SSalil ret = hclge_tm_dwrr_cfg(hdev); 126284844054SSalil if (ret) 126384844054SSalil return ret; 126484844054SSalil 126584844054SSalil /* Cfg schd mode for each level schd */ 126684844054SSalil return hclge_tm_schd_mode_hw(hdev); 126784844054SSalil } 126884844054SSalil 1269e98d7183SFuyun Liang static int hclge_pause_param_setup_hw(struct hclge_dev *hdev) 127018838d0cSFuyun Liang { 127118838d0cSFuyun Liang struct hclge_mac *mac = &hdev->hw.mac; 127218838d0cSFuyun Liang 1273e98d7183SFuyun Liang return hclge_pause_param_cfg(hdev, mac->mac_addr, 127418838d0cSFuyun Liang HCLGE_DEFAULT_PAUSE_TRANS_GAP, 127518838d0cSFuyun Liang HCLGE_DEFAULT_PAUSE_TRANS_TIME); 127618838d0cSFuyun Liang } 127718838d0cSFuyun Liang 12789dc2145dSYunsheng Lin static int hclge_pfc_setup_hw(struct hclge_dev *hdev) 12799dc2145dSYunsheng Lin { 12809dc2145dSYunsheng Lin u8 enable_bitmap = 0; 12819dc2145dSYunsheng Lin 12829dc2145dSYunsheng Lin if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) 12839dc2145dSYunsheng Lin enable_bitmap = HCLGE_TX_MAC_PAUSE_EN_MSK | 12849dc2145dSYunsheng Lin HCLGE_RX_MAC_PAUSE_EN_MSK; 12859dc2145dSYunsheng Lin 12869dc2145dSYunsheng Lin return hclge_pfc_pause_en_cfg(hdev, enable_bitmap, 1287d3ad430aSYunsheng Lin hdev->tm_info.pfc_en); 12889dc2145dSYunsheng Lin } 12899dc2145dSYunsheng Lin 129067bf2541SYunsheng Lin /* Each Tc has a 1024 queue sets to backpress, it divides to 129167bf2541SYunsheng Lin * 32 group, each group contains 32 queue sets, which can be 129267bf2541SYunsheng Lin * represented by u32 bitmap. 129367bf2541SYunsheng Lin */ 129467bf2541SYunsheng Lin static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc) 129567bf2541SYunsheng Lin { 1296e8ccbb7dSYunsheng Lin int i; 129767bf2541SYunsheng Lin 129867bf2541SYunsheng Lin for (i = 0; i < HCLGE_BP_GRP_NUM; i++) { 1299e8ccbb7dSYunsheng Lin u32 qs_bitmap = 0; 1300e8ccbb7dSYunsheng Lin int k, ret; 130167bf2541SYunsheng Lin 130267bf2541SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1303e8ccbb7dSYunsheng Lin struct hclge_vport *vport = &hdev->vport[k]; 130467bf2541SYunsheng Lin u16 qs_id = vport->qs_offset + tc; 130567bf2541SYunsheng Lin u8 grp, sub_grp; 130667bf2541SYunsheng Lin 1307e4e87715SPeng Li grp = hnae3_get_field(qs_id, HCLGE_BP_GRP_ID_M, 130867bf2541SYunsheng Lin HCLGE_BP_GRP_ID_S); 1309e4e87715SPeng Li sub_grp = hnae3_get_field(qs_id, HCLGE_BP_SUB_GRP_ID_M, 131067bf2541SYunsheng Lin HCLGE_BP_SUB_GRP_ID_S); 131167bf2541SYunsheng Lin if (i == grp) 131267bf2541SYunsheng Lin qs_bitmap |= (1 << sub_grp); 131367bf2541SYunsheng Lin } 131467bf2541SYunsheng Lin 131567bf2541SYunsheng Lin ret = hclge_tm_qs_bp_cfg(hdev, tc, i, qs_bitmap); 131667bf2541SYunsheng Lin if (ret) 131767bf2541SYunsheng Lin return ret; 131867bf2541SYunsheng Lin } 131967bf2541SYunsheng Lin 132067bf2541SYunsheng Lin return 0; 132167bf2541SYunsheng Lin } 132267bf2541SYunsheng Lin 13239dc2145dSYunsheng Lin static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) 13249dc2145dSYunsheng Lin { 13259dc2145dSYunsheng Lin bool tx_en, rx_en; 13269dc2145dSYunsheng Lin 13279dc2145dSYunsheng Lin switch (hdev->tm_info.fc_mode) { 13289dc2145dSYunsheng Lin case HCLGE_FC_NONE: 13299dc2145dSYunsheng Lin tx_en = false; 13309dc2145dSYunsheng Lin rx_en = false; 13319dc2145dSYunsheng Lin break; 13329dc2145dSYunsheng Lin case HCLGE_FC_RX_PAUSE: 13339dc2145dSYunsheng Lin tx_en = false; 13349dc2145dSYunsheng Lin rx_en = true; 13359dc2145dSYunsheng Lin break; 13369dc2145dSYunsheng Lin case HCLGE_FC_TX_PAUSE: 13379dc2145dSYunsheng Lin tx_en = true; 13389dc2145dSYunsheng Lin rx_en = false; 13399dc2145dSYunsheng Lin break; 13409dc2145dSYunsheng Lin case HCLGE_FC_FULL: 13419dc2145dSYunsheng Lin tx_en = true; 13429dc2145dSYunsheng Lin rx_en = true; 13439dc2145dSYunsheng Lin break; 13446d0ec65cSYunsheng Lin case HCLGE_FC_PFC: 13456d0ec65cSYunsheng Lin tx_en = false; 13466d0ec65cSYunsheng Lin rx_en = false; 13476d0ec65cSYunsheng Lin break; 13489dc2145dSYunsheng Lin default: 13499dc2145dSYunsheng Lin tx_en = true; 13509dc2145dSYunsheng Lin rx_en = true; 13519dc2145dSYunsheng Lin } 13529dc2145dSYunsheng Lin 13539dc2145dSYunsheng Lin return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en); 13549dc2145dSYunsheng Lin } 13559dc2145dSYunsheng Lin 135673fc9c48SHuazhong Tan static int hclge_tm_bp_setup(struct hclge_dev *hdev) 135773fc9c48SHuazhong Tan { 135873fc9c48SHuazhong Tan int ret = 0; 135973fc9c48SHuazhong Tan int i; 136073fc9c48SHuazhong Tan 136173fc9c48SHuazhong Tan for (i = 0; i < hdev->tm_info.num_tc; i++) { 136273fc9c48SHuazhong Tan ret = hclge_bp_setup_hw(hdev, i); 136373fc9c48SHuazhong Tan if (ret) 136473fc9c48SHuazhong Tan return ret; 136573fc9c48SHuazhong Tan } 136673fc9c48SHuazhong Tan 136773fc9c48SHuazhong Tan return ret; 136873fc9c48SHuazhong Tan } 136973fc9c48SHuazhong Tan 137044e59e37SYunsheng Lin int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init) 137184844054SSalil { 137284844054SSalil int ret; 137384844054SSalil 1374e98d7183SFuyun Liang ret = hclge_pause_param_setup_hw(hdev); 137518838d0cSFuyun Liang if (ret) 137618838d0cSFuyun Liang return ret; 137718838d0cSFuyun Liang 13786d0ec65cSYunsheng Lin ret = hclge_mac_pause_setup_hw(hdev); 13796d0ec65cSYunsheng Lin if (ret) 13806d0ec65cSYunsheng Lin return ret; 138184844054SSalil 13829dc2145dSYunsheng Lin /* Only DCB-supported dev supports qset back pressure and pfc cmd */ 13832daf4a65SYunsheng Lin if (!hnae3_dev_dcb_supported(hdev)) 13842daf4a65SYunsheng Lin return 0; 13852daf4a65SYunsheng Lin 138644e59e37SYunsheng Lin /* GE MAC does not support PFC, when driver is initializing and MAC 138744e59e37SYunsheng Lin * is in GE Mode, ignore the error here, otherwise initialization 138844e59e37SYunsheng Lin * will fail. 138944e59e37SYunsheng Lin */ 13909dc2145dSYunsheng Lin ret = hclge_pfc_setup_hw(hdev); 139144e59e37SYunsheng Lin if (init && ret == -EOPNOTSUPP) 139244e59e37SYunsheng Lin dev_warn(&hdev->pdev->dev, "GE MAC does not support pfc\n"); 1393fba2efdaSHuazhong Tan else if (ret) { 1394fba2efdaSHuazhong Tan dev_err(&hdev->pdev->dev, "config pfc failed! ret = %d\n", 1395fba2efdaSHuazhong Tan ret); 139644e59e37SYunsheng Lin return ret; 1397fba2efdaSHuazhong Tan } 13989dc2145dSYunsheng Lin 139973fc9c48SHuazhong Tan return hclge_tm_bp_setup(hdev); 140077f255c1SYunsheng Lin } 140177f255c1SYunsheng Lin 1402e432abfbSYunsheng Lin void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc) 140377f255c1SYunsheng Lin { 140477f255c1SYunsheng Lin struct hclge_vport *vport = hdev->vport; 140577f255c1SYunsheng Lin struct hnae3_knic_private_info *kinfo; 140677f255c1SYunsheng Lin u32 i, k; 140777f255c1SYunsheng Lin 140877f255c1SYunsheng Lin for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { 140977f255c1SYunsheng Lin hdev->tm_info.prio_tc[i] = prio_tc[i]; 141077f255c1SYunsheng Lin 141177f255c1SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 141277f255c1SYunsheng Lin kinfo = &vport[k].nic.kinfo; 141377f255c1SYunsheng Lin kinfo->prio_tc[i] = prio_tc[i]; 141477f255c1SYunsheng Lin } 141577f255c1SYunsheng Lin } 141677f255c1SYunsheng Lin } 141777f255c1SYunsheng Lin 1418e432abfbSYunsheng Lin void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc) 141977f255c1SYunsheng Lin { 14209b2f3477SWeihang Li u8 bit_map = 0; 14219b2f3477SWeihang Li u8 i; 142277f255c1SYunsheng Lin 142377f255c1SYunsheng Lin hdev->tm_info.num_tc = num_tc; 142477f255c1SYunsheng Lin 142577f255c1SYunsheng Lin for (i = 0; i < hdev->tm_info.num_tc; i++) 142677f255c1SYunsheng Lin bit_map |= BIT(i); 142777f255c1SYunsheng Lin 142877f255c1SYunsheng Lin if (!bit_map) { 142977f255c1SYunsheng Lin bit_map = 1; 143077f255c1SYunsheng Lin hdev->tm_info.num_tc = 1; 143177f255c1SYunsheng Lin } 143277f255c1SYunsheng Lin 143377f255c1SYunsheng Lin hdev->hw_tc_map = bit_map; 143477f255c1SYunsheng Lin 143577f255c1SYunsheng Lin hclge_tm_schd_info_init(hdev); 143684844054SSalil } 143784844054SSalil 1438ae179b2fSYunsheng Lin void hclge_tm_pfc_info_update(struct hclge_dev *hdev) 1439ae179b2fSYunsheng Lin { 1440ae179b2fSYunsheng Lin /* DCB is enabled if we have more than 1 TC or pfc_en is 1441ae179b2fSYunsheng Lin * non-zero. 1442ae179b2fSYunsheng Lin */ 1443ae179b2fSYunsheng Lin if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en) 1444ae179b2fSYunsheng Lin hdev->flag |= HCLGE_FLAG_DCB_ENABLE; 1445ae179b2fSYunsheng Lin else 1446ae179b2fSYunsheng Lin hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; 1447ae179b2fSYunsheng Lin 1448ae179b2fSYunsheng Lin hclge_pfc_info_init(hdev); 1449ae179b2fSYunsheng Lin } 1450ae179b2fSYunsheng Lin 145144e59e37SYunsheng Lin int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) 145284844054SSalil { 145384844054SSalil int ret; 145484844054SSalil 145584844054SSalil if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && 145684844054SSalil (hdev->tx_sch_mode != HCLGE_FLAG_VNET_BASE_SCH_MODE)) 145784844054SSalil return -ENOTSUPP; 145884844054SSalil 145984844054SSalil ret = hclge_tm_schd_setup_hw(hdev); 146084844054SSalil if (ret) 146184844054SSalil return ret; 146284844054SSalil 146344e59e37SYunsheng Lin ret = hclge_pause_setup_hw(hdev, init); 146484844054SSalil if (ret) 146584844054SSalil return ret; 146684844054SSalil 146784844054SSalil return 0; 146884844054SSalil } 146984844054SSalil 147084844054SSalil int hclge_tm_schd_init(struct hclge_dev *hdev) 147184844054SSalil { 14727979a223SYunsheng Lin /* fc_mode is HCLGE_FC_FULL on reset */ 14737979a223SYunsheng Lin hdev->tm_info.fc_mode = HCLGE_FC_FULL; 14747979a223SYunsheng Lin hdev->fc_mode_last_time = hdev->tm_info.fc_mode; 14757979a223SYunsheng Lin 1476b6872fd3SYunsheng Lin if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE && 1477b6872fd3SYunsheng Lin hdev->tm_info.num_pg != 1) 1478b6872fd3SYunsheng Lin return -EINVAL; 1479b6872fd3SYunsheng Lin 1480b6872fd3SYunsheng Lin hclge_tm_schd_info_init(hdev); 148184844054SSalil 148244e59e37SYunsheng Lin return hclge_tm_init_hw(hdev, true); 148384844054SSalil } 1484672ad0edSHuazhong Tan 1485672ad0edSHuazhong Tan int hclge_tm_vport_map_update(struct hclge_dev *hdev) 1486672ad0edSHuazhong Tan { 1487672ad0edSHuazhong Tan struct hclge_vport *vport = hdev->vport; 1488672ad0edSHuazhong Tan int ret; 1489672ad0edSHuazhong Tan 1490672ad0edSHuazhong Tan hclge_tm_vport_tc_info_update(vport); 1491672ad0edSHuazhong Tan 1492672ad0edSHuazhong Tan ret = hclge_vport_q_to_qs_map(hdev, vport); 1493672ad0edSHuazhong Tan if (ret) 1494672ad0edSHuazhong Tan return ret; 1495672ad0edSHuazhong Tan 1496672ad0edSHuazhong Tan if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) 1497672ad0edSHuazhong Tan return 0; 1498672ad0edSHuazhong Tan 1499672ad0edSHuazhong Tan return hclge_tm_bp_setup(hdev); 1500672ad0edSHuazhong Tan } 1501