Commit 4189703c authored by zhangyuyang's avatar zhangyuyang
Browse files

drivers:misc:sdma-dae: bugfix of channel operation

kunpeng inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB8U9I


CVE: NA

----------------------------------------------------------------------

1. fix channel ida management.
2. change channel reset logic.
3. change memory alloc flag to GFP_ATOMIC in lock.

Fixes: f8eeb398 ("drivers: misc: sdma-dae: support channel management")
Signed-off-by: default avatarzhangyuyang <zhangyuyang31@huawei.com>
parent 74e85e88
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -124,14 +124,16 @@ static int sdma_add_ida_ref(struct hisi_sdma_channel *pchannel, int ida)
	spin_lock(&pchannel->owner_chn_lock);
	entry = sdma_search_ida_ref(pchannel, ida);
	if (entry == NULL) {
		entry = kzalloc(sizeof(struct hisi_sdma_channel_node), GFP_KERNEL);
		entry = kzalloc(sizeof(struct hisi_sdma_channel_node), GFP_ATOMIC);
		if (entry == NULL) {
			spin_unlock(&pchannel->owner_chn_lock);
			return -ENOMEM;
		}
		entry->ida = ida;
		entry->ref = 1;
		hash_add(pchannel->sdma_ida_ht, &entry->node, entry->ida);
	}
	} else
		entry->ref++;
	spin_unlock(&pchannel->owner_chn_lock);
	return 0;
}
@@ -143,8 +145,11 @@ static bool sdma_del_ida_ref(struct hisi_sdma_channel *pchannel, int ida)
	spin_lock(&pchannel->owner_chn_lock);
	entry = sdma_search_ida_ref(pchannel, ida);
	if (entry != NULL) {
		entry->ref--;
		if (entry->ref == 0) {
			hash_del(&entry->node);
			kfree(entry);
		}
	} else {
		spin_unlock(&pchannel->owner_chn_lock);
		return false;
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ struct hisi_sdma_channel {

struct hisi_sdma_channel_node {
	int ida;
	u32 ref;
	struct hlist_node node;
};

+7 −7
Original line number Diff line number Diff line
@@ -89,18 +89,18 @@ static void sdma_channel_init(struct hisi_sdma_channel *pchan)

static void sdma_channel_reset_sq_cq(struct hisi_sdma_channel *pchan)
{
	u32 sq_head, sq_tail, cq_head, cq_tail;
	u32 cq_head, cq_tail;

	sq_head = sdma_channel_get_sq_head(pchan);
	sq_tail = sdma_channel_get_sq_tail(pchan);
	cq_head = sdma_channel_get_cq_head(pchan);
	cq_tail = sdma_channel_get_cq_tail(pchan);

	if (sq_head != sq_tail)
		sdma_channel_set_sq_tail(pchan, sq_head);

	if (cq_head != cq_tail)
	while (cq_head != cq_tail) {
		sdma_channel_set_cq_head(pchan, cq_tail);
		msleep(HISI_SDMA_FSM_INTERVAL);

		cq_head = sdma_channel_get_cq_head(pchan);
		cq_tail = sdma_channel_get_cq_tail(pchan);
	}
}

static void sdma_channel_reset(struct hisi_sdma_channel *pchan)