[PATCH net-next 5/9] net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver

2017-06-09 Thread Salil Mehta
THis patch adds the support of the Scheduling and Shaping
functionalities during the transmit leg. This also adds the
support of Pause at MAC level. (Pause at per-priority level
shall be added later along with the DCB feature).

Hardware as such consists of two types of cofiguration of 6 level
schedulers. Algorithms varies according to the level and type
of scheduler being used. Current patch is used to initialize
the mapping, algorithms(like SP, DWRR etc) and shaper(CIR, PIR etc)
being used.

Signed-off-by: Daode Huang 
Signed-off-by: lipeng 
Signed-off-by: Salil Mehta 
Signed-off-by: Yisen Zhuang 
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c  | 1018 
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h  |  108 +++
 2 files changed, 1126 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
new file mode 100644
index 000..2b66a0e
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hclge_tm.h"
+
+enum hclge_shaper_level {
+   HCLGE_SHAPER_LVL_PRI= 0,
+   HCLGE_SHAPER_LVL_PG = 1,
+   HCLGE_SHAPER_LVL_PORT   = 2,
+   HCLGE_SHAPER_LVL_QSET   = 3,
+   HCLGE_SHAPER_LVL_CNT= 4,
+   HCLGE_SHAPER_LVL_VF = 0,
+   HCLGE_SHAPER_LVL_PF = 1,
+};
+
+#define HCLGE_SHAPER_BS_U_DEF  1
+#define HCLGE_SHAPER_BS_S_DEF  4
+
+#define HCLGE_ETHER_MAX_RATE   10
+
+/* hclge_shaper_para_calc: calculate ir parameter for the shaper
+ * @ir: Rate to be config, its unit is Mbps
+ * @shaper_level: the shaper level. eg: port, pg, priority, queueset
+ * @ir_b: IR_B parameter of IR shaper
+ * @ir_u: IR_U parameter of IR shaper
+ * @ir_s: IR_S parameter of IR shaper
+ *
+ * the formula:
+ *
+ * IR_b * (2 ^ IR_u) * 8
+ * IR(Mbps) = -  *  CLOCK(1000Mbps)
+ * Tick * (2 ^ IR_s)
+ *
+ * @return: 0: calculate sucessful, negative: fail
+ */
+static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
+ u8 *ir_b, u8 *ir_u, u8 *ir_s)
+{
+   const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
+   6 * 256,/* Prioriy level */
+   6 * 32, /* Prioriy group level */
+   6 * 8,  /* Port level */
+   6 * 256 /* Qset level */
+   };
+   u8 ir_u_calc = 0, ir_s_calc = 0;
+   u32 ir_calc;
+   u32 tick;
+
+   /* Calc tick */
+   if (shaper_level >= HCLGE_SHAPER_LVL_CNT)
+   return -ENOMEM;
+
+   tick = tick_array[shaper_level];
+
+   /**
+* Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0
+* the formula is changed to:
+*  126 * 1 * 8
+* ir_calc =  * 1000
+*  tick * 1
+*/
+   ir_calc = (1008000 + (tick >> 1) - 1) / tick;
+
+   if (ir_calc == ir) {
+   *ir_b = 126;
+   *ir_u = 0;
+   *ir_s = 0;
+
+   return 0;
+   } else if (ir_calc > ir) {
+   /* Increasing the denominator to select ir_s value */
+   while (ir_calc > ir) {
+   ir_s_calc++;
+   ir_calc = 1008000 / (tick * (1 << ir_s_calc));
+   }
+
+   if (ir_calc == ir)
+   *ir_b = 126;
+   else
+   *ir_b = (ir * tick * (1 << ir_s_calc) + 4000) / 8000;
+   } else {
+   /* Increasing the numerator to select ir_u value */
+   u32 numerator;
+
+   while (ir_calc < ir) {
+   ir_u_calc++;
+   numerator = 1008000 * (1 << ir_u_calc);
+   ir_calc = (numerator + (tick >> 1)) / tick;
+   }
+
+   if (ir_calc == ir) {
+   *ir_b = 126;
+   } else {
+   u32 denominator = (8000 * (1 << --ir_u_calc));
+   *ir_b = (ir * tick + (denominator >> 1)) / denominator;
+   }
+   }
+
+   *ir_u = ir_u_calc;
+   *ir_s = ir_s_calc;
+
+   return 0;
+}
+
+static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
+{
+   struct hclge_desc desc;
+
+   hclge_cmd_setup_basic_desc(, 

[PATCH net-next 5/9] net: hns3: Add support of TX Scheduler & Shaper to HNS3 driver

2017-06-09 Thread Salil Mehta
THis patch adds the support of the Scheduling and Shaping
functionalities during the transmit leg. This also adds the
support of Pause at MAC level. (Pause at per-priority level
shall be added later along with the DCB feature).

Hardware as such consists of two types of cofiguration of 6 level
schedulers. Algorithms varies according to the level and type
of scheduler being used. Current patch is used to initialize
the mapping, algorithms(like SP, DWRR etc) and shaper(CIR, PIR etc)
being used.

Signed-off-by: Daode Huang 
Signed-off-by: lipeng 
Signed-off-by: Salil Mehta 
Signed-off-by: Yisen Zhuang 
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c  | 1018 
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h  |  108 +++
 2 files changed, 1126 insertions(+)
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
 create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
new file mode 100644
index 000..2b66a0e
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -0,0 +1,1018 @@
+/*
+ * Copyright (c) 2016~2017 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include 
+
+#include "hclge_cmd.h"
+#include "hclge_main.h"
+#include "hclge_tm.h"
+
+enum hclge_shaper_level {
+   HCLGE_SHAPER_LVL_PRI= 0,
+   HCLGE_SHAPER_LVL_PG = 1,
+   HCLGE_SHAPER_LVL_PORT   = 2,
+   HCLGE_SHAPER_LVL_QSET   = 3,
+   HCLGE_SHAPER_LVL_CNT= 4,
+   HCLGE_SHAPER_LVL_VF = 0,
+   HCLGE_SHAPER_LVL_PF = 1,
+};
+
+#define HCLGE_SHAPER_BS_U_DEF  1
+#define HCLGE_SHAPER_BS_S_DEF  4
+
+#define HCLGE_ETHER_MAX_RATE   10
+
+/* hclge_shaper_para_calc: calculate ir parameter for the shaper
+ * @ir: Rate to be config, its unit is Mbps
+ * @shaper_level: the shaper level. eg: port, pg, priority, queueset
+ * @ir_b: IR_B parameter of IR shaper
+ * @ir_u: IR_U parameter of IR shaper
+ * @ir_s: IR_S parameter of IR shaper
+ *
+ * the formula:
+ *
+ * IR_b * (2 ^ IR_u) * 8
+ * IR(Mbps) = -  *  CLOCK(1000Mbps)
+ * Tick * (2 ^ IR_s)
+ *
+ * @return: 0: calculate sucessful, negative: fail
+ */
+static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
+ u8 *ir_b, u8 *ir_u, u8 *ir_s)
+{
+   const u16 tick_array[HCLGE_SHAPER_LVL_CNT] = {
+   6 * 256,/* Prioriy level */
+   6 * 32, /* Prioriy group level */
+   6 * 8,  /* Port level */
+   6 * 256 /* Qset level */
+   };
+   u8 ir_u_calc = 0, ir_s_calc = 0;
+   u32 ir_calc;
+   u32 tick;
+
+   /* Calc tick */
+   if (shaper_level >= HCLGE_SHAPER_LVL_CNT)
+   return -ENOMEM;
+
+   tick = tick_array[shaper_level];
+
+   /**
+* Calc the speed if ir_b = 126, ir_u = 0 and ir_s = 0
+* the formula is changed to:
+*  126 * 1 * 8
+* ir_calc =  * 1000
+*  tick * 1
+*/
+   ir_calc = (1008000 + (tick >> 1) - 1) / tick;
+
+   if (ir_calc == ir) {
+   *ir_b = 126;
+   *ir_u = 0;
+   *ir_s = 0;
+
+   return 0;
+   } else if (ir_calc > ir) {
+   /* Increasing the denominator to select ir_s value */
+   while (ir_calc > ir) {
+   ir_s_calc++;
+   ir_calc = 1008000 / (tick * (1 << ir_s_calc));
+   }
+
+   if (ir_calc == ir)
+   *ir_b = 126;
+   else
+   *ir_b = (ir * tick * (1 << ir_s_calc) + 4000) / 8000;
+   } else {
+   /* Increasing the numerator to select ir_u value */
+   u32 numerator;
+
+   while (ir_calc < ir) {
+   ir_u_calc++;
+   numerator = 1008000 * (1 << ir_u_calc);
+   ir_calc = (numerator + (tick >> 1)) / tick;
+   }
+
+   if (ir_calc == ir) {
+   *ir_b = 126;
+   } else {
+   u32 denominator = (8000 * (1 << --ir_u_calc));
+   *ir_b = (ir * tick + (denominator >> 1)) / denominator;
+   }
+   }
+
+   *ir_u = ir_u_calc;
+   *ir_s = ir_s_calc;
+
+   return 0;
+}
+
+static int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
+{
+   struct hclge_desc desc;
+
+   hclge_cmd_setup_basic_desc(, HCLGE_OPC_CFG_MAC_PAUSE_EN, false);
+
+   desc.data[0] = cpu_to_le32((tx ? HCLGE_TX_MAC_PAUSE_EN_MSK