Browse Source

MLK-10048-3: ASoC: fsl_asrc: fix asrc crach when suspend/resume

merge 7e1a620a03

The reason of crach is that some variables are not protected in
function mxc_asrc_suspend(), when suspend, there is possibility to
access one NULL pointer.
Refine the spin lock usage, add protecting for pair_hold.

Signed-off-by: Shengjiu Wang <shengjiu.wang@freescale.com>
isee-imx_3.14.28.y
Shengjiu Wang 6 years ago
committed by Nitin Garg
parent
commit
d5bc5032b7
1 changed files with 26 additions and 10 deletions
  1. +26
    -10
      sound/soc/fsl/fsl_asrc_m2m.c

+ 26
- 10
sound/soc/fsl/fsl_asrc_m2m.c View File

@ -369,9 +369,10 @@ int fsl_asrc_process_buffer(struct fsl_asrc_pair *pair,
spin_unlock_irqrestore(&m2m->lock, lock_flags);
return -EFAULT;
}
fsl_asrc_read_last_FIFO(pair);
spin_unlock_irqrestore(&m2m->lock, lock_flags);
fsl_asrc_read_last_FIFO(pair);
/* Update final lengths after getting last FIFO */
pbuf->input_buffer_length = m2m->dma_block[IN].length;
pbuf->output_buffer_length = m2m->dma_block[OUT].length;
@ -485,6 +486,7 @@ static long fsl_asrc_ioctl_req_pair(struct fsl_asrc_pair *pair,
struct fsl_asrc_m2m *m2m = pair->private;
struct device *dev = &asrc_priv->pdev->dev;
struct asrc_req req;
unsigned long lock_flags;
long ret;
ret = copy_from_user(&req, user, sizeof(req));
@ -499,7 +501,9 @@ static long fsl_asrc_ioctl_req_pair(struct fsl_asrc_pair *pair,
return ret;
}
spin_lock_irqsave(&m2m->lock, lock_flags);
m2m->pair_hold = 1;
spin_unlock_irqrestore(&m2m->lock, lock_flags);
pair->channels = req.chn_num;
req.index = pair->index;
@ -571,9 +575,6 @@ static long fsl_asrc_ioctl_config_pair(struct fsl_asrc_pair *pair,
return -EBUSY;
}
init_completion(&m2m->complete[IN]);
init_completion(&m2m->complete[OUT]);
ret = copy_to_user(user, &config, sizeof(config));
if (ret) {
pair_err("failed to send config to user space: %ld\n", ret);
@ -824,6 +825,9 @@ static int fsl_asrc_open(struct inode *inode, struct file *file)
pair->private = m2m;
pair->asrc_priv = asrc_priv;
init_completion(&m2m->complete[IN]);
init_completion(&m2m->complete[OUT]);
spin_lock_init(&m2m->lock);
file->private_data = pair;
@ -846,9 +850,11 @@ static int fsl_asrc_close(struct inode *inode, struct file *file)
goto out;
/* Make sure we have clear the pointer */
spin_lock_irqsave(&asrc_priv->lock, lock_flags);
for (i = 0; i < ASRC_PAIR_MAX_NUM; i++)
if (asrc_priv->pair[i] == pair)
asrc_priv->pair[i] = NULL;
spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
if (m2m->asrc_active) {
m2m->asrc_active = 0;
@ -861,8 +867,8 @@ static int fsl_asrc_close(struct inode *inode, struct file *file)
fsl_asrc_output_dma_callback((void *)pair);
}
spin_lock_irqsave(&m2m->lock, lock_flags);
if (m2m->pair_hold) {
spin_lock_irqsave(&m2m->lock, lock_flags);
m2m->pair_hold = 0;
spin_unlock_irqrestore(&m2m->lock, lock_flags);
@ -875,10 +881,13 @@ static int fsl_asrc_close(struct inode *inode, struct file *file)
kfree(m2m->dma_block[OUT].dma_vaddr);
fsl_asrc_release_pair(pair);
}
} else
spin_unlock_irqrestore(&m2m->lock, lock_flags);
spin_lock_irqsave(&asrc_priv->lock, lock_flags);
kfree(m2m);
kfree(pair);
spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
file->private_data = NULL;
out:
@ -920,22 +929,29 @@ static void fsl_asrc_m2m_suspend(struct fsl_asrc *asrc_priv)
{
struct fsl_asrc_pair *pair;
struct fsl_asrc_m2m *m2m;
unsigned long lock_flags;
int i;
for (i = 0; i < ASRC_PAIR_MAX_NUM; i++) {
spin_lock_irqsave(&asrc_priv->lock, lock_flags);
pair = asrc_priv->pair[i];
if (!pair || !pair->private)
if (!pair || !pair->private) {
spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
continue;
}
m2m = pair->private;
if (!completion_done(&m2m->complete[IN])) {
dmaengine_terminate_all(pair->dma_chan[IN]);
if (pair->dma_chan[IN])
dmaengine_terminate_all(pair->dma_chan[IN]);
fsl_asrc_input_dma_callback((void *)pair);
}
if (!completion_done(&m2m->complete[OUT])) {
dmaengine_terminate_all(pair->dma_chan[OUT]);
if (pair->dma_chan[OUT])
dmaengine_terminate_all(pair->dma_chan[OUT]);
fsl_asrc_output_dma_callback((void *)pair);
}
spin_unlock_irqrestore(&asrc_priv->lock, lock_flags);
}
}

Loading…
Cancel
Save