summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Kiryanov <rkir@google.com>2024-01-11 13:46:22 -0800
committerRoman Kiryanov <rkir@google.com>2024-01-19 12:10:13 -0800
commit1b0a7d01bb5935588db85a54b5d80c5eabbaedf5 (patch)
tree2eeeead293a03491ab7c77e6eb498de3652377de
parent7638ffeafee0adb892909545f95efad331b2fd11 (diff)
downloadvirtual-device-1b0a7d01bb5935588db85a54b5d80c5eabbaedf5.tar.gz
Retire DMA from goldfish_pipe
replaced by goldfish_address_space Bug: 319713048 Test: boot emulator with the updated kernel Change-Id: Ic075712c9481c2c9d27bf8e1ed32f404e64d9088 Signed-off-by: Roman Kiryanov <rkir@google.com>
-rw-r--r--goldfish_drivers/goldfish_pipe.c319
-rw-r--r--uapi/goldfish/goldfish_dma.h84
2 files changed, 16 insertions, 387 deletions
diff --git a/goldfish_drivers/goldfish_pipe.c b/goldfish_drivers/goldfish_pipe.c
index 4c6fb21..a9eaefc 100644
--- a/goldfish_drivers/goldfish_pipe.c
+++ b/goldfish_drivers/goldfish_pipe.c
@@ -53,7 +53,6 @@
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/bug.h>
-#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -68,8 +67,6 @@
#include <linux/sched.h>
#include <linux/slab.h>
-#include <goldfish/goldfish_dma.h>
-
static const char DEVICE_NAME[] = "goldfish_pipe_dprctd";
/*
@@ -77,8 +74,11 @@ static const char DEVICE_NAME[] = "goldfish_pipe_dprctd";
* can benefit from knowing it
* Notes:
* version 2 was an intermediate release and isn't supported anymore.
- * version 3 is goldfish_pipe v2 without DMA support.
- * version 4 (current) is goldfish_pipe v2 with DMA support.
+ * version 3 is goldfish_pipe_v2 without DMA support.
+ * version 4 (current) is goldfish_pipe_v2 with DMA support.
+ *
+ * goldfish_address_space replaces DMA in goldfish_pipe,
+ * DMA is retired in goldfish_pipe.
*/
enum {
PIPE_DRIVER_VERSION = 4,
@@ -89,8 +89,6 @@ enum {
MAX_BUFFERS_PER_COMMAND = 336,
MAX_SIGNALLED_PIPES = 64,
INITIAL_PIPES_CAPACITY = 64,
- DMA_REGION_MIN_SIZE = PAGE_SIZE,
- DMA_REGION_MAX_SIZE = 256 << 20
};
/* List of bitflags returned in status of CMD_POLL command */
@@ -116,10 +114,6 @@ enum PipeWakeFlags {
PIPE_WAKE_READ = 1 << 1,
/* pipe can now be written to */
PIPE_WAKE_WRITE = 1 << 2,
- /* unlock this pipe's DMA buffer */
- PIPE_WAKE_UNLOCK_DMA = 1 << 3,
- /* unlock DMA buffer of the pipe shared to this pipe */
- PIPE_WAKE_UNLOCK_DMA_SHARED = 1 << 4,
};
/* Bit flags for the 'flags' field */
@@ -181,14 +175,6 @@ enum PipeCmdCode {
PIPE_CMD_WAKE_ON_WRITE,
PIPE_CMD_READ,
PIPE_CMD_WAKE_ON_READ,
-
- /*
- * TODO(zyy): implement a deferred read/write execution to allow
- * parallel processing of pipe operations on the host.
- */
- PIPE_CMD_WAKE_ON_DONE_IO,
- PIPE_CMD_DMA_HOST_MAP,
- PIPE_CMD_DMA_HOST_UNMAP,
};
@@ -200,24 +186,17 @@ struct goldfish_pipe_command {
s32 id; /* pipe id, guest -> host */
s32 status; /* command execution status, host -> guest */
s32 reserved; /* to pad to 64-bit boundary */
- union {
- /* Parameters for PIPE_CMD_{READ,WRITE} */
- struct {
- /* number of buffers, guest -> host */
- u32 buffers_count;
- /* number of consumed bytes, host -> guest */
- s32 consumed_size;
- /* buffer pointers, guest -> host */
- u64 ptrs[MAX_BUFFERS_PER_COMMAND];
- /* buffer sizes, guest -> host */
- u32 sizes[MAX_BUFFERS_PER_COMMAND];
- } rw_params;
- /* Parameters for PIPE_CMD_DMA_HOST_(UN)MAP */
- struct {
- u64 dma_paddr;
- u64 sz;
- } dma_maphost_params;
- };
+ /* Parameters for PIPE_CMD_{READ,WRITE} */
+ struct {
+ /* number of buffers, guest -> host */
+ u32 buffers_count;
+ /* number of consumed bytes, host -> guest */
+ s32 consumed_size;
+ /* buffer pointers, guest -> host */
+ u64 ptrs[MAX_BUFFERS_PER_COMMAND];
+ /* buffer sizes, guest -> host */
+ u32 sizes[MAX_BUFFERS_PER_COMMAND];
+ } rw_params;
};
/* A single signalled pipe information */
@@ -239,24 +218,6 @@ struct goldfish_pipe_dev_buffers {
signalled_pipe_buffers[MAX_SIGNALLED_PIPES];
};
-/*
- * The main data structure tracking state is
- * struct goldfish_dma_context, which is included
- * as an extra pointer field in struct goldfish_pipe.
- * Each such context is associated with possibly
- * one physical address and size describing the
- * allocated DMA region, and only one allocation
- * is allowed for each pipe fd. Further allocations
- * require more open()'s of pipe fd's.
- */
-struct goldfish_dma_context {
- struct device *pdev_dev; /* pointer to feed to dma_*_coherent */
- void *dma_vaddr; /* kernel vaddr of dma region */
- size_t dma_size; /* size of dma region */
- dma_addr_t phys_begin; /* paddr of dma region */
- dma_addr_t phys_end; /* paddr of dma region + dma_size */
-};
-
/* This data type models a given pipe instance */
struct goldfish_pipe {
/* pipe ID - index into goldfish_pipe_dev::pipes array */
@@ -297,9 +258,6 @@ struct goldfish_pipe {
/* A buffer of pages, too large to fit into a stack frame */
struct page *pages[MAX_BUFFERS_PER_COMMAND];
-
- /* Holds information about reserved DMA region for this pipe */
- struct goldfish_dma_context *dma;
};
/* The global driver data. Holds a reference to the i/o page used to
@@ -346,9 +304,6 @@ struct goldfish_pipe_dev {
unsigned char __iomem *base;
struct miscdevice miscdev;
-
- /* DMA info */
- size_t dma_alloc_total;
};
static int goldfish_pipe_cmd_locked(struct goldfish_pipe *pipe,
@@ -874,7 +829,6 @@ static int goldfish_pipe_open(struct inode *inode, struct file *file)
spin_unlock_irqrestore(&dev->lock, flags);
if (status < 0)
goto err_cmd;
- pipe->dma = NULL;
/* All is done, save the pipe into the file's private data field */
file->private_data = pipe;
@@ -891,40 +845,6 @@ err_pipe:
return status;
}
-static void goldfish_pipe_dma_release_host(struct goldfish_pipe *pipe)
-{
- struct goldfish_dma_context *dma = pipe->dma;
- struct device *pdev_dev;
-
- if (!dma)
- return;
-
- pdev_dev = pipe->dev->pdev_dev;
-
- if (dma->dma_vaddr) {
- pipe->command_buffer->dma_maphost_params.dma_paddr =
- dma->phys_begin;
- pipe->command_buffer->dma_maphost_params.sz = dma->dma_size;
- goldfish_pipe_cmd(pipe, PIPE_CMD_DMA_HOST_UNMAP);
- }
-}
-
-static void goldfish_pipe_dma_release_guest(struct goldfish_pipe *pipe)
-{
- struct goldfish_dma_context *dma = pipe->dma;
-
- if (!dma)
- return;
-
- if (dma->dma_vaddr) {
- dma_free_coherent(dma->pdev_dev,
- dma->dma_size,
- dma->dma_vaddr,
- dma->phys_begin);
- pipe->dev->dma_alloc_total -= dma->dma_size;
- }
-}
-
static int goldfish_pipe_release(struct inode *inode, struct file *filp)
{
unsigned long flags;
@@ -932,7 +852,6 @@ static int goldfish_pipe_release(struct inode *inode, struct file *filp)
struct goldfish_pipe_dev *dev = pipe->dev;
/* The guest is closing the channel, so tell the emulator right now */
- goldfish_pipe_dma_release_host(pipe);
goldfish_pipe_cmd(pipe, PIPE_CMD_CLOSE);
spin_lock_irqsave(&dev->lock, flags);
@@ -942,14 +861,6 @@ static int goldfish_pipe_release(struct inode *inode, struct file *filp)
filp->private_data = NULL;
- /* Even if a fd is duped or involved in a forked process,
- * open/release methods are called only once, ever.
- * This makes goldfish_pipe_release a safe point
- * to delete the DMA region.
- */
- goldfish_pipe_dma_release_guest(pipe);
-
- kfree(pipe->dma);
free_page((unsigned long)pipe->command_buffer);
kfree(pipe);
@@ -987,200 +898,6 @@ static const struct vm_operations_struct goldfish_dma_vm_ops = {
.close = goldfish_dma_vma_close,
};
-static bool is_page_size_multiple(unsigned long sz)
-{
- return !(sz & (PAGE_SIZE - 1));
-}
-
-static bool check_region_size_valid(size_t size)
-{
- if (size < DMA_REGION_MIN_SIZE)
- return false;
-
- if (size > DMA_REGION_MAX_SIZE)
- return false;
-
- return is_page_size_multiple(size);
-}
-
-static int goldfish_pipe_dma_alloc_locked(struct goldfish_pipe *pipe)
-{
- struct goldfish_dma_context *dma = pipe->dma;
-
- if (dma->dma_vaddr)
- return 0;
-
- dma->phys_begin = 0;
- dma->dma_vaddr = dma_alloc_coherent(dma->pdev_dev,
- dma->dma_size,
- &dma->phys_begin,
- GFP_KERNEL);
- if (!dma->dma_vaddr)
- return -ENOMEM;
-
- dma->phys_end = dma->phys_begin + dma->dma_size;
- pipe->dev->dma_alloc_total += dma->dma_size;
- pipe->command_buffer->dma_maphost_params.dma_paddr = dma->phys_begin;
- pipe->command_buffer->dma_maphost_params.sz = dma->dma_size;
-
- goldfish_pipe_cmd_locked(pipe, PIPE_CMD_DMA_HOST_MAP);
- /* A workaround for b/110152998 */
- return 0;
-}
-
-static int goldfish_dma_mmap_locked(struct goldfish_pipe *pipe,
- struct vm_area_struct *vma)
-{
- struct goldfish_dma_context *dma = pipe->dma;
- struct device *pdev_dev = pipe->dev->pdev_dev;
- size_t sz_requested = vma->vm_end - vma->vm_start;
- int status;
-
- if (!check_region_size_valid(sz_requested)) {
- dev_err(pdev_dev, "%s: bad size (%zu) requested\n", __func__,
- sz_requested);
- return -EINVAL;
- }
-
- /* Alloc phys region if not allocated already. */
- status = goldfish_pipe_dma_alloc_locked(pipe);
- if (status)
- return status;
-
- status = remap_pfn_range(vma,
- vma->vm_start,
- dma->phys_begin >> PAGE_SHIFT,
- sz_requested,
- vma->vm_page_prot);
- if (status < 0) {
- dev_err(pdev_dev, "Cannot remap pfn range....\n");
- return -EAGAIN;
- }
- vma->vm_ops = &goldfish_dma_vm_ops;
- return 0;
-}
-
-/* When we call mmap() on a pipe fd, we obtain a pointer into
- * the physically contiguous DMA region of the pipe device
- * (Goldfish DMA).
- */
-static int goldfish_dma_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct goldfish_pipe *pipe =
- (struct goldfish_pipe *)(filp->private_data);
- int status;
-
- if (mutex_lock_interruptible(&pipe->lock))
- return -ERESTARTSYS;
-
- status = goldfish_dma_mmap_locked(pipe, vma);
- mutex_unlock(&pipe->lock);
- return status;
-}
-
-static int goldfish_pipe_dma_create_region(struct goldfish_pipe *pipe,
- size_t size)
-{
- struct goldfish_dma_context *dma =
- kzalloc(sizeof(struct goldfish_dma_context), GFP_KERNEL);
- struct device *pdev_dev = pipe->dev->pdev_dev;
-
- if (dma) {
- if (mutex_lock_interruptible(&pipe->lock)) {
- kfree(dma);
- return -ERESTARTSYS;
- }
-
- if (pipe->dma) {
- mutex_unlock(&pipe->lock);
- kfree(dma);
- dev_err(pdev_dev, "The DMA region already allocated\n");
- return -EBUSY;
- }
-
- dma->dma_size = size;
- dma->pdev_dev = pipe->dev->pdev_dev;
- pipe->dma = dma;
- mutex_unlock(&pipe->lock);
- return 0;
- }
-
- dev_err(pdev_dev, "Could not allocate DMA context info!\n");
- return -ENOMEM;
-}
-
-static long goldfish_dma_ioctl_getoff(struct goldfish_pipe *pipe,
- unsigned long arg)
-{
- struct device *pdev_dev = pipe->dev->pdev_dev;
- struct goldfish_dma_ioctl_info ioctl_data;
- struct goldfish_dma_context *dma;
-
- BUILD_BUG_ON(sizeof_field(struct goldfish_dma_ioctl_info, phys_begin) <
- sizeof_field(struct goldfish_dma_context, phys_begin));
-
- if (mutex_lock_interruptible(&pipe->lock)) {
- dev_err(pdev_dev, "DMA_GETOFF: the pipe is not locked\n");
- return -EACCES;
- }
-
- dma = pipe->dma;
- if (dma) {
- ioctl_data.phys_begin = dma->phys_begin;
- ioctl_data.size = dma->dma_size;
- } else {
- ioctl_data.phys_begin = 0;
- ioctl_data.size = 0;
- }
-
- if (copy_to_user((void __user *)arg, &ioctl_data,
- sizeof(ioctl_data))) {
- mutex_unlock(&pipe->lock);
- return -EFAULT;
- }
-
- mutex_unlock(&pipe->lock);
- return 0;
-}
-
-static long goldfish_dma_ioctl_create_region(struct goldfish_pipe *pipe,
- unsigned long arg)
-{
- struct goldfish_dma_ioctl_info ioctl_data;
-
- if (copy_from_user(&ioctl_data, (void __user *)arg, sizeof(ioctl_data)))
- return -EFAULT;
-
- if (!check_region_size_valid(ioctl_data.size)) {
- dev_err(pipe->dev->pdev_dev,
- "DMA_CREATE_REGION: bad size (%lld) requested\n",
- ioctl_data.size);
- return -EINVAL;
- }
-
- return goldfish_pipe_dma_create_region(pipe, ioctl_data.size);
-}
-
-static long goldfish_dma_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct goldfish_pipe *pipe =
- (struct goldfish_pipe *)(file->private_data);
-
- switch (cmd) {
- case GOLDFISH_DMA_IOC_LOCK:
- return 0;
- case GOLDFISH_DMA_IOC_UNLOCK:
- wake_up_interruptible(&pipe->wake_queue);
- return 0;
- case GOLDFISH_DMA_IOC_GETOFF:
- return goldfish_dma_ioctl_getoff(pipe, arg);
- case GOLDFISH_DMA_IOC_CREATE_REGION:
- return goldfish_dma_ioctl_create_region(pipe, arg);
- }
- return -ENOTTY;
-}
-
static const struct file_operations goldfish_pipe_fops = {
.owner = THIS_MODULE,
.read = goldfish_pipe_read,
@@ -1188,10 +905,6 @@ static const struct file_operations goldfish_pipe_fops = {
.poll = goldfish_pipe_poll,
.open = goldfish_pipe_open,
.release = goldfish_pipe_release,
- /* DMA-related operations */
- .mmap = goldfish_dma_mmap,
- .unlocked_ioctl = goldfish_dma_ioctl,
- .compat_ioctl = goldfish_dma_ioctl,
};
static void init_miscdevice(struct miscdevice *miscdev)
diff --git a/uapi/goldfish/goldfish_dma.h b/uapi/goldfish/goldfish_dma.h
deleted file mode 100644
index a901902..0000000
--- a/uapi/goldfish/goldfish_dma.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2018 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef UAPI_GOLDFISH_DMA_H
-#define UAPI_GOLDFISH_DMA_H
-
-#include <linux/types.h>
-
-/* GOLDFISH DMA
- *
- * Goldfish DMA is an extension to the pipe device
- * and is designed to facilitate high-speed RAM->RAM
- * transfers from guest to host.
- *
- * Interface (guest side):
- *
- * The guest user calls goldfish_dma_alloc (ioctls)
- * and then mmap() on a goldfish pipe fd,
- * which means that it wants high-speed access to
- * host-visible memory.
- *
- * The guest can then write into the pointer
- * returned by mmap(), and these writes
- * become immediately visible on the host without BQL
- * or otherweise context switching.
- *
- * dma_alloc_coherent() is used to obtain contiguous
- * physical memory regions, and we allocate and interact
- * with this region on both guest and host through
- * the following ioctls:
- *
- * - LOCK: lock the region for data access.
- * - UNLOCK: unlock the region. This may also be done from the host
- * through the WAKE_ON_UNLOCK_DMA procedure.
- * - CREATE_REGION: initialize size info for a dma region.
- * - GETOFF: send physical address to guest drivers.
- * - (UN)MAPHOST: uses goldfish_pipe_cmd to tell the host to
- * (un)map to the guest physical address associated
- * with the current dma context. This makes the physically
- * contiguous memory (in)visible to the host.
- *
- * Guest userspace obtains a pointer to the DMA memory
- * through mmap(), which also lazily allocates the memory
- * with dma_alloc_coherent. (On last pipe close(), the region is freed).
- * The mmaped() region can handle very high bandwidth
- * transfers, and pipe operations can be used at the same
- * time to handle synchronization and command communication.
- */
-
-#define GOLDFISH_DMA_BUFFER_SIZE (32 * 1024 * 1024)
-
-struct goldfish_dma_ioctl_info {
- __u64 phys_begin;
- __u64 size;
-};
-
-/* There is an ioctl associated with goldfish dma driver.
- * Make it conflict with ioctls that are not likely to be used
- * in the emulator.
- * 'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict!
- * 'G' 00-0F linux/gigaset_dev.h conflict!
- */
-#define GOLDFISH_DMA_IOC_MAGIC 'G'
-#define GOLDFISH_DMA_IOC_OP(OP) _IOWR(GOLDFISH_DMA_IOC_MAGIC, OP, \
- struct goldfish_dma_ioctl_info)
-
-#define GOLDFISH_DMA_IOC_LOCK GOLDFISH_DMA_IOC_OP(0)
-#define GOLDFISH_DMA_IOC_UNLOCK GOLDFISH_DMA_IOC_OP(1)
-#define GOLDFISH_DMA_IOC_GETOFF GOLDFISH_DMA_IOC_OP(2)
-#define GOLDFISH_DMA_IOC_CREATE_REGION GOLDFISH_DMA_IOC_OP(3)
-
-#endif /* UAPI_GOLDFISH_DMA_H */