RDMA/hns: Optimize mhop put flow for multi-hop addressing
authorXi Wang <wangxi11@huawei.com>
Tue, 17 Mar 2020 03:55:24 +0000 (11:55 +0800)
committerJason Gunthorpe <jgg@mellanox.com>
Tue, 24 Mar 2020 23:18:56 +0000 (20:18 -0300)
Optimizes hns_roce_table_mhop_get() by encapsulating code about clearing
hem into clear_mhop_hem(), which will make the code flow clearer.

Link: https://lore.kernel.org/r/1584417324-2255-3-git-send-email-liweihang@huawei.com
Signed-off-by: Xi Wang <wangxi11@huawei.com>
Signed-off-by: Weihang Li <liweihang@huawei.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/hns/hns_roce_hem.c

index cc557f1..c963787 100644 (file)
@@ -94,25 +94,27 @@ bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type)
        return hop_num ? true : false;
 }
 
-static bool hns_roce_check_hem_null(struct hns_roce_hem **hem, u64 start_idx,
-                           u32 bt_chunk_num, u64 hem_max_num)
+static bool hns_roce_check_hem_null(struct hns_roce_hem **hem, u64 hem_idx,
+                                   u32 bt_chunk_num, u64 hem_max_num)
 {
+       u64 start_idx = round_down(hem_idx, bt_chunk_num);
        u64 check_max_num = start_idx + bt_chunk_num;
        u64 i;
 
        for (i = start_idx; (i < check_max_num) && (i < hem_max_num); i++)
-               if (hem[i])
+               if (i != hem_idx && hem[i])
                        return false;
 
        return true;
 }
 
-static bool hns_roce_check_bt_null(u64 **bt, u64 start_idx, u32 bt_chunk_num)
+static bool hns_roce_check_bt_null(u64 **bt, u64 ba_idx, u32 bt_chunk_num)
 {
+       u64 start_idx = round_down(ba_idx, bt_chunk_num);
        int i;
 
        for (i = 0; i < bt_chunk_num; i++)
-               if (bt[start_idx + i])
+               if (i != ba_idx && bt[start_idx + i])
                        return false;
 
        return true;
@@ -723,116 +725,75 @@ out:
        return ret;
 }
 
+static void clear_mhop_hem(struct hns_roce_dev *hr_dev,
+                          struct hns_roce_hem_table *table, unsigned long obj,
+                          struct hns_roce_hem_mhop *mhop,
+                          struct hns_roce_hem_index *index)
+{
+       struct ib_device *ibdev = &hr_dev->ib_dev;
+       u32 hop_num = mhop->hop_num;
+       u32 chunk_ba_num;
+       int step_idx;
+
+       index->inited = HEM_INDEX_BUF;
+       chunk_ba_num = mhop->bt_chunk_size / BA_BYTE_LEN;
+       if (check_whether_bt_num_2(table->type, hop_num)) {
+               if (hns_roce_check_hem_null(table->hem, index->buf,
+                                           chunk_ba_num, table->num_hem))
+                       index->inited |= HEM_INDEX_L0;
+       } else if (check_whether_bt_num_3(table->type, hop_num)) {
+               if (hns_roce_check_hem_null(table->hem, index->buf,
+                                           chunk_ba_num, table->num_hem)) {
+                       index->inited |= HEM_INDEX_L1;
+                       if (hns_roce_check_bt_null(table->bt_l1, index->l1,
+                                                  chunk_ba_num))
+                               index->inited |= HEM_INDEX_L0;
+               }
+       }
+
+       if (table->type < HEM_TYPE_MTT) {
+               if (hop_num == HNS_ROCE_HOP_NUM_0)
+                       step_idx = 0;
+               else
+                       step_idx = hop_num;
+
+               if (hr_dev->hw->clear_hem(hr_dev, table, obj, step_idx))
+                       ibdev_warn(ibdev, "Clear hop%d HEM failed.\n", hop_num);
+
+               if (index->inited & HEM_INDEX_L1)
+                       if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
+                               ibdev_warn(ibdev, "Clear HEM step 1 failed.\n");
+
+               if (index->inited & HEM_INDEX_L0)
+                       if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
+                               ibdev_warn(ibdev, "Clear HEM step 0 failed.\n");
+       }
+}
+
 static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
                                    struct hns_roce_hem_table *table,
                                    unsigned long obj,
                                    int check_refcount)
 {
-       struct device *dev = hr_dev->dev;
-       struct hns_roce_hem_mhop mhop;
-       unsigned long mhop_obj = obj;
-       u32 bt_chunk_size;
-       u32 chunk_ba_num;
-       u32 hop_num;
-       u32 start_idx;
-       u32 bt_num;
-       u64 hem_idx;
-       u64 bt_l1_idx = 0;
+       struct ib_device *ibdev = &hr_dev->ib_dev;
+       struct hns_roce_hem_index index = {};
+       struct hns_roce_hem_mhop mhop = {};
        int ret;
 
-       ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
-       if (ret)
-               return;
-
-       bt_chunk_size = mhop.bt_chunk_size;
-       hop_num = mhop.hop_num;
-       chunk_ba_num = bt_chunk_size / BA_BYTE_LEN;
-
-       bt_num = hns_roce_get_bt_num(table->type, hop_num);
-       switch (bt_num) {
-       case 3:
-               hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
-                         mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
-               bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
-               break;
-       case 2:
-               hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
-               break;
-       case 1:
-               hem_idx = mhop.l0_idx;
-               break;
-       default:
-               dev_err(dev, "Table %d not support hop_num = %d!\n",
-                            table->type, hop_num);
+       ret = calc_hem_config(hr_dev, table, obj, &mhop, &index);
+       if (ret) {
+               ibdev_err(ibdev, "calc hem config failed!\n");
                return;
        }
 
        mutex_lock(&table->mutex);
-
-       if (check_refcount && (--table->hem[hem_idx]->refcount > 0)) {
+       if (check_refcount && (--table->hem[index.buf]->refcount > 0)) {
                mutex_unlock(&table->mutex);
                return;
        }
 
-       if (table->type < HEM_TYPE_MTT && hop_num == 1) {
-               if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
-                       dev_warn(dev, "Clear HEM base address failed.\n");
-       } else if (table->type < HEM_TYPE_MTT && hop_num == 2) {
-               if (hr_dev->hw->clear_hem(hr_dev, table, obj, 2))
-                       dev_warn(dev, "Clear HEM base address failed.\n");
-       } else if (table->type < HEM_TYPE_MTT &&
-                  hop_num == HNS_ROCE_HOP_NUM_0) {
-               if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
-                       dev_warn(dev, "Clear HEM base address failed.\n");
-       }
-
-       /*
-        * free buffer space chunk for QPC/MTPT/CQC/SRQC/SCCC.
-        * free bt space chunk for MTT/CQE.
-        */
-       hns_roce_free_hem(hr_dev, table->hem[hem_idx]);
-       table->hem[hem_idx] = NULL;
-
-       if (check_whether_bt_num_2(table->type, hop_num)) {
-               start_idx = mhop.l0_idx * chunk_ba_num;
-               if (hns_roce_check_hem_null(table->hem, start_idx,
-                                           chunk_ba_num, table->num_hem)) {
-                       if (table->type < HEM_TYPE_MTT &&
-                           hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
-                               dev_warn(dev, "Clear HEM base address failed.\n");
-
-                       dma_free_coherent(dev, bt_chunk_size,
-                                         table->bt_l0[mhop.l0_idx],
-                                         table->bt_l0_dma_addr[mhop.l0_idx]);
-                       table->bt_l0[mhop.l0_idx] = NULL;
-               }
-       } else if (check_whether_bt_num_3(table->type, hop_num)) {
-               start_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
-                           mhop.l1_idx * chunk_ba_num;
-               if (hns_roce_check_hem_null(table->hem, start_idx,
-                                           chunk_ba_num, table->num_hem)) {
-                       if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
-                               dev_warn(dev, "Clear HEM base address failed.\n");
-
-                       dma_free_coherent(dev, bt_chunk_size,
-                                         table->bt_l1[bt_l1_idx],
-                                         table->bt_l1_dma_addr[bt_l1_idx]);
-                       table->bt_l1[bt_l1_idx] = NULL;
-
-                       start_idx = mhop.l0_idx * chunk_ba_num;
-                       if (hns_roce_check_bt_null(table->bt_l1, start_idx,
-                                                  chunk_ba_num)) {
-                               if (hr_dev->hw->clear_hem(hr_dev, table, obj,
-                                                         0))
-                                       dev_warn(dev, "Clear HEM base address failed.\n");
-
-                               dma_free_coherent(dev, bt_chunk_size,
-                                           table->bt_l0[mhop.l0_idx],
-                                           table->bt_l0_dma_addr[mhop.l0_idx]);
-                               table->bt_l0[mhop.l0_idx] = NULL;
-                       }
-               }
-       }
+       clear_mhop_hem(hr_dev, table, obj, &mhop, &index);
+       free_mhop_hem(hr_dev, table, &mhop, &index);
 
        mutex_unlock(&table->mutex);
 }