linux/drivers/infiniband/hw/hns/hns_roce_hem.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 Hisilicon Limited.
   3 * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
   4 *
   5 * This software is available to you under a choice of one of two
   6 * licenses.  You may choose to be licensed under the terms of the GNU
   7 * General Public License (GPL) Version 2, available from the file
   8 * COPYING in the main directory of this source tree, or the
   9 * OpenIB.org BSD license below:
  10 *
  11 *     Redistribution and use in source and binary forms, with or
  12 *     without modification, are permitted provided that the following
  13 *     conditions are met:
  14 *
  15 *      - Redistributions of source code must retain the above
  16 *        copyright notice, this list of conditions and the following
  17 *        disclaimer.
  18 *
  19 *      - Redistributions in binary form must reproduce the above
  20 *        copyright notice, this list of conditions and the following
  21 *        disclaimer in the documentation and/or other materials
  22 *        provided with the distribution.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31 * SOFTWARE.
  32 */
  33
  34#include <linux/platform_device.h>
  35#include "hns_roce_device.h"
  36#include "hns_roce_hem.h"
  37#include "hns_roce_common.h"
  38
  39#define DMA_ADDR_T_SHIFT                12
  40#define BT_BA_SHIFT                     32
  41
  42bool hns_roce_check_whether_mhop(struct hns_roce_dev *hr_dev, u32 type)
  43{
  44        if ((hr_dev->caps.qpc_hop_num && type == HEM_TYPE_QPC) ||
  45            (hr_dev->caps.mpt_hop_num && type == HEM_TYPE_MTPT) ||
  46            (hr_dev->caps.cqc_hop_num && type == HEM_TYPE_CQC) ||
  47            (hr_dev->caps.srqc_hop_num && type == HEM_TYPE_SRQC) ||
  48            (hr_dev->caps.cqe_hop_num && type == HEM_TYPE_CQE) ||
  49            (hr_dev->caps.mtt_hop_num && type == HEM_TYPE_MTT))
  50                return true;
  51
  52        return false;
  53}
  54EXPORT_SYMBOL_GPL(hns_roce_check_whether_mhop);
  55
  56static bool hns_roce_check_hem_null(struct hns_roce_hem **hem, u64 start_idx,
  57                            u32 bt_chunk_num)
  58{
  59        int i;
  60
  61        for (i = 0; i < bt_chunk_num; i++)
  62                if (hem[start_idx + i])
  63                        return false;
  64
  65        return true;
  66}
  67
  68static bool hns_roce_check_bt_null(u64 **bt, u64 start_idx, u32 bt_chunk_num)
  69{
  70        int i;
  71
  72        for (i = 0; i < bt_chunk_num; i++)
  73                if (bt[start_idx + i])
  74                        return false;
  75
  76        return true;
  77}
  78
  79static int hns_roce_get_bt_num(u32 table_type, u32 hop_num)
  80{
  81        if (check_whether_bt_num_3(table_type, hop_num))
  82                return 3;
  83        else if (check_whether_bt_num_2(table_type, hop_num))
  84                return 2;
  85        else if (check_whether_bt_num_1(table_type, hop_num))
  86                return 1;
  87        else
  88                return 0;
  89}
  90
  91int hns_roce_calc_hem_mhop(struct hns_roce_dev *hr_dev,
  92                           struct hns_roce_hem_table *table, unsigned long *obj,
  93                           struct hns_roce_hem_mhop *mhop)
  94{
  95        struct device *dev = hr_dev->dev;
  96        u32 chunk_ba_num;
  97        u32 table_idx;
  98        u32 bt_num;
  99        u32 chunk_size;
 100
 101        switch (table->type) {
 102        case HEM_TYPE_QPC:
 103                mhop->buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz
 104                                             + PAGE_SHIFT);
 105                mhop->bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz
 106                                             + PAGE_SHIFT);
 107                mhop->ba_l0_num = hr_dev->caps.qpc_bt_num;
 108                mhop->hop_num = hr_dev->caps.qpc_hop_num;
 109                break;
 110        case HEM_TYPE_MTPT:
 111                mhop->buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz
 112                                             + PAGE_SHIFT);
 113                mhop->bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz
 114                                             + PAGE_SHIFT);
 115                mhop->ba_l0_num = hr_dev->caps.mpt_bt_num;
 116                mhop->hop_num = hr_dev->caps.mpt_hop_num;
 117                break;
 118        case HEM_TYPE_CQC:
 119                mhop->buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz
 120                                             + PAGE_SHIFT);
 121                mhop->bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz
 122                                            + PAGE_SHIFT);
 123                mhop->ba_l0_num = hr_dev->caps.cqc_bt_num;
 124                mhop->hop_num = hr_dev->caps.cqc_hop_num;
 125                break;
 126        case HEM_TYPE_SRQC:
 127                mhop->buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
 128                                             + PAGE_SHIFT);
 129                mhop->bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz
 130                                             + PAGE_SHIFT);
 131                mhop->ba_l0_num = hr_dev->caps.srqc_bt_num;
 132                mhop->hop_num = hr_dev->caps.srqc_hop_num;
 133                break;
 134        case HEM_TYPE_MTT:
 135                mhop->buf_chunk_size = 1 << (hr_dev->caps.mtt_buf_pg_sz
 136                                             + PAGE_SHIFT);
 137                mhop->bt_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz
 138                                             + PAGE_SHIFT);
 139                mhop->ba_l0_num = mhop->bt_chunk_size / 8;
 140                mhop->hop_num = hr_dev->caps.mtt_hop_num;
 141                break;
 142        case HEM_TYPE_CQE:
 143                mhop->buf_chunk_size = 1 << (hr_dev->caps.cqe_buf_pg_sz
 144                                             + PAGE_SHIFT);
 145                mhop->bt_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz
 146                                             + PAGE_SHIFT);
 147                mhop->ba_l0_num = mhop->bt_chunk_size / 8;
 148                mhop->hop_num = hr_dev->caps.cqe_hop_num;
 149                break;
 150        default:
 151                dev_err(dev, "Table %d not support multi-hop addressing!\n",
 152                         table->type);
 153                return -EINVAL;
 154        }
 155
 156        if (!obj)
 157                return 0;
 158
 159        /*
 160         * QPC/MTPT/CQC/SRQC alloc hem for buffer pages.
 161         * MTT/CQE alloc hem for bt pages.
 162         */
 163        bt_num = hns_roce_get_bt_num(table->type, mhop->hop_num);
 164        chunk_ba_num = mhop->bt_chunk_size / 8;
 165        chunk_size = table->type < HEM_TYPE_MTT ? mhop->buf_chunk_size :
 166                              mhop->bt_chunk_size;
 167        table_idx = (*obj & (table->num_obj - 1)) /
 168                     (chunk_size / table->obj_size);
 169        switch (bt_num) {
 170        case 3:
 171                mhop->l2_idx = table_idx & (chunk_ba_num - 1);
 172                mhop->l1_idx = table_idx / chunk_ba_num & (chunk_ba_num - 1);
 173                mhop->l0_idx = table_idx / chunk_ba_num / chunk_ba_num;
 174                break;
 175        case 2:
 176                mhop->l1_idx = table_idx & (chunk_ba_num - 1);
 177                mhop->l0_idx = table_idx / chunk_ba_num;
 178                break;
 179        case 1:
 180                mhop->l0_idx = table_idx;
 181                break;
 182        default:
 183                dev_err(dev, "Table %d not support hop_num = %d!\n",
 184                             table->type, mhop->hop_num);
 185                return -EINVAL;
 186        }
 187        if (mhop->l0_idx >= mhop->ba_l0_num)
 188                mhop->l0_idx %= mhop->ba_l0_num;
 189
 190        return 0;
 191}
 192EXPORT_SYMBOL_GPL(hns_roce_calc_hem_mhop);
 193
 194static struct hns_roce_hem *hns_roce_alloc_hem(struct hns_roce_dev *hr_dev,
 195                                               int npages,
 196                                               unsigned long hem_alloc_size,
 197                                               gfp_t gfp_mask)
 198{
 199        struct hns_roce_hem_chunk *chunk = NULL;
 200        struct hns_roce_hem *hem;
 201        struct scatterlist *mem;
 202        int order;
 203        void *buf;
 204
 205        WARN_ON(gfp_mask & __GFP_HIGHMEM);
 206
 207        hem = kmalloc(sizeof(*hem),
 208                      gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
 209        if (!hem)
 210                return NULL;
 211
 212        hem->refcount = 0;
 213        INIT_LIST_HEAD(&hem->chunk_list);
 214
 215        order = get_order(hem_alloc_size);
 216
 217        while (npages > 0) {
 218                if (!chunk) {
 219                        chunk = kmalloc(sizeof(*chunk),
 220                                gfp_mask & ~(__GFP_HIGHMEM | __GFP_NOWARN));
 221                        if (!chunk)
 222                                goto fail;
 223
 224                        sg_init_table(chunk->mem, HNS_ROCE_HEM_CHUNK_LEN);
 225                        chunk->npages = 0;
 226                        chunk->nsg = 0;
 227                        memset(chunk->buf, 0, sizeof(chunk->buf));
 228                        list_add_tail(&chunk->list, &hem->chunk_list);
 229                }
 230
 231                while (1 << order > npages)
 232                        --order;
 233
 234                /*
 235                 * Alloc memory one time. If failed, don't alloc small block
 236                 * memory, directly return fail.
 237                 */
 238                mem = &chunk->mem[chunk->npages];
 239                buf = dma_alloc_coherent(hr_dev->dev, PAGE_SIZE << order,
 240                                &sg_dma_address(mem), gfp_mask);
 241                if (!buf)
 242                        goto fail;
 243
 244                chunk->buf[chunk->npages] = buf;
 245                sg_dma_len(mem) = PAGE_SIZE << order;
 246
 247                ++chunk->npages;
 248                ++chunk->nsg;
 249                npages -= 1 << order;
 250        }
 251
 252        return hem;
 253
 254fail:
 255        hns_roce_free_hem(hr_dev, hem);
 256        return NULL;
 257}
 258
 259void hns_roce_free_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem *hem)
 260{
 261        struct hns_roce_hem_chunk *chunk, *tmp;
 262        int i;
 263
 264        if (!hem)
 265                return;
 266
 267        list_for_each_entry_safe(chunk, tmp, &hem->chunk_list, list) {
 268                for (i = 0; i < chunk->npages; ++i)
 269                        dma_free_coherent(hr_dev->dev,
 270                                   sg_dma_len(&chunk->mem[i]),
 271                                   chunk->buf[i],
 272                                   sg_dma_address(&chunk->mem[i]));
 273                kfree(chunk);
 274        }
 275
 276        kfree(hem);
 277}
 278
 279static int hns_roce_set_hem(struct hns_roce_dev *hr_dev,
 280                            struct hns_roce_hem_table *table, unsigned long obj)
 281{
 282        spinlock_t *lock = &hr_dev->bt_cmd_lock;
 283        struct device *dev = hr_dev->dev;
 284        unsigned long end = 0;
 285        unsigned long flags;
 286        struct hns_roce_hem_iter iter;
 287        void __iomem *bt_cmd;
 288        u32 bt_cmd_h_val = 0;
 289        u32 bt_cmd_val[2];
 290        u32 bt_cmd_l = 0;
 291        u64 bt_ba = 0;
 292        int ret = 0;
 293
 294        /* Find the HEM(Hardware Entry Memory) entry */
 295        unsigned long i = (obj & (table->num_obj - 1)) /
 296                          (table->table_chunk_size / table->obj_size);
 297
 298        switch (table->type) {
 299        case HEM_TYPE_QPC:
 300                roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
 301                               ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_QPC);
 302                break;
 303        case HEM_TYPE_MTPT:
 304                roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
 305                               ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
 306                               HEM_TYPE_MTPT);
 307                break;
 308        case HEM_TYPE_CQC:
 309                roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
 310                               ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S, HEM_TYPE_CQC);
 311                break;
 312        case HEM_TYPE_SRQC:
 313                roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M,
 314                               ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S,
 315                               HEM_TYPE_SRQC);
 316                break;
 317        default:
 318                return ret;
 319        }
 320        roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M,
 321                       ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S, obj);
 322        roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S, 0);
 323        roce_set_bit(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S, 1);
 324
 325        /* Currently iter only a chunk */
 326        for (hns_roce_hem_first(table->hem[i], &iter);
 327             !hns_roce_hem_last(&iter); hns_roce_hem_next(&iter)) {
 328                bt_ba = hns_roce_hem_addr(&iter) >> DMA_ADDR_T_SHIFT;
 329
 330                spin_lock_irqsave(lock, flags);
 331
 332                bt_cmd = hr_dev->reg_base + ROCEE_BT_CMD_H_REG;
 333
 334                end = msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS) + jiffies;
 335                while (1) {
 336                        if (readl(bt_cmd) >> BT_CMD_SYNC_SHIFT) {
 337                                if (!(time_before(jiffies, end))) {
 338                                        dev_err(dev, "Write bt_cmd err,hw_sync is not zero.\n");
 339                                        spin_unlock_irqrestore(lock, flags);
 340                                        return -EBUSY;
 341                                }
 342                        } else {
 343                                break;
 344                        }
 345                        msleep(HW_SYNC_SLEEP_TIME_INTERVAL);
 346                }
 347
 348                bt_cmd_l = (u32)bt_ba;
 349                roce_set_field(bt_cmd_h_val, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M,
 350                               ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S,
 351                               bt_ba >> BT_BA_SHIFT);
 352
 353                bt_cmd_val[0] = bt_cmd_l;
 354                bt_cmd_val[1] = bt_cmd_h_val;
 355                hns_roce_write64_k(bt_cmd_val,
 356                                   hr_dev->reg_base + ROCEE_BT_CMD_L_REG);
 357                spin_unlock_irqrestore(lock, flags);
 358        }
 359
 360        return ret;
 361}
 362
 363static int hns_roce_table_mhop_get(struct hns_roce_dev *hr_dev,
 364                                   struct hns_roce_hem_table *table,
 365                                   unsigned long obj)
 366{
 367        struct device *dev = hr_dev->dev;
 368        struct hns_roce_hem_mhop mhop;
 369        struct hns_roce_hem_iter iter;
 370        u32 buf_chunk_size;
 371        u32 bt_chunk_size;
 372        u32 chunk_ba_num;
 373        u32 hop_num;
 374        u32 size;
 375        u32 bt_num;
 376        u64 hem_idx;
 377        u64 bt_l1_idx = 0;
 378        u64 bt_l0_idx = 0;
 379        u64 bt_ba;
 380        unsigned long mhop_obj = obj;
 381        int bt_l1_allocated = 0;
 382        int bt_l0_allocated = 0;
 383        int step_idx;
 384        int ret;
 385
 386        ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
 387        if (ret)
 388                return ret;
 389
 390        buf_chunk_size = mhop.buf_chunk_size;
 391        bt_chunk_size = mhop.bt_chunk_size;
 392        hop_num = mhop.hop_num;
 393        chunk_ba_num = bt_chunk_size / 8;
 394
 395        bt_num = hns_roce_get_bt_num(table->type, hop_num);
 396        switch (bt_num) {
 397        case 3:
 398                hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
 399                          mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
 400                bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
 401                bt_l0_idx = mhop.l0_idx;
 402                break;
 403        case 2:
 404                hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
 405                bt_l0_idx = mhop.l0_idx;
 406                break;
 407        case 1:
 408                hem_idx = mhop.l0_idx;
 409                break;
 410        default:
 411                dev_err(dev, "Table %d not support hop_num = %d!\n",
 412                             table->type, hop_num);
 413                return -EINVAL;
 414        }
 415
 416        mutex_lock(&table->mutex);
 417
 418        if (table->hem[hem_idx]) {
 419                ++table->hem[hem_idx]->refcount;
 420                goto out;
 421        }
 422
 423        /* alloc L1 BA's chunk */
 424        if ((check_whether_bt_num_3(table->type, hop_num) ||
 425                check_whether_bt_num_2(table->type, hop_num)) &&
 426                !table->bt_l0[bt_l0_idx]) {
 427                table->bt_l0[bt_l0_idx] = dma_alloc_coherent(dev, bt_chunk_size,
 428                                            &(table->bt_l0_dma_addr[bt_l0_idx]),
 429                                            GFP_KERNEL);
 430                if (!table->bt_l0[bt_l0_idx]) {
 431                        ret = -ENOMEM;
 432                        goto out;
 433                }
 434                bt_l0_allocated = 1;
 435
 436                /* set base address to hardware */
 437                if (table->type < HEM_TYPE_MTT) {
 438                        step_idx = 0;
 439                        if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
 440                                ret = -ENODEV;
 441                                dev_err(dev, "set HEM base address to HW failed!\n");
 442                                goto err_dma_alloc_l1;
 443                        }
 444                }
 445        }
 446
 447        /* alloc L2 BA's chunk */
 448        if (check_whether_bt_num_3(table->type, hop_num) &&
 449            !table->bt_l1[bt_l1_idx])  {
 450                table->bt_l1[bt_l1_idx] = dma_alloc_coherent(dev, bt_chunk_size,
 451                                            &(table->bt_l1_dma_addr[bt_l1_idx]),
 452                                            GFP_KERNEL);
 453                if (!table->bt_l1[bt_l1_idx]) {
 454                        ret = -ENOMEM;
 455                        goto err_dma_alloc_l1;
 456                }
 457                bt_l1_allocated = 1;
 458                *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) =
 459                                               table->bt_l1_dma_addr[bt_l1_idx];
 460
 461                /* set base address to hardware */
 462                step_idx = 1;
 463                if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
 464                        ret = -ENODEV;
 465                        dev_err(dev, "set HEM base address to HW failed!\n");
 466                        goto err_alloc_hem_buf;
 467                }
 468        }
 469
 470        /*
 471         * alloc buffer space chunk for QPC/MTPT/CQC/SRQC.
 472         * alloc bt space chunk for MTT/CQE.
 473         */
 474        size = table->type < HEM_TYPE_MTT ? buf_chunk_size : bt_chunk_size;
 475        table->hem[hem_idx] = hns_roce_alloc_hem(hr_dev,
 476                                                size >> PAGE_SHIFT,
 477                                                size,
 478                                                (table->lowmem ? GFP_KERNEL :
 479                                                GFP_HIGHUSER) | __GFP_NOWARN);
 480        if (!table->hem[hem_idx]) {
 481                ret = -ENOMEM;
 482                goto err_alloc_hem_buf;
 483        }
 484
 485        hns_roce_hem_first(table->hem[hem_idx], &iter);
 486        bt_ba = hns_roce_hem_addr(&iter);
 487
 488        if (table->type < HEM_TYPE_MTT) {
 489                if (hop_num == 2) {
 490                        *(table->bt_l1[bt_l1_idx] + mhop.l2_idx) = bt_ba;
 491                        step_idx = 2;
 492                } else if (hop_num == 1) {
 493                        *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba;
 494                        step_idx = 1;
 495                } else if (hop_num == HNS_ROCE_HOP_NUM_0) {
 496                        step_idx = 0;
 497                }
 498
 499                /* set HEM base address to hardware */
 500                if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) {
 501                        ret = -ENODEV;
 502                        dev_err(dev, "set HEM base address to HW failed!\n");
 503                        goto err_alloc_hem_buf;
 504                }
 505        } else if (hop_num == 2) {
 506                *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba;
 507        }
 508
 509        ++table->hem[hem_idx]->refcount;
 510        goto out;
 511
 512err_alloc_hem_buf:
 513        if (bt_l1_allocated) {
 514                dma_free_coherent(dev, bt_chunk_size, table->bt_l1[bt_l1_idx],
 515                                  table->bt_l1_dma_addr[bt_l1_idx]);
 516                table->bt_l1[bt_l1_idx] = NULL;
 517        }
 518
 519err_dma_alloc_l1:
 520        if (bt_l0_allocated) {
 521                dma_free_coherent(dev, bt_chunk_size, table->bt_l0[bt_l0_idx],
 522                                  table->bt_l0_dma_addr[bt_l0_idx]);
 523                table->bt_l0[bt_l0_idx] = NULL;
 524        }
 525
 526out:
 527        mutex_unlock(&table->mutex);
 528        return ret;
 529}
 530
 531int hns_roce_table_get(struct hns_roce_dev *hr_dev,
 532                       struct hns_roce_hem_table *table, unsigned long obj)
 533{
 534        struct device *dev = hr_dev->dev;
 535        int ret = 0;
 536        unsigned long i;
 537
 538        if (hns_roce_check_whether_mhop(hr_dev, table->type))
 539                return hns_roce_table_mhop_get(hr_dev, table, obj);
 540
 541        i = (obj & (table->num_obj - 1)) / (table->table_chunk_size /
 542             table->obj_size);
 543
 544        mutex_lock(&table->mutex);
 545
 546        if (table->hem[i]) {
 547                ++table->hem[i]->refcount;
 548                goto out;
 549        }
 550
 551        table->hem[i] = hns_roce_alloc_hem(hr_dev,
 552                                       table->table_chunk_size >> PAGE_SHIFT,
 553                                       table->table_chunk_size,
 554                                       (table->lowmem ? GFP_KERNEL :
 555                                        GFP_HIGHUSER) | __GFP_NOWARN);
 556        if (!table->hem[i]) {
 557                ret = -ENOMEM;
 558                goto out;
 559        }
 560
 561        /* Set HEM base address(128K/page, pa) to Hardware */
 562        if (hns_roce_set_hem(hr_dev, table, obj)) {
 563                hns_roce_free_hem(hr_dev, table->hem[i]);
 564                table->hem[i] = NULL;
 565                ret = -ENODEV;
 566                dev_err(dev, "set HEM base address to HW failed.\n");
 567                goto out;
 568        }
 569
 570        ++table->hem[i]->refcount;
 571out:
 572        mutex_unlock(&table->mutex);
 573        return ret;
 574}
 575
 576static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev,
 577                                    struct hns_roce_hem_table *table,
 578                                    unsigned long obj,
 579                                    int check_refcount)
 580{
 581        struct device *dev = hr_dev->dev;
 582        struct hns_roce_hem_mhop mhop;
 583        unsigned long mhop_obj = obj;
 584        u32 bt_chunk_size;
 585        u32 chunk_ba_num;
 586        u32 hop_num;
 587        u32 start_idx;
 588        u32 bt_num;
 589        u64 hem_idx;
 590        u64 bt_l1_idx = 0;
 591        int ret;
 592
 593        ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
 594        if (ret)
 595                return;
 596
 597        bt_chunk_size = mhop.bt_chunk_size;
 598        hop_num = mhop.hop_num;
 599        chunk_ba_num = bt_chunk_size / 8;
 600
 601        bt_num = hns_roce_get_bt_num(table->type, hop_num);
 602        switch (bt_num) {
 603        case 3:
 604                hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
 605                          mhop.l1_idx * chunk_ba_num + mhop.l2_idx;
 606                bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
 607                break;
 608        case 2:
 609                hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx;
 610                break;
 611        case 1:
 612                hem_idx = mhop.l0_idx;
 613                break;
 614        default:
 615                dev_err(dev, "Table %d not support hop_num = %d!\n",
 616                             table->type, hop_num);
 617                return;
 618        }
 619
 620        mutex_lock(&table->mutex);
 621
 622        if (check_refcount && (--table->hem[hem_idx]->refcount > 0)) {
 623                mutex_unlock(&table->mutex);
 624                return;
 625        }
 626
 627        if (table->type < HEM_TYPE_MTT && hop_num == 1) {
 628                if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
 629                        dev_warn(dev, "Clear HEM base address failed.\n");
 630        } else if (table->type < HEM_TYPE_MTT && hop_num == 2) {
 631                if (hr_dev->hw->clear_hem(hr_dev, table, obj, 2))
 632                        dev_warn(dev, "Clear HEM base address failed.\n");
 633        } else if (table->type < HEM_TYPE_MTT &&
 634                   hop_num == HNS_ROCE_HOP_NUM_0) {
 635                if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
 636                        dev_warn(dev, "Clear HEM base address failed.\n");
 637        }
 638
 639        /*
 640         * free buffer space chunk for QPC/MTPT/CQC/SRQC.
 641         * free bt space chunk for MTT/CQE.
 642         */
 643        hns_roce_free_hem(hr_dev, table->hem[hem_idx]);
 644        table->hem[hem_idx] = NULL;
 645
 646        if (check_whether_bt_num_2(table->type, hop_num)) {
 647                start_idx = mhop.l0_idx * chunk_ba_num;
 648                if (hns_roce_check_hem_null(table->hem, start_idx,
 649                                            chunk_ba_num)) {
 650                        if (table->type < HEM_TYPE_MTT &&
 651                            hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
 652                                dev_warn(dev, "Clear HEM base address failed.\n");
 653
 654                        dma_free_coherent(dev, bt_chunk_size,
 655                                          table->bt_l0[mhop.l0_idx],
 656                                          table->bt_l0_dma_addr[mhop.l0_idx]);
 657                        table->bt_l0[mhop.l0_idx] = NULL;
 658                }
 659        } else if (check_whether_bt_num_3(table->type, hop_num)) {
 660                start_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num +
 661                            mhop.l1_idx * chunk_ba_num;
 662                if (hns_roce_check_hem_null(table->hem, start_idx,
 663                                            chunk_ba_num)) {
 664                        if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1))
 665                                dev_warn(dev, "Clear HEM base address failed.\n");
 666
 667                        dma_free_coherent(dev, bt_chunk_size,
 668                                          table->bt_l1[bt_l1_idx],
 669                                          table->bt_l1_dma_addr[bt_l1_idx]);
 670                        table->bt_l1[bt_l1_idx] = NULL;
 671
 672                        start_idx = mhop.l0_idx * chunk_ba_num;
 673                        if (hns_roce_check_bt_null(table->bt_l1, start_idx,
 674                                                   chunk_ba_num)) {
 675                                if (hr_dev->hw->clear_hem(hr_dev, table, obj,
 676                                                          0))
 677                                        dev_warn(dev, "Clear HEM base address failed.\n");
 678
 679                                dma_free_coherent(dev, bt_chunk_size,
 680                                            table->bt_l0[mhop.l0_idx],
 681                                            table->bt_l0_dma_addr[mhop.l0_idx]);
 682                                table->bt_l0[mhop.l0_idx] = NULL;
 683                        }
 684                }
 685        }
 686
 687        mutex_unlock(&table->mutex);
 688}
 689
 690void hns_roce_table_put(struct hns_roce_dev *hr_dev,
 691                        struct hns_roce_hem_table *table, unsigned long obj)
 692{
 693        struct device *dev = hr_dev->dev;
 694        unsigned long i;
 695
 696        if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
 697                hns_roce_table_mhop_put(hr_dev, table, obj, 1);
 698                return;
 699        }
 700
 701        i = (obj & (table->num_obj - 1)) /
 702            (table->table_chunk_size / table->obj_size);
 703
 704        mutex_lock(&table->mutex);
 705
 706        if (--table->hem[i]->refcount == 0) {
 707                /* Clear HEM base address */
 708                if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0))
 709                        dev_warn(dev, "Clear HEM base address failed.\n");
 710
 711                hns_roce_free_hem(hr_dev, table->hem[i]);
 712                table->hem[i] = NULL;
 713        }
 714
 715        mutex_unlock(&table->mutex);
 716}
 717
 718void *hns_roce_table_find(struct hns_roce_dev *hr_dev,
 719                          struct hns_roce_hem_table *table,
 720                          unsigned long obj, dma_addr_t *dma_handle)
 721{
 722        struct hns_roce_hem_chunk *chunk;
 723        struct hns_roce_hem_mhop mhop;
 724        struct hns_roce_hem *hem;
 725        void *addr = NULL;
 726        unsigned long mhop_obj = obj;
 727        unsigned long obj_per_chunk;
 728        unsigned long idx_offset;
 729        int offset, dma_offset;
 730        int length;
 731        int i, j;
 732        u32 hem_idx = 0;
 733
 734        if (!table->lowmem)
 735                return NULL;
 736
 737        mutex_lock(&table->mutex);
 738
 739        if (!hns_roce_check_whether_mhop(hr_dev, table->type)) {
 740                obj_per_chunk = table->table_chunk_size / table->obj_size;
 741                hem = table->hem[(obj & (table->num_obj - 1)) / obj_per_chunk];
 742                idx_offset = (obj & (table->num_obj - 1)) % obj_per_chunk;
 743                dma_offset = offset = idx_offset * table->obj_size;
 744        } else {
 745                hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop);
 746                /* mtt mhop */
 747                i = mhop.l0_idx;
 748                j = mhop.l1_idx;
 749                if (mhop.hop_num == 2)
 750                        hem_idx = i * (mhop.bt_chunk_size / 8) + j;
 751                else if (mhop.hop_num == 1 ||
 752                         mhop.hop_num == HNS_ROCE_HOP_NUM_0)
 753                        hem_idx = i;
 754
 755                hem = table->hem[hem_idx];
 756                dma_offset = offset = (obj & (table->num_obj - 1)) *
 757                                       table->obj_size % mhop.bt_chunk_size;
 758                if (mhop.hop_num == 2)
 759                        dma_offset = offset = 0;
 760        }
 761
 762        if (!hem)
 763                goto out;
 764
 765        list_for_each_entry(chunk, &hem->chunk_list, list) {
 766                for (i = 0; i < chunk->npages; ++i) {
 767                        length = sg_dma_len(&chunk->mem[i]);
 768                        if (dma_handle && dma_offset >= 0) {
 769                                if (length > (u32)dma_offset)
 770                                        *dma_handle = sg_dma_address(
 771                                                &chunk->mem[i]) + dma_offset;
 772                                dma_offset -= length;
 773                        }
 774
 775                        if (length > (u32)offset) {
 776                                addr = chunk->buf[i] + offset;
 777                                goto out;
 778                        }
 779                        offset -= length;
 780                }
 781        }
 782
 783out:
 784        mutex_unlock(&table->mutex);
 785        return addr;
 786}
 787EXPORT_SYMBOL_GPL(hns_roce_table_find);
 788
 789int hns_roce_table_get_range(struct hns_roce_dev *hr_dev,
 790                             struct hns_roce_hem_table *table,
 791                             unsigned long start, unsigned long end)
 792{
 793        struct hns_roce_hem_mhop mhop;
 794        unsigned long inc = table->table_chunk_size / table->obj_size;
 795        unsigned long i;
 796        int ret;
 797
 798        if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
 799                hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
 800                inc = mhop.bt_chunk_size / table->obj_size;
 801        }
 802
 803        /* Allocate MTT entry memory according to chunk(128K) */
 804        for (i = start; i <= end; i += inc) {
 805                ret = hns_roce_table_get(hr_dev, table, i);
 806                if (ret)
 807                        goto fail;
 808        }
 809
 810        return 0;
 811
 812fail:
 813        while (i > start) {
 814                i -= inc;
 815                hns_roce_table_put(hr_dev, table, i);
 816        }
 817        return ret;
 818}
 819
 820void hns_roce_table_put_range(struct hns_roce_dev *hr_dev,
 821                              struct hns_roce_hem_table *table,
 822                              unsigned long start, unsigned long end)
 823{
 824        struct hns_roce_hem_mhop mhop;
 825        unsigned long inc = table->table_chunk_size / table->obj_size;
 826        unsigned long i;
 827
 828        if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
 829                hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
 830                inc = mhop.bt_chunk_size / table->obj_size;
 831        }
 832
 833        for (i = start; i <= end; i += inc)
 834                hns_roce_table_put(hr_dev, table, i);
 835}
 836
 837int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev,
 838                            struct hns_roce_hem_table *table, u32 type,
 839                            unsigned long obj_size, unsigned long nobj,
 840                            int use_lowmem)
 841{
 842        struct device *dev = hr_dev->dev;
 843        unsigned long obj_per_chunk;
 844        unsigned long num_hem;
 845
 846        if (!hns_roce_check_whether_mhop(hr_dev, type)) {
 847                table->table_chunk_size = hr_dev->caps.chunk_sz;
 848                obj_per_chunk = table->table_chunk_size / obj_size;
 849                num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
 850
 851                table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
 852                if (!table->hem)
 853                        return -ENOMEM;
 854        } else {
 855                unsigned long buf_chunk_size;
 856                unsigned long bt_chunk_size;
 857                unsigned long bt_chunk_num;
 858                unsigned long num_bt_l0 = 0;
 859                u32 hop_num;
 860
 861                switch (type) {
 862                case HEM_TYPE_QPC:
 863                        buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz
 864                                        + PAGE_SHIFT);
 865                        bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz
 866                                        + PAGE_SHIFT);
 867                        num_bt_l0 = hr_dev->caps.qpc_bt_num;
 868                        hop_num = hr_dev->caps.qpc_hop_num;
 869                        break;
 870                case HEM_TYPE_MTPT:
 871                        buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz
 872                                        + PAGE_SHIFT);
 873                        bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz
 874                                        + PAGE_SHIFT);
 875                        num_bt_l0 = hr_dev->caps.mpt_bt_num;
 876                        hop_num = hr_dev->caps.mpt_hop_num;
 877                        break;
 878                case HEM_TYPE_CQC:
 879                        buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz
 880                                        + PAGE_SHIFT);
 881                        bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz
 882                                        + PAGE_SHIFT);
 883                        num_bt_l0 = hr_dev->caps.cqc_bt_num;
 884                        hop_num = hr_dev->caps.cqc_hop_num;
 885                        break;
 886                case HEM_TYPE_SRQC:
 887                        buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz
 888                                        + PAGE_SHIFT);
 889                        bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz
 890                                        + PAGE_SHIFT);
 891                        num_bt_l0 = hr_dev->caps.srqc_bt_num;
 892                        hop_num = hr_dev->caps.srqc_hop_num;
 893                        break;
 894                case HEM_TYPE_MTT:
 895                        buf_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz
 896                                        + PAGE_SHIFT);
 897                        bt_chunk_size = buf_chunk_size;
 898                        hop_num = hr_dev->caps.mtt_hop_num;
 899                        break;
 900                case HEM_TYPE_CQE:
 901                        buf_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz
 902                                        + PAGE_SHIFT);
 903                        bt_chunk_size = buf_chunk_size;
 904                        hop_num = hr_dev->caps.cqe_hop_num;
 905                        break;
 906                default:
 907                        dev_err(dev,
 908                          "Table %d not support to init hem table here!\n",
 909                          type);
 910                        return -EINVAL;
 911                }
 912                obj_per_chunk = buf_chunk_size / obj_size;
 913                num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk;
 914                bt_chunk_num = bt_chunk_size / 8;
 915                if (table->type >= HEM_TYPE_MTT)
 916                        num_bt_l0 = bt_chunk_num;
 917
 918                table->hem = kcalloc(num_hem, sizeof(*table->hem),
 919                                         GFP_KERNEL);
 920                if (!table->hem)
 921                        goto err_kcalloc_hem_buf;
 922
 923                if (check_whether_bt_num_3(table->type, hop_num)) {
 924                        unsigned long num_bt_l1;
 925
 926                        num_bt_l1 = (num_hem + bt_chunk_num - 1) /
 927                                             bt_chunk_num;
 928                        table->bt_l1 = kcalloc(num_bt_l1,
 929                                               sizeof(*table->bt_l1),
 930                                               GFP_KERNEL);
 931                        if (!table->bt_l1)
 932                                goto err_kcalloc_bt_l1;
 933
 934                        table->bt_l1_dma_addr = kcalloc(num_bt_l1,
 935                                                 sizeof(*table->bt_l1_dma_addr),
 936                                                 GFP_KERNEL);
 937
 938                        if (!table->bt_l1_dma_addr)
 939                                goto err_kcalloc_l1_dma;
 940                }
 941
 942                if (check_whether_bt_num_2(table->type, hop_num) ||
 943                        check_whether_bt_num_3(table->type, hop_num)) {
 944                        table->bt_l0 = kcalloc(num_bt_l0, sizeof(*table->bt_l0),
 945                                               GFP_KERNEL);
 946                        if (!table->bt_l0)
 947                                goto err_kcalloc_bt_l0;
 948
 949                        table->bt_l0_dma_addr = kcalloc(num_bt_l0,
 950                                                 sizeof(*table->bt_l0_dma_addr),
 951                                                 GFP_KERNEL);
 952                        if (!table->bt_l0_dma_addr)
 953                                goto err_kcalloc_l0_dma;
 954                }
 955        }
 956
 957        table->type = type;
 958        table->num_hem = num_hem;
 959        table->num_obj = nobj;
 960        table->obj_size = obj_size;
 961        table->lowmem = use_lowmem;
 962        mutex_init(&table->mutex);
 963
 964        return 0;
 965
 966err_kcalloc_l0_dma:
 967        kfree(table->bt_l0);
 968        table->bt_l0 = NULL;
 969
 970err_kcalloc_bt_l0:
 971        kfree(table->bt_l1_dma_addr);
 972        table->bt_l1_dma_addr = NULL;
 973
 974err_kcalloc_l1_dma:
 975        kfree(table->bt_l1);
 976        table->bt_l1 = NULL;
 977
 978err_kcalloc_bt_l1:
 979        kfree(table->hem);
 980        table->hem = NULL;
 981
 982err_kcalloc_hem_buf:
 983        return -ENOMEM;
 984}
 985
 986static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev,
 987                                            struct hns_roce_hem_table *table)
 988{
 989        struct hns_roce_hem_mhop mhop;
 990        u32 buf_chunk_size;
 991        int i;
 992        u64 obj;
 993
 994        hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop);
 995        buf_chunk_size = table->type < HEM_TYPE_MTT ? mhop.buf_chunk_size :
 996                                        mhop.bt_chunk_size;
 997
 998        for (i = 0; i < table->num_hem; ++i) {
 999                obj = i * buf_chunk_size / table->obj_size;
1000                if (table->hem[i])
1001                        hns_roce_table_mhop_put(hr_dev, table, obj, 0);
1002        }
1003
1004        kfree(table->hem);
1005        table->hem = NULL;
1006        kfree(table->bt_l1);
1007        table->bt_l1 = NULL;
1008        kfree(table->bt_l1_dma_addr);
1009        table->bt_l1_dma_addr = NULL;
1010        kfree(table->bt_l0);
1011        table->bt_l0 = NULL;
1012        kfree(table->bt_l0_dma_addr);
1013        table->bt_l0_dma_addr = NULL;
1014}
1015
1016void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev,
1017                                struct hns_roce_hem_table *table)
1018{
1019        struct device *dev = hr_dev->dev;
1020        unsigned long i;
1021
1022        if (hns_roce_check_whether_mhop(hr_dev, table->type)) {
1023                hns_roce_cleanup_mhop_hem_table(hr_dev, table);
1024                return;
1025        }
1026
1027        for (i = 0; i < table->num_hem; ++i)
1028                if (table->hem[i]) {
1029                        if (hr_dev->hw->clear_hem(hr_dev, table,
1030                            i * table->table_chunk_size / table->obj_size, 0))
1031                                dev_err(dev, "Clear HEM base address failed.\n");
1032
1033                        hns_roce_free_hem(hr_dev, table->hem[i]);
1034                }
1035
1036        kfree(table->hem);
1037}
1038
1039void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev)
1040{
1041        hns_roce_cleanup_hem_table(hr_dev, &hr_dev->cq_table.table);
1042        hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.irrl_table);
1043        if (hr_dev->caps.trrl_entry_sz)
1044                hns_roce_cleanup_hem_table(hr_dev,
1045                                           &hr_dev->qp_table.trrl_table);
1046        hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.qp_table);
1047        hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table);
1048        hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table);
1049        if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE))
1050                hns_roce_cleanup_hem_table(hr_dev,
1051                                           &hr_dev->mr_table.mtt_cqe_table);
1052}
1053