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

Commit 9e3908f3 authored by Patrick Lai's avatar Patrick Lai Committed by Banajit Goswami
Browse files

ASoC: msm: qdsp6v2: move frame info to be per session based



When audio stream manager returns READ_DONE event, the payload
which comes with the event contains size of captured audio data
and offset indicating where the data starts in the buffer.
Before this change, size and offset information is stored in
global variable which can be shared by all capture sessions.
If the offset is overwritten by another session with larger value,
buffer can be indexed beyond actual size of buffer when copying
captured data into user-space buffer. Move the structure as part
of per session private data to prevent overwriting.

Change-Id: Iaee12b0153b945a315e95c862fa2522cbd69c6f8
Signed-off-by: default avatarPatrick Lai <plai@codeaurora.org>
Signed-off-by: default avatarBanajit Goswami <bgoswami@codeaurora.org>
parent b9ae0269
Loading
Loading
Loading
Loading
+16 −10
Original line number Original line Diff line number Diff line
@@ -116,8 +116,6 @@ static unsigned int supported_sample_rates[] = {
	88200, 96000, 176400, 192000
	88200, 96000, 176400, 192000
};
};


static uint32_t in_frame_info[CAPTURE_MAX_NUM_PERIODS][2];

static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
	.count = ARRAY_SIZE(supported_sample_rates),
	.count = ARRAY_SIZE(supported_sample_rates),
	.list = supported_sample_rates,
	.list = supported_sample_rates,
@@ -183,11 +181,11 @@ static void event_handler(uint32_t opcode,
	case ASM_DATA_EVENT_READ_DONE_V2: {
	case ASM_DATA_EVENT_READ_DONE_V2: {
		pr_debug("ASM_DATA_EVENT_READ_DONE_V2\n");
		pr_debug("ASM_DATA_EVENT_READ_DONE_V2\n");
		pr_debug("token = 0x%08x\n", token);
		pr_debug("token = 0x%08x\n", token);
		in_frame_info[token][0] = payload[4];
		prtd->in_frame_info[token].size = payload[4];
		in_frame_info[token][1] = payload[5];
		prtd->in_frame_info[token].offset = payload[5];
		/* assume data size = 0 during flushing */
		/* assume data size = 0 during flushing */
		if (in_frame_info[token][0]) {
		if (prtd->in_frame_info[token].size) {
			prtd->pcm_irq_pos += in_frame_info[token][0];
			prtd->pcm_irq_pos += prtd->in_frame_info[token].size;
			pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
			pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
			if (atomic_read(&prtd->start))
			if (atomic_read(&prtd->start))
				snd_pcm_period_elapsed(substream);
				snd_pcm_period_elapsed(substream);
@@ -378,6 +376,12 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)


	pr_debug("%s\n", __func__);
	pr_debug("%s\n", __func__);
	if (prtd->enabled == IDLE) {
	if (prtd->enabled == IDLE) {
		prtd->in_frame_info = kcalloc(runtime->periods,
					sizeof(struct msm_audio_in_frame_info),
					GFP_KERNEL);
		if (!prtd->in_frame_info)
			return -ENOMEM;

		params = &soc_prtd->dpcm[substream->stream].hw_params;
		params = &soc_prtd->dpcm[substream->stream].hw_params;
		if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
		if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE)
			bits_per_sample = 24;
			bits_per_sample = 24;
@@ -398,6 +402,7 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
			pr_err("%s: q6asm_open_read failed\n", __func__);
			pr_err("%s: q6asm_open_read failed\n", __func__);
			q6asm_audio_client_free(prtd->audio_client);
			q6asm_audio_client_free(prtd->audio_client);
			prtd->audio_client = NULL;
			prtd->audio_client = NULL;
			kfree(prtd->in_frame_info);
			return -ENOMEM;
			return -ENOMEM;
		}
		}


@@ -753,7 +758,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
		xfer = fbytes;
		xfer = fbytes;
		if (xfer > size)
		if (xfer > size)
			xfer = size;
			xfer = size;
		offset = in_frame_info[idx][1];
		offset = prtd->in_frame_info[idx].offset;
		pr_debug("Offset value = %d\n", offset);
		pr_debug("Offset value = %d\n", offset);
		if (copy_to_user(buf, bufptr+offset, xfer)) {
		if (copy_to_user(buf, bufptr+offset, xfer)) {
			pr_err("Failed to copy buf to user\n");
			pr_err("Failed to copy buf to user\n");
@@ -762,12 +767,12 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
		}
		}
		fbytes -= xfer;
		fbytes -= xfer;
		size -= xfer;
		size -= xfer;
		in_frame_info[idx][1] += xfer;
		prtd->in_frame_info[idx].offset += xfer;
		pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
		pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
					__func__, fbytes, size, xfer);
					__func__, fbytes, size, xfer);
		pr_debug(" Sending next buffer to dsp\n");
		pr_debug(" Sending next buffer to dsp\n");
		memset(&in_frame_info[idx], 0,
		memset(&prtd->in_frame_info[idx], 0,
			sizeof(uint32_t) * 2);
		       sizeof(struct msm_audio_in_frame_info));
		atomic_dec(&prtd->in_count);
		atomic_dec(&prtd->in_count);
		ret = q6asm_read(prtd->audio_client);
		ret = q6asm_read(prtd->audio_client);
		if (ret < 0) {
		if (ret < 0) {
@@ -792,6 +797,7 @@ static int msm_pcm_capture_close(struct snd_pcm_substream *substream)


	pr_debug("%s\n", __func__);
	pr_debug("%s\n", __func__);
	if (prtd->audio_client) {
	if (prtd->audio_client) {
		kfree(prtd->in_frame_info);
		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
		q6asm_audio_client_buf_free_contiguous(dir,
		q6asm_audio_client_buf_free_contiguous(dir,
				prtd->audio_client);
				prtd->audio_client);
+7 −1
Original line number Original line Diff line number Diff line
/*
/*
 * Copyright (C) 2008 Google, Inc.
 * Copyright (C) 2008 Google, Inc.
 * Copyright (C) 2008 HTC Corporation
 * Copyright (C) 2008 HTC Corporation
 * Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
 *
 *
 * This software is licensed under the terms of the GNU General Public
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * License version 2, as published by the Free Software Foundation, and
@@ -52,6 +52,11 @@ struct audio_locks {
	wait_queue_head_t flush_wait;
	wait_queue_head_t flush_wait;
};
};


struct msm_audio_in_frame_info {
	uint32_t size;
	uint32_t offset;
};

struct msm_audio {
struct msm_audio {
	struct snd_pcm_substream *substream;
	struct snd_pcm_substream *substream;
	unsigned int pcm_size;
	unsigned int pcm_size;
@@ -95,6 +100,7 @@ struct msm_audio {
	int cmd_interrupt;
	int cmd_interrupt;
	bool meta_data_mode;
	bool meta_data_mode;
	uint32_t volume;
	uint32_t volume;
	struct msm_audio_in_frame_info *in_frame_info; /* array of frame info */
};
};


struct output_meta_data_st {
struct output_meta_data_st {