[PATCH linux dev-4.7] aspeed: fix the debugfs write operation
Cédric Le Goater
clg at kaod.org
Fri Oct 21 00:54:20 AEDT 2016
It was incompatible with the seq_file used in the read so the read
operation was changed also. Now you can write to the debug file with:
# echo 0x1E630004=0x3DBB2081 > /sys/kernel/debug/aspeed/1e630000.spi
# cat /sys/kernel/debug/aspeed/1e630000.spi
0x1E630000: 0x00000002
0x1E630004: 0x3DBB2081
0x1E630008: 0x00000000
0x1E63000C: 0x00000000
0x1E630010: 0x00000000
0x1E630014: 0x00000000
Some basic checks are done to not ruin the kernel but anyhow, this is
not for upstream. It is just a useful devmem replacement.
Signed-off-by: Cédric Le Goater <clg at kaod.org>
---
arch/arm/mach-aspeed/debugfs.c | 69 +++++++++++++++++++++++++++--------------
1 file changed, 47 insertions(+), 22 deletions(-)
Index: linux-openbmc-4.7.git/arch/arm/mach-aspeed/debugfs.c
===================================================================
--- linux-openbmc-4.7.git.orig/arch/arm/mach-aspeed/debugfs.c
+++ linux-openbmc-4.7.git/arch/arm/mach-aspeed/debugfs.c
@@ -23,21 +23,36 @@
#define AST_IO(__pa) ((void __iomem *)(((__pa) & 0x001fffff) | AST_IO_VA))
struct aspeed_controller {
+ struct device *dev;
const char *name;
unsigned int base;
unsigned int nregs;
};
-static int aspeed_show(struct seq_file *s, void *unused)
+static ssize_t aspeed_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct aspeed_controller *ctrl = s->private;
+ struct aspeed_controller *ctrl = filp->private_data;
+ char *kbuf;
+ int ret, n = 0;
+ size_t size;
int i;
- for (i = 0; i < ctrl->nregs; i += 4)
- seq_printf(s, "0x%08X: 0x%08X\n", ctrl->base | i,
- readl(AST_IO(ctrl->base | i)));
+ size = ctrl->nregs * 23 + 1;
+ kbuf = kzalloc(size, GFP_KERNEL);
+ if (!kbuf)
+ return -ENOMEM;
+
+ for (i = 0; i < ctrl->nregs; i += 4) {
+ n += scnprintf(kbuf + n, size - n, "0x%08X: 0x%08X\n",
+ ctrl->base | i, readl(AST_IO(ctrl->base | i)));
+ }
+
+ ret = simple_read_from_buffer(ubuf, count, ppos, kbuf, n);
- return 0;
+ kfree(kbuf);
+
+ return ret;
}
static ssize_t aspeed_write(struct file *filp, const char __user *ubuf,
@@ -45,35 +60,44 @@ static ssize_t aspeed_write(struct file
{
struct aspeed_controller *ctrl = filp->private_data;
unsigned int reg, val;
- char buf[50];
+ char *kbuf = kmalloc(count + 1, GFP_KERNEL);
int ret;
- ret = simple_write_to_buffer(buf, sizeof(buf), ppos, ubuf, count);
- if (!ret)
- return -EFAULT;
+ if (!kbuf)
+ return -ENOMEM;
+
+ ret = simple_write_to_buffer(kbuf, count, ppos, ubuf, count);
+ if (ret != count) {
+ kfree(kbuf);
+ return ret >= 0 ? -EIO : ret;
+ }
+ kbuf[count] = '\0';
+
+ ret = sscanf(kbuf, "%x=%x", ®, &val);
+ kfree(kbuf);
- ret = sscanf(buf, "%x=%x", ®, &val);
if (ret != 2)
return -EINVAL;
- if (reg >= ctrl->nregs)
+ if ((ctrl->base & reg) != ctrl->base) {
+ dev_err(ctrl->dev, "wrong base address: %x\n", reg);
return -EINVAL;
+ }
- writel(val, AST_IO(ctrl->base | reg));
- return count;
-}
+ if ((~ctrl->base & reg) >= ctrl->nregs) {
+ dev_err(ctrl->dev, "wrong register: %x\n", reg);
+ return -EINVAL;
+ }
-static int aspeed_open(struct inode *inode, struct file *file)
-{
- return single_open(file, aspeed_show, inode->i_private);
+ writel(val, AST_IO(reg));
+ return count;
}
static const struct file_operations aspeed_fops = {
- .open = aspeed_open,
- .read = seq_read,
+ .open = simple_open,
+ .read = aspeed_read,
.write = aspeed_write,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = generic_file_llseek,
};
static struct dentry *aspeed_debugfs_root;
@@ -95,6 +119,7 @@ static int aspeed_device_show(struct dev
if (!ctrl)
return -ENOMEM;
+ ctrl->dev = dev;
ctrl->name = pdev->name;
ctrl->base = r->start;
ctrl->nregs = resource_size(r);
More information about the openbmc
mailing list