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

Commit 32374150 authored by Kuirong Wang's avatar Kuirong Wang Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: msm: Update the error handling when APR sends packet failed



Update the error handling when APR sends packet failed so that audio
driver can perform proper error recovery.

CRs-Fixed: 1050605
Change-Id: I6210e244e6299ec747836f40d03e92c15c6e53ee
Signed-off-by: default avatarKuirong Wang <kuirongw@codeaurora.org>
parent 86691680
Loading
Loading
Loading
Loading
+14 −4
Original line number Diff line number Diff line
@@ -276,6 +276,7 @@ int apr_send_pkt(void *handle, uint32_t *buf)
	uint16_t dest_id;
	uint16_t client_id;
	uint16_t w_len;
	int rc;
	unsigned long flags;

	if (!handle || !buf) {
@@ -317,14 +318,23 @@ int apr_send_pkt(void *handle, uint32_t *buf)
	APR_PKT_INFO("Tx: dest_svc[%d], opcode[0x%X], size[%d]",
			hdr->dest_svc, hdr->opcode, hdr->pkt_size);

	w_len = apr_tal_write(clnt->handle, buf,
	rc = apr_tal_write(clnt->handle, buf,
			(struct apr_pkt_priv *)&svc->pkt_owner,
			hdr->pkt_size);
	if (w_len != hdr->pkt_size)
		pr_err("Unable to write APR pkt successfully: %d\n", w_len);
	if (rc >= 0) {
		w_len = rc;
		if (w_len != hdr->pkt_size) {
			pr_err("%s: Unable to write whole APR pkt successfully: %d\n",
			       __func__, rc);
			rc = -EINVAL;
		}
	} else {
		pr_err("%s: Write APR pkt failed with error %d\n",
			__func__, rc);
	}
	spin_unlock_irqrestore(&svc->w_lock, flags);

	return w_len;
	return rc;
}

int apr_pkt_config(void *handle, struct apr_pkt_cfg *cfg)
+2 −0
Original line number Diff line number Diff line
@@ -340,6 +340,8 @@ int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd,
void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac,
				uint32_t *size, uint32_t *idx);

int q6asm_cpu_buf_release(int dir, struct audio_client *ac);

void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
					uint32_t *size, uint32_t *idx);

+20 −1
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ struct snd_msm {

#define CMD_EOS_MIN_TIMEOUT_LENGTH  50
#define CMD_EOS_TIMEOUT_MULTIPLIER  (HZ * 50)
#define MAX_PB_COPY_RETRIES         3

static struct snd_pcm_hardware msm_pcm_hardware_capture = {
	.info =                 (SNDRV_PCM_INFO_MMAP |
@@ -625,6 +626,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
	void *data = NULL;
	uint32_t idx = 0;
	uint32_t size = 0;
	uint32_t retries = 0;

	struct snd_pcm_runtime *runtime = substream->runtime;
	struct msm_audio *prtd = runtime->private_data;
@@ -633,7 +635,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
	pr_debug("%s: prtd->out_count = %d\n",
				__func__, atomic_read(&prtd->out_count));

	while (fbytes > 0) {
	while ((fbytes > 0) && (retries < MAX_PB_COPY_RETRIES)) {
		if (prtd->reset_event) {
			pr_err("%s: In SSR return ENETRESET before wait\n",
				__func__);
@@ -662,6 +664,13 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,

		data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size,
			&idx);
		if (data == NULL) {
			retries++;
			continue;
		} else {
			retries = 0;
		}

		if (fbytes > size)
			xfer = size;
		else
@@ -673,6 +682,9 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
						__func__, fbytes, xfer, size);
			if (copy_from_user(bufptr, buf, xfer)) {
				ret = -EFAULT;
				pr_err("%s: copy_from_user failed\n",
					__func__);
				q6asm_cpu_buf_release(IN, prtd->audio_client);
				goto fail;
			}
			buf += xfer;
@@ -686,6 +698,8 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
							0, 0, NO_TIMESTAMP);
				if (ret < 0) {
					ret = -EFAULT;
					q6asm_cpu_buf_release(IN,
						prtd->audio_client);
					goto fail;
				}
			} else
@@ -694,6 +708,9 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
		}
	}
fail:
	if (retries >= MAX_PB_COPY_RETRIES)
		ret = -ENOMEM;

	return  ret;
}

@@ -798,6 +815,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
		if (copy_to_user(buf, bufptr+offset, xfer)) {
			pr_err("Failed to copy buf to user\n");
			ret = -EFAULT;
			q6asm_cpu_buf_release(OUT, prtd->audio_client);
			goto fail;
		}
		fbytes -= xfer;
@@ -813,6 +831,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
		if (ret < 0) {
			pr_err("q6asm read failed\n");
			ret = -EFAULT;
			q6asm_cpu_buf_release(OUT, prtd->audio_client);
			goto fail;
		}
	} else
+34 −0
Original line number Diff line number Diff line
@@ -1988,6 +1988,40 @@ void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size,
	return NULL;
}

int q6asm_cpu_buf_release(int dir, struct audio_client *ac)
{
	struct audio_port_data *port;
	int ret = 0;
	int idx;

	if (!ac || ((dir != IN) && (dir != OUT))) {
		pr_err("%s: ac %pK dir %d\n", __func__, ac, dir);
		ret = -EINVAL;
		goto exit;
	}

	if (ac->io_mode & SYNC_IO_MODE) {
		port = &ac->port[dir];
		mutex_lock(&port->lock);
		idx = port->cpu_buf;
		if (port->cpu_buf == 0) {
			port->cpu_buf = port->max_buf_cnt - 1;
		} else if (port->cpu_buf < port->max_buf_cnt) {
			port->cpu_buf = port->cpu_buf - 1;
		} else {
			pr_err("%s: buffer index(%d) out of range\n",
			       __func__, port->cpu_buf);
			ret = -EINVAL;
			mutex_unlock(&port->lock);
			goto exit;
		}
		port->buf[port->cpu_buf].used = dir ^ 1;
		mutex_unlock(&port->lock);
	}
exit:
	return ret;
}

void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac,
					uint32_t *size, uint32_t *index)
{