Unverified Commit 7c98201b authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11504 sdma-dae support debugfs and fast mode

Merge Pull Request from: @zhangshuowen96 
 
1. support debugfs to query channel status/channel pointer status/channel sqe&cqe
2. support fast mode for lower latency and bigger bandwidth
3. fix some icsl codecheck problems 
 
Link:https://gitee.com/openeuler/kernel/pulls/11504

 

Reviewed-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents 21cf0fd1 691ff791
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-or-later
MODULE_NAME := sdma-dae
MODULE_NAME := sdma_dae
ccflags-y += -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-sign-compare -Wno-type-limits

$(MODULE_NAME)-objs := sdma_main.o sdma_cdev.o sdma_umem.o sdma_irq.o sdma_auth.o
$(MODULE_NAME)-objs := sdma_main.o sdma_cdev.o sdma_umem.o sdma_irq.o sdma_auth.o sdma_dbg.o

obj-$(CONFIG_SDMA_DAE) += sdma-dae.o
 No newline at end of file
obj-$(CONFIG_SDMA_DAE) += sdma_dae.o
 No newline at end of file
+13 −7
Original line number Diff line number Diff line
@@ -15,15 +15,16 @@
#define HISI_SDMA_MMAP_IO			2
#define HISI_SDMA_MMAP_SHMEM			3
#define HISI_SDMA_FSM_INTERVAL			20
#define HISI_SDMA_FSM_TIMEOUT			10
#define HISI_SDMA_FSM_TIMEOUT			5
#define HISI_SDMA_LOW_ADDR_SHIFT		32

#define HISI_SDMA_MAX_BASE_ADDR_SIZE		0x100000
#define HISI_SDMA_MAX_COMMEN_BASE_ADDR_SIZE	0x10000
#define HISI_SDMA_CHANNEL_IOMEM_SIZE		0x1000
#define HISI_SDMA_SQ_ENTRY_SIZE			64UL
#define HISI_SDMA_CQ_ENTRY_SIZE			16UL
#define HISI_SDMA_SQ_LENGTH			(1U << 16)
#define HISI_SDMA_CQ_LENGTH			(1U << 16)
#define HISI_SDMA_SQ_LENGTH			(1U << 10)
#define HISI_SDMA_CQ_LENGTH			(1U << 10)

#define HISI_STARS_CHN_NUM			32
#define HISI_SDMA_DEFAULT_CHANNEL_NUM		(192 - HISI_STARS_CHN_NUM)
@@ -40,7 +41,11 @@
#define HISI_SDMA_CLR_NORMAL_SQE_CNT		1
#define HISI_SDMA_CLR_ERR_SQE_CNT		2

#define HISI_SDMA_FAST_MODE			0
#define HISI_SDMA_SAFE_MODE			1

#define HISI_SDMA_HBM_CACHE_PRELOAD_MODE	0x6
#define SDMA_UNUSED				__attribute__((__unused__))

