RDMA/hns: Configure BT BA and BT attribute for the contexts in hip08
authorWei Hu(Xavier) <xavier.huwei@huawei.com>
Wed, 30 Aug 2017 09:23:07 +0000 (17:23 +0800)
committerDoug Ledford <dledford@redhat.com>
Wed, 27 Sep 2017 12:34:56 +0000 (08:34 -0400)
BT is used to retrieve the addresses of the contexts(QPC/MPT/CQC/SRQC)
in memory. In order to support multi hop addressing for the contexts,
the BT BA should be configured by mailbox, and the BT attribution will
be set by command.

This patch is to configure the BT BA and BT attribution for the
contexts.

Signed-off-by: Shaobo Xu <xushaobo2@huawei.com>
Signed-off-by: Lijun Ou <oulijun@huawei.com>
Signed-off-by: Wei Hu (Xavier) <xavier.huwei@huawei.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/hns/hns_roce_cmd.h
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.h

index f5a9ee2fc53d9334769bec285dd3c28de06e1b4d..fc400698af1b5501d1b02608b8e6ce9f9a21ca44 100644 (file)
 #define HNS_ROCE_MAILBOX_SIZE          4096
 #define HNS_ROCE_CMD_TIMEOUT_MSECS     10000
 
+enum {
+       /* QPC BT commands */
+       HNS_ROCE_CMD_WRITE_QPC_BT0      = 0x0,
+       HNS_ROCE_CMD_WRITE_QPC_BT1      = 0x1,
+       HNS_ROCE_CMD_WRITE_QPC_BT2      = 0x2,
+       HNS_ROCE_CMD_READ_QPC_BT0       = 0x4,
+       HNS_ROCE_CMD_READ_QPC_BT1       = 0x5,
+       HNS_ROCE_CMD_READ_QPC_BT2       = 0x6,
+       HNS_ROCE_CMD_DESTROY_QPC_BT0    = 0x8,
+       HNS_ROCE_CMD_DESTROY_QPC_BT1    = 0x9,
+       HNS_ROCE_CMD_DESTROY_QPC_BT2    = 0xa,
+
+       /* CQC BT commands */
+       HNS_ROCE_CMD_WRITE_CQC_BT0      = 0x10,
+       HNS_ROCE_CMD_WRITE_CQC_BT1      = 0x11,
+       HNS_ROCE_CMD_WRITE_CQC_BT2      = 0x12,
+       HNS_ROCE_CMD_READ_CQC_BT0       = 0x14,
+       HNS_ROCE_CMD_READ_CQC_BT1       = 0x15,
+       HNS_ROCE_CMD_READ_CQC_BT2       = 0x1b,
+       HNS_ROCE_CMD_DESTROY_CQC_BT0    = 0x18,
+       HNS_ROCE_CMD_DESTROY_CQC_BT1    = 0x19,
+       HNS_ROCE_CMD_DESTROY_CQC_BT2    = 0x1a,
+
+       /* MPT BT commands */
+       HNS_ROCE_CMD_WRITE_MPT_BT0      = 0x20,
+       HNS_ROCE_CMD_WRITE_MPT_BT1      = 0x21,
+       HNS_ROCE_CMD_WRITE_MPT_BT2      = 0x22,
+       HNS_ROCE_CMD_READ_MPT_BT0       = 0x24,
+       HNS_ROCE_CMD_READ_MPT_BT1       = 0x25,
+       HNS_ROCE_CMD_READ_MPT_BT2       = 0x26,
+       HNS_ROCE_CMD_DESTROY_MPT_BT0    = 0x28,
+       HNS_ROCE_CMD_DESTROY_MPT_BT1    = 0x29,
+       HNS_ROCE_CMD_DESTROY_MPT_BT2    = 0x2a,
+
+       /* SRQC BT commands */
+       HNS_ROCE_CMD_WRITE_SRQC_BT0     = 0x30,
+       HNS_ROCE_CMD_WRITE_SRQC_BT1     = 0x31,
+       HNS_ROCE_CMD_WRITE_SRQC_BT2     = 0x32,
+       HNS_ROCE_CMD_READ_SRQC_BT0      = 0x34,
+       HNS_ROCE_CMD_READ_SRQC_BT1      = 0x35,
+       HNS_ROCE_CMD_READ_SRQC_BT2      = 0x36,
+       HNS_ROCE_CMD_DESTROY_SRQC_BT0   = 0x38,
+       HNS_ROCE_CMD_DESTROY_SRQC_BT1   = 0x39,
+       HNS_ROCE_CMD_DESTROY_SRQC_BT2   = 0x3a,
+};
+
 enum {
        /* TPT commands */
        HNS_ROCE_CMD_SW2HW_MPT          = 0xd,
index 5127edcec834b37e27957370c54cae149ce4fb3e..77cf476d609618b37c9d3eebbd5a84db4a4efe62 100644 (file)
@@ -475,6 +475,62 @@ static int hns_roce_alloc_vf_resource(struct hns_roce_dev *hr_dev)
        return hns_roce_cmq_send(hr_dev, desc, 2);
 }
 
