diff options
| -rw-r--r-- | 0001-goldfish_pipe-An-implementation-of-more-parallel-pip.patch | 1927 | ||||
| -rw-r--r-- | 0002-CHROMIUM-android-fix-warning-when-releasing-active-s.patch | 76 | ||||
| -rw-r--r-- | 0003-goldfish-Add-goldfish-sync-driver.patch | 1429 | ||||
| -rw-r--r-- | series | 3 |
4 files changed, 3435 insertions, 0 deletions
diff --git a/0001-goldfish_pipe-An-implementation-of-more-parallel-pip.patch b/0001-goldfish_pipe-An-implementation-of-more-parallel-pip.patch new file mode 100644 index 00000000000000..248bf0a8603767 --- /dev/null +++ b/0001-goldfish_pipe-An-implementation-of-more-parallel-pip.patch @@ -0,0 +1,1927 @@ +From c53b6059ba261505317a4d8de63832846c9c92fb Mon Sep 17 00:00:00 2001 +From: Jin Qian <jinqian@android.com> +Date: Mon, 27 Feb 2017 12:06:21 -0800 +Subject: [PATCH 1/3] goldfish_pipe: An implementation of more parallel pipe + +This is a driver code for a redesigned android pipe. +Currently it works for x86 and x64 emulators with the following +performance results: + ADB push to /dev/null, + Ubuntu, + 400 MB file, + times are for (1 / 10 / 100) parallel adb commands +x86 adb push: (4.4s / 11.5s / 2m10s) -> (2.8s / 6s / 51s) +x64 adb push: (7s / 15s / (too long, 6m+) -> (2.7s / 6.2s / 52s) + +ADB pull and push to /data/ have the same %% of speedup +More importantly, I don't see any signs of slowdowns when +run in parallel with Antutu benchmark, so it is definitely +making much better job at multithreading. + +Signed-off-by: Yurii Zubrytskyi <zyy@google.com> +Signed-off-by: Jin Qian <jinqian@android.com> +--- + drivers/platform/goldfish/goldfish_pipe.c | 976 +++++++++++++++-------- + drivers/platform/goldfish/goldfish_pipe_legacy.c | 671 +++++++++++++++ + 2 files changed, 1315 insertions(+), 332 deletions(-) + create mode 100644 drivers/platform/goldfish/goldfish_pipe_legacy.c + +--- a/drivers/platform/goldfish/goldfish_pipe.c ++++ b/drivers/platform/goldfish/goldfish_pipe.c +@@ -1,8 +1,8 @@ + /* +- * Copyright (C) 2011 Google, Inc. + * Copyright (C) 2012 Intel, Inc. + * Copyright (C) 2013 Intel, Inc. + * Copyright (C) 2014 Linaro Limited ++ * Copyright (C) 2011-2016 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 +@@ -46,6 +46,7 @@ + * exchange is properly mapped during a transfer. + */ + ++ + #include <linux/module.h> + #include <linux/interrupt.h> + #include <linux/kernel.h> +@@ -63,122 +64,232 @@ + #include <linux/acpi.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 ++}; ++ ++/* + * IMPORTANT: The following constants must match the ones used and defined + * in external/qemu/hw/goldfish_pipe.c in the Android source tree. + */ + +-/* pipe device registers */ +-#define PIPE_REG_COMMAND 0x00 /* write: value = command */ +-#define PIPE_REG_STATUS 0x04 /* read */ +-#define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */ +-#define PIPE_REG_CHANNEL_HIGH 0x30 /* read/write: channel id */ +-#define PIPE_REG_SIZE 0x0c /* read/write: buffer size */ +-#define PIPE_REG_ADDRESS 0x10 /* write: physical address */ +-#define PIPE_REG_ADDRESS_HIGH 0x34 /* write: physical address */ +-#define PIPE_REG_WAKES 0x14 /* read: wake flags */ +-#define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ +-#define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ +-#define PIPE_REG_ACCESS_PARAMS 0x20 /* write: batch access */ +-#define PIPE_REG_VERSION 0x24 /* read: device version */ +- +-/* list of commands for PIPE_REG_COMMAND */ +-#define CMD_OPEN 1 /* open new channel */ +-#define CMD_CLOSE 2 /* close channel (from guest) */ +-#define CMD_POLL 3 /* poll read/write status */ +- + /* List of bitflags returned in status of CMD_POLL command */ +-#define PIPE_POLL_IN (1 << 0) +-#define PIPE_POLL_OUT (1 << 1) +-#define PIPE_POLL_HUP (1 << 2) +- +-/* The following commands are related to write operations */ +-#define CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */ +-#define CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing +- is possible */ +-#define CMD_READ_BUFFER 6 /* receive a user buffer from the emulator */ +-#define CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading +- * is possible */ ++enum PipePollFlags { ++ PIPE_POLL_IN = 1 << 0, ++ PIPE_POLL_OUT = 1 << 1, ++ PIPE_POLL_HUP = 1 << 2 ++}; + + /* Possible status values used to signal errors - see goldfish_pipe_error_convert */ +-#define PIPE_ERROR_INVAL -1 +-#define PIPE_ERROR_AGAIN -2 +-#define PIPE_ERROR_NOMEM -3 +-#define PIPE_ERROR_IO -4 ++enum PipeErrors { ++ PIPE_ERROR_INVAL = -1, ++ PIPE_ERROR_AGAIN = -2, ++ PIPE_ERROR_NOMEM = -3, ++ PIPE_ERROR_IO = -4 ++}; + + /* Bit-flags used to signal events from the emulator */ +-#define PIPE_WAKE_CLOSED (1 << 0) /* emulator closed pipe */ +-#define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */ +-#define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */ +- +-struct access_params { +- unsigned long channel; +- u32 size; +- unsigned long address; +- u32 cmd; +- u32 result; +- /* reserved for future extension */ ++enum PipeWakeFlags { ++ PIPE_WAKE_CLOSED = 1 << 0, /* emulator closed pipe */ ++ PIPE_WAKE_READ = 1 << 1, /* pipe can now be read from */ ++ PIPE_WAKE_WRITE = 1 << 2 /* pipe can now be written to */ ++}; ++ ++/* Bit flags for the 'flags' field */ ++enum PipeFlagsBits { ++ BIT_CLOSED_ON_HOST = 0, /* pipe closed by host */ ++ BIT_WAKE_ON_WRITE = 1, /* want to be woken on writes */ ++ BIT_WAKE_ON_READ = 2, /* want to be woken on reads */ ++}; ++ ++enum PipeRegs { ++ PIPE_REG_CMD = 0, ++ ++ PIPE_REG_SIGNAL_BUFFER_HIGH = 4, ++ PIPE_REG_SIGNAL_BUFFER = 8, ++ PIPE_REG_SIGNAL_BUFFER_COUNT = 12, ++ ++ PIPE_REG_OPEN_BUFFER_HIGH = 20, ++ PIPE_REG_OPEN_BUFFER = 24, ++ ++ PIPE_REG_VERSION = 36, ++ ++ PIPE_REG_GET_SIGNALLED = 48, ++}; ++ ++enum PipeCmdCode { ++ PIPE_CMD_OPEN = 1, /* to be used by the pipe device itself */ ++ PIPE_CMD_CLOSE, ++ PIPE_CMD_POLL, ++ PIPE_CMD_WRITE, ++ 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, ++}; ++ ++enum { ++ MAX_BUFFERS_PER_COMMAND = 336, ++ MAX_SIGNALLED_PIPES = 64, ++ INITIAL_PIPES_CAPACITY = 64 ++}; ++ ++struct goldfish_pipe_dev; ++struct goldfish_pipe; ++struct goldfish_pipe_command; ++ ++/* A per-pipe command structure, shared with the host */ ++struct goldfish_pipe_command { ++ s32 cmd; /* PipeCmdCode, guest -> host */ ++ 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; ++ }; ++}; ++ ++/* A single signalled pipe information */ ++struct signalled_pipe_buffer { ++ u32 id; + u32 flags; + }; + +-/* The global driver data. Holds a reference to the i/o page used to +- * communicate with the emulator, and a wake queue for blocked tasks +- * waiting to be awoken. +- */ +-struct goldfish_pipe_dev { +- spinlock_t lock; +- unsigned char __iomem *base; +- struct access_params *aps; +- int irq; +- u32 version; ++/* Parameters for the PIPE_CMD_OPEN command */ ++struct open_command_param { ++ u64 command_buffer_ptr; ++ u32 rw_params_max_count; + }; + +-static struct goldfish_pipe_dev pipe_dev[1]; ++/* Device-level set of buffers shared with the host */ ++struct goldfish_pipe_dev_buffers { ++ struct open_command_param open_command_params; ++ struct signalled_pipe_buffer signalled_pipe_buffers[ ++ MAX_SIGNALLED_PIPES]; ++}; + + /* This data type models a given pipe instance */ + struct goldfish_pipe { +- struct goldfish_pipe_dev *dev; +- struct mutex lock; ++ /* pipe ID - index into goldfish_pipe_dev::pipes array */ ++ u32 id; ++ /* The wake flags pipe is waiting for ++ * Note: not protected with any lock, uses atomic operations ++ * and barriers to make it thread-safe. ++ */ + unsigned long flags; ++ /* wake flags host have signalled, ++ * - protected by goldfish_pipe_dev::lock ++ */ ++ unsigned long signalled_flags; ++ ++ /* A pointer to command buffer */ ++ struct goldfish_pipe_command *command_buffer; ++ ++ /* doubly linked list of signalled pipes, protected by ++ * goldfish_pipe_dev::lock ++ */ ++ struct goldfish_pipe *prev_signalled; ++ struct goldfish_pipe *next_signalled; ++ ++ /* ++ * A pipe's own lock. Protects the following: ++ * - *command_buffer - makes sure a command can safely write its ++ * parameters to the host and read the results back. ++ */ ++ struct mutex lock; ++ ++ /* A wake queue for sleeping until host signals an event */ + wait_queue_head_t wake_queue; ++ /* Pointer to the parent goldfish_pipe_dev instance */ ++ struct goldfish_pipe_dev *dev; + }; + ++/* The global driver data. Holds a reference to the i/o page used to ++ * communicate with the emulator, and a wake queue for blocked tasks ++ * waiting to be awoken. ++ */ ++struct goldfish_pipe_dev { ++ /* ++ * Global device spinlock. Protects the following members: ++ * - pipes, pipes_capacity ++ * - [*pipes, *pipes + pipes_capacity) - array data ++ * - first_signalled_pipe, ++ * goldfish_pipe::prev_signalled, ++ * goldfish_pipe::next_signalled, ++ * goldfish_pipe::signalled_flags - all singnalled-related fields, ++ * in all allocated pipes ++ * - open_command_params - PIPE_CMD_OPEN-related buffers ++ * ++ * It looks like a lot of different fields, but the trick is that ++ * the only operation that happens often is the signalled pipes array ++ * manipulation. That's why it's OK for now to keep the rest of the ++ * fields under the same lock. If we notice too much contention because ++ * of PIPE_CMD_OPEN, then we should add a separate lock there. ++ */ ++ spinlock_t lock; + +-/* Bit flags for the 'flags' field */ +-enum { +- BIT_CLOSED_ON_HOST = 0, /* pipe closed by host */ +- BIT_WAKE_ON_WRITE = 1, /* want to be woken on writes */ +- BIT_WAKE_ON_READ = 2, /* want to be woken on reads */ ++ /* ++ * Array of the pipes of |pipes_capacity| elements, ++ * indexed by goldfish_pipe::id ++ */ ++ struct goldfish_pipe **pipes; ++ u32 pipes_capacity; ++ ++ /* Pointers to the buffers host uses for interaction with this driver */ ++ struct goldfish_pipe_dev_buffers *buffers; ++ ++ /* Head of a doubly linked list of signalled pipes */ ++ struct goldfish_pipe *first_signalled_pipe; ++ ++ /* Some device-specific data */ ++ int irq; ++ int version; ++ unsigned char __iomem *base; + }; + ++struct goldfish_pipe_dev pipe_dev[1] = {}; + +-static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) ++static int goldfish_cmd_locked(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) + { +- unsigned long flags; +- u32 status; +- struct goldfish_pipe_dev *dev = pipe->dev; +- +- spin_lock_irqsave(&dev->lock, flags); +- gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, +- dev->base + PIPE_REG_CHANNEL_HIGH); +- writel(cmd, dev->base + PIPE_REG_COMMAND); +- status = readl(dev->base + PIPE_REG_STATUS); +- spin_unlock_irqrestore(&dev->lock, flags); +- return status; ++ pipe->command_buffer->cmd = cmd; ++ /* failure by default */ ++ pipe->command_buffer->status = PIPE_ERROR_INVAL; ++ writel(pipe->id, pipe->dev->base + PIPE_REG_CMD); ++ return pipe->command_buffer->status; + } + +-static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) ++static int goldfish_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) + { +- unsigned long flags; +- struct goldfish_pipe_dev *dev = pipe->dev; ++ int status; + +- spin_lock_irqsave(&dev->lock, flags); +- gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, +- dev->base + PIPE_REG_CHANNEL_HIGH); +- writel(cmd, dev->base + PIPE_REG_COMMAND); +- spin_unlock_irqrestore(&dev->lock, flags); ++ if (mutex_lock_interruptible(&pipe->lock)) ++ return PIPE_ERROR_IO; ++ status = goldfish_cmd_locked(pipe, cmd); ++ mutex_unlock(&pipe->lock); ++ return status; + } + +-/* This function converts an error code returned by the emulator through ++/* ++ * This function converts an error code returned by the emulator through + * the PIPE_REG_STATUS i/o register into a valid negative errno value. + */ + static int goldfish_pipe_error_convert(int status) +@@ -195,184 +306,202 @@ static int goldfish_pipe_error_convert(i + } + } + +-/* +- * Notice: QEMU will return 0 for un-known register access, indicating +- * param_acess is supported or not +- */ +-static int valid_batchbuffer_addr(struct goldfish_pipe_dev *dev, +- struct access_params *aps) ++static int pin_user_pages(unsigned long first_page, unsigned long last_page, ++ unsigned int last_page_size, int is_write, ++ struct page *pages[MAX_BUFFERS_PER_COMMAND], ++ unsigned int *iter_last_page_size) ++{ ++ int ret; ++ int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; ++ ++ if (requested_pages > MAX_BUFFERS_PER_COMMAND) { ++ requested_pages = MAX_BUFFERS_PER_COMMAND; ++ *iter_last_page_size = PAGE_SIZE; ++ } else { ++ *iter_last_page_size = last_page_size; ++ } ++ ++ ret = get_user_pages_fast( ++ first_page, requested_pages, !is_write, pages); ++ if (ret <= 0) ++ return -EFAULT; ++ if (ret < requested_pages) ++ *iter_last_page_size = PAGE_SIZE; ++ return ret; ++ ++} ++ ++static void release_user_pages(struct page **pages, int pages_count, ++ int is_write, s32 consumed_size) + { +- u32 aph, apl; +- u64 paddr; +- aph = readl(dev->base + PIPE_REG_PARAMS_ADDR_HIGH); +- apl = readl(dev->base + PIPE_REG_PARAMS_ADDR_LOW); ++ int i; + +- paddr = ((u64)aph << 32) | apl; +- if (paddr != (__pa(aps))) +- return 0; +- return 1; ++ for (i = 0; i < pages_count; i++) { ++ if (!is_write && consumed_size > 0) ++ set_page_dirty(pages[i]); ++ put_page(pages[i]); ++ } ++} ++ ++/* Populate the call parameters, merging adjacent pages together */ ++static void populate_rw_params( ++ struct page **pages, int pages_count, ++ unsigned long address, unsigned long address_end, ++ unsigned long first_page, unsigned long last_page, ++ unsigned int iter_last_page_size, int is_write, ++ struct goldfish_pipe_command *command) ++{ ++ /* ++ * Process the first page separately - it's the only page that ++ * needs special handling for its start address. ++ */ ++ unsigned long xaddr = page_to_phys(pages[0]); ++ unsigned long xaddr_prev = xaddr; ++ int buffer_idx = 0; ++ int i = 1; ++ int size_on_page = first_page == last_page ++ ? (int)(address_end - address) ++ : (PAGE_SIZE - (address & ~PAGE_MASK)); ++ command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK)); ++ command->rw_params.sizes[0] = size_on_page; ++ for (; i < pages_count; ++i) { ++ xaddr = page_to_phys(pages[i]); ++ size_on_page = (i == pages_count - 1) ? ++ iter_last_page_size : PAGE_SIZE; ++ if (xaddr == xaddr_prev + PAGE_SIZE) { ++ command->rw_params.sizes[buffer_idx] += size_on_page; ++ } else { ++ ++buffer_idx; ++ command->rw_params.ptrs[buffer_idx] = (u64)xaddr; ++ command->rw_params.sizes[buffer_idx] = size_on_page; ++ } ++ xaddr_prev = xaddr; ++ } ++ command->rw_params.buffers_count = buffer_idx + 1; + } + +-/* 0 on success */ +-static int setup_access_params_addr(struct platform_device *pdev, +- struct goldfish_pipe_dev *dev) ++static int transfer_max_buffers(struct goldfish_pipe *pipe, ++ unsigned long address, unsigned long address_end, int is_write, ++ unsigned long last_page, unsigned int last_page_size, ++ s32 *consumed_size, int *status) + { +- dma_addr_t dma_handle; +- struct access_params *aps; ++ struct page *pages[MAX_BUFFERS_PER_COMMAND]; ++ unsigned long first_page = address & PAGE_MASK; ++ unsigned int iter_last_page_size; ++ int pages_count = pin_user_pages(first_page, last_page, ++ last_page_size, is_write, ++ pages, &iter_last_page_size); + +- aps = dmam_alloc_coherent(&pdev->dev, sizeof(struct access_params), +- &dma_handle, GFP_KERNEL); +- if (!aps) +- return -ENOMEM; ++ if (pages_count < 0) ++ return pages_count; + +- writel(upper_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_HIGH); +- writel(lower_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_LOW); ++ /* Serialize access to the pipe command buffers */ ++ if (mutex_lock_interruptible(&pipe->lock)) ++ return -ERESTARTSYS; + +- if (valid_batchbuffer_addr(dev, aps)) { +- dev->aps = aps; +- return 0; +- } else +- return -1; ++ populate_rw_params(pages, pages_count, address, address_end, ++ first_page, last_page, iter_last_page_size, is_write, ++ pipe->command_buffer); ++ ++ /* Transfer the data */ ++ *status = goldfish_cmd_locked(pipe, ++ is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ); ++ ++ *consumed_size = pipe->command_buffer->rw_params.consumed_size; ++ ++ mutex_unlock(&pipe->lock); ++ ++ release_user_pages(pages, pages_count, is_write, *consumed_size); ++ ++ return 0; + } + +-/* A value that will not be set by qemu emulator */ +-#define INITIAL_BATCH_RESULT (0xdeadbeaf) +-static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, +- unsigned long address, unsigned long avail, +- struct goldfish_pipe *pipe, int *status) +-{ +- struct access_params *aps = dev->aps; +- +- if (aps == NULL) +- return -1; +- +- aps->result = INITIAL_BATCH_RESULT; +- aps->channel = (unsigned long)pipe; +- aps->size = avail; +- aps->address = address; +- aps->cmd = cmd; +- writel(cmd, dev->base + PIPE_REG_ACCESS_PARAMS); +- /* +- * If the aps->result has not changed, that means +- * that the batch command failed +- */ +- if (aps->result == INITIAL_BATCH_RESULT) +- return -1; +- *status = aps->result; ++static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write) ++{ ++ u32 wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; ++ ++ set_bit(wakeBit, &pipe->flags); ++ ++ /* Tell the emulator we're going to wait for a wake event */ ++ (void)goldfish_cmd(pipe, ++ is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ); ++ ++ while (test_bit(wakeBit, &pipe->flags)) { ++ if (wait_event_interruptible( ++ pipe->wake_queue, ++ !test_bit(wakeBit, &pipe->flags))) ++ return -ERESTARTSYS; ++ ++ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) ++ return -EIO; ++ } ++ + return 0; + } + +-static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, +- size_t bufflen, int is_write) ++static ssize_t goldfish_pipe_read_write(struct file *filp, ++ char __user *buffer, size_t bufflen, int is_write) + { +- unsigned long irq_flags; + struct goldfish_pipe *pipe = filp->private_data; +- struct goldfish_pipe_dev *dev = pipe->dev; +- unsigned long address, address_end; + int count = 0, ret = -EINVAL; ++ unsigned long address, address_end, last_page; ++ unsigned int last_page_size; + + /* If the emulator already closed the pipe, no need to go further */ +- if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) ++ if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))) + return -EIO; +- + /* Null reads or writes succeeds */ + if (unlikely(bufflen == 0)) + return 0; +- + /* Check the buffer range for access */ +- if (!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, +- buffer, bufflen)) ++ if (unlikely(!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, ++ buffer, bufflen))) + return -EFAULT; + +- /* Serialize access to the pipe */ +- if (mutex_lock_interruptible(&pipe->lock)) +- return -ERESTARTSYS; +- +- address = (unsigned long)(void *)buffer; ++ address = (unsigned long)buffer; + address_end = address + bufflen; ++ last_page = (address_end - 1) & PAGE_MASK; ++ last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1; + + while (address < address_end) { +- unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; +- unsigned long next = page_end < address_end ? page_end +- : address_end; +- unsigned long avail = next - address; +- int status, wakeBit; +- struct page *page; +- +- /* Either vaddr or paddr depending on the device version */ +- unsigned long xaddr; ++ s32 consumed_size; ++ int status; + +- /* +- * We grab the pages on a page-by-page basis in case user +- * space gives us a potentially huge buffer but the read only +- * returns a small amount, then there's no need to pin that +- * much memory to the process. +- */ +- ret = get_user_pages_unlocked(address, 1, &page, +- is_write ? 0 : FOLL_WRITE); ++ ret = transfer_max_buffers(pipe, address, address_end, is_write, ++ last_page, last_page_size, &consumed_size, ++ &status); + if (ret < 0) + break; + +- if (dev->version) { +- /* Device version 1 or newer (qemu-android) expects the +- * physical address. ++ if (consumed_size > 0) { ++ /* No matter what's the status, we've transferred ++ * something. + */ +- xaddr = page_to_phys(page) | (address & ~PAGE_MASK); +- } else { +- /* Device version 0 (classic emulator) expects the +- * virtual address. +- */ +- xaddr = address; ++ count += consumed_size; ++ address += consumed_size; + } +- +- /* Now, try to transfer the bytes in the current page */ +- spin_lock_irqsave(&dev->lock, irq_flags); +- if (access_with_param(dev, +- is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, +- xaddr, avail, pipe, &status)) { +- gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, +- dev->base + PIPE_REG_CHANNEL_HIGH); +- writel(avail, dev->base + PIPE_REG_SIZE); +- gf_write_ptr((void *)xaddr, +- dev->base + PIPE_REG_ADDRESS, +- dev->base + PIPE_REG_ADDRESS_HIGH); +- writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, +- dev->base + PIPE_REG_COMMAND); +- status = readl(dev->base + PIPE_REG_STATUS); +- } +- spin_unlock_irqrestore(&dev->lock, irq_flags); +- +- if (status > 0 && !is_write) +- set_page_dirty(page); +- put_page(page); +- +- if (status > 0) { /* Correct transfer */ +- count += status; +- address += status; ++ if (status > 0) + continue; +- } else if (status == 0) { /* EOF */ ++ if (status == 0) { ++ /* EOF */ + ret = 0; + break; +- } else if (status < 0 && count > 0) { ++ } ++ if (count > 0) { + /* +- * An error occurred and we already transferred +- * something on one of the previous pages. ++ * An error occurred, but we already transferred ++ * something on one of the previous iterations. + * Just return what we already copied and log this + * err. +- * +- * Note: This seems like an incorrect approach but +- * cannot change it until we check if any user space +- * ABI relies on this behavior. + */ + if (status != PIPE_ERROR_AGAIN) +- pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n", ++ pr_info_ratelimited("goldfish_pipe: backend error %d on %s\n", + status, is_write ? "write" : "read"); +- ret = 0; + break; + } + + /* +- * If the error is not PIPE_ERROR_AGAIN, or if we are not in ++ * If the error is not PIPE_ERROR_AGAIN, or if we are in + * non-blocking mode, just return the error code. + */ + if (status != PIPE_ERROR_AGAIN || +@@ -381,139 +510,214 @@ static ssize_t goldfish_pipe_read_write( + break; + } + +- /* +- * The backend blocked the read/write, wait until the backend +- * tells us it's ready to process more data. +- */ +- wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; +- set_bit(wakeBit, &pipe->flags); +- +- /* Tell the emulator we're going to wait for a wake event */ +- goldfish_cmd(pipe, +- is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ); +- +- /* Unlock the pipe, then wait for the wake signal */ +- mutex_unlock(&pipe->lock); +- +- while (test_bit(wakeBit, &pipe->flags)) { +- if (wait_event_interruptible( +- pipe->wake_queue, +- !test_bit(wakeBit, &pipe->flags))) +- return -ERESTARTSYS; +- +- if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) +- return -EIO; +- } +- +- /* Try to re-acquire the lock */ +- if (mutex_lock_interruptible(&pipe->lock)) +- return -ERESTARTSYS; ++ status = wait_for_host_signal(pipe, is_write); ++ if (status < 0) ++ return status; + } +- mutex_unlock(&pipe->lock); + +- if (ret < 0) +- return ret; +- else ++ if (count > 0) + return count; ++ return ret; + } + + static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, +- size_t bufflen, loff_t *ppos) ++ size_t bufflen, loff_t *ppos) + { +- return goldfish_pipe_read_write(filp, buffer, bufflen, 0); ++ return goldfish_pipe_read_write(filp, buffer, bufflen, ++ /* is_write */ 0); + } + + static ssize_t goldfish_pipe_write(struct file *filp, + const char __user *buffer, size_t bufflen, + loff_t *ppos) + { +- return goldfish_pipe_read_write(filp, (char __user *)buffer, +- bufflen, 1); ++ return goldfish_pipe_read_write(filp, ++ /* cast away the const */(char __user *)buffer, bufflen, ++ /* is_write */ 1); + } + +- + static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait) + { + struct goldfish_pipe *pipe = filp->private_data; + unsigned int mask = 0; + int status; + +- mutex_lock(&pipe->lock); +- + poll_wait(filp, &pipe->wake_queue, wait); + +- status = goldfish_cmd_status(pipe, CMD_POLL); +- +- mutex_unlock(&pipe->lock); ++ status = goldfish_cmd(pipe, PIPE_CMD_POLL); ++ if (status < 0) ++ return -ERESTARTSYS; + + if (status & PIPE_POLL_IN) + mask |= POLLIN | POLLRDNORM; +- + if (status & PIPE_POLL_OUT) + mask |= POLLOUT | POLLWRNORM; +- + if (status & PIPE_POLL_HUP) + mask |= POLLHUP; +- + if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) + mask |= POLLERR; + + return mask; + } + +-static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) ++static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev, ++ u32 id, u32 flags) + { +- struct goldfish_pipe_dev *dev = dev_id; +- unsigned long irq_flags; +- int count = 0; ++ struct goldfish_pipe *pipe; + +- /* +- * We're going to read from the emulator a list of (channel,flags) +- * pairs corresponding to the wake events that occurred on each +- * blocked pipe (i.e. channel). +- */ +- spin_lock_irqsave(&dev->lock, irq_flags); +- for (;;) { +- /* First read the channel, 0 means the end of the list */ +- struct goldfish_pipe *pipe; +- unsigned long wakes; +- unsigned long channel = 0; ++ if (WARN_ON(id >= dev->pipes_capacity)) ++ return; + +-#ifdef CONFIG_64BIT +- channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32; ++ pipe = dev->pipes[id]; ++ if (!pipe) ++ return; ++ pipe->signalled_flags |= flags; ++ ++ if (pipe->prev_signalled || pipe->next_signalled ++ || dev->first_signalled_pipe == pipe) ++ return; /* already in the list */ ++ pipe->next_signalled = dev->first_signalled_pipe; ++ if (dev->first_signalled_pipe) ++ dev->first_signalled_pipe->prev_signalled = pipe; ++ dev->first_signalled_pipe = pipe; ++} ++ ++static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev, ++ struct goldfish_pipe *pipe) { ++ if (pipe->prev_signalled) ++ pipe->prev_signalled->next_signalled = pipe->next_signalled; ++ if (pipe->next_signalled) ++ pipe->next_signalled->prev_signalled = pipe->prev_signalled; ++ if (pipe == dev->first_signalled_pipe) ++ dev->first_signalled_pipe = pipe->next_signalled; ++ pipe->prev_signalled = NULL; ++ pipe->next_signalled = NULL; ++} + +- if (channel == 0) +- break; +-#endif +- channel |= readl(dev->base + PIPE_REG_CHANNEL); ++static struct goldfish_pipe *signalled_pipes_pop_front( ++ struct goldfish_pipe_dev *dev, int *wakes) ++{ ++ struct goldfish_pipe *pipe; ++ unsigned long flags; + +- if (channel == 0) +- break; ++ spin_lock_irqsave(&dev->lock, flags); + +- /* Convert channel to struct pipe pointer + read wake flags */ +- wakes = readl(dev->base + PIPE_REG_WAKES); +- pipe = (struct goldfish_pipe *)(ptrdiff_t)channel; ++ pipe = dev->first_signalled_pipe; ++ if (pipe) { ++ *wakes = pipe->signalled_flags; ++ pipe->signalled_flags = 0; ++ /* ++ * This is an optimized version of ++ * signalled_pipes_remove_locked() ++ * - We want to make it as fast as possible to ++ * wake the sleeping pipe operations faster. ++ */ ++ dev->first_signalled_pipe = pipe->next_signalled; ++ if (dev->first_signalled_pipe) ++ dev->first_signalled_pipe->prev_signalled = NULL; ++ pipe->next_signalled = NULL; ++ } + +- /* Did the emulator just closed a pipe? */ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return pipe; ++} ++ ++static void goldfish_interrupt_task(unsigned long unused) ++{ ++ struct goldfish_pipe_dev *dev = pipe_dev; ++ /* Iterate over the signalled pipes and wake them one by one */ ++ struct goldfish_pipe *pipe; ++ int wakes; ++ ++ while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) { + if (wakes & PIPE_WAKE_CLOSED) { +- set_bit(BIT_CLOSED_ON_HOST, &pipe->flags); +- wakes |= PIPE_WAKE_READ | PIPE_WAKE_WRITE; ++ pipe->flags = 1 << BIT_CLOSED_ON_HOST; ++ } else { ++ if (wakes & PIPE_WAKE_READ) ++ clear_bit(BIT_WAKE_ON_READ, &pipe->flags); ++ if (wakes & PIPE_WAKE_WRITE) ++ clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); + } +- if (wakes & PIPE_WAKE_READ) +- clear_bit(BIT_WAKE_ON_READ, &pipe->flags); +- if (wakes & PIPE_WAKE_WRITE) +- clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); +- ++ /* ++ * wake_up_interruptible() implies a write barrier, so don't ++ * explicitly add another one here. ++ */ + wake_up_interruptible(&pipe->wake_queue); +- count++; + } +- spin_unlock_irqrestore(&dev->lock, irq_flags); ++} ++DECLARE_TASKLET(goldfish_interrupt_tasklet, goldfish_interrupt_task, 0); ++ ++/* ++ * The general idea of the interrupt handling: ++ * ++ * 1. device raises an interrupt if there's at least one signalled pipe ++ * 2. IRQ handler reads the signalled pipes and their count from the device ++ * 3. device writes them into a shared buffer and returns the count ++ * it only resets the IRQ if it has returned all signalled pipes, ++ * otherwise it leaves it raised, so IRQ handler will be called ++ * again for the next chunk ++ * 4. IRQ handler adds all returned pipes to the device's signalled pipes list ++ * 5. IRQ handler launches a tasklet to process the signalled pipes from the ++ * list in a separate context ++ */ ++static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) ++{ ++ u32 count; ++ u32 i; ++ unsigned long flags; ++ struct goldfish_pipe_dev *dev = dev_id; ++ ++ if (dev != pipe_dev) ++ return IRQ_NONE; ++ ++ /* Request the signalled pipes from the device */ ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ count = readl(dev->base + PIPE_REG_GET_SIGNALLED); ++ if (count == 0) { ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return IRQ_NONE; ++ } ++ if (count > MAX_SIGNALLED_PIPES) ++ count = MAX_SIGNALLED_PIPES; + +- return (count == 0) ? IRQ_NONE : IRQ_HANDLED; ++ for (i = 0; i < count; ++i) ++ signalled_pipes_add_locked(dev, ++ dev->buffers->signalled_pipe_buffers[i].id, ++ dev->buffers->signalled_pipe_buffers[i].flags); ++ ++ spin_unlock_irqrestore(&dev->lock, flags); ++ ++ tasklet_schedule(&goldfish_interrupt_tasklet); ++ return IRQ_HANDLED; ++} ++ ++static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) ++{ ++ int id; ++ ++ for (id = 0; id < dev->pipes_capacity; ++id) ++ if (!dev->pipes[id]) ++ return id; ++ ++ { ++ /* Reallocate the array */ ++ u32 new_capacity = 2 * dev->pipes_capacity; ++ struct goldfish_pipe **pipes = ++ kcalloc(new_capacity, sizeof(*pipes), GFP_KERNEL); ++ if (!pipes) ++ return -ENOMEM; ++ memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); ++ kfree(dev->pipes); ++ dev->pipes = pipes; ++ id = dev->pipes_capacity; ++ dev->pipes_capacity = new_capacity; ++ } ++ return id; + } + + /** +- * goldfish_pipe_open - open a channel to the AVD ++ * goldfish_pipe_open - open a channel to the AVD + * @inode: inode of device + * @file: file struct of opener + * +@@ -525,12 +729,13 @@ static irqreturn_t goldfish_pipe_interru + */ + static int goldfish_pipe_open(struct inode *inode, struct file *file) + { +- struct goldfish_pipe *pipe; + struct goldfish_pipe_dev *dev = pipe_dev; +- int32_t status; ++ unsigned long flags; ++ int id; ++ int status; + + /* Allocate new pipe kernel object */ +- pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); ++ struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); + if (pipe == NULL) + return -ENOMEM; + +@@ -539,29 +744,69 @@ static int goldfish_pipe_open(struct ino + init_waitqueue_head(&pipe->wake_queue); + + /* +- * Now, tell the emulator we're opening a new pipe. We use the +- * pipe object's address as the channel identifier for simplicity. ++ * Command buffer needs to be allocated on its own page to make sure ++ * it is physically contiguous in host's address space. + */ ++ pipe->command_buffer = ++ (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL); ++ if (!pipe->command_buffer) { ++ status = -ENOMEM; ++ goto err_pipe; ++ } + +- status = goldfish_cmd_status(pipe, CMD_OPEN); +- if (status < 0) { +- kfree(pipe); +- return status; ++ spin_lock_irqsave(&dev->lock, flags); ++ ++ id = get_free_pipe_id_locked(dev); ++ if (id < 0) { ++ status = id; ++ goto err_id_locked; + } + ++ dev->pipes[id] = pipe; ++ pipe->id = id; ++ pipe->command_buffer->id = id; ++ ++ /* Now tell the emulator we're opening a new pipe. */ ++ dev->buffers->open_command_params.rw_params_max_count = ++ MAX_BUFFERS_PER_COMMAND; ++ dev->buffers->open_command_params.command_buffer_ptr = ++ (u64)(unsigned long)__pa(pipe->command_buffer); ++ status = goldfish_cmd_locked(pipe, PIPE_CMD_OPEN); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ if (status < 0) ++ goto err_cmd; + /* All is done, save the pipe into the file's private data field */ + file->private_data = pipe; + return 0; ++ ++err_cmd: ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->pipes[id] = NULL; ++err_id_locked: ++ spin_unlock_irqrestore(&dev->lock, flags); ++ free_page((unsigned long)pipe->command_buffer); ++err_pipe: ++ kfree(pipe); ++ return status; + } + + static int goldfish_pipe_release(struct inode *inode, struct file *filp) + { ++ unsigned long flags; + struct goldfish_pipe *pipe = filp->private_data; ++ struct goldfish_pipe_dev *dev = pipe->dev; + + /* The guest is closing the channel, so tell the emulator right now */ +- goldfish_cmd(pipe, CMD_CLOSE); +- kfree(pipe); ++ (void)goldfish_cmd(pipe, PIPE_CMD_CLOSE); ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ dev->pipes[pipe->id] = NULL; ++ signalled_pipes_remove_locked(dev, pipe); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ + filp->private_data = NULL; ++ free_page((unsigned long)pipe->command_buffer); ++ kfree(pipe); + return 0; + } + +@@ -574,18 +819,91 @@ static const struct file_operations gold + .release = goldfish_pipe_release, + }; + +-static struct miscdevice goldfish_pipe_device = { ++static struct miscdevice goldfish_pipe_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "goldfish_pipe", + .fops = &goldfish_pipe_fops, + }; + ++static int goldfish_pipe_device_init(struct platform_device *pdev) ++{ ++ char *page; ++ struct goldfish_pipe_dev *dev = pipe_dev; ++ int err = devm_request_irq(&pdev->dev, dev->irq, ++ goldfish_pipe_interrupt, ++ IRQF_SHARED, "goldfish_pipe", dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to allocate IRQ for v2\n"); ++ return err; ++ } ++ ++ err = misc_register(&goldfish_pipe_dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to register v2 device\n"); ++ return err; ++ } ++ ++ dev->first_signalled_pipe = NULL; ++ dev->pipes_capacity = INITIAL_PIPES_CAPACITY; ++ dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), ++ GFP_KERNEL); ++ if (!dev->pipes) ++ return -ENOMEM; ++ ++ /* ++ * We're going to pass two buffers, open_command_params and ++ * signalled_pipe_buffers, to the host. This means each of those buffers ++ * needs to be contained in a single physical page. The easiest choice ++ * is to just allocate a page and place the buffers in it. ++ */ ++ if (WARN_ON(sizeof(*dev->buffers) > PAGE_SIZE)) ++ return -ENOMEM; ++ ++ page = (char *)__get_free_page(GFP_KERNEL); ++ if (!page) { ++ kfree(dev->pipes); ++ return -ENOMEM; ++ } ++ dev->buffers = (struct goldfish_pipe_dev_buffers *)page; ++ ++ /* Send the buffer addresses to the host */ ++ { ++ u64 paddr = __pa(&dev->buffers->signalled_pipe_buffers); ++ ++ writel((u32)(unsigned long)(paddr >> 32), ++ dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH); ++ writel((u32)(unsigned long)paddr, ++ dev->base + PIPE_REG_SIGNAL_BUFFER); ++ writel((u32)MAX_SIGNALLED_PIPES, ++ dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT); ++ ++ paddr = __pa(&dev->buffers->open_command_params); ++ writel((u32)(unsigned long)(paddr >> 32), ++ dev->base + PIPE_REG_OPEN_BUFFER_HIGH); ++ writel((u32)(unsigned long)paddr, ++ dev->base + PIPE_REG_OPEN_BUFFER); ++ } ++ return 0; ++} ++ ++static void goldfish_pipe_device_deinit(struct platform_device *pdev) ++{ ++ struct goldfish_pipe_dev *dev = pipe_dev; ++ ++ misc_deregister(&goldfish_pipe_dev); ++ kfree(dev->pipes); ++ free_page((unsigned long)dev->buffers); ++} ++ + static int goldfish_pipe_probe(struct platform_device *pdev) + { + int err; + struct resource *r; + struct goldfish_pipe_dev *dev = pipe_dev; + ++ if (WARN_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE)) ++ return -ENOMEM; ++ + /* not thread safe, but this should not happen */ + WARN_ON(dev->base != NULL); + +@@ -609,26 +927,21 @@ static int goldfish_pipe_probe(struct pl + } + dev->irq = r->start; + +- err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt, +- IRQF_SHARED, "goldfish_pipe", dev); +- if (err) { +- dev_err(&pdev->dev, "unable to allocate IRQ\n"); +- goto error; +- } +- +- err = misc_register(&goldfish_pipe_device); +- if (err) { +- dev_err(&pdev->dev, "unable to register device\n"); +- goto error; +- } +- setup_access_params_addr(pdev, dev); +- +- /* Although the pipe device in the classic Android emulator does not +- * recognize the 'version' register, it won't treat this as an error +- * either and will simply return 0, which is fine. ++ /* ++ * 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((u32)PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION); + dev->version = readl(dev->base + PIPE_REG_VERSION); +- return 0; ++ if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION)) ++ return -EINVAL; ++ ++ err = goldfish_pipe_device_init(pdev); ++ if (!err) ++ return 0; + + error: + dev->base = NULL; +@@ -638,7 +951,7 @@ error: + static int goldfish_pipe_remove(struct platform_device *pdev) + { + struct goldfish_pipe_dev *dev = pipe_dev; +- misc_deregister(&goldfish_pipe_device); ++ goldfish_pipe_device_deinit(pdev); + dev->base = NULL; + return 0; + } +@@ -655,17 +968,16 @@ static const struct of_device_id goldfis + }; + MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); + +-static struct platform_driver goldfish_pipe = { ++static struct platform_driver goldfish_pipe_driver = { + .probe = goldfish_pipe_probe, + .remove = goldfish_pipe_remove, + .driver = { + .name = "goldfish_pipe", +- .owner = THIS_MODULE, + .of_match_table = goldfish_pipe_of_match, + .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), + } + }; + +-module_platform_driver(goldfish_pipe); ++module_platform_driver(goldfish_pipe_driver); + MODULE_AUTHOR("David Turner <digit@google.com>"); + MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/platform/goldfish/goldfish_pipe_legacy.c +@@ -0,0 +1,671 @@ ++/* ++ * Copyright (C) 2011 Google, Inc. ++ * Copyright (C) 2012 Intel, Inc. ++ * Copyright (C) 2013 Intel, Inc. ++ * Copyright (C) 2014 Linaro Limited ++ * ++ * 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. ++ * ++ */ ++ ++/* 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 = "<pipename>"; ++ * if (write(fd, msg, strlen(msg)+1) < 0) { ++ * ... could not connect to <pipename> 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 <linux/module.h> ++#include <linux/interrupt.h> ++#include <linux/kernel.h> ++#include <linux/spinlock.h> ++#include <linux/miscdevice.h> ++#include <linux/platform_device.h> ++#include <linux/poll.h> ++#include <linux/sched.h> ++#include <linux/bitops.h> ++#include <linux/slab.h> ++#include <linux/io.h> ++#include <linux/goldfish.h> ++#include <linux/dma-mapping.h> ++#include <linux/mm.h> ++#include <linux/acpi.h> ++ ++/* ++ * IMPORTANT: The following constants must match the ones used and defined ++ * in external/qemu/hw/goldfish_pipe.c in the Android source tree. ++ */ ++ ++/* pipe device registers */ ++#define PIPE_REG_COMMAND 0x00 /* write: value = command */ ++#define PIPE_REG_STATUS 0x04 /* read */ ++#define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */ ++#define PIPE_REG_CHANNEL_HIGH 0x30 /* read/write: channel id */ ++#define PIPE_REG_SIZE 0x0c /* read/write: buffer size */ ++#define PIPE_REG_ADDRESS 0x10 /* write: physical address */ ++#define PIPE_REG_ADDRESS_HIGH 0x34 /* write: physical address */ ++#define PIPE_REG_WAKES 0x14 /* read: wake flags */ ++#define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ ++#define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ ++#define PIPE_REG_ACCESS_PARAMS 0x20 /* write: batch access */ ++#define PIPE_REG_VERSION 0x24 /* read: device version */ ++ ++/* list of commands for PIPE_REG_COMMAND */ ++#define CMD_OPEN 1 /* open new channel */ ++#define CMD_CLOSE 2 /* close channel (from guest) */ ++#define CMD_POLL 3 /* poll read/write status */ ++ ++/* List of bitflags returned in status of CMD_POLL command */ ++#define PIPE_POLL_IN (1 << 0) ++#define PIPE_POLL_OUT (1 << 1) ++#define PIPE_POLL_HUP (1 << 2) ++ ++/* The following commands are related to write operations */ ++#define CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */ ++#define CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing ++ is possible */ ++#define CMD_READ_BUFFER 6 /* receive a user buffer from the emulator */ ++#define CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading ++ * is possible */ ++ ++/* Possible status values used to signal errors - see goldfish_pipe_error_convert */ ++#define PIPE_ERROR_INVAL -1 ++#define PIPE_ERROR_AGAIN -2 ++#define PIPE_ERROR_NOMEM -3 ++#define PIPE_ERROR_IO -4 ++ ++/* Bit-flags used to signal events from the emulator */ ++#define PIPE_WAKE_CLOSED (1 << 0) /* emulator closed pipe */ ++#define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */ ++#define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */ ++ ++struct access_params { ++ unsigned long channel; ++ u32 size; ++ unsigned long address; ++ u32 cmd; ++ u32 result; ++ /* reserved for future extension */ ++ u32 flags; ++}; ++ ++/* The global driver data. Holds a reference to the i/o page used to ++ * communicate with the emulator, and a wake queue for blocked tasks ++ * waiting to be awoken. ++ */ ++struct goldfish_pipe_dev { ++ spinlock_t lock; ++ unsigned char __iomem *base; ++ struct access_params *aps; ++ int irq; ++ u32 version; ++}; ++ ++static struct goldfish_pipe_dev pipe_dev[1]; ++ ++/* This data type models a given pipe instance */ ++struct goldfish_pipe { ++ struct goldfish_pipe_dev *dev; ++ struct mutex lock; ++ unsigned long flags; ++ wait_queue_head_t wake_queue; ++}; ++ ++ ++/* Bit flags for the 'flags' field */ ++enum { ++ BIT_CLOSED_ON_HOST = 0, /* pipe closed by host */ ++ BIT_WAKE_ON_WRITE = 1, /* want to be woken on writes */ ++ BIT_WAKE_ON_READ = 2, /* want to be woken on reads */ ++}; ++ ++ ++static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) ++{ ++ unsigned long flags; ++ u32 status; ++ struct goldfish_pipe_dev *dev = pipe->dev; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, ++ dev->base + PIPE_REG_CHANNEL_HIGH); ++ writel(cmd, dev->base + PIPE_REG_COMMAND); ++ status = readl(dev->base + PIPE_REG_STATUS); ++ spin_unlock_irqrestore(&dev->lock, flags); ++ return status; ++} ++ ++static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) ++{ ++ unsigned long flags; ++ struct goldfish_pipe_dev *dev = pipe->dev; ++ ++ spin_lock_irqsave(&dev->lock, flags); ++ gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, ++ dev->base + PIPE_REG_CHANNEL_HIGH); ++ writel(cmd, dev->base + PIPE_REG_COMMAND); ++ spin_unlock_irqrestore(&dev->lock, flags); ++} ++ ++/* This function converts an error code returned by the emulator through ++ * the PIPE_REG_STATUS i/o register into a valid negative errno value. ++ */ ++static int goldfish_pipe_error_convert(int status) ++{ ++ switch (status) { ++ case PIPE_ERROR_AGAIN: ++ return -EAGAIN; ++ case PIPE_ERROR_NOMEM: ++ return -ENOMEM; ++ case PIPE_ERROR_IO: ++ return -EIO; ++ default: ++ return -EINVAL; ++ } ++} ++ ++/* ++ * Notice: QEMU will return 0 for un-known register access, indicating ++ * param_acess is supported or not ++ */ ++static int valid_batchbuffer_addr(struct goldfish_pipe_dev *dev, ++ struct access_params *aps) ++{ ++ u32 aph, apl; ++ u64 paddr; ++ aph = readl(dev->base + PIPE_REG_PARAMS_ADDR_HIGH); ++ apl = readl(dev->base + PIPE_REG_PARAMS_ADDR_LOW); ++ ++ paddr = ((u64)aph << 32) | apl; ++ if (paddr != (__pa(aps))) ++ return 0; ++ return 1; ++} ++ ++/* 0 on success */ ++static int setup_access_params_addr(struct platform_device *pdev, ++ struct goldfish_pipe_dev *dev) ++{ ++ dma_addr_t dma_handle; ++ struct access_params *aps; ++ ++ aps = dmam_alloc_coherent(&pdev->dev, sizeof(struct access_params), ++ &dma_handle, GFP_KERNEL); ++ if (!aps) ++ return -ENOMEM; ++ ++ writel(upper_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_HIGH); ++ writel(lower_32_bits(dma_handle), dev->base + PIPE_REG_PARAMS_ADDR_LOW); ++ ++ if (valid_batchbuffer_addr(dev, aps)) { ++ dev->aps = aps; ++ return 0; ++ } else ++ return -1; ++} ++ ++/* A value that will not be set by qemu emulator */ ++#define INITIAL_BATCH_RESULT (0xdeadbeaf) ++static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, ++ unsigned long address, unsigned long avail, ++ struct goldfish_pipe *pipe, int *status) ++{ ++ struct access_params *aps = dev->aps; ++ ++ if (aps == NULL) ++ return -1; ++ ++ aps->result = INITIAL_BATCH_RESULT; ++ aps->channel = (unsigned long)pipe; ++ aps->size = avail; ++ aps->address = address; ++ aps->cmd = cmd; ++ writel(cmd, dev->base + PIPE_REG_ACCESS_PARAMS); ++ /* ++ * If the aps->result has not changed, that means ++ * that the batch command failed ++ */ ++ if (aps->result == INITIAL_BATCH_RESULT) ++ return -1; ++ *status = aps->result; ++ return 0; ++} ++ ++static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, ++ size_t bufflen, int is_write) ++{ ++ unsigned long irq_flags; ++ struct goldfish_pipe *pipe = filp->private_data; ++ struct goldfish_pipe_dev *dev = pipe->dev; ++ unsigned long address, address_end; ++ int count = 0, ret = -EINVAL; ++ ++ /* If the emulator already closed the pipe, no need to go further */ ++ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) ++ return -EIO; ++ ++ /* Null reads or writes succeeds */ ++ if (unlikely(bufflen == 0)) ++ return 0; ++ ++ /* Check the buffer range for access */ ++ if (!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, ++ buffer, bufflen)) ++ return -EFAULT; ++ ++ /* Serialize access to the pipe */ ++ if (mutex_lock_interruptible(&pipe->lock)) ++ return -ERESTARTSYS; ++ ++ address = (unsigned long)(void *)buffer; ++ address_end = address + bufflen; ++ ++ while (address < address_end) { ++ unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; ++ unsigned long next = page_end < address_end ? page_end ++ : address_end; ++ unsigned long avail = next - address; ++ int status, wakeBit; ++ struct page *page; ++ ++ /* Either vaddr or paddr depending on the device version */ ++ unsigned long xaddr; ++ ++ /* ++ * We grab the pages on a page-by-page basis in case user ++ * space gives us a potentially huge buffer but the read only ++ * returns a small amount, then there's no need to pin that ++ * much memory to the process. ++ */ ++ ret = get_user_pages_unlocked(address, 1, &page, ++ is_write ? 0 : FOLL_WRITE); ++ if (ret < 0) ++ break; ++ ++ if (dev->version) { ++ /* Device version 1 or newer (qemu-android) expects the ++ * physical address. ++ */ ++ xaddr = page_to_phys(page) | (address & ~PAGE_MASK); ++ } else { ++ /* Device version 0 (classic emulator) expects the ++ * virtual address. ++ */ ++ xaddr = address; ++ } ++ ++ /* Now, try to transfer the bytes in the current page */ ++ spin_lock_irqsave(&dev->lock, irq_flags); ++ if (access_with_param(dev, ++ is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, ++ xaddr, avail, pipe, &status)) { ++ gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, ++ dev->base + PIPE_REG_CHANNEL_HIGH); ++ writel(avail, dev->base + PIPE_REG_SIZE); ++ gf_write_ptr((void *)xaddr, ++ dev->base + PIPE_REG_ADDRESS, ++ dev->base + PIPE_REG_ADDRESS_HIGH); ++ writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, ++ dev->base + PIPE_REG_COMMAND); ++ status = readl(dev->base + PIPE_REG_STATUS); ++ } ++ spin_unlock_irqrestore(&dev->lock, irq_flags); ++ ++ if (status > 0 && !is_write) ++ set_page_dirty(page); ++ put_page(page); ++ ++ if (status > 0) { /* Correct transfer */ ++ count += status; ++ address += status; ++ continue; ++ } else if (status == 0) { /* EOF */ ++ ret = 0; ++ break; ++ } else if (status < 0 && count > 0) { ++ /* ++ * An error occurred and we already transferred ++ * something on one of the previous pages. ++ * Just return what we already copied and log this ++ * err. ++ * ++ * Note: This seems like an incorrect approach but ++ * cannot change it until we check if any user space ++ * ABI relies on this behavior. ++ */ ++ if (status != PIPE_ERROR_AGAIN) ++ pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n", ++ status, is_write ? "write" : "read"); ++ ret = 0; ++ break; ++ } ++ ++ /* ++ * If the error is not PIPE_ERROR_AGAIN, or if we are not in ++ * non-blocking mode, just return the error code. ++ */ ++ if (status != PIPE_ERROR_AGAIN || ++ (filp->f_flags & O_NONBLOCK) != 0) { ++ ret = goldfish_pipe_error_convert(status); ++ break; ++ } ++ ++ /* ++ * The backend blocked the read/write, wait until the backend ++ * tells us it's ready to process more data. ++ */ ++ wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; ++ set_bit(wakeBit, &pipe->flags); ++ ++ /* Tell the emulator we're going to wait for a wake event */ ++ goldfish_cmd(pipe, ++ is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ); ++ ++ /* Unlock the pipe, then wait for the wake signal */ ++ mutex_unlock(&pipe->lock); ++ ++ while (test_bit(wakeBit, &pipe->flags)) { ++ if (wait_event_interruptible( ++ pipe->wake_queue, ++ !test_bit(wakeBit, &pipe->flags))) ++ return -ERESTARTSYS; ++ ++ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) ++ return -EIO; ++ } ++ ++ /* Try to re-acquire the lock */ ++ if (mutex_lock_interruptible(&pipe->lock)) ++ return -ERESTARTSYS; ++ } ++ mutex_unlock(&pipe->lock); ++ ++ if (ret < 0) ++ return ret; ++ else ++ return count; ++} ++ ++static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, ++ size_t bufflen, loff_t *ppos) ++{ ++ return goldfish_pipe_read_write(filp, buffer, bufflen, 0); ++} ++ ++static ssize_t goldfish_pipe_write(struct file *filp, ++ const char __user *buffer, size_t bufflen, ++ loff_t *ppos) ++{ ++ return goldfish_pipe_read_write(filp, (char __user *)buffer, ++ bufflen, 1); ++} ++ ++ ++static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait) ++{ ++ struct goldfish_pipe *pipe = filp->private_data; ++ unsigned int mask = 0; ++ int status; ++ ++ mutex_lock(&pipe->lock); ++ ++ poll_wait(filp, &pipe->wake_queue, wait); ++ ++ status = goldfish_cmd_status(pipe, CMD_POLL); ++ ++ mutex_unlock(&pipe->lock); ++ ++ if (status & PIPE_POLL_IN) ++ mask |= POLLIN | POLLRDNORM; ++ ++ if (status & PIPE_POLL_OUT) ++ mask |= POLLOUT | POLLWRNORM; ++ ++ if (status & PIPE_POLL_HUP) ++ mask |= POLLHUP; ++ ++ if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) ++ mask |= POLLERR; ++ ++ return mask; ++} ++ ++static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) ++{ ++ struct goldfish_pipe_dev *dev = dev_id; ++ unsigned long irq_flags; ++ int count = 0; ++ ++ /* ++ * We're going to read from the emulator a list of (channel,flags) ++ * pairs corresponding to the wake events that occurred on each ++ * blocked pipe (i.e. channel). ++ */ ++ spin_lock_irqsave(&dev->lock, irq_flags); ++ for (;;) { ++ /* First read the channel, 0 means the end of the list */ ++ struct goldfish_pipe *pipe; ++ unsigned long wakes; ++ unsigned long channel = 0; ++ ++#ifdef CONFIG_64BIT ++ channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32; ++ ++ if (channel == 0) ++ break; ++#endif ++ channel |= readl(dev->base + PIPE_REG_CHANNEL); ++ ++ if (channel == 0) ++ break; ++ ++ /* Convert channel to struct pipe pointer + read wake flags */ ++ wakes = readl(dev->base + PIPE_REG_WAKES); ++ pipe = (struct goldfish_pipe *)(ptrdiff_t)channel; ++ ++ /* Did the emulator just closed a pipe? */ ++ if (wakes & PIPE_WAKE_CLOSED) { ++ set_bit(BIT_CLOSED_ON_HOST, &pipe->flags); ++ wakes |= PIPE_WAKE_READ | PIPE_WAKE_WRITE; ++ } ++ if (wakes & PIPE_WAKE_READ) ++ clear_bit(BIT_WAKE_ON_READ, &pipe->flags); ++ if (wakes & PIPE_WAKE_WRITE) ++ clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); ++ ++ wake_up_interruptible(&pipe->wake_queue); ++ count++; ++ } ++ spin_unlock_irqrestore(&dev->lock, irq_flags); ++ ++ return (count == 0) ? IRQ_NONE : IRQ_HANDLED; ++} ++ ++/** ++ * goldfish_pipe_open - open a channel to the AVD ++ * @inode: inode of device ++ * @file: file struct of opener ++ * ++ * Create a new pipe link between the emulator and the use application. ++ * Each new request produces a new pipe. ++ * ++ * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit ++ * right now so this is fine. A move to 64bit will need this addressing ++ */ ++static int goldfish_pipe_open(struct inode *inode, struct file *file) ++{ ++ struct goldfish_pipe *pipe; ++ struct goldfish_pipe_dev *dev = pipe_dev; ++ int32_t status; ++ ++ /* Allocate new pipe kernel object */ ++ pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); ++ if (pipe == NULL) ++ return -ENOMEM; ++ ++ pipe->dev = dev; ++ mutex_init(&pipe->lock); ++ init_waitqueue_head(&pipe->wake_queue); ++ ++ /* ++ * Now, tell the emulator we're opening a new pipe. We use the ++ * pipe object's address as the channel identifier for simplicity. ++ */ ++ ++ status = goldfish_cmd_status(pipe, CMD_OPEN); ++ if (status < 0) { ++ kfree(pipe); ++ return status; ++ } ++ ++ /* All is done, save the pipe into the file's private data field */ ++ file->private_data = pipe; ++ return 0; ++} ++ ++static int goldfish_pipe_release(struct inode *inode, struct file *filp) ++{ ++ struct goldfish_pipe *pipe = filp->private_data; ++ ++ /* The guest is closing the channel, so tell the emulator right now */ ++ goldfish_cmd(pipe, CMD_CLOSE); ++ kfree(pipe); ++ filp->private_data = NULL; ++ return 0; ++} ++ ++static const struct file_operations goldfish_pipe_fops = { ++ .owner = THIS_MODULE, ++ .read = goldfish_pipe_read, ++ .write = goldfish_pipe_write, ++ .poll = goldfish_pipe_poll, ++ .open = goldfish_pipe_open, ++ .release = goldfish_pipe_release, ++}; ++ ++static struct miscdevice goldfish_pipe_device = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "goldfish_pipe", ++ .fops = &goldfish_pipe_fops, ++}; ++ ++static int goldfish_pipe_probe(struct platform_device *pdev) ++{ ++ int err; ++ struct resource *r; ++ struct goldfish_pipe_dev *dev = pipe_dev; ++ ++ /* not thread safe, but this should not happen */ ++ WARN_ON(dev->base != NULL); ++ ++ spin_lock_init(&dev->lock); ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL || resource_size(r) < PAGE_SIZE) { ++ dev_err(&pdev->dev, "can't allocate i/o page\n"); ++ return -EINVAL; ++ } ++ dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); ++ if (dev->base == NULL) { ++ dev_err(&pdev->dev, "ioremap failed\n"); ++ return -EINVAL; ++ } ++ ++ r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (r == NULL) { ++ err = -EINVAL; ++ goto error; ++ } ++ dev->irq = r->start; ++ ++ err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt, ++ IRQF_SHARED, "goldfish_pipe", dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to allocate IRQ\n"); ++ goto error; ++ } ++ ++ err = misc_register(&goldfish_pipe_device); ++ if (err) { ++ dev_err(&pdev->dev, "unable to register device\n"); ++ goto error; ++ } ++ setup_access_params_addr(pdev, dev); ++ ++ /* Although the pipe device in the classic Android emulator does not ++ * recognize the 'version' register, it won't treat this as an error ++ * either and will simply return 0, which is fine. ++ */ ++ dev->version = readl(dev->base + PIPE_REG_VERSION); ++ return 0; ++ ++error: ++ dev->base = NULL; ++ return err; ++} ++ ++static int goldfish_pipe_remove(struct platform_device *pdev) ++{ ++ struct goldfish_pipe_dev *dev = pipe_dev; ++ misc_deregister(&goldfish_pipe_device); ++ dev->base = NULL; ++ return 0; ++} ++ ++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 = { ++ .probe = goldfish_pipe_probe, ++ .remove = goldfish_pipe_remove, ++ .driver = { ++ .name = "goldfish_pipe", ++ .owner = THIS_MODULE, ++ .of_match_table = goldfish_pipe_of_match, ++ .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), ++ } ++}; ++ ++module_platform_driver(goldfish_pipe); ++MODULE_AUTHOR("David Turner <digit@google.com>"); ++MODULE_LICENSE("GPL"); diff --git a/0002-CHROMIUM-android-fix-warning-when-releasing-active-s.patch b/0002-CHROMIUM-android-fix-warning-when-releasing-active-s.patch new file mode 100644 index 00000000000000..01b6e8dc2672ec --- /dev/null +++ b/0002-CHROMIUM-android-fix-warning-when-releasing-active-s.patch @@ -0,0 +1,76 @@ +From 384a2aaec210cc69d53cf9eec2cc7f15b10d7312 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov <dtor@chromium.org> +Date: Tue, 8 Sep 2015 17:30:52 -0700 +Subject: [PATCH 2/3] CHROMIUM: android: fix warning when releasing active sync + point + +Userspace can close the sync device while there are still active fence +points, in which case kernel produces the following warning: + +[ 43.853176] ------------[ cut here ]------------ +[ 43.857834] WARNING: CPU: 0 PID: 892 at /mnt/host/source/src/third_party/kernel/v3.18/drivers/staging/android/sync.c:439 android_fence_release+0x88/0x104() +[ 43.871741] CPU: 0 PID: 892 Comm: Binder_5 Tainted: G U 3.18.0-07661-g0550ce9 #1 +[ 43.880176] Hardware name: Google Tegra210 Smaug Rev 1+ (DT) +[ 43.885834] Call trace: +[ 43.888294] [<ffffffc000207464>] dump_backtrace+0x0/0x10c +[ 43.893697] [<ffffffc000207580>] show_stack+0x10/0x1c +[ 43.898756] [<ffffffc000ab1258>] dump_stack+0x74/0xb8 +[ 43.903814] [<ffffffc00021d414>] warn_slowpath_common+0x84/0xb0 +[ 43.909736] [<ffffffc00021d530>] warn_slowpath_null+0x14/0x20 +[ 43.915482] [<ffffffc00088aefc>] android_fence_release+0x84/0x104 +[ 43.921582] [<ffffffc000671cc4>] fence_release+0x104/0x134 +[ 43.927066] [<ffffffc00088b0cc>] sync_fence_free+0x74/0x9c +[ 43.932552] [<ffffffc00088b128>] sync_fence_release+0x34/0x48 +[ 43.938304] [<ffffffc000317bbc>] __fput+0x100/0x1b8 +[ 43.943185] [<ffffffc000317cc8>] ____fput+0x8/0x14 +[ 43.947982] [<ffffffc000237f38>] task_work_run+0xb0/0xe4 +[ 43.953297] [<ffffffc000207074>] do_notify_resume+0x44/0x5c +[ 43.958867] ---[ end trace 5a2aa4027cc5d171 ]--- + +Let's fix it by introducing a new optional callback (disable_signaling) +to fence operations so that drivers can do proper clean ups when we +remove last callback for given fence. + +Signed-off-by: Dmitry Torokhov <dtor@chromium.org> +Reviewed-on: https://chromium-review.googlesource.com/303409 +Reviewed-by: Andrew Bresticker <abrestic@chromium.org> +Signed-off-by: Jin Qian <jinqian@android.com> +--- + drivers/dma-buf/dma-fence.c | 6 +++++- + include/linux/dma-fence.h | 2 ++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +--- a/drivers/dma-buf/dma-fence.c ++++ b/drivers/dma-buf/dma-fence.c +@@ -332,8 +332,12 @@ dma_fence_remove_callback(struct dma_fen + spin_lock_irqsave(fence->lock, flags); + + ret = !list_empty(&cb->node); +- if (ret) ++ if (ret) { + list_del_init(&cb->node); ++ if (list_empty(&fence->cb_list)) ++ if (fence->ops->disable_signaling) ++ fence->ops->disable_signaling(fence); ++ } + + spin_unlock_irqrestore(fence->lock, flags); + +--- a/include/linux/dma-fence.h ++++ b/include/linux/dma-fence.h +@@ -109,6 +109,7 @@ struct dma_fence_cb { + * @get_driver_name: returns the driver name. + * @get_timeline_name: return the name of the context this fence belongs to. + * @enable_signaling: enable software signaling of fence. ++ * @disable_signaling: disable software signaling of fence (optional). + * @signaled: [optional] peek whether the fence is signaled, can be null. + * @wait: custom wait implementation, or dma_fence_default_wait. + * @release: [optional] called on destruction of fence, can be null +@@ -168,6 +169,7 @@ struct dma_fence_ops { + const char * (*get_driver_name)(struct dma_fence *fence); + const char * (*get_timeline_name)(struct dma_fence *fence); + bool (*enable_signaling)(struct dma_fence *fence); ++ void (*disable_signaling)(struct dma_fence *fence); + bool (*signaled)(struct dma_fence *fence); + signed long (*wait)(struct dma_fence *fence, + bool intr, signed long timeout); diff --git a/0003-goldfish-Add-goldfish-sync-driver.patch b/0003-goldfish-Add-goldfish-sync-driver.patch new file mode 100644 index 00000000000000..2bf72499f49cf8 --- /dev/null +++ b/0003-goldfish-Add-goldfish-sync-driver.patch @@ -0,0 +1,1429 @@ +From c7f0d1bafcc183f23995c4757cf9ecc9e0bd1cc8 Mon Sep 17 00:00:00 2001 +From: Lingfeng Yang <lfy@google.com> +Date: Mon, 13 Jun 2016 09:24:07 -0700 +Subject: [PATCH 3/3] goldfish: Add goldfish sync driver + +This is kernel driver for controlling the Goldfish sync +device on the host. It is used to maintain ordering +in critical OpenGL state changes while using +GPU emulation. + +The guest open()'s the Goldfish sync device to create +a context for possibly maintaining sync timeline and fences. +There is a 1:1 correspondence between such sync contexts +and OpenGL contexts in the guest that need synchronization +(which in turn, is anything involving swapping buffers, +SurfaceFlinger, or Hardware Composer). + +The ioctl QUEUE_WORK takes a handle to a sync object +and attempts to tell the host GPU to wait on the sync object +and deal with signaling it. It possibly outputs +a fence FD on which the Android systems that use them +(GLConsumer, SurfaceFlinger, anything employing +EGL_ANDROID_native_fence_sync) can use to wait. + +Design decisions and work log: + +- New approach is to have the guest issue ioctls that + trigger host wait, and then host increments timeline. +- We need the host's sync object handle and sync thread handle + as the necessary information for that. +- ioctl() from guest can work simultaneously with the + interrupt handling for commands from host. +- optimization: don't write back on timeline inc +- Change spin lock design to be much more lightweight; + do not call sw_sync functions or loop too long + anywhere. +- Send read/write commands in batches to minimize guest/host + transitions. +- robustness: BUG if we will overrun the cmd buffer. +- robustness: return fd -1 if we cannot get an unused fd. +- correctness: remove global mutex +- cleanup pass done, incl. but not limited to: + - removal of clear_upto and + - switching to devm_*** + +Signed-off-by: Dmitry Shmidt <dimitrysh@google.com> +Signed-off-by: Lingfeng Yang <lfy@google.com> +Signed-off-by: Jin Qian <jinqian@android.com> +--- + Documentation/devicetree/bindings/goldfish/sync.txt | 17 + drivers/staging/goldfish/Kconfig | 8 + drivers/staging/goldfish/Makefile | 6 + drivers/staging/goldfish/goldfish_sync_timeline.c | 980 ++++++++++++++++ + drivers/staging/goldfish/goldfish_sync_timeline_fence.c | 258 ++++ + drivers/staging/goldfish/goldfish_sync_timeline_fence.h | 72 + + 6 files changed, 1341 insertions(+) + create mode 100644 Documentation/devicetree/bindings/goldfish/sync.txt + create mode 100644 drivers/staging/goldfish/goldfish_sync_timeline.c + create mode 100644 drivers/staging/goldfish/goldfish_sync_timeline_fence.c + create mode 100644 drivers/staging/goldfish/goldfish_sync_timeline_fence.h + +--- /dev/null ++++ b/Documentation/devicetree/bindings/goldfish/sync.txt +@@ -0,0 +1,17 @@ ++Android Goldfish QEMU Sync Device ++ ++goldfish sync virtual device generated by android emulator. ++ ++Required properties: ++ ++- compatible : should contain "google,goldfish-sync" to match emulator ++- reg : <registers mapping> ++- interrupts : <interrupt mapping> ++ ++Example: ++ ++ android_pipe@a010000 { ++ compatible = "google,goldfish-sync"; ++ reg = <ff01D000 0x0100>; ++ interrupts = <0xb>; ++ }; +--- a/drivers/staging/goldfish/Kconfig ++++ b/drivers/staging/goldfish/Kconfig +@@ -4,6 +4,14 @@ config GOLDFISH_AUDIO + ---help--- + Emulated audio channel for the Goldfish Android Virtual Device + ++config GOLDFISH_SYNC ++ tristate "Goldfish AVD Sync Driver" ++ depends on GOLDFISH ++ depends on SW_SYNC ++ depends on SYNC_FILE ++ ---help--- ++ Emulated sync fences for the Goldfish Android Virtual Device ++ + config MTD_GOLDFISH_NAND + tristate "Goldfish NAND device" + depends on GOLDFISH +--- a/drivers/staging/goldfish/Makefile ++++ b/drivers/staging/goldfish/Makefile +@@ -4,3 +4,9 @@ + + obj-$(CONFIG_GOLDFISH_AUDIO) += goldfish_audio.o + obj-$(CONFIG_MTD_GOLDFISH_NAND) += goldfish_nand.o ++ ++# and sync ++ ++ccflags-y := -Idrivers/staging/android ++goldfish_sync-objs := goldfish_sync_timeline_fence.o goldfish_sync_timeline.o ++obj-$(CONFIG_GOLDFISH_SYNC) += goldfish_sync.o +--- /dev/null ++++ b/drivers/staging/goldfish/goldfish_sync_timeline.c +@@ -0,0 +1,980 @@ ++/* ++ * Copyright (C) 2016 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. ++ * ++ */ ++ ++#include <linux/fdtable.h> ++#include <linux/file.h> ++#include <linux/init.h> ++#include <linux/miscdevice.h> ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/platform_device.h> ++ ++#include <linux/interrupt.h> ++#include <linux/kref.h> ++#include <linux/spinlock.h> ++#include <linux/types.h> ++ ++#include <linux/io.h> ++#include <linux/mm.h> ++#include <linux/acpi.h> ++ ++#include <linux/string.h> ++ ++#include <linux/fs.h> ++#include <linux/syscalls.h> ++#include <linux/sync_file.h> ++#include <linux/dma-fence.h> ++ ++#include "goldfish_sync_timeline_fence.h" ++ ++#define DTRACE() pr_debug("%s: enter", __func__) ++ ++/* The Goldfish sync driver is designed to provide a interface ++ * between the underlying host's sync device and the kernel's ++ * fence sync framework.. ++ * The purpose of the device/driver is to enable lightweight ++ * creation and signaling of timelines and fences ++ * in order to synchronize the guest with host-side graphics events. ++ * ++ * Each time the interrupt trips, the driver ++ * may perform a sync operation. ++ */ ++ ++/* The operations are: */ ++ ++/* Ready signal - used to mark when irq should lower */ ++#define CMD_SYNC_READY 0 ++ ++/* Create a new timeline. writes timeline handle */ ++#define CMD_CREATE_SYNC_TIMELINE 1 ++ ++/* Create a fence object. reads timeline handle and time argument. ++ * Writes fence fd to the SYNC_REG_HANDLE register. ++ */ ++#define CMD_CREATE_SYNC_FENCE 2 ++ ++/* Increments timeline. reads timeline handle and time argument */ ++#define CMD_SYNC_TIMELINE_INC 3 ++ ++/* Destroys a timeline. reads timeline handle */ ++#define CMD_DESTROY_SYNC_TIMELINE 4 ++ ++/* Starts a wait on the host with ++ * the given glsync object and sync thread handle. ++ */ ++#define CMD_TRIGGER_HOST_WAIT 5 ++ ++/* The register layout is: */ ++ ++/* host->guest batch commands */ ++#define SYNC_REG_BATCH_COMMAND 0x00 ++/* guest->host batch commands */ ++#define SYNC_REG_BATCH_GUESTCOMMAND 0x04 ++/* communicate physical address of host->guest batch commands */ ++#define SYNC_REG_BATCH_COMMAND_ADDR 0x08 ++/* 64-bit part */ ++#define SYNC_REG_BATCH_COMMAND_ADDR_HIGH 0x0c ++/* communicate physical address of guest->host commands */ ++#define SYNC_REG_BATCH_GUESTCOMMAND_ADDR 0x10 ++/* 64-bit part */ ++#define SYNC_REG_BATCH_GUESTCOMMAND_ADDR_HIGH 0x14 ++/* signals that the device has been probed */ ++#define SYNC_REG_INIT 0x18 ++ ++/* There is an ioctl associated with goldfish sync driver. ++ * Make it conflict with ioctls that are not likely to be used ++ * in the emulator. ++ * ++ * '@' 00-0F linux/radeonfb.h conflict! ++ * '@' 00-0F drivers/video/aty/aty128fb.c conflict! ++ */ ++#define GOLDFISH_SYNC_IOC_MAGIC '@' ++ ++#define GOLDFISH_SYNC_IOC_QUEUE_WORK \ ++ _IOWR(GOLDFISH_SYNC_IOC_MAGIC, 0, struct goldfish_sync_ioctl_info) ++ ++/* The above definitions (command codes, register layout, ioctl definitions) ++ * need to be in sync with the following files: ++ * ++ * Host-side (emulator): ++ * external/qemu/android/emulation/goldfish_sync.h ++ * external/qemu-android/hw/misc/goldfish_sync.c ++ * ++ * Guest-side (system image): ++ * device/generic/goldfish-opengl/system/egl/goldfish_sync.h ++ * device/generic/goldfish/ueventd.ranchu.rc ++ * platform/build/target/board/generic/sepolicy/file_contexts ++ */ ++struct goldfish_sync_hostcmd { ++ /* sorted for alignment */ ++ u64 handle; ++ u64 hostcmd_handle; ++ u32 cmd; ++ u32 time_arg; ++}; ++ ++struct goldfish_sync_guestcmd { ++ u64 host_command; /* u64 for alignment */ ++ u64 glsync_handle; ++ u64 thread_handle; ++ u64 guest_timeline_handle; ++}; ++ ++#define GOLDFISH_SYNC_MAX_CMDS 32 ++ ++struct goldfish_sync_state { ++ char __iomem *reg_base; ++ int irq; ++ ++ /* Spinlock protects |to_do| / |to_do_end|. */ ++ spinlock_t lock; ++ /* |mutex_lock| protects all concurrent access ++ * to timelines for both kernel and user space. ++ */ ++ struct mutex mutex_lock; ++ ++ /* Buffer holding commands issued from host. */ ++ struct goldfish_sync_hostcmd to_do[GOLDFISH_SYNC_MAX_CMDS]; ++ u32 to_do_end; ++ ++ /* Addresses for the reading or writing ++ * of individual commands. The host can directly write ++ * to |batch_hostcmd| (and then this driver immediately ++ * copies contents to |to_do|). This driver either replies ++ * through |batch_hostcmd| or simply issues a ++ * guest->host command through |batch_guestcmd|. ++ */ ++ struct goldfish_sync_hostcmd *batch_hostcmd; ++ struct goldfish_sync_guestcmd *batch_guestcmd; ++ ++ /* Used to give this struct itself to a work queue ++ * function for executing actual sync commands. ++ */ ++ struct work_struct work_item; ++}; ++ ++static struct goldfish_sync_state global_sync_state[1]; ++ ++struct goldfish_sync_timeline_obj { ++ struct goldfish_sync_timeline *sync_tl; ++ u32 current_time; ++ /* We need to be careful about when we deallocate ++ * this |goldfish_sync_timeline_obj| struct. ++ * In order to ensure proper cleanup, we need to ++ * consider the triggered host-side wait that may ++ * still be in flight when the guest close()'s a ++ * goldfish_sync device's sync context fd (and ++ * destroys the |sync_tl| field above). ++ * The host-side wait may raise IRQ ++ * and tell the kernel to increment the timeline _after_ ++ * the |sync_tl| has already been set to null. ++ * ++ * From observations on OpenGL apps and CTS tests, this ++ * happens at some very low probability upon context ++ * destruction or process close, but it does happen ++ * and it needs to be handled properly. Otherwise, ++ * if we clean up the surrounding |goldfish_sync_timeline_obj| ++ * too early, any |handle| field of any host->guest command ++ * might not even point to a null |sync_tl| field, ++ * but to garbage memory or even a reclaimed |sync_tl|. ++ * If we do not count such "pending waits" and kfree the object ++ * immediately upon |goldfish_sync_timeline_destroy|, ++ * we might get mysterous RCU stalls after running a long ++ * time because the garbage memory that is being read ++ * happens to be interpretable as a |spinlock_t| struct ++ * that is currently in the locked state. ++ * ++ * To track when to free the |goldfish_sync_timeline_obj| ++ * itself, we maintain a kref. ++ * The kref essentially counts the timeline itself plus ++ * the number of waits in flight. kref_init/kref_put ++ * are issued on ++ * |goldfish_sync_timeline_create|/|goldfish_sync_timeline_destroy| ++ * and kref_get/kref_put are issued on ++ * |goldfish_sync_fence_create|/|goldfish_sync_timeline_inc|. ++ * ++ * The timeline is destroyed after reference count ++ * reaches zero, which would happen after ++ * |goldfish_sync_timeline_destroy| and all pending ++ * |goldfish_sync_timeline_inc|'s are fulfilled. ++ * ++ * NOTE (1): We assume that |fence_create| and ++ * |timeline_inc| calls are 1:1, otherwise the kref scheme ++ * will not work. This is a valid assumption as long ++ * as the host-side virtual device implementation ++ * does not insert any timeline increments ++ * that we did not trigger from here. ++ * ++ * NOTE (2): The use of kref by itself requires no locks, ++ * but this does not mean everything works without locks. ++ * Related timeline operations do require a lock of some sort, ++ * or at least are not proven to work without it. ++ * In particualr, we assume that all the operations ++ * done on the |kref| field above are done in contexts where ++ * |global_sync_state->mutex_lock| is held. Do not ++ * remove that lock until everything is proven to work ++ * without it!!! ++ */ ++ struct kref kref; ++}; ++ ++/* We will call |delete_timeline_obj| when the last reference count ++ * of the kref is decremented. This deletes the sync ++ * timeline object along with the wrapper itself. ++ */ ++static void delete_timeline_obj(struct kref *kref) ++{ ++ struct goldfish_sync_timeline_obj *obj = ++ container_of(kref, struct goldfish_sync_timeline_obj, kref); ++ ++ goldfish_sync_timeline_put_internal(obj->sync_tl); ++ obj->sync_tl = NULL; ++ kfree(obj); ++} ++ ++static u64 gensym_ctr; ++static void gensym(char *dst) ++{ ++ sprintf(dst, "goldfish_sync:gensym:%llu", gensym_ctr); ++ gensym_ctr++; ++} ++ ++/* |goldfish_sync_timeline_create| assumes that |global_sync_state->mutex_lock| ++ * is held. ++ */ ++static struct goldfish_sync_timeline_obj * ++goldfish_sync_timeline_create(void) ++{ ++ char timeline_name[256]; ++ struct goldfish_sync_timeline *res_sync_tl = NULL; ++ struct goldfish_sync_timeline_obj *res; ++ ++ DTRACE(); ++ ++ gensym(timeline_name); ++ ++ res_sync_tl = goldfish_sync_timeline_create_internal(timeline_name); ++ if (!res_sync_tl) { ++ pr_err("Failed to create goldfish_sw_sync timeline."); ++ return NULL; ++ } ++ ++ res = kzalloc(sizeof(*res), GFP_KERNEL); ++ res->sync_tl = res_sync_tl; ++ res->current_time = 0; ++ kref_init(&res->kref); ++ ++ pr_debug("new timeline_obj=0x%p", res); ++ return res; ++} ++ ++/* |goldfish_sync_fence_create| assumes that |global_sync_state->mutex_lock| ++ * is held. ++ */ ++static int ++goldfish_sync_fence_create(struct goldfish_sync_timeline_obj *obj, u32 val) ++{ ++ int fd; ++ char fence_name[256]; ++ struct sync_pt *syncpt = NULL; ++ struct sync_file *sync_file_obj = NULL; ++ struct goldfish_sync_timeline *tl; ++ ++ DTRACE(); ++ ++ if (!obj) ++ return -1; ++ ++ tl = obj->sync_tl; ++ ++ syncpt = goldfish_sync_pt_create_internal( ++ tl, sizeof(struct sync_pt) + 4, val); ++ if (!syncpt) { ++ pr_err( ++ "could not create sync point! goldfish_sync_timeline=0x%p val=%d", ++ tl, val); ++ return -1; ++ } ++ ++ fd = get_unused_fd_flags(O_CLOEXEC); ++ if (fd < 0) { ++ pr_err("could not get unused fd for sync fence. errno=%d", fd); ++ goto err_cleanup_pt; ++ } ++ ++ gensym(fence_name); ++ ++ sync_file_obj = sync_file_create(&syncpt->base); ++ if (!sync_file_obj) { ++ pr_err("could not create sync fence! goldfish_sync_timeline=0x%p val=%d sync_pt=0x%p", ++ tl, val, syncpt); ++ goto err_cleanup_fd_pt; ++ } ++ ++ pr_debug("installing sync fence into fd %d sync_file_obj=0x%p", ++ fd, sync_file_obj); ++ fd_install(fd, sync_file_obj->file); ++ kref_get(&obj->kref); ++ ++ return fd; ++ ++err_cleanup_fd_pt: ++ put_unused_fd(fd); ++err_cleanup_pt: ++ dma_fence_put(&syncpt->base); ++ return -1; ++} ++ ++/* |goldfish_sync_timeline_inc| assumes that |global_sync_state->mutex_lock| ++ * is held. ++ */ ++static void ++goldfish_sync_timeline_inc(struct goldfish_sync_timeline_obj *obj, u32 inc) ++{ ++ DTRACE(); ++ /* Just give up if someone else nuked the timeline. ++ * Whoever it was won't care that it doesn't get signaled. ++ */ ++ if (!obj) ++ return; ++ ++ pr_debug("timeline_obj=0x%p", obj); ++ goldfish_sync_timeline_signal_internal(obj->sync_tl, inc); ++ pr_debug("incremented timeline. increment max_time"); ++ obj->current_time += inc; ++ ++ /* Here, we will end up deleting the timeline object if it ++ * turns out that this call was a pending increment after ++ * |goldfish_sync_timeline_destroy| was called. ++ */ ++ kref_put(&obj->kref, delete_timeline_obj); ++ pr_debug("done"); ++} ++ ++/* |goldfish_sync_timeline_destroy| assumes ++ * that |global_sync_state->mutex_lock| is held. ++ */ ++static void ++goldfish_sync_timeline_destroy(struct goldfish_sync_timeline_obj *obj) ++{ ++ DTRACE(); ++ /* See description of |goldfish_sync_timeline_obj| for why we ++ * should not immediately destroy |obj| ++ */ ++ kref_put(&obj->kref, delete_timeline_obj); ++} ++ ++static inline void ++goldfish_sync_cmd_queue(struct goldfish_sync_state *sync_state, ++ u32 cmd, ++ u64 handle, ++ u32 time_arg, ++ u64 hostcmd_handle) ++{ ++ struct goldfish_sync_hostcmd *to_add; ++ ++ DTRACE(); ++ ++ if (WARN_ON(sync_state->to_do_end == GOLDFISH_SYNC_MAX_CMDS)) ++ return; ++ ++ to_add = &sync_state->to_do[sync_state->to_do_end]; ++ ++ to_add->cmd = cmd; ++ to_add->handle = handle; ++ to_add->time_arg = time_arg; ++ to_add->hostcmd_handle = hostcmd_handle; ++ ++ sync_state->to_do_end += 1; ++} ++ ++static inline void ++goldfish_sync_hostcmd_reply(struct goldfish_sync_state *sync_state, ++ u32 cmd, ++ u64 handle, ++ u32 time_arg, ++ u64 hostcmd_handle) ++{ ++ unsigned long irq_flags; ++ struct goldfish_sync_hostcmd *batch_hostcmd = ++ sync_state->batch_hostcmd; ++ ++ DTRACE(); ++ ++ spin_lock_irqsave(&sync_state->lock, irq_flags); ++ ++ batch_hostcmd->cmd = cmd; ++ batch_hostcmd->handle = handle; ++ batch_hostcmd->time_arg = time_arg; ++ batch_hostcmd->hostcmd_handle = hostcmd_handle; ++ writel(0, sync_state->reg_base + SYNC_REG_BATCH_COMMAND); ++ ++ spin_unlock_irqrestore(&sync_state->lock, irq_flags); ++} ++ ++static inline void ++goldfish_sync_send_guestcmd(struct goldfish_sync_state *sync_state, ++ u32 cmd, ++ u64 glsync_handle, ++ u64 thread_handle, ++ u64 timeline_handle) ++{ ++ unsigned long irq_flags; ++ struct goldfish_sync_guestcmd *batch_guestcmd = ++ sync_state->batch_guestcmd; ++ ++ DTRACE(); ++ ++ spin_lock_irqsave(&sync_state->lock, irq_flags); ++ ++ batch_guestcmd->host_command = (u64)cmd; ++ batch_guestcmd->glsync_handle = (u64)glsync_handle; ++ batch_guestcmd->thread_handle = (u64)thread_handle; ++ batch_guestcmd->guest_timeline_handle = (u64)timeline_handle; ++ writel(0, sync_state->reg_base + SYNC_REG_BATCH_GUESTCOMMAND); ++ ++ spin_unlock_irqrestore(&sync_state->lock, irq_flags); ++} ++ ++/* |goldfish_sync_interrupt| handles IRQ raises from the virtual device. ++ * In the context of OpenGL, this interrupt will fire whenever we need ++ * to signal a fence fd in the guest, with the command ++ * |CMD_SYNC_TIMELINE_INC|. ++ * However, because this function will be called in an interrupt context, ++ * it is necessary to do the actual work of signaling off of interrupt context. ++ * The shared work queue is used for this purpose. At the end when ++ * all pending commands are intercepted by the interrupt handler, ++ * we call |schedule_work|, which will later run the actual ++ * desired sync command in |goldfish_sync_work_item_fn|. ++ */ ++static irqreturn_t goldfish_sync_interrupt(int irq, void *dev_id) ++{ ++ struct goldfish_sync_state *sync_state = dev_id; ++ ++ u32 nextcmd; ++ u32 command_r; ++ u64 handle_rw; ++ u32 time_r; ++ u64 hostcmd_handle_rw; ++ ++ int count = 0; ++ ++ DTRACE(); ++ ++ sync_state = dev_id; ++ ++ spin_lock(&sync_state->lock); ++ ++ for (;;) { ++ readl(sync_state->reg_base + SYNC_REG_BATCH_COMMAND); ++ nextcmd = sync_state->batch_hostcmd->cmd; ++ ++ if (nextcmd == 0) ++ break; ++ ++ command_r = nextcmd; ++ handle_rw = sync_state->batch_hostcmd->handle; ++ time_r = sync_state->batch_hostcmd->time_arg; ++ hostcmd_handle_rw = sync_state->batch_hostcmd->hostcmd_handle; ++ ++ goldfish_sync_cmd_queue( ++ sync_state, ++ command_r, ++ handle_rw, ++ time_r, ++ hostcmd_handle_rw); ++ ++ count++; ++ } ++ ++ spin_unlock(&sync_state->lock); ++ ++ schedule_work(&sync_state->work_item); ++ ++ return (count == 0) ? IRQ_NONE : IRQ_HANDLED; ++} ++ ++/* |goldfish_sync_work_item_fn| does the actual work of servicing ++ * host->guest sync commands. This function is triggered whenever ++ * the IRQ for the goldfish sync device is raised. Once it starts ++ * running, it grabs the contents of the buffer containing the ++ * commands it needs to execute (there may be multiple, because ++ * our IRQ is active high and not edge triggered), and then ++ * runs all of them one after the other. ++ */ ++static void goldfish_sync_work_item_fn(struct work_struct *input) ++{ ++ struct goldfish_sync_state *sync_state; ++ int sync_fence_fd; ++ ++ struct goldfish_sync_timeline_obj *timeline; ++ u64 timeline_ptr; ++ ++ u64 hostcmd_handle; ++ ++ u32 cmd; ++ u64 handle; ++ u32 time_arg; ++ ++ struct goldfish_sync_hostcmd *todo; ++ u32 todo_end; ++ ++ unsigned long irq_flags; ++ ++ struct goldfish_sync_hostcmd to_run[GOLDFISH_SYNC_MAX_CMDS]; ++ u32 i = 0; ++ ++ sync_state = container_of(input, struct goldfish_sync_state, work_item); ++ ++ mutex_lock(&sync_state->mutex_lock); ++ ++ spin_lock_irqsave(&sync_state->lock, irq_flags); { ++ todo_end = sync_state->to_do_end; ++ ++ pr_debug("num sync todos: %u", sync_state->to_do_end); ++ ++ for (i = 0; i < todo_end; i++) ++ to_run[i] = sync_state->to_do[i]; ++ ++ /* We expect that commands will come in at a slow enough rate ++ * so that incoming items will not be more than ++ * GOLDFISH_SYNC_MAX_CMDS. ++ * ++ * This is because the way the sync device is used, ++ * it's only for managing buffer data transfers per frame, ++ * with a sequential dependency between putting things in ++ * to_do and taking them out. Once a set of commands is ++ * queued up in to_do, the user of the device waits for ++ * them to be processed before queuing additional commands, ++ * which limits the rate at which commands come in ++ * to the rate at which we take them out here. ++ * ++ * We also don't expect more than MAX_CMDS to be issued ++ * at once; there is a correspondence between ++ * which buffers need swapping to the (display / buffer queue) ++ * to particular commands, and we don't expect there to be ++ * enough display or buffer queues in operation at once ++ * to overrun GOLDFISH_SYNC_MAX_CMDS. ++ */ ++ sync_state->to_do_end = 0; ++ ++ } spin_unlock_irqrestore(&sync_state->lock, irq_flags); ++ ++ for (i = 0; i < todo_end; i++) { ++ pr_debug("todo index: %u", i); ++ ++ todo = &to_run[i]; ++ ++ cmd = todo->cmd; ++ ++ handle = (u64)todo->handle; ++ time_arg = todo->time_arg; ++ hostcmd_handle = (u64)todo->hostcmd_handle; ++ ++ DTRACE(); ++ ++ timeline = ++ (struct goldfish_sync_timeline_obj *)(uintptr_t)handle; ++ ++ switch (cmd) { ++ case CMD_SYNC_READY: ++ break; ++ case CMD_CREATE_SYNC_TIMELINE: ++ pr_debug("exec CMD_CREATE_SYNC_TIMELINE: handle=0x%llx time_arg=%d", ++ handle, time_arg); ++ timeline = goldfish_sync_timeline_create(); ++ timeline_ptr = (uintptr_t)timeline; ++ goldfish_sync_hostcmd_reply(sync_state, ++ CMD_CREATE_SYNC_TIMELINE, ++ timeline_ptr, ++ 0, ++ hostcmd_handle); ++ pr_debug("sync timeline created: %p", timeline); ++ break; ++ case CMD_CREATE_SYNC_FENCE: ++ pr_debug("exec CMD_CREATE_SYNC_FENCE: handle=0x%llx time_arg=%d", ++ handle, time_arg); ++ sync_fence_fd = goldfish_sync_fence_create( ++ timeline, time_arg); ++ goldfish_sync_hostcmd_reply(sync_state, ++ CMD_CREATE_SYNC_FENCE, ++ sync_fence_fd, ++ 0, ++ hostcmd_handle); ++ break; ++ case CMD_SYNC_TIMELINE_INC: ++ pr_debug("exec CMD_SYNC_TIMELINE_INC: handle=0x%llx time_arg=%d", ++ handle, time_arg); ++ goldfish_sync_timeline_inc(timeline, time_arg); ++ break; ++ case CMD_DESTROY_SYNC_TIMELINE: ++ pr_debug("exec CMD_DESTROY_SYNC_TIMELINE: handle=0x%llx time_arg=%d", ++ handle, time_arg); ++ goldfish_sync_timeline_destroy(timeline); ++ break; ++ } ++ pr_debug("Done executing sync command"); ++ } ++ mutex_unlock(&sync_state->mutex_lock); ++} ++ ++/* Guest-side interface: file operations */ ++ ++/* Goldfish sync context and ioctl info. ++ * ++ * When a sync context is created by open()-ing the goldfish sync device, we ++ * create a sync context (|goldfish_sync_context|). ++ * ++ * Currently, the only data required to track is the sync timeline itself ++ * along with the current time, which are all packed up in the ++ * |goldfish_sync_timeline_obj| field. We use a |goldfish_sync_context| ++ * as the filp->private_data. ++ * ++ * Next, when a sync context user requests that work be queued and a fence ++ * fd provided, we use the |goldfish_sync_ioctl_info| struct, which holds ++ * information about which host handles to touch for this particular ++ * queue-work operation. We need to know about the host-side sync thread ++ * and the particular host-side GLsync object. We also possibly write out ++ * a file descriptor. ++ */ ++struct goldfish_sync_context { ++ struct goldfish_sync_timeline_obj *timeline; ++}; ++ ++struct goldfish_sync_ioctl_info { ++ u64 host_glsync_handle_in; ++ u64 host_syncthread_handle_in; ++ int fence_fd_out; ++}; ++ ++static int goldfish_sync_open(struct inode *inode, struct file *file) ++{ ++ struct goldfish_sync_context *sync_context; ++ ++ DTRACE(); ++ ++ mutex_lock(&global_sync_state->mutex_lock); ++ ++ sync_context = kzalloc(sizeof(*sync_context), ++ GFP_KERNEL); ++ ++ if (!sync_context) { ++ pr_err("Creation of goldfish sync context failed!"); ++ mutex_unlock(&global_sync_state->mutex_lock); ++ return -ENOMEM; ++ } ++ ++ sync_context->timeline = NULL; ++ ++ file->private_data = sync_context; ++ ++ pr_debug("successfully create a sync context @0x%p", sync_context); ++ ++ mutex_unlock(&global_sync_state->mutex_lock); ++ ++ return 0; ++} ++ ++static int goldfish_sync_release(struct inode *inode, struct file *file) ++{ ++ struct goldfish_sync_context *sync_context; ++ ++ DTRACE(); ++ ++ mutex_lock(&global_sync_state->mutex_lock); ++ ++ sync_context = file->private_data; ++ ++ if (sync_context->timeline) ++ goldfish_sync_timeline_destroy(sync_context->timeline); ++ ++ sync_context->timeline = NULL; ++ ++ kfree(sync_context); ++ ++ mutex_unlock(&global_sync_state->mutex_lock); ++ ++ return 0; ++} ++ ++/* |goldfish_sync_ioctl| is the guest-facing interface of goldfish sync ++ * and is used in conjunction with eglCreateSyncKHR to queue up the ++ * actual work of waiting for the EGL sync command to complete, ++ * possibly returning a fence fd to the guest. ++ */ ++static long goldfish_sync_ioctl(struct file *file, ++ unsigned int cmd, ++ unsigned long arg) ++{ ++ struct goldfish_sync_context *sync_context_data; ++ struct goldfish_sync_timeline_obj *timeline; ++ int fd_out; ++ struct goldfish_sync_ioctl_info ioctl_data; ++ ++ DTRACE(); ++ ++ sync_context_data = file->private_data; ++ fd_out = -1; ++ ++ switch (cmd) { ++ case GOLDFISH_SYNC_IOC_QUEUE_WORK: ++ ++ pr_debug("exec GOLDFISH_SYNC_IOC_QUEUE_WORK"); ++ ++ mutex_lock(&global_sync_state->mutex_lock); ++ ++ if (copy_from_user(&ioctl_data, ++ (void __user *)arg, ++ sizeof(ioctl_data))) { ++ pr_err("Failed to copy memory for ioctl_data from user."); ++ mutex_unlock(&global_sync_state->mutex_lock); ++ return -EFAULT; ++ } ++ ++ if (ioctl_data.host_syncthread_handle_in == 0) { ++ pr_debug("Error: zero host syncthread handle!!!"); ++ mutex_unlock(&global_sync_state->mutex_lock); ++ return -EFAULT; ++ } ++ ++ if (!sync_context_data->timeline) { ++ pr_debug("no timeline yet, create one."); ++ sync_context_data->timeline = ++ goldfish_sync_timeline_create(); ++ pr_debug("timeline: 0x%p", ++ &sync_context_data->timeline); ++ } ++ ++ timeline = sync_context_data->timeline; ++ fd_out = goldfish_sync_fence_create(timeline, ++ timeline->current_time + 1); ++ pr_debug("Created fence with fd %d and current time %u (timeline: 0x%p)", ++ fd_out, ++ sync_context_data->timeline->current_time + 1, ++ sync_context_data->timeline); ++ ++ ioctl_data.fence_fd_out = fd_out; ++ ++ if (copy_to_user((void __user *)arg, ++ &ioctl_data, ++ sizeof(ioctl_data))) { ++ pr_debug("Error, could not copy to user!!!"); ++ ++ sys_close(fd_out); ++ /* We won't be doing an increment, kref_put ++ * immediately. ++ */ ++ kref_put(&timeline->kref, delete_timeline_obj); ++ mutex_unlock(&global_sync_state->mutex_lock); ++ return -EFAULT; ++ } ++ ++ /* We are now about to trigger a host-side wait; ++ * accumulate on |pending_waits|. ++ */ ++ goldfish_sync_send_guestcmd( ++ global_sync_state, ++ CMD_TRIGGER_HOST_WAIT, ++ ioctl_data.host_glsync_handle_in, ++ ioctl_data.host_syncthread_handle_in, ++ (u64)(uintptr_t)(sync_context_data->timeline)); ++ ++ mutex_unlock(&global_sync_state->mutex_lock); ++ return 0; ++ default: ++ return -ENOTTY; ++ } ++} ++ ++static const struct file_operations goldfish_sync_fops = { ++ .owner = THIS_MODULE, ++ .open = goldfish_sync_open, ++ .release = goldfish_sync_release, ++ .unlocked_ioctl = goldfish_sync_ioctl, ++ .compat_ioctl = goldfish_sync_ioctl, ++}; ++ ++static struct miscdevice goldfish_sync_device = { ++ .name = "goldfish_sync", ++ .fops = &goldfish_sync_fops, ++}; ++ ++static bool setup_verify_batch_cmd_addr(struct goldfish_sync_state *sync_state, ++ void *batch_addr, ++ u32 addr_offset, ++ u32 addr_offset_high) ++{ ++ u64 batch_addr_phys; ++ u32 batch_addr_phys_test_lo; ++ u32 batch_addr_phys_test_hi; ++ ++ if (!batch_addr) { ++ pr_err("Could not use batch command address!"); ++ return false; ++ } ++ ++ batch_addr_phys = virt_to_phys(batch_addr); ++ writel((u32)(batch_addr_phys), ++ sync_state->reg_base + addr_offset); ++ writel((u32)(batch_addr_phys >> 32), ++ sync_state->reg_base + addr_offset_high); ++ ++ batch_addr_phys_test_lo = ++ readl(sync_state->reg_base + addr_offset); ++ batch_addr_phys_test_hi = ++ readl(sync_state->reg_base + addr_offset_high); ++ ++ if (virt_to_phys(batch_addr) != ++ (((u64)batch_addr_phys_test_hi << 32) | ++ batch_addr_phys_test_lo)) { ++ pr_err("Invalid batch command address!"); ++ return false; ++ } ++ ++ return true; ++} ++ ++int goldfish_sync_probe(struct platform_device *pdev) ++{ ++ struct resource *ioresource; ++ struct goldfish_sync_state *sync_state = global_sync_state; ++ int status; ++ ++ DTRACE(); ++ ++ sync_state->to_do_end = 0; ++ ++ spin_lock_init(&sync_state->lock); ++ mutex_init(&sync_state->mutex_lock); ++ ++ platform_set_drvdata(pdev, sync_state); ++ ++ ioresource = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!ioresource) { ++ pr_err("platform_get_resource failed"); ++ return -ENODEV; ++ } ++ ++ sync_state->reg_base = ++ devm_ioremap(&pdev->dev, ioresource->start, PAGE_SIZE); ++ if (!sync_state->reg_base) { ++ pr_err("Could not ioremap"); ++ return -ENOMEM; ++ } ++ ++ sync_state->irq = platform_get_irq(pdev, 0); ++ if (sync_state->irq < 0) { ++ pr_err("Could not platform_get_irq"); ++ return -ENODEV; ++ } ++ ++ status = devm_request_irq(&pdev->dev, ++ sync_state->irq, ++ goldfish_sync_interrupt, ++ IRQF_SHARED, ++ pdev->name, ++ sync_state); ++ if (status) { ++ pr_err("request_irq failed"); ++ return -ENODEV; ++ } ++ ++ INIT_WORK(&sync_state->work_item, ++ goldfish_sync_work_item_fn); ++ ++ misc_register(&goldfish_sync_device); ++ ++ /* Obtain addresses for batch send/recv of commands. */ ++ { ++ struct goldfish_sync_hostcmd *batch_addr_hostcmd; ++ struct goldfish_sync_guestcmd *batch_addr_guestcmd; ++ ++ batch_addr_hostcmd = ++ devm_kzalloc(&pdev->dev, ++ sizeof(struct goldfish_sync_hostcmd), ++ GFP_KERNEL); ++ batch_addr_guestcmd = ++ devm_kzalloc(&pdev->dev, ++ sizeof(struct goldfish_sync_guestcmd), ++ GFP_KERNEL); ++ ++ if (!setup_verify_batch_cmd_addr( ++ sync_state, ++ batch_addr_hostcmd, ++ SYNC_REG_BATCH_COMMAND_ADDR, ++ SYNC_REG_BATCH_COMMAND_ADDR_HIGH)) { ++ pr_err("goldfish_sync: Could not setup batch command address"); ++ return -ENODEV; ++ } ++ ++ if (!setup_verify_batch_cmd_addr( ++ sync_state, ++ batch_addr_guestcmd, ++ SYNC_REG_BATCH_GUESTCOMMAND_ADDR, ++ SYNC_REG_BATCH_GUESTCOMMAND_ADDR_HIGH)) { ++ pr_err("goldfish_sync: Could not setup batch guest command address"); ++ return -ENODEV; ++ } ++ ++ sync_state->batch_hostcmd = batch_addr_hostcmd; ++ sync_state->batch_guestcmd = batch_addr_guestcmd; ++ } ++ ++ pr_info("goldfish_sync: Initialized goldfish sync device"); ++ ++ writel(0, sync_state->reg_base + SYNC_REG_INIT); ++ ++ return 0; ++} ++ ++static int goldfish_sync_remove(struct platform_device *pdev) ++{ ++ struct goldfish_sync_state *sync_state = global_sync_state; ++ ++ DTRACE(); ++ ++ misc_deregister(&goldfish_sync_device); ++ memset(sync_state, 0, sizeof(struct goldfish_sync_state)); ++ return 0; ++} ++ ++static const struct of_device_id goldfish_sync_of_match[] = { ++ { .compatible = "google,goldfish-sync", }, ++ {}, ++}; ++MODULE_DEVICE_TABLE(of, goldfish_sync_of_match); ++ ++static const struct acpi_device_id goldfish_sync_acpi_match[] = { ++ { "GFSH0006", 0 }, ++ { }, ++}; ++ ++MODULE_DEVICE_TABLE(acpi, goldfish_sync_acpi_match); ++ ++static struct platform_driver goldfish_sync = { ++ .probe = goldfish_sync_probe, ++ .remove = goldfish_sync_remove, ++ .driver = { ++ .name = "goldfish_sync", ++ .of_match_table = goldfish_sync_of_match, ++ .acpi_match_table = ACPI_PTR(goldfish_sync_acpi_match), ++ } ++}; ++ ++module_platform_driver(goldfish_sync); ++ ++MODULE_AUTHOR("Google, Inc."); ++MODULE_DESCRIPTION("Android QEMU Sync Driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.0"); +--- /dev/null ++++ b/drivers/staging/goldfish/goldfish_sync_timeline_fence.c +@@ -0,0 +1,258 @@ ++/* ++ * Timeline-based sync for Goldfish Sync ++ * Based on "Sync File validation framework" ++ * (drivers/dma-buf/sw_sync.c) ++ * ++ * Copyright (C) 2017 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. ++ * ++ */ ++ ++#include <linux/slab.h> ++#include <linux/fs.h> ++#include <linux/syscalls.h> ++#include <linux/sync_file.h> ++#include <linux/dma-fence.h> ++ ++#include "goldfish_sync_timeline_fence.h" ++ ++/** ++ * struct goldfish_sync_timeline - sync object ++ * @kref: reference count on fence. ++ * @name: name of the goldfish_sync_timeline. Useful for debugging ++ * @child_list_head: list of children sync_pts for goldfish_sync_timeline ++ * @child_list_lock: lock protecting @child_list_head and fence.status ++ * @active_list_head: list of active (unsignaled/errored) sync_pts ++ */ ++struct goldfish_sync_timeline { ++ struct kref kref; ++ char name[32]; ++ ++ /* protected by child_list_lock */ ++ u64 context; ++ int value; ++ ++ struct list_head child_list_head; ++ /* protecting @child_list_head and fence.status */ ++ spinlock_t child_list_lock; ++ ++ struct list_head active_list_head; ++}; ++ ++static inline struct goldfish_sync_timeline *fence_parent( ++ struct dma_fence *fence) ++{ ++ return container_of(fence->lock, struct goldfish_sync_timeline, ++ child_list_lock); ++} ++ ++static const struct dma_fence_ops goldfish_sync_timeline_fence_ops; ++ ++static inline struct sync_pt *goldfish_sync_fence_to_sync_pt( ++ struct dma_fence *fence) ++{ ++ if (fence->ops != &goldfish_sync_timeline_fence_ops) ++ return NULL; ++ return container_of(fence, struct sync_pt, base); ++} ++ ++/** ++ * goldfish_sync_timeline_create_internal() - creates a sync object ++ * @name: sync_timeline name ++ * ++ * Creates a new sync_timeline. Returns the sync_timeline object or NULL in ++ * case of error. ++ */ ++struct goldfish_sync_timeline ++*goldfish_sync_timeline_create_internal(const char *name) ++{ ++ struct goldfish_sync_timeline *obj; ++ ++ obj = kzalloc(sizeof(*obj), GFP_KERNEL); ++ if (!obj) ++ return NULL; ++ ++ kref_init(&obj->kref); ++ obj->context = dma_fence_context_alloc(1); ++ strlcpy(obj->name, name, sizeof(obj->name)); ++ ++ INIT_LIST_HEAD(&obj->child_list_head); ++ INIT_LIST_HEAD(&obj->active_list_head); ++ spin_lock_init(&obj->child_list_lock); ++ ++ return obj; ++} ++ ++static void goldfish_sync_timeline_free_internal(struct kref *kref) ++{ ++ struct goldfish_sync_timeline *obj = ++ container_of(kref, struct goldfish_sync_timeline, kref); ++ ++ kfree(obj); ++} ++ ++static void goldfish_sync_timeline_get_internal( ++ struct goldfish_sync_timeline *obj) ++{ ++ kref_get(&obj->kref); ++} ++ ++void goldfish_sync_timeline_put_internal(struct goldfish_sync_timeline *obj) ++{ ++ kref_put(&obj->kref, goldfish_sync_timeline_free_internal); ++} ++ ++/** ++ * goldfish_sync_timeline_signal() - ++ * signal a status change on a goldfish_sync_timeline ++ * @obj: sync_timeline to signal ++ * @inc: num to increment on timeline->value ++ * ++ * A sync implementation should call this any time one of it's fences ++ * has signaled or has an error condition. ++ */ ++void goldfish_sync_timeline_signal_internal( ++ struct goldfish_sync_timeline *obj, unsigned int inc) ++{ ++ unsigned long flags; ++ struct sync_pt *pt, *next; ++ ++ spin_lock_irqsave(&obj->child_list_lock, flags); ++ ++ obj->value += inc; ++ ++ list_for_each_entry_safe(pt, next, &obj->active_list_head, ++ active_list) { ++ if (dma_fence_is_signaled_locked(&pt->base)) ++ list_del_init(&pt->active_list); ++ } ++ ++ spin_unlock_irqrestore(&obj->child_list_lock, flags); ++} ++ ++/** ++ * goldfish_sync_pt_create_internal() - creates a sync pt ++ * @parent: fence's parent sync_timeline ++ * @size: size to allocate for this pt ++ * @inc: value of the fence ++ * ++ * Creates a new sync_pt as a child of @parent. @size bytes will be ++ * allocated allowing for implementation specific data to be kept after ++ * the generic sync_timeline struct. Returns the sync_pt object or ++ * NULL in case of error. ++ */ ++struct sync_pt *goldfish_sync_pt_create_internal( ++ struct goldfish_sync_timeline *obj, int size, unsigned int value) ++{ ++ unsigned long flags; ++ struct sync_pt *pt; ++ ++ if (size < sizeof(*pt)) ++ return NULL; ++ ++ pt = kzalloc(size, GFP_KERNEL); ++ if (!pt) ++ return NULL; ++ ++ spin_lock_irqsave(&obj->child_list_lock, flags); ++ goldfish_sync_timeline_get_internal(obj); ++ dma_fence_init(&pt->base, &goldfish_sync_timeline_fence_ops, ++ &obj->child_list_lock, obj->context, value); ++ list_add_tail(&pt->child_list, &obj->child_list_head); ++ INIT_LIST_HEAD(&pt->active_list); ++ spin_unlock_irqrestore(&obj->child_list_lock, flags); ++ return pt; ++} ++ ++static const char *goldfish_sync_timeline_fence_get_driver_name( ++ struct dma_fence *fence) ++{ ++ return "sw_sync"; ++} ++ ++static const char *goldfish_sync_timeline_fence_get_timeline_name( ++ struct dma_fence *fence) ++{ ++ struct goldfish_sync_timeline *parent = fence_parent(fence); ++ ++ return parent->name; ++} ++ ++static void goldfish_sync_timeline_fence_release(struct dma_fence *fence) ++{ ++ struct sync_pt *pt = goldfish_sync_fence_to_sync_pt(fence); ++ struct goldfish_sync_timeline *parent = fence_parent(fence); ++ unsigned long flags; ++ ++ spin_lock_irqsave(fence->lock, flags); ++ list_del(&pt->child_list); ++ if (!list_empty(&pt->active_list)) ++ list_del(&pt->active_list); ++ spin_unlock_irqrestore(fence->lock, flags); ++ ++ goldfish_sync_timeline_put_internal(parent); ++ dma_fence_free(fence); ++} ++ ++static bool goldfish_sync_timeline_fence_signaled(struct dma_fence *fence) ++{ ++ struct goldfish_sync_timeline *parent = fence_parent(fence); ++ ++ return (fence->seqno > parent->value) ? false : true; ++} ++ ++static bool goldfish_sync_timeline_fence_enable_signaling( ++ struct dma_fence *fence) ++{ ++ struct sync_pt *pt = goldfish_sync_fence_to_sync_pt(fence); ++ struct goldfish_sync_timeline *parent = fence_parent(fence); ++ ++ if (goldfish_sync_timeline_fence_signaled(fence)) ++ return false; ++ ++ list_add_tail(&pt->active_list, &parent->active_list_head); ++ return true; ++} ++ ++static void goldfish_sync_timeline_fence_disable_signaling( ++ struct dma_fence *fence) ++{ ++ struct sync_pt *pt = container_of(fence, struct sync_pt, base); ++ ++ list_del_init(&pt->active_list); ++} ++ ++static void goldfish_sync_timeline_fence_value_str( ++ struct dma_fence *fence, char *str, int size) ++{ ++ snprintf(str, size, "%d", fence->seqno); ++} ++ ++static void goldfish_sync_timeline_fence_timeline_value_str( ++ struct dma_fence *fence, ++ char *str, int size) ++{ ++ struct goldfish_sync_timeline *parent = fence_parent(fence); ++ ++ snprintf(str, size, "%d", parent->value); ++} ++ ++static const struct dma_fence_ops goldfish_sync_timeline_fence_ops = { ++ .get_driver_name = goldfish_sync_timeline_fence_get_driver_name, ++ .get_timeline_name = goldfish_sync_timeline_fence_get_timeline_name, ++ .enable_signaling = goldfish_sync_timeline_fence_enable_signaling, ++ .disable_signaling = goldfish_sync_timeline_fence_disable_signaling, ++ .signaled = goldfish_sync_timeline_fence_signaled, ++ .wait = dma_fence_default_wait, ++ .release = goldfish_sync_timeline_fence_release, ++ .fence_value_str = goldfish_sync_timeline_fence_value_str, ++ .timeline_value_str = goldfish_sync_timeline_fence_timeline_value_str, ++}; +--- /dev/null ++++ b/drivers/staging/goldfish/goldfish_sync_timeline_fence.h +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (C) 2016 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. ++ * ++ */ ++ ++#include <linux/sync_file.h> ++#include <linux/dma-fence.h> ++ ++/** ++ * struct sync_pt - sync_pt object ++ * @base: base fence object ++ * @child_list: sync timeline child's list ++ * @active_list: sync timeline active child's list ++ */ ++struct sync_pt { ++ struct dma_fence base; ++ struct list_head child_list; ++ struct list_head active_list; ++}; ++ ++/** ++ * goldfish_sync_timeline_create_internal() - creates a sync object ++ * @name: goldfish_sync_timeline name ++ * ++ * Creates a new goldfish_sync_timeline. ++ * Returns the goldfish_sync_timeline object or NULL in case of error. ++ */ ++struct goldfish_sync_timeline ++*goldfish_sync_timeline_create_internal(const char *name); ++ ++/** ++ * goldfish_sync_pt_create_internal() - creates a sync pt ++ * @parent: fence's parent goldfish_sync_timeline ++ * @size: size to allocate for this pt ++ * @inc: value of the fence ++ * ++ * Creates a new sync_pt as a child of @parent. @size bytes will be ++ * allocated allowing for implementation specific data to be kept after ++ * the generic sync_timeline struct. Returns the sync_pt object or ++ * NULL in case of error. ++ */ ++struct sync_pt ++*goldfish_sync_pt_create_internal( ++ struct goldfish_sync_timeline *obj, int size, unsigned int value); ++ ++/** ++ * goldfish_sync_timeline_signal_internal() - ++ * signal a status change on a sync_timeline ++ * @obj: goldfish_sync_timeline to signal ++ * @inc: num to increment on timeline->value ++ * ++ * A sync implementation should call this any time one of it's fences ++ * has signaled or has an error condition. ++ */ ++void goldfish_sync_timeline_signal_internal( ++ struct goldfish_sync_timeline *obj, unsigned int inc); ++ ++/** ++ * goldfish_sync_timeline_put_internal() - dec refcount of a sync_timeline ++ * and clean up memory if it was the last ref. ++ * @obj: goldfish_sync_timeline to decref ++ */ ++void goldfish_sync_timeline_put_internal(struct goldfish_sync_timeline *obj); @@ -1,3 +1,6 @@ +0001-goldfish_pipe-An-implementation-of-more-parallel-pip.patch +0002-CHROMIUM-android-fix-warning-when-releasing-active-s.patch +0003-goldfish-Add-goldfish-sync-driver.patch eventpoll.h-fix-epoll-event-masks.patch eventpoll.h-add-missing-epoll-event-masks.patch 0001-drbd-rename-usermode_helper-to-drbd_usermode_helper.patch |
