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

Commit 2ae23287 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-lsm-client: Update lsm client driver to prevent buffer overrun"

parents d577325e 4867dc18
Loading
Loading
Loading
Loading
+45 −9
Original line number Diff line number Diff line
@@ -93,6 +93,9 @@ struct lsm_priv {
	struct mutex lsm_api_lock;
	int appl_cnt;
	int dma_write;
	int xrun_count;
	int xrun_index;
	spinlock_t xrun_lock;
};

enum { /* lsm session states */
@@ -224,6 +227,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
		int rc;
		struct lsm_cmd_read_done *read_done = (struct lsm_cmd_read_done *)payload;
		int buf_index = 0;
		unsigned long flags = 0;

		if (prtd->lsm_client->session != token ||
		    !read_done) {
@@ -250,10 +254,13 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
				prtd->lsm_client->out_hw_params.period_count);
				return;
			}
			spin_lock_irqsave(&prtd->xrun_lock, flags);
			prtd->dma_write += read_done->total_size;
			atomic_inc(&prtd->buf_count);
			snd_pcm_period_elapsed(substream);
			wake_up(&prtd->period_wait);
			if (atomic_read(&prtd->buf_count) <
				prtd->lsm_client->out_hw_params.period_count) {
				/* queue the next period buffer */
				buf_index = (buf_index + 1) %
				prtd->lsm_client->out_hw_params.period_count;
@@ -262,6 +269,15 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
					dev_err(rtd->dev,
						"%s: error in queuing the lab buffer rc %d\n",
						__func__, rc);
			} else {
				dev_dbg(rtd->dev,
					"%s: xrun: further lab to be queued after read from user\n",
					 __func__);
				if (!prtd->xrun_count)
					prtd->xrun_index = buf_index;
				(prtd->xrun_count)++;
			}
			spin_unlock_irqrestore(&prtd->xrun_lock, flags);
		} else
			dev_err(rtd->dev, "%s: Invalid lab buffer returned by dsp\n",
				__func__);
@@ -970,6 +986,8 @@ static int msm_lsm_start_lab_buffer(struct lsm_priv *prtd, uint16_t status)
		atomic_set(&prtd->buf_count, 0);
		prtd->appl_cnt = 0;
		prtd->dma_write = 0;
		prtd->xrun_count = 0;
		prtd->xrun_index = 0;

		rc = msm_lsm_queue_lab_buffer(prtd, 0);
		if (rc)
@@ -2377,6 +2395,7 @@ static int msm_lsm_open(struct snd_pcm_substream *substream)
	}
	mutex_init(&prtd->lsm_api_lock);
	spin_lock_init(&prtd->event_lock);
	spin_lock_init(&prtd->xrun_lock);
	init_waitqueue_head(&prtd->event_wait);
	init_waitqueue_head(&prtd->period_wait);
	prtd->substream = substream;
@@ -2721,7 +2740,8 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch,
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct lsm_priv *prtd = runtime->private_data;
	char *pcm_buf = NULL;
	int rc = 0;
	int rc = 0, buf_index = 0;
	unsigned long flags = 0;
	struct snd_soc_pcm_runtime *rtd;

	if (!substream->private_data) {
@@ -2776,7 +2796,23 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch,
	}
	prtd->appl_cnt = (prtd->appl_cnt + 1) %
		prtd->lsm_client->out_hw_params.period_count;

	spin_lock_irqsave(&prtd->xrun_lock, flags);
	/* Queue lab buffer here if in xrun */
	if (prtd->xrun_count > 0) {
		(prtd->xrun_count)--;
		buf_index = (prtd->xrun_index + 1) %
			prtd->lsm_client->out_hw_params.period_count;
		rc = msm_lsm_queue_lab_buffer(prtd, buf_index);
		if (rc)
			dev_err(rtd->dev,
				"%s: error in queuing the lab buffer rc %d\n",
				__func__, rc);
		prtd->xrun_index = buf_index;
	}
	atomic_dec(&prtd->buf_count);
	spin_unlock_irqrestore(&prtd->xrun_lock, flags);

	return 0;
}