2 * Copyright (c) 2016 Hisilicon Limited.
3 * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
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:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
34 #include "hns_roce_device.h"
35 #include "hns_roce_hem.h"
36 #include "hns_roce_common.h"
38 #define HEM_INDEX_BUF BIT(0)
39 #define HEM_INDEX_L0 BIT(1)
40 #define HEM_INDEX_L1 BIT(2)
41 struct hns_roce_hem_index
{
45 u32 inited
; /* indicate which index is available */
48 bool hns_roce_check_whether_mhop(struct hns_roce_dev
*hr_dev
, u32 type
)
54 hop_num
= hr_dev
->caps
.qpc_hop_num
;
57 hop_num
= hr_dev
->caps
.mpt_hop_num
;
60 hop_num
= hr_dev
->caps
.cqc_hop_num
;
63 hop_num
= hr_dev
->caps
.srqc_hop_num
;
66 hop_num
= hr_dev
->caps
.sccc_hop_num
;
68 case HEM_TYPE_QPC_TIMER
:
69 hop_num
= hr_dev
->caps
.qpc_timer_hop_num
;
71 case HEM_TYPE_CQC_TIMER
:
72 hop_num
= hr_dev
->caps
.cqc_timer_hop_num
;
75 hop_num
= hr_dev
->caps
.gmv_hop_num
;
84 static bool hns_roce_check_hem_null(struct hns_roce_hem
**hem
, u64 hem_idx
,
85 u32 bt_chunk_num
, u64 hem_max_num
)
87 u64 start_idx
= round_down(hem_idx
, bt_chunk_num
);
88 u64 check_max_num
= start_idx
+ bt_chunk_num
;
91 for (i
= start_idx
; (i
< check_max_num
) && (i
< hem_max_num
); i
++)
92 if (i
!= hem_idx
&& hem
[i
])
98 static bool hns_roce_check_bt_null(u64
**bt
, u64 ba_idx
, u32 bt_chunk_num
)
100 u64 start_idx
= round_down(ba_idx
, bt_chunk_num
);
103 for (i
= 0; i
< bt_chunk_num
; i
++)
104 if (i
!= ba_idx
&& bt
[start_idx
+ i
])
110 static int hns_roce_get_bt_num(u32 table_type
, u32 hop_num
)
112 if (check_whether_bt_num_3(table_type
, hop_num
))
114 else if (check_whether_bt_num_2(table_type
, hop_num
))
116 else if (check_whether_bt_num_1(table_type
, hop_num
))
122 static int get_hem_table_config(struct hns_roce_dev
*hr_dev
,
123 struct hns_roce_hem_mhop
*mhop
,
126 struct device
*dev
= hr_dev
->dev
;
130 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.qpc_buf_pg_sz
132 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.qpc_ba_pg_sz
134 mhop
->ba_l0_num
= hr_dev
->caps
.qpc_bt_num
;
135 mhop
->hop_num
= hr_dev
->caps
.qpc_hop_num
;
138 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.mpt_buf_pg_sz
140 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.mpt_ba_pg_sz
142 mhop
->ba_l0_num
= hr_dev
->caps
.mpt_bt_num
;
143 mhop
->hop_num
= hr_dev
->caps
.mpt_hop_num
;
146 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.cqc_buf_pg_sz
148 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.cqc_ba_pg_sz
150 mhop
->ba_l0_num
= hr_dev
->caps
.cqc_bt_num
;
151 mhop
->hop_num
= hr_dev
->caps
.cqc_hop_num
;
154 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.sccc_buf_pg_sz
156 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.sccc_ba_pg_sz
158 mhop
->ba_l0_num
= hr_dev
->caps
.sccc_bt_num
;
159 mhop
->hop_num
= hr_dev
->caps
.sccc_hop_num
;
161 case HEM_TYPE_QPC_TIMER
:
162 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.qpc_timer_buf_pg_sz
164 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.qpc_timer_ba_pg_sz
166 mhop
->ba_l0_num
= hr_dev
->caps
.qpc_timer_bt_num
;
167 mhop
->hop_num
= hr_dev
->caps
.qpc_timer_hop_num
;
169 case HEM_TYPE_CQC_TIMER
:
170 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.cqc_timer_buf_pg_sz
172 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.cqc_timer_ba_pg_sz
174 mhop
->ba_l0_num
= hr_dev
->caps
.cqc_timer_bt_num
;
175 mhop
->hop_num
= hr_dev
->caps
.cqc_timer_hop_num
;
178 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.srqc_buf_pg_sz
180 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.srqc_ba_pg_sz
182 mhop
->ba_l0_num
= hr_dev
->caps
.srqc_bt_num
;
183 mhop
->hop_num
= hr_dev
->caps
.srqc_hop_num
;
186 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.gmv_buf_pg_sz
+
188 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.gmv_ba_pg_sz
+
190 mhop
->ba_l0_num
= hr_dev
->caps
.gmv_bt_num
;
191 mhop
->hop_num
= hr_dev
->caps
.gmv_hop_num
;
194 dev_err(dev
, "table %u not support multi-hop addressing!\n",
202 int hns_roce_calc_hem_mhop(struct hns_roce_dev
*hr_dev
,
203 struct hns_roce_hem_table
*table
, unsigned long *obj
,
204 struct hns_roce_hem_mhop
*mhop
)
206 struct device
*dev
= hr_dev
->dev
;
212 if (get_hem_table_config(hr_dev
, mhop
, table
->type
))
219 * QPC/MTPT/CQC/SRQC/SCCC alloc hem for buffer pages.
220 * MTT/CQE alloc hem for bt pages.
222 bt_num
= hns_roce_get_bt_num(table
->type
, mhop
->hop_num
);
223 chunk_ba_num
= mhop
->bt_chunk_size
/ BA_BYTE_LEN
;
224 chunk_size
= table
->type
< HEM_TYPE_MTT
? mhop
->buf_chunk_size
:
226 table_idx
= *obj
/ (chunk_size
/ table
->obj_size
);
229 mhop
->l2_idx
= table_idx
& (chunk_ba_num
- 1);
230 mhop
->l1_idx
= table_idx
/ chunk_ba_num
& (chunk_ba_num
- 1);
231 mhop
->l0_idx
= (table_idx
/ chunk_ba_num
) / chunk_ba_num
;
234 mhop
->l1_idx
= table_idx
& (chunk_ba_num
- 1);
235 mhop
->l0_idx
= table_idx
/ chunk_ba_num
;
238 mhop
->l0_idx
= table_idx
;
241 dev_err(dev
, "table %u not support hop_num = %u!\n",
242 table
->type
, mhop
->hop_num
);
245 if (mhop
->l0_idx
>= mhop
->ba_l0_num
)
246 mhop
->l0_idx
%= mhop
->ba_l0_num
;
251 static struct hns_roce_hem
*hns_roce_alloc_hem(struct hns_roce_dev
*hr_dev
,
252 unsigned long hem_alloc_size
,
255 struct hns_roce_hem
*hem
;
259 WARN_ON(gfp_mask
& __GFP_HIGHMEM
);
261 order
= get_order(hem_alloc_size
);
262 if (PAGE_SIZE
<< order
!= hem_alloc_size
) {
263 dev_err(hr_dev
->dev
, "invalid hem_alloc_size: %lu!\n",
268 hem
= kmalloc(sizeof(*hem
),
269 gfp_mask
& ~(__GFP_HIGHMEM
| __GFP_NOWARN
));
273 buf
= dma_alloc_coherent(hr_dev
->dev
, hem_alloc_size
,
274 &hem
->dma
, gfp_mask
);
279 hem
->size
= hem_alloc_size
;
288 void hns_roce_free_hem(struct hns_roce_dev
*hr_dev
, struct hns_roce_hem
*hem
)
293 dma_free_coherent(hr_dev
->dev
, hem
->size
, hem
->buf
, hem
->dma
);
298 static int calc_hem_config(struct hns_roce_dev
*hr_dev
,
299 struct hns_roce_hem_table
*table
, unsigned long obj
,
300 struct hns_roce_hem_mhop
*mhop
,
301 struct hns_roce_hem_index
*index
)
303 struct device
*dev
= hr_dev
->dev
;
304 unsigned long mhop_obj
= obj
;
305 u32 l0_idx
, l1_idx
, l2_idx
;
310 ret
= hns_roce_calc_hem_mhop(hr_dev
, table
, &mhop_obj
, mhop
);
314 l0_idx
= mhop
->l0_idx
;
315 l1_idx
= mhop
->l1_idx
;
316 l2_idx
= mhop
->l2_idx
;
317 chunk_ba_num
= mhop
->bt_chunk_size
/ BA_BYTE_LEN
;
318 bt_num
= hns_roce_get_bt_num(table
->type
, mhop
->hop_num
);
321 index
->l1
= l0_idx
* chunk_ba_num
+ l1_idx
;
323 index
->buf
= l0_idx
* chunk_ba_num
* chunk_ba_num
+
324 l1_idx
* chunk_ba_num
+ l2_idx
;
328 index
->buf
= l0_idx
* chunk_ba_num
+ l1_idx
;
334 dev_err(dev
, "table %u not support mhop.hop_num = %u!\n",
335 table
->type
, mhop
->hop_num
);
339 if (unlikely(index
->buf
>= table
->num_hem
)) {
340 dev_err(dev
, "table %u exceed hem limt idx %llu, max %lu!\n",
341 table
->type
, index
->buf
, table
->num_hem
);
348 static void free_mhop_hem(struct hns_roce_dev
*hr_dev
,
349 struct hns_roce_hem_table
*table
,
350 struct hns_roce_hem_mhop
*mhop
,
351 struct hns_roce_hem_index
*index
)
353 u32 bt_size
= mhop
->bt_chunk_size
;
354 struct device
*dev
= hr_dev
->dev
;
356 if (index
->inited
& HEM_INDEX_BUF
) {
357 hns_roce_free_hem(hr_dev
, table
->hem
[index
->buf
]);
358 table
->hem
[index
->buf
] = NULL
;
361 if (index
->inited
& HEM_INDEX_L1
) {
362 dma_free_coherent(dev
, bt_size
, table
->bt_l1
[index
->l1
],
363 table
->bt_l1_dma_addr
[index
->l1
]);
364 table
->bt_l1
[index
->l1
] = NULL
;
367 if (index
->inited
& HEM_INDEX_L0
) {
368 dma_free_coherent(dev
, bt_size
, table
->bt_l0
[index
->l0
],
369 table
->bt_l0_dma_addr
[index
->l0
]);
370 table
->bt_l0
[index
->l0
] = NULL
;
374 static int alloc_mhop_hem(struct hns_roce_dev
*hr_dev
,
375 struct hns_roce_hem_table
*table
,
376 struct hns_roce_hem_mhop
*mhop
,
377 struct hns_roce_hem_index
*index
)
379 u32 bt_size
= mhop
->bt_chunk_size
;
380 struct device
*dev
= hr_dev
->dev
;
386 /* alloc L1 BA's chunk */
387 if ((check_whether_bt_num_3(table
->type
, mhop
->hop_num
) ||
388 check_whether_bt_num_2(table
->type
, mhop
->hop_num
)) &&
389 !table
->bt_l0
[index
->l0
]) {
390 table
->bt_l0
[index
->l0
] = dma_alloc_coherent(dev
, bt_size
,
391 &table
->bt_l0_dma_addr
[index
->l0
],
393 if (!table
->bt_l0
[index
->l0
]) {
397 index
->inited
|= HEM_INDEX_L0
;
400 /* alloc L2 BA's chunk */
401 if (check_whether_bt_num_3(table
->type
, mhop
->hop_num
) &&
402 !table
->bt_l1
[index
->l1
]) {
403 table
->bt_l1
[index
->l1
] = dma_alloc_coherent(dev
, bt_size
,
404 &table
->bt_l1_dma_addr
[index
->l1
],
406 if (!table
->bt_l1
[index
->l1
]) {
410 index
->inited
|= HEM_INDEX_L1
;
411 *(table
->bt_l0
[index
->l0
] + mhop
->l1_idx
) =
412 table
->bt_l1_dma_addr
[index
->l1
];
416 * alloc buffer space chunk for QPC/MTPT/CQC/SRQC/SCCC.
417 * alloc bt space chunk for MTT/CQE.
419 size
= table
->type
< HEM_TYPE_MTT
? mhop
->buf_chunk_size
: bt_size
;
420 flag
= GFP_KERNEL
| __GFP_NOWARN
;
421 table
->hem
[index
->buf
] = hns_roce_alloc_hem(hr_dev
, size
, flag
);
422 if (!table
->hem
[index
->buf
]) {
427 index
->inited
|= HEM_INDEX_BUF
;
428 bt_ba
= table
->hem
[index
->buf
]->dma
;
430 if (table
->type
< HEM_TYPE_MTT
) {
431 if (mhop
->hop_num
== 2)
432 *(table
->bt_l1
[index
->l1
] + mhop
->l2_idx
) = bt_ba
;
433 else if (mhop
->hop_num
== 1)
434 *(table
->bt_l0
[index
->l0
] + mhop
->l1_idx
) = bt_ba
;
435 } else if (mhop
->hop_num
== 2) {
436 *(table
->bt_l0
[index
->l0
] + mhop
->l1_idx
) = bt_ba
;
441 free_mhop_hem(hr_dev
, table
, mhop
, index
);
446 static int set_mhop_hem(struct hns_roce_dev
*hr_dev
,
447 struct hns_roce_hem_table
*table
, unsigned long obj
,
448 struct hns_roce_hem_mhop
*mhop
,
449 struct hns_roce_hem_index
*index
)
451 struct device
*dev
= hr_dev
->dev
;
455 if (index
->inited
& HEM_INDEX_L0
) {
456 ret
= hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, 0);
458 dev_err(dev
, "set HEM step 0 failed!\n");
463 if (index
->inited
& HEM_INDEX_L1
) {
464 ret
= hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, 1);
466 dev_err(dev
, "set HEM step 1 failed!\n");
471 if (index
->inited
& HEM_INDEX_BUF
) {
472 if (mhop
->hop_num
== HNS_ROCE_HOP_NUM_0
)
475 step_idx
= mhop
->hop_num
;
476 ret
= hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, step_idx
);
478 dev_err(dev
, "set HEM step last failed!\n");
484 static int hns_roce_table_mhop_get(struct hns_roce_dev
*hr_dev
,
485 struct hns_roce_hem_table
*table
,
488 struct hns_roce_hem_index index
= {};
489 struct hns_roce_hem_mhop mhop
= {};
490 struct device
*dev
= hr_dev
->dev
;
493 ret
= calc_hem_config(hr_dev
, table
, obj
, &mhop
, &index
);
495 dev_err(dev
, "calc hem config failed!\n");
499 mutex_lock(&table
->mutex
);
500 if (table
->hem
[index
.buf
]) {
501 refcount_inc(&table
->hem
[index
.buf
]->refcount
);
505 ret
= alloc_mhop_hem(hr_dev
, table
, &mhop
, &index
);
507 dev_err(dev
, "alloc mhop hem failed!\n");
511 /* set HEM base address to hardware */
512 if (table
->type
< HEM_TYPE_MTT
) {
513 ret
= set_mhop_hem(hr_dev
, table
, obj
, &mhop
, &index
);
515 dev_err(dev
, "set HEM address to HW failed!\n");
520 refcount_set(&table
->hem
[index
.buf
]->refcount
, 1);
524 free_mhop_hem(hr_dev
, table
, &mhop
, &index
);
526 mutex_unlock(&table
->mutex
);
530 int hns_roce_table_get(struct hns_roce_dev
*hr_dev
,
531 struct hns_roce_hem_table
*table
, unsigned long obj
)
533 struct device
*dev
= hr_dev
->dev
;
537 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
))
538 return hns_roce_table_mhop_get(hr_dev
, table
, obj
);
540 i
= obj
/ (table
->table_chunk_size
/ table
->obj_size
);
542 mutex_lock(&table
->mutex
);
545 refcount_inc(&table
->hem
[i
]->refcount
);
549 table
->hem
[i
] = hns_roce_alloc_hem(hr_dev
,
550 table
->table_chunk_size
,
551 GFP_KERNEL
| __GFP_NOWARN
);
552 if (!table
->hem
[i
]) {
557 /* Set HEM base address(128K/page, pa) to Hardware */
558 ret
= hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, HEM_HOP_STEP_DIRECT
);
560 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
561 table
->hem
[i
] = NULL
;
562 dev_err(dev
, "set HEM base address to HW failed, ret = %d.\n",
567 refcount_set(&table
->hem
[i
]->refcount
, 1);
569 mutex_unlock(&table
->mutex
);
573 static void clear_mhop_hem(struct hns_roce_dev
*hr_dev
,
574 struct hns_roce_hem_table
*table
, unsigned long obj
,
575 struct hns_roce_hem_mhop
*mhop
,
576 struct hns_roce_hem_index
*index
)
578 struct device
*dev
= hr_dev
->dev
;
579 u32 hop_num
= mhop
->hop_num
;
584 index
->inited
= HEM_INDEX_BUF
;
585 chunk_ba_num
= mhop
->bt_chunk_size
/ BA_BYTE_LEN
;
586 if (check_whether_bt_num_2(table
->type
, hop_num
)) {
587 if (hns_roce_check_hem_null(table
->hem
, index
->buf
,
588 chunk_ba_num
, table
->num_hem
))
589 index
->inited
|= HEM_INDEX_L0
;
590 } else if (check_whether_bt_num_3(table
->type
, hop_num
)) {
591 if (hns_roce_check_hem_null(table
->hem
, index
->buf
,
592 chunk_ba_num
, table
->num_hem
)) {
593 index
->inited
|= HEM_INDEX_L1
;
594 if (hns_roce_check_bt_null(table
->bt_l1
, index
->l1
,
596 index
->inited
|= HEM_INDEX_L0
;
600 if (table
->type
< HEM_TYPE_MTT
) {
601 if (hop_num
== HNS_ROCE_HOP_NUM_0
)
606 ret
= hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, step_idx
);
608 dev_warn(dev
, "failed to clear hop%u HEM, ret = %d.\n",
611 if (index
->inited
& HEM_INDEX_L1
) {
612 ret
= hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 1);
614 dev_warn(dev
, "failed to clear HEM step 1, ret = %d.\n",
618 if (index
->inited
& HEM_INDEX_L0
) {
619 ret
= hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 0);
621 dev_warn(dev
, "failed to clear HEM step 0, ret = %d.\n",
627 static void hns_roce_table_mhop_put(struct hns_roce_dev
*hr_dev
,
628 struct hns_roce_hem_table
*table
,
632 struct hns_roce_hem_index index
= {};
633 struct hns_roce_hem_mhop mhop
= {};
634 struct device
*dev
= hr_dev
->dev
;
637 ret
= calc_hem_config(hr_dev
, table
, obj
, &mhop
, &index
);
639 dev_err(dev
, "calc hem config failed!\n");
644 mutex_lock(&table
->mutex
);
645 else if (!refcount_dec_and_mutex_lock(&table
->hem
[index
.buf
]->refcount
,
649 clear_mhop_hem(hr_dev
, table
, obj
, &mhop
, &index
);
650 free_mhop_hem(hr_dev
, table
, &mhop
, &index
);
652 mutex_unlock(&table
->mutex
);
655 void hns_roce_table_put(struct hns_roce_dev
*hr_dev
,
656 struct hns_roce_hem_table
*table
, unsigned long obj
)
658 struct device
*dev
= hr_dev
->dev
;
662 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
663 hns_roce_table_mhop_put(hr_dev
, table
, obj
, 1);
667 i
= obj
/ (table
->table_chunk_size
/ table
->obj_size
);
669 if (!refcount_dec_and_mutex_lock(&table
->hem
[i
]->refcount
,
673 ret
= hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, HEM_HOP_STEP_DIRECT
);
675 dev_warn_ratelimited(dev
, "failed to clear HEM base address, ret = %d.\n",
678 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
679 table
->hem
[i
] = NULL
;
681 mutex_unlock(&table
->mutex
);
684 void *hns_roce_table_find(struct hns_roce_dev
*hr_dev
,
685 struct hns_roce_hem_table
*table
,
686 unsigned long obj
, dma_addr_t
*dma_handle
)
688 struct hns_roce_hem_mhop mhop
;
689 struct hns_roce_hem
*hem
;
690 unsigned long mhop_obj
= obj
;
691 unsigned long obj_per_chunk
;
692 unsigned long idx_offset
;
693 int offset
, dma_offset
;
698 mutex_lock(&table
->mutex
);
700 if (!hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
701 obj_per_chunk
= table
->table_chunk_size
/ table
->obj_size
;
702 hem
= table
->hem
[obj
/ obj_per_chunk
];
703 idx_offset
= obj
% obj_per_chunk
;
704 dma_offset
= offset
= idx_offset
* table
->obj_size
;
706 u32 seg_size
= 64; /* 8 bytes per BA and 8 BA per segment */
708 if (hns_roce_calc_hem_mhop(hr_dev
, table
, &mhop_obj
, &mhop
))
713 if (mhop
.hop_num
== 2)
714 hem_idx
= i
* (mhop
.bt_chunk_size
/ BA_BYTE_LEN
) + j
;
715 else if (mhop
.hop_num
== 1 ||
716 mhop
.hop_num
== HNS_ROCE_HOP_NUM_0
)
719 hem
= table
->hem
[hem_idx
];
720 dma_offset
= offset
= obj
* seg_size
% mhop
.bt_chunk_size
;
721 if (mhop
.hop_num
== 2)
722 dma_offset
= offset
= 0;
728 *dma_handle
= hem
->dma
+ dma_offset
;
729 addr
= hem
->buf
+ offset
;
732 mutex_unlock(&table
->mutex
);
736 int hns_roce_init_hem_table(struct hns_roce_dev
*hr_dev
,
737 struct hns_roce_hem_table
*table
, u32 type
,
738 unsigned long obj_size
, unsigned long nobj
)
740 unsigned long obj_per_chunk
;
741 unsigned long num_hem
;
743 if (!hns_roce_check_whether_mhop(hr_dev
, type
)) {
744 table
->table_chunk_size
= hr_dev
->caps
.chunk_sz
;
745 obj_per_chunk
= table
->table_chunk_size
/ obj_size
;
746 num_hem
= DIV_ROUND_UP(nobj
, obj_per_chunk
);
748 table
->hem
= kcalloc(num_hem
, sizeof(*table
->hem
), GFP_KERNEL
);
752 struct hns_roce_hem_mhop mhop
= {};
753 unsigned long buf_chunk_size
;
754 unsigned long bt_chunk_size
;
755 unsigned long bt_chunk_num
;
756 unsigned long num_bt_l0
;
759 if (get_hem_table_config(hr_dev
, &mhop
, type
))
762 buf_chunk_size
= mhop
.buf_chunk_size
;
763 bt_chunk_size
= mhop
.bt_chunk_size
;
764 num_bt_l0
= mhop
.ba_l0_num
;
765 hop_num
= mhop
.hop_num
;
767 obj_per_chunk
= buf_chunk_size
/ obj_size
;
768 num_hem
= DIV_ROUND_UP(nobj
, obj_per_chunk
);
769 bt_chunk_num
= bt_chunk_size
/ BA_BYTE_LEN
;
771 if (type
>= HEM_TYPE_MTT
)
772 num_bt_l0
= bt_chunk_num
;
774 table
->hem
= kcalloc(num_hem
, sizeof(*table
->hem
),
777 goto err_kcalloc_hem_buf
;
779 if (check_whether_bt_num_3(type
, hop_num
)) {
780 unsigned long num_bt_l1
;
782 num_bt_l1
= DIV_ROUND_UP(num_hem
, bt_chunk_num
);
783 table
->bt_l1
= kcalloc(num_bt_l1
,
784 sizeof(*table
->bt_l1
),
787 goto err_kcalloc_bt_l1
;
789 table
->bt_l1_dma_addr
= kcalloc(num_bt_l1
,
790 sizeof(*table
->bt_l1_dma_addr
),
793 if (!table
->bt_l1_dma_addr
)
794 goto err_kcalloc_l1_dma
;
797 if (check_whether_bt_num_2(type
, hop_num
) ||
798 check_whether_bt_num_3(type
, hop_num
)) {
799 table
->bt_l0
= kcalloc(num_bt_l0
, sizeof(*table
->bt_l0
),
802 goto err_kcalloc_bt_l0
;
804 table
->bt_l0_dma_addr
= kcalloc(num_bt_l0
,
805 sizeof(*table
->bt_l0_dma_addr
),
807 if (!table
->bt_l0_dma_addr
)
808 goto err_kcalloc_l0_dma
;
813 table
->num_hem
= num_hem
;
814 table
->obj_size
= obj_size
;
815 mutex_init(&table
->mutex
);
824 kfree(table
->bt_l1_dma_addr
);
825 table
->bt_l1_dma_addr
= NULL
;
839 static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev
*hr_dev
,
840 struct hns_roce_hem_table
*table
)
842 struct hns_roce_hem_mhop mhop
;
847 if (hns_roce_calc_hem_mhop(hr_dev
, table
, NULL
, &mhop
))
849 buf_chunk_size
= table
->type
< HEM_TYPE_MTT
? mhop
.buf_chunk_size
:
852 for (i
= 0; i
< table
->num_hem
; ++i
) {
853 obj
= i
* buf_chunk_size
/ table
->obj_size
;
855 hns_roce_table_mhop_put(hr_dev
, table
, obj
, 0);
862 kfree(table
->bt_l1_dma_addr
);
863 table
->bt_l1_dma_addr
= NULL
;
866 kfree(table
->bt_l0_dma_addr
);
867 table
->bt_l0_dma_addr
= NULL
;
870 void hns_roce_cleanup_hem_table(struct hns_roce_dev
*hr_dev
,
871 struct hns_roce_hem_table
*table
)
873 struct device
*dev
= hr_dev
->dev
;
878 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
879 hns_roce_cleanup_mhop_hem_table(hr_dev
, table
);
880 mutex_destroy(&table
->mutex
);
884 for (i
= 0; i
< table
->num_hem
; ++i
)
886 obj
= i
* table
->table_chunk_size
/ table
->obj_size
;
887 ret
= hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 0);
889 dev_err(dev
, "clear HEM base address failed, ret = %d.\n",
892 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
895 mutex_destroy(&table
->mutex
);
899 void hns_roce_cleanup_hem(struct hns_roce_dev
*hr_dev
)
901 if (hr_dev
->caps
.flags
& HNS_ROCE_CAP_FLAG_SRQ
)
902 hns_roce_cleanup_hem_table(hr_dev
,
903 &hr_dev
->srq_table
.table
);
904 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->cq_table
.table
);
905 if (hr_dev
->caps
.qpc_timer_entry_sz
)
906 hns_roce_cleanup_hem_table(hr_dev
,
907 &hr_dev
->qpc_timer_table
);
908 if (hr_dev
->caps
.cqc_timer_entry_sz
)
909 hns_roce_cleanup_hem_table(hr_dev
,
910 &hr_dev
->cqc_timer_table
);
911 if (hr_dev
->caps
.flags
& HNS_ROCE_CAP_FLAG_QP_FLOW_CTRL
)
912 hns_roce_cleanup_hem_table(hr_dev
,
913 &hr_dev
->qp_table
.sccc_table
);
914 if (hr_dev
->caps
.trrl_entry_sz
)
915 hns_roce_cleanup_hem_table(hr_dev
,
916 &hr_dev
->qp_table
.trrl_table
);
918 if (hr_dev
->caps
.gmv_entry_sz
)
919 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->gmv_table
);
921 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->qp_table
.irrl_table
);
922 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->qp_table
.qp_table
);
923 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->mr_table
.mtpt_table
);
926 struct hns_roce_hem_item
{
927 struct list_head list
; /* link all hems in the same bt level */
928 struct list_head sibling
; /* link all hems in last hop for mtt */
931 size_t count
; /* max ba numbers */
932 int start
; /* start buf offset in this hem */
933 int end
; /* end buf offset in this hem */
936 /* All HEM items are linked in a tree structure */
937 struct hns_roce_hem_head
{
938 struct list_head branch
[HNS_ROCE_MAX_BT_REGION
];
939 struct list_head root
;
940 struct list_head leaf
;
943 static struct hns_roce_hem_item
*
944 hem_list_alloc_item(struct hns_roce_dev
*hr_dev
, int start
, int end
, int count
,
947 struct hns_roce_hem_item
*hem
;
949 hem
= kzalloc(sizeof(*hem
), GFP_KERNEL
);
954 hem
->addr
= dma_alloc_coherent(hr_dev
->dev
, count
* BA_BYTE_LEN
,
955 &hem
->dma_addr
, GFP_KERNEL
);
965 INIT_LIST_HEAD(&hem
->list
);
966 INIT_LIST_HEAD(&hem
->sibling
);
971 static void hem_list_free_item(struct hns_roce_dev
*hr_dev
,
972 struct hns_roce_hem_item
*hem
, bool exist_bt
)
975 dma_free_coherent(hr_dev
->dev
, hem
->count
* BA_BYTE_LEN
,
976 hem
->addr
, hem
->dma_addr
);
980 static void hem_list_free_all(struct hns_roce_dev
*hr_dev
,
981 struct list_head
*head
, bool exist_bt
)
983 struct hns_roce_hem_item
*hem
, *temp_hem
;
985 list_for_each_entry_safe(hem
, temp_hem
, head
, list
) {
986 list_del(&hem
->list
);
987 hem_list_free_item(hr_dev
, hem
, exist_bt
);
991 static void hem_list_link_bt(void *base_addr
, u64 table_addr
)
993 *(u64
*)(base_addr
) = table_addr
;
996 /* assign L0 table address to hem from root bt */
997 static void hem_list_assign_bt(struct hns_roce_hem_item
*hem
, void *cpu_addr
,
1000 hem
->addr
= cpu_addr
;
1001 hem
->dma_addr
= (dma_addr_t
)phy_addr
;
1004 static inline bool hem_list_page_is_in_range(struct hns_roce_hem_item
*hem
,
1007 return (hem
->start
<= offset
&& offset
<= hem
->end
);
1010 static struct hns_roce_hem_item
*hem_list_search_item(struct list_head
*ba_list
,
1013 struct hns_roce_hem_item
*hem
, *temp_hem
;
1014 struct hns_roce_hem_item
*found
= NULL
;
1016 list_for_each_entry_safe(hem
, temp_hem
, ba_list
, list
) {
1017 if (hem_list_page_is_in_range(hem
, page_offset
)) {
1026 static bool hem_list_is_bottom_bt(int hopnum
, int bt_level
)
1029 * hopnum base address table levels
1033 * 3 L0 -> L1 -> L2 -> buf
1035 return bt_level
>= (hopnum
? hopnum
- 1 : hopnum
);
1039 * calc base address entries num
1040 * @hopnum: num of mutihop addressing
1041 * @bt_level: base address table level
1042 * @unit: ba entries per bt page
1044 static u64
hem_list_calc_ba_range(int hopnum
, int bt_level
, int unit
)
1050 if (hopnum
<= bt_level
)
1053 * hopnum bt_level range
1059 * 3 0 unit * unit * unit
1064 max
= hopnum
- bt_level
;
1065 for (i
= 0; i
< max
; i
++)
1072 * calc the root ba entries which could cover all regions
1073 * @regions: buf region array
1074 * @region_cnt: array size of @regions
1075 * @unit: ba entries per bt page
1077 int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region
*regions
,
1078 int region_cnt
, int unit
)
1080 struct hns_roce_buf_region
*r
;
1085 for (i
= 0; i
< region_cnt
; i
++) {
1086 r
= (struct hns_roce_buf_region
*)®ions
[i
];
1087 if (r
->hopnum
> 1) {
1088 step
= hem_list_calc_ba_range(r
->hopnum
, 1, unit
);
1090 total
+= (r
->count
+ step
- 1) / step
;
1099 static int hem_list_alloc_mid_bt(struct hns_roce_dev
*hr_dev
,
1100 const struct hns_roce_buf_region
*r
, int unit
,
1101 int offset
, struct list_head
*mid_bt
,
1102 struct list_head
*btm_bt
)
1104 struct hns_roce_hem_item
*hem_ptrs
[HNS_ROCE_MAX_BT_LEVEL
] = { NULL
};
1105 struct list_head temp_list
[HNS_ROCE_MAX_BT_LEVEL
];
1106 struct hns_roce_hem_item
*cur
, *pre
;
1107 const int hopnum
= r
->hopnum
;
1119 if (hopnum
> HNS_ROCE_MAX_BT_LEVEL
) {
1120 dev_err(hr_dev
->dev
, "invalid hopnum %d!\n", hopnum
);
1124 if (offset
< r
->offset
) {
1125 dev_err(hr_dev
->dev
, "invalid offset %d, min %u!\n",
1130 distance
= offset
- r
->offset
;
1131 max_ofs
= r
->offset
+ r
->count
- 1;
1132 for (level
= 0; level
< hopnum
; level
++)
1133 INIT_LIST_HEAD(&temp_list
[level
]);
1135 /* config L1 bt to last bt and link them to corresponding parent */
1136 for (level
= 1; level
< hopnum
; level
++) {
1137 if (!hem_list_is_bottom_bt(hopnum
, level
)) {
1138 cur
= hem_list_search_item(&mid_bt
[level
], offset
);
1140 hem_ptrs
[level
] = cur
;
1145 step
= hem_list_calc_ba_range(hopnum
, level
, unit
);
1151 start_aligned
= (distance
/ step
) * step
+ r
->offset
;
1152 end
= min_t(u64
, start_aligned
+ step
- 1, max_ofs
);
1153 cur
= hem_list_alloc_item(hr_dev
, start_aligned
, end
, unit
,
1159 hem_ptrs
[level
] = cur
;
1160 list_add(&cur
->list
, &temp_list
[level
]);
1161 if (hem_list_is_bottom_bt(hopnum
, level
))
1162 list_add(&cur
->sibling
, &temp_list
[0]);
1164 /* link bt to parent bt */
1166 pre
= hem_ptrs
[level
- 1];
1167 step
= (cur
->start
- pre
->start
) / step
* BA_BYTE_LEN
;
1168 hem_list_link_bt(pre
->addr
+ step
, cur
->dma_addr
);
1172 list_splice(&temp_list
[0], btm_bt
);
1173 for (level
= 1; level
< hopnum
; level
++)
1174 list_splice(&temp_list
[level
], &mid_bt
[level
]);
1179 for (level
= 1; level
< hopnum
; level
++)
1180 hem_list_free_all(hr_dev
, &temp_list
[level
], true);
1185 static struct hns_roce_hem_item
*
1186 alloc_root_hem(struct hns_roce_dev
*hr_dev
, int unit
, int *max_ba_num
,
1187 const struct hns_roce_buf_region
*regions
, int region_cnt
)
1189 const struct hns_roce_buf_region
*r
;
1190 struct hns_roce_hem_item
*hem
;
1194 ba_num
= hns_roce_hem_list_calc_root_ba(regions
, region_cnt
, unit
);
1196 return ERR_PTR(-ENOMEM
);
1199 return ERR_PTR(-ENOBUFS
);
1201 offset
= regions
[0].offset
;
1202 /* indicate to last region */
1203 r
= ®ions
[region_cnt
- 1];
1204 hem
= hem_list_alloc_item(hr_dev
, offset
, r
->offset
+ r
->count
- 1,
1207 return ERR_PTR(-ENOMEM
);
1209 *max_ba_num
= ba_num
;
1214 static int alloc_fake_root_bt(struct hns_roce_dev
*hr_dev
, void *cpu_base
,
1215 u64 phy_base
, const struct hns_roce_buf_region
*r
,
1216 struct list_head
*branch_head
,
1217 struct list_head
*leaf_head
)
1219 struct hns_roce_hem_item
*hem
;
1221 hem
= hem_list_alloc_item(hr_dev
, r
->offset
, r
->offset
+ r
->count
- 1,
1226 hem_list_assign_bt(hem
, cpu_base
, phy_base
);
1227 list_add(&hem
->list
, branch_head
);
1228 list_add(&hem
->sibling
, leaf_head
);
1233 static int setup_middle_bt(struct hns_roce_dev
*hr_dev
, void *cpu_base
,
1234 int unit
, const struct hns_roce_buf_region
*r
,
1235 const struct list_head
*branch_head
)
1237 struct hns_roce_hem_item
*hem
, *temp_hem
;
1242 step
= hem_list_calc_ba_range(r
->hopnum
, 1, unit
);
1246 /* if exist mid bt, link L1 to L0 */
1247 list_for_each_entry_safe(hem
, temp_hem
, branch_head
, list
) {
1248 offset
= (hem
->start
- r
->offset
) / step
* BA_BYTE_LEN
;
1249 hem_list_link_bt(cpu_base
+ offset
, hem
->dma_addr
);
1257 setup_root_hem(struct hns_roce_dev
*hr_dev
, struct hns_roce_hem_list
*hem_list
,
1258 int unit
, int max_ba_num
, struct hns_roce_hem_head
*head
,
1259 const struct hns_roce_buf_region
*regions
, int region_cnt
)
1261 const struct hns_roce_buf_region
*r
;
1262 struct hns_roce_hem_item
*root_hem
;
1268 root_hem
= list_first_entry(&head
->root
,
1269 struct hns_roce_hem_item
, list
);
1274 for (i
= 0; i
< region_cnt
&& total
< max_ba_num
; i
++) {
1279 /* all regions's mid[x][0] shared the root_bt's trunk */
1280 cpu_base
= root_hem
->addr
+ total
* BA_BYTE_LEN
;
1281 phy_base
= root_hem
->dma_addr
+ total
* BA_BYTE_LEN
;
1283 /* if hopnum is 0 or 1, cut a new fake hem from the root bt
1284 * which's address share to all regions.
1286 if (hem_list_is_bottom_bt(r
->hopnum
, 0))
1287 ret
= alloc_fake_root_bt(hr_dev
, cpu_base
, phy_base
, r
,
1288 &head
->branch
[i
], &head
->leaf
);
1290 ret
= setup_middle_bt(hr_dev
, cpu_base
, unit
, r
,
1291 &hem_list
->mid_bt
[i
][1]);
1299 list_splice(&head
->leaf
, &hem_list
->btm_bt
);
1300 list_splice(&head
->root
, &hem_list
->root_bt
);
1301 for (i
= 0; i
< region_cnt
; i
++)
1302 list_splice(&head
->branch
[i
], &hem_list
->mid_bt
[i
][0]);
1307 static int hem_list_alloc_root_bt(struct hns_roce_dev
*hr_dev
,
1308 struct hns_roce_hem_list
*hem_list
, int unit
,
1309 const struct hns_roce_buf_region
*regions
,
1312 struct hns_roce_hem_item
*root_hem
;
1313 struct hns_roce_hem_head head
;
1318 root_hem
= hem_list_search_item(&hem_list
->root_bt
, regions
[0].offset
);
1323 root_hem
= alloc_root_hem(hr_dev
, unit
, &max_ba_num
, regions
,
1325 if (IS_ERR(root_hem
))
1326 return PTR_ERR(root_hem
);
1328 /* List head for storing all allocated HEM items */
1329 INIT_LIST_HEAD(&head
.root
);
1330 INIT_LIST_HEAD(&head
.leaf
);
1331 for (i
= 0; i
< region_cnt
; i
++)
1332 INIT_LIST_HEAD(&head
.branch
[i
]);
1334 hem_list
->root_ba
= root_hem
->dma_addr
;
1335 list_add(&root_hem
->list
, &head
.root
);
1336 ret
= setup_root_hem(hr_dev
, hem_list
, unit
, max_ba_num
, &head
, regions
,
1339 for (i
= 0; i
< region_cnt
; i
++)
1340 hem_list_free_all(hr_dev
, &head
.branch
[i
], false);
1342 hem_list_free_all(hr_dev
, &head
.root
, true);
1348 /* construct the base address table and link them by address hop config */
1349 int hns_roce_hem_list_request(struct hns_roce_dev
*hr_dev
,
1350 struct hns_roce_hem_list
*hem_list
,
1351 const struct hns_roce_buf_region
*regions
,
1352 int region_cnt
, unsigned int bt_pg_shift
)
1354 const struct hns_roce_buf_region
*r
;
1360 if (region_cnt
> HNS_ROCE_MAX_BT_REGION
) {
1361 dev_err(hr_dev
->dev
, "invalid region region_cnt %d!\n",
1366 unit
= (1 << bt_pg_shift
) / BA_BYTE_LEN
;
1367 for (i
= 0; i
< region_cnt
; i
++) {
1372 end
= r
->offset
+ r
->count
;
1373 for (ofs
= r
->offset
; ofs
< end
; ofs
+= unit
) {
1374 ret
= hem_list_alloc_mid_bt(hr_dev
, r
, unit
, ofs
,
1375 hem_list
->mid_bt
[i
],
1378 dev_err(hr_dev
->dev
,
1379 "alloc hem trunk fail ret = %d!\n", ret
);
1385 ret
= hem_list_alloc_root_bt(hr_dev
, hem_list
, unit
, regions
,
1388 dev_err(hr_dev
->dev
, "alloc hem root fail ret = %d!\n", ret
);
1393 hns_roce_hem_list_release(hr_dev
, hem_list
);
1398 void hns_roce_hem_list_release(struct hns_roce_dev
*hr_dev
,
1399 struct hns_roce_hem_list
*hem_list
)
1403 for (i
= 0; i
< HNS_ROCE_MAX_BT_REGION
; i
++)
1404 for (j
= 0; j
< HNS_ROCE_MAX_BT_LEVEL
; j
++)
1405 hem_list_free_all(hr_dev
, &hem_list
->mid_bt
[i
][j
],
1408 hem_list_free_all(hr_dev
, &hem_list
->root_bt
, true);
1409 INIT_LIST_HEAD(&hem_list
->btm_bt
);
1410 hem_list
->root_ba
= 0;
1413 void hns_roce_hem_list_init(struct hns_roce_hem_list
*hem_list
)
1417 INIT_LIST_HEAD(&hem_list
->root_bt
);
1418 INIT_LIST_HEAD(&hem_list
->btm_bt
);
1419 for (i
= 0; i
< HNS_ROCE_MAX_BT_REGION
; i
++)
1420 for (j
= 0; j
< HNS_ROCE_MAX_BT_LEVEL
; j
++)
1421 INIT_LIST_HEAD(&hem_list
->mid_bt
[i
][j
]);
1424 void *hns_roce_hem_list_find_mtt(struct hns_roce_dev
*hr_dev
,
1425 struct hns_roce_hem_list
*hem_list
,
1426 int offset
, int *mtt_cnt
)
1428 struct list_head
*head
= &hem_list
->btm_bt
;
1429 struct hns_roce_hem_item
*hem
, *temp_hem
;
1430 void *cpu_base
= NULL
;
1433 list_for_each_entry_safe(hem
, temp_hem
, head
, sibling
) {
1434 if (hem_list_page_is_in_range(hem
, offset
)) {
1435 nr
= offset
- hem
->start
;
1436 cpu_base
= hem
->addr
+ nr
* BA_BYTE_LEN
;
1437 nr
= hem
->end
+ 1 - offset
;