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

Commit ead1a158 authored by Banajit Goswami's avatar Banajit Goswami
Browse files

ASoC: msm: fix integer overflow for long duration offload playback



32 bit variable is used for storing number of bytes copied to DSP,
which can overflow when playback duration goes beyond 24 hours.
Change data type for this variable to uint64_t, to prevent overflow
and related playback anomaly.

CRs-Fixed: 877677
Change-Id: Ie4dfa630cf89559bb784d4712c52526665baeca6
Signed-off-by: default avatarDhananjay Kumar <dhakumar@codeaurora.org>
Signed-off-by: default avatarBanajit Goswami <bgoswami@codeaurora.org>
parent f1b95032
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ struct snd_compr_params {
 */
struct snd_compr_tstamp {
	__u32 byte_offset;
	__u32 copied_total;
	__u64 copied_total;
	__u32 pcm_frames;
	__u32 pcm_io_frames;
	__u32 sampling_rate;
+1 −1
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ static int snd_compr_update_tstamp(struct snd_compr_stream *stream,
	err = stream->ops->pointer(stream, tstamp);
	if (err)
		return err;
	pr_debug("dsp consumed till %d total %d bytes\n",
	pr_debug("dsp consumed till %d total %llu bytes\n",
		tstamp->byte_offset, tstamp->copied_total);
	if (stream->direction == SND_COMPRESS_PLAYBACK)
		stream->runtime->total_bytes_transferred = tstamp->copied_total;
+15 −12
Original line number Diff line number Diff line
@@ -129,9 +129,9 @@ struct msm_compr_audio {
	uint32_t app_pointer;
	uint32_t buffer_size;
	uint32_t byte_offset;
	uint32_t copied_total; /* bytes consumed by DSP */
	uint32_t bytes_received; /* from userspace */
	uint32_t bytes_sent; /* to DSP */
	uint64_t copied_total; /* bytes consumed by DSP */
	uint64_t bytes_received; /* from userspace */
	uint64_t bytes_sent; /* to DSP */

	int32_t first_buffer;
	int32_t last_buffer;
@@ -300,7 +300,7 @@ static int msm_compr_send_ddp_cfg(struct audio_client *ac,
static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
{
	int buffer_length;
	int bytes_available;
	uint64_t bytes_available;
	struct audio_aio_write_param param;

	if (!atomic_read(&prtd->start)) {
@@ -314,7 +314,7 @@ static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
		return -EPERM;
	}

	pr_debug("%s: bytes_received = %d copied_total = %d\n",
	pr_debug("%s: bytes_received = %llu copied_total = %llu\n",
		__func__, prtd->bytes_received, prtd->copied_total);
	if (prtd->first_buffer &&  prtd->gapless_state.use_dsp_gapless_mode &&
		prtd->compr_passthr == LEGACY_PCM)
@@ -371,7 +371,8 @@ static void compr_event_handler(uint32_t opcode,
	struct audio_client *ac;
	uint32_t chan_mode = 0;
	uint32_t sample_rate = 0;
	int bytes_available, stream_id;
	uint64_t bytes_available;
	int stream_id;
	uint32_t stream_index;
	unsigned long flags;

@@ -388,10 +389,12 @@ static void compr_event_handler(uint32_t opcode,
		spin_lock_irqsave(&prtd->lock, flags);

		if (payload[3]) {
			pr_err("WRITE FAILED w/ err 0x%x !, paddr 0x%x byte_offset=%d, copied_total=%d, token=%d\n",
			pr_err("%s: WRITE FAILED w/ err 0x%x !, paddr 0x%x, byte_offset=%d,copied_total=%llu,token=%d\n",
				__func__,
				payload[3],
				payload[0],
				prtd->byte_offset, prtd->copied_total, token);
				prtd->byte_offset,
				prtd->copied_total, token);

			if (atomic_cmpxchg(&prtd->drain, 1, 0) &&
			    prtd->last_buffer) {
@@ -1990,7 +1993,7 @@ static int msm_compr_copy(struct snd_compr_stream *cstream,
	struct msm_compr_audio *prtd = runtime->private_data;
	void *dstn;
	size_t copy;
	size_t bytes_available = 0;
	uint64_t bytes_available = 0;
	unsigned long flags;

	pr_debug("%s: count = %zd\n", __func__, count);
@@ -2034,7 +2037,7 @@ static int msm_compr_copy(struct snd_compr_stream *cstream,
			bytes_available = prtd->bytes_received -
					  prtd->copied_total;
			if (bytes_available >= runtime->fragment_size) {
				pr_debug("%s: handle xrun, bytes_to_write = %zd\n",
				pr_debug("%s: handle xrun, bytes_to_write = %llu\n",
					 __func__, bytes_available);
				atomic_set(&prtd->xrun, 0);
				msm_compr_send_buffer(prtd);