Skip to content

Commit b58c443

Browse files
fengchengwentmonjalo
authored andcommitted
dma/hisi_acc: add data path operations
This commit adds data path ops for Hisilicon accelerator DMA driver. Signed-off-by: Chengwen Feng <[email protected]>
1 parent 2557ad8 commit b58c443

File tree

3 files changed

+398
-13
lines changed

3 files changed

+398
-13
lines changed

doc/guides/dmadevs/hisi_acc.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,16 @@ Configuration requirements:
5353
* Only one ``vchan`` is supported per ``dmadev``.
5454
* Silent mode is not supported.
5555
* The transfer direction must be set to ``RTE_DMA_DIR_MEM_TO_MEM``.
56+
57+
58+
Device Datapath Capability and Limitation
59+
-----------------------------------------
60+
61+
Support memory copy and fill operations.
62+
63+
.. note::
64+
65+
Currently, the maximum size of the operation data is limited to 16MB-1B in the driver.
66+
The device actually supports operations in a larger data size,
67+
but the driver requires complex operations in the datapth.
68+
If you have such requirement, please contact the maintainers.

drivers/dma/hisi_acc/hisi_acc_dmadev.c

Lines changed: 311 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <sys/ioctl.h>
99

1010
#include <rte_byteorder.h>
11+
#include <rte_cycles.h>
1112
#include <rte_eal.h>
1213
#include <rte_io.h>
1314
#include <rte_kvargs.h>
@@ -79,6 +80,7 @@ hacc_dma_start(struct rte_dma_dev *dev)
7980
if (hw->started) {
8081
hw->ridx = 0;
8182
hw->cridx = 0;
83+
hw->stop_proc = 0;
8284
return 0;
8385
}
8486

@@ -94,6 +96,7 @@ hacc_dma_start(struct rte_dma_dev *dev)
9496
hw->cq_head = 0;
9597
hw->cqs_completed = 0;
9698
hw->cqe_vld = 1;
99+
hw->stop_proc = 0;
97100
hw->submitted = 0;
98101
hw->completed = 0;
99102
hw->errors = 0;
@@ -110,17 +113,33 @@ hacc_dma_start(struct rte_dma_dev *dev)
110113
static int
111114
hacc_dma_stop(struct rte_dma_dev *dev)
112115
{
116+
#define MAX_WAIT_MSEC 1000
117+
#define MAX_CPL_NUM 64
113118
struct hacc_dma_dev *hw = dev->data->dev_private;
114-
115-
if ((*hw->sq_status != 0) || (*hw->cq_status != 0)) {
116-
/* This indicates that the dev is abnormal. The correct error handling
117-
* is to close the dev (so that kernel module will perform error handling)
118-
* and apply for a new dev.
119-
* If an error code is returned here, the dev cannot be closed. Therefore,
120-
* zero is returned and an error trace is added.
121-
*/
122-
HACC_DMA_ERR(hw, "detect dev is abnormal!");
123-
return 0;
119+
uint32_t wait_msec = 0;
120+
121+
/* Flag stop processing new requests. */
122+
hw->stop_proc = 1;
123+
/* Currently, there is no method to notify the hardware to stop.
124+
* Therefore, the timeout mechanism is used to wait for the dataplane
125+
* to stop.
126+
*/
127+
while (hw->sq_head != hw->sq_tail && wait_msec++ < MAX_WAIT_MSEC) {
128+
if ((*hw->sq_status != 0) || (*hw->cq_status != 0)) {
129+
/* This indicates that the dev is abnormal. The correct error handling
130+
* is to close the dev (so that kernel module will perform error handling)
131+
* and apply for a new dev.
132+
* If an error code is returned here, the dev cannot be closed. Therefore,
133+
* zero is returned and an error trace is added.
134+
*/
135+
HACC_DMA_ERR(hw, "detect dev is abnormal!");
136+
return 0;
137+
}
138+
rte_delay_ms(1);
139+
}
140+
if (hw->sq_head != hw->sq_tail) {
141+
HACC_DMA_ERR(hw, "dev is still active!");
142+
return -EBUSY;
124143
}
125144

126145
return 0;
@@ -187,10 +206,11 @@ hacc_dma_dump(const struct rte_dma_dev *dev, FILE *f)
187206
{
188207
struct hacc_dma_dev *hw = dev->data->dev_private;
189208

190-
fprintf(f, " sqn: %u sq_status: %s cq_status: %s\n"
209+
fprintf(f, " sqn: %u sq_status: %s cq_status: %s stop_proc: %u\n"
191210
" sqe_size: %u sq_depth: %u sq_depth_mask: %u cq_depth: %u\n",
192211
hw->sqn, (*hw->sq_status != 0) ? "ERR" : "OK",
193212
(*hw->cq_status != 0) ? "ERR" : "OK",
213+
hw->stop_proc,
194214
hw->sqe_size, hw->sq_depth, hw->sq_depth_mask, hw->cq_depth);
195215
fprintf(f, " ridx: %u cridx: %u\n"
196216
" sq_head: %u sq_tail: %u cq_sq_head: %u avail_sqes: %u\n"
@@ -206,6 +226,280 @@ hacc_dma_dump(const struct rte_dma_dev *dev, FILE *f)
206226
return 0;
207227
}
208228

229+
static inline void
230+
hacc_dma_sq_doorbell(struct hacc_dma_dev *hw)
231+
{
232+
uint64_t doorbell = (uint64_t)(hw->sqn & HACC_DMA_DOORBELL_SQN_MASK) |
233+
(HACC_DMA_DOORBELL_SQ_CMD << HACC_DMA_DOORBELL_CMD_SHIFT) |
234+
(((uint64_t)hw->sq_tail) << HACC_DMA_DOORBELL_IDX_SHIFT);
235+
rte_io_wmb();
236+
*(volatile uint64_t *)hw->doorbell_reg = doorbell;
237+
}
238+
239+
static int
240+
hacc_dma_copy(void *dev_private, uint16_t vchan, rte_iova_t src, rte_iova_t dst,
241+
uint32_t length, uint64_t flags)
242+
{
243+
struct hacc_dma_dev *hw = dev_private;
244+
struct hacc_dma_sqe *sqe = &hw->sqe[hw->sq_tail];
245+
246+
RTE_SET_USED(vchan);
247+
248+
if (unlikely(hw->stop_proc > 0))
249+
return -EPERM;
250+
251+
if (unlikely(length > HACC_DMA_MAX_OP_SIZE)) {
252+
hw->invalid_lens++;
253+
return -EINVAL;
254+
}
255+
256+
if (unlikely(*hw->sq_status != 0)) {
257+
hw->io_errors++;
258+
return -EIO;
259+
}
260+
261+
if (hw->avail_sqes == 0) {
262+
hw->qfulls++;
263+
return -ENOSPC;
264+
}
265+
266+
sqe->bd_type = HACC_DMA_SQE_TYPE;
267+
sqe->task_type = HACC_DMA_TASK_TYPE;
268+
sqe->task_type_ext = HACC_DMA_DATA_MEMCPY;
269+
sqe->init_val = 0;
270+
sqe->addr_array = src;
271+
sqe->dst_addr = dst;
272+
sqe->data_size = length;
273+
sqe->dw0 = HACC_DMA_SVA_PREFETCH_EN;
274+
sqe->wb_field = 0;
275+
276+
hw->sq_tail = (hw->sq_tail + 1) & hw->sq_depth_mask;
277+
hw->avail_sqes--;
278+
hw->submitted++;
279+
280+
if (flags & RTE_DMA_OP_FLAG_SUBMIT)
281+
hacc_dma_sq_doorbell(hw);
282+
283+
return hw->ridx++;
284+
}
285+
286+
static int
287+
hacc_dma_fill(void *dev_private, uint16_t vchan, uint64_t pattern,
288+
rte_iova_t dst, uint32_t length, uint64_t flags)
289+
{
290+
struct hacc_dma_dev *hw = dev_private;
291+
struct hacc_dma_sqe *sqe = &hw->sqe[hw->sq_tail];
292+
293+
RTE_SET_USED(vchan);
294+
295+
if (unlikely(hw->stop_proc > 0))
296+
return -EPERM;
297+
298+
if (unlikely(length > HACC_DMA_MAX_OP_SIZE)) {
299+
hw->invalid_lens++;
300+
return -EINVAL;
301+
}
302+
303+
if (unlikely(*hw->sq_status != 0)) {
304+
hw->io_errors++;
305+
return -EIO;
306+
}
307+
308+
if (hw->avail_sqes == 0) {
309+
hw->qfulls++;
310+
return -ENOSPC;
311+
}
312+
313+
sqe->bd_type = HACC_DMA_SQE_TYPE;
314+
sqe->task_type = HACC_DMA_TASK_TYPE;
315+
sqe->task_type_ext = HACC_DMA_DATA_MEMSET;
316+
sqe->init_val = pattern;
317+
sqe->addr_array = 0;
318+
sqe->dst_addr = dst;
319+
sqe->data_size = length;
320+
sqe->dw0 = HACC_DMA_SVA_PREFETCH_EN;
321+
sqe->wb_field = 0;
322+
323+
hw->sq_tail = (hw->sq_tail + 1) & hw->sq_depth_mask;
324+
hw->avail_sqes--;
325+
hw->submitted++;
326+
327+
if (flags & RTE_DMA_OP_FLAG_SUBMIT)
328+
hacc_dma_sq_doorbell(hw);
329+
330+
return hw->ridx++;
331+
}
332+
333+
static int
334+
hacc_dma_submit(void *dev_private, uint16_t vchan)
335+
{
336+
struct hacc_dma_dev *hw = dev_private;
337+
338+
RTE_SET_USED(vchan);
339+
340+
if (unlikely(*hw->sq_status != 0)) {
341+
hw->io_errors++;
342+
return -EIO;
343+
}
344+
345+
hacc_dma_sq_doorbell(hw);
346+
347+
return 0;
348+
}
349+
350+
static inline void
351+
hacc_dma_cq_doorbell(struct hacc_dma_dev *hw)
352+
{
353+
uint64_t doorbell = (uint64_t)(hw->sqn & HACC_DMA_DOORBELL_SQN_MASK) |
354+
(HACC_DMA_DOORBELL_CQ_CMD << HACC_DMA_DOORBELL_CMD_SHIFT) |
355+
(((uint64_t)hw->cq_head) << HACC_DMA_DOORBELL_IDX_SHIFT);
356+
rte_io_wmb();
357+
*(volatile uint64_t *)hw->doorbell_reg = doorbell;
358+
}
359+
360+
static inline void
361+
hacc_dma_scan_cq(struct hacc_dma_dev *hw)
362+
{
363+
volatile struct hacc_dma_cqe *cqe;
364+
struct hacc_dma_sqe *sqe;
365+
uint16_t csq_head = hw->cq_sq_head;
366+
uint16_t cq_head = hw->cq_head;
367+
uint16_t count = 0;
368+
uint64_t misc;
369+
370+
if (unlikely(*hw->cq_status != 0)) {
371+
hw->io_errors++;
372+
return;
373+
}
374+
375+
while (count < hw->cq_depth) {
376+
cqe = &hw->cqe[cq_head];
377+
misc = cqe->misc;
378+
misc = rte_le_to_cpu_64(misc);
379+
if (RTE_FIELD_GET64(HACC_DMA_CQE_VALID_B, misc) != hw->cqe_vld)
380+
break;
381+
382+
csq_head = RTE_FIELD_GET64(HACC_DMA_SQ_HEAD_MASK, misc);
383+
if (unlikely(csq_head > hw->sq_depth_mask)) {
384+
/**
385+
* Defensive programming to prevent overflow of the
386+
* status array indexed by csq_head. Only error logs
387+
* are used for prompting.
388+
*/
389+
HACC_DMA_ERR(hw, "invalid csq_head: %u!", csq_head);
390+
count = 0;
391+
break;
392+
}
393+
sqe = &hw->sqe[csq_head];
394+
if (sqe->done_flag != HACC_DMA_TASK_DONE ||
395+
sqe->err_type || sqe->ext_err_type || sqe->wtype) {
396+
hw->status[csq_head] = RTE_DMA_STATUS_ERROR_UNKNOWN;
397+
}
398+
399+
count++;
400+
cq_head++;
401+
if (cq_head == hw->cq_depth) {
402+
hw->cqe_vld = !hw->cqe_vld;
403+
cq_head = 0;
404+
}
405+
}
406+
407+
if (count == 0)
408+
return;
409+
410+
hw->cq_head = cq_head;
411+
hw->cq_sq_head = (csq_head + 1) & hw->sq_depth_mask;
412+
hw->avail_sqes += count;
413+
hw->cqs_completed += count;
414+
if (hw->cqs_completed >= HACC_DMA_CQ_DOORBELL_PACE) {
415+
hacc_dma_cq_doorbell(hw);
416+
hw->cqs_completed = 0;
417+
}
418+
}
419+
420+
static inline uint16_t
421+
hacc_dma_calc_cpls(struct hacc_dma_dev *hw, const uint16_t nb_cpls)
422+
{
423+
uint16_t cpl_num;
424+
425+
if (hw->cq_sq_head >= hw->sq_head)
426+
cpl_num = hw->cq_sq_head - hw->sq_head;
427+
else
428+
cpl_num = hw->sq_depth_mask + 1 - hw->sq_head + hw->cq_sq_head;
429+
430+
if (cpl_num > nb_cpls)
431+
cpl_num = nb_cpls;
432+
433+
return cpl_num;
434+
}
435+
436+
static uint16_t
437+
hacc_dma_completed(void *dev_private,
438+
uint16_t vchan, const uint16_t nb_cpls,
439+
uint16_t *last_idx, bool *has_error)
440+
{
441+
struct hacc_dma_dev *hw = dev_private;
442+
uint16_t sq_head = hw->sq_head;
443+
uint16_t cpl_num, i;
444+
445+
RTE_SET_USED(vchan);
446+
hacc_dma_scan_cq(hw);
447+
448+
cpl_num = hacc_dma_calc_cpls(hw, nb_cpls);
449+
for (i = 0; i < cpl_num; i++) {
450+
if (hw->status[sq_head]) {
451+
*has_error = true;
452+
break;
453+
}
454+
sq_head = (sq_head + 1) & hw->sq_depth_mask;
455+
}
456+
*last_idx = hw->cridx + i - 1;
457+
if (i > 0) {
458+
hw->cridx += i;
459+
hw->sq_head = sq_head;
460+
hw->completed += i;
461+
}
462+
463+
return i;
464+
}
465+
466+
static uint16_t
467+
hacc_dma_completed_status(void *dev_private,
468+
uint16_t vchan, const uint16_t nb_cpls,
469+
uint16_t *last_idx, enum rte_dma_status_code *status)
470+
{
471+
struct hacc_dma_dev *hw = dev_private;
472+
uint16_t sq_head = hw->sq_head;
473+
uint16_t cpl_num, i;
474+
475+
RTE_SET_USED(vchan);
476+
hacc_dma_scan_cq(hw);
477+
478+
cpl_num = hacc_dma_calc_cpls(hw, nb_cpls);
479+
for (i = 0; i < cpl_num; i++) {
480+
status[i] = hw->status[sq_head];
481+
hw->errors += !!status[i];
482+
hw->status[sq_head] = 0;
483+
sq_head = (sq_head + 1) & hw->sq_depth_mask;
484+
}
485+
*last_idx = hw->cridx + cpl_num - 1;
486+
if (likely(cpl_num > 0)) {
487+
hw->cridx += cpl_num;
488+
hw->sq_head = sq_head;
489+
hw->completed += cpl_num;
490+
}
491+
492+
return cpl_num;
493+
}
494+
495+
static uint16_t
496+
hacc_dma_burst_capacity(const void *dev_private, uint16_t vchan)
497+
{
498+
const struct hacc_dma_dev *hw = dev_private;
499+
RTE_SET_USED(vchan);
500+
return hw->avail_sqes;
501+
}
502+
209503
static const struct rte_dma_dev_ops hacc_dmadev_ops = {
210504
.dev_info_get = hacc_dma_info_get,
211505
.dev_configure = hacc_dma_configure,
@@ -297,6 +591,12 @@ hacc_dma_create(struct rte_uacce_device *uacce_dev, uint16_t queue_id)
297591
dev->device = &uacce_dev->device;
298592
dev->dev_ops = &hacc_dmadev_ops;
299593
dev->fp_obj->dev_private = dev->data->dev_private;
594+
dev->fp_obj->copy = hacc_dma_copy;
595+
dev->fp_obj->fill = hacc_dma_fill;
596+
dev->fp_obj->submit = hacc_dma_submit;
597+
dev->fp_obj->completed = hacc_dma_completed;
598+
dev->fp_obj->completed_status = hacc_dma_completed_status;
599+
dev->fp_obj->burst_capacity = hacc_dma_burst_capacity;
300600

301601
hw = dev->data->dev_private;
302602
hw->data = dev->data; /* make sure ACC_DMA_DEBUG/INFO/WARN/ERR was available. */

0 commit comments

Comments
 (0)