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


Reply via email to