struct chn_ioe_info {
	u32 ch_err_status;
@@ -111,10 +116,10 @@ struct hisi_sdma_cq_entry {
};

struct hisi_sdma_queue_info {
	u32    sq_head;
	u32    sq_tail;
	u32    cq_head;
	u32    cq_tail;
	u16    sq_head;
	u16    sq_tail;
	u16    cq_head;
	u16    cq_tail;
	u32    cq_vld;
	int    lock;
	u32    lock_pid;
@@ -202,5 +207,6 @@ struct hisi_sdma_ioctl_func_list {
#define IOCTL_SDMA_CQ_TAIL_REG		_IOWR('s', 17, struct hisi_sdma_reg_info)
#define IOCTL_SDMA_DFX_REG		_IOWR('s', 18, struct hisi_sdma_reg_info)
#define IOCTL_SDMA_SQE_CNT_REG		_IOW('s', 19, struct hisi_sdma_reg_info)
#define IOCTL_GET_SDMA_MODE			_IOR('s', 20, bool)

#endif
+183 −24
Original line number Diff line number Diff line
@@ -6,7 +6,6 @@
#include <linux/platform_device.h>
#include <linux/sort.h>
#include <linux/mm.h>
#include <linux/version.h>

#include "sdma_hal.h"
#include "sdma_umem.h"
@@ -38,6 +37,74 @@ struct pasid_info {
	u32 dst_pasid;
};

static struct hisi_sdma_pid_ref_hte *sdma_search_pid_ref(struct hisi_sdma_device *psdma_dev,
							 u32 pid)
{
	struct hisi_sdma_pid_ref_hte *entry = NULL;

	hash_for_each_possible(psdma_dev->sdma_pid_ref_ht, entry, node, pid) {
		if (entry->pid == pid)
			return entry;
	}

	return NULL;
}

static int sdma_add_pid_ref(struct hisi_sdma_device *psdma_dev, u32 pid)
{
	struct hisi_sdma_pid_ref_hte *entry = NULL;

	spin_lock(&psdma_dev->pid_lock);
	entry = sdma_search_pid_ref(psdma_dev, pid);
	if (!entry) {
		entry = kmalloc_node(sizeof(struct hisi_sdma_pid_ref_hte), GFP_KERNEL,
				     psdma_dev->node_idx);
		if (!entry) {
			spin_unlock(&psdma_dev->pid_lock);
			return -ENOMEM;
		}
		entry->pid = pid;
		entry->ref = 1;
		hash_add(psdma_dev->sdma_pid_ref_ht, &entry->node, entry->pid);
	} else {
		entry->ref++;
	}
	spin_unlock(&psdma_dev->pid_lock);

	return 0;
}

static void sdma_del_pid_ref(struct hisi_sdma_device *psdma_dev, u32 pid)
{
	struct hisi_sdma_pid_ref_hte *entry = NULL;

	spin_lock(&psdma_dev->pid_lock);
	entry = sdma_search_pid_ref(psdma_dev, pid);
	if (entry) {
		entry->ref--;
		if (entry->ref == 0) {
			hash_del(&entry->node);
			kfree(entry);
			sdma_free_authority_ht_with_pid(pid);
		}
	}
	spin_unlock(&psdma_dev->pid_lock);
}

void sdma_clear_pid_ref(struct hisi_sdma_device *psdma_dev)
{
	struct hisi_sdma_pid_ref_hte *entry = NULL;
	struct hlist_node *tmp;
	u32 bkt;

	spin_lock(&psdma_dev->pid_lock);
	hash_for_each_safe(psdma_dev->sdma_pid_ref_ht, bkt, tmp, entry, node) {
		hash_del(&entry->node);
		kfree(entry);
	}
	spin_unlock(&psdma_dev->pid_lock);
}

static int __do_sdma_open(struct hisi_sdma_device *psdma_dev, struct file *file)
{
	struct file_open_data *data;
@@ -49,17 +116,23 @@ static int __do_sdma_open(struct hisi_sdma_device *psdma_dev, struct file *file)
	if (id < 0)
		return id;

	ret = sdma_add_pid_ref(psdma_dev, (u32)current->tgid);
	if (ret != 0) {
		dev_err(&psdma_dev->pdev->dev, "alloc pid_ref hash failed\n");
		goto free_ida;
	}

	dev_dbg(&psdma_dev->pdev->dev, "%s: ida alloc id = %d\n", __func__, id);
	data = kmalloc_node(sizeof(struct file_open_data), GFP_KERNEL, psdma_dev->node_idx);
	if (!data) {
		ret = -ENOMEM;
		goto free_ida;
		goto free_pid_ref_ht;
	}

	handle = iommu_sva_bind_device(&psdma_dev->pdev->dev, current->mm, NULL);
	if (IS_ERR(handle)) {
		dev_err(&psdma_dev->pdev->dev, "failed to bind sva, %ld\n", PTR_ERR(handle));
		ret = PTR_ERR(handle);
		ret = (int)PTR_ERR(handle);
		goto free_privt_data;
	}

@@ -84,6 +157,8 @@ static int __do_sdma_open(struct hisi_sdma_device *psdma_dev, struct file *file)
	iommu_sva_unbind_device(handle);
free_privt_data:
	kfree(data);
free_pid_ref_ht:
	sdma_del_pid_ref(psdma_dev, current->tgid);
free_ida:
	ida_free(g_info.fd_ida, id);
	return ret;
@@ -147,10 +222,17 @@ static int ioctl_sdma_pin_umem(struct file *file, unsigned long arg)

static int ioctl_sdma_get_process_id(struct file *file, unsigned long arg)
{
	struct file_open_data *data = file->private_data;
	u32 pid = (u32)current->tgid;
	u32 pasid = data->pasid;

	if (*(g_info.sdma_mode) == HISI_SDMA_FAST_MODE) {
		if (copy_to_user((u32 __user *)(uintptr_t)arg, &pasid, sizeof(u32)))
			return -EFAULT;
	} else {
		if (copy_to_user((u32 __user *)(uintptr_t)arg, &pid, sizeof(u32)))
			return -EFAULT;
	}

	return 0;
}
@@ -176,7 +258,8 @@ static int ioctl_sdma_get_chn(struct file *file, unsigned long arg)
	u32 alloc_chn_num_max, idx;
	int ret;

	list_node = kmalloc_node(sizeof(struct hisi_sdma_channel_list), GFP_KERNEL, pdev->node_idx);
	list_node = kmalloc_node(sizeof(struct hisi_sdma_channel_list), GFP_KERNEL,
				 pdev->node_idx);
	if (!list_node)
		return -ENOMEM;

@@ -265,7 +348,7 @@ static int cmp(const void *a, const void *b)
	return 0;
}

static int ioctl_get_near_sdmaid(struct file *file, unsigned long arg)
static int ioctl_get_near_sdmaid(struct file *file SDMA_UNUSED, unsigned long arg)
{
	struct hisi_sdma_numa_domain sdma_numa[HISI_SDMA_MAX_DEVS];
	u32 num = g_info.core_dev->sdma_device_num;
@@ -410,6 +493,9 @@ static int ioctl_sdma_add_authority_ht(struct file *file, unsigned long arg)
	u32 list_num;
	int ret;

	if (*(g_info.sdma_mode) == HISI_SDMA_FAST_MODE)
		return 0;

	if (copy_from_user(&pid_info, (struct hisi_sdma_pid_info __user *)(uintptr_t)arg,
			   sizeof(struct hisi_sdma_pid_info))) {
		dev_err(&pdev->pdev->dev, "get hisi_sdma_pid_info failed\n");
@@ -475,9 +561,9 @@ static void sdma_fill_sqe(struct hisi_sdma_sq_entry *sq_entry, struct hisi_sdma_
	sq_entry->src_streamid    = streamid;
	sq_entry->dst_streamid    = streamid;
	sq_entry->src_addr_l      = (u32)(task->src_addr & 0xffffffff);
	sq_entry->src_addr_h      = (u32)(task->src_addr >> 32);
	sq_entry->src_addr_h      = (u32)(task->src_addr >> HISI_SDMA_LOW_ADDR_SHIFT);
	sq_entry->dst_addr_l      = (u32)(task->dst_addr & 0xffffffff);
	sq_entry->dst_addr_h      = (u32)(task->dst_addr >> 32);
	sq_entry->dst_addr_h      = (u32)(task->dst_addr >> HISI_SDMA_LOW_ADDR_SHIFT);
	sq_entry->length_move     = task->length;
	sq_entry->sns             = 1;
	sq_entry->dns             = 1;
@@ -511,7 +597,8 @@ static bool sdma_check_channel_permission(struct hisi_sdma_channel *pchannel, u3
	return true;
}

static int sdma_send_task_kernel(struct file_open_data *data, struct hisi_sdma_task_info *task_info,
static int sdma_send_task_kernel(struct file_open_data *data,
				 struct hisi_sdma_task_info *task_info,
				 struct hisi_sdma_sqe_task *task_list)
{
	struct hisi_sdma_device *pdev = data->psdma_dev;
@@ -529,6 +616,11 @@ static int sdma_send_task_kernel(struct file_open_data *data, struct hisi_sdma_t
		return -EPERM;
	}
	sq_tail = pchannel->sync_info_base->sq_tail;
	if (sq_tail >= HISI_SDMA_SQ_LENGTH) {
		spin_unlock(&pchannel->owner_chn_lock);
		dev_err(&pdev->pdev->dev, "sq_tail in share mem wrong, sq_tail = %u\n", sq_tail);
		return -EINVAL;
	}
	for (i = 0; i < task_info->task_cnt; i++) {
		if (task_info->req_cnt != 0) {
			/* not send/record tasks whose length == 0 */
@@ -635,6 +727,25 @@ static int ioctl_sdma_send_task(struct file *file, unsigned long arg)
	return ret;
}

/* register value should be between cq_head(software update) and cq_tail(hardware updated) */
static bool sdma_cq_head_validate(struct hisi_sdma_channel *pchan, u32 reg_value)
{
	u32 cq_tail;
	u32 cq_head;

	cq_head = sdma_channel_get_cq_head(pchan);
	cq_tail = sdma_channel_get_cq_tail(pchan);
	if (cq_tail > cq_head) {
		if (reg_value <= cq_tail && reg_value >= cq_head)
			return true;
	} else {
		if (reg_value <= cq_tail || reg_value >= cq_head)
			return true;
	}

	return false;
}

static int sdma_operation_reg(struct hisi_sdma_device *pdev, unsigned long arg,
			      u32 (*get_func)(struct hisi_sdma_channel *),
			      void (*set_func)(struct hisi_sdma_channel *, u32))
@@ -660,10 +771,16 @@ static int sdma_operation_reg(struct hisi_sdma_device *pdev, unsigned long arg,
				 sizeof(struct hisi_sdma_reg_info)))
			return -EFAULT;
	} else if (reg_info.type == HISI_SDMA_WRITE_REG) {
		if (!set_func)
			dev_err(dev, "write operation not supported\n");
		else
		if (set_func) {
			if (reg_info.reg_value == sdma_channel_get_cq_head(pchannel))
				return 0;
			if (sdma_cq_head_validate(pchannel, reg_info.reg_value)) {
				set_func(pchannel, reg_info.reg_value);
			} else {
				dev_err(dev, "cq_head value illegal!\n");
				return -EINVAL;
			}
		}
	}

	return 0;
@@ -682,7 +799,7 @@ static int ioctl_sdma_sq_tail_reg(struct file *file, unsigned long arg)
	struct file_open_data *data = file->private_data;
	struct hisi_sdma_device *pdev = data->psdma_dev;

	return sdma_operation_reg(pdev, arg, sdma_channel_get_sq_tail, sdma_channel_set_sq_tail);
	return sdma_operation_reg(pdev, arg, sdma_channel_get_sq_tail, NULL);
}

static int ioctl_sdma_cq_head_reg(struct file *file, unsigned long arg)
@@ -759,6 +876,16 @@ static int ioctl_sdma_sqe_cnt_reg(struct file *file, unsigned long arg)
	return 0;
}

static int ioctl_get_sdma_mode(struct file *file SDMA_UNUSED, unsigned long arg)
{
	bool mode = *(g_info.sdma_mode);

	if (copy_to_user((bool __user *)(uintptr_t)arg, &mode, sizeof(bool)))
		return -EFAULT;

	return 0;
}

struct hisi_sdma_ioctl_func_list g_ioctl_funcs[] = {
	{IOCTL_SDMA_GET_PROCESS_ID,		ioctl_sdma_get_process_id},
	{IOCTL_SDMA_GET_CHN,			ioctl_sdma_get_chn},
@@ -779,6 +906,7 @@ struct hisi_sdma_ioctl_func_list g_ioctl_funcs[] = {
	{IOCTL_SDMA_CQ_TAIL_REG,		ioctl_sdma_cq_tail_reg},
	{IOCTL_SDMA_DFX_REG,			ioctl_sdma_dfx_reg},
	{IOCTL_SDMA_SQE_CNT_REG,		ioctl_sdma_sqe_cnt_reg},
	{IOCTL_GET_SDMA_MODE,			ioctl_get_sdma_mode},
};

static long sdma_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
@@ -829,12 +957,19 @@ static int sdma_core_open(struct inode *inode, struct file *file)
	return 0;
}

ssize_t sdma_read_info(struct file *file, char __user *buf, size_t size, loff_t *ppos)
ssize_t sdma_read_info(struct file *file, char __user *buf SDMA_UNUSED, size_t size SDMA_UNUSED,
		       loff_t *ppos SDMA_UNUSED)
{
	struct file_open_data *data = file->private_data;
	struct hisi_sdma_device *pdev = data->psdma_dev;
	struct device *dev = &pdev->pdev->dev;
	u32 share_chns = *(g_info.share_chns);
	bool mode = *(g_info.sdma_mode);

	if (mode == HISI_SDMA_FAST_MODE)
		dev_info(dev, "sdma is running unter fast mode\n");
	else
		dev_info(dev, "sdma is running unter safe mode\n");

	if (share_chns > pdev->nr_channel)
		share_chns = pdev->nr_channel;
@@ -844,7 +979,7 @@ ssize_t sdma_read_info(struct file *file, char __user *buf, size_t size, loff_t
	return 0;
}

static int sdma_dev_release(struct inode *inode, struct file *file)
static int sdma_dev_release(struct inode *inode SDMA_UNUSED, struct file *file)
{
	struct file_open_data *data = file->private_data;
	struct hisi_sdma_device *pdev = data->psdma_dev;
@@ -885,15 +1020,17 @@ static int sdma_dev_release(struct inode *inode, struct file *file)
		iommu_sva_unbind_device(data->handle);

	sdma_hash_free_entry(data->ida);
	sdma_free_authority_ht_with_pid(pid);
	sdma_del_pid_ref(pdev, pid);
	ida_free(g_info.fd_ida, data->ida);

	kfree(file->private_data);
	file->private_data = NULL;
	return 0;
}

static int remap_addr_range(u32 chn_num, u64 offset, u64 size)
{
	bool mode = *(g_info.sdma_mode);
	u64 sync_size;

	sync_size = (u64)((sizeof(struct hisi_sdma_queue_info) + PAGE_SIZE - ALIGN_NUM) /
@@ -905,8 +1042,11 @@ static int remap_addr_range(u32 chn_num, u64 offset, u64 size)
	}

	if (offset < chn_num * HISI_SDMA_MMAP_CQE) {
		pr_err("sdma not support sqe mmap\n");
		if (mode == HISI_SDMA_SAFE_MODE || size > HISI_SDMA_SQ_SIZE) {
			pr_err("sdma mmap size exceed sqe range\n");
			return -EINVAL;
		}
		return HISI_SDMA_MMAP_SQE;
	} else if (offset < chn_num * HISI_SDMA_MMAP_IO) {
		if (size > HISI_SDMA_CQ_SIZE) {
			pr_err("sdma mmap size exceed cqe range\n");
@@ -914,8 +1054,11 @@ static int remap_addr_range(u32 chn_num, u64 offset, u64 size)
		}
		return HISI_SDMA_MMAP_CQE;
	} else if (offset < chn_num * HISI_SDMA_MMAP_SHMEM) {
		if (mode == HISI_SDMA_SAFE_MODE || size > HISI_SDMA_REG_SIZE) {
			pr_err("sdma not support io reg mmap\n");
			return -EINVAL;
		}
		return HISI_SDMA_MMAP_IO;
	} else {
		if (size > sync_size) {
			pr_err("sdma mmap size exceed share mem range\n");
@@ -944,12 +1087,26 @@ static int sdma_dev_mmap(struct file *file, struct vm_area_struct *vma)

	dev_dbg(dev, "sdma total channel num = %u, user mmap offset = 0x%llx", chn_num, offset);
	switch (remap_addr_range(chn_num, offset, size)) {
	case HISI_SDMA_MMAP_SQE:
		pchan = chn_base + offset;
		pfn_start = virt_to_phys(pchan->sq_base) >> PAGE_SHIFT;
		ret = remap_pfn_range(vma, vma->vm_start, pfn_start, size, vma->vm_page_prot);
		break;

	case HISI_SDMA_MMAP_CQE:
		pchan = chn_base + offset - chn_num * HISI_SDMA_MMAP_CQE;
		pfn_start = virt_to_phys(pchan->cq_base) >> PAGE_SHIFT;
		ret = remap_pfn_range(vma, vma->vm_start, pfn_start, size, vma->vm_page_prot);
		break;

	case HISI_SDMA_MMAP_IO:
		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
		pfn_start = (io_base + HISI_SDMA_CH_OFFSET) >> PAGE_SHIFT;
		pfn_start += (offset - chn_num * HISI_SDMA_MMAP_IO) * HISI_SDMA_REG_SIZE /
			     PAGE_SIZE;
		ret = io_remap_pfn_range(vma, vma->vm_start, pfn_start, size, vma->vm_page_prot);
		break;

	case HISI_SDMA_MMAP_SHMEM:
		pchan = chn_base + offset - chn_num * HISI_SDMA_MMAP_SHMEM;
		pfn_start = virt_to_phys(pchan->sync_info_base) >> PAGE_SHIFT;
@@ -980,9 +1137,11 @@ void sdma_cdev_init(struct cdev *cdev)
	cdev->owner = THIS_MODULE;
}

void sdma_info_sync_cdev(struct hisi_sdma_core_device *p, u32 *share_chns, struct ida *fd_ida)
void sdma_info_sync_cdev(struct hisi_sdma_core_device *p, u32 *share_chns, struct ida *fd_ida,
			 bool *safe_mode)
{
	g_info.core_dev = p;
	g_info.fd_ida = fd_ida;
	g_info.share_chns = share_chns;
	g_info.sdma_mode = safe_mode;
}
+492 −0

File added.

Preview size limit exceeded, changes collapsed.

+25 −1
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#define RW_R_R			0644
#define SDMA_IRQ_NUM_MAX	512
#define ALIGN_NUM		1
#define HISI_SDMA_HAL_HASH_BUCKETS_BITS 8

/**
 * struct hisi_sdma_channel - Information about one channel in the SDMA device
@@ -41,6 +42,12 @@ struct hisi_sdma_channel {
	u16 cnt_used;
};

struct hisi_sdma_pid_ref_hte {
	u32 pid;
	u32 ref;
	struct hlist_node node;
};

/**
 * struct hisi_sdma_device - SDMA device structure
 * @idx: SDMA device's ID
@@ -77,6 +84,8 @@ struct hisi_sdma_device {

	int irq_cnt;
	int irq[SDMA_IRQ_NUM_MAX];
	DECLARE_HASHTABLE(sdma_pid_ref_ht, HISI_SDMA_HAL_HASH_BUCKETS_BITS);
	spinlock_t pid_lock;
};

struct hisi_sdma_core_device {
@@ -88,12 +97,17 @@ struct hisi_sdma_core_device {

struct hisi_sdma_global_info {
	u32 *share_chns;
	bool *sdma_mode;
	struct hisi_sdma_core_device *core_dev;
	struct ida *fd_ida;
};

void sdma_clear_pid_ref(struct hisi_sdma_device *psdma_dev);
int sdma_create_dbg_node(struct dentry *sdma_dbgfs_dir);
void sdma_cdev_init(struct cdev *cdev);
void sdma_info_sync_cdev(struct hisi_sdma_core_device *p, u32 *share_chns, struct ida *fd_ida);
void sdma_info_sync_cdev(struct hisi_sdma_core_device *p, u32 *share_chns, struct ida *fd_ida,
			 bool *safe_mode);
void sdma_info_sync_dbg(struct hisi_sdma_core_device *p, u32 *share_chns);

static inline void chn_set_val(struct hisi_sdma_channel *pchan, int reg, u32 val, u32 mask)
{
@@ -128,6 +142,16 @@ static inline bool sdma_channel_is_idle(struct hisi_sdma_channel *pchan)
	return chn_get_val(pchan, HISI_SDMA_CH_STATUS_REG, HISI_SDMA_CHN_FSM_IDLE_MSK) == 1;
}

static inline bool sdma_channel_is_running(struct hisi_sdma_channel *pchan)
{
	return chn_get_val(pchan, HISI_SDMA_CH_STATUS_REG, HISI_SDMA_CHN_FSM_RUNNING_MSK) == 1;
}

static inline bool sdma_channel_is_abort(struct hisi_sdma_channel *pchan)
{
	return chn_get_val(pchan, HISI_SDMA_CH_STATUS_REG, HISI_SDMA_CHN_FSM_ABORT_MSK) == 1;
}

static inline bool sdma_channel_is_quiescent(struct hisi_sdma_channel *pchan)
{
	return chn_get_val(pchan, HISI_SDMA_CH_STATUS_REG, HISI_SDMA_CHN_FSM_QUIESCENT_MSK) == 1;
Loading