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 29ff7e4d0dSHuazhong Tan * @ir_para: parameters of IR shaper 30d9c7d20dSGuangbin Huang * @max_tm_rate: max tm rate is available to config 3184844054SSalil * 3284844054SSalil * the formula: 3384844054SSalil * 3484844054SSalil * IR_b * (2 ^ IR_u) * 8 3584844054SSalil * IR(Mbps) = ------------------------- * CLOCK(1000Mbps) 3684844054SSalil * Tick * (2 ^ IR_s) 3784844054SSalil * 3884844054SSalil * @return: 0: calculate sucessful, negative: fail 3984844054SSalil */ 4084844054SSalil static int hclge_shaper_para_calc(u32 ir, u8 shaper_level, 41ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para *ir_para, 42d9c7d20dSGuangbin Huang u32 max_tm_rate) 4384844054SSalil { 44b37ce587SYufeng Mo #define DIVISOR_CLK (1000 * 8) 45b37ce587SYufeng Mo #define DIVISOR_IR_B_126 (126 * DIVISOR_CLK) 46b37ce587SYufeng Mo 473ea7af9eSColin Ian King static const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = { 4884844054SSalil 6 * 256, /* Prioriy level */ 4984844054SSalil 6 * 32, /* Prioriy group level */ 5084844054SSalil 6 * 8, /* Port level */ 5184844054SSalil 6 * 256 /* Qset level */ 5284844054SSalil }; 539b2f3477SWeihang Li u8 ir_u_calc = 0; 549b2f3477SWeihang Li u8 ir_s_calc = 0; 5584844054SSalil u32 ir_calc; 5684844054SSalil u32 tick; 5784844054SSalil 5884844054SSalil /* Calc tick */ 5904f25edbSYunsheng Lin if (shaper_level >= HCLGE_SHAPER_LVL_CNT || 60d9c7d20dSGuangbin Huang ir > max_tm_rate) 6184844054SSalil return -EINVAL; 6284844054SSalil 6384844054SSalil tick = tick_array[shaper_level]; 6484844054SSalil 6584844054SSalil /** 6684844054SSalil * Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0 6784844054SSalil * the formula is changed to: 6884844054SSalil * 126 * 1 * 8 6984844054SSalil * ir_calc = ---------------- * 1000 7084844054SSalil * tick * 1 7184844054SSalil */ 72b37ce587SYufeng Mo ir_calc = (DIVISOR_IR_B_126 + (tick >> 1) - 1) / tick; 7384844054SSalil 7484844054SSalil if (ir_calc == ir) { 75ff7e4d0dSHuazhong Tan ir_para->ir_b = 126; 76ff7e4d0dSHuazhong Tan ir_para->ir_u = 0; 77ff7e4d0dSHuazhong Tan ir_para->ir_s = 0; 7884844054SSalil 7984844054SSalil return 0; 8084844054SSalil } else if (ir_calc > ir) { 8184844054SSalil /* Increasing the denominator to select ir_s value */ 821a92497dSYonglong Liu while (ir_calc >= ir && ir) { 8384844054SSalil ir_s_calc++; 84b37ce587SYufeng Mo ir_calc = DIVISOR_IR_B_126 / (tick * (1 << ir_s_calc)); 8584844054SSalil } 8684844054SSalil 87ff7e4d0dSHuazhong Tan ir_para->ir_b = (ir * tick * (1 << ir_s_calc) + 88ff7e4d0dSHuazhong Tan (DIVISOR_CLK >> 1)) / DIVISOR_CLK; 8984844054SSalil } else { 9084844054SSalil /* Increasing the numerator to select ir_u value */ 9184844054SSalil u32 numerator; 9284844054SSalil 9384844054SSalil while (ir_calc < ir) { 9484844054SSalil ir_u_calc++; 95b37ce587SYufeng Mo numerator = DIVISOR_IR_B_126 * (1 << ir_u_calc); 9684844054SSalil ir_calc = (numerator + (tick >> 1)) / tick; 9784844054SSalil } 9884844054SSalil 9984844054SSalil if (ir_calc == ir) { 100ff7e4d0dSHuazhong Tan ir_para->ir_b = 126; 10184844054SSalil } else { 1021a92497dSYonglong Liu u32 denominator = DIVISOR_CLK * (1 << --ir_u_calc); 103ff7e4d0dSHuazhong Tan ir_para->ir_b = (ir * tick + (denominator >> 1)) / 104ff7e4d0dSHuazhong Tan denominator; 10584844054SSalil } 10684844054SSalil } 10784844054SSalil 108ff7e4d0dSHuazhong Tan ir_para->ir_u = ir_u_calc; 109ff7e4d0dSHuazhong Tan ir_para->ir_s = ir_s_calc; 11084844054SSalil 11184844054SSalil return 0; 11284844054SSalil } 11384844054SSalil 11464fd2300SPeng Li static int hclge_pfc_stats_get(struct hclge_dev *hdev, 11564fd2300SPeng Li enum hclge_opcode_type opcode, u64 *stats) 11664fd2300SPeng Li { 11764fd2300SPeng Li struct hclge_desc desc[HCLGE_TM_PFC_PKT_GET_CMD_NUM]; 11864fd2300SPeng Li int ret, i, j; 11964fd2300SPeng Li 12064fd2300SPeng Li if (!(opcode == HCLGE_OPC_QUERY_PFC_RX_PKT_CNT || 12164fd2300SPeng Li opcode == HCLGE_OPC_QUERY_PFC_TX_PKT_CNT)) 12264fd2300SPeng Li return -EINVAL; 12364fd2300SPeng Li 12463cbf7a9SYufeng Mo for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM - 1; i++) { 12564fd2300SPeng Li hclge_cmd_setup_basic_desc(&desc[i], opcode, true); 12664fd2300SPeng Li desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT); 12764fd2300SPeng Li } 12864fd2300SPeng Li 12963cbf7a9SYufeng Mo hclge_cmd_setup_basic_desc(&desc[i], opcode, true); 13063cbf7a9SYufeng Mo 13164fd2300SPeng Li ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_TM_PFC_PKT_GET_CMD_NUM); 13220670328SYunsheng Lin if (ret) 13364fd2300SPeng Li return ret; 13464fd2300SPeng Li 13564fd2300SPeng Li for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM; i++) { 13664fd2300SPeng Li struct hclge_pfc_stats_cmd *pfc_stats = 13764fd2300SPeng Li (struct hclge_pfc_stats_cmd *)desc[i].data; 13864fd2300SPeng Li 13964fd2300SPeng Li for (j = 0; j < HCLGE_TM_PFC_NUM_GET_PER_CMD; j++) { 14064fd2300SPeng Li u32 index = i * HCLGE_TM_PFC_PKT_GET_CMD_NUM + j; 14164fd2300SPeng Li 14264fd2300SPeng Li if (index < HCLGE_MAX_TC_NUM) 14364fd2300SPeng Li stats[index] = 14464fd2300SPeng Li le64_to_cpu(pfc_stats->pkt_num[j]); 14564fd2300SPeng Li } 14664fd2300SPeng Li } 14764fd2300SPeng Li return 0; 14864fd2300SPeng Li } 14964fd2300SPeng Li 15064fd2300SPeng Li int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats) 15164fd2300SPeng Li { 15264fd2300SPeng Li return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_RX_PKT_CNT, stats); 15364fd2300SPeng Li } 15464fd2300SPeng Li 15564fd2300SPeng Li int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats) 15664fd2300SPeng Li { 15764fd2300SPeng Li return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_TX_PKT_CNT, stats); 15864fd2300SPeng Li } 15964fd2300SPeng Li 16061387774SPeng Li int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx) 16184844054SSalil { 16284844054SSalil struct hclge_desc desc; 16384844054SSalil 16484844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PAUSE_EN, false); 16584844054SSalil 16684844054SSalil desc.data[0] = cpu_to_le32((tx ? HCLGE_TX_MAC_PAUSE_EN_MSK : 0) | 16784844054SSalil (rx ? HCLGE_RX_MAC_PAUSE_EN_MSK : 0)); 16884844054SSalil 16984844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 17084844054SSalil } 17184844054SSalil 1729dc2145dSYunsheng Lin static int hclge_pfc_pause_en_cfg(struct hclge_dev *hdev, u8 tx_rx_bitmap, 1739dc2145dSYunsheng Lin u8 pfc_bitmap) 1749dc2145dSYunsheng Lin { 1759dc2145dSYunsheng Lin struct hclge_desc desc; 176d0d72bacSJian Shen struct hclge_pfc_en_cmd *pfc = (struct hclge_pfc_en_cmd *)desc.data; 1779dc2145dSYunsheng Lin 1789dc2145dSYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_PFC_PAUSE_EN, false); 1799dc2145dSYunsheng Lin 1809dc2145dSYunsheng Lin pfc->tx_rx_en_bitmap = tx_rx_bitmap; 1819dc2145dSYunsheng Lin pfc->pri_en_bitmap = pfc_bitmap; 1829dc2145dSYunsheng Lin 1839dc2145dSYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 1849dc2145dSYunsheng Lin } 1859dc2145dSYunsheng Lin 186e98d7183SFuyun Liang static int hclge_pause_param_cfg(struct hclge_dev *hdev, const u8 *addr, 18718838d0cSFuyun Liang u8 pause_trans_gap, u16 pause_trans_time) 18818838d0cSFuyun Liang { 18918838d0cSFuyun Liang struct hclge_cfg_pause_param_cmd *pause_param; 19018838d0cSFuyun Liang struct hclge_desc desc; 19118838d0cSFuyun Liang 192d0d72bacSJian Shen pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data; 19318838d0cSFuyun Liang 19418838d0cSFuyun Liang hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, false); 19518838d0cSFuyun Liang 19618838d0cSFuyun Liang ether_addr_copy(pause_param->mac_addr, addr); 197cd2086bfSFuyun Liang ether_addr_copy(pause_param->mac_addr_extra, addr); 19818838d0cSFuyun Liang pause_param->pause_trans_gap = pause_trans_gap; 19918838d0cSFuyun Liang pause_param->pause_trans_time = cpu_to_le16(pause_trans_time); 20018838d0cSFuyun Liang 20118838d0cSFuyun Liang return hclge_cmd_send(&hdev->hw, &desc, 1); 20218838d0cSFuyun Liang } 20318838d0cSFuyun Liang 204e98d7183SFuyun Liang int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr) 20518838d0cSFuyun Liang { 20618838d0cSFuyun Liang struct hclge_cfg_pause_param_cmd *pause_param; 20718838d0cSFuyun Liang struct hclge_desc desc; 20818838d0cSFuyun Liang u16 trans_time; 20918838d0cSFuyun Liang u8 trans_gap; 21018838d0cSFuyun Liang int ret; 21118838d0cSFuyun Liang 212d0d72bacSJian Shen pause_param = (struct hclge_cfg_pause_param_cmd *)desc.data; 21318838d0cSFuyun Liang 21418838d0cSFuyun Liang hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_MAC_PARA, true); 21518838d0cSFuyun Liang 21618838d0cSFuyun Liang ret = hclge_cmd_send(&hdev->hw, &desc, 1); 21718838d0cSFuyun Liang if (ret) 21818838d0cSFuyun Liang return ret; 21918838d0cSFuyun Liang 22018838d0cSFuyun Liang trans_gap = pause_param->pause_trans_gap; 22118838d0cSFuyun Liang trans_time = le16_to_cpu(pause_param->pause_trans_time); 22218838d0cSFuyun Liang 2239b2f3477SWeihang Li return hclge_pause_param_cfg(hdev, mac_addr, trans_gap, trans_time); 22418838d0cSFuyun Liang } 22518838d0cSFuyun Liang 22684844054SSalil static int hclge_fill_pri_array(struct hclge_dev *hdev, u8 *pri, u8 pri_id) 22784844054SSalil { 22884844054SSalil u8 tc; 22984844054SSalil 230c5795c53SYunsheng Lin tc = hdev->tm_info.prio_tc[pri_id]; 23184844054SSalil 23284844054SSalil if (tc >= hdev->tm_info.num_tc) 23384844054SSalil return -EINVAL; 23484844054SSalil 23584844054SSalil /** 23684844054SSalil * the register for priority has four bytes, the first bytes includes 23784844054SSalil * priority0 and priority1, the higher 4bit stands for priority1 23884844054SSalil * while the lower 4bit stands for priority0, as below: 23984844054SSalil * first byte: | pri_1 | pri_0 | 24084844054SSalil * second byte: | pri_3 | pri_2 | 24184844054SSalil * third byte: | pri_5 | pri_4 | 24284844054SSalil * fourth byte: | pri_7 | pri_6 | 24384844054SSalil */ 24484844054SSalil pri[pri_id >> 1] |= tc << ((pri_id & 1) * 4); 24584844054SSalil 24684844054SSalil return 0; 24784844054SSalil } 24884844054SSalil 24984844054SSalil static int hclge_up_to_tc_map(struct hclge_dev *hdev) 25084844054SSalil { 25184844054SSalil struct hclge_desc desc; 25284844054SSalil u8 *pri = (u8 *)desc.data; 25384844054SSalil u8 pri_id; 25484844054SSalil int ret; 25584844054SSalil 25684844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PRI_TO_TC_MAPPING, false); 25784844054SSalil 258c5795c53SYunsheng Lin for (pri_id = 0; pri_id < HNAE3_MAX_USER_PRIO; pri_id++) { 25984844054SSalil ret = hclge_fill_pri_array(hdev, pri, pri_id); 26084844054SSalil if (ret) 26184844054SSalil return ret; 26284844054SSalil } 26384844054SSalil 26484844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 26584844054SSalil } 26684844054SSalil 26784844054SSalil static int hclge_tm_pg_to_pri_map_cfg(struct hclge_dev *hdev, 26884844054SSalil u8 pg_id, u8 pri_bit_map) 26984844054SSalil { 27084844054SSalil struct hclge_pg_to_pri_link_cmd *map; 27184844054SSalil struct hclge_desc desc; 27284844054SSalil 27384844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_TO_PRI_LINK, false); 27484844054SSalil 27584844054SSalil map = (struct hclge_pg_to_pri_link_cmd *)desc.data; 27684844054SSalil 27784844054SSalil map->pg_id = pg_id; 27884844054SSalil map->pri_bit_map = pri_bit_map; 27984844054SSalil 28084844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 28184844054SSalil } 28284844054SSalil 28384844054SSalil static int hclge_tm_qs_to_pri_map_cfg(struct hclge_dev *hdev, 28484844054SSalil u16 qs_id, u8 pri) 28584844054SSalil { 28684844054SSalil struct hclge_qs_to_pri_link_cmd *map; 28784844054SSalil struct hclge_desc desc; 28884844054SSalil 28984844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_TO_PRI_LINK, false); 29084844054SSalil 29184844054SSalil map = (struct hclge_qs_to_pri_link_cmd *)desc.data; 29284844054SSalil 29384844054SSalil map->qs_id = cpu_to_le16(qs_id); 29484844054SSalil map->priority = pri; 29584844054SSalil map->link_vld = HCLGE_TM_QS_PRI_LINK_VLD_MSK; 29684844054SSalil 29784844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 29884844054SSalil } 29984844054SSalil 30084844054SSalil static int hclge_tm_q_to_qs_map_cfg(struct hclge_dev *hdev, 30132c7fbc8SJian Shen u16 q_id, u16 qs_id) 30284844054SSalil { 30384844054SSalil struct hclge_nq_to_qs_link_cmd *map; 30484844054SSalil struct hclge_desc desc; 30584844054SSalil 30684844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_NQ_TO_QS_LINK, false); 30784844054SSalil 30884844054SSalil map = (struct hclge_nq_to_qs_link_cmd *)desc.data; 30984844054SSalil 31084844054SSalil map->nq_id = cpu_to_le16(q_id); 31184844054SSalil map->qset_id = cpu_to_le16(qs_id | HCLGE_TM_Q_QS_LINK_VLD_MSK); 31284844054SSalil 31384844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 31484844054SSalil } 31584844054SSalil 31684844054SSalil static int hclge_tm_pg_weight_cfg(struct hclge_dev *hdev, u8 pg_id, 31784844054SSalil u8 dwrr) 31884844054SSalil { 31984844054SSalil struct hclge_pg_weight_cmd *weight; 32084844054SSalil struct hclge_desc desc; 32184844054SSalil 32284844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_WEIGHT, false); 32384844054SSalil 32484844054SSalil weight = (struct hclge_pg_weight_cmd *)desc.data; 32584844054SSalil 32684844054SSalil weight->pg_id = pg_id; 32784844054SSalil weight->dwrr = dwrr; 32884844054SSalil 32984844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 33084844054SSalil } 33184844054SSalil 33284844054SSalil static int hclge_tm_pri_weight_cfg(struct hclge_dev *hdev, u8 pri_id, 33384844054SSalil u8 dwrr) 33484844054SSalil { 33584844054SSalil struct hclge_priority_weight_cmd *weight; 33684844054SSalil struct hclge_desc desc; 33784844054SSalil 33884844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_WEIGHT, false); 33984844054SSalil 34084844054SSalil weight = (struct hclge_priority_weight_cmd *)desc.data; 34184844054SSalil 34284844054SSalil weight->pri_id = pri_id; 34384844054SSalil weight->dwrr = dwrr; 34484844054SSalil 34584844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 34684844054SSalil } 34784844054SSalil 34884844054SSalil static int hclge_tm_qs_weight_cfg(struct hclge_dev *hdev, u16 qs_id, 34984844054SSalil u8 dwrr) 35084844054SSalil { 35184844054SSalil struct hclge_qs_weight_cmd *weight; 35284844054SSalil struct hclge_desc desc; 35384844054SSalil 35484844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_WEIGHT, false); 35584844054SSalil 35684844054SSalil weight = (struct hclge_qs_weight_cmd *)desc.data; 35784844054SSalil 35884844054SSalil weight->qs_id = cpu_to_le16(qs_id); 35984844054SSalil weight->dwrr = dwrr; 36084844054SSalil 36184844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 36284844054SSalil } 36384844054SSalil 36463cbf7a9SYufeng Mo static u32 hclge_tm_get_shapping_para(u8 ir_b, u8 ir_u, u8 ir_s, 36563cbf7a9SYufeng Mo u8 bs_b, u8 bs_s) 36663cbf7a9SYufeng Mo { 36763cbf7a9SYufeng Mo u32 shapping_para = 0; 36863cbf7a9SYufeng Mo 36963cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, IR_B, ir_b); 37063cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, IR_U, ir_u); 37163cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, IR_S, ir_s); 37263cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, BS_B, bs_b); 37363cbf7a9SYufeng Mo hclge_tm_set_field(shapping_para, BS_S, bs_s); 37463cbf7a9SYufeng Mo 37563cbf7a9SYufeng Mo return shapping_para; 37663cbf7a9SYufeng Mo } 37763cbf7a9SYufeng Mo 37884844054SSalil static int hclge_tm_pg_shapping_cfg(struct hclge_dev *hdev, 37984844054SSalil enum hclge_shap_bucket bucket, u8 pg_id, 38063cbf7a9SYufeng Mo u32 shapping_para) 38184844054SSalil { 38284844054SSalil struct hclge_pg_shapping_cmd *shap_cfg_cmd; 38384844054SSalil enum hclge_opcode_type opcode; 38484844054SSalil struct hclge_desc desc; 38584844054SSalil 38684844054SSalil opcode = bucket ? HCLGE_OPC_TM_PG_P_SHAPPING : 38784844054SSalil HCLGE_OPC_TM_PG_C_SHAPPING; 38884844054SSalil hclge_cmd_setup_basic_desc(&desc, opcode, false); 38984844054SSalil 39084844054SSalil shap_cfg_cmd = (struct hclge_pg_shapping_cmd *)desc.data; 39184844054SSalil 39284844054SSalil shap_cfg_cmd->pg_id = pg_id; 39384844054SSalil 394a90bb9a5SYunsheng Lin shap_cfg_cmd->pg_shapping_para = cpu_to_le32(shapping_para); 39584844054SSalil 39684844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 39784844054SSalil } 39884844054SSalil 3990a5677d3SYunsheng Lin static int hclge_tm_port_shaper_cfg(struct hclge_dev *hdev) 4000a5677d3SYunsheng Lin { 4010a5677d3SYunsheng Lin struct hclge_port_shapping_cmd *shap_cfg_cmd; 402ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para ir_para; 4030a5677d3SYunsheng Lin struct hclge_desc desc; 404cdd332acSGuojia Liao u32 shapping_para; 4050a5677d3SYunsheng Lin int ret; 4060a5677d3SYunsheng Lin 407ff7e4d0dSHuazhong Tan ret = hclge_shaper_para_calc(hdev->hw.mac.speed, HCLGE_SHAPER_LVL_PORT, 408ff7e4d0dSHuazhong Tan &ir_para, 409d9c7d20dSGuangbin Huang hdev->ae_dev->dev_specs.max_tm_rate); 4100a5677d3SYunsheng Lin if (ret) 4110a5677d3SYunsheng Lin return ret; 4120a5677d3SYunsheng Lin 4130a5677d3SYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PORT_SHAPPING, false); 4140a5677d3SYunsheng Lin shap_cfg_cmd = (struct hclge_port_shapping_cmd *)desc.data; 4150a5677d3SYunsheng Lin 416ff7e4d0dSHuazhong Tan shapping_para = hclge_tm_get_shapping_para(ir_para.ir_b, ir_para.ir_u, 417ff7e4d0dSHuazhong Tan ir_para.ir_s, 41863cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 41963cbf7a9SYufeng Mo HCLGE_SHAPER_BS_S_DEF); 4200a5677d3SYunsheng Lin 4210a5677d3SYunsheng Lin shap_cfg_cmd->port_shapping_para = cpu_to_le32(shapping_para); 4220a5677d3SYunsheng Lin 4230a5677d3SYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 4240a5677d3SYunsheng Lin } 4250a5677d3SYunsheng Lin 42684844054SSalil static int hclge_tm_pri_shapping_cfg(struct hclge_dev *hdev, 42784844054SSalil enum hclge_shap_bucket bucket, u8 pri_id, 42863cbf7a9SYufeng Mo u32 shapping_para) 42984844054SSalil { 43084844054SSalil struct hclge_pri_shapping_cmd *shap_cfg_cmd; 43184844054SSalil enum hclge_opcode_type opcode; 43284844054SSalil struct hclge_desc desc; 43384844054SSalil 43484844054SSalil opcode = bucket ? HCLGE_OPC_TM_PRI_P_SHAPPING : 43584844054SSalil HCLGE_OPC_TM_PRI_C_SHAPPING; 43684844054SSalil 43784844054SSalil hclge_cmd_setup_basic_desc(&desc, opcode, false); 43884844054SSalil 43984844054SSalil shap_cfg_cmd = (struct hclge_pri_shapping_cmd *)desc.data; 44084844054SSalil 44184844054SSalil shap_cfg_cmd->pri_id = pri_id; 44284844054SSalil 443a90bb9a5SYunsheng Lin shap_cfg_cmd->pri_shapping_para = cpu_to_le32(shapping_para); 44484844054SSalil 44584844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 44684844054SSalil } 44784844054SSalil 44884844054SSalil static int hclge_tm_pg_schd_mode_cfg(struct hclge_dev *hdev, u8 pg_id) 44984844054SSalil { 45084844054SSalil struct hclge_desc desc; 45184844054SSalil 45284844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PG_SCH_MODE_CFG, false); 45384844054SSalil 45484844054SSalil if (hdev->tm_info.pg_info[pg_id].pg_sch_mode == HCLGE_SCH_MODE_DWRR) 45584844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 45684844054SSalil else 45784844054SSalil desc.data[1] = 0; 45884844054SSalil 45984844054SSalil desc.data[0] = cpu_to_le32(pg_id); 46084844054SSalil 46184844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 46284844054SSalil } 46384844054SSalil 46484844054SSalil static int hclge_tm_pri_schd_mode_cfg(struct hclge_dev *hdev, u8 pri_id) 46584844054SSalil { 46684844054SSalil struct hclge_desc desc; 46784844054SSalil 46884844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_PRI_SCH_MODE_CFG, false); 46984844054SSalil 47084844054SSalil if (hdev->tm_info.tc_info[pri_id].tc_sch_mode == HCLGE_SCH_MODE_DWRR) 47184844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 47284844054SSalil else 47384844054SSalil desc.data[1] = 0; 47484844054SSalil 47584844054SSalil desc.data[0] = cpu_to_le32(pri_id); 47684844054SSalil 47784844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 47884844054SSalil } 47984844054SSalil 480cc9bb43aSYunsheng Lin static int hclge_tm_qs_schd_mode_cfg(struct hclge_dev *hdev, u16 qs_id, u8 mode) 48184844054SSalil { 48284844054SSalil struct hclge_desc desc; 48384844054SSalil 48484844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_QS_SCH_MODE_CFG, false); 48584844054SSalil 486cc9bb43aSYunsheng Lin if (mode == HCLGE_SCH_MODE_DWRR) 48784844054SSalil desc.data[1] = cpu_to_le32(HCLGE_TM_TX_SCHD_DWRR_MSK); 48884844054SSalil else 48984844054SSalil desc.data[1] = 0; 49084844054SSalil 49184844054SSalil desc.data[0] = cpu_to_le32(qs_id); 49284844054SSalil 49384844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 49484844054SSalil } 49584844054SSalil 49667bf2541SYunsheng Lin static int hclge_tm_qs_bp_cfg(struct hclge_dev *hdev, u8 tc, u8 grp_id, 49767bf2541SYunsheng Lin u32 bit_map) 49884844054SSalil { 49984844054SSalil struct hclge_bp_to_qs_map_cmd *bp_to_qs_map_cmd; 50084844054SSalil struct hclge_desc desc; 50184844054SSalil 50284844054SSalil hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_BP_TO_QSET_MAPPING, 50384844054SSalil false); 50484844054SSalil 50584844054SSalil bp_to_qs_map_cmd = (struct hclge_bp_to_qs_map_cmd *)desc.data; 50684844054SSalil 50784844054SSalil bp_to_qs_map_cmd->tc_id = tc; 50867bf2541SYunsheng Lin bp_to_qs_map_cmd->qs_group_id = grp_id; 50967bf2541SYunsheng Lin bp_to_qs_map_cmd->qs_bit_map = cpu_to_le32(bit_map); 51084844054SSalil 51184844054SSalil return hclge_cmd_send(&hdev->hw, &desc, 1); 51284844054SSalil } 51384844054SSalil 514ee9e4424SYonglong Liu int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate) 515ee9e4424SYonglong Liu { 516ee9e4424SYonglong Liu struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 517ee9e4424SYonglong Liu struct hclge_qs_shapping_cmd *shap_cfg_cmd; 518ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para ir_para; 519ee9e4424SYonglong Liu struct hclge_dev *hdev = vport->back; 520ee9e4424SYonglong Liu struct hclge_desc desc; 521ee9e4424SYonglong Liu u32 shaper_para; 522ee9e4424SYonglong Liu int ret, i; 523ee9e4424SYonglong Liu 524ee9e4424SYonglong Liu if (!max_tx_rate) 525d9c7d20dSGuangbin Huang max_tx_rate = hdev->ae_dev->dev_specs.max_tm_rate; 526ee9e4424SYonglong Liu 527ee9e4424SYonglong Liu ret = hclge_shaper_para_calc(max_tx_rate, HCLGE_SHAPER_LVL_QSET, 528ff7e4d0dSHuazhong Tan &ir_para, 529d9c7d20dSGuangbin Huang hdev->ae_dev->dev_specs.max_tm_rate); 530ee9e4424SYonglong Liu if (ret) 531ee9e4424SYonglong Liu return ret; 532ee9e4424SYonglong Liu 533ff7e4d0dSHuazhong Tan shaper_para = hclge_tm_get_shapping_para(ir_para.ir_b, ir_para.ir_u, 534ff7e4d0dSHuazhong Tan ir_para.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; 736ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para ir_para; 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 */ 748ff7e4d0dSHuazhong Tan ret = hclge_shaper_para_calc(hdev->tm_info.pg_info[i].bw_limit, 74984844054SSalil HCLGE_SHAPER_LVL_PG, 750ff7e4d0dSHuazhong Tan &ir_para, max_tm_rate); 75184844054SSalil if (ret) 75284844054SSalil return ret; 75384844054SSalil 75463cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 75563cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 75663cbf7a9SYufeng Mo HCLGE_SHAPER_BS_S_DEF); 75784844054SSalil ret = hclge_tm_pg_shapping_cfg(hdev, 75884844054SSalil HCLGE_TM_SHAP_C_BUCKET, i, 75963cbf7a9SYufeng Mo shaper_para); 76084844054SSalil if (ret) 76184844054SSalil return ret; 76284844054SSalil 763ff7e4d0dSHuazhong Tan shaper_para = hclge_tm_get_shapping_para(ir_para.ir_b, 764ff7e4d0dSHuazhong Tan ir_para.ir_u, 765ff7e4d0dSHuazhong Tan ir_para.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; 870ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para ir_para; 87163cbf7a9SYufeng Mo u32 shaper_para; 87284844054SSalil int ret; 87384844054SSalil u32 i; 87484844054SSalil 87584844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 876ff7e4d0dSHuazhong Tan ret = hclge_shaper_para_calc(hdev->tm_info.tc_info[i].bw_limit, 87784844054SSalil HCLGE_SHAPER_LVL_PRI, 878ff7e4d0dSHuazhong Tan &ir_para, max_tm_rate); 87984844054SSalil if (ret) 88084844054SSalil return ret; 88184844054SSalil 88263cbf7a9SYufeng Mo shaper_para = hclge_tm_get_shapping_para(0, 0, 0, 88363cbf7a9SYufeng Mo HCLGE_SHAPER_BS_U_DEF, 88484844054SSalil HCLGE_SHAPER_BS_S_DEF); 88563cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_C_BUCKET, i, 88663cbf7a9SYufeng Mo shaper_para); 88784844054SSalil if (ret) 88884844054SSalil return ret; 88984844054SSalil 890ff7e4d0dSHuazhong Tan shaper_para = hclge_tm_get_shapping_para(ir_para.ir_b, 891ff7e4d0dSHuazhong Tan ir_para.ir_u, 892ff7e4d0dSHuazhong Tan ir_para.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; 907ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para ir_para; 90863cbf7a9SYufeng Mo u32 shaper_para; 90984844054SSalil int ret; 91084844054SSalil 91184844054SSalil ret = hclge_shaper_para_calc(vport->bw_limit, HCLGE_SHAPER_LVL_VF, 912ff7e4d0dSHuazhong Tan &ir_para, 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 925ff7e4d0dSHuazhong Tan shaper_para = hclge_tm_get_shapping_para(ir_para.ir_b, ir_para.ir_u, 926ff7e4d0dSHuazhong Tan ir_para.ir_s, 92784844054SSalil HCLGE_SHAPER_BS_U_DEF, 92884844054SSalil HCLGE_SHAPER_BS_S_DEF); 92963cbf7a9SYufeng Mo ret = hclge_tm_pri_shapping_cfg(hdev, HCLGE_TM_SHAP_P_BUCKET, 93063cbf7a9SYufeng Mo vport->vport_id, shaper_para); 93184844054SSalil if (ret) 93284844054SSalil return ret; 93384844054SSalil 93484844054SSalil return 0; 93584844054SSalil } 93684844054SSalil 93784844054SSalil static int hclge_tm_pri_vnet_base_shaper_qs_cfg(struct hclge_vport *vport) 93884844054SSalil { 93984844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 94084844054SSalil struct hclge_dev *hdev = vport->back; 941d9c7d20dSGuangbin Huang u32 max_tm_rate = hdev->ae_dev->dev_specs.max_tm_rate; 942ff7e4d0dSHuazhong Tan struct hclge_shaper_ir_para ir_para; 94384844054SSalil u32 i; 94484844054SSalil int ret; 94584844054SSalil 94684844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 947ff7e4d0dSHuazhong Tan ret = hclge_shaper_para_calc(hdev->tm_info.tc_info[i].bw_limit, 94884844054SSalil HCLGE_SHAPER_LVL_QSET, 949ff7e4d0dSHuazhong Tan &ir_para, max_tm_rate); 95084844054SSalil if (ret) 95184844054SSalil return ret; 95284844054SSalil } 95384844054SSalil 95484844054SSalil return 0; 95584844054SSalil } 95684844054SSalil 95784844054SSalil static int hclge_tm_pri_vnet_base_shaper_cfg(struct hclge_dev *hdev) 95884844054SSalil { 95984844054SSalil struct hclge_vport *vport = hdev->vport; 96084844054SSalil int ret; 96184844054SSalil u32 i; 96284844054SSalil 96384844054SSalil /* Need config vport shaper */ 96484844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 96584844054SSalil ret = hclge_tm_pri_vnet_base_shaper_pri_cfg(vport); 96684844054SSalil if (ret) 96784844054SSalil return ret; 96884844054SSalil 96984844054SSalil ret = hclge_tm_pri_vnet_base_shaper_qs_cfg(vport); 97084844054SSalil if (ret) 97184844054SSalil return ret; 97284844054SSalil 97384844054SSalil vport++; 97484844054SSalil } 97584844054SSalil 97684844054SSalil return 0; 97784844054SSalil } 97884844054SSalil 97984844054SSalil static int hclge_tm_pri_shaper_cfg(struct hclge_dev *hdev) 98084844054SSalil { 98184844054SSalil int ret; 98284844054SSalil 98384844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 98484844054SSalil ret = hclge_tm_pri_tc_base_shaper_cfg(hdev); 98584844054SSalil if (ret) 98684844054SSalil return ret; 98784844054SSalil } else { 98884844054SSalil ret = hclge_tm_pri_vnet_base_shaper_cfg(hdev); 98984844054SSalil if (ret) 99084844054SSalil return ret; 99184844054SSalil } 99284844054SSalil 99384844054SSalil return 0; 99484844054SSalil } 99584844054SSalil 99684844054SSalil static int hclge_tm_pri_tc_base_dwrr_cfg(struct hclge_dev *hdev) 99784844054SSalil { 998cc9bb43aSYunsheng Lin struct hclge_vport *vport = hdev->vport; 99984844054SSalil struct hclge_pg_info *pg_info; 100084844054SSalil u8 dwrr; 100184844054SSalil int ret; 1002cc9bb43aSYunsheng Lin u32 i, k; 100384844054SSalil 100484844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 100584844054SSalil pg_info = 100684844054SSalil &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; 100784844054SSalil dwrr = pg_info->tc_dwrr[i]; 100884844054SSalil 100984844054SSalil ret = hclge_tm_pri_weight_cfg(hdev, i, dwrr); 101084844054SSalil if (ret) 101184844054SSalil return ret; 101284844054SSalil 1013cc9bb43aSYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1014cc9bb43aSYunsheng Lin ret = hclge_tm_qs_weight_cfg( 1015cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, 1016cc9bb43aSYunsheng Lin vport[k].dwrr); 101784844054SSalil if (ret) 101884844054SSalil return ret; 101984844054SSalil } 1020cc9bb43aSYunsheng Lin } 102184844054SSalil 102284844054SSalil return 0; 102384844054SSalil } 102484844054SSalil 1025330baff5SYunsheng Lin static int hclge_tm_ets_tc_dwrr_cfg(struct hclge_dev *hdev) 1026330baff5SYunsheng Lin { 1027330baff5SYunsheng Lin #define DEFAULT_TC_WEIGHT 1 1028330baff5SYunsheng Lin #define DEFAULT_TC_OFFSET 14 1029330baff5SYunsheng Lin 1030330baff5SYunsheng Lin struct hclge_ets_tc_weight_cmd *ets_weight; 1031330baff5SYunsheng Lin struct hclge_desc desc; 1032ebaf1908SWeihang Li unsigned int i; 1033330baff5SYunsheng Lin 1034330baff5SYunsheng Lin hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_ETS_TC_WEIGHT, false); 1035330baff5SYunsheng Lin ets_weight = (struct hclge_ets_tc_weight_cmd *)desc.data; 1036330baff5SYunsheng Lin 1037330baff5SYunsheng Lin for (i = 0; i < HNAE3_MAX_TC; i++) { 1038330baff5SYunsheng Lin struct hclge_pg_info *pg_info; 1039330baff5SYunsheng Lin 1040330baff5SYunsheng Lin ets_weight->tc_weight[i] = DEFAULT_TC_WEIGHT; 1041330baff5SYunsheng Lin 1042330baff5SYunsheng Lin if (!(hdev->hw_tc_map & BIT(i))) 1043330baff5SYunsheng Lin continue; 1044330baff5SYunsheng Lin 1045330baff5SYunsheng Lin pg_info = 1046330baff5SYunsheng Lin &hdev->tm_info.pg_info[hdev->tm_info.tc_info[i].pgid]; 1047330baff5SYunsheng Lin ets_weight->tc_weight[i] = pg_info->tc_dwrr[i]; 1048330baff5SYunsheng Lin } 1049330baff5SYunsheng Lin 1050330baff5SYunsheng Lin ets_weight->weight_offset = DEFAULT_TC_OFFSET; 1051330baff5SYunsheng Lin 1052330baff5SYunsheng Lin return hclge_cmd_send(&hdev->hw, &desc, 1); 1053330baff5SYunsheng Lin } 1054330baff5SYunsheng Lin 105584844054SSalil static int hclge_tm_pri_vnet_base_dwrr_pri_cfg(struct hclge_vport *vport) 105684844054SSalil { 105784844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 105884844054SSalil struct hclge_dev *hdev = vport->back; 105984844054SSalil int ret; 106084844054SSalil u8 i; 106184844054SSalil 106284844054SSalil /* Vf dwrr */ 106384844054SSalil ret = hclge_tm_pri_weight_cfg(hdev, vport->vport_id, vport->dwrr); 106484844054SSalil if (ret) 106584844054SSalil return ret; 106684844054SSalil 106784844054SSalil /* Qset dwrr */ 106884844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 106984844054SSalil ret = hclge_tm_qs_weight_cfg( 107084844054SSalil hdev, vport->qs_offset + i, 107184844054SSalil hdev->tm_info.pg_info[0].tc_dwrr[i]); 107284844054SSalil if (ret) 107384844054SSalil return ret; 107484844054SSalil } 107584844054SSalil 107684844054SSalil return 0; 107784844054SSalil } 107884844054SSalil 107984844054SSalil static int hclge_tm_pri_vnet_base_dwrr_cfg(struct hclge_dev *hdev) 108084844054SSalil { 108184844054SSalil struct hclge_vport *vport = hdev->vport; 108284844054SSalil int ret; 108384844054SSalil u32 i; 108484844054SSalil 108584844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 108684844054SSalil ret = hclge_tm_pri_vnet_base_dwrr_pri_cfg(vport); 108784844054SSalil if (ret) 108884844054SSalil return ret; 108984844054SSalil 109084844054SSalil vport++; 109184844054SSalil } 109284844054SSalil 109384844054SSalil return 0; 109484844054SSalil } 109584844054SSalil 109684844054SSalil static int hclge_tm_pri_dwrr_cfg(struct hclge_dev *hdev) 109784844054SSalil { 109884844054SSalil int ret; 109984844054SSalil 110084844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 110184844054SSalil ret = hclge_tm_pri_tc_base_dwrr_cfg(hdev); 110284844054SSalil if (ret) 110384844054SSalil return ret; 1104330baff5SYunsheng Lin 1105330baff5SYunsheng Lin if (!hnae3_dev_dcb_supported(hdev)) 1106330baff5SYunsheng Lin return 0; 1107330baff5SYunsheng Lin 1108330baff5SYunsheng Lin ret = hclge_tm_ets_tc_dwrr_cfg(hdev); 1109330baff5SYunsheng Lin if (ret == -EOPNOTSUPP) { 1110330baff5SYunsheng Lin dev_warn(&hdev->pdev->dev, 1111330baff5SYunsheng Lin "fw %08x does't support ets tc weight cmd\n", 1112330baff5SYunsheng Lin hdev->fw_version); 1113330baff5SYunsheng Lin ret = 0; 1114330baff5SYunsheng Lin } 1115330baff5SYunsheng Lin 1116330baff5SYunsheng Lin return ret; 111784844054SSalil } else { 111884844054SSalil ret = hclge_tm_pri_vnet_base_dwrr_cfg(hdev); 111984844054SSalil if (ret) 112084844054SSalil return ret; 112184844054SSalil } 112284844054SSalil 112384844054SSalil return 0; 112484844054SSalil } 112584844054SSalil 11269e5157baSYunsheng Lin static int hclge_tm_map_cfg(struct hclge_dev *hdev) 112784844054SSalil { 112884844054SSalil int ret; 112984844054SSalil 113077f255c1SYunsheng Lin ret = hclge_up_to_tc_map(hdev); 113177f255c1SYunsheng Lin if (ret) 113277f255c1SYunsheng Lin return ret; 113377f255c1SYunsheng Lin 113484844054SSalil ret = hclge_tm_pg_to_pri_map(hdev); 113584844054SSalil if (ret) 113684844054SSalil return ret; 113784844054SSalil 113884844054SSalil return hclge_tm_pri_q_qs_cfg(hdev); 113984844054SSalil } 114084844054SSalil 114184844054SSalil static int hclge_tm_shaper_cfg(struct hclge_dev *hdev) 114284844054SSalil { 114384844054SSalil int ret; 114484844054SSalil 11450a5677d3SYunsheng Lin ret = hclge_tm_port_shaper_cfg(hdev); 11460a5677d3SYunsheng Lin if (ret) 11470a5677d3SYunsheng Lin return ret; 11480a5677d3SYunsheng Lin 114984844054SSalil ret = hclge_tm_pg_shaper_cfg(hdev); 115084844054SSalil if (ret) 115184844054SSalil return ret; 115284844054SSalil 115384844054SSalil return hclge_tm_pri_shaper_cfg(hdev); 115484844054SSalil } 115584844054SSalil 115684844054SSalil int hclge_tm_dwrr_cfg(struct hclge_dev *hdev) 115784844054SSalil { 115884844054SSalil int ret; 115984844054SSalil 116084844054SSalil ret = hclge_tm_pg_dwrr_cfg(hdev); 116184844054SSalil if (ret) 116284844054SSalil return ret; 116384844054SSalil 116484844054SSalil return hclge_tm_pri_dwrr_cfg(hdev); 116584844054SSalil } 116684844054SSalil 116784844054SSalil static int hclge_tm_lvl2_schd_mode_cfg(struct hclge_dev *hdev) 116884844054SSalil { 116984844054SSalil int ret; 117084844054SSalil u8 i; 117184844054SSalil 117284844054SSalil /* Only being config on TC-Based scheduler mode */ 117384844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_VNET_BASE_SCH_MODE) 117484844054SSalil return 0; 117584844054SSalil 117684844054SSalil for (i = 0; i < hdev->tm_info.num_pg; i++) { 117784844054SSalil ret = hclge_tm_pg_schd_mode_cfg(hdev, i); 117884844054SSalil if (ret) 117984844054SSalil return ret; 118084844054SSalil } 118184844054SSalil 118284844054SSalil return 0; 118384844054SSalil } 118484844054SSalil 118584844054SSalil static int hclge_tm_schd_mode_vnet_base_cfg(struct hclge_vport *vport) 118684844054SSalil { 118784844054SSalil struct hnae3_knic_private_info *kinfo = &vport->nic.kinfo; 118884844054SSalil struct hclge_dev *hdev = vport->back; 118984844054SSalil int ret; 119084844054SSalil u8 i; 119184844054SSalil 119204f25edbSYunsheng Lin if (vport->vport_id >= HNAE3_MAX_TC) 119304f25edbSYunsheng Lin return -EINVAL; 119404f25edbSYunsheng Lin 119584844054SSalil ret = hclge_tm_pri_schd_mode_cfg(hdev, vport->vport_id); 119684844054SSalil if (ret) 119784844054SSalil return ret; 119884844054SSalil 119984844054SSalil for (i = 0; i < kinfo->num_tc; i++) { 1200cc9bb43aSYunsheng Lin u8 sch_mode = hdev->tm_info.tc_info[i].tc_sch_mode; 1201cc9bb43aSYunsheng Lin 1202cc9bb43aSYunsheng Lin ret = hclge_tm_qs_schd_mode_cfg(hdev, vport->qs_offset + i, 1203cc9bb43aSYunsheng Lin sch_mode); 120484844054SSalil if (ret) 120584844054SSalil return ret; 120684844054SSalil } 120784844054SSalil 120884844054SSalil return 0; 120984844054SSalil } 121084844054SSalil 121184844054SSalil static int hclge_tm_lvl34_schd_mode_cfg(struct hclge_dev *hdev) 121284844054SSalil { 121384844054SSalil struct hclge_vport *vport = hdev->vport; 121484844054SSalil int ret; 1215cc9bb43aSYunsheng Lin u8 i, k; 121684844054SSalil 121784844054SSalil if (hdev->tx_sch_mode == HCLGE_FLAG_TC_BASE_SCH_MODE) { 121884844054SSalil for (i = 0; i < hdev->tm_info.num_tc; i++) { 121984844054SSalil ret = hclge_tm_pri_schd_mode_cfg(hdev, i); 122084844054SSalil if (ret) 122184844054SSalil return ret; 122284844054SSalil 1223cc9bb43aSYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1224cc9bb43aSYunsheng Lin ret = hclge_tm_qs_schd_mode_cfg( 1225cc9bb43aSYunsheng Lin hdev, vport[k].qs_offset + i, 1226cc9bb43aSYunsheng Lin HCLGE_SCH_MODE_DWRR); 122784844054SSalil if (ret) 122884844054SSalil return ret; 122984844054SSalil } 1230cc9bb43aSYunsheng Lin } 123184844054SSalil } else { 123284844054SSalil for (i = 0; i < hdev->num_alloc_vport; i++) { 123384844054SSalil ret = hclge_tm_schd_mode_vnet_base_cfg(vport); 123484844054SSalil if (ret) 123584844054SSalil return ret; 123684844054SSalil 123784844054SSalil vport++; 123884844054SSalil } 123984844054SSalil } 124084844054SSalil 124184844054SSalil return 0; 124284844054SSalil } 124384844054SSalil 12449e5157baSYunsheng Lin static int hclge_tm_schd_mode_hw(struct hclge_dev *hdev) 124584844054SSalil { 124684844054SSalil int ret; 124784844054SSalil 124884844054SSalil ret = hclge_tm_lvl2_schd_mode_cfg(hdev); 124984844054SSalil if (ret) 125084844054SSalil return ret; 125184844054SSalil 125284844054SSalil return hclge_tm_lvl34_schd_mode_cfg(hdev); 125384844054SSalil } 125484844054SSalil 12559e5157baSYunsheng Lin int hclge_tm_schd_setup_hw(struct hclge_dev *hdev) 125684844054SSalil { 125784844054SSalil int ret; 125884844054SSalil 125984844054SSalil /* Cfg tm mapping */ 126084844054SSalil ret = hclge_tm_map_cfg(hdev); 126184844054SSalil if (ret) 126284844054SSalil return ret; 126384844054SSalil 126484844054SSalil /* Cfg tm shaper */ 126584844054SSalil ret = hclge_tm_shaper_cfg(hdev); 126684844054SSalil if (ret) 126784844054SSalil return ret; 126884844054SSalil 126984844054SSalil /* Cfg dwrr */ 127084844054SSalil ret = hclge_tm_dwrr_cfg(hdev); 127184844054SSalil if (ret) 127284844054SSalil return ret; 127384844054SSalil 127484844054SSalil /* Cfg schd mode for each level schd */ 127584844054SSalil return hclge_tm_schd_mode_hw(hdev); 127684844054SSalil } 127784844054SSalil 1278e98d7183SFuyun Liang static int hclge_pause_param_setup_hw(struct hclge_dev *hdev) 127918838d0cSFuyun Liang { 128018838d0cSFuyun Liang struct hclge_mac *mac = &hdev->hw.mac; 128118838d0cSFuyun Liang 1282e98d7183SFuyun Liang return hclge_pause_param_cfg(hdev, mac->mac_addr, 128318838d0cSFuyun Liang HCLGE_DEFAULT_PAUSE_TRANS_GAP, 128418838d0cSFuyun Liang HCLGE_DEFAULT_PAUSE_TRANS_TIME); 128518838d0cSFuyun Liang } 128618838d0cSFuyun Liang 12879dc2145dSYunsheng Lin static int hclge_pfc_setup_hw(struct hclge_dev *hdev) 12889dc2145dSYunsheng Lin { 12899dc2145dSYunsheng Lin u8 enable_bitmap = 0; 12909dc2145dSYunsheng Lin 12919dc2145dSYunsheng Lin if (hdev->tm_info.fc_mode == HCLGE_FC_PFC) 12929dc2145dSYunsheng Lin enable_bitmap = HCLGE_TX_MAC_PAUSE_EN_MSK | 12939dc2145dSYunsheng Lin HCLGE_RX_MAC_PAUSE_EN_MSK; 12949dc2145dSYunsheng Lin 12959dc2145dSYunsheng Lin return hclge_pfc_pause_en_cfg(hdev, enable_bitmap, 1296d3ad430aSYunsheng Lin hdev->tm_info.pfc_en); 12979dc2145dSYunsheng Lin } 12989dc2145dSYunsheng Lin 129967bf2541SYunsheng Lin /* Each Tc has a 1024 queue sets to backpress, it divides to 130067bf2541SYunsheng Lin * 32 group, each group contains 32 queue sets, which can be 130167bf2541SYunsheng Lin * represented by u32 bitmap. 130267bf2541SYunsheng Lin */ 130367bf2541SYunsheng Lin static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc) 130467bf2541SYunsheng Lin { 1305e8ccbb7dSYunsheng Lin int i; 130667bf2541SYunsheng Lin 130767bf2541SYunsheng Lin for (i = 0; i < HCLGE_BP_GRP_NUM; i++) { 1308e8ccbb7dSYunsheng Lin u32 qs_bitmap = 0; 1309e8ccbb7dSYunsheng Lin int k, ret; 131067bf2541SYunsheng Lin 131167bf2541SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 1312e8ccbb7dSYunsheng Lin struct hclge_vport *vport = &hdev->vport[k]; 131367bf2541SYunsheng Lin u16 qs_id = vport->qs_offset + tc; 131467bf2541SYunsheng Lin u8 grp, sub_grp; 131567bf2541SYunsheng Lin 1316e4e87715SPeng Li grp = hnae3_get_field(qs_id, HCLGE_BP_GRP_ID_M, 131767bf2541SYunsheng Lin HCLGE_BP_GRP_ID_S); 1318e4e87715SPeng Li sub_grp = hnae3_get_field(qs_id, HCLGE_BP_SUB_GRP_ID_M, 131967bf2541SYunsheng Lin HCLGE_BP_SUB_GRP_ID_S); 132067bf2541SYunsheng Lin if (i == grp) 132167bf2541SYunsheng Lin qs_bitmap |= (1 << sub_grp); 132267bf2541SYunsheng Lin } 132367bf2541SYunsheng Lin 132467bf2541SYunsheng Lin ret = hclge_tm_qs_bp_cfg(hdev, tc, i, qs_bitmap); 132567bf2541SYunsheng Lin if (ret) 132667bf2541SYunsheng Lin return ret; 132767bf2541SYunsheng Lin } 132867bf2541SYunsheng Lin 132967bf2541SYunsheng Lin return 0; 133067bf2541SYunsheng Lin } 133167bf2541SYunsheng Lin 13329dc2145dSYunsheng Lin static int hclge_mac_pause_setup_hw(struct hclge_dev *hdev) 13339dc2145dSYunsheng Lin { 13349dc2145dSYunsheng Lin bool tx_en, rx_en; 13359dc2145dSYunsheng Lin 13369dc2145dSYunsheng Lin switch (hdev->tm_info.fc_mode) { 13379dc2145dSYunsheng Lin case HCLGE_FC_NONE: 13389dc2145dSYunsheng Lin tx_en = false; 13399dc2145dSYunsheng Lin rx_en = false; 13409dc2145dSYunsheng Lin break; 13419dc2145dSYunsheng Lin case HCLGE_FC_RX_PAUSE: 13429dc2145dSYunsheng Lin tx_en = false; 13439dc2145dSYunsheng Lin rx_en = true; 13449dc2145dSYunsheng Lin break; 13459dc2145dSYunsheng Lin case HCLGE_FC_TX_PAUSE: 13469dc2145dSYunsheng Lin tx_en = true; 13479dc2145dSYunsheng Lin rx_en = false; 13489dc2145dSYunsheng Lin break; 13499dc2145dSYunsheng Lin case HCLGE_FC_FULL: 13509dc2145dSYunsheng Lin tx_en = true; 13519dc2145dSYunsheng Lin rx_en = true; 13529dc2145dSYunsheng Lin break; 13536d0ec65cSYunsheng Lin case HCLGE_FC_PFC: 13546d0ec65cSYunsheng Lin tx_en = false; 13556d0ec65cSYunsheng Lin rx_en = false; 13566d0ec65cSYunsheng Lin break; 13579dc2145dSYunsheng Lin default: 13589dc2145dSYunsheng Lin tx_en = true; 13599dc2145dSYunsheng Lin rx_en = true; 13609dc2145dSYunsheng Lin } 13619dc2145dSYunsheng Lin 13629dc2145dSYunsheng Lin return hclge_mac_pause_en_cfg(hdev, tx_en, rx_en); 13639dc2145dSYunsheng Lin } 13649dc2145dSYunsheng Lin 136573fc9c48SHuazhong Tan static int hclge_tm_bp_setup(struct hclge_dev *hdev) 136673fc9c48SHuazhong Tan { 13679d8d5a36SYufeng Mo int ret; 136873fc9c48SHuazhong Tan int i; 136973fc9c48SHuazhong Tan 137073fc9c48SHuazhong Tan for (i = 0; i < hdev->tm_info.num_tc; i++) { 137173fc9c48SHuazhong Tan ret = hclge_bp_setup_hw(hdev, i); 137273fc9c48SHuazhong Tan if (ret) 137373fc9c48SHuazhong Tan return ret; 137473fc9c48SHuazhong Tan } 137573fc9c48SHuazhong Tan 137673fc9c48SHuazhong Tan return ret; 137773fc9c48SHuazhong Tan } 137873fc9c48SHuazhong Tan 137944e59e37SYunsheng Lin int hclge_pause_setup_hw(struct hclge_dev *hdev, bool init) 138084844054SSalil { 138184844054SSalil int ret; 138284844054SSalil 1383e98d7183SFuyun Liang ret = hclge_pause_param_setup_hw(hdev); 138418838d0cSFuyun Liang if (ret) 138518838d0cSFuyun Liang return ret; 138618838d0cSFuyun Liang 13876d0ec65cSYunsheng Lin ret = hclge_mac_pause_setup_hw(hdev); 13886d0ec65cSYunsheng Lin if (ret) 13896d0ec65cSYunsheng Lin return ret; 139084844054SSalil 13919dc2145dSYunsheng Lin /* Only DCB-supported dev supports qset back pressure and pfc cmd */ 13922daf4a65SYunsheng Lin if (!hnae3_dev_dcb_supported(hdev)) 13932daf4a65SYunsheng Lin return 0; 13942daf4a65SYunsheng Lin 139544e59e37SYunsheng Lin /* GE MAC does not support PFC, when driver is initializing and MAC 139644e59e37SYunsheng Lin * is in GE Mode, ignore the error here, otherwise initialization 139744e59e37SYunsheng Lin * will fail. 139844e59e37SYunsheng Lin */ 13999dc2145dSYunsheng Lin ret = hclge_pfc_setup_hw(hdev); 140044e59e37SYunsheng Lin if (init && ret == -EOPNOTSUPP) 140144e59e37SYunsheng Lin dev_warn(&hdev->pdev->dev, "GE MAC does not support pfc\n"); 1402fba2efdaSHuazhong Tan else if (ret) { 1403fba2efdaSHuazhong Tan dev_err(&hdev->pdev->dev, "config pfc failed! ret = %d\n", 1404fba2efdaSHuazhong Tan ret); 140544e59e37SYunsheng Lin return ret; 1406fba2efdaSHuazhong Tan } 14079dc2145dSYunsheng Lin 140873fc9c48SHuazhong Tan return hclge_tm_bp_setup(hdev); 140977f255c1SYunsheng Lin } 141077f255c1SYunsheng Lin 1411e432abfbSYunsheng Lin void hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc) 141277f255c1SYunsheng Lin { 141377f255c1SYunsheng Lin struct hclge_vport *vport = hdev->vport; 141477f255c1SYunsheng Lin struct hnae3_knic_private_info *kinfo; 141577f255c1SYunsheng Lin u32 i, k; 141677f255c1SYunsheng Lin 141777f255c1SYunsheng Lin for (i = 0; i < HNAE3_MAX_USER_PRIO; i++) { 141877f255c1SYunsheng Lin hdev->tm_info.prio_tc[i] = prio_tc[i]; 141977f255c1SYunsheng Lin 142077f255c1SYunsheng Lin for (k = 0; k < hdev->num_alloc_vport; k++) { 142177f255c1SYunsheng Lin kinfo = &vport[k].nic.kinfo; 142277f255c1SYunsheng Lin kinfo->prio_tc[i] = prio_tc[i]; 142377f255c1SYunsheng Lin } 142477f255c1SYunsheng Lin } 142577f255c1SYunsheng Lin } 142677f255c1SYunsheng Lin 1427e432abfbSYunsheng Lin void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc) 142877f255c1SYunsheng Lin { 14299b2f3477SWeihang Li u8 bit_map = 0; 14309b2f3477SWeihang Li u8 i; 143177f255c1SYunsheng Lin 143277f255c1SYunsheng Lin hdev->tm_info.num_tc = num_tc; 143377f255c1SYunsheng Lin 143477f255c1SYunsheng Lin for (i = 0; i < hdev->tm_info.num_tc; i++) 143577f255c1SYunsheng Lin bit_map |= BIT(i); 143677f255c1SYunsheng Lin 143777f255c1SYunsheng Lin if (!bit_map) { 143877f255c1SYunsheng Lin bit_map = 1; 143977f255c1SYunsheng Lin hdev->tm_info.num_tc = 1; 144077f255c1SYunsheng Lin } 144177f255c1SYunsheng Lin 144277f255c1SYunsheng Lin hdev->hw_tc_map = bit_map; 144377f255c1SYunsheng Lin 144477f255c1SYunsheng Lin hclge_tm_schd_info_init(hdev); 144584844054SSalil } 144684844054SSalil 1447ae179b2fSYunsheng Lin void hclge_tm_pfc_info_update(struct hclge_dev *hdev) 1448ae179b2fSYunsheng Lin { 1449ae179b2fSYunsheng Lin /* DCB is enabled if we have more than 1 TC or pfc_en is 1450ae179b2fSYunsheng Lin * non-zero. 1451ae179b2fSYunsheng Lin */ 1452ae179b2fSYunsheng Lin if (hdev->tm_info.num_tc > 1 || hdev->tm_info.pfc_en) 1453ae179b2fSYunsheng Lin hdev->flag |= HCLGE_FLAG_DCB_ENABLE; 1454ae179b2fSYunsheng Lin else 1455ae179b2fSYunsheng Lin hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE; 1456ae179b2fSYunsheng Lin 1457ae179b2fSYunsheng Lin hclge_pfc_info_init(hdev); 1458ae179b2fSYunsheng Lin } 1459ae179b2fSYunsheng Lin 146044e59e37SYunsheng Lin int hclge_tm_init_hw(struct hclge_dev *hdev, bool init) 146184844054SSalil { 146284844054SSalil int ret; 146384844054SSalil 146484844054SSalil if ((hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE) && 146584844054SSalil (hdev->tx_sch_mode != HCLGE_FLAG_VNET_BASE_SCH_MODE)) 146684844054SSalil return -ENOTSUPP; 146784844054SSalil 146884844054SSalil ret = hclge_tm_schd_setup_hw(hdev); 146984844054SSalil if (ret) 147084844054SSalil return ret; 147184844054SSalil 147244e59e37SYunsheng Lin ret = hclge_pause_setup_hw(hdev, init); 147384844054SSalil if (ret) 147484844054SSalil return ret; 147584844054SSalil 147684844054SSalil return 0; 147784844054SSalil } 147884844054SSalil 147984844054SSalil int hclge_tm_schd_init(struct hclge_dev *hdev) 148084844054SSalil { 14817979a223SYunsheng Lin /* fc_mode is HCLGE_FC_FULL on reset */ 14827979a223SYunsheng Lin hdev->tm_info.fc_mode = HCLGE_FC_FULL; 14837979a223SYunsheng Lin hdev->fc_mode_last_time = hdev->tm_info.fc_mode; 14847979a223SYunsheng Lin 1485b6872fd3SYunsheng Lin if (hdev->tx_sch_mode != HCLGE_FLAG_TC_BASE_SCH_MODE && 1486b6872fd3SYunsheng Lin hdev->tm_info.num_pg != 1) 1487b6872fd3SYunsheng Lin return -EINVAL; 1488b6872fd3SYunsheng Lin 1489b6872fd3SYunsheng Lin hclge_tm_schd_info_init(hdev); 149084844054SSalil 149144e59e37SYunsheng Lin return hclge_tm_init_hw(hdev, true); 149284844054SSalil } 1493672ad0edSHuazhong Tan 1494672ad0edSHuazhong Tan int hclge_tm_vport_map_update(struct hclge_dev *hdev) 1495672ad0edSHuazhong Tan { 1496672ad0edSHuazhong Tan struct hclge_vport *vport = hdev->vport; 1497672ad0edSHuazhong Tan int ret; 1498672ad0edSHuazhong Tan 1499672ad0edSHuazhong Tan hclge_tm_vport_tc_info_update(vport); 1500672ad0edSHuazhong Tan 1501672ad0edSHuazhong Tan ret = hclge_vport_q_to_qs_map(hdev, vport); 1502672ad0edSHuazhong Tan if (ret) 1503672ad0edSHuazhong Tan return ret; 1504672ad0edSHuazhong Tan 1505672ad0edSHuazhong Tan if (!(hdev->flag & HCLGE_FLAG_DCB_ENABLE)) 1506672ad0edSHuazhong Tan return 0; 1507672ad0edSHuazhong Tan 1508672ad0edSHuazhong Tan return hclge_tm_bp_setup(hdev); 1509672ad0edSHuazhong Tan } 1510