MLK-22340-4: ASoC: fsl_rpmsg_i2s: add lock to protect the resource
Use the spin lock to protect the work_write_index and work_read_index,
Use the spin lock to protect the period_done_msg_enabled flag
That is to avoid the read and write flag confliction.
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
(cherry picked from commit 6de0ce94dd)
This commit is contained in:
@ -164,14 +164,21 @@ static void rpmsg_i2s_work(struct work_struct *work)
|
||||
struct work_of_rpmsg *work_of_rpmsg;
|
||||
struct i2s_info *i2s_info;
|
||||
bool is_period_done = false;
|
||||
unsigned long flags;
|
||||
struct i2s_rpmsg msg;
|
||||
|
||||
work_of_rpmsg = container_of(work, struct work_of_rpmsg, work);
|
||||
i2s_info = work_of_rpmsg->i2s_info;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->lock[0], flags);
|
||||
if (i2s_info->period_done_msg_enabled[0]) {
|
||||
i2s_send_message(&i2s_info->period_done_msg[0], i2s_info);
|
||||
memcpy(&msg, &i2s_info->period_done_msg[0], sizeof(struct i2s_rpmsg_s));
|
||||
i2s_info->period_done_msg_enabled[0] = false;
|
||||
}
|
||||
spin_unlock_irqrestore(&i2s_info->lock[0], flags);
|
||||
|
||||
i2s_send_message(&msg, i2s_info);
|
||||
} else
|
||||
spin_unlock_irqrestore(&i2s_info->lock[0], flags);
|
||||
|
||||
if (i2s_info->period_done_msg_enabled[1]) {
|
||||
i2s_send_message(&i2s_info->period_done_msg[1], i2s_info);
|
||||
@ -186,8 +193,10 @@ static void rpmsg_i2s_work(struct work_struct *work)
|
||||
if (!is_period_done)
|
||||
i2s_send_message(&work_of_rpmsg->msg, i2s_info);
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
i2s_info->work_read_index++;
|
||||
i2s_info->work_read_index %= WORK_MAX_NUM;
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
}
|
||||
|
||||
static int fsl_rpmsg_i2s_probe(struct platform_device *pdev)
|
||||
@ -238,6 +247,7 @@ static int fsl_rpmsg_i2s_probe(struct platform_device *pdev)
|
||||
mutex_init(&i2s_info->i2c_lock);
|
||||
spin_lock_init(&i2s_info->lock[0]);
|
||||
spin_lock_init(&i2s_info->lock[1]);
|
||||
spin_lock_init(&i2s_info->wq_lock);
|
||||
|
||||
if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"fsl,imx7ulp-rpmsg-i2s")) {
|
||||
|
||||
@ -412,6 +412,7 @@ struct i2s_info {
|
||||
int (*send_message)(struct i2s_rpmsg *msg, struct i2s_info *info);
|
||||
dma_callback callback[2];
|
||||
spinlock_t lock[2];
|
||||
spinlock_t wq_lock;
|
||||
struct mutex tx_lock;
|
||||
struct mutex i2c_lock;
|
||||
struct stream_timer stream_timer[2];
|
||||
|
||||
@ -129,7 +129,7 @@ static void imx_rpmsg_timer_callback(struct timer_list *t)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
unsigned long flags;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rpmsg = &i2s_info->rpmsg[I2S_TX_PERIOD_DONE + I2S_TYPE_A_NUM];
|
||||
@ -141,7 +141,9 @@ static void imx_rpmsg_timer_callback(struct timer_list *t)
|
||||
else
|
||||
rpmsg->send_msg.header.cmd = I2S_RX_PERIOD_DONE;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
|
||||
@ -149,6 +151,7 @@ static void imx_rpmsg_timer_callback(struct timer_list *t)
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
i2s_info->msg_drop_count[substream->stream]++;
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
}
|
||||
|
||||
static int imx_rpmsg_pcm_open(struct snd_pcm_substream *substream)
|
||||
@ -295,7 +298,7 @@ static int imx_rpmsg_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
unsigned long flags;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rpmsg = &i2s_info->rpmsg[I2S_TX_BUFFER];
|
||||
@ -317,17 +320,23 @@ static int imx_rpmsg_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
|
||||
rpmsg->send_msg.param.buffer_size /
|
||||
rpmsg->send_msg.param.period_size;
|
||||
|
||||
i2s_info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete;
|
||||
i2s_info->callback_param[substream->stream] = substream;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
|
||||
i2s_info->work_write_index++;
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
i2s_info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete;
|
||||
i2s_info->callback_param[substream->stream] = substream;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -338,7 +347,7 @@ static int imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
unsigned long flags;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rpmsg = &i2s_info->rpmsg[I2S_TX_START];
|
||||
@ -350,14 +359,19 @@ static int imx_rpmsg_async_issue_pending(struct snd_pcm_substream *substream)
|
||||
else
|
||||
rpmsg->send_msg.header.cmd = I2S_RX_START;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
|
||||
i2s_info->work_write_index++;
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -369,7 +383,7 @@ static int imx_rpmsg_restart(struct snd_pcm_substream *substream)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
unsigned long flags;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rpmsg = &i2s_info->rpmsg[I2S_TX_RESTART];
|
||||
@ -381,15 +395,19 @@ static int imx_rpmsg_restart(struct snd_pcm_substream *substream)
|
||||
else
|
||||
rpmsg->send_msg.header.cmd = I2S_RX_RESTART;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
|
||||
i2s_info->work_write_index++;
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
return -EPIPE;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -400,7 +418,7 @@ static int imx_rpmsg_pause(struct snd_pcm_substream *substream)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
unsigned long flags;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rpmsg = &i2s_info->rpmsg[I2S_TX_PAUSE];
|
||||
@ -412,15 +430,19 @@ static int imx_rpmsg_pause(struct snd_pcm_substream *substream)
|
||||
else
|
||||
rpmsg->send_msg.header.cmd = I2S_RX_PAUSE;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
|
||||
i2s_info->work_write_index++;
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
return -EPIPE;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -431,8 +453,8 @@ static int imx_rpmsg_terminate_all(struct snd_pcm_substream *substream)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
int cmd;
|
||||
unsigned long flags;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
rpmsg = &i2s_info->rpmsg[I2S_TX_TERMINATE];
|
||||
@ -458,14 +480,19 @@ static int imx_rpmsg_terminate_all(struct snd_pcm_substream *substream)
|
||||
|
||||
del_timer(&i2s_info->stream_timer[substream->stream].timer);
|
||||
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq, &i2s_info->work_list[index].work);
|
||||
i2s_info->work_write_index++;
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
} else {
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
return -EPIPE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -524,10 +551,10 @@ int imx_rpmsg_pcm_ack(struct snd_pcm_substream *substream)
|
||||
struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(cpu_dai->dev);
|
||||
struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info;
|
||||
struct i2s_rpmsg *rpmsg;
|
||||
int index = i2s_info->work_write_index;
|
||||
int buffer_tail = 0;
|
||||
int writen_num = 0;
|
||||
snd_pcm_sframes_t avail;
|
||||
unsigned long flags;
|
||||
|
||||
if (!rpmsg_i2s->force_lpa)
|
||||
return 0;
|
||||
@ -554,9 +581,13 @@ int imx_rpmsg_pcm_ack(struct snd_pcm_substream *substream)
|
||||
writen_num += runtime->periods;
|
||||
|
||||
rpmsg->send_msg.param.buffer_tail = buffer_tail;
|
||||
|
||||
spin_lock_irqsave(&i2s_info->lock[substream->stream], flags);
|
||||
memcpy(&i2s_info->period_done_msg[substream->stream], rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
|
||||
i2s_info->period_done_msg_enabled[substream->stream] = true;
|
||||
spin_unlock_irqrestore(&i2s_info->lock[substream->stream], flags);
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
avail = snd_pcm_playback_hw_avail(runtime);
|
||||
@ -564,7 +595,9 @@ int imx_rpmsg_pcm_ack(struct snd_pcm_substream *substream)
|
||||
avail = snd_pcm_capture_hw_avail(runtime);
|
||||
|
||||
if ((avail - writen_num * runtime->period_size) <= runtime->period_size) {
|
||||
spin_lock_irqsave(&i2s_info->wq_lock, flags);
|
||||
if (i2s_info->work_write_index != i2s_info->work_read_index) {
|
||||
int index = i2s_info->work_write_index;
|
||||
memcpy(&i2s_info->work_list[index].msg, rpmsg,
|
||||
sizeof(struct i2s_rpmsg_s));
|
||||
queue_work(i2s_info->rpmsg_wq,
|
||||
@ -573,6 +606,7 @@ int imx_rpmsg_pcm_ack(struct snd_pcm_substream *substream)
|
||||
i2s_info->work_write_index %= WORK_MAX_NUM;
|
||||
} else
|
||||
i2s_info->msg_drop_count[substream->stream]++;
|
||||
spin_unlock_irqrestore(&i2s_info->wq_lock, flags);
|
||||
} else {
|
||||
if (rpmsg_i2s->force_lpa && !timer_pending(&i2s_info->stream_timer[substream->stream].timer)) {
|
||||
int time_msec;
|
||||
|
||||
Reference in New Issue
Block a user