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