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 HW_SYNC_TIMEOUT_MSECS 500
40 #define HW_SYNC_SLEEP_TIME_INTERVAL 20
42 #define HNS_ROCE_HEM_ALLOC_SIZE (1 << 17)
43 #define HNS_ROCE_TABLE_CHUNK_SIZE (1 << 17)
45 #define DMA_ADDR_T_SHIFT 12
46 #define BT_CMD_SYNC_SHIFT 31
47 #define BT_BA_SHIFT 32
49 struct hns_roce_hem
*hns_roce_alloc_hem(struct hns_roce_dev
*hr_dev
, int npages
,
52 struct hns_roce_hem_chunk
*chunk
= NULL
;
53 struct hns_roce_hem
*hem
;
54 struct scatterlist
*mem
;
58 WARN_ON(gfp_mask
& __GFP_HIGHMEM
);
60 hem
= kmalloc(sizeof(*hem
),
61 gfp_mask
& ~(__GFP_HIGHMEM
| __GFP_NOWARN
));
66 INIT_LIST_HEAD(&hem
->chunk_list
);
68 order
= get_order(HNS_ROCE_HEM_ALLOC_SIZE
);
72 chunk
= kmalloc(sizeof(*chunk
),
73 gfp_mask
& ~(__GFP_HIGHMEM
| __GFP_NOWARN
));
77 sg_init_table(chunk
->mem
, HNS_ROCE_HEM_CHUNK_LEN
);
80 list_add_tail(&chunk
->list
, &hem
->chunk_list
);
83 while (1 << order
> npages
)
87 * Alloc memory one time. If failed, don't alloc small block
88 * memory, directly return fail.
90 mem
= &chunk
->mem
[chunk
->npages
];
91 buf
= dma_alloc_coherent(&hr_dev
->pdev
->dev
, PAGE_SIZE
<< order
,
92 &sg_dma_address(mem
), gfp_mask
);
96 sg_set_buf(mem
, buf
, PAGE_SIZE
<< order
);
98 sg_dma_len(mem
) = PAGE_SIZE
<< order
;
102 npages
-= 1 << order
;
108 hns_roce_free_hem(hr_dev
, hem
);
112 void hns_roce_free_hem(struct hns_roce_dev
*hr_dev
, struct hns_roce_hem
*hem
)
114 struct hns_roce_hem_chunk
*chunk
, *tmp
;
120 list_for_each_entry_safe(chunk
, tmp
, &hem
->chunk_list
, list
) {
121 for (i
= 0; i
< chunk
->npages
; ++i
)
122 dma_free_coherent(&hr_dev
->pdev
->dev
,
123 chunk
->mem
[i
].length
,
124 lowmem_page_address(sg_page(&chunk
->mem
[i
])),
125 sg_dma_address(&chunk
->mem
[i
]));
132 static int hns_roce_set_hem(struct hns_roce_dev
*hr_dev
,
133 struct hns_roce_hem_table
*table
, unsigned long obj
)
135 struct device
*dev
= &hr_dev
->pdev
->dev
;
136 spinlock_t
*lock
= &hr_dev
->bt_cmd_lock
;
137 unsigned long end
= 0;
139 struct hns_roce_hem_iter iter
;
140 void __iomem
*bt_cmd
;
141 u32 bt_cmd_h_val
= 0;
147 /* Find the HEM(Hardware Entry Memory) entry */
148 unsigned long i
= (obj
& (table
->num_obj
- 1)) /
149 (HNS_ROCE_TABLE_CHUNK_SIZE
/ table
->obj_size
);
151 switch (table
->type
) {
153 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
154 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
, HEM_TYPE_QPC
);
157 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
158 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
,
162 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
163 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
, HEM_TYPE_CQC
);
166 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
167 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
,
173 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M
,
174 ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S
, obj
);
175 roce_set_bit(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S
, 0);
176 roce_set_bit(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S
, 1);
178 /* Currently iter only a chunk */
179 for (hns_roce_hem_first(table
->hem
[i
], &iter
);
180 !hns_roce_hem_last(&iter
); hns_roce_hem_next(&iter
)) {
181 bt_ba
= hns_roce_hem_addr(&iter
) >> DMA_ADDR_T_SHIFT
;
183 spin_lock_irqsave(lock
, flags
);
185 bt_cmd
= hr_dev
->reg_base
+ ROCEE_BT_CMD_H_REG
;
187 end
= msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS
) + jiffies
;
189 if (readl(bt_cmd
) >> BT_CMD_SYNC_SHIFT
) {
190 if (!(time_before(jiffies
, end
))) {
191 dev_err(dev
, "Write bt_cmd err,hw_sync is not zero.\n");
192 spin_unlock_irqrestore(lock
, flags
);
198 msleep(HW_SYNC_SLEEP_TIME_INTERVAL
);
201 bt_cmd_l
= (u32
)bt_ba
;
202 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M
,
203 ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S
,
204 bt_ba
>> BT_BA_SHIFT
);
206 bt_cmd_val
[0] = bt_cmd_l
;
207 bt_cmd_val
[1] = bt_cmd_h_val
;
208 hns_roce_write64_k(bt_cmd_val
,
209 hr_dev
->reg_base
+ ROCEE_BT_CMD_L_REG
);
210 spin_unlock_irqrestore(lock
, flags
);
216 static int hns_roce_clear_hem(struct hns_roce_dev
*hr_dev
,
217 struct hns_roce_hem_table
*table
,
220 struct device
*dev
= &hr_dev
->pdev
->dev
;
221 unsigned long end
= 0;
223 void __iomem
*bt_cmd
;
224 uint32_t bt_cmd_val
[2];
225 u32 bt_cmd_h_val
= 0;
228 switch (table
->type
) {
230 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
231 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
, HEM_TYPE_QPC
);
234 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
235 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
,
239 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
240 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
, HEM_TYPE_CQC
);
243 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_M
,
244 ROCEE_BT_CMD_H_ROCEE_BT_CMD_MDF_S
,
250 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_M
,
251 ROCEE_BT_CMD_H_ROCEE_BT_CMD_IN_MDF_S
, obj
);
252 roce_set_bit(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_S
, 0);
253 roce_set_bit(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_HW_SYNS_S
, 1);
254 roce_set_field(bt_cmd_h_val
, ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_M
,
255 ROCEE_BT_CMD_H_ROCEE_BT_CMD_BA_H_S
, 0);
257 spin_lock_irqsave(&hr_dev
->bt_cmd_lock
, flags
);
259 bt_cmd
= hr_dev
->reg_base
+ ROCEE_BT_CMD_H_REG
;
261 end
= msecs_to_jiffies(HW_SYNC_TIMEOUT_MSECS
) + jiffies
;
263 if (readl(bt_cmd
) >> BT_CMD_SYNC_SHIFT
) {
264 if (!(time_before(jiffies
, end
))) {
265 dev_err(dev
, "Write bt_cmd err,hw_sync is not zero.\n");
266 spin_unlock_irqrestore(&hr_dev
->bt_cmd_lock
,
273 msleep(HW_SYNC_SLEEP_TIME_INTERVAL
);
277 bt_cmd_val
[1] = bt_cmd_h_val
;
278 hns_roce_write64_k(bt_cmd_val
, hr_dev
->reg_base
+ ROCEE_BT_CMD_L_REG
);
279 spin_unlock_irqrestore(&hr_dev
->bt_cmd_lock
, flags
);
284 int hns_roce_table_get(struct hns_roce_dev
*hr_dev
,
285 struct hns_roce_hem_table
*table
, unsigned long obj
)
287 struct device
*dev
= &hr_dev
->pdev
->dev
;
291 i
= (obj
& (table
->num_obj
- 1)) / (HNS_ROCE_TABLE_CHUNK_SIZE
/
294 mutex_lock(&table
->mutex
);
297 ++table
->hem
[i
]->refcount
;
301 table
->hem
[i
] = hns_roce_alloc_hem(hr_dev
,
302 HNS_ROCE_TABLE_CHUNK_SIZE
>> PAGE_SHIFT
,
303 (table
->lowmem
? GFP_KERNEL
:
304 GFP_HIGHUSER
) | __GFP_NOWARN
);
305 if (!table
->hem
[i
]) {
310 /* Set HEM base address(128K/page, pa) to Hardware */
311 if (hns_roce_set_hem(hr_dev
, table
, obj
)) {
313 dev_err(dev
, "set HEM base address to HW failed.\n");
317 ++table
->hem
[i
]->refcount
;
319 mutex_unlock(&table
->mutex
);
323 void hns_roce_table_put(struct hns_roce_dev
*hr_dev
,
324 struct hns_roce_hem_table
*table
, unsigned long obj
)
326 struct device
*dev
= &hr_dev
->pdev
->dev
;
329 i
= (obj
& (table
->num_obj
- 1)) /
330 (HNS_ROCE_TABLE_CHUNK_SIZE
/ table
->obj_size
);
332 mutex_lock(&table
->mutex
);
334 if (--table
->hem
[i
]->refcount
== 0) {
335 /* Clear HEM base address */
336 if (hns_roce_clear_hem(hr_dev
, table
, obj
))
337 dev_warn(dev
, "Clear HEM base address failed.\n");
339 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
340 table
->hem
[i
] = NULL
;
343 mutex_unlock(&table
->mutex
);
346 void *hns_roce_table_find(struct hns_roce_hem_table
*table
, unsigned long obj
,
347 dma_addr_t
*dma_handle
)
349 struct hns_roce_hem_chunk
*chunk
;
352 int offset
, dma_offset
;
353 struct hns_roce_hem
*hem
;
354 struct page
*page
= NULL
;
359 mutex_lock(&table
->mutex
);
360 idx
= (obj
& (table
->num_obj
- 1)) * table
->obj_size
;
361 hem
= table
->hem
[idx
/ HNS_ROCE_TABLE_CHUNK_SIZE
];
362 dma_offset
= offset
= idx
% HNS_ROCE_TABLE_CHUNK_SIZE
;
367 list_for_each_entry(chunk
, &hem
->chunk_list
, list
) {
368 for (i
= 0; i
< chunk
->npages
; ++i
) {
369 if (dma_handle
&& dma_offset
>= 0) {
370 if (sg_dma_len(&chunk
->mem
[i
]) >
372 *dma_handle
= sg_dma_address(
373 &chunk
->mem
[i
]) + dma_offset
;
374 dma_offset
-= sg_dma_len(&chunk
->mem
[i
]);
377 if (chunk
->mem
[i
].length
> (u32
)offset
) {
378 page
= sg_page(&chunk
->mem
[i
]);
381 offset
-= chunk
->mem
[i
].length
;
386 mutex_unlock(&table
->mutex
);
387 return page
? lowmem_page_address(page
) + offset
: NULL
;
390 int hns_roce_table_get_range(struct hns_roce_dev
*hr_dev
,
391 struct hns_roce_hem_table
*table
,
392 unsigned long start
, unsigned long end
)
394 unsigned long inc
= HNS_ROCE_TABLE_CHUNK_SIZE
/ table
->obj_size
;
398 /* Allocate MTT entry memory according to chunk(128K) */
399 for (i
= start
; i
<= end
; i
+= inc
) {
400 ret
= hns_roce_table_get(hr_dev
, table
, i
);
410 hns_roce_table_put(hr_dev
, table
, i
);
415 void hns_roce_table_put_range(struct hns_roce_dev
*hr_dev
,
416 struct hns_roce_hem_table
*table
,
417 unsigned long start
, unsigned long end
)
421 for (i
= start
; i
<= end
;
422 i
+= HNS_ROCE_TABLE_CHUNK_SIZE
/ table
->obj_size
)
423 hns_roce_table_put(hr_dev
, table
, i
);
426 int hns_roce_init_hem_table(struct hns_roce_dev
*hr_dev
,
427 struct hns_roce_hem_table
*table
, u32 type
,
428 unsigned long obj_size
, unsigned long nobj
,
431 unsigned long obj_per_chunk
;
432 unsigned long num_hem
;
434 obj_per_chunk
= HNS_ROCE_TABLE_CHUNK_SIZE
/ obj_size
;
435 num_hem
= (nobj
+ obj_per_chunk
- 1) / obj_per_chunk
;
437 table
->hem
= kcalloc(num_hem
, sizeof(*table
->hem
), GFP_KERNEL
);
442 table
->num_hem
= num_hem
;
443 table
->num_obj
= nobj
;
444 table
->obj_size
= obj_size
;
445 table
->lowmem
= use_lowmem
;
446 mutex_init(&table
->mutex
);
451 void hns_roce_cleanup_hem_table(struct hns_roce_dev
*hr_dev
,
452 struct hns_roce_hem_table
*table
)
454 struct device
*dev
= &hr_dev
->pdev
->dev
;
457 for (i
= 0; i
< table
->num_hem
; ++i
)
459 if (hns_roce_clear_hem(hr_dev
, table
,
460 i
* HNS_ROCE_TABLE_CHUNK_SIZE
/ table
->obj_size
))
461 dev_err(dev
, "Clear HEM base address failed.\n");
463 hns_roce_free_hem(hr_dev
, table
->hem
[i
]);
469 void hns_roce_cleanup_hem(struct hns_roce_dev
*hr_dev
)
471 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->cq_table
.table
);
472 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->qp_table
.irrl_table
);
473 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->qp_table
.qp_table
);
474 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->mr_table
.mtpt_table
);
475 hns_roce_cleanup_hem_table(hr_dev
, &hr_dev
->mr_table
.mtt_table
);