+static int hns_roce_v2_set_bt(struct hns_roce_dev *hr_dev)
+{
+       u8 srqc_hop_num = hr_dev->caps.srqc_hop_num;
+       u8 qpc_hop_num = hr_dev->caps.qpc_hop_num;
+       u8 cqc_hop_num = hr_dev->caps.cqc_hop_num;
+       u8 mpt_hop_num = hr_dev->caps.mpt_hop_num;
+       struct hns_roce_cfg_bt_attr *req;
+       struct hns_roce_cmq_desc desc;
+
+       hns_roce_cmq_setup_basic_desc(&desc, HNS_ROCE_OPC_CFG_BT_ATTR, false);
+       req = (struct hns_roce_cfg_bt_attr *)desc.data;
+       memset(req, 0, sizeof(*req));
+
+       roce_set_field(req->vf_qpc_cfg, CFG_BT_ATTR_DATA_0_VF_QPC_BA_PGSZ_M,
+                      CFG_BT_ATTR_DATA_0_VF_QPC_BA_PGSZ_S,
+                      hr_dev->caps.qpc_ba_pg_sz);
+       roce_set_field(req->vf_qpc_cfg, CFG_BT_ATTR_DATA_0_VF_QPC_BUF_PGSZ_M,
+                      CFG_BT_ATTR_DATA_0_VF_QPC_BUF_PGSZ_S,
+                      hr_dev->caps.qpc_buf_pg_sz);
+       roce_set_field(req->vf_qpc_cfg, CFG_BT_ATTR_DATA_0_VF_QPC_HOPNUM_M,
+                      CFG_BT_ATTR_DATA_0_VF_QPC_HOPNUM_S,
+                      qpc_hop_num == HNS_ROCE_HOP_NUM_0 ? 0 : qpc_hop_num);
+
+       roce_set_field(req->vf_srqc_cfg, CFG_BT_ATTR_DATA_1_VF_SRQC_BA_PGSZ_M,
+                      CFG_BT_ATTR_DATA_1_VF_SRQC_BA_PGSZ_S,
+                      hr_dev->caps.srqc_ba_pg_sz);
+       roce_set_field(req->vf_srqc_cfg, CFG_BT_ATTR_DATA_1_VF_SRQC_BUF_PGSZ_M,
+                      CFG_BT_ATTR_DATA_1_VF_SRQC_BUF_PGSZ_S,
+                      hr_dev->caps.srqc_buf_pg_sz);
+       roce_set_field(req->vf_srqc_cfg, CFG_BT_ATTR_DATA_1_VF_SRQC_HOPNUM_M,
+                      CFG_BT_ATTR_DATA_1_VF_SRQC_HOPNUM_S,
+                      srqc_hop_num == HNS_ROCE_HOP_NUM_0 ? 0 : srqc_hop_num);
+
+       roce_set_field(req->vf_cqc_cfg, CFG_BT_ATTR_DATA_2_VF_CQC_BA_PGSZ_M,
+                      CFG_BT_ATTR_DATA_2_VF_CQC_BA_PGSZ_S,
+                      hr_dev->caps.cqc_ba_pg_sz);
+       roce_set_field(req->vf_cqc_cfg, CFG_BT_ATTR_DATA_2_VF_CQC_BUF_PGSZ_M,
+                      CFG_BT_ATTR_DATA_2_VF_CQC_BUF_PGSZ_S,
+                      hr_dev->caps.cqc_buf_pg_sz);
+       roce_set_field(req->vf_cqc_cfg, CFG_BT_ATTR_DATA_2_VF_CQC_HOPNUM_M,
+                      CFG_BT_ATTR_DATA_2_VF_CQC_HOPNUM_S,
+                      cqc_hop_num == HNS_ROCE_HOP_NUM_0 ? 0 : cqc_hop_num);
+
+       roce_set_field(req->vf_mpt_cfg, CFG_BT_ATTR_DATA_3_VF_MPT_BA_PGSZ_M,
+                      CFG_BT_ATTR_DATA_3_VF_MPT_BA_PGSZ_S,
+                      hr_dev->caps.mpt_ba_pg_sz);
+       roce_set_field(req->vf_mpt_cfg, CFG_BT_ATTR_DATA_3_VF_MPT_BUF_PGSZ_M,
+                      CFG_BT_ATTR_DATA_3_VF_MPT_BUF_PGSZ_S,
+                      hr_dev->caps.mpt_buf_pg_sz);
+       roce_set_field(req->vf_mpt_cfg, CFG_BT_ATTR_DATA_3_VF_MPT_HOPNUM_M,
+                      CFG_BT_ATTR_DATA_3_VF_MPT_HOPNUM_S,
+                      mpt_hop_num == HNS_ROCE_HOP_NUM_0 ? 0 : mpt_hop_num);
+
+       return hns_roce_cmq_send(hr_dev, &desc, 1);
+}
+
 static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
 {
        struct hns_roce_caps *caps = &hr_dev->caps;
@@ -563,7 +619,12 @@ static int hns_roce_v2_profile(struct hns_roce_dev *hr_dev)
        caps->local_ca_ack_delay = 0;
        caps->max_mtu = IB_MTU_4096;
 
-       return 0;
+       ret = hns_roce_v2_set_bt(hr_dev);
+       if (ret)
+               dev_err(hr_dev->dev, "Configure bt attribute fail, ret = %d.\n",
+                       ret);
+
+       return ret;
 }
 
 static int hns_roce_v2_cmd_pending(struct hns_roce_dev *hr_dev)
@@ -648,12 +709,147 @@ static int hns_roce_v2_chk_mbox(struct hns_roce_dev *hr_dev,
        return 0;
 }
 
+static int hns_roce_v2_set_hem(struct hns_roce_dev *hr_dev,
+                              struct hns_roce_hem_table *table, int obj,
+                              int step_idx)
+{
+       struct device *dev = hr_dev->dev;
+       struct hns_roce_cmd_mailbox *mailbox;
+       struct hns_roce_hem_iter iter;
+       struct hns_roce_hem_mhop mhop;
+       struct hns_roce_hem *hem;
+       unsigned long mhop_obj = obj;
+       int i, j, k;
+       int ret = 0;
+       u64 hem_idx = 0;
+       u64 l1_idx = 0;
+       u64 bt_ba = 0;
+       u32 chunk_ba_num;
+       u32 hop_num;
+       u16 op = 0xff;
+
+       if (!hns_roce_check_whether_mhop(hr_dev, table->type))
+               return 0;
+
+       hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
+       i = mhop.l0_idx;
+       j = mhop.l1_idx;
+       k = mhop.l2_idx;
+       hop_num = mhop.hop_num;
+       chunk_ba_num = mhop.bt_chunk_size / 8;
+
+       if (hop_num == 2) {
+               hem_idx = i * chunk_ba_num * chunk_ba_num + j * chunk_ba_num +
+                         k;
+               l1_idx = i * chunk_ba_num + j;
+       } else if (hop_num == 1) {
+               hem_idx = i * chunk_ba_num + j;
+       } else if (hop_num == HNS_ROCE_HOP_NUM_0) {
+               hem_idx = i;
+       }
+
+       switch (table->type) {
+       case HEM_TYPE_QPC:
+               op = HNS_ROCE_CMD_WRITE_QPC_BT0;
+               break;
+       case HEM_TYPE_MTPT:
+               op = HNS_ROCE_CMD_WRITE_MPT_BT0;
+               break;
+       case HEM_TYPE_CQC:
+               op = HNS_ROCE_CMD_WRITE_CQC_BT0;
+               break;
+       case HEM_TYPE_SRQC:
+               op = HNS_ROCE_CMD_WRITE_SRQC_BT0;
+               break;
+       default:
+               dev_warn(dev, "Table %d not to be written by mailbox!\n",
+                        table->type);
+               return 0;
+       }
+       op += step_idx;
+
+       mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+
+       if (check_whether_last_step(hop_num, step_idx)) {
+               hem = table->hem[hem_idx];
+               for (hns_roce_hem_first(hem, &iter);
+                    !hns_roce_hem_last(&iter); hns_roce_hem_next(&iter)) {
+                       bt_ba = hns_roce_hem_addr(&iter);
+
+                       /* configure the ba, tag, and op */
+                       ret = hns_roce_cmd_mbox(hr_dev, bt_ba, mailbox->dma,
+                                               obj, 0, op,
+                                               HNS_ROCE_CMD_TIMEOUT_MSECS);
+               }
+       } else {
+               if (step_idx == 0)
+                       bt_ba = table->bt_l0_dma_addr[i];
+               else if (step_idx == 1 && hop_num == 2)
+                       bt_ba = table->bt_l1_dma_addr[l1_idx];
+
+               /* configure the ba, tag, and op */
+               ret = hns_roce_cmd_mbox(hr_dev, bt_ba, mailbox->dma, obj,
+                                       0, op, HNS_ROCE_CMD_TIMEOUT_MSECS);
+       }
+
+       hns_roce_free_cmd_mailbox(hr_dev, mailbox);
+       return ret;
+}
+
+static int hns_roce_v2_clear_hem(struct hns_roce_dev *hr_dev,
+                                struct hns_roce_hem_table *table, int obj,
+                                int step_idx)
+{
+       struct device *dev = hr_dev->dev;
+       struct hns_roce_cmd_mailbox *mailbox;
+       int ret = 0;
+       u16 op = 0xff;
+
+       if (!hns_roce_check_whether_mhop(hr_dev, table->type))
+               return 0;
+
+       switch (table->type) {
+       case HEM_TYPE_QPC:
+               op = HNS_ROCE_CMD_DESTROY_QPC_BT0;
+               break;
+       case HEM_TYPE_MTPT:
+               op = HNS_ROCE_CMD_DESTROY_MPT_BT0;
+               break;
+       case HEM_TYPE_CQC:
+               op = HNS_ROCE_CMD_DESTROY_CQC_BT0;
+               break;
+       case HEM_TYPE_SRQC:
+               op = HNS_ROCE_CMD_DESTROY_SRQC_BT0;
+               break;
+       default:
+               dev_warn(dev, "Table %d not to be destroyed by mailbox!\n",
+                        table->type);
+               return 0;
+       }
+       op += step_idx;
+
+       mailbox = hns_roce_alloc_cmd_mailbox(hr_dev);
+       if (IS_ERR(mailbox))
+               return PTR_ERR(mailbox);
+
+       /* configure the tag and op */
+       ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, obj, 0, op,
+                               HNS_ROCE_CMD_TIMEOUT_MSECS);
+
+       hns_roce_free_cmd_mailbox(hr_dev, mailbox);
+       return ret;
+}
+
 static const struct hns_roce_hw hns_roce_hw_v2 = {
        .cmq_init = hns_roce_v2_cmq_init,
        .cmq_exit = hns_roce_v2_cmq_exit,
        .hw_profile = hns_roce_v2_profile,
        .post_mbox = hns_roce_v2_post_mbox,
        .chk_mbox = hns_roce_v2_chk_mbox,
+       .set_hem = hns_roce_v2_set_hem,
+       .clear_hem = hns_roce_v2_clear_hem,
 };
 
 static const struct pci_device_id hns_roce_hw_v2_pci_tbl[] = {
index 91f5161f3411cf3380158e6ffa10636559c85b5d..cc8c8d05d6992bc00459d0d4e7644c6b99233006 100644 (file)
 #define HNS_ROCE_CMQ_EN_B              16
 #define HNS_ROCE_CMQ_ENABLE            BIT(HNS_ROCE_CMQ_EN_B)
 
+#define check_whether_last_step(hop_num, step_idx) \
+       ((step_idx == 0 && hop_num == HNS_ROCE_HOP_NUM_0) || \
+       (step_idx == 1 && hop_num == 1) || \
+       (step_idx == 2 && hop_num == 2))
+
 /* CMQ command */
 enum hns_roce_opcode_type {
        HNS_ROCE_OPC_QUERY_HW_VER                       = 0x8000,
@@ -239,6 +244,50 @@ struct hns_roce_vf_res_b {
 #define VF_RES_B_DATA_3_VF_SL_NUM_S 16
 #define VF_RES_B_DATA_3_VF_SL_NUM_M GENMASK(19, 16)
 
+struct hns_roce_cfg_bt_attr {
+       u32 vf_qpc_cfg;
+       u32 vf_srqc_cfg;
+       u32 vf_cqc_cfg;
+       u32 vf_mpt_cfg;
+       u32 rsv[2];
+};
+
+#define CFG_BT_ATTR_DATA_0_VF_QPC_BA_PGSZ_S 0
+#define CFG_BT_ATTR_DATA_0_VF_QPC_BA_PGSZ_M GENMASK(3, 0)
+
+#define CFG_BT_ATTR_DATA_0_VF_QPC_BUF_PGSZ_S 4
+#define CFG_BT_ATTR_DATA_0_VF_QPC_BUF_PGSZ_M GENMASK(7, 4)
+
+#define CFG_BT_ATTR_DATA_0_VF_QPC_HOPNUM_S 8
+#define CFG_BT_ATTR_DATA_0_VF_QPC_HOPNUM_M GENMASK(9, 8)
+
+#define CFG_BT_ATTR_DATA_1_VF_SRQC_BA_PGSZ_S 0
+#define CFG_BT_ATTR_DATA_1_VF_SRQC_BA_PGSZ_M GENMASK(3, 0)
+
+#define CFG_BT_ATTR_DATA_1_VF_SRQC_BUF_PGSZ_S 4
+#define CFG_BT_ATTR_DATA_1_VF_SRQC_BUF_PGSZ_M GENMASK(7, 4)
+
+#define CFG_BT_ATTR_DATA_1_VF_SRQC_HOPNUM_S 8
+#define CFG_BT_ATTR_DATA_1_VF_SRQC_HOPNUM_M GENMASK(9, 8)
+
+#define CFG_BT_ATTR_DATA_2_VF_CQC_BA_PGSZ_S 0
+#define CFG_BT_ATTR_DATA_2_VF_CQC_BA_PGSZ_M GENMASK(3, 0)
+
+#define CFG_BT_ATTR_DATA_2_VF_CQC_BUF_PGSZ_S 4
+#define CFG_BT_ATTR_DATA_2_VF_CQC_BUF_PGSZ_M GENMASK(7, 4)
+
+#define CFG_BT_ATTR_DATA_2_VF_CQC_HOPNUM_S 8
+#define CFG_BT_ATTR_DATA_2_VF_CQC_HOPNUM_M GENMASK(9, 8)
+
+#define CFG_BT_ATTR_DATA_3_VF_MPT_BA_PGSZ_S 0
+#define CFG_BT_ATTR_DATA_3_VF_MPT_BA_PGSZ_M GENMASK(3, 0)
+
+#define CFG_BT_ATTR_DATA_3_VF_MPT_BUF_PGSZ_S 4
+#define CFG_BT_ATTR_DATA_3_VF_MPT_BUF_PGSZ_M GENMASK(7, 4)
+
+#define CFG_BT_ATTR_DATA_3_VF_MPT_HOPNUM_S 8
+#define CFG_BT_ATTR_DATA_3_VF_MPT_HOPNUM_M GENMASK(9, 8)
+
 struct hns_roce_cmq_desc {
        u16 opcode;
        u16 flag;