[PATCH 11/15] platform: goldfish: pipe: Split the driver to v2 specific and the rest
From: Roman Kiryanov Move probe/remove and other driver stuff to a separate file to plug v1 there later. Signed-off-by: Roman Kiryanov --- drivers/platform/goldfish/Makefile | 3 +- drivers/platform/goldfish/goldfish_pipe.c| 124 +++ drivers/platform/goldfish/goldfish_pipe.h| 10 ++ drivers/platform/goldfish/goldfish_pipe_v2.c | 112 +++-- drivers/platform/goldfish/goldfish_pipe_v2.h | 10 ++ 5 files changed, 161 insertions(+), 98 deletions(-) create mode 100644 drivers/platform/goldfish/goldfish_pipe.c create mode 100644 drivers/platform/goldfish/goldfish_pipe.h create mode 100644 drivers/platform/goldfish/goldfish_pipe_v2.h diff --git a/drivers/platform/goldfish/Makefile b/drivers/platform/goldfish/Makefile index 81f899a987a2..016769e003d8 100644 --- a/drivers/platform/goldfish/Makefile +++ b/drivers/platform/goldfish/Makefile @@ -1,4 +1,5 @@ # # Makefile for Goldfish platform specific drivers # -obj-$(CONFIG_GOLDFISH_PIPE)+= goldfish_pipe_v2.o +obj-$(CONFIG_GOLDFISH_PIPE)+= goldfish_pipe_all.o +goldfish_pipe_all-objs := goldfish_pipe.o goldfish_pipe_v2.o diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c new file mode 100644 index ..792b20bdf76c --- /dev/null +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* This source file contains the implementation of a special device driver + * that intends to provide a *very* fast communication channel between the + * guest system and the QEMU emulator. + * + * Usage from the guest is simply the following (error handling simplified): + * + *int fd = open("/dev/qemu_pipe",O_RDWR); + * write() or read() through the pipe. + * + * This driver doesn't deal with the exact protocol used during the session. + * It is intended to be as simple as something like: + * + *// do this _just_ after opening the fd to connect to a specific + *// emulator service. + *const char* msg = ""; + *if (write(fd, msg, strlen(msg)+1) < 0) { + * ... could not connect to service + * close(fd); + *} + * + *// after this, simply read() and write() to communicate with the + *// service. Exact protocol details left as an exercise to the reader. + * + * This driver is very fast because it doesn't copy any data through + * intermediate buffers, since the emulator is capable of translating + * guest user addresses into host ones. + * + * Note that we must however ensure that each user page involved in the + * exchange is properly mapped during a transfer. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "goldfish_pipe_qemu.h" +#include "goldfish_pipe.h" +#include "goldfish_pipe_v2.h" + +/* + * Update this when something changes in the driver's behavior so the host + * can benefit from knowing it + */ +enum { + PIPE_DRIVER_VERSION = 2, + PIPE_CURRENT_DEVICE_VERSION = 2 +}; + +static int goldfish_pipe_probe(struct platform_device *pdev) +{ + struct resource *r; + char __iomem *base; + int irq; + int version; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r || resource_size(r) < PAGE_SIZE) { + dev_err(>dev, "can't allocate i/o page\n"); + return -EINVAL; + } + base = devm_ioremap(>dev, r->start, PAGE_SIZE); + if (!base) { + dev_err(>dev, "ioremap failed\n"); + return -EINVAL; + } + + r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!r) + return -EINVAL; + + irq = r->start; + + /* +* Exchange the versions with the host device +* +* Note: v1 driver used to not report its version, so we write it before +* reading device version back: this allows the host implementation to +* detect the old driver (if there was no version write before read). +*/ + writel(PIPE_DRIVER_VERSION, base + PIPE_REG_VERSION); + version = readl(base + PIPE_REG_VERSION); + + if (WARN_ON(version < PIPE_CURRENT_DEVICE_VERSION)) + return -EINVAL; + + return goldfish_pipe_device_init(pdev, base, irq); +} + +static int goldfish_pipe_remove(struct platform_device *pdev) +{ + struct goldfish_pipe_dev_base *dev = platform_get_drvdata(pdev); + + return dev->deinit(dev, pdev); +} + +static const struct acpi_device_id goldfish_pipe_acpi_match[] = { + { "GFSH0003", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); + +static const struct of_device_id goldfish_pipe_of_match[] = { + { .compatible = "google,android-pipe", }, + {}, +}; +MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); + +static struct platform_driver goldfish_pipe_driver = { + .probe = goldfish_pipe_probe, + .remove = goldfish_pipe_remove, + .driver = {
[PATCH 11/15] platform: goldfish: pipe: Split the driver to v2 specific and the rest
From: Roman Kiryanov Move probe/remove and other driver stuff to a separate file to plug v1 there later. Signed-off-by: Roman Kiryanov --- drivers/platform/goldfish/Makefile | 3 +- drivers/platform/goldfish/goldfish_pipe.c| 124 +++ drivers/platform/goldfish/goldfish_pipe.h| 10 ++ drivers/platform/goldfish/goldfish_pipe_v2.c | 112 +++-- drivers/platform/goldfish/goldfish_pipe_v2.h | 10 ++ 5 files changed, 161 insertions(+), 98 deletions(-) create mode 100644 drivers/platform/goldfish/goldfish_pipe.c create mode 100644 drivers/platform/goldfish/goldfish_pipe.h create mode 100644 drivers/platform/goldfish/goldfish_pipe_v2.h diff --git a/drivers/platform/goldfish/Makefile b/drivers/platform/goldfish/Makefile index 81f899a987a2..016769e003d8 100644 --- a/drivers/platform/goldfish/Makefile +++ b/drivers/platform/goldfish/Makefile @@ -1,4 +1,5 @@ # # Makefile for Goldfish platform specific drivers # -obj-$(CONFIG_GOLDFISH_PIPE)+= goldfish_pipe_v2.o +obj-$(CONFIG_GOLDFISH_PIPE)+= goldfish_pipe_all.o +goldfish_pipe_all-objs := goldfish_pipe.o goldfish_pipe_v2.o diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c new file mode 100644 index ..792b20bdf76c --- /dev/null +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* This source file contains the implementation of a special device driver + * that intends to provide a *very* fast communication channel between the + * guest system and the QEMU emulator. + * + * Usage from the guest is simply the following (error handling simplified): + * + *int fd = open("/dev/qemu_pipe",O_RDWR); + * write() or read() through the pipe. + * + * This driver doesn't deal with the exact protocol used during the session. + * It is intended to be as simple as something like: + * + *// do this _just_ after opening the fd to connect to a specific + *// emulator service. + *const char* msg = ""; + *if (write(fd, msg, strlen(msg)+1) < 0) { + * ... could not connect to service + * close(fd); + *} + * + *// after this, simply read() and write() to communicate with the + *// service. Exact protocol details left as an exercise to the reader. + * + * This driver is very fast because it doesn't copy any data through + * intermediate buffers, since the emulator is capable of translating + * guest user addresses into host ones. + * + * Note that we must however ensure that each user page involved in the + * exchange is properly mapped during a transfer. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "goldfish_pipe_qemu.h" +#include "goldfish_pipe.h" +#include "goldfish_pipe_v2.h" + +/* + * Update this when something changes in the driver's behavior so the host + * can benefit from knowing it + */ +enum { + PIPE_DRIVER_VERSION = 2, + PIPE_CURRENT_DEVICE_VERSION = 2 +}; + +static int goldfish_pipe_probe(struct platform_device *pdev) +{ + struct resource *r; + char __iomem *base; + int irq; + int version; + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r || resource_size(r) < PAGE_SIZE) { + dev_err(>dev, "can't allocate i/o page\n"); + return -EINVAL; + } + base = devm_ioremap(>dev, r->start, PAGE_SIZE); + if (!base) { + dev_err(>dev, "ioremap failed\n"); + return -EINVAL; + } + + r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!r) + return -EINVAL; + + irq = r->start; + + /* +* Exchange the versions with the host device +* +* Note: v1 driver used to not report its version, so we write it before +* reading device version back: this allows the host implementation to +* detect the old driver (if there was no version write before read). +*/ + writel(PIPE_DRIVER_VERSION, base + PIPE_REG_VERSION); + version = readl(base + PIPE_REG_VERSION); + + if (WARN_ON(version < PIPE_CURRENT_DEVICE_VERSION)) + return -EINVAL; + + return goldfish_pipe_device_init(pdev, base, irq); +} + +static int goldfish_pipe_remove(struct platform_device *pdev) +{ + struct goldfish_pipe_dev_base *dev = platform_get_drvdata(pdev); + + return dev->deinit(dev, pdev); +} + +static const struct acpi_device_id goldfish_pipe_acpi_match[] = { + { "GFSH0003", 0 }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); + +static const struct of_device_id goldfish_pipe_of_match[] = { + { .compatible = "google,android-pipe", }, + {}, +}; +MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); + +static struct platform_driver goldfish_pipe_driver = { + .probe = goldfish_pipe_probe, + .remove = goldfish_pipe_remove, + .driver = {