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 42 bool 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 } 54 EXPORT_SYMBOL_GPL(hns_roce_check_whether_mhop); 55 56 static 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 68 static 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 79 static 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 91 int 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 } 192 EXPORT_SYMBOL_GPL(hns_roce_calc_hem_mhop); 193 194 static 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 254 fail: 255 hns_roce_free_hem(hr_dev, hem); 256 return NULL; 257 } 258 259 void 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 279 static 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 mdelay(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 363 static 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 } else { 498 ret = -EINVAL; 499 goto err_dma_alloc_l1; 500 } 501 502 /* set HEM base address to hardware */ 503 if (hr_dev->hw->set_hem(hr_dev, table, obj, step_idx)) { 504 ret = -ENODEV; 505 dev_err(dev, "set HEM base address to HW failed!\n"); 506 goto err_alloc_hem_buf; 507 } 508 } else if (hop_num == 2) { 509 *(table->bt_l0[bt_l0_idx] + mhop.l1_idx) = bt_ba; 510 } 511 512 ++table->hem[hem_idx]->refcount; 513 goto out; 514 515 err_alloc_hem_buf: 516 if (bt_l1_allocated) { 517 dma_free_coherent(dev, bt_chunk_size, table->bt_l1[bt_l1_idx], 518 table->bt_l1_dma_addr[bt_l1_idx]); 519 table->bt_l1[bt_l1_idx] = NULL; 520 } 521 522 err_dma_alloc_l1: 523 if (bt_l0_allocated) { 524 dma_free_coherent(dev, bt_chunk_size, table->bt_l0[bt_l0_idx], 525 table->bt_l0_dma_addr[bt_l0_idx]); 526 table->bt_l0[bt_l0_idx] = NULL; 527 } 528 529 out: 530 mutex_unlock(&table->mutex); 531 return ret; 532 } 533 534 int hns_roce_table_get(struct hns_roce_dev *hr_dev, 535 struct hns_roce_hem_table *table, unsigned long obj) 536 { 537 struct device *dev = hr_dev->dev; 538 int ret = 0; 539 unsigned long i; 540 541 if (hns_roce_check_whether_mhop(hr_dev, table->type)) 542 return hns_roce_table_mhop_get(hr_dev, table, obj); 543 544 i = (obj & (table->num_obj - 1)) / (table->table_chunk_size / 545 table->obj_size); 546 547 mutex_lock(&table->mutex); 548 549 if (table->hem[i]) { 550 ++table->hem[i]->refcount; 551 goto out; 552 } 553 554 table->hem[i] = hns_roce_alloc_hem(hr_dev, 555 table->table_chunk_size >> PAGE_SHIFT, 556 table->table_chunk_size, 557 (table->lowmem ? GFP_KERNEL : 558 GFP_HIGHUSER) | __GFP_NOWARN); 559 if (!table->hem[i]) { 560 ret = -ENOMEM; 561 goto out; 562 } 563 564 /* Set HEM base address(128K/page, pa) to Hardware */ 565 if (hns_roce_set_hem(hr_dev, table, obj)) { 566 hns_roce_free_hem(hr_dev, table->hem[i]); 567 table->hem[i] = NULL; 568 ret = -ENODEV; 569 dev_err(dev, "set HEM base address to HW failed.\n"); 570 goto out; 571 } 572 573 ++table->hem[i]->refcount; 574 out: 575 mutex_unlock(&table->mutex); 576 return ret; 577 } 578 579 static void hns_roce_table_mhop_put(struct hns_roce_dev *hr_dev, 580 struct hns_roce_hem_table *table, 581 unsigned long obj, 582 int check_refcount) 583 { 584 struct device *dev = hr_dev->dev; 585 struct hns_roce_hem_mhop mhop; 586 unsigned long mhop_obj = obj; 587 u32 bt_chunk_size; 588 u32 chunk_ba_num; 589 u32 hop_num; 590 u32 start_idx; 591 u32 bt_num; 592 u64 hem_idx; 593 u64 bt_l1_idx = 0; 594 int ret; 595 596 ret = hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop); 597 if (ret) 598 return; 599 600 bt_chunk_size = mhop.bt_chunk_size; 601 hop_num = mhop.hop_num; 602 chunk_ba_num = bt_chunk_size / 8; 603 604 bt_num = hns_roce_get_bt_num(table->type, hop_num); 605 switch (bt_num) { 606 case 3: 607 hem_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num + 608 mhop.l1_idx * chunk_ba_num + mhop.l2_idx; 609 bt_l1_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx; 610 break; 611 case 2: 612 hem_idx = mhop.l0_idx * chunk_ba_num + mhop.l1_idx; 613 break; 614 case 1: 615 hem_idx = mhop.l0_idx; 616 break; 617 default: 618 dev_err(dev, "Table %d not support hop_num = %d!\n", 619 table->type, hop_num); 620 return; 621 } 622 623 mutex_lock(&table->mutex); 624 625 if (check_refcount && (--table->hem[hem_idx]->refcount > 0)) { 626 mutex_unlock(&table->mutex); 627 return; 628 } 629 630 if (table->type < HEM_TYPE_MTT && hop_num == 1) { 631 if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1)) 632 dev_warn(dev, "Clear HEM base address failed.\n"); 633 } else if (table->type < HEM_TYPE_MTT && hop_num == 2) { 634 if (hr_dev->hw->clear_hem(hr_dev, table, obj, 2)) 635 dev_warn(dev, "Clear HEM base address failed.\n"); 636 } else if (table->type < HEM_TYPE_MTT && 637 hop_num == HNS_ROCE_HOP_NUM_0) { 638 if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0)) 639 dev_warn(dev, "Clear HEM base address failed.\n"); 640 } 641 642 /* 643 * free buffer space chunk for QPC/MTPT/CQC/SRQC. 644 * free bt space chunk for MTT/CQE. 645 */ 646 hns_roce_free_hem(hr_dev, table->hem[hem_idx]); 647 table->hem[hem_idx] = NULL; 648 649 if (check_whether_bt_num_2(table->type, hop_num)) { 650 start_idx = mhop.l0_idx * chunk_ba_num; 651 if (hns_roce_check_hem_null(table->hem, start_idx, 652 chunk_ba_num)) { 653 if (table->type < HEM_TYPE_MTT && 654 hr_dev->hw->clear_hem(hr_dev, table, obj, 0)) 655 dev_warn(dev, "Clear HEM base address failed.\n"); 656 657 dma_free_coherent(dev, bt_chunk_size, 658 table->bt_l0[mhop.l0_idx], 659 table->bt_l0_dma_addr[mhop.l0_idx]); 660 table->bt_l0[mhop.l0_idx] = NULL; 661 } 662 } else if (check_whether_bt_num_3(table->type, hop_num)) { 663 start_idx = mhop.l0_idx * chunk_ba_num * chunk_ba_num + 664 mhop.l1_idx * chunk_ba_num; 665 if (hns_roce_check_hem_null(table->hem, start_idx, 666 chunk_ba_num)) { 667 if (hr_dev->hw->clear_hem(hr_dev, table, obj, 1)) 668 dev_warn(dev, "Clear HEM base address failed.\n"); 669 670 dma_free_coherent(dev, bt_chunk_size, 671 table->bt_l1[bt_l1_idx], 672 table->bt_l1_dma_addr[bt_l1_idx]); 673 table->bt_l1[bt_l1_idx] = NULL; 674 675 start_idx = mhop.l0_idx * chunk_ba_num; 676 if (hns_roce_check_bt_null(table->bt_l1, start_idx, 677 chunk_ba_num)) { 678 if (hr_dev->hw->clear_hem(hr_dev, table, obj, 679 0)) 680 dev_warn(dev, "Clear HEM base address failed.\n"); 681 682 dma_free_coherent(dev, bt_chunk_size, 683 table->bt_l0[mhop.l0_idx], 684 table->bt_l0_dma_addr[mhop.l0_idx]); 685 table->bt_l0[mhop.l0_idx] = NULL; 686 } 687 } 688 } 689 690 mutex_unlock(&table->mutex); 691 } 692 693 void hns_roce_table_put(struct hns_roce_dev *hr_dev, 694 struct hns_roce_hem_table *table, unsigned long obj) 695 { 696 struct device *dev = hr_dev->dev; 697 unsigned long i; 698 699 if (hns_roce_check_whether_mhop(hr_dev, table->type)) { 700 hns_roce_table_mhop_put(hr_dev, table, obj, 1); 701 return; 702 } 703 704 i = (obj & (table->num_obj - 1)) / 705 (table->table_chunk_size / table->obj_size); 706 707 mutex_lock(&table->mutex); 708 709 if (--table->hem[i]->refcount == 0) { 710 /* Clear HEM base address */ 711 if (hr_dev->hw->clear_hem(hr_dev, table, obj, 0)) 712 dev_warn(dev, "Clear HEM base address failed.\n"); 713 714 hns_roce_free_hem(hr_dev, table->hem[i]); 715 table->hem[i] = NULL; 716 } 717 718 mutex_unlock(&table->mutex); 719 } 720 721 void *hns_roce_table_find(struct hns_roce_dev *hr_dev, 722 struct hns_roce_hem_table *table, 723 unsigned long obj, dma_addr_t *dma_handle) 724 { 725 struct hns_roce_hem_chunk *chunk; 726 struct hns_roce_hem_mhop mhop; 727 struct hns_roce_hem *hem; 728 void *addr = NULL; 729 unsigned long mhop_obj = obj; 730 unsigned long obj_per_chunk; 731 unsigned long idx_offset; 732 int offset, dma_offset; 733 int length; 734 int i, j; 735 u32 hem_idx = 0; 736 737 if (!table->lowmem) 738 return NULL; 739 740 mutex_lock(&table->mutex); 741 742 if (!hns_roce_check_whether_mhop(hr_dev, table->type)) { 743 obj_per_chunk = table->table_chunk_size / table->obj_size; 744 hem = table->hem[(obj & (table->num_obj - 1)) / obj_per_chunk]; 745 idx_offset = (obj & (table->num_obj - 1)) % obj_per_chunk; 746 dma_offset = offset = idx_offset * table->obj_size; 747 } else { 748 hns_roce_calc_hem_mhop(hr_dev, table, &mhop_obj, &mhop); 749 /* mtt mhop */ 750 i = mhop.l0_idx; 751 j = mhop.l1_idx; 752 if (mhop.hop_num == 2) 753 hem_idx = i * (mhop.bt_chunk_size / 8) + j; 754 else if (mhop.hop_num == 1 || 755 mhop.hop_num == HNS_ROCE_HOP_NUM_0) 756 hem_idx = i; 757 758 hem = table->hem[hem_idx]; 759 dma_offset = offset = (obj & (table->num_obj - 1)) * 760 table->obj_size % mhop.bt_chunk_size; 761 if (mhop.hop_num == 2) 762 dma_offset = offset = 0; 763 } 764 765 if (!hem) 766 goto out; 767 768 list_for_each_entry(chunk, &hem->chunk_list, list) { 769 for (i = 0; i < chunk->npages; ++i) { 770 length = sg_dma_len(&chunk->mem[i]); 771 if (dma_handle && dma_offset >= 0) { 772 if (length > (u32)dma_offset) 773 *dma_handle = sg_dma_address( 774 &chunk->mem[i]) + dma_offset; 775 dma_offset -= length; 776 } 777 778 if (length > (u32)offset) { 779 addr = chunk->buf[i] + offset; 780 goto out; 781 } 782 offset -= length; 783 } 784 } 785 786 out: 787 mutex_unlock(&table->mutex); 788 return addr; 789 } 790 EXPORT_SYMBOL_GPL(hns_roce_table_find); 791 792 int hns_roce_table_get_range(struct hns_roce_dev *hr_dev, 793 struct hns_roce_hem_table *table, 794 unsigned long start, unsigned long end) 795 { 796 struct hns_roce_hem_mhop mhop; 797 unsigned long inc = table->table_chunk_size / table->obj_size; 798 unsigned long i; 799 int ret; 800 801 if (hns_roce_check_whether_mhop(hr_dev, table->type)) { 802 hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop); 803 inc = mhop.bt_chunk_size / table->obj_size; 804 } 805 806 /* Allocate MTT entry memory according to chunk(128K) */ 807 for (i = start; i <= end; i += inc) { 808 ret = hns_roce_table_get(hr_dev, table, i); 809 if (ret) 810 goto fail; 811 } 812 813 return 0; 814 815 fail: 816 while (i > start) { 817 i -= inc; 818 hns_roce_table_put(hr_dev, table, i); 819 } 820 return ret; 821 } 822 823 void hns_roce_table_put_range(struct hns_roce_dev *hr_dev, 824 struct hns_roce_hem_table *table, 825 unsigned long start, unsigned long end) 826 { 827 struct hns_roce_hem_mhop mhop; 828 unsigned long inc = table->table_chunk_size / table->obj_size; 829 unsigned long i; 830 831 if (hns_roce_check_whether_mhop(hr_dev, table->type)) { 832 hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop); 833 inc = mhop.bt_chunk_size / table->obj_size; 834 } 835 836 for (i = start; i <= end; i += inc) 837 hns_roce_table_put(hr_dev, table, i); 838 } 839 840 int hns_roce_init_hem_table(struct hns_roce_dev *hr_dev, 841 struct hns_roce_hem_table *table, u32 type, 842 unsigned long obj_size, unsigned long nobj, 843 int use_lowmem) 844 { 845 struct device *dev = hr_dev->dev; 846 unsigned long obj_per_chunk; 847 unsigned long num_hem; 848 849 if (!hns_roce_check_whether_mhop(hr_dev, type)) { 850 table->table_chunk_size = hr_dev->caps.chunk_sz; 851 obj_per_chunk = table->table_chunk_size / obj_size; 852 num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk; 853 854 table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL); 855 if (!table->hem) 856 return -ENOMEM; 857 } else { 858 unsigned long buf_chunk_size; 859 unsigned long bt_chunk_size; 860 unsigned long bt_chunk_num; 861 unsigned long num_bt_l0 = 0; 862 u32 hop_num; 863 864 switch (type) { 865 case HEM_TYPE_QPC: 866 buf_chunk_size = 1 << (hr_dev->caps.qpc_buf_pg_sz 867 + PAGE_SHIFT); 868 bt_chunk_size = 1 << (hr_dev->caps.qpc_ba_pg_sz 869 + PAGE_SHIFT); 870 num_bt_l0 = hr_dev->caps.qpc_bt_num; 871 hop_num = hr_dev->caps.qpc_hop_num; 872 break; 873 case HEM_TYPE_MTPT: 874 buf_chunk_size = 1 << (hr_dev->caps.mpt_buf_pg_sz 875 + PAGE_SHIFT); 876 bt_chunk_size = 1 << (hr_dev->caps.mpt_ba_pg_sz 877 + PAGE_SHIFT); 878 num_bt_l0 = hr_dev->caps.mpt_bt_num; 879 hop_num = hr_dev->caps.mpt_hop_num; 880 break; 881 case HEM_TYPE_CQC: 882 buf_chunk_size = 1 << (hr_dev->caps.cqc_buf_pg_sz 883 + PAGE_SHIFT); 884 bt_chunk_size = 1 << (hr_dev->caps.cqc_ba_pg_sz 885 + PAGE_SHIFT); 886 num_bt_l0 = hr_dev->caps.cqc_bt_num; 887 hop_num = hr_dev->caps.cqc_hop_num; 888 break; 889 case HEM_TYPE_SRQC: 890 buf_chunk_size = 1 << (hr_dev->caps.srqc_buf_pg_sz 891 + PAGE_SHIFT); 892 bt_chunk_size = 1 << (hr_dev->caps.srqc_ba_pg_sz 893 + PAGE_SHIFT); 894 num_bt_l0 = hr_dev->caps.srqc_bt_num; 895 hop_num = hr_dev->caps.srqc_hop_num; 896 break; 897 case HEM_TYPE_MTT: 898 buf_chunk_size = 1 << (hr_dev->caps.mtt_ba_pg_sz 899 + PAGE_SHIFT); 900 bt_chunk_size = buf_chunk_size; 901 hop_num = hr_dev->caps.mtt_hop_num; 902 break; 903 case HEM_TYPE_CQE: 904 buf_chunk_size = 1 << (hr_dev->caps.cqe_ba_pg_sz 905 + PAGE_SHIFT); 906 bt_chunk_size = buf_chunk_size; 907 hop_num = hr_dev->caps.cqe_hop_num; 908 break; 909 default: 910 dev_err(dev, 911 "Table %d not support to init hem table here!\n", 912 type); 913 return -EINVAL; 914 } 915 obj_per_chunk = buf_chunk_size / obj_size; 916 num_hem = (nobj + obj_per_chunk - 1) / obj_per_chunk; 917 bt_chunk_num = bt_chunk_size / 8; 918 if (type >= HEM_TYPE_MTT) 919 num_bt_l0 = bt_chunk_num; 920 921 table->hem = kcalloc(num_hem, sizeof(*table->hem), 922 GFP_KERNEL); 923 if (!table->hem) 924 goto err_kcalloc_hem_buf; 925 926 if (check_whether_bt_num_3(type, hop_num)) { 927 unsigned long num_bt_l1; 928 929 num_bt_l1 = (num_hem + bt_chunk_num - 1) / 930 bt_chunk_num; 931 table->bt_l1 = kcalloc(num_bt_l1, 932 sizeof(*table->bt_l1), 933 GFP_KERNEL); 934 if (!table->bt_l1) 935 goto err_kcalloc_bt_l1; 936 937 table->bt_l1_dma_addr = kcalloc(num_bt_l1, 938 sizeof(*table->bt_l1_dma_addr), 939 GFP_KERNEL); 940 941 if (!table->bt_l1_dma_addr) 942 goto err_kcalloc_l1_dma; 943 } 944 945 if (check_whether_bt_num_2(type, hop_num) || 946 check_whether_bt_num_3(type, hop_num)) { 947 table->bt_l0 = kcalloc(num_bt_l0, sizeof(*table->bt_l0), 948 GFP_KERNEL); 949 if (!table->bt_l0) 950 goto err_kcalloc_bt_l0; 951 952 table->bt_l0_dma_addr = kcalloc(num_bt_l0, 953 sizeof(*table->bt_l0_dma_addr), 954 GFP_KERNEL); 955 if (!table->bt_l0_dma_addr) 956 goto err_kcalloc_l0_dma; 957 } 958 } 959 960 table->type = type; 961 table->num_hem = num_hem; 962 table->num_obj = nobj; 963 table->obj_size = obj_size; 964 table->lowmem = use_lowmem; 965 mutex_init(&table->mutex); 966 967 return 0; 968 969 err_kcalloc_l0_dma: 970 kfree(table->bt_l0); 971 table->bt_l0 = NULL; 972 973 err_kcalloc_bt_l0: 974 kfree(table->bt_l1_dma_addr); 975 table->bt_l1_dma_addr = NULL; 976 977 err_kcalloc_l1_dma: 978 kfree(table->bt_l1); 979 table->bt_l1 = NULL; 980 981 err_kcalloc_bt_l1: 982 kfree(table->hem); 983 table->hem = NULL; 984 985 err_kcalloc_hem_buf: 986 return -ENOMEM; 987 } 988 989 static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev, 990 struct hns_roce_hem_table *table) 991 { 992 struct hns_roce_hem_mhop mhop; 993 u32 buf_chunk_size; 994 int i; 995 u64 obj; 996 997 hns_roce_calc_hem_mhop(hr_dev, table, NULL, &mhop); 998 buf_chunk_size = table->type < HEM_TYPE_MTT ? mhop.buf_chunk_size : 999 mhop.bt_chunk_size; 1000 1001 for (i = 0; i < table->num_hem; ++i) { 1002 obj = i * buf_chunk_size / table->obj_size; 1003 if (table->hem[i]) 1004 hns_roce_table_mhop_put(hr_dev, table, obj, 0); 1005 } 1006 1007 kfree(table->hem); 1008 table->hem = NULL; 1009 kfree(table->bt_l1); 1010 table->bt_l1 = NULL; 1011 kfree(table->bt_l1_dma_addr); 1012 table->bt_l1_dma_addr = NULL; 1013 kfree(table->bt_l0); 1014 table->bt_l0 = NULL; 1015 kfree(table->bt_l0_dma_addr); 1016 table->bt_l0_dma_addr = NULL; 1017 } 1018 1019 void hns_roce_cleanup_hem_table(struct hns_roce_dev *hr_dev, 1020 struct hns_roce_hem_table *table) 1021 { 1022 struct device *dev = hr_dev->dev; 1023 unsigned long i; 1024 1025 if (hns_roce_check_whether_mhop(hr_dev, table->type)) { 1026 hns_roce_cleanup_mhop_hem_table(hr_dev, table); 1027 return; 1028 } 1029 1030 for (i = 0; i < table->num_hem; ++i) 1031 if (table->hem[i]) { 1032 if (hr_dev->hw->clear_hem(hr_dev, table, 1033 i * table->table_chunk_size / table->obj_size, 0)) 1034 dev_err(dev, "Clear HEM base address failed.\n"); 1035 1036 hns_roce_free_hem(hr_dev, table->hem[i]); 1037 } 1038 1039 kfree(table->hem); 1040 } 1041 1042 void hns_roce_cleanup_hem(struct hns_roce_dev *hr_dev) 1043 { 1044 hns_roce_cleanup_hem_table(hr_dev, &hr_dev->cq_table.table); 1045 if (hr_dev->caps.trrl_entry_sz) 1046 hns_roce_cleanup_hem_table(hr_dev, 1047 &hr_dev->qp_table.trrl_table); 1048 hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.irrl_table); 1049 hns_roce_cleanup_hem_table(hr_dev, &hr_dev->qp_table.qp_table); 1050 hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtpt_table); 1051 if (hns_roce_check_whether_mhop(hr_dev, HEM_TYPE_CQE)) 1052 hns_roce_cleanup_hem_table(hr_dev, 1053 &hr_dev->mr_table.mtt_cqe_table); 1054 hns_roce_cleanup_hem_table(hr_dev, &hr_dev->mr_table.mtt_table); 1055 } 1056