Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6adf1458 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ASoC: msm: qdsp6v2: Track no wait commands"

parents e6a50a28 af77ff28
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <sound/apr_audio-v2.h>
#include <linux/list.h>
#include <linux/msm_ion.h>
#include <linux/spinlock.h>

#define IN                      0x000
#define OUT                     0x001
@@ -173,6 +174,8 @@ struct audio_client {
	/* Relative or absolute TS */
	atomic_t	       time_flag;
	atomic_t	       nowait_cmd_cnt;
	struct list_head       no_wait_que;
	spinlock_t             no_wait_que_spinlock;
	atomic_t               mem_state;
	void		       *priv;
	uint32_t               io_mode;
+81 −18
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#include <linux/dma-mapping.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/msm_audio.h>

@@ -64,6 +63,11 @@ static struct asm_mmap this_mmap;
/* session id: 0 reserved */
static struct audio_client *session[SESSION_MAX+1];

struct asm_no_wait_node {
	struct list_head	list;
	int32_t			opcode;
};

struct asm_buffer_node {
	struct list_head list;
	phys_addr_t buf_phys_addr;
@@ -429,6 +433,54 @@ static void q6asm_session_free(struct audio_client *ac)
	return;
}

static int q6asm_add_nowait_opcode(struct audio_client *ac, uint32_t opcode)
{
	struct asm_no_wait_node		*new_node;
	unsigned long flags;
	int ret = 0;

	new_node = kmalloc(sizeof(struct asm_no_wait_node), GFP_ATOMIC);
	if (new_node == NULL) {
		ret = -ENOMEM;
		goto done;
	}
	new_node->opcode = opcode;
	INIT_LIST_HEAD(&new_node->list);

	spin_lock_irqsave(&ac->no_wait_que_spinlock, flags);
	list_add_tail(&new_node->list, &ac->no_wait_que);
	spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags);

done:
	return ret;
}

static bool q6asm_remove_nowait_opcode(struct audio_client *ac,
						uint32_t opcode)
{
	struct list_head		*ptr, *next;
	struct asm_no_wait_node		*node;
	unsigned long flags;
	bool ret = false;

	spin_lock_irqsave(&ac->no_wait_que_spinlock, flags);
	list_for_each_safe(ptr, next, &ac->no_wait_que) {
		node = list_entry(ptr,
			struct asm_no_wait_node, list);
		if (node->opcode == opcode) {
			list_del(&node->list);
			kfree(node);
			ret = true;
			goto done;
		}
	}

	pr_err("%s: nowait opcode NOT found 0x%x\n", __func__, opcode);
done:
	spin_unlock_irqrestore(&ac->no_wait_que_spinlock, flags);
	return ret;
}

static uint32_t q6asm_get_next_buf(struct audio_client *ac,
		uint32_t curr_buf, uint32_t max_buf_cnt)
{
@@ -899,6 +951,9 @@ void q6asm_audio_client_free(struct audio_client *ac)
{
	int loopcnt;
	struct audio_port_data *port;
	struct list_head		*ptr, *next;
	struct asm_no_wait_node		*node;

	if (!ac) {
		pr_err("%s: ac %p\n", __func__, ac);
		return;
@@ -922,6 +977,13 @@ void q6asm_audio_client_free(struct audio_client *ac)
		}
	}

	list_for_each_safe(ptr, next, &ac->no_wait_que) {
		node = list_entry(ptr, struct asm_no_wait_node, list);
		list_del(&node->list);
		kfree(node);
	}
	list_del(&ac->no_wait_que);

	apr_deregister(ac->apr2);
	ac->apr2 = NULL;
	apr_deregister(ac->apr);
@@ -1060,6 +1122,7 @@ struct audio_client *q6asm_audio_client_alloc(app_cb cb, void *priv)
	}
	atomic_set(&ac->cmd_state, 0);
	atomic_set(&ac->nowait_cmd_cnt, 0);
	INIT_LIST_HEAD(&ac->no_wait_que);
	atomic_set(&ac->mem_state, 0);

	rc = send_asm_custom_topology(ac);
@@ -1435,29 +1498,18 @@ static int32_t q6asm_srvc_callback(struct apr_client_data *data, void *priv)
	return 0;
}

static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type)
static bool remove_no_wait_cmd(struct audio_client *ac, uint32_t opcode,
				uint32_t *cmd_type)
{
	if (opcode == APR_BASIC_RSP_RESULT) {
		if (cmd_type != NULL) {
			switch (cmd_type[0]) {
			case ASM_SESSION_CMD_RUN_V2:
			case ASM_SESSION_CMD_PAUSE:
			case ASM_DATA_CMD_EOS:
			case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
			case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
			case ASM_STREAM_CMD_SET_PP_PARAMS_V2:
				return 1;
			default:
				pr_debug("%s: default err 0x%x\n",
				__func__, cmd_type[0]);
				break;
			}
			return q6asm_remove_nowait_opcode(ac, cmd_type[0]);
		} else
			pr_err("%s: null pointer!", __func__);
	} else if (opcode == ASM_DATA_EVENT_RENDERED_EOS)
		return 1;
		return q6asm_remove_nowait_opcode(ac, ASM_DATA_CMD_EOS);

	return 0;
	return false;
}

static void q6asm_process_mtmx_get_param_rsp(struct audio_client *ac,
@@ -1545,7 +1597,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)

	payload = data->payload;
	if ((atomic_read(&ac->nowait_cmd_cnt) > 0) &&
		is_no_wait_cmd_rsp(data->opcode, payload)) {
		remove_no_wait_cmd(ac, data->opcode, payload)) {
		pr_debug("%s: nowait_cmd_cnt %d\n",
				__func__,
				atomic_read(&ac->nowait_cmd_cnt));
@@ -2837,9 +2889,11 @@ static int __q6asm_run_nowait(struct audio_client *ac, uint32_t flags,

	/* have to increase first avoid race */
	atomic_inc(&ac->nowait_cmd_cnt);
	q6asm_add_nowait_opcode(ac, run.hdr.opcode);
	rc = apr_send_pkt(ac->apr, (uint32_t *) &run);
	if (rc < 0) {
		atomic_dec(&ac->nowait_cmd_cnt);
		q6asm_remove_nowait_opcode(ac, run.hdr.opcode);
		pr_err("%s: Commmand run failed[%d]", __func__, rc);
		return -EINVAL;
	}
@@ -6265,9 +6319,11 @@ static int __q6asm_cmd_nowait(struct audio_client *ac, int cmd,
			hdr.opcode);
	/* have to increase first avoid race */
	atomic_inc(&ac->nowait_cmd_cnt);
	q6asm_add_nowait_opcode(ac, hdr.opcode);
	rc = apr_send_pkt(ac->apr, (uint32_t *) &hdr);
	if (rc < 0) {
		atomic_dec(&ac->nowait_cmd_cnt);
		q6asm_remove_nowait_opcode(ac, hdr.opcode);
		pr_err("%s: Commmand 0x%x failed %d\n",
				__func__, hdr.opcode, rc);
		goto fail_cmd;
@@ -6323,10 +6379,12 @@ int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id,
	silence.num_samples_to_remove    = initial_samples;

	atomic_inc(&ac->nowait_cmd_cnt);
	q6asm_add_nowait_opcode(ac, silence.hdr.opcode);
	rc = apr_send_pkt(ac->apr, (uint32_t *) &silence);
	if (rc < 0) {
		pr_err("%s: Commmand silence failed[%d]", __func__, rc);
		atomic_dec(&ac->nowait_cmd_cnt);
		q6asm_remove_nowait_opcode(ac, silence.hdr.opcode);
		goto fail_cmd;
	}

@@ -6334,10 +6392,12 @@ int __q6asm_send_meta_data(struct audio_client *ac, uint32_t stream_id,
	silence.num_samples_to_remove    = trailing_samples;

	atomic_inc(&ac->nowait_cmd_cnt);
	q6asm_add_nowait_opcode(ac, silence.hdr.opcode);
	rc = apr_send_pkt(ac->apr, (uint32_t *) &silence);
	if (rc < 0) {
		pr_err("%s: Commmand silence failed[%d]", __func__, rc);
		atomic_dec(&ac->nowait_cmd_cnt);
		q6asm_remove_nowait_opcode(ac, silence.hdr.opcode);
		goto fail_cmd;
	}

@@ -6837,10 +6897,12 @@ static int q6asm_send_asm_cal_nowait(struct audio_client *ac)
		payload_params.data_payload_size);

	atomic_inc(&ac->nowait_cmd_cnt);
	q6asm_add_nowait_opcode(ac, hdr.opcode);
	rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
	if (rc < 0) {
		pr_err("%s: audio audstrm cal send failed\n", __func__);
		atomic_dec(&ac->nowait_cmd_cnt);
		q6asm_remove_nowait_opcode(ac, hdr.opcode);
		rc = -EINVAL;
		goto done;
	}
@@ -7060,6 +7122,7 @@ static int __init q6asm_init(void)
	}
	atomic_set(&common_client.cmd_state, 0);
	atomic_set(&common_client.nowait_cmd_cnt, 0);
	INIT_LIST_HEAD(&common_client.no_wait_que);
	atomic_set(&common_client.mem_state, 0);

	ret = q6asm_init_cal_data();