summaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2019-02-04 14:00:50 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2019-02-06 08:31:13 +0100
commitd60e9aa5f5a21374950dfd15bedafeccf76c3b1d (patch)
treee50c6df4a5f508ecfcd8fe727b5c23a397ec4189 /drivers/misc
parent1455e221ae3023270a4716be6b47c038249955fd (diff)
downloadbarebox-d60e9aa5f5a21374950dfd15bedafeccf76c3b1d.tar.gz
barebox-d60e9aa5f5a21374950dfd15bedafeccf76c3b1d.tar.xz
misc: fix /dev/mem size
The size of /dev/mem was limited to the lower half of the 64bit address range. This is unfortunate since on some architectures (MIPS64, namely) the upper half contains meaningful addresses. We can't just set /dev/mem to its real size since that's bigger than the maximum loff_t. Set the DEVFS_IS_CHARACTER_DEV flag instead for /dev/mem which will cause the size checks in lseek and friends to be bypassed. Also fix the size the memory device is registered with. We used to set the size to ~0, but the real size is one higher. To do this explicitly register the device with specifying the end address rather than the size. This will make /dev/mem appear with filesize 0, but so does /dev/zero already. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mem.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/drivers/misc/mem.c b/drivers/misc/mem.c
index 60981a3e98..6dd7f687c9 100644
--- a/drivers/misc/mem.c
+++ b/drivers/misc/mem.c
@@ -21,8 +21,18 @@ static int mem_probe(struct device_d *dev)
dev->priv = cdev;
cdev->name = (char*)dev->resource[0].name;
- cdev->size = min_t(unsigned long long, resource_size(&dev->resource[0]),
- S64_MAX);
+ if (dev->resource[0].start == 0 && dev->resource[0].end == ~0) {
+ /*
+ * Special case for /dev/mem. We can't express it's size as it's
+ * outside of our address range. Set DEVFS_IS_CHARACTER_DEV to
+ * bypass size checks.
+ */
+ cdev->size = 0;
+ cdev->flags = DEVFS_IS_CHARACTER_DEV;
+ } else {
+ cdev->size = resource_size(&dev->resource[0]);
+ }
+
cdev->ops = &memops;
cdev->dev = dev;
@@ -38,7 +48,26 @@ static struct driver_d mem_drv = {
static int mem_init(void)
{
- add_mem_device("mem", 0, ~0, IORESOURCE_MEM_WRITEABLE);
+ struct device_d *dev;
+ struct resource res = {
+ .start = 0,
+ .end = ~0,
+ .flags = IORESOURCE_MEM,
+ .name = "mem",
+ };
+ int ret;
+
+ dev = device_alloc("mem", DEVICE_ID_DYNAMIC);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->resource = xmemdup(&res, sizeof(res));
+ dev->num_resources = 1;
+
+ ret = platform_device_register(dev);
+ if (ret)
+ return ret;
+
return platform_driver_register(&mem_drv);
}
device_initcall(mem_init);