From: Ahmad Fatoum <ah...@a3f.at> The new qemu_fw_cfg file system can simplify the ramfb driver a great deal as it's then no longer necessary to enumerate the files in the driver.
Signed-off-by: Ahmad Fatoum <ah...@a3f.at> --- drivers/video/Kconfig | 2 +- drivers/video/ramfb.c | 98 +++++++------------------------------------ fs/qemu_fw_cfg.c | 36 ++++++++++++++++ 3 files changed, 52 insertions(+), 84 deletions(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ef19948219f3..86f780ffc417 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -106,7 +106,7 @@ config DRIVER_VIDEO_SIMPLEFB config DRIVER_VIDEO_RAMFB bool "QEMU RamFB support" - select QEMU_FW_CFG + select FS_QEMU_FW_CFG help Add support for setting up a QEMU RamFB driver. diff --git a/drivers/video/ramfb.c b/drivers/video/ramfb.c index 5b03d8a9c821..cc490496175b 100644 --- a/drivers/video/ramfb.c +++ b/drivers/video/ramfb.c @@ -19,7 +19,6 @@ struct ramfb { struct fb_info info; dma_addr_t screen_dma; struct fb_videomode mode; - u16 etcfb_select; }; struct fw_cfg_etc_ramfb { @@ -31,37 +30,6 @@ struct fw_cfg_etc_ramfb { u32 stride; } __packed; -static int fw_cfg_find_file(struct device *dev, int fd, const char *filename) -{ - size_t filename_len = strlen(filename); - ssize_t ret; - __be32 count; - int i; - - ioctl(fd, FW_CFG_SELECT, &(u16) { FW_CFG_FILE_DIR }); - - lseek(fd, 0, SEEK_SET); - - ret = read(fd, &count, sizeof(count)); - if (ret < 0) - return ret; - - for (i = 0; i < be32_to_cpu(count); i++) { - struct fw_cfg_file qfile; - - read(fd, &qfile, sizeof(qfile)); - - dev_dbg(dev, "enumerating file %s\n", qfile.name); - - if (memcmp(qfile.name, filename, filename_len)) - continue; - - return be16_to_cpu(qfile.select); - } - - return -ENOENT; -} - static void ramfb_populate_modes(struct ramfb *ramfb) { struct fb_info *info = &ramfb->info; @@ -81,14 +49,15 @@ static void ramfb_populate_modes(struct ramfb *ramfb) static int ramfb_activate_var(struct fb_info *fbi) { struct ramfb *ramfb = fbi->priv; + struct device *hwdev = fbi->dev.parent->parent; if (fbi->screen_base) - dma_free_coherent(DMA_DEVICE_BROKEN, - fbi->screen_base, ramfb->screen_dma, fbi->screen_size); + dma_free_coherent(hwdev, fbi->screen_base, ramfb->screen_dma, + fbi->screen_size); fbi->screen_size = fbi->xres * fbi->yres * fbi->bits_per_pixel / BITS_PER_BYTE; - fbi->screen_base = dma_alloc_coherent(DMA_DEVICE_BROKEN, - fbi->screen_size, &ramfb->screen_dma); + fbi->screen_base = dma_alloc_coherent(hwdev, fbi->screen_size, + &ramfb->screen_dma); return 0; } @@ -107,8 +76,6 @@ static void ramfb_enable(struct fb_info *fbi) etc_ramfb->height = cpu_to_be32(fbi->yres); etc_ramfb->stride = cpu_to_be32(fbi->line_length); - ioctl(ramfb->fd, FW_CFG_SELECT, &ramfb->etcfb_select); - pwrite(ramfb->fd, etc_ramfb, sizeof(*etc_ramfb), 0); dma_free(etc_ramfb); @@ -119,74 +86,39 @@ static struct fb_ops ramfb_ops = { .fb_enable = ramfb_enable, }; -static int ramfb_probe(struct device *parent_dev, int fd) +static int ramfb_probe(struct device *dev) { int ret; struct ramfb *ramfb; struct fb_info *fbi; - ret = -ENODEV; - ramfb = xzalloc(sizeof(*ramfb)); - ramfb->fd = fd; - - ret = fw_cfg_find_file(parent_dev, fd, "etc/ramfb"); - if (ret < 0) { - dev_dbg(parent_dev, "ramfb: fw_cfg (etc/ramfb) file not found\n"); - return -ENODEV; - } - - ramfb->etcfb_select = ret; - dev_dbg(parent_dev, "etc/ramfb file at slot 0x%x\n", ramfb->etcfb_select); + ramfb->fd = (int)(uintptr_t)dev->platform_data; fbi = &ramfb->info; fbi->priv = ramfb; fbi->fbops = &ramfb_ops; - fbi->dev.parent = parent_dev; + fbi->dev.parent = dev; ramfb_populate_modes(ramfb); ret = register_framebuffer(fbi); if (ret < 0) { - dev_err(parent_dev, "Unable to register ramfb: %d\n", ret); + dev_err(dev, "Unable to register ramfb: %d\n", ret); return ret; } - dev_info(parent_dev, "ramfb registered\n"); + dev_info(dev, "ramfb registered\n"); return 0; } -static int ramfb_driver_init(void) -{ - struct cdev *cdev; - int err = 0; - - for_each_cdev(cdev) { - int fd, ret; - - if (!strstarts(cdev->name, "fw_cfg")) - continue; - - fd = cdev_fdopen(cdev, O_RDWR); - if (fd < 0) { - err = fd; - continue; - } - - ret = ramfb_probe(cdev->dev, fd); - if (ret == 0) - continue; - if (ret != -ENODEV && ret != -ENXIO) - err = ret; - - close(fd); - } - - return err; -} -device_initcall(ramfb_driver_init); +static struct driver ramfb_driver = { + .probe = ramfb_probe, + .name = "qemu-ramfb", +}; +device_platform_driver(ramfb_driver); MODULE_AUTHOR("Adrian Negreanu <adrian.negre...@nxp.com>"); MODULE_DESCRIPTION("QEMU RamFB driver"); diff --git a/fs/qemu_fw_cfg.c b/fs/qemu_fw_cfg.c index a21e6fbf637b..1aa44fb52c70 100644 --- a/fs/qemu_fw_cfg.c +++ b/fs/qemu_fw_cfg.c @@ -401,3 +401,39 @@ static int qemu_fw_cfg_fs_init(void) return register_fs_driver(&fw_cfg_fs_driver); } coredevice_initcall(qemu_fw_cfg_fs_init); + +static int qemu_fw_cfg_early_mount(void) +{ + struct cdev *cdev; + struct device *dev; + const char *mntpath; + int dirfd, fd; + + cdev = cdev_by_name("fw_cfg"); + if (!cdev) + return 0; + + /* + * Trigger a mount, so ramfb device can be detected and + * environment can be loaded + */ + mntpath = cdev_mount(cdev); + if (IS_ERR(mntpath)) + return PTR_ERR(mntpath); + + dirfd = open(mntpath, O_PATH | O_DIRECTORY); + if (dirfd < 0) + return dirfd; + + fd = openat(dirfd, "by_name/etc/ramfb", O_WRONLY); + close(dirfd); + if (fd >= 0) { + dev = device_alloc("qemu-ramfb", DEVICE_ID_SINGLE); + dev->parent = cdev->dev; + dev->platform_data = (void *)(uintptr_t)fd; + platform_device_register(dev); + } + + return 0; +} +late_initcall(qemu_fw_cfg_early_mount); -- 2.39.5