OSDN Git Service

RDMA/hns: Add timer allocation support for hip08
authorYangyang Li <liyangyang20@huawei.com>
Tue, 18 Dec 2018 13:21:55 +0000 (21:21 +0800)
committerJason Gunthorpe <jgg@mellanox.com>
Thu, 24 Jan 2019 16:22:30 +0000 (09:22 -0700)
This patch adds qpc timer and cqc timer allocation support for hardware
timeout retransmission in kernel space driver.

Signed-off-by: Yangyang Li <liyangyang20@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/hns/hns_roce_cmd.h
drivers/infiniband/hw/hns/hns_roce_device.h
drivers/infiniband/hw/hns/hns_roce_hem.c
drivers/infiniband/hw/hns/hns_roce_hem.h
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h
drivers/infiniband/hw/hns/hns_roce_main.c

index f682cb4..059fd1d 100644 (file)
@@ -75,6 +75,10 @@ enum {
        HNS_ROCE_CMD_DESTROY_MPT_BT1    = 0x29,
        HNS_ROCE_CMD_DESTROY_MPT_BT2    = 0x2a,
 
+       /* CQC TIMER commands */
+       HNS_ROCE_CMD_WRITE_CQC_TIMER_BT0 = 0x23,
+       HNS_ROCE_CMD_READ_CQC_TIMER_BT0  = 0x27,
+
        /* MPT commands */
        HNS_ROCE_CMD_QUERY_MPT          = 0x62,
 
@@ -89,6 +93,10 @@ enum {
        HNS_ROCE_CMD_DESTROY_SRQC_BT1   = 0x39,
        HNS_ROCE_CMD_DESTROY_SRQC_BT2   = 0x3a,
 
+       /* QPC TIMER commands */
+       HNS_ROCE_CMD_WRITE_QPC_TIMER_BT0 = 0x33,
+       HNS_ROCE_CMD_READ_QPC_TIMER_BT0  = 0x37,
+
        /* EQC commands */
        HNS_ROCE_CMD_CREATE_AEQC        = 0x80,
        HNS_ROCE_CMD_MODIFY_AEQC        = 0x81,
index bbcc56f..6fde434 100644 (file)
@@ -732,6 +732,8 @@ struct hns_roce_caps {
        u32             max_extend_sg;
        int             num_qps;        /* 256k */
        int             reserved_qps;
+       int             num_qpc_timer;
+       int             num_cqc_timer;
        u32             max_srq_sg;
        int             num_srqs;
        u32             max_wqes;       /* 16k */
@@ -772,6 +774,8 @@ struct hns_roce_caps {
        int             trrl_entry_sz;
        int             cqc_entry_sz;
        int             sccc_entry_sz;
+       int             qpc_timer_entry_sz;
+       int             cqc_timer_entry_sz;
        int             srqc_entry_sz;
        int             idx_entry_sz;
        u32             pbl_ba_pg_sz;
@@ -781,8 +785,10 @@ struct hns_roce_caps {
        int             ceqe_depth;
        enum ib_mtu     max_mtu;
        u32             qpc_bt_num;
+       u32             qpc_timer_bt_num;
        u32             srqc_bt_num;
        u32             cqc_bt_num;
+       u32             cqc_timer_bt_num;
        u32             mpt_bt_num;
        u32             sccc_bt_num;
        u32             qpc_ba_pg_sz;
@@ -803,6 +809,12 @@ struct hns_roce_caps {
        u32             sccc_ba_pg_sz;
        u32             sccc_buf_pg_sz;
        u32             sccc_hop_num;
+       u32             qpc_timer_ba_pg_sz;
+       u32             qpc_timer_buf_pg_sz;
+       u32             qpc_timer_hop_num;
+       u32             cqc_timer_ba_pg_sz;
+       u32             cqc_timer_buf_pg_sz;
+       u32             cqc_timer_hop_num;
        u32             cqe_ba_pg_sz;
        u32             cqe_buf_pg_sz;
        u32             cqe_hop_num;
@@ -932,6 +944,8 @@ struct hns_roce_dev {
        struct hns_roce_srq_table srq_table;
        struct hns_roce_qp_table  qp_table;
        struct hns_roce_eq_table  eq_table;
+       struct hns_roce_hem_table  qpc_timer_table;
+       struct hns_roce_hem_table  cqc_timer_table;
 
        int                     cmd_mod;
        int                     loop_idc;
index fc7b69e..f1fec56 100644 (file)
@@ -46,6 +46,8 @@ bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type)
            (hr_dev->caps.cqc_hop_num && type == HEM_TYPE_CQC) ||
            (hr_dev->caps.srqc_hop_num && type == HEM_TYPE_SRQC) ||
            (hr_dev->caps.sccc_hop_num && type == HEM_TYPE_SCCC) ||
+           (hr_dev->caps.qpc_timer_hop_num && type == HEM_TYPE_QPC_TIMER) ||
+           (hr_dev->caps.cqc_timer_hop_num && type == HEM_TYPE_CQC_TIMER) ||
            (hr_dev->caps.cqe_hop_num && type == HEM_TYPE_CQE) ||
            (hr_dev->caps.mtt_hop_num && type == HEM_TYPE_MTT) ||
            (hr_dev->caps.srqwqe_hop_num && type == HEM_TYPE_SRQWQE) ||
@@ -134,6 +136,22 @@ int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
                mhop->ba_l0_num = hr_dev->caps.sccc_bt_num;
                mhop->hop_num = hr_dev->caps.sccc_hop_num;
                break;
+       case HEM_TYPE_QPC_TIMER:
+               mhop->buf_chunk_size = 1 << (hr_dev->caps.qpc_timer_buf_pg_sz
+                                            + PAGE_SHIFT);
+               mhop->bt_chunk_size = 1 << (hr_dev->caps.qpc_timer_ba_pg_sz
+                                           + PAGE_SHIFT);
+               mhop->ba_l0_num = hr_dev->caps.qpc_timer_bt_num;
+               mhop->hop_num = hr_dev->caps.qpc_timer_hop_num;
+               break;
+       case HEM_TYPE_CQC_TIMER:
+               mhop->buf_chunk_size = 1 << (hr_dev->caps.cqc_timer_buf_pg_sz
+                                            + PAGE_SHIFT);
+               mhop->bt_chunk_size = 1 << (hr_dev->caps.cqc_timer_ba_pg_sz
+                                           + PAGE_SHIFT);
+               mhop->ba_l0_num = hr_dev->caps.cqc_timer_bt_num;
+               mhop->hop_num = hr_dev->caps.cqc_timer_hop_num;
+               break;
        case HEM_TYPE_SRQC:
                mhop->buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
                                             + PAGE_SHIFT);
@@ -602,6 +620,7 @@ out:
        mutex_unlock(&table->mutex);
        return ret;
 }
+EXPORT_SYMBOL_GPL(hns_roce_table_get);
 
 static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
                                    struct hns_roce_hem_table *table,
@@ -744,6 +763,7 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev,
 
        mutex_unlock(&table->mutex);
 }
+EXPORT_SYMBOL_GPL(hns_roce_table_put);
 
 void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
                          struct hns_roce_hem_table *table,
@@ -921,6 +941,22 @@ int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
                        num_bt_l0 = hr_dev->caps.sccc_bt_num;
                        hop_num = hr_dev->caps.sccc_hop_num;
                        break;
+               case HEM_TYPE_QPC_TIMER:
+                       buf_chunk_size = 1 << (hr_dev->caps.qpc_timer_buf_pg_sz
+                                       + PAGE_SHIFT);
+                       bt_chunk_size = 1 << (hr_dev->caps.qpc_timer_ba_pg_sz
+                                       + PAGE_SHIFT);
+                       num_bt_l0 = hr_dev->caps.qpc_timer_bt_num;
+                       hop_num = hr_dev->caps.qpc_timer_hop_num;
+                       break;
+               case HEM_TYPE_CQC_TIMER:
+                       buf_chunk_size = 1 << (hr_dev->caps.cqc_timer_buf_pg_sz
+                                       + PAGE_SHIFT);
+                       bt_chunk_size = 1 << (hr_dev->caps.cqc_timer_ba_pg_sz
+                                       + PAGE_SHIFT);
+                       num_bt_l0 = hr_dev->caps.cqc_timer_bt_num;
+                       hop_num = hr_dev->caps.cqc_timer_hop_num;
+                       break;
                case HEM_TYPE_SRQC:
                        buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
                                        + PAGE_SHIFT);
@@ -1098,6 +1134,12 @@ void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev)
                hns_roce_cleanup_hem_table(hr_dev,
                                           &hr_dev->srq_table.table);
        hns_roce_cleanup_hem_table(hr_dev, &hr_dev->cq_table.table);
+       if (hr_dev->caps.qpc_timer_entry_sz)
+               hns_roce_cleanup_hem_table(hr_dev,
+                                          &hr_dev->qpc_timer_table);
+       if (hr_dev->caps.cqc_timer_entry_sz)
+               hns_roce_cleanup_hem_table(hr_dev,
+                                          &hr_dev->cqc_timer_table);
        if (hr_dev->caps.sccc_entry_sz)
                hns_roce_cleanup_hem_table(hr_dev,
                                           &hr_dev->qp_table.sccc_table);
index b2aeb74..d9d6689 100644 (file)
@@ -45,6 +45,8 @@ enum {
        HEM_TYPE_CQC,
        HEM_TYPE_SRQC,
        HEM_TYPE_SCCC,
+       HEM_TYPE_QPC_TIMER,
+       HEM_TYPE_CQC_TIMER,
 
         /* UNMAP HEM */
        HEM_TYPE_MTT,
index 5e57f5f..d63dd15 100644 (file)
@@ -1085,6 +1085,41 @@ static int hns_roce_query_pf_resource(struct hns_roce_dev *hr_dev)
        return 0;
 }
 
+static int hns_roce_query_pf_timer_resource(struct hns_roce_dev *hr_dev)
+{
+       struct hns_roce_pf_timer_res_a *req_a;
+       struct hns_roce_cmq_desc desc[2];
+       int ret, i;
+
+       for (i = 0; i < 2; i++) {
+               hns_roce_cmq_setup_basic_desc(&desc[i],
+                                             HNS_ROCE_OPC_QUERY_PF_TIMER_RES,
+                                             true);
+
+               if (i == 0)
+                       desc[i].flag |= cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
+               else
+                       desc[i].flag &= ~cpu_to_le16(HNS_ROCE_CMD_FLAG_NEXT);
+       }
+
+       ret = hns_roce_cmq_send(hr_dev, desc, 2);
+       if (ret)
+               return ret;
+
+       req_a = (struct hns_roce_pf_timer_res_a *)desc[0].data;
+
+       hr_dev->caps.qpc_timer_bt_num =
+                               roce_get_field(req_a->qpc_timer_bt_idx_num,
+                                       PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_M,
+                                       PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_S);
+       hr_dev->caps.cqc_timer_bt_num =
+                               roce_get_field(req_a->cqc_timer_bt_idx_num,
+                                       PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_M,
+                                       PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_S);
+
+       return 0;
+}
+
 static int hns_roce_set_vf_switch_param(struct hns_roce_dev *hr_dev,
                                                  int vf_id)
 {
@@ -1315,6 +1350,16 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
                return ret;
        }
 
+       if (hr_dev->pci_dev->revision == 0x21) {
+               ret = hns_roce_query_pf_timer_resource(hr_dev);
+               if (ret) {
+                       dev_err(hr_dev->dev,
+                               "Query pf timer resource fail, ret = %d.\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        ret = hns_roce_alloc_vf_resource(hr_dev);
        if (ret) {
                dev_err(hr_dev->dev, "Allocate vf resource fail, ret = %d.\n",
@@ -1439,6 +1484,17 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
                               HNS_ROCE_CAP_FLAG_SRQ |
                               HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL;
 
+               caps->num_qpc_timer       = HNS_ROCE_V2_MAX_QPC_TIMER_NUM;
+               caps->qpc_timer_entry_sz  = HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ;
+               caps->qpc_timer_ba_pg_sz  = 0;
+               caps->qpc_timer_buf_pg_sz = 0;
+               caps->qpc_timer_hop_num   = HNS_ROCE_HOP_NUM_0;
+               caps->num_cqc_timer       = HNS_ROCE_V2_MAX_CQC_TIMER_NUM;
+               caps->cqc_timer_entry_sz  = HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ;
+               caps->cqc_timer_ba_pg_sz  = 0;
+               caps->cqc_timer_buf_pg_sz = 0;
+               caps->cqc_timer_hop_num   = HNS_ROCE_HOP_NUM_0;
+
                caps->sccc_entry_sz     = HNS_ROCE_V2_SCCC_ENTRY_SZ;
                caps->sccc_ba_pg_sz     = 0;
                caps->sccc_buf_pg_sz    = 0;
@@ -1644,7 +1700,8 @@ static void hns_roce_free_link_table(struct hns_roce_dev *hr_dev,
 static int hns_roce_v2_init(struct hns_roce_dev *hr_dev)
 {
        struct hns_roce_v2_priv *priv = hr_dev->priv;
-       int ret;
+       int qpc_count, cqc_count;
+       int ret, i;
 
        /* TSQ includes SQ doorbell and ack doorbell */
        ret = hns_roce_init_link_table(hr_dev, TSQ_LINK_TABLE);
@@ -1659,8 +1716,40 @@ static int hns_roce_v2_init(struct hns_roce_dev *hr_dev)
                goto err_tpq_init_failed;
        }
 
+       /* Alloc memory for QPC Timer buffer space chunk*/
+       for (qpc_count = 0; qpc_count < hr_dev->caps.qpc_timer_bt_num;
+            qpc_count++) {
+               ret = hns_roce_table_get(hr_dev, &hr_dev->qpc_timer_table,
+                                        qpc_count);
+               if (ret) {
+                       dev_err(hr_dev->dev, "QPC Timer get failed\n");
+                       goto err_qpc_timer_failed;
+               }
+       }
+
+       /* Alloc memory for CQC Timer buffer space chunk*/
+       for (cqc_count = 0; cqc_count < hr_dev->caps.cqc_timer_bt_num;
+            cqc_count++) {
+               ret = hns_roce_table_get(hr_dev, &hr_dev->cqc_timer_table,
+                                        cqc_count);
+               if (ret) {
+                       dev_err(hr_dev->dev, "CQC Timer get failed\n");
+                       goto err_cqc_timer_failed;
+               }
+       }
+
        return 0;
 
+err_cqc_timer_failed:
+       for (i = 0; i < cqc_count; i++)
+               hns_roce_table_put(hr_dev, &hr_dev->cqc_timer_table, i);
+
+err_qpc_timer_failed:
+       for (i = 0; i < qpc_count; i++)
+               hns_roce_table_put(hr_dev, &hr_dev->qpc_timer_table, i);
+
+       hns_roce_free_link_table(hr_dev, &priv->tpq);
+
 err_tpq_init_failed:
        hns_roce_free_link_table(hr_dev, &priv->tsq);
 
@@ -2699,6 +2788,12 @@ static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev,
        case HEM_TYPE_SCCC:
                op = HNS_ROCE_CMD_WRITE_SCCC_BT0;
                break;
+       case HEM_TYPE_QPC_TIMER:
+               op = HNS_ROCE_CMD_WRITE_QPC_TIMER_BT0;
+               break;
+       case HEM_TYPE_CQC_TIMER:
+               op = HNS_ROCE_CMD_WRITE_CQC_TIMER_BT0;
+               break;
        default:
                dev_warn(dev, "Table %d not to be written by mailbox!\n",
                         table->type);
@@ -2763,6 +2858,8 @@ static int hns_roce_v2_clear_hem(struct hns_roce_dev *hr_dev,
                op = HNS_ROCE_CMD_DESTROY_CQC_BT0;
                break;
        case HEM_TYPE_SCCC:
+       case HEM_TYPE_QPC_TIMER:
+       case HEM_TYPE_CQC_TIMER:
                break;
        case HEM_TYPE_SRQC:
                op = HNS_ROCE_CMD_DESTROY_SRQC_BT0;
@@ -2773,7 +2870,9 @@ static int hns_roce_v2_clear_hem(struct hns_roce_dev *hr_dev,
                return 0;
        }
 
-       if (table->type == HEM_TYPE_SCCC)
+       if (table->type == HEM_TYPE_SCCC ||
+           table->type == HEM_TYPE_QPC_TIMER ||
+           table->type == HEM_TYPE_CQC_TIMER)
                return 0;
 
        op += step_idx;
index 4da247d..242eeae 100644 (file)
 #define HNS_ROCE_VF_SL_NUM                     8
 
 #define HNS_ROCE_V2_MAX_QP_NUM                 0x2000
+#define HNS_ROCE_V2_MAX_QPC_TIMER_NUM          0x200
 #define HNS_ROCE_V2_MAX_WQE_NUM                        0x8000
 #define        HNS_ROCE_V2_MAX_SRQ                     0x100000
 #define HNS_ROCE_V2_MAX_SRQ_WR                 0x8000
 #define HNS_ROCE_V2_MAX_SRQ_SGE                        0x100
 #define HNS_ROCE_V2_MAX_CQ_NUM                 0x8000
+#define HNS_ROCE_V2_MAX_CQC_TIMER_NUM          0x100
 #define HNS_ROCE_V2_MAX_SRQ_NUM                        0x100000
 #define HNS_ROCE_V2_MAX_CQE_NUM                        0x10000
 #define HNS_ROCE_V2_MAX_SRQWQE_NUM             0x8000
@@ -85,6 +87,8 @@
 #define HNS_ROCE_V2_MTT_ENTRY_SZ               64
 #define HNS_ROCE_V2_CQE_ENTRY_SIZE             32
 #define HNS_ROCE_V2_SCCC_ENTRY_SZ              32
+#define HNS_ROCE_V2_QPC_TIMER_ENTRY_SZ         4096
+#define HNS_ROCE_V2_CQC_TIMER_ENTRY_SZ         4096
 #define HNS_ROCE_V2_PAGE_SIZE_SUPPORTED                0xFFFFF000
 #define HNS_ROCE_V2_MAX_INNER_MTPT_NUM         2
 #define HNS_ROCE_INVALID_LKEY                  0x100
@@ -229,6 +233,7 @@ enum hns_roce_opcode_type {
        HNS_ROCE_OPC_ALLOC_VF_RES                       = 0x8401,
        HNS_ROCE_OPC_CFG_EXT_LLM                        = 0x8403,
        HNS_ROCE_OPC_CFG_TMOUT_LLM                      = 0x8404,
+       HNS_ROCE_OPC_QUERY_PF_TIMER_RES                 = 0x8406,
        HNS_ROCE_OPC_CFG_SGID_TB                        = 0x8500,
        HNS_ROCE_OPC_CFG_SMAC_TB                        = 0x8501,
        HNS_ROCE_OPC_POST_MB                            = 0x8504,
@@ -1336,6 +1341,25 @@ struct hns_roce_pf_res_b {
 #define PF_RES_DATA_4_PF_SCCC_BT_NUM_S 9
 #define PF_RES_DATA_4_PF_SCCC_BT_NUM_M GENMASK(17, 9)
 
+struct hns_roce_pf_timer_res_a {
+       __le32  rsv0;
+       __le32  qpc_timer_bt_idx_num;
+       __le32  cqc_timer_bt_idx_num;
+       __le32  rsv[3];
+};
+
+#define PF_RES_DATA_1_PF_QPC_TIMER_BT_IDX_S 0
+#define PF_RES_DATA_1_PF_QPC_TIMER_BT_IDX_M GENMASK(11, 0)
+
+#define PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_S 16
+#define PF_RES_DATA_1_PF_QPC_TIMER_BT_NUM_M GENMASK(28, 16)
+
+#define PF_RES_DATA_2_PF_CQC_TIMER_BT_IDX_S 0
+#define PF_RES_DATA_2_PF_CQC_TIMER_BT_IDX_M GENMASK(10, 0)
+
+#define PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_S 16
+#define PF_RES_DATA_2_PF_CQC_TIMER_BT_NUM_M GENMASK(27, 16)
+
 struct hns_roce_vf_res_a {
        __le32 vf_id;
        __le32 vf_qpc_bt_idx_num;
index 3145866..67a8c43 100644 (file)
@@ -715,8 +715,44 @@ static int hns_roce_init_hem(struct hns_roce_dev *hr_dev)
                }
        }
 
+       if (hr_dev->caps.qpc_timer_entry_sz) {
+               ret = hns_roce_init_hem_table(hr_dev,
+                                             &hr_dev->qpc_timer_table,
+                                             HEM_TYPE_QPC_TIMER,
+                                             hr_dev->caps.qpc_timer_entry_sz,
+                                             hr_dev->caps.num_qpc_timer, 1);
+               if (ret) {
+                       dev_err(dev,
+                             "Failed to init QPC timer memory, aborting.\n");
+                       goto err_unmap_ctx;
+               }
+       }
+
+       if (hr_dev->caps.cqc_timer_entry_sz) {
+               ret = hns_roce_init_hem_table(hr_dev,
+                                             &hr_dev->cqc_timer_table,
+                                             HEM_TYPE_CQC_TIMER,
+                                             hr_dev->caps.cqc_timer_entry_sz,
+                                             hr_dev->caps.num_cqc_timer, 1);
+               if (ret) {
+                       dev_err(dev,
+                             "Failed to init CQC timer memory, aborting.\n");
+                       goto err_unmap_qpc_timer;
+               }
+       }
+
        return 0;
 
+err_unmap_qpc_timer:
+       if (hr_dev->caps.qpc_timer_entry_sz)
+               hns_roce_cleanup_hem_table(hr_dev,
+                                          &hr_dev->qpc_timer_table);
+
+err_unmap_ctx:
+       if (hr_dev->caps.sccc_entry_sz)
+               hns_roce_cleanup_hem_table(hr_dev,
+                                          &hr_dev->qp_table.sccc_table);
+
 err_unmap_idx:
        if (hr_dev->caps.num_idx_segs)
                hns_roce_cleanup_hem_table(hr_dev,