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)
110113static int
111114hacc_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+
209503static 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