summaryrefslogtreecommitdiff
path: root/asoc
diff options
context:
space:
mode:
authorShashi Kant Maurya <smaury@codeaurora.org>2020-11-19 17:33:42 +0530
committerGerrit - the friendly Code Review server <code-review@localhost>2020-12-10 06:11:45 -0800
commit8b699bc1775f1df3eeed557c6aaf5fa2d647d6f6 (patch)
tree2f4bda58aa7379ba16abb8ee8e70248f68cf793e /asoc
parent8e3d6a8632f6eac48eacebb6939a3063ba0c2946 (diff)
downloadmsm-extra-8b699bc1775f1df3eeed557c6aaf5fa2d647d6f6.tar.gz
asoc: wsa881x: Fix crash while capturing swr_slv codec dump
Swr-slv address is overwritten during wsa881x_swr_probe, hence soundwire getting incorrect slave address. While accessing swr master from swr slave due to incorrect address device crashed To avoid the issue align the debugfs similar to wsa883x codec. Change-Id: Ic8aaa0728a43936cd4c6e1ed590e01ba8f0fbf5b Signed-off-by: Shashi Kant Maurya <smaury@codeaurora.org>
Diffstat (limited to 'asoc')
-rw-r--r--asoc/codecs/wsa881x.c227
1 files changed, 140 insertions, 87 deletions
diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c
index b23bc01f..52f29d88 100644
--- a/asoc/codecs/wsa881x.c
+++ b/asoc/codecs/wsa881x.c
@@ -109,6 +109,11 @@ struct wsa881x_priv {
int (*register_notifier)(void *handle,
struct notifier_block *nblock,
bool enable);
+ struct dentry *debugfs_dent;
+ struct dentry *debugfs_peek;
+ struct dentry *debugfs_poke;
+ struct dentry *debugfs_reg_dump;
+ unsigned int read_data;
};
/* from bolero to WSA events */
@@ -146,14 +151,6 @@ static int wsa881x_ocp_poll_timer_sec = WSA881X_OCP_CTL_POLL_TIMER_SEC;
module_param(wsa881x_ocp_poll_timer_sec, int, 0664);
MODULE_PARM_DESC(wsa881x_ocp_poll_timer_sec, "timer for ocp ctl polling");
-static struct wsa881x_priv *dbgwsa881x;
-static struct dentry *debugfs_wsa881x_dent;
-static struct dentry *debugfs_peek;
-static struct dentry *debugfs_poke;
-static struct dentry *debugfs_reg_dump;
-static unsigned int read_data;
-static unsigned int devnum;
-
static int32_t wsa881x_resource_acquire(struct snd_soc_component *component,
bool enable);
@@ -401,30 +398,28 @@ static bool is_swr_slv_reg_readable(int reg)
return ret;
}
-static ssize_t wsa881x_swrslave_reg_show(char __user *ubuf, size_t count,
- loff_t *ppos)
+static ssize_t wsa881x_swrslave_reg_show(struct swr_device *pdev, char __user *ubuf,
+ size_t count, loff_t *ppos)
{
int i, reg_val, len;
ssize_t total = 0;
char tmp_buf[SWR_SLV_MAX_BUF_LEN];
- if (!ubuf || !ppos || (devnum == 0))
+ if (!ubuf || !ppos)
return 0;
for (i = (((int) *ppos / BYTES_PER_LINE) + SWR_SLV_START_REG_ADDR);
- i <= SWR_SLV_MAX_REG_ADDR; i++) {
+ i <= SWR_SLV_MAX_REG_ADDR; i++) {
if (!is_swr_slv_reg_readable(i))
continue;
- swr_read(dbgwsa881x->swr_slave, devnum,
- i, &reg_val, 1);
- len = snprintf(tmp_buf, 25, "0x%.3x: 0x%.2x\n", i,
- (reg_val & 0xFF));
+ swr_read(pdev, pdev->dev_num, i, &reg_val, 1);
+ len = snprintf(tmp_buf, sizeof(tmp_buf), "0x%.3x: 0x%.2x\n", i,
+ (reg_val & 0xFF));
if (len < 0) {
pr_err("%s: fail to fill the buffer\n", __func__);
total = -EFAULT;
goto copy_err;
}
-
if ((total + len) >= count - 1)
break;
if (copy_to_user((ubuf + total), tmp_buf, len)) {
@@ -432,53 +427,84 @@ static ssize_t wsa881x_swrslave_reg_show(char __user *ubuf, size_t count,
total = -EFAULT;
goto copy_err;
}
- *ppos += len;
total += len;
+ *ppos += len;
}
copy_err:
+ *ppos = SWR_SLV_MAX_REG_ADDR * BYTES_PER_LINE;
return total;
}
+static ssize_t codec_debug_dump(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct swr_device *pdev;
+
+ if (!count || !file || !ppos || !ubuf)
+ return -EINVAL;
+
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
+
+ if (*ppos < 0)
+ return -EINVAL;
+
+ return wsa881x_swrslave_reg_show(pdev, ubuf, count, ppos);
+}
+
static ssize_t codec_debug_read(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
char lbuf[SWR_SLV_RD_BUF_LEN];
- char *access_str;
- ssize_t ret_cnt;
+ struct swr_device *pdev = NULL;
+ struct wsa881x_priv *wsa881x = NULL;
if (!count || !file || !ppos || !ubuf)
return -EINVAL;
- access_str = file->private_data;
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
+
+ wsa881x = swr_get_dev_data(pdev);
+ if (!wsa881x)
+ return -EINVAL;
+
if (*ppos < 0)
return -EINVAL;
- if (!strcmp(access_str, "swrslave_peek")) {
- snprintf(lbuf, sizeof(lbuf), "0x%x\n", (read_data & 0xFF));
- ret_cnt = simple_read_from_buffer(ubuf, count, ppos, lbuf,
- strnlen(lbuf, 7));
- } else if (!strcmp(access_str, "swrslave_reg_dump")) {
- ret_cnt = wsa881x_swrslave_reg_show(ubuf, count, ppos);
- } else {
- pr_err("%s: %s not permitted to read\n", __func__, access_str);
- ret_cnt = -EPERM;
- }
- return ret_cnt;
+ snprintf(lbuf, sizeof(lbuf), "0x%x\n",
+ (wsa881x->read_data & 0xFF));
+
+ return simple_read_from_buffer(ubuf, count, ppos, lbuf,
+ strnlen(lbuf, 7));
}
-static ssize_t codec_debug_write(struct file *filp,
- const char __user *ubuf, size_t cnt, loff_t *ppos)
+static ssize_t codec_debug_peek_write(struct file *file,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
{
char lbuf[SWR_SLV_WR_BUF_LEN];
- int rc;
+ int rc = 0;
u32 param[5];
- char *access_str;
+ struct swr_device *pdev = NULL;
+ struct wsa881x_priv *wsa881x = NULL;
+
+ if (!cnt || !file || !ppos || !ubuf)
+ return -EINVAL;
+
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
- if (!filp || !ppos || !ubuf)
+ wsa881x = swr_get_dev_data(pdev);
+ if (!wsa881x)
+ return -EINVAL;
+
+ if (*ppos < 0)
return -EINVAL;
- access_str = filp->private_data;
if (cnt > sizeof(lbuf) - 1)
return -EINVAL;
@@ -487,32 +513,46 @@ static ssize_t codec_debug_write(struct file *filp,
return -EFAULT;
lbuf[cnt] = '\0';
- if (!strcmp(access_str, "swrslave_poke")) {
- /* write */
- rc = get_parameters(lbuf, param, 3);
- if ((param[0] <= SWR_SLV_MAX_REG_ADDR) && (param[1] <= 0xFF) &&
- (rc == 0))
- swr_write(dbgwsa881x->swr_slave, param[2],
- param[0], &param[1]);
- else
- rc = -EINVAL;
- } else if (!strcmp(access_str, "swrslave_peek")) {
- /* read */
- rc = get_parameters(lbuf, param, 2);
- if ((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0))
- swr_read(dbgwsa881x->swr_slave, param[1],
- param[0], &read_data, 1);
- else
- rc = -EINVAL;
- } else if (!strcmp(access_str, "swrslave_reg_dump")) {
- /* reg dump */
- rc = get_parameters(lbuf, param, 1);
- if ((rc == 0) && (param[0] > 0) &&
- (param[0] <= SWR_SLV_MAX_DEVICES))
- devnum = param[0];
- else
- rc = -EINVAL;
- }
+ rc = get_parameters(lbuf, param, 1);
+ if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) && (rc == 0)))
+ return -EINVAL;
+ swr_read(pdev, pdev->dev_num, param[0], &wsa881x->read_data, 1);
+ if (rc == 0)
+ rc = cnt;
+ else
+ pr_err("%s: rc = %d\n", __func__, rc);
+
+ return rc;
+}
+
+static ssize_t codec_debug_write(struct file *file,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ char lbuf[SWR_SLV_WR_BUF_LEN];
+ int rc = 0;
+ u32 param[5];
+ struct swr_device *pdev;
+
+ if (!file || !ppos || !ubuf)
+ return -EINVAL;
+
+ pdev = file->private_data;
+ if (!pdev)
+ return -EINVAL;
+
+ if (cnt > sizeof(lbuf) - 1)
+ return -EINVAL;
+
+ rc = copy_from_user(lbuf, ubuf, cnt);
+ if (rc)
+ return -EFAULT;
+
+ lbuf[cnt] = '\0';
+ rc = get_parameters(lbuf, param, 2);
+ if (!((param[0] <= SWR_SLV_MAX_REG_ADDR) &&
+ (param[1] <= 0xFF) && (rc == 0)))
+ return -EINVAL;
+ swr_write(pdev, pdev->dev_num, param[0], &param[1]);
if (rc == 0)
rc = cnt;
else
@@ -521,12 +561,21 @@ static ssize_t codec_debug_write(struct file *filp,
return rc;
}
-static const struct file_operations codec_debug_ops = {
+static const struct file_operations codec_debug_write_ops = {
.open = codec_debug_open,
.write = codec_debug_write,
+};
+
+static const struct file_operations codec_debug_read_ops = {
+ .open = codec_debug_open,
.read = codec_debug_read,
+ .write = codec_debug_peek_write,
};
+static const struct file_operations codec_debug_dump_ops = {
+ .open = codec_debug_open,
+ .read = codec_debug_dump,
+};
static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x)
{
mutex_lock(&wsa881x->res_lock);
@@ -1454,27 +1503,31 @@ static int wsa881x_swr_probe(struct swr_device *pdev)
wsa881x_gpio_ctrl(wsa881x, true);
wsa881x->state = WSA881X_DEV_UP;
- if (!debugfs_wsa881x_dent) {
- dbgwsa881x = wsa881x;
- debugfs_wsa881x_dent = debugfs_create_dir(
- "wsa881x_swr_slave", 0);
- if (!IS_ERR(debugfs_wsa881x_dent)) {
- debugfs_peek = debugfs_create_file("swrslave_peek",
- S_IFREG | 0444, debugfs_wsa881x_dent,
- (void *) "swrslave_peek",
- &codec_debug_ops);
-
- debugfs_poke = debugfs_create_file("swrslave_poke",
- S_IFREG | 0444, debugfs_wsa881x_dent,
- (void *) "swrslave_poke",
- &codec_debug_ops);
-
- debugfs_reg_dump = debugfs_create_file(
+ if (!wsa881x->debugfs_dent) {
+ wsa881x->debugfs_dent = debugfs_create_dir(
+ dev_name(&pdev->dev), 0);
+ if (!IS_ERR(wsa881x->debugfs_dent)) {
+ wsa881x->debugfs_peek =
+ debugfs_create_file("swrslave_peek",
+ S_IFREG | 0444,
+ wsa881x->debugfs_dent,
+ (void *) pdev,
+ &codec_debug_read_ops);
+
+ wsa881x->debugfs_poke =
+ debugfs_create_file("swrslave_poke",
+ S_IFREG | 0444,
+ wsa881x->debugfs_dent,
+ (void *) pdev,
+ &codec_debug_write_ops);
+
+ wsa881x->debugfs_reg_dump =
+ debugfs_create_file(
"swrslave_reg_dump",
S_IFREG | 0444,
- debugfs_wsa881x_dent,
- (void *) "swrslave_reg_dump",
- &codec_debug_ops);
+ wsa881x->debugfs_dent,
+ (void *) pdev,
+ &codec_debug_dump_ops);
}
}
@@ -1566,8 +1619,8 @@ static int wsa881x_swr_remove(struct swr_device *pdev)
if (wsa881x->register_notifier)
wsa881x->register_notifier(wsa881x->handle,
&wsa881x->bolero_nblock, false);
- debugfs_remove_recursive(debugfs_wsa881x_dent);
- debugfs_wsa881x_dent = NULL;
+ debugfs_remove_recursive(wsa881x->debugfs_dent);
+ wsa881x->debugfs_dent = NULL;
mutex_destroy(&wsa881x->res_lock);
mutex_destroy(&wsa881x->temp_lock);
snd_soc_unregister_component(&pdev->dev);