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 <linux/platform_device.h>
35 #include "hns_roce_device.h"
36 #include "hns_roce_hem.h"
37 #include "hns_roce_common.h"
39 #define DMA_ADDR_T_SHIFT 12
40 #define BT_BA_SHIFT 32
42 bool hns_roce_check_whether_mhop(struct hns_roce_dev
*hr_dev
, u32 type
)
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
.sccc_hop_num
&& type
== HEM_TYPE_SCCC
) ||
49 (hr_dev
->caps
.qpc_timer_hop_num
&& type
== HEM_TYPE_QPC_TIMER
) ||
50 (hr_dev
->caps
.cqc_timer_hop_num
&& type
== HEM_TYPE_CQC_TIMER
) ||
51 (hr_dev
->caps
.cqe_hop_num
&& type
== HEM_TYPE_CQE
) ||
52 (hr_dev
->caps
.mtt_hop_num
&& type
== HEM_TYPE_MTT
) ||
53 (hr_dev
->caps
.srqwqe_hop_num
&& type
== HEM_TYPE_SRQWQE
) ||
54 (hr_dev
->caps
.idx_hop_num
&& type
== HEM_TYPE_IDX
))
59 EXPORT_SYMBOL_GPL(hns_roce_check_whether_mhop
);
61 static bool hns_roce_check_hem_null(struct hns_roce_hem
**hem
, u64 start_idx
,
66 for (i
= 0; i
< bt_chunk_num
; i
++)
67 if (hem
[start_idx
+ i
])
73 static bool hns_roce_check_bt_null(u64
**bt
, u64 start_idx
, u32 bt_chunk_num
)
77 for (i
= 0; i
< bt_chunk_num
; i
++)
78 if (bt
[start_idx
+ i
])
84 static int hns_roce_get_bt_num(u32 table_type
, u32 hop_num
)
86 if (check_whether_bt_num_3(table_type
, hop_num
))
88 else if (check_whether_bt_num_2(table_type
, hop_num
))
90 else if (check_whether_bt_num_1(table_type
, hop_num
))
96 int hns_roce_calc_hem_mhop(struct hns_roce_dev
*hr_dev
,
97 struct hns_roce_hem_table
*table
, unsigned long *obj
,
98 struct hns_roce_hem_mhop
*mhop
)
100 struct device
*dev
= hr_dev
->dev
;
106 switch (table
->type
) {
108 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.qpc_buf_pg_sz
110 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.qpc_ba_pg_sz
112 mhop
->ba_l0_num
= hr_dev
->caps
.qpc_bt_num
;
113 mhop
->hop_num
= hr_dev
->caps
.qpc_hop_num
;
116 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.mpt_buf_pg_sz
118 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.mpt_ba_pg_sz
120 mhop
->ba_l0_num
= hr_dev
->caps
.mpt_bt_num
;
121 mhop
->hop_num
= hr_dev
->caps
.mpt_hop_num
;
124 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.cqc_buf_pg_sz
126 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.cqc_ba_pg_sz
128 mhop
->ba_l0_num
= hr_dev
->caps
.cqc_bt_num
;
129 mhop
->hop_num
= hr_dev
->caps
.cqc_hop_num
;
132 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.sccc_buf_pg_sz
134 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.sccc_ba_pg_sz
136 mhop
->ba_l0_num
= hr_dev
->caps
.sccc_bt_num
;
137 mhop
->hop_num
= hr_dev
->caps
.sccc_hop_num
;
139 case HEM_TYPE_QPC_TIMER
:
140 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.qpc_timer_buf_pg_sz
142 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.qpc_timer_ba_pg_sz
144 mhop
->ba_l0_num
= hr_dev
->caps
.qpc_timer_bt_num
;
145 mhop
->hop_num
= hr_dev
->caps
.qpc_timer_hop_num
;
147 case HEM_TYPE_CQC_TIMER
:
148 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.cqc_timer_buf_pg_sz
150 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.cqc_timer_ba_pg_sz
152 mhop
->ba_l0_num
= hr_dev
->caps
.cqc_timer_bt_num
;
153 mhop
->hop_num
= hr_dev
->caps
.cqc_timer_hop_num
;
156 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.srqc_buf_pg_sz
158 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.srqc_ba_pg_sz
160 mhop
->ba_l0_num
= hr_dev
->caps
.srqc_bt_num
;
161 mhop
->hop_num
= hr_dev
->caps
.srqc_hop_num
;
164 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.mtt_buf_pg_sz
166 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.mtt_ba_pg_sz
168 mhop
->ba_l0_num
= mhop
->bt_chunk_size
/ 8;
169 mhop
->hop_num
= hr_dev
->caps
.mtt_hop_num
;
172 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.cqe_buf_pg_sz
174 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.cqe_ba_pg_sz
176 mhop
->ba_l0_num
= mhop
->bt_chunk_size
/ 8;
177 mhop
->hop_num
= hr_dev
->caps
.cqe_hop_num
;
179 case HEM_TYPE_SRQWQE
:
180 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.srqwqe_buf_pg_sz
182 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.srqwqe_ba_pg_sz
184 mhop
->ba_l0_num
= mhop
->bt_chunk_size
/ 8;
185 mhop
->hop_num
= hr_dev
->caps
.srqwqe_hop_num
;
188 mhop
->buf_chunk_size
= 1 << (hr_dev
->caps
.idx_buf_pg_sz
190 mhop
->bt_chunk_size
= 1 << (hr_dev
->caps
.idx_ba_pg_sz
192 mhop
->ba_l0_num
= mhop
->bt_chunk_size
/ 8;
193 mhop
->hop_num
= hr_dev
->caps
.idx_hop_num
;
196 dev_err(dev
, "Table %d not support multi-hop addressing!\n",
205 * QPC/MTPT/CQC/SRQC/SCCC alloc hem for buffer pages.
206 * MTT/CQE alloc hem for bt pages.
208 bt_num
= hns_roce_get_bt_num(table
->type
, mhop
->hop_num
);
209 chunk_ba_num
= mhop
->bt_chunk_size
/ 8;
210 chunk_size
= table
->type
< HEM_TYPE_MTT
? mhop
->buf_chunk_size
:
212 table_idx
= (*obj
& (table
->num_obj
- 1)) /
213 (chunk_size
/ table
->obj_size
);
216 mhop
->l2_idx
= table_idx
& (chunk_ba_num
- 1);
217 mhop
->l1_idx
= table_idx
/ chunk_ba_num
& (chunk_ba_num
- 1);
218 mhop
->l0_idx
= (table_idx
/ chunk_ba_num
) / chunk_ba_num
;
221 mhop
->l1_idx
= table_idx
& (chunk_ba_num
- 1);
222 mhop
->l0_idx
= table_idx
/ chunk_ba_num
;
225 mhop
->l0_idx
= table_idx
;
228 dev_err(dev
, "Table %d not support hop_num = %d!\n",
229 table
->type
, mhop
->hop_num
);
232 if (mhop
->l0_idx
>= mhop
->ba_l0_num
)
233 mhop
->l0_idx
%= mhop
->ba_l0_num
;
237 EXPORT_SYMBOL_GPL(hns_roce_calc_hem_mhop
);
239 static struct hns_roce_hem
*hns_roce_alloc_hem(struct hns_roce_dev
*hr_dev
,
241 unsigned long hem_alloc_size
,
244 struct hns_roce_hem_chunk
*chunk
= NULL
;
245 struct hns_roce_hem
*hem
;
246 struct scatterlist
*mem
;
250 WARN_ON(gfp_mask
& __GFP_HIGHMEM
);
252 hem
= kmalloc(sizeof(*hem
),
253 gfp_mask
& ~(__GFP_HIGHMEM
| __GFP_NOWARN
));
258 INIT_LIST_HEAD(&hem
->chunk_list
);
260 order
= get_order(hem_alloc_size
);
264 chunk
= kmalloc(sizeof(*chunk
),
265 gfp_mask
& ~(__GFP_HIGHMEM
| __GFP_NOWARN
));
269 sg_init_table(chunk
->mem
, HNS_ROCE_HEM_CHUNK_LEN
);
272 memset(chunk
->buf
, 0, sizeof(chunk
->buf
));
273 list_add_tail(&chunk
->list
, &hem
->chunk_list
);
276 while (1 << order
> npages
)
280 * Alloc memory one time. If failed, don't alloc small block
281 * memory, directly return fail.
283 mem
= &chunk
->mem
[chunk
->npages
];
284 buf
= dma_alloc_coherent(hr_dev
->dev
, PAGE_SIZE
<< order
,
285 &sg_dma_address(mem
), gfp_mask
);
289 chunk
->buf
[chunk
->npages
] = buf
;
290 sg_dma_len(mem
) = PAGE_SIZE
<< order
;
294 npages
-= 1 << order
;
300 hns_roce_free_hem(hr_dev
, hem
);
304 void hns_roce_free_hem(struct hns_roce_dev
*hr_dev
, struct hns_roce_hem
*hem
)
306 struct hns_roce_hem_chunk
*chunk
, *tmp
;
312 list_for_each_entry_safe(chunk
, tmp
, &hem
->chunk_list
, list
) {
313 for (i
= 0; i
< chunk
->npages
; ++i
)
314 dma_free_coherent(hr_dev
->dev
,
315 sg_dma_len(&chunk
->mem
[i
]),
317 sg_dma_address(&chunk
->mem
[i
]));
324 static int hns_roce_set_hem(struct hns_roce_dev
*hr_dev
,
325 struct hns_roce_hem_table
*table
, unsigned long obj
)
327 spinlock_t
*lock
= &hr_dev
->bt_cmd_lock
;
328 struct device
*dev
= hr_dev
->dev
;
329 unsigned long end
= 0;
331 struct hns_roce_hem_iter iter
;
332 void __iomem
*bt_cmd
;
333 u32 bt_cmd_h_val
= 0;
339 /* Find the HEM(Hardware Entry Memory) entry */
340 unsigned long i
= (obj
& (table
->num_obj
- 1)) /
341 (table
->table_chunk_size
/ table
->obj_size
);
343 switch (table
->type
) {
345 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
346 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
, HEM_TYPE_QPC
);
349 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
350 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
,
354 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
355 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
, HEM_TYPE_CQC
);
358 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
359 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
,
365 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M
,
366 ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S
, obj
);
367 roce_set_bit(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S
, 0);
368 roce_set_bit(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S
, 1);
370 /* Currently iter only a chunk */
371 for (hns_roce_hem_first(table
->hem
[i
], &iter
);
372 !hns_roce_hem_last(&iter
); hns_roce_hem_next(&iter
)) {
373 bt_ba
= hns_roce_hem_addr(&iter
) >> DMA_ADDR_T_SHIFT
;
375 spin_lock_irqsave(lock
, flags
);
377 bt_cmd
= hr_dev
->reg_base
+ ROCEE_BT_CMD_H_REG
;
379 end
= msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS
) + jiffies
;
381 if (readl(bt_cmd
) >> BT_CMD_SYNC_SHIFT
) {
382 if (!(time_before(jiffies
, end
))) {
383 dev_err(dev
, "Write bt_cmd err,hw_sync is not zero.\n");
384 spin_unlock_irqrestore(lock
, flags
);
390 mdelay(HW_SYNC_SLEEP_TIME_INTERVAL
);
393 bt_cmd_l
= (u32
)bt_ba
;
394 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M
,
395 ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S
,
396 bt_ba
>> BT_BA_SHIFT
);
398 bt_cmd_val
[0] = bt_cmd_l
;
399 bt_cmd_val
[1] = bt_cmd_h_val
;
400 hns_roce_write64_k(bt_cmd_val
,
401 hr_dev
->reg_base
+ ROCEE_BT_CMD_L_REG
);
402 spin_unlock_irqrestore(lock
, flags
);
408 static int hns_roce_table_mhop_get(struct hns_roce_dev
*hr_dev
,
409 struct hns_roce_hem_table
*table
,
412 struct device
*dev
= hr_dev
->dev
;
413 struct hns_roce_hem_mhop mhop
;
414 struct hns_roce_hem_iter iter
;
425 unsigned long mhop_obj
= obj
;
426 int bt_l1_allocated
= 0;
427 int bt_l0_allocated
= 0;
431 ret
= hns_roce_calc_hem_mhop(hr_dev
, table
, &mhop_obj
, &mhop
);
435 buf_chunk_size
= mhop
.buf_chunk_size
;
436 bt_chunk_size
= mhop
.bt_chunk_size
;
437 hop_num
= mhop
.hop_num
;
438 chunk_ba_num
= bt_chunk_size
/ 8;
440 bt_num
= hns_roce_get_bt_num(table
->type
, hop_num
);
443 hem_idx
= mhop
.l0_idx
* chunk_ba_num
* chunk_ba_num
+
444 mhop
.l1_idx
* chunk_ba_num
+ mhop
.l2_idx
;
445 bt_l1_idx
= mhop
.l0_idx
* chunk_ba_num
+ mhop
.l1_idx
;
446 bt_l0_idx
= mhop
.l0_idx
;
449 hem_idx
= mhop
.l0_idx
* chunk_ba_num
+ mhop
.l1_idx
;
450 bt_l0_idx
= mhop
.l0_idx
;
453 hem_idx
= mhop
.l0_idx
;
456 dev_err(dev
, "Table %d not support hop_num = %d!\n",
457 table
->type
, hop_num
);
461 mutex_lock(&table
->mutex
);
463 if (table
->hem
[hem_idx
]) {
464 ++table
->hem
[hem_idx
]->refcount
;
468 /* alloc L1 BA's chunk */
469 if ((check_whether_bt_num_3(table
->type
, hop_num
) ||
470 check_whether_bt_num_2(table
->type
, hop_num
)) &&
471 !table
->bt_l0
[bt_l0_idx
]) {
472 table
->bt_l0
[bt_l0_idx
] = dma_alloc_coherent(dev
, bt_chunk_size
,
473 &(table
->bt_l0_dma_addr
[bt_l0_idx
]),
475 if (!table
->bt_l0
[bt_l0_idx
]) {
481 /* set base address to hardware */
482 if (table
->type
< HEM_TYPE_MTT
) {
484 if (hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, step_idx
)) {
486 dev_err(dev
, "set HEM base address to HW failed!\n");
487 goto err_dma_alloc_l1
;
492 /* alloc L2 BA's chunk */
493 if (check_whether_bt_num_3(table
->type
, hop_num
) &&
494 !table
->bt_l1
[bt_l1_idx
]) {
495 table
->bt_l1
[bt_l1_idx
] = dma_alloc_coherent(dev
, bt_chunk_size
,
496 &(table
->bt_l1_dma_addr
[bt_l1_idx
]),
498 if (!table
->bt_l1
[bt_l1_idx
]) {
500 goto err_dma_alloc_l1
;
503 *(table
->bt_l0
[bt_l0_idx
] + mhop
.l1_idx
) =
504 table
->bt_l1_dma_addr
[bt_l1_idx
];
506 /* set base address to hardware */
508 if (hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, step_idx
)) {
510 dev_err(dev
, "set HEM base address to HW failed!\n");
511 goto err_alloc_hem_buf
;
516 * alloc buffer space chunk for QPC/MTPT/CQC/SRQC/SCCC.
517 * alloc bt space chunk for MTT/CQE.
519 size
= table
->type
< HEM_TYPE_MTT
? buf_chunk_size
: bt_chunk_size
;
520 table
->hem
[hem_idx
] = hns_roce_alloc_hem(hr_dev
,
523 (table
->lowmem
? GFP_KERNEL
:
524 GFP_HIGHUSER
) | __GFP_NOWARN
);
525 if (!table
->hem
[hem_idx
]) {
527 goto err_alloc_hem_buf
;
530 hns_roce_hem_first(table
->hem
[hem_idx
], &iter
);
531 bt_ba
= hns_roce_hem_addr(&iter
);
533 if (table
->type
< HEM_TYPE_MTT
) {
535 *(table
->bt_l1
[bt_l1_idx
] + mhop
.l2_idx
) = bt_ba
;
537 } else if (hop_num
== 1) {
538 *(table
->bt_l0
[bt_l0_idx
] + mhop
.l1_idx
) = bt_ba
;
540 } else if (hop_num
== HNS_ROCE_HOP_NUM_0
) {
544 goto err_dma_alloc_l1
;
547 /* set HEM base address to hardware */
548 if (hr_dev
->hw
->set_hem(hr_dev
, table
, obj
, step_idx
)) {
550 dev_err(dev
, "set HEM base address to HW failed!\n");
551 goto err_alloc_hem_buf
;
553 } else if (hop_num
== 2) {
554 *(table
->bt_l0
[bt_l0_idx
] + mhop
.l1_idx
) = bt_ba
;
557 ++table
->hem
[hem_idx
]->refcount
;
561 if (bt_l1_allocated
) {
562 dma_free_coherent(dev
, bt_chunk_size
, table
->bt_l1
[bt_l1_idx
],
563 table
->bt_l1_dma_addr
[bt_l1_idx
]);
564 table
->bt_l1
[bt_l1_idx
] = NULL
;
568 if (bt_l0_allocated
) {
569 dma_free_coherent(dev
, bt_chunk_size
, table
->bt_l0
[bt_l0_idx
],
570 table
->bt_l0_dma_addr
[bt_l0_idx
]);
571 table
->bt_l0
[bt_l0_idx
] = NULL
;
575 mutex_unlock(&table
->mutex
);
579 int hns_roce_table_get(struct hns_roce_dev
*hr_dev
,
580 struct hns_roce_hem_table
*table
, unsigned long obj
)
582 struct device
*dev
= hr_dev
->dev
;
586 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
))
587 return hns_roce_table_mhop_get(hr_dev
, table
, obj
);
589 i
= (obj
& (table
->num_obj
- 1)) / (table
->table_chunk_size
/
592 mutex_lock(&table
->mutex
);
595 ++table
->hem
[i
]->refcount
;
599 table
->hem
[i
] = hns_roce_alloc_hem(hr_dev
,
600 table
->table_chunk_size
>> PAGE_SHIFT
,
601 table
->table_chunk_size
,
602 (table
->lowmem
? GFP_KERNEL
:
603 GFP_HIGHUSER
) | __GFP_NOWARN
);
604 if (!table
->hem
[i
]) {
609 /* Set HEM base address(128K/page, pa) to Hardware */
610 if (hns_roce_set_hem(hr_dev
, table
, obj
)) {
611 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
612 table
->hem
[i
] = NULL
;
614 dev_err(dev
, "set HEM base address to HW failed.\n");
618 ++table
->hem
[i
]->refcount
;
620 mutex_unlock(&table
->mutex
);
623 EXPORT_SYMBOL_GPL(hns_roce_table_get
);
625 static void hns_roce_table_mhop_put(struct hns_roce_dev
*hr_dev
,
626 struct hns_roce_hem_table
*table
,
630 struct device
*dev
= hr_dev
->dev
;
631 struct hns_roce_hem_mhop mhop
;
632 unsigned long mhop_obj
= obj
;
642 ret
= hns_roce_calc_hem_mhop(hr_dev
, table
, &mhop_obj
, &mhop
);
646 bt_chunk_size
= mhop
.bt_chunk_size
;
647 hop_num
= mhop
.hop_num
;
648 chunk_ba_num
= bt_chunk_size
/ 8;
650 bt_num
= hns_roce_get_bt_num(table
->type
, hop_num
);
653 hem_idx
= mhop
.l0_idx
* chunk_ba_num
* chunk_ba_num
+
654 mhop
.l1_idx
* chunk_ba_num
+ mhop
.l2_idx
;
655 bt_l1_idx
= mhop
.l0_idx
* chunk_ba_num
+ mhop
.l1_idx
;
658 hem_idx
= mhop
.l0_idx
* chunk_ba_num
+ mhop
.l1_idx
;
661 hem_idx
= mhop
.l0_idx
;
664 dev_err(dev
, "Table %d not support hop_num = %d!\n",
665 table
->type
, hop_num
);
669 mutex_lock(&table
->mutex
);
671 if (check_refcount
&& (--table
->hem
[hem_idx
]->refcount
> 0)) {
672 mutex_unlock(&table
->mutex
);
676 if (table
->type
< HEM_TYPE_MTT
&& hop_num
== 1) {
677 if (hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 1))
678 dev_warn(dev
, "Clear HEM base address failed.\n");
679 } else if (table
->type
< HEM_TYPE_MTT
&& hop_num
== 2) {
680 if (hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 2))
681 dev_warn(dev
, "Clear HEM base address failed.\n");
682 } else if (table
->type
< HEM_TYPE_MTT
&&
683 hop_num
== HNS_ROCE_HOP_NUM_0
) {
684 if (hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 0))
685 dev_warn(dev
, "Clear HEM base address failed.\n");
689 * free buffer space chunk for QPC/MTPT/CQC/SRQC/SCCC.
690 * free bt space chunk for MTT/CQE.
692 hns_roce_free_hem(hr_dev
, table
->hem
[hem_idx
]);
693 table
->hem
[hem_idx
] = NULL
;
695 if (check_whether_bt_num_2(table
->type
, hop_num
)) {
696 start_idx
= mhop
.l0_idx
* chunk_ba_num
;
697 if (hns_roce_check_hem_null(table
->hem
, start_idx
,
699 if (table
->type
< HEM_TYPE_MTT
&&
700 hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 0))
701 dev_warn(dev
, "Clear HEM base address failed.\n");
703 dma_free_coherent(dev
, bt_chunk_size
,
704 table
->bt_l0
[mhop
.l0_idx
],
705 table
->bt_l0_dma_addr
[mhop
.l0_idx
]);
706 table
->bt_l0
[mhop
.l0_idx
] = NULL
;
708 } else if (check_whether_bt_num_3(table
->type
, hop_num
)) {
709 start_idx
= mhop
.l0_idx
* chunk_ba_num
* chunk_ba_num
+
710 mhop
.l1_idx
* chunk_ba_num
;
711 if (hns_roce_check_hem_null(table
->hem
, start_idx
,
713 if (hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 1))
714 dev_warn(dev
, "Clear HEM base address failed.\n");
716 dma_free_coherent(dev
, bt_chunk_size
,
717 table
->bt_l1
[bt_l1_idx
],
718 table
->bt_l1_dma_addr
[bt_l1_idx
]);
719 table
->bt_l1
[bt_l1_idx
] = NULL
;
721 start_idx
= mhop
.l0_idx
* chunk_ba_num
;
722 if (hns_roce_check_bt_null(table
->bt_l1
, start_idx
,
724 if (hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
,
726 dev_warn(dev
, "Clear HEM base address failed.\n");
728 dma_free_coherent(dev
, bt_chunk_size
,
729 table
->bt_l0
[mhop
.l0_idx
],
730 table
->bt_l0_dma_addr
[mhop
.l0_idx
]);
731 table
->bt_l0
[mhop
.l0_idx
] = NULL
;
736 mutex_unlock(&table
->mutex
);
739 void hns_roce_table_put(struct hns_roce_dev
*hr_dev
,
740 struct hns_roce_hem_table
*table
, unsigned long obj
)
742 struct device
*dev
= hr_dev
->dev
;
745 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
746 hns_roce_table_mhop_put(hr_dev
, table
, obj
, 1);
750 i
= (obj
& (table
->num_obj
- 1)) /
751 (table
->table_chunk_size
/ table
->obj_size
);
753 mutex_lock(&table
->mutex
);
755 if (--table
->hem
[i
]->refcount
== 0) {
756 /* Clear HEM base address */
757 if (hr_dev
->hw
->clear_hem(hr_dev
, table
, obj
, 0))
758 dev_warn(dev
, "Clear HEM base address failed.\n");
760 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
761 table
->hem
[i
] = NULL
;
764 mutex_unlock(&table
->mutex
);
766 EXPORT_SYMBOL_GPL(hns_roce_table_put
);
768 void *hns_roce_table_find(struct hns_roce_dev
*hr_dev
,
769 struct hns_roce_hem_table
*table
,
770 unsigned long obj
, dma_addr_t
*dma_handle
)
772 struct hns_roce_hem_chunk
*chunk
;
773 struct hns_roce_hem_mhop mhop
;
774 struct hns_roce_hem
*hem
;
776 unsigned long mhop_obj
= obj
;
777 unsigned long obj_per_chunk
;
778 unsigned long idx_offset
;
779 int offset
, dma_offset
;
787 mutex_lock(&table
->mutex
);
789 if (!hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
790 obj_per_chunk
= table
->table_chunk_size
/ table
->obj_size
;
791 hem
= table
->hem
[(obj
& (table
->num_obj
- 1)) / obj_per_chunk
];
792 idx_offset
= (obj
& (table
->num_obj
- 1)) % obj_per_chunk
;
793 dma_offset
= offset
= idx_offset
* table
->obj_size
;
795 hns_roce_calc_hem_mhop(hr_dev
, table
, &mhop_obj
, &mhop
);
799 if (mhop
.hop_num
== 2)
800 hem_idx
= i
* (mhop
.bt_chunk_size
/ 8) + j
;
801 else if (mhop
.hop_num
== 1 ||
802 mhop
.hop_num
== HNS_ROCE_HOP_NUM_0
)
805 hem
= table
->hem
[hem_idx
];
806 dma_offset
= offset
= (obj
& (table
->num_obj
- 1)) *
807 table
->obj_size
% mhop
.bt_chunk_size
;
808 if (mhop
.hop_num
== 2)
809 dma_offset
= offset
= 0;
815 list_for_each_entry(chunk
, &hem
->chunk_list
, list
) {
816 for (i
= 0; i
< chunk
->npages
; ++i
) {
817 length
= sg_dma_len(&chunk
->mem
[i
]);
818 if (dma_handle
&& dma_offset
>= 0) {
819 if (length
> (u32
)dma_offset
)
820 *dma_handle
= sg_dma_address(
821 &chunk
->mem
[i
]) + dma_offset
;
822 dma_offset
-= length
;
825 if (length
> (u32
)offset
) {
826 addr
= chunk
->buf
[i
] + offset
;
834 mutex_unlock(&table
->mutex
);
837 EXPORT_SYMBOL_GPL(hns_roce_table_find
);
839 int hns_roce_table_get_range(struct hns_roce_dev
*hr_dev
,
840 struct hns_roce_hem_table
*table
,
841 unsigned long start
, unsigned long end
)
843 struct hns_roce_hem_mhop mhop
;
844 unsigned long inc
= table
->table_chunk_size
/ table
->obj_size
;
848 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
849 hns_roce_calc_hem_mhop(hr_dev
, table
, NULL
, &mhop
);
850 inc
= mhop
.bt_chunk_size
/ table
->obj_size
;
853 /* Allocate MTT entry memory according to chunk(128K) */
854 for (i
= start
; i
<= end
; i
+= inc
) {
855 ret
= hns_roce_table_get(hr_dev
, table
, i
);
865 hns_roce_table_put(hr_dev
, table
, i
);
870 void hns_roce_table_put_range(struct hns_roce_dev
*hr_dev
,
871 struct hns_roce_hem_table
*table
,
872 unsigned long start
, unsigned long end
)
874 struct hns_roce_hem_mhop mhop
;
875 unsigned long inc
= table
->table_chunk_size
/ table
->obj_size
;
878 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
879 hns_roce_calc_hem_mhop(hr_dev
, table
, NULL
, &mhop
);
880 inc
= mhop
.bt_chunk_size
/ table
->obj_size
;
883 for (i
= start
; i
<= end
; i
+= inc
)
884 hns_roce_table_put(hr_dev
, table
, i
);
887 int hns_roce_init_hem_table(struct hns_roce_dev
*hr_dev
,
888 struct hns_roce_hem_table
*table
, u32 type
,
889 unsigned long obj_size
, unsigned long nobj
,
892 struct device
*dev
= hr_dev
->dev
;
893 unsigned long obj_per_chunk
;
894 unsigned long num_hem
;
896 if (!hns_roce_check_whether_mhop(hr_dev
, type
)) {
897 table
->table_chunk_size
= hr_dev
->caps
.chunk_sz
;
898 obj_per_chunk
= table
->table_chunk_size
/ obj_size
;
899 num_hem
= (nobj
+ obj_per_chunk
- 1) / obj_per_chunk
;
901 table
->hem
= kcalloc(num_hem
, sizeof(*table
->hem
), GFP_KERNEL
);
905 unsigned long buf_chunk_size
;
906 unsigned long bt_chunk_size
;
907 unsigned long bt_chunk_num
;
908 unsigned long num_bt_l0
= 0;
913 buf_chunk_size
= 1 << (hr_dev
->caps
.qpc_buf_pg_sz
915 bt_chunk_size
= 1 << (hr_dev
->caps
.qpc_ba_pg_sz
917 num_bt_l0
= hr_dev
->caps
.qpc_bt_num
;
918 hop_num
= hr_dev
->caps
.qpc_hop_num
;
921 buf_chunk_size
= 1 << (hr_dev
->caps
.mpt_buf_pg_sz
923 bt_chunk_size
= 1 << (hr_dev
->caps
.mpt_ba_pg_sz
925 num_bt_l0
= hr_dev
->caps
.mpt_bt_num
;
926 hop_num
= hr_dev
->caps
.mpt_hop_num
;
929 buf_chunk_size
= 1 << (hr_dev
->caps
.cqc_buf_pg_sz
931 bt_chunk_size
= 1 << (hr_dev
->caps
.cqc_ba_pg_sz
933 num_bt_l0
= hr_dev
->caps
.cqc_bt_num
;
934 hop_num
= hr_dev
->caps
.cqc_hop_num
;
937 buf_chunk_size
= 1 << (hr_dev
->caps
.sccc_buf_pg_sz
939 bt_chunk_size
= 1 << (hr_dev
->caps
.sccc_ba_pg_sz
941 num_bt_l0
= hr_dev
->caps
.sccc_bt_num
;
942 hop_num
= hr_dev
->caps
.sccc_hop_num
;
944 case HEM_TYPE_QPC_TIMER
:
945 buf_chunk_size
= 1 << (hr_dev
->caps
.qpc_timer_buf_pg_sz
947 bt_chunk_size
= 1 << (hr_dev
->caps
.qpc_timer_ba_pg_sz
949 num_bt_l0
= hr_dev
->caps
.qpc_timer_bt_num
;
950 hop_num
= hr_dev
->caps
.qpc_timer_hop_num
;
952 case HEM_TYPE_CQC_TIMER
:
953 buf_chunk_size
= 1 << (hr_dev
->caps
.cqc_timer_buf_pg_sz
955 bt_chunk_size
= 1 << (hr_dev
->caps
.cqc_timer_ba_pg_sz
957 num_bt_l0
= hr_dev
->caps
.cqc_timer_bt_num
;
958 hop_num
= hr_dev
->caps
.cqc_timer_hop_num
;
961 buf_chunk_size
= 1 << (hr_dev
->caps
.srqc_buf_pg_sz
963 bt_chunk_size
= 1 << (hr_dev
->caps
.srqc_ba_pg_sz
965 num_bt_l0
= hr_dev
->caps
.srqc_bt_num
;
966 hop_num
= hr_dev
->caps
.srqc_hop_num
;
969 buf_chunk_size
= 1 << (hr_dev
->caps
.mtt_ba_pg_sz
971 bt_chunk_size
= buf_chunk_size
;
972 hop_num
= hr_dev
->caps
.mtt_hop_num
;
975 buf_chunk_size
= 1 << (hr_dev
->caps
.cqe_ba_pg_sz
977 bt_chunk_size
= buf_chunk_size
;
978 hop_num
= hr_dev
->caps
.cqe_hop_num
;
980 case HEM_TYPE_SRQWQE
:
981 buf_chunk_size
= 1 << (hr_dev
->caps
.srqwqe_ba_pg_sz
983 bt_chunk_size
= buf_chunk_size
;
984 hop_num
= hr_dev
->caps
.srqwqe_hop_num
;
987 buf_chunk_size
= 1 << (hr_dev
->caps
.idx_ba_pg_sz
989 bt_chunk_size
= buf_chunk_size
;
990 hop_num
= hr_dev
->caps
.idx_hop_num
;
994 "Table %d not support to init hem table here!\n",
998 obj_per_chunk
= buf_chunk_size
/ obj_size
;
999 num_hem
= (nobj
+ obj_per_chunk
- 1) / obj_per_chunk
;
1000 bt_chunk_num
= bt_chunk_size
/ 8;
1001 if (type
>= HEM_TYPE_MTT
)
1002 num_bt_l0
= bt_chunk_num
;
1004 table
->hem
= kcalloc(num_hem
, sizeof(*table
->hem
),
1007 goto err_kcalloc_hem_buf
;
1009 if (check_whether_bt_num_3(type
, hop_num
)) {
1010 unsigned long num_bt_l1
;
1012 num_bt_l1
= (num_hem
+ bt_chunk_num
- 1) /
1014 table
->bt_l1
= kcalloc(num_bt_l1
,
1015 sizeof(*table
->bt_l1
),
1018 goto err_kcalloc_bt_l1
;
1020 table
->bt_l1_dma_addr
= kcalloc(num_bt_l1
,
1021 sizeof(*table
->bt_l1_dma_addr
),
1024 if (!table
->bt_l1_dma_addr
)
1025 goto err_kcalloc_l1_dma
;
1028 if (check_whether_bt_num_2(type
, hop_num
) ||
1029 check_whether_bt_num_3(type
, hop_num
)) {
1030 table
->bt_l0
= kcalloc(num_bt_l0
, sizeof(*table
->bt_l0
),
1033 goto err_kcalloc_bt_l0
;
1035 table
->bt_l0_dma_addr
= kcalloc(num_bt_l0
,
1036 sizeof(*table
->bt_l0_dma_addr
),
1038 if (!table
->bt_l0_dma_addr
)
1039 goto err_kcalloc_l0_dma
;
1044 table
->num_hem
= num_hem
;
1045 table
->num_obj
= nobj
;
1046 table
->obj_size
= obj_size
;
1047 table
->lowmem
= use_lowmem
;
1048 mutex_init(&table
->mutex
);
1053 kfree(table
->bt_l0
);
1054 table
->bt_l0
= NULL
;
1057 kfree(table
->bt_l1_dma_addr
);
1058 table
->bt_l1_dma_addr
= NULL
;
1061 kfree(table
->bt_l1
);
1062 table
->bt_l1
= NULL
;
1068 err_kcalloc_hem_buf
:
1072 static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev
*hr_dev
,
1073 struct hns_roce_hem_table
*table
)
1075 struct hns_roce_hem_mhop mhop
;
1080 hns_roce_calc_hem_mhop(hr_dev
, table
, NULL
, &mhop
);
1081 buf_chunk_size
= table
->type
< HEM_TYPE_MTT
? mhop
.buf_chunk_size
:
1084 for (i
= 0; i
< table
->num_hem
; ++i
) {
1085 obj
= i
* buf_chunk_size
/ table
->obj_size
;
1087 hns_roce_table_mhop_put(hr_dev
, table
, obj
, 0);
1092 kfree(table
->bt_l1
);
1093 table
->bt_l1
= NULL
;
1094 kfree(table
->bt_l1_dma_addr
);
1095 table
->bt_l1_dma_addr
= NULL
;
1096 kfree(table
->bt_l0
);
1097 table
->bt_l0
= NULL
;
1098 kfree(table
->bt_l0_dma_addr
);
1099 table
->bt_l0_dma_addr
= NULL
;
1102 void hns_roce_cleanup_hem_table(struct hns_roce_dev
*hr_dev
,
1103 struct hns_roce_hem_table
*table
)
1105 struct device
*dev
= hr_dev
->dev
;
1108 if (hns_roce_check_whether_mhop(hr_dev
, table
->type
)) {
1109 hns_roce_cleanup_mhop_hem_table(hr_dev
, table
);
1113 for (i
= 0; i
< table
->num_hem
; ++i
)
1114 if (table
->hem
[i
]) {
1115 if (hr_dev
->hw
->clear_hem(hr_dev
, table
,
1116 i
* table
->table_chunk_size
/ table
->obj_size
, 0))
1117 dev_err(dev
, "Clear HEM base address failed.\n");
1119 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
1125 void hns_roce_cleanup_hem(struct hns_roce_dev
*hr_dev
)
1127 if ((hr_dev
->caps
.num_idx_segs
))
1128 hns_roce_cleanup_hem_table(hr_dev
,
1129 &hr_dev
->mr_table
.mtt_idx_table
);
1130 if (hr_dev
->caps
.num_srqwqe_segs
)
1131 hns_roce_cleanup_hem_table(hr_dev
,
1132 &hr_dev
->mr_table
.mtt_srqwqe_table
);
1133 if (hr_dev
->caps
.srqc_entry_sz
)
1134 hns_roce_cleanup_hem_table(hr_dev
,
1135 &hr_dev
->srq_table
.table
);
1136 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->cq_table
.table
);
1137 if (hr_dev
->caps
.qpc_timer_entry_sz
)
1138 hns_roce_cleanup_hem_table(hr_dev
,
1139 &hr_dev
->qpc_timer_table
);
1140 if (hr_dev
->caps
.cqc_timer_entry_sz
)
1141 hns_roce_cleanup_hem_table(hr_dev
,
1142 &hr_dev
->cqc_timer_table
);
1143 if (hr_dev
->caps
.sccc_entry_sz
)
1144 hns_roce_cleanup_hem_table(hr_dev
,
1145 &hr_dev
->qp_table
.sccc_table
);
1146 if (hr_dev
->caps
.trrl_entry_sz
)
1147 hns_roce_cleanup_hem_table(hr_dev
,
1148 &hr_dev
->qp_table
.trrl_table
);
1149 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->qp_table
.irrl_table
);
1150 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->qp_table
.qp_table
);
1151 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->mr_table
.mtpt_table
);
1152 if (hns_roce_check_whether_mhop(hr_dev
, HEM_TYPE_CQE
))
1153 hns_roce_cleanup_hem_table(hr_dev
,
1154 &hr_dev
->mr_table
.mtt_cqe_table
);
1155 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->mr_table
.mtt_table
);