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:
Divya Ojha 2017-04-27 22:52:40 +05:30
parent bf1349b227
commit b9faf02678
1 changed files with 36 additions and 22 deletions

View File

@ -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;
}