ASoC: msm: qdsp6v2: make audio debugfs read and release exclusive
A thread can read audio debugfs entry while another closes the device. Protect these operations with a mutex and before read check audio data for a valid pointer. Change-Id: If29a308c1a8329d7befd047d41abe5f6ab626199 Signed-off-by: Divya Ojha <dojha@codeaurora.org>
This commit is contained in:
parent
bf1349b227
commit
b9faf02678
|
@ -27,11 +27,14 @@
|
|||
#include <linux/msm_audio_ion.h>
|
||||
#include <linux/compat.h>
|
||||
#include <sound/q6core.h>
|
||||
#include <linux/mutex.h>
|
||||
#include "audio_utils_aio.h"
|
||||
#ifdef CONFIG_USE_DEV_CTRL_VOLUME
|
||||
#include <linux/qdsp6v2/audio_dev_ctl.h>
|
||||
#endif /*CONFIG_USE_DEV_CTRL_VOLUME*/
|
||||
DEFINE_MUTEX(lock);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
|
||||
int audio_aio_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
|
@ -44,29 +47,37 @@ ssize_t audio_aio_debug_read(struct file *file, char __user *buf,
|
|||
const int debug_bufmax = 4096;
|
||||
static char buffer[4096];
|
||||
int n = 0;
|
||||
struct q6audio_aio *audio = file->private_data;
|
||||
struct q6audio_aio *audio;
|
||||
|
||||
mutex_lock(&audio->lock);
|
||||
n = scnprintf(buffer, debug_bufmax, "opened %d\n", audio->opened);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"enabled %d\n", audio->enabled);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"stopped %d\n", audio->stopped);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"feedback %d\n", audio->feedback);
|
||||
mutex_unlock(&audio->lock);
|
||||
/* Following variables are only useful for debugging when
|
||||
* when playback halts unexpectedly. Thus, no mutual exclusion
|
||||
* enforced
|
||||
*/
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"wflush %d\n", audio->wflush);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"rflush %d\n", audio->rflush);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"inqueue empty %d\n", list_empty(&audio->in_queue));
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"outqueue empty %d\n", list_empty(&audio->out_queue));
|
||||
mutex_lock(&lock);
|
||||
if (file->private_data != NULL) {
|
||||
audio = file->private_data;
|
||||
mutex_lock(&audio->lock);
|
||||
n = scnprintf(buffer, debug_bufmax, "opened %d\n",
|
||||
audio->opened);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"enabled %d\n", audio->enabled);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"stopped %d\n", audio->stopped);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"feedback %d\n", audio->feedback);
|
||||
mutex_unlock(&audio->lock);
|
||||
/* Following variables are only useful for debugging when
|
||||
* when playback halts unexpectedly. Thus, no mutual exclusion
|
||||
* enforced
|
||||
*/
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"wflush %d\n", audio->wflush);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"rflush %d\n", audio->rflush);
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"inqueue empty %d\n",
|
||||
list_empty(&audio->in_queue));
|
||||
n += scnprintf(buffer + n, debug_bufmax - n,
|
||||
"outqueue empty %d\n",
|
||||
list_empty(&audio->out_queue));
|
||||
}
|
||||
mutex_unlock(&lock);
|
||||
buffer[n] = 0;
|
||||
return simple_read_from_buffer(buf, count, ppos, buffer, n);
|
||||
}
|
||||
|
@ -574,6 +585,7 @@ int audio_aio_release(struct inode *inode, struct file *file)
|
|||
{
|
||||
struct q6audio_aio *audio = file->private_data;
|
||||
pr_debug("%s[%pK]\n", __func__, audio);
|
||||
mutex_lock(&lock);
|
||||
mutex_lock(&audio->lock);
|
||||
mutex_lock(&audio->read_lock);
|
||||
mutex_lock(&audio->write_lock);
|
||||
|
@ -617,6 +629,8 @@ int audio_aio_release(struct inode *inode, struct file *file)
|
|||
#endif
|
||||
kfree(audio->codec_cfg);
|
||||
kfree(audio);
|
||||
file->private_data = NULL;
|
||||
mutex_unlock(&lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue