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 4984844054SSalil 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 */ 6184844054SSalil if (shaper_level >= HCLGE_SHAPER_LVL_CNT) 6284844054SSalil return -EINVAL; 6384844054SSalil 6484844054SSalil tick = tick_array[shaper_level]; 6584844054SSalil 6684844054SSalil /** 6784844054SSalil * Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0 6884844054SSalil * the formula is changed to: 6984844054SSalil * 126 * 1 * 8 7084844054SSalil * ir_calc = ---------------- * 1000 7184844054SSalil * tick * 1 7284844054SSalil */ 73b37ce587SYufeng Mo ir_calc = (DIVISOR_IR_B_126 + (tick >> 1) - 1) / tick; 7484844054SSalil 7584844054SSalil if (ir_calc == ir) { 7684844054SSalil *ir_b = 126; 7784844054SSalil *ir_u = 0; 7884844054SSalil *ir_s = 0; 7984844054SSalil 8084844054SSalil return 0; 8184844054SSalil } else if (ir_calc > ir) { 8284844054SSalil /* Increasing the denominator to select ir_s value */ 8384844054SSalil while (ir_calc > ir) { 8484844054SSalil ir_s_calc++; 85b37ce587SYufeng Mo ir_calc = DIVISOR_IR_B_126 / (tick * (1 << ir_s_calc)); 8684844054SSalil } 8784844054SSalil 8884844054SSalil if (ir_calc == ir) 8984844054SSalil *ir_b = 126; 9084844054SSalil else 91b37ce587SYufeng Mo *ir_b = (ir * tick * (1 << ir_s_calc) + 92b37ce587SYufeng Mo (DIVISOR_CLK >> 1)) / DIVISOR_CLK; 9384844054SSalil } else { 9484844054SSalil /* Increasing the numerator to select ir_u value */ 9584844054SSalil u32 numerator; 9684844054SSalil 9784844054SSalil while (ir_calc < ir) { 9884844054SSalil ir_u_calc++; 99b37ce587SYufeng Mo numerator = DIVISOR_IR_B_126 * (1 << ir_u_calc); 10084844054SSalil ir_calc = (numerator + (tick >> 1)) / tick; 10184844054SSalil } 10284844054SSalil 10384844054SSalil if (ir_calc == ir) { 10484844054SSalil *ir_b = 126; 10584844054SSalil } else { 106b37ce587SYufeng Mo u32 denominator = (DIVISOR_CLK * (1 << --ir_u_calc)); 10784844054SSalil *ir_b = (ir * tick + (denominator >> 1)) / denominator; 10884844054SSalil } 10984844054SSalil } 11084844054SSalil 11184844054SSalil *ir_u = ir_u_calc; 11284844054SSalil *ir_s = ir_s_calc; 11384844054SSalil 11484844054SSalil return 0; 11584844054SSalil } 11684844054SSalil 11764fd2300SPeng Li static int hclge_pfc_stats_get(struct hclge_dev *hdev, 11864fd2300SPeng Li enum hclge_opcode_type opcode, u64 *stats) 11964fd2300SPeng Li { 12064fd2300SPeng Li struct hclge_desc desc[HCLGE_TM_PFC_PKT_GET_CMD_NUM]; 12164fd2300SPeng Li int ret, i, j; 12264fd2300SPeng Li 12364fd2300SPeng Li if (!(opcode == HCLGE_OPC_QUERY_PFC_RX_PKT_CNT || 12464fd2300SPeng Li opcode == HCLGE_OPC_QUERY_PFC_TX_PKT_CNT)) 12564fd2300SPeng Li return -EINVAL; 12664fd2300SPeng Li 12763cbf7a9SYufeng Mo for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM - 1; i++) { 12864fd2300SPeng Li hclge_cmd_setup_basic_desc(&desc[i], opcode, true); 12964fd2300SPeng Li desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); 13064fd2300SPeng Li } 13164fd2300SPeng Li 13263cbf7a9SYufeng Mo hclge_cmd_setup_basic_desc(&desc[i], opcode, true); 13363cbf7a9SYufeng Mo 13464fd2300SPeng Li ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_TM_PFC_PKT_GET_CMD_NUM); 13520670328SYunsheng Lin if (ret) 13664fd2300SPeng Li return ret; 13764fd2300SPeng Li 13864fd2300SPeng Li for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM; i++) { 13964fd2300SPeng Li struct hclge_pfc_stats_cmd *pfc_stats = 14064fd2300SPeng Li (struct hclge_pfc_stats_cmd *)desc[i].data; 14164fd2300SPeng Li 14264fd2300SPeng Li for (j = 0; j < HCLGE_TM_PFC_NUM_GET_PER_CMD; j++) { 14364fd2300SPeng Li u32 index = i * HCLGE_TM_PFC_PKT_GET_CMD_NUM + j; 14464fd2300SPeng Li 14564fd2300SPeng Li if (index < HCLGE_MAX_TC_NUM) 14664fd2300SPeng Li stats[index] = 14764fd2300SPeng Li le64_to_cpu(pfc_stats->pkt_num[j]); 14864fd2300SPeng Li } 14964fd2300SPeng Li } 15064fd2300SPeng Li return 0; 15164fd2300SPeng Li } 15264fd2300SPeng Li 15364fd2300SPeng Li int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats) 15464fd2300SPeng Li { 15564fd2300SPeng Li return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_RX_PKT_CNT, stats); 15664fd2300SPeng Li } 15764fd2300SPeng Li 15864fd2300SPeng Li int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats) 15964fd2300SPeng Li { 16064fd2300SPeng Li return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_TX_PKT_CNT, stats); 16164fd2300SPeng Li } 16264fd2300SPeng Li 16361387774SPeng Li int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx) 16484844054SSalil { 16584844054SSalil struct hclge_desc desc; 16684844054SSalil 16784844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PAUSE_EN, false); 16884844054SSalil 16984844054SSalil desc.data[0] = cpu_to_le32((tx ? HCLGE_TX_MAC_PAUSE_EN_MSK : 0) | 17084844054SSalil (rx ? HCLGE_RX_MAC_PAUSE_EN_MSK : 0)); 17184844054SSalil 17284844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 17384844054SSalil } 17484844054SSalil 1759dc2145dSYunsheng Lin static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap, 1769dc2145dSYunsheng Lin u8 pfc_bitmap) 1779dc2145dSYunsheng Lin { 1789dc2145dSYunsheng Lin struct hclge_desc desc; 179d0d72bacSJian Shen struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)desc.data; 1809dc2145dSYunsheng Lin 1819dc2145dSYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_PFC_PAUSE_EN, false); 1829dc2145dSYunsheng Lin 1839dc2145dSYunsheng Lin pfc->tx_rx_en_bitmap = tx_rx_bitmap; 1849dc2145dSYunsheng Lin pfc->pri_en_bitmap = pfc_bitmap; 1859dc2145dSYunsheng Lin 1869dc2145dSYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 1879dc2145dSYunsheng Lin } 1889dc2145dSYunsheng Lin 189e98d7183SFuyun Liang static int hclge_pause_param_cfg(struct hclge_dev *hdev, const u8 *addr, 19018838d0cSFuyun Liang u8 pause_trans_gap, u16 pause_trans_time) 19118838d0cSFuyun Liang { 19218838d0cSFuyun Liang struct hclge_cfg_pause_param_cmd *pause_param; 19318838d0cSFuyun Liang struct hclge_desc desc; 19418838d0cSFuyun Liang 195d0d72bacSJian Shen pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data; 19618838d0cSFuyun Liang 19718838d0cSFuyun Liang hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, false); 19818838d0cSFuyun Liang 19918838d0cSFuyun Liang ether_addr_copy(pause_param->mac_addr, addr); 200cd2086bfSFuyun Liang ether_addr_copy(pause_param->mac_addr_extra, addr); 20118838d0cSFuyun Liang pause_param->pause_trans_gap = pause_trans_gap; 20218838d0cSFuyun Liang pause_param->pause_trans_time = cpu_to_le16(pause_trans_time); 20318838d0cSFuyun Liang 20418838d0cSFuyun Liang return hclge_cmd_send(&hdev->hw, &desc, 1); 20518838d0cSFuyun Liang } 20618838d0cSFuyun Liang 207e98d7183SFuyun Liang int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr) 20818838d0cSFuyun Liang { 20918838d0cSFuyun Liang struct hclge_cfg_pause_param_cmd *pause_param; 21018838d0cSFuyun Liang struct hclge_desc desc; 21118838d0cSFuyun Liang u16 trans_time; 21218838d0cSFuyun Liang u8 trans_gap; 21318838d0cSFuyun Liang int ret; 21418838d0cSFuyun Liang 215d0d72bacSJian Shen pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data; 21618838d0cSFuyun Liang 21718838d0cSFuyun Liang hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, true); 21818838d0cSFuyun Liang 21918838d0cSFuyun Liang ret = hclge_cmd_send(&hdev->hw, &desc, 1); 22018838d0cSFuyun Liang if (ret) 22118838d0cSFuyun Liang return ret; 22218838d0cSFuyun Liang 22318838d0cSFuyun Liang trans_gap = pause_param->pause_trans_gap; 22418838d0cSFuyun Liang trans_time = le16_to_cpu(pause_param->pause_trans_time); 22518838d0cSFuyun Liang 2269b2f3477SWeihang Li return hclge_pause_param_cfg(hdev, mac_addr, trans_gap, trans_time); 22718838d0cSFuyun Liang } 22818838d0cSFuyun Liang 22984844054SSalil static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id) 23084844054SSalil { 23184844054SSalil u8 tc; 23284844054SSalil 233c5795c53SYunsheng Lin tc = hdev->tm_info.prio_tc[pri_id]; 23484844054SSalil 23584844054SSalil if (tc >= hdev->tm_info.num_tc) 23684844054SSalil return -EINVAL; 23784844054SSalil 23884844054SSalil /** 23984844054SSalil * the register for priority has four bytes, the first bytes includes 24084844054SSalil * priority0 and priority1, the higher 4bit stands for priority1 24184844054SSalil * while the lower 4bit stands for priority0, as below: 24284844054SSalil * first byte: | pri_1 | pri_0 | 24384844054SSalil * second byte: | pri_3 | pri_2 | 24484844054SSalil * third byte: | pri_5 | pri_4 | 24584844054SSalil * fourth byte: | pri_7 | pri_6 | 24684844054SSalil */ 24784844054SSalil pri[pri_id >> 1] |= tc << ((pri_id & 1) * 4); 24884844054SSalil 24984844054SSalil return 0; 25084844054SSalil } 25184844054SSalil 25284844054SSalil static int hclge_up_to_tc_map(struct hclge_dev *hdev) 25384844054SSalil { 25484844054SSalil struct hclge_desc desc; 25584844054SSalil u8 *pri = (u8 *)desc.data; 25684844054SSalil u8 pri_id; 25784844054SSalil int ret; 25884844054SSalil 25984844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, false); 26084844054SSalil 261c5795c53SYunsheng Lin for (pri_id = 0; pri_id < HNAE3_MAX_USER_PRIO; pri_id++) { 26284844054SSalil ret = hclge_fill_pri_array(hdev, pri, pri_id); 26384844054SSalil if (ret) 26484844054SSalil return ret; 26584844054SSalil } 26684844054SSalil 26784844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 26884844054SSalil } 26984844054SSalil 27084844054SSalil static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev, 27184844054SSalil u8 pg_id, u8 pri_bit_map) 27284844054SSalil { 27384844054SSalil struct hclge_pg_to_pri_link_cmd *map; 27484844054SSalil struct hclge_desc desc; 27584844054SSalil 27684844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_TO_PRI_LINK, false); 27784844054SSalil 27884844054SSalil map = (struct hclge_pg_to_pri_link_cmd *)desc.data; 27984844054SSalil 28084844054SSalil map->pg_id = pg_id; 28184844054SSalil map->pri_bit_map = pri_bit_map; 28284844054SSalil 28384844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 28484844054SSalil } 28584844054SSalil 28684844054SSalil static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev, 28784844054SSalil u16 qs_id, u8 pri) 28884844054SSalil { 28984844054SSalil struct hclge_qs_to_pri_link_cmd *map; 29084844054SSalil struct hclge_desc desc; 29184844054SSalil 29284844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_TO_PRI_LINK, false); 29384844054SSalil 29484844054SSalil map = (struct hclge_qs_to_pri_link_cmd *)desc.data; 29584844054SSalil 29684844054SSalil map->qs_id = cpu_to_le16(qs_id); 29784844054SSalil map->priority = pri; 29884844054SSalil map->link_vld = HCLGE_TM_QS_PRI_LINK_VLD_MSK; 29984844054SSalil 30084844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 30184844054SSalil } 30284844054SSalil 30384844054SSalil static int hclge_tm_q_to_qs_map_cfg(struct hclge_dev *hdev, 30432c7fbc8SJian Shen u16 q_id, u16 qs_id) 30584844054SSalil { 30684844054SSalil struct hclge_nq_to_qs_link_cmd *map; 30784844054SSalil struct hclge_desc desc; 30884844054SSalil 30984844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NQ_TO_QS_LINK, false); 31084844054SSalil 31184844054SSalil map = (struct hclge_nq_to_qs_link_cmd *)desc.data; 31284844054SSalil 31384844054SSalil map->nq_id = cpu_to_le16(q_id); 31484844054SSalil map->qset_id = cpu_to_le16(qs_id | HCLGE_TM_Q_QS_LINK_VLD_MSK); 31584844054SSalil 31684844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 31784844054SSalil } 31884844054SSalil 31984844054SSalil static int hclge_tm_pg_weight_cfg(struct hclge_dev *hdev, u8 pg_id, 32084844054SSalil u8 dwrr) 32184844054SSalil { 32284844054SSalil struct hclge_pg_weight_cmd *weight; 32384844054SSalil struct hclge_desc desc; 32484844054SSalil 32584844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_WEIGHT, false); 32684844054SSalil 32784844054SSalil weight = (struct hclge_pg_weight_cmd *)desc.data; 32884844054SSalil 32984844054SSalil weight->pg_id = pg_id; 33084844054SSalil weight->dwrr = dwrr; 33184844054SSalil 33284844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 33384844054SSalil } 33484844054SSalil 33584844054SSalil static int hclge_tm_pri_weight_cfg(struct hclge_dev *hdev, u8 pri_id, 33684844054SSalil u8 dwrr) 33784844054SSalil { 33884844054SSalil struct hclge_priority_weight_cmd *weight; 33984844054SSalil struct hclge_desc desc; 34084844054SSalil 34184844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_WEIGHT, false); 34284844054SSalil 34384844054SSalil weight = (struct hclge_priority_weight_cmd *)desc.data; 34484844054SSalil 34584844054SSalil weight->pri_id = pri_id; 34684844054SSalil weight->dwrr = dwrr; 34784844054SSalil 34884844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 34984844054SSalil } 35084844054SSalil 35184844054SSalil static int hclge_tm_qs_weight_cfg(struct hclge_dev *hdev, u16 qs_id, 35284844054SSalil u8 dwrr) 35384844054SSalil { 35484844054SSalil struct hclge_qs_weight_cmd *weight; 35584844054SSalil struct hclge_desc desc; 35684844054SSalil 35784844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_WEIGHT, false); 35884844054SSalil 35984844054SSalil weight = (struct hclge_qs_weight_cmd *)desc.data; 36084844054SSalil 36184844054SSalil weight->qs_id = cpu_to_le16(qs_id); 36284844054SSalil weight->dwrr = dwrr; 36384844054SSalil 36484844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 36584844054SSalil } 36684844054SSalil 36763cbf7a9SYufeng Mo static u32 hclge_tm_get_shapping_para(u8 ir_b, u8 ir_u, u8 ir_s, 36863cbf7a9SYufeng Mo u8 bs_b, u8 bs_s) 36963cbf7a9SYufeng Mo { 37063cbf7a9SYufeng Mo u32 shapping_para = 0; 37163cbf7a9SYufeng Mo 37263cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, IR_B, ir_b); 37363cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, IR_U, ir_u); 37463cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, IR_S, ir_s); 37563cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, BS_B, bs_b); 37663cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, BS_S, bs_s); 37763cbf7a9SYufeng Mo 37863cbf7a9SYufeng Mo return shapping_para; 37963cbf7a9SYufeng Mo } 38063cbf7a9SYufeng Mo 38184844054SSalil static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev, 38284844054SSalil enum hclge_shap_bucket bucket, u8 pg_id, 38363cbf7a9SYufeng Mo u32 shapping_para) 38484844054SSalil { 38584844054SSalil struct hclge_pg_shapping_cmd *shap_cfg_cmd; 38684844054SSalil enum hclge_opcode_type opcode; 38784844054SSalil struct hclge_desc desc; 38884844054SSalil 38984844054SSalil opcode = bucket ? HCLGE_OPC_TM_PG_P_SHAPPING : 39084844054SSalil HCLGE_OPC_TM_PG_C_SHAPPING; 39184844054SSalil hclge_cmd_setup_basic_desc(&desc, opcode, false); 39284844054SSalil 39384844054SSalil shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data; 39484844054SSalil 39584844054SSalil shap_cfg_cmd->pg_id = pg_id; 39684844054SSalil 397a90bb9a5SYunsheng Lin shap_cfg_cmd->pg_shapping_para = cpu_to_le32(shapping_para); 39884844054SSalil 39984844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 40084844054SSalil } 40184844054SSalil 4020a5677d3SYunsheng Lin static int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev) 4030a5677d3SYunsheng Lin { 4040a5677d3SYunsheng Lin struct hclge_port_shapping_cmd *shap_cfg_cmd; 4050a5677d3SYunsheng Lin struct hclge_desc desc; 4060a5677d3SYunsheng Lin u32 shapping_para = 0; 4070a5677d3SYunsheng Lin u8 ir_u, ir_b, ir_s; 4080a5677d3SYunsheng Lin int ret; 4090a5677d3SYunsheng Lin 410d9ea1562SYunsheng Lin ret = hclge_shaper_para_calc(hdev->hw.mac.speed, 4110a5677d3SYunsheng Lin HCLGE_SHAPER_LVL_PORT, 4120a5677d3SYunsheng Lin &ir_b, &ir_u, &ir_s); 4130a5677d3SYunsheng Lin if (ret) 4140a5677d3SYunsheng Lin return ret; 4150a5677d3SYunsheng Lin 4160a5677d3SYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PORT_SHAPPING, false); 4170a5677d3SYunsheng Lin shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data; 4180a5677d3SYunsheng Lin 41963cbf7a9SYufeng Mo shapping_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 42063cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 42163cbf7a9SYufeng Mo HCLGE_SHAPER_BS_S_DEF); 4220a5677d3SYunsheng Lin 4230a5677d3SYunsheng Lin shap_cfg_cmd->port_shapping_para = cpu_to_le32(shapping_para); 4240a5677d3SYunsheng Lin 4250a5677d3SYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 4260a5677d3SYunsheng Lin } 4270a5677d3SYunsheng Lin 42884844054SSalil static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev, 42984844054SSalil enum hclge_shap_bucket bucket, u8 pri_id, 43063cbf7a9SYufeng Mo u32 shapping_para) 43184844054SSalil { 43284844054SSalil struct hclge_pri_shapping_cmd *shap_cfg_cmd; 43384844054SSalil enum hclge_opcode_type opcode; 43484844054SSalil struct hclge_desc desc; 43584844054SSalil 43684844054SSalil opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING : 43784844054SSalil HCLGE_OPC_TM_PRI_C_SHAPPING; 43884844054SSalil 43984844054SSalil hclge_cmd_setup_basic_desc(&desc, opcode, false); 44084844054SSalil 44184844054SSalil shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data; 44284844054SSalil 44384844054SSalil shap_cfg_cmd->pri_id = pri_id; 44484844054SSalil 445a90bb9a5SYunsheng Lin shap_cfg_cmd->pri_shapping_para = cpu_to_le32(shapping_para); 44684844054SSalil 44784844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 44884844054SSalil } 44984844054SSalil 45084844054SSalil static int hclge_tm_pg_schd_mode_cfg(struct hclge_dev *hdev, u8 pg_id) 45184844054SSalil { 45284844054SSalil struct hclge_desc desc; 45384844054SSalil 45484844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, false); 45584844054SSalil 45684844054SSalil if (hdev->tm_info.pg_info[pg_id].pg_sch_mode == HCLGE_SCH_MODE_DWRR) 45784844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 45884844054SSalil else 45984844054SSalil desc.data[1] = 0; 46084844054SSalil 46184844054SSalil desc.data[0] = cpu_to_le32(pg_id); 46284844054SSalil 46384844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 46484844054SSalil } 46584844054SSalil 46684844054SSalil static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id) 46784844054SSalil { 46884844054SSalil struct hclge_desc desc; 46984844054SSalil 47084844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, false); 47184844054SSalil 47284844054SSalil if (hdev->tm_info.tc_info[pri_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR) 47384844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 47484844054SSalil else 47584844054SSalil desc.data[1] = 0; 47684844054SSalil 47784844054SSalil desc.data[0] = cpu_to_le32(pri_id); 47884844054SSalil 47984844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 48084844054SSalil } 48184844054SSalil 482cc9bb43aSYunsheng Lin static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id, u8 mode) 48384844054SSalil { 48484844054SSalil struct hclge_desc desc; 48584844054SSalil 48684844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false); 48784844054SSalil 488cc9bb43aSYunsheng Lin if (mode == HCLGE_SCH_MODE_DWRR) 48984844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 49084844054SSalil else 49184844054SSalil desc.data[1] = 0; 49284844054SSalil 49384844054SSalil desc.data[0] = cpu_to_le32(qs_id); 49484844054SSalil 49584844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 49684844054SSalil } 49784844054SSalil 49867bf2541SYunsheng Lin static int hclge_tm_qs_bp_cfg(struct hclge_dev *hdev, u8 tc, u8 grp_id, 49967bf2541SYunsheng Lin u32 bit_map) 50084844054SSalil { 50184844054SSalil struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd; 50284844054SSalil struct hclge_desc desc; 50384844054SSalil 50484844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_BP_TO_QSET_MAPPING, 50584844054SSalil false); 50684844054SSalil 50784844054SSalil bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data; 50884844054SSalil 50984844054SSalil bp_to_qs_map_cmd->tc_id = tc; 51067bf2541SYunsheng Lin bp_to_qs_map_cmd->qs_group_id = grp_id; 51167bf2541SYunsheng Lin bp_to_qs_map_cmd->qs_bit_map = cpu_to_le32(bit_map); 51284844054SSalil 51384844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 51484844054SSalil } 51584844054SSalil 51684844054SSalil static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport) 51784844054SSalil { 51884844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 51984844054SSalil struct hclge_dev *hdev = vport->back; 520672ad0edSHuazhong Tan u16 max_rss_size; 52184844054SSalil u8 i; 52284844054SSalil 523de67a690SYunsheng Lin /* TC configuration is shared by PF/VF in one port, only allow 524de67a690SYunsheng Lin * one tc for VF for simplicity. VF's vport_id is non zero. 525de67a690SYunsheng Lin */ 526de67a690SYunsheng Lin kinfo->num_tc = vport->vport_id ? 1 : 527de67a690SYunsheng Lin min_t(u16, vport->alloc_tqps, hdev->tm_info.num_tc); 528de67a690SYunsheng Lin vport->qs_offset = (vport->vport_id ? hdev->tm_info.num_tc : 0) + 529de67a690SYunsheng Lin (vport->vport_id ? (vport->vport_id - 1) : 0); 530de67a690SYunsheng Lin 531672ad0edSHuazhong Tan max_rss_size = min_t(u16, hdev->rss_size_max, 532672ad0edSHuazhong Tan vport->alloc_tqps / kinfo->num_tc); 533672ad0edSHuazhong Tan 5349b2f3477SWeihang Li /* Set to user value, no larger than max_rss_size. */ 535672ad0edSHuazhong Tan if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size && 536672ad0edSHuazhong Tan kinfo->req_rss_size <= max_rss_size) { 537672ad0edSHuazhong Tan dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n", 538672ad0edSHuazhong Tan kinfo->rss_size, kinfo->req_rss_size); 539672ad0edSHuazhong Tan kinfo->rss_size = kinfo->req_rss_size; 540672ad0edSHuazhong Tan } else if (kinfo->rss_size > max_rss_size || 541672ad0edSHuazhong Tan (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size)) { 5429b2f3477SWeihang Li /* Set to the maximum specification value (max_rss_size). */ 543672ad0edSHuazhong Tan dev_info(&hdev->pdev->dev, "rss changes from %d to %d\n", 544672ad0edSHuazhong Tan kinfo->rss_size, max_rss_size); 545672ad0edSHuazhong Tan kinfo->rss_size = max_rss_size; 546672ad0edSHuazhong Tan } 547672ad0edSHuazhong Tan 548672ad0edSHuazhong Tan kinfo->num_tqps = kinfo->num_tc * kinfo->rss_size; 54984844054SSalil vport->dwrr = 100; /* 100 percent as init */ 55068ece54eSYunsheng Lin vport->alloc_rss_size = kinfo->rss_size; 551de67a690SYunsheng Lin vport->bw_limit = hdev->tm_info.pg_info[0].bw_limit; 55284844054SSalil 553af958827SHuazhong Tan for (i = 0; i < HNAE3_MAX_TC; i++) { 554de67a690SYunsheng Lin if (hdev->hw_tc_map & BIT(i) && i < kinfo->num_tc) { 55584844054SSalil kinfo->tc_info[i].enable = true; 55684844054SSalil kinfo->tc_info[i].tqp_offset = i * kinfo->rss_size; 55784844054SSalil kinfo->tc_info[i].tqp_count = kinfo->rss_size; 55884844054SSalil kinfo->tc_info[i].tc = i; 55984844054SSalil } else { 56084844054SSalil /* Set to default queue if TC is disable */ 56184844054SSalil kinfo->tc_info[i].enable = false; 56284844054SSalil kinfo->tc_info[i].tqp_offset = 0; 56384844054SSalil kinfo->tc_info[i].tqp_count = 1; 56484844054SSalil kinfo->tc_info[i].tc = 0; 56584844054SSalil } 56684844054SSalil } 567c5795c53SYunsheng Lin 568c5795c53SYunsheng Lin memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc, 569c5795c53SYunsheng Lin FIELD_SIZEOF(struct hnae3_knic_private_info, prio_tc)); 57084844054SSalil } 57184844054SSalil 57284844054SSalil static void hclge_tm_vport_info_update(struct hclge_dev *hdev) 57384844054SSalil { 57484844054SSalil struct hclge_vport *vport = hdev->vport; 57584844054SSalil u32 i; 57684844054SSalil 57784844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 57884844054SSalil hclge_tm_vport_tc_info_update(vport); 57984844054SSalil 58084844054SSalil vport++; 58184844054SSalil } 58284844054SSalil } 58384844054SSalil 58484844054SSalil static void hclge_tm_tc_info_init(struct hclge_dev *hdev) 58584844054SSalil { 58684844054SSalil u8 i; 58784844054SSalil 58884844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 58984844054SSalil hdev->tm_info.tc_info[i].tc_id = i; 59084844054SSalil hdev->tm_info.tc_info[i].tc_sch_mode = HCLGE_SCH_MODE_DWRR; 59184844054SSalil hdev->tm_info.tc_info[i].pgid = 0; 59284844054SSalil hdev->tm_info.tc_info[i].bw_limit = 59384844054SSalil hdev->tm_info.pg_info[0].bw_limit; 59484844054SSalil } 59584844054SSalil 596c5795c53SYunsheng Lin for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) 597c5795c53SYunsheng Lin hdev->tm_info.prio_tc[i] = 598c5795c53SYunsheng Lin (i >= hdev->tm_info.num_tc) ? 0 : i; 599c5795c53SYunsheng Lin 6007979a223SYunsheng Lin /* DCB is enabled if we have more than 1 TC */ 6017979a223SYunsheng Lin if (hdev->tm_info.num_tc > 1) 6027979a223SYunsheng Lin hdev->flag |= HCLGE_FLAG_DCB_ENABLE; 6037979a223SYunsheng Lin else 60484844054SSalil hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; 60584844054SSalil } 60684844054SSalil 60784844054SSalil static void hclge_tm_pg_info_init(struct hclge_dev *hdev) 60884844054SSalil { 609b37ce587SYufeng Mo #define BW_PERCENT 100 610b37ce587SYufeng Mo 61184844054SSalil u8 i; 61284844054SSalil 61384844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 61484844054SSalil int k; 61584844054SSalil 616b37ce587SYufeng Mo hdev->tm_info.pg_dwrr[i] = i ? 0 : BW_PERCENT; 61784844054SSalil 61884844054SSalil hdev->tm_info.pg_info[i].pg_id = i; 61984844054SSalil hdev->tm_info.pg_info[i].pg_sch_mode = HCLGE_SCH_MODE_DWRR; 62084844054SSalil 62184844054SSalil hdev->tm_info.pg_info[i].bw_limit = HCLGE_ETHER_MAX_RATE; 62284844054SSalil 62384844054SSalil if (i != 0) 62484844054SSalil continue; 62584844054SSalil 62684844054SSalil hdev->tm_info.pg_info[i].tc_bit_map = hdev->hw_tc_map; 62784844054SSalil for (k = 0; k < hdev->tm_info.num_tc; k++) 628b37ce587SYufeng Mo hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT; 62984844054SSalil } 63084844054SSalil } 63184844054SSalil 6327979a223SYunsheng Lin static void hclge_pfc_info_init(struct hclge_dev *hdev) 6337979a223SYunsheng Lin { 6347979a223SYunsheng Lin if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) { 6357979a223SYunsheng Lin if (hdev->fc_mode_last_time == HCLGE_FC_PFC) 6367979a223SYunsheng Lin dev_warn(&hdev->pdev->dev, 6377979a223SYunsheng Lin "DCB is disable, but last mode is FC_PFC\n"); 6387979a223SYunsheng Lin 6397979a223SYunsheng Lin hdev->tm_info.fc_mode = hdev->fc_mode_last_time; 6407979a223SYunsheng Lin } else if (hdev->tm_info.fc_mode != HCLGE_FC_PFC) { 6417979a223SYunsheng Lin /* fc_mode_last_time record the last fc_mode when 6427979a223SYunsheng Lin * DCB is enabled, so that fc_mode can be set to 6437979a223SYunsheng Lin * the correct value when DCB is disabled. 6447979a223SYunsheng Lin */ 6457979a223SYunsheng Lin hdev->fc_mode_last_time = hdev->tm_info.fc_mode; 6467979a223SYunsheng Lin hdev->tm_info.fc_mode = HCLGE_FC_PFC; 6477979a223SYunsheng Lin } 6487979a223SYunsheng Lin } 6497979a223SYunsheng Lin 65084844054SSalil static int hclge_tm_schd_info_init(struct hclge_dev *hdev) 65184844054SSalil { 65284844054SSalil if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && 65384844054SSalil (hdev->tm_info.num_pg != 1)) 65484844054SSalil return -EINVAL; 65584844054SSalil 65684844054SSalil hclge_tm_pg_info_init(hdev); 65784844054SSalil 65884844054SSalil hclge_tm_tc_info_init(hdev); 65984844054SSalil 66084844054SSalil hclge_tm_vport_info_update(hdev); 66184844054SSalil 6627979a223SYunsheng Lin hclge_pfc_info_init(hdev); 66384844054SSalil 66484844054SSalil return 0; 66584844054SSalil } 66684844054SSalil 66784844054SSalil static int hclge_tm_pg_to_pri_map(struct hclge_dev *hdev) 66884844054SSalil { 66984844054SSalil int ret; 67084844054SSalil u32 i; 67184844054SSalil 67284844054SSalil if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) 67384844054SSalil return 0; 67484844054SSalil 67584844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 67684844054SSalil /* Cfg mapping */ 67784844054SSalil ret = hclge_tm_pg_to_pri_map_cfg( 67884844054SSalil hdev, i, hdev->tm_info.pg_info[i].tc_bit_map); 67984844054SSalil if (ret) 68084844054SSalil return ret; 68184844054SSalil } 68284844054SSalil 68384844054SSalil return 0; 68484844054SSalil } 68584844054SSalil 68684844054SSalil static int hclge_tm_pg_shaper_cfg(struct hclge_dev *hdev) 68784844054SSalil { 68884844054SSalil u8 ir_u, ir_b, ir_s; 68963cbf7a9SYufeng Mo u32 shaper_para; 69084844054SSalil int ret; 69184844054SSalil u32 i; 69284844054SSalil 69384844054SSalil /* Cfg pg schd */ 69484844054SSalil if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) 69584844054SSalil return 0; 69684844054SSalil 69784844054SSalil /* Pg to pri */ 69884844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 69984844054SSalil /* Calc shaper para */ 70084844054SSalil ret = hclge_shaper_para_calc( 70184844054SSalil hdev->tm_info.pg_info[i].bw_limit, 70284844054SSalil HCLGE_SHAPER_LVL_PG, 70384844054SSalil &ir_b, &ir_u, &ir_s); 70484844054SSalil if (ret) 70584844054SSalil return ret; 70684844054SSalil 70763cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 70863cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 70963cbf7a9SYufeng Mo HCLGE_SHAPER_BS_S_DEF); 71084844054SSalil ret = hclge_tm_pg_shapping_cfg(hdev, 71184844054SSalil HCLGE_TM_SHAP_C_BUCKET, i, 71263cbf7a9SYufeng Mo shaper_para); 71384844054SSalil if (ret) 71484844054SSalil return ret; 71584844054SSalil 71663cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 71784844054SSalil HCLGE_SHAPER_BS_U_DEF, 71884844054SSalil HCLGE_SHAPER_BS_S_DEF); 71963cbf7a9SYufeng Mo ret = hclge_tm_pg_shapping_cfg(hdev, 72063cbf7a9SYufeng Mo HCLGE_TM_SHAP_P_BUCKET, i, 72163cbf7a9SYufeng Mo shaper_para); 72284844054SSalil if (ret) 72384844054SSalil return ret; 72484844054SSalil } 72584844054SSalil 72684844054SSalil return 0; 72784844054SSalil } 72884844054SSalil 72984844054SSalil static int hclge_tm_pg_dwrr_cfg(struct hclge_dev *hdev) 73084844054SSalil { 73184844054SSalil int ret; 73284844054SSalil u32 i; 73384844054SSalil 73484844054SSalil /* cfg pg schd */ 73584844054SSalil if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) 73684844054SSalil return 0; 73784844054SSalil 73884844054SSalil /* pg to prio */ 73984844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 74084844054SSalil /* Cfg dwrr */ 7419b2f3477SWeihang Li ret = hclge_tm_pg_weight_cfg(hdev, i, hdev->tm_info.pg_dwrr[i]); 74284844054SSalil if (ret) 74384844054SSalil return ret; 74484844054SSalil } 74584844054SSalil 74684844054SSalil return 0; 74784844054SSalil } 74884844054SSalil 74984844054SSalil static int hclge_vport_q_to_qs_map(struct hclge_dev *hdev, 75084844054SSalil struct hclge_vport *vport) 75184844054SSalil { 75284844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 75384844054SSalil struct hnae3_queue **tqp = kinfo->tqp; 75484844054SSalil struct hnae3_tc_info *v_tc_info; 75584844054SSalil u32 i, j; 75684844054SSalil int ret; 75784844054SSalil 75884844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 75984844054SSalil v_tc_info = &kinfo->tc_info[i]; 76084844054SSalil for (j = 0; j < v_tc_info->tqp_count; j++) { 76184844054SSalil struct hnae3_queue *q = tqp[v_tc_info->tqp_offset + j]; 76284844054SSalil 76384844054SSalil ret = hclge_tm_q_to_qs_map_cfg(hdev, 76484844054SSalil hclge_get_queue_id(q), 76584844054SSalil vport->qs_offset + i); 76684844054SSalil if (ret) 76784844054SSalil return ret; 76884844054SSalil } 76984844054SSalil } 77084844054SSalil 77184844054SSalil return 0; 77284844054SSalil } 77384844054SSalil 77484844054SSalil static int hclge_tm_pri_q_qs_cfg(struct hclge_dev *hdev) 77584844054SSalil { 77684844054SSalil struct hclge_vport *vport = hdev->vport; 77784844054SSalil int ret; 778cc9bb43aSYunsheng Lin u32 i, k; 77984844054SSalil 78084844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 78184844054SSalil /* Cfg qs -> pri mapping, one by one mapping */ 782de67a690SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 783de67a690SYunsheng Lin struct hnae3_knic_private_info *kinfo = 784de67a690SYunsheng Lin &vport[k].nic.kinfo; 785de67a690SYunsheng Lin 786de67a690SYunsheng Lin for (i = 0; i < kinfo->num_tc; i++) { 787cc9bb43aSYunsheng Lin ret = hclge_tm_qs_to_pri_map_cfg( 788cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, i); 78984844054SSalil if (ret) 79084844054SSalil return ret; 79184844054SSalil } 792de67a690SYunsheng Lin } 79384844054SSalil } else if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) { 79484844054SSalil /* Cfg qs -> pri mapping, qs = tc, pri = vf, 8 qs -> 1 pri */ 79584844054SSalil for (k = 0; k < hdev->num_alloc_vport; k++) 79684844054SSalil for (i = 0; i < HNAE3_MAX_TC; i++) { 79784844054SSalil ret = hclge_tm_qs_to_pri_map_cfg( 79884844054SSalil hdev, vport[k].qs_offset + i, k); 79984844054SSalil if (ret) 80084844054SSalil return ret; 80184844054SSalil } 80284844054SSalil } else { 80384844054SSalil return -EINVAL; 80484844054SSalil } 80584844054SSalil 80684844054SSalil /* Cfg q -> qs mapping */ 80784844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 80884844054SSalil ret = hclge_vport_q_to_qs_map(hdev, vport); 80984844054SSalil if (ret) 81084844054SSalil return ret; 81184844054SSalil 81284844054SSalil vport++; 81384844054SSalil } 81484844054SSalil 81584844054SSalil return 0; 81684844054SSalil } 81784844054SSalil 81884844054SSalil static int hclge_tm_pri_tc_base_shaper_cfg(struct hclge_dev *hdev) 81984844054SSalil { 82084844054SSalil u8 ir_u, ir_b, ir_s; 82163cbf7a9SYufeng Mo u32 shaper_para; 82284844054SSalil int ret; 82384844054SSalil u32 i; 82484844054SSalil 82584844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 82684844054SSalil ret = hclge_shaper_para_calc( 82784844054SSalil hdev->tm_info.tc_info[i].bw_limit, 82884844054SSalil HCLGE_SHAPER_LVL_PRI, 82984844054SSalil &ir_b, &ir_u, &ir_s); 83084844054SSalil if (ret) 83184844054SSalil return ret; 83284844054SSalil 83363cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 83463cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 83584844054SSalil HCLGE_SHAPER_BS_S_DEF); 83663cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, i, 83763cbf7a9SYufeng Mo shaper_para); 83884844054SSalil if (ret) 83984844054SSalil return ret; 84084844054SSalil 84163cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 84263cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 84384844054SSalil HCLGE_SHAPER_BS_S_DEF); 84463cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, i, 84563cbf7a9SYufeng Mo shaper_para); 84684844054SSalil if (ret) 84784844054SSalil return ret; 84884844054SSalil } 84984844054SSalil 85084844054SSalil return 0; 85184844054SSalil } 85284844054SSalil 85384844054SSalil static int hclge_tm_pri_vnet_base_shaper_pri_cfg(struct hclge_vport *vport) 85484844054SSalil { 85584844054SSalil struct hclge_dev *hdev = vport->back; 85684844054SSalil u8 ir_u, ir_b, ir_s; 85763cbf7a9SYufeng Mo u32 shaper_para; 85884844054SSalil int ret; 85984844054SSalil 86084844054SSalil ret = hclge_shaper_para_calc(vport->bw_limit, HCLGE_SHAPER_LVL_VF, 86184844054SSalil &ir_b, &ir_u, &ir_s); 86284844054SSalil if (ret) 86384844054SSalil return ret; 86484844054SSalil 86563cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 86663cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 86784844054SSalil HCLGE_SHAPER_BS_S_DEF); 86863cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, 86963cbf7a9SYufeng Mo vport->vport_id, shaper_para); 87084844054SSalil if (ret) 87184844054SSalil return ret; 87284844054SSalil 87363cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(ir_b, ir_u, ir_s, 87484844054SSalil HCLGE_SHAPER_BS_U_DEF, 87584844054SSalil HCLGE_SHAPER_BS_S_DEF); 87663cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, 87763cbf7a9SYufeng Mo vport->vport_id, shaper_para); 87884844054SSalil if (ret) 87984844054SSalil return ret; 88084844054SSalil 88184844054SSalil return 0; 88284844054SSalil } 88384844054SSalil 88484844054SSalil static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport) 88584844054SSalil { 88684844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 88784844054SSalil struct hclge_dev *hdev = vport->back; 88884844054SSalil u8 ir_u, ir_b, ir_s; 88984844054SSalil u32 i; 89084844054SSalil int ret; 89184844054SSalil 89284844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 89384844054SSalil ret = hclge_shaper_para_calc( 89484844054SSalil hdev->tm_info.tc_info[i].bw_limit, 89584844054SSalil HCLGE_SHAPER_LVL_QSET, 89684844054SSalil &ir_b, &ir_u, &ir_s); 89784844054SSalil if (ret) 89884844054SSalil return ret; 89984844054SSalil } 90084844054SSalil 90184844054SSalil return 0; 90284844054SSalil } 90384844054SSalil 90484844054SSalil static int hclge_tm_pri_vnet_base_shaper_cfg(struct hclge_dev *hdev) 90584844054SSalil { 90684844054SSalil struct hclge_vport *vport = hdev->vport; 90784844054SSalil int ret; 90884844054SSalil u32 i; 90984844054SSalil 91084844054SSalil /* Need config vport shaper */ 91184844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 91284844054SSalil ret = hclge_tm_pri_vnet_base_shaper_pri_cfg(vport); 91384844054SSalil if (ret) 91484844054SSalil return ret; 91584844054SSalil 91684844054SSalil ret = hclge_tm_pri_vnet_base_shaper_qs_cfg(vport); 91784844054SSalil if (ret) 91884844054SSalil return ret; 91984844054SSalil 92084844054SSalil vport++; 92184844054SSalil } 92284844054SSalil 92384844054SSalil return 0; 92484844054SSalil } 92584844054SSalil 92684844054SSalil static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev) 92784844054SSalil { 92884844054SSalil int ret; 92984844054SSalil 93084844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 93184844054SSalil ret = hclge_tm_pri_tc_base_shaper_cfg(hdev); 93284844054SSalil if (ret) 93384844054SSalil return ret; 93484844054SSalil } else { 93584844054SSalil ret = hclge_tm_pri_vnet_base_shaper_cfg(hdev); 93684844054SSalil if (ret) 93784844054SSalil return ret; 93884844054SSalil } 93984844054SSalil 94084844054SSalil return 0; 94184844054SSalil } 94284844054SSalil 94384844054SSalil static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) 94484844054SSalil { 945cc9bb43aSYunsheng Lin struct hclge_vport *vport = hdev->vport; 94684844054SSalil struct hclge_pg_info *pg_info; 94784844054SSalil u8 dwrr; 94884844054SSalil int ret; 949cc9bb43aSYunsheng Lin u32 i, k; 95084844054SSalil 95184844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 95284844054SSalil pg_info = 95384844054SSalil &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; 95484844054SSalil dwrr = pg_info->tc_dwrr[i]; 95584844054SSalil 95684844054SSalil ret = hclge_tm_pri_weight_cfg(hdev, i, dwrr); 95784844054SSalil if (ret) 95884844054SSalil return ret; 95984844054SSalil 960cc9bb43aSYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 961cc9bb43aSYunsheng Lin ret = hclge_tm_qs_weight_cfg( 962cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, 963cc9bb43aSYunsheng Lin vport[k].dwrr); 96484844054SSalil if (ret) 96584844054SSalil return ret; 96684844054SSalil } 967cc9bb43aSYunsheng Lin } 96884844054SSalil 96984844054SSalil return 0; 97084844054SSalil } 97184844054SSalil 972330baff5SYunsheng Lin static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) 973330baff5SYunsheng Lin { 974330baff5SYunsheng Lin #define DEFAULT_TC_WEIGHT 1 975330baff5SYunsheng Lin #define DEFAULT_TC_OFFSET 14 976330baff5SYunsheng Lin 977330baff5SYunsheng Lin struct hclge_ets_tc_weight_cmd *ets_weight; 978330baff5SYunsheng Lin struct hclge_desc desc; 979330baff5SYunsheng Lin int i; 980330baff5SYunsheng Lin 981330baff5SYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, false); 982330baff5SYunsheng Lin ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data; 983330baff5SYunsheng Lin 984330baff5SYunsheng Lin for (i = 0; i < HNAE3_MAX_TC; i++) { 985330baff5SYunsheng Lin struct hclge_pg_info *pg_info; 986330baff5SYunsheng Lin 987330baff5SYunsheng Lin ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT; 988330baff5SYunsheng Lin 989330baff5SYunsheng Lin if (!(hdev->hw_tc_map & BIT(i))) 990330baff5SYunsheng Lin continue; 991330baff5SYunsheng Lin 992330baff5SYunsheng Lin pg_info = 993330baff5SYunsheng Lin &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; 994330baff5SYunsheng Lin ets_weight->tc_weight[i] = pg_info->tc_dwrr[i]; 995330baff5SYunsheng Lin } 996330baff5SYunsheng Lin 997330baff5SYunsheng Lin ets_weight->weight_offset = DEFAULT_TC_OFFSET; 998330baff5SYunsheng Lin 999330baff5SYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 1000330baff5SYunsheng Lin } 1001330baff5SYunsheng Lin 100284844054SSalil static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport) 100384844054SSalil { 100484844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 100584844054SSalil struct hclge_dev *hdev = vport->back; 100684844054SSalil int ret; 100784844054SSalil u8 i; 100884844054SSalil 100984844054SSalil /* Vf dwrr */ 101084844054SSalil ret = hclge_tm_pri_weight_cfg(hdev, vport->vport_id, vport->dwrr); 101184844054SSalil if (ret) 101284844054SSalil return ret; 101384844054SSalil 101484844054SSalil /* Qset dwrr */ 101584844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 101684844054SSalil ret = hclge_tm_qs_weight_cfg( 101784844054SSalil hdev, vport->qs_offset + i, 101884844054SSalil hdev->tm_info.pg_info[0].tc_dwrr[i]); 101984844054SSalil if (ret) 102084844054SSalil return ret; 102184844054SSalil } 102284844054SSalil 102384844054SSalil return 0; 102484844054SSalil } 102584844054SSalil 102684844054SSalil static int hclge_tm_pri_vnet_base_dwrr_cfg(struct hclge_dev *hdev) 102784844054SSalil { 102884844054SSalil struct hclge_vport *vport = hdev->vport; 102984844054SSalil int ret; 103084844054SSalil u32 i; 103184844054SSalil 103284844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 103384844054SSalil ret = hclge_tm_pri_vnet_base_dwrr_pri_cfg(vport); 103484844054SSalil if (ret) 103584844054SSalil return ret; 103684844054SSalil 103784844054SSalil vport++; 103884844054SSalil } 103984844054SSalil 104084844054SSalil return 0; 104184844054SSalil } 104284844054SSalil 104384844054SSalil static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev) 104484844054SSalil { 104584844054SSalil int ret; 104684844054SSalil 104784844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 104884844054SSalil ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev); 104984844054SSalil if (ret) 105084844054SSalil return ret; 1051330baff5SYunsheng Lin 1052330baff5SYunsheng Lin if (!hnae3_dev_dcb_supported(hdev)) 1053330baff5SYunsheng Lin return 0; 1054330baff5SYunsheng Lin 1055330baff5SYunsheng Lin ret = hclge_tm_ets_tc_dwrr_cfg(hdev); 1056330baff5SYunsheng Lin if (ret == -EOPNOTSUPP) { 1057330baff5SYunsheng Lin dev_warn(&hdev->pdev->dev, 1058330baff5SYunsheng Lin "fw %08x does't support ets tc weight cmd\n", 1059330baff5SYunsheng Lin hdev->fw_version); 1060330baff5SYunsheng Lin ret = 0; 1061330baff5SYunsheng Lin } 1062330baff5SYunsheng Lin 1063330baff5SYunsheng Lin return ret; 106484844054SSalil } else { 106584844054SSalil ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev); 106684844054SSalil if (ret) 106784844054SSalil return ret; 106884844054SSalil } 106984844054SSalil 107084844054SSalil return 0; 107184844054SSalil } 107284844054SSalil 10739e5157baSYunsheng Lin static int hclge_tm_map_cfg(struct hclge_dev *hdev) 107484844054SSalil { 107584844054SSalil int ret; 107684844054SSalil 107777f255c1SYunsheng Lin ret = hclge_up_to_tc_map(hdev); 107877f255c1SYunsheng Lin if (ret) 107977f255c1SYunsheng Lin return ret; 108077f255c1SYunsheng Lin 108184844054SSalil ret = hclge_tm_pg_to_pri_map(hdev); 108284844054SSalil if (ret) 108384844054SSalil return ret; 108484844054SSalil 108584844054SSalil return hclge_tm_pri_q_qs_cfg(hdev); 108684844054SSalil } 108784844054SSalil 108884844054SSalil static int hclge_tm_shaper_cfg(struct hclge_dev *hdev) 108984844054SSalil { 109084844054SSalil int ret; 109184844054SSalil 10920a5677d3SYunsheng Lin ret = hclge_tm_port_shaper_cfg(hdev); 10930a5677d3SYunsheng Lin if (ret) 10940a5677d3SYunsheng Lin return ret; 10950a5677d3SYunsheng Lin 109684844054SSalil ret = hclge_tm_pg_shaper_cfg(hdev); 109784844054SSalil if (ret) 109884844054SSalil return ret; 109984844054SSalil 110084844054SSalil return hclge_tm_pri_shaper_cfg(hdev); 110184844054SSalil } 110284844054SSalil 110384844054SSalil int hclge_tm_dwrr_cfg(struct hclge_dev *hdev) 110484844054SSalil { 110584844054SSalil int ret; 110684844054SSalil 110784844054SSalil ret = hclge_tm_pg_dwrr_cfg(hdev); 110884844054SSalil if (ret) 110984844054SSalil return ret; 111084844054SSalil 111184844054SSalil return hclge_tm_pri_dwrr_cfg(hdev); 111284844054SSalil } 111384844054SSalil 111484844054SSalil static int hclge_tm_lvl2_schd_mode_cfg(struct hclge_dev *hdev) 111584844054SSalil { 111684844054SSalil int ret; 111784844054SSalil u8 i; 111884844054SSalil 111984844054SSalil /* Only being config on TC-Based scheduler mode */ 112084844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) 112184844054SSalil return 0; 112284844054SSalil 112384844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 112484844054SSalil ret = hclge_tm_pg_schd_mode_cfg(hdev, i); 112584844054SSalil if (ret) 112684844054SSalil return ret; 112784844054SSalil } 112884844054SSalil 112984844054SSalil return 0; 113084844054SSalil } 113184844054SSalil 113284844054SSalil static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport) 113384844054SSalil { 113484844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 113584844054SSalil struct hclge_dev *hdev = vport->back; 113684844054SSalil int ret; 113784844054SSalil u8 i; 113884844054SSalil 113984844054SSalil ret = hclge_tm_pri_schd_mode_cfg(hdev, vport->vport_id); 114084844054SSalil if (ret) 114184844054SSalil return ret; 114284844054SSalil 114384844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 1144cc9bb43aSYunsheng Lin u8 sch_mode = hdev->tm_info.tc_info[i].tc_sch_mode; 1145cc9bb43aSYunsheng Lin 1146cc9bb43aSYunsheng Lin ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i, 1147cc9bb43aSYunsheng Lin sch_mode); 114884844054SSalil if (ret) 114984844054SSalil return ret; 115084844054SSalil } 115184844054SSalil 115284844054SSalil return 0; 115384844054SSalil } 115484844054SSalil 115584844054SSalil static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) 115684844054SSalil { 115784844054SSalil struct hclge_vport *vport = hdev->vport; 115884844054SSalil int ret; 1159cc9bb43aSYunsheng Lin u8 i, k; 116084844054SSalil 116184844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 116284844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 116384844054SSalil ret = hclge_tm_pri_schd_mode_cfg(hdev, i); 116484844054SSalil if (ret) 116584844054SSalil return ret; 116684844054SSalil 1167cc9bb43aSYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1168cc9bb43aSYunsheng Lin ret = hclge_tm_qs_schd_mode_cfg( 1169cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, 1170cc9bb43aSYunsheng Lin HCLGE_SCH_MODE_DWRR); 117184844054SSalil if (ret) 117284844054SSalil return ret; 117384844054SSalil } 1174cc9bb43aSYunsheng Lin } 117584844054SSalil } else { 117684844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 117784844054SSalil ret = hclge_tm_schd_mode_vnet_base_cfg(vport); 117884844054SSalil if (ret) 117984844054SSalil return ret; 118084844054SSalil 118184844054SSalil vport++; 118284844054SSalil } 118384844054SSalil } 118484844054SSalil 118584844054SSalil return 0; 118684844054SSalil } 118784844054SSalil 11889e5157baSYunsheng Lin static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) 118984844054SSalil { 119084844054SSalil int ret; 119184844054SSalil 119284844054SSalil ret = hclge_tm_lvl2_schd_mode_cfg(hdev); 119384844054SSalil if (ret) 119484844054SSalil return ret; 119584844054SSalil 119684844054SSalil return hclge_tm_lvl34_schd_mode_cfg(hdev); 119784844054SSalil } 119884844054SSalil 11999e5157baSYunsheng Lin int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) 120084844054SSalil { 120184844054SSalil int ret; 120284844054SSalil 120384844054SSalil /* Cfg tm mapping */ 120484844054SSalil ret = hclge_tm_map_cfg(hdev); 120584844054SSalil if (ret) 120684844054SSalil return ret; 120784844054SSalil 120884844054SSalil /* Cfg tm shaper */ 120984844054SSalil ret = hclge_tm_shaper_cfg(hdev); 121084844054SSalil if (ret) 121184844054SSalil return ret; 121284844054SSalil 121384844054SSalil /* Cfg dwrr */ 121484844054SSalil ret = hclge_tm_dwrr_cfg(hdev); 121584844054SSalil if (ret) 121684844054SSalil return ret; 121784844054SSalil 121884844054SSalil /* Cfg schd mode for each level schd */ 121984844054SSalil return hclge_tm_schd_mode_hw(hdev); 122084844054SSalil } 122184844054SSalil 1222e98d7183SFuyun Liang static int hclge_pause_param_setup_hw(struct hclge_dev *hdev) 122318838d0cSFuyun Liang { 122418838d0cSFuyun Liang struct hclge_mac *mac = &hdev->hw.mac; 122518838d0cSFuyun Liang 1226e98d7183SFuyun Liang return hclge_pause_param_cfg(hdev, mac->mac_addr, 122718838d0cSFuyun Liang HCLGE_DEFAULT_PAUSE_TRANS_GAP, 122818838d0cSFuyun Liang HCLGE_DEFAULT_PAUSE_TRANS_TIME); 122918838d0cSFuyun Liang } 123018838d0cSFuyun Liang 12319dc2145dSYunsheng Lin static int hclge_pfc_setup_hw(struct hclge_dev *hdev) 12329dc2145dSYunsheng Lin { 12339dc2145dSYunsheng Lin u8 enable_bitmap = 0; 12349dc2145dSYunsheng Lin 12359dc2145dSYunsheng Lin if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) 12369dc2145dSYunsheng Lin enable_bitmap = HCLGE_TX_MAC_PAUSE_EN_MSK | 12379dc2145dSYunsheng Lin HCLGE_RX_MAC_PAUSE_EN_MSK; 12389dc2145dSYunsheng Lin 12399dc2145dSYunsheng Lin return hclge_pfc_pause_en_cfg(hdev, enable_bitmap, 1240d3ad430aSYunsheng Lin hdev->tm_info.pfc_en); 12419dc2145dSYunsheng Lin } 12429dc2145dSYunsheng Lin 124367bf2541SYunsheng Lin /* Each Tc has a 1024 queue sets to backpress, it divides to 124467bf2541SYunsheng Lin * 32 group, each group contains 32 queue sets, which can be 124567bf2541SYunsheng Lin * represented by u32 bitmap. 124667bf2541SYunsheng Lin */ 124767bf2541SYunsheng Lin static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc) 124867bf2541SYunsheng Lin { 1249e8ccbb7dSYunsheng Lin int i; 125067bf2541SYunsheng Lin 125167bf2541SYunsheng Lin for (i = 0; i < HCLGE_BP_GRP_NUM; i++) { 1252e8ccbb7dSYunsheng Lin u32 qs_bitmap = 0; 1253e8ccbb7dSYunsheng Lin int k, ret; 125467bf2541SYunsheng Lin 125567bf2541SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1256e8ccbb7dSYunsheng Lin struct hclge_vport *vport = &hdev->vport[k]; 125767bf2541SYunsheng Lin u16 qs_id = vport->qs_offset + tc; 125867bf2541SYunsheng Lin u8 grp, sub_grp; 125967bf2541SYunsheng Lin 1260e4e87715SPeng Li grp = hnae3_get_field(qs_id, HCLGE_BP_GRP_ID_M, 126167bf2541SYunsheng Lin HCLGE_BP_GRP_ID_S); 1262e4e87715SPeng Li sub_grp = hnae3_get_field(qs_id, HCLGE_BP_SUB_GRP_ID_M, 126367bf2541SYunsheng Lin HCLGE_BP_SUB_GRP_ID_S); 126467bf2541SYunsheng Lin if (i == grp) 126567bf2541SYunsheng Lin qs_bitmap |= (1 << sub_grp); 126667bf2541SYunsheng Lin } 126767bf2541SYunsheng Lin 126867bf2541SYunsheng Lin ret = hclge_tm_qs_bp_cfg(hdev, tc, i, qs_bitmap); 126967bf2541SYunsheng Lin if (ret) 127067bf2541SYunsheng Lin return ret; 127167bf2541SYunsheng Lin } 127267bf2541SYunsheng Lin 127367bf2541SYunsheng Lin return 0; 127467bf2541SYunsheng Lin } 127567bf2541SYunsheng Lin 12769dc2145dSYunsheng Lin static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) 12779dc2145dSYunsheng Lin { 12789dc2145dSYunsheng Lin bool tx_en, rx_en; 12799dc2145dSYunsheng Lin 12809dc2145dSYunsheng Lin switch (hdev->tm_info.fc_mode) { 12819dc2145dSYunsheng Lin case HCLGE_FC_NONE: 12829dc2145dSYunsheng Lin tx_en = false; 12839dc2145dSYunsheng Lin rx_en = false; 12849dc2145dSYunsheng Lin break; 12859dc2145dSYunsheng Lin case HCLGE_FC_RX_PAUSE: 12869dc2145dSYunsheng Lin tx_en = false; 12879dc2145dSYunsheng Lin rx_en = true; 12889dc2145dSYunsheng Lin break; 12899dc2145dSYunsheng Lin case HCLGE_FC_TX_PAUSE: 12909dc2145dSYunsheng Lin tx_en = true; 12919dc2145dSYunsheng Lin rx_en = false; 12929dc2145dSYunsheng Lin break; 12939dc2145dSYunsheng Lin case HCLGE_FC_FULL: 12949dc2145dSYunsheng Lin tx_en = true; 12959dc2145dSYunsheng Lin rx_en = true; 12969dc2145dSYunsheng Lin break; 12976d0ec65cSYunsheng Lin case HCLGE_FC_PFC: 12986d0ec65cSYunsheng Lin tx_en = false; 12996d0ec65cSYunsheng Lin rx_en = false; 13006d0ec65cSYunsheng Lin break; 13019dc2145dSYunsheng Lin default: 13029dc2145dSYunsheng Lin tx_en = true; 13039dc2145dSYunsheng Lin rx_en = true; 13049dc2145dSYunsheng Lin } 13059dc2145dSYunsheng Lin 13069dc2145dSYunsheng Lin return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en); 13079dc2145dSYunsheng Lin } 13089dc2145dSYunsheng Lin 130973fc9c48SHuazhong Tan static int hclge_tm_bp_setup(struct hclge_dev *hdev) 131073fc9c48SHuazhong Tan { 131173fc9c48SHuazhong Tan int ret = 0; 131273fc9c48SHuazhong Tan int i; 131373fc9c48SHuazhong Tan 131473fc9c48SHuazhong Tan for (i = 0; i < hdev->tm_info.num_tc; i++) { 131573fc9c48SHuazhong Tan ret = hclge_bp_setup_hw(hdev, i); 131673fc9c48SHuazhong Tan if (ret) 131773fc9c48SHuazhong Tan return ret; 131873fc9c48SHuazhong Tan } 131973fc9c48SHuazhong Tan 132073fc9c48SHuazhong Tan return ret; 132173fc9c48SHuazhong Tan } 132273fc9c48SHuazhong Tan 132344e59e37SYunsheng Lin int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init) 132484844054SSalil { 132584844054SSalil int ret; 132684844054SSalil 1327e98d7183SFuyun Liang ret = hclge_pause_param_setup_hw(hdev); 132818838d0cSFuyun Liang if (ret) 132918838d0cSFuyun Liang return ret; 133018838d0cSFuyun Liang 13316d0ec65cSYunsheng Lin ret = hclge_mac_pause_setup_hw(hdev); 13326d0ec65cSYunsheng Lin if (ret) 13336d0ec65cSYunsheng Lin return ret; 133484844054SSalil 13359dc2145dSYunsheng Lin /* Only DCB-supported dev supports qset back pressure and pfc cmd */ 13362daf4a65SYunsheng Lin if (!hnae3_dev_dcb_supported(hdev)) 13372daf4a65SYunsheng Lin return 0; 13382daf4a65SYunsheng Lin 133944e59e37SYunsheng Lin /* GE MAC does not support PFC, when driver is initializing and MAC 134044e59e37SYunsheng Lin * is in GE Mode, ignore the error here, otherwise initialization 134144e59e37SYunsheng Lin * will fail. 134244e59e37SYunsheng Lin */ 13439dc2145dSYunsheng Lin ret = hclge_pfc_setup_hw(hdev); 134444e59e37SYunsheng Lin if (init && ret == -EOPNOTSUPP) 134544e59e37SYunsheng Lin dev_warn(&hdev->pdev->dev, "GE MAC does not support pfc\n"); 1346fba2efdaSHuazhong Tan else if (ret) { 1347fba2efdaSHuazhong Tan dev_err(&hdev->pdev->dev, "config pfc failed! ret = %d\n", 1348fba2efdaSHuazhong Tan ret); 134944e59e37SYunsheng Lin return ret; 1350fba2efdaSHuazhong Tan } 13519dc2145dSYunsheng Lin 135273fc9c48SHuazhong Tan return hclge_tm_bp_setup(hdev); 135377f255c1SYunsheng Lin } 135477f255c1SYunsheng Lin 1355e432abfbSYunsheng Lin void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc) 135677f255c1SYunsheng Lin { 135777f255c1SYunsheng Lin struct hclge_vport *vport = hdev->vport; 135877f255c1SYunsheng Lin struct hnae3_knic_private_info *kinfo; 135977f255c1SYunsheng Lin u32 i, k; 136077f255c1SYunsheng Lin 136177f255c1SYunsheng Lin for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { 136277f255c1SYunsheng Lin hdev->tm_info.prio_tc[i] = prio_tc[i]; 136377f255c1SYunsheng Lin 136477f255c1SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 136577f255c1SYunsheng Lin kinfo = &vport[k].nic.kinfo; 136677f255c1SYunsheng Lin kinfo->prio_tc[i] = prio_tc[i]; 136777f255c1SYunsheng Lin } 136877f255c1SYunsheng Lin } 136977f255c1SYunsheng Lin } 137077f255c1SYunsheng Lin 1371e432abfbSYunsheng Lin void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc) 137277f255c1SYunsheng Lin { 13739b2f3477SWeihang Li u8 bit_map = 0; 13749b2f3477SWeihang Li u8 i; 137577f255c1SYunsheng Lin 137677f255c1SYunsheng Lin hdev->tm_info.num_tc = num_tc; 137777f255c1SYunsheng Lin 137877f255c1SYunsheng Lin for (i = 0; i < hdev->tm_info.num_tc; i++) 137977f255c1SYunsheng Lin bit_map |= BIT(i); 138077f255c1SYunsheng Lin 138177f255c1SYunsheng Lin if (!bit_map) { 138277f255c1SYunsheng Lin bit_map = 1; 138377f255c1SYunsheng Lin hdev->tm_info.num_tc = 1; 138477f255c1SYunsheng Lin } 138577f255c1SYunsheng Lin 138677f255c1SYunsheng Lin hdev->hw_tc_map = bit_map; 138777f255c1SYunsheng Lin 138877f255c1SYunsheng Lin hclge_tm_schd_info_init(hdev); 138984844054SSalil } 139084844054SSalil 139144e59e37SYunsheng Lin int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) 139284844054SSalil { 139384844054SSalil int ret; 139484844054SSalil 139584844054SSalil if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && 139684844054SSalil (hdev->tx_sch_mode != HCLGE_FLAG_VNET_BASE_SCH_MODE)) 139784844054SSalil return -ENOTSUPP; 139884844054SSalil 139984844054SSalil ret = hclge_tm_schd_setup_hw(hdev); 140084844054SSalil if (ret) 140184844054SSalil return ret; 140284844054SSalil 140344e59e37SYunsheng Lin ret = hclge_pause_setup_hw(hdev, init); 140484844054SSalil if (ret) 140584844054SSalil return ret; 140684844054SSalil 140784844054SSalil return 0; 140884844054SSalil } 140984844054SSalil 141084844054SSalil int hclge_tm_schd_init(struct hclge_dev *hdev) 141184844054SSalil { 14127979a223SYunsheng Lin int ret; 141384844054SSalil 14147979a223SYunsheng Lin /* fc_mode is HCLGE_FC_FULL on reset */ 14157979a223SYunsheng Lin hdev->tm_info.fc_mode = HCLGE_FC_FULL; 14167979a223SYunsheng Lin hdev->fc_mode_last_time = hdev->tm_info.fc_mode; 14177979a223SYunsheng Lin 14187979a223SYunsheng Lin ret = hclge_tm_schd_info_init(hdev); 141984844054SSalil if (ret) 142084844054SSalil return ret; 142184844054SSalil 142244e59e37SYunsheng Lin return hclge_tm_init_hw(hdev, true); 142384844054SSalil } 1424672ad0edSHuazhong Tan 1425672ad0edSHuazhong Tan int hclge_tm_vport_map_update(struct hclge_dev *hdev) 1426672ad0edSHuazhong Tan { 1427672ad0edSHuazhong Tan struct hclge_vport *vport = hdev->vport; 1428672ad0edSHuazhong Tan int ret; 1429672ad0edSHuazhong Tan 1430672ad0edSHuazhong Tan hclge_tm_vport_tc_info_update(vport); 1431672ad0edSHuazhong Tan 1432672ad0edSHuazhong Tan ret = hclge_vport_q_to_qs_map(hdev, vport); 1433672ad0edSHuazhong Tan if (ret) 1434672ad0edSHuazhong Tan return ret; 1435672ad0edSHuazhong Tan 1436672ad0edSHuazhong Tan if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) 1437672ad0edSHuazhong Tan return 0; 1438672ad0edSHuazhong Tan 1439672ad0edSHuazhong Tan return hclge_tm_bp_setup(hdev); 1440672ad0edSHuazhong Tan } 1441