1c3c4e307SRoman Kiryanov // SPDX-License-Identifier: GPL-2.0 2c89f2750SDavid 'Digit' Turner /* 3c89f2750SDavid 'Digit' Turner * Copyright (C) 2012 Intel, Inc. 4c89f2750SDavid 'Digit' Turner * Copyright (C) 2013 Intel, Inc. 52f3be882SChristoffer Dall * Copyright (C) 2014 Linaro Limited 6726ea1a8SJin Qian * Copyright (C) 2011-2016 Google, Inc. 7c89f2750SDavid 'Digit' Turner * 8c89f2750SDavid 'Digit' Turner * This software is licensed under the terms of the GNU General Public 9c89f2750SDavid 'Digit' Turner * License version 2, as published by the Free Software Foundation, and 10c89f2750SDavid 'Digit' Turner * may be copied, distributed, and modified under those terms. 11c89f2750SDavid 'Digit' Turner * 12c89f2750SDavid 'Digit' Turner * This program is distributed in the hope that it will be useful, 13c89f2750SDavid 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of 14c89f2750SDavid 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15c89f2750SDavid 'Digit' Turner * GNU General Public License for more details. 16c89f2750SDavid 'Digit' Turner * 17c89f2750SDavid 'Digit' Turner */ 18c89f2750SDavid 'Digit' Turner 19c89f2750SDavid 'Digit' Turner /* This source file contains the implementation of a special device driver 20c89f2750SDavid 'Digit' Turner * that intends to provide a *very* fast communication channel between the 21c89f2750SDavid 'Digit' Turner * guest system and the QEMU emulator. 22c89f2750SDavid 'Digit' Turner * 23c89f2750SDavid 'Digit' Turner * Usage from the guest is simply the following (error handling simplified): 24c89f2750SDavid 'Digit' Turner * 25c89f2750SDavid 'Digit' Turner * int fd = open("/dev/qemu_pipe",O_RDWR); 26c89f2750SDavid 'Digit' Turner * .... write() or read() through the pipe. 27c89f2750SDavid 'Digit' Turner * 28c89f2750SDavid 'Digit' Turner * This driver doesn't deal with the exact protocol used during the session. 29c89f2750SDavid 'Digit' Turner * It is intended to be as simple as something like: 30c89f2750SDavid 'Digit' Turner * 31c89f2750SDavid 'Digit' Turner * // do this _just_ after opening the fd to connect to a specific 32c89f2750SDavid 'Digit' Turner * // emulator service. 33c89f2750SDavid 'Digit' Turner * const char* msg = "<pipename>"; 34c89f2750SDavid 'Digit' Turner * if (write(fd, msg, strlen(msg)+1) < 0) { 35c89f2750SDavid 'Digit' Turner * ... could not connect to <pipename> service 36c89f2750SDavid 'Digit' Turner * close(fd); 37c89f2750SDavid 'Digit' Turner * } 38c89f2750SDavid 'Digit' Turner * 39c89f2750SDavid 'Digit' Turner * // after this, simply read() and write() to communicate with the 40c89f2750SDavid 'Digit' Turner * // service. Exact protocol details left as an exercise to the reader. 41c89f2750SDavid 'Digit' Turner * 42c89f2750SDavid 'Digit' Turner * This driver is very fast because it doesn't copy any data through 43c89f2750SDavid 'Digit' Turner * intermediate buffers, since the emulator is capable of translating 44c89f2750SDavid 'Digit' Turner * guest user addresses into host ones. 45c89f2750SDavid 'Digit' Turner * 46c89f2750SDavid 'Digit' Turner * Note that we must however ensure that each user page involved in the 47c89f2750SDavid 'Digit' Turner * exchange is properly mapped during a transfer. 48c89f2750SDavid 'Digit' Turner */ 49c89f2750SDavid 'Digit' Turner 50c89f2750SDavid 'Digit' Turner #include <linux/module.h> 51ac316725SRandy Dunlap #include <linux/mod_devicetable.h> 52c89f2750SDavid 'Digit' Turner #include <linux/interrupt.h> 53c89f2750SDavid 'Digit' Turner #include <linux/kernel.h> 54c89f2750SDavid 'Digit' Turner #include <linux/spinlock.h> 55c89f2750SDavid 'Digit' Turner #include <linux/miscdevice.h> 56c89f2750SDavid 'Digit' Turner #include <linux/platform_device.h> 57c89f2750SDavid 'Digit' Turner #include <linux/poll.h> 58c89f2750SDavid 'Digit' Turner #include <linux/sched.h> 59c89f2750SDavid 'Digit' Turner #include <linux/bitops.h> 60c89f2750SDavid 'Digit' Turner #include <linux/slab.h> 61c89f2750SDavid 'Digit' Turner #include <linux/io.h> 621d427da1SShraddha Barke #include <linux/dma-mapping.h> 632f3be882SChristoffer Dall #include <linux/mm.h> 64d62f324bSJason Hu #include <linux/acpi.h> 65d23069a5SRoman Kiryanov #include <linux/bug.h> 6695577010SRoman Kiryanov #include "goldfish_pipe_qemu.h" 67c89f2750SDavid 'Digit' Turner 68c89f2750SDavid 'Digit' Turner /* 69726ea1a8SJin Qian * Update this when something changes in the driver's behavior so the host 70726ea1a8SJin Qian * can benefit from knowing it 71726ea1a8SJin Qian */ 72726ea1a8SJin Qian enum { 73726ea1a8SJin Qian PIPE_DRIVER_VERSION = 2, 74726ea1a8SJin Qian PIPE_CURRENT_DEVICE_VERSION = 2 75726ea1a8SJin Qian }; 76726ea1a8SJin Qian 77726ea1a8SJin Qian enum { 78726ea1a8SJin Qian MAX_BUFFERS_PER_COMMAND = 336, 79726ea1a8SJin Qian MAX_SIGNALLED_PIPES = 64, 80726ea1a8SJin Qian INITIAL_PIPES_CAPACITY = 64 81726ea1a8SJin Qian }; 82726ea1a8SJin Qian 83726ea1a8SJin Qian struct goldfish_pipe_dev; 84726ea1a8SJin Qian 85726ea1a8SJin Qian /* A per-pipe command structure, shared with the host */ 86726ea1a8SJin Qian struct goldfish_pipe_command { 87726ea1a8SJin Qian s32 cmd; /* PipeCmdCode, guest -> host */ 88726ea1a8SJin Qian s32 id; /* pipe id, guest -> host */ 89726ea1a8SJin Qian s32 status; /* command execution status, host -> guest */ 90726ea1a8SJin Qian s32 reserved; /* to pad to 64-bit boundary */ 91726ea1a8SJin Qian union { 92726ea1a8SJin Qian /* Parameters for PIPE_CMD_{READ,WRITE} */ 93726ea1a8SJin Qian struct { 94726ea1a8SJin Qian /* number of buffers, guest -> host */ 95726ea1a8SJin Qian u32 buffers_count; 96726ea1a8SJin Qian /* number of consumed bytes, host -> guest */ 97726ea1a8SJin Qian s32 consumed_size; 98726ea1a8SJin Qian /* buffer pointers, guest -> host */ 99726ea1a8SJin Qian u64 ptrs[MAX_BUFFERS_PER_COMMAND]; 100726ea1a8SJin Qian /* buffer sizes, guest -> host */ 101726ea1a8SJin Qian u32 sizes[MAX_BUFFERS_PER_COMMAND]; 102726ea1a8SJin Qian } rw_params; 103726ea1a8SJin Qian }; 104726ea1a8SJin Qian }; 105726ea1a8SJin Qian 106726ea1a8SJin Qian /* A single signalled pipe information */ 107726ea1a8SJin Qian struct signalled_pipe_buffer { 108726ea1a8SJin Qian u32 id; 109c89f2750SDavid 'Digit' Turner u32 flags; 110c89f2750SDavid 'Digit' Turner }; 111c89f2750SDavid 'Digit' Turner 112726ea1a8SJin Qian /* Parameters for the PIPE_CMD_OPEN command */ 113726ea1a8SJin Qian struct open_command_param { 114726ea1a8SJin Qian u64 command_buffer_ptr; 115726ea1a8SJin Qian u32 rw_params_max_count; 116726ea1a8SJin Qian }; 117726ea1a8SJin Qian 118726ea1a8SJin Qian /* Device-level set of buffers shared with the host */ 119726ea1a8SJin Qian struct goldfish_pipe_dev_buffers { 120726ea1a8SJin Qian struct open_command_param open_command_params; 121562a74deSRoman Kiryanov struct signalled_pipe_buffer 122562a74deSRoman Kiryanov signalled_pipe_buffers[MAX_SIGNALLED_PIPES]; 123726ea1a8SJin Qian }; 124726ea1a8SJin Qian 125726ea1a8SJin Qian /* This data type models a given pipe instance */ 126726ea1a8SJin Qian struct goldfish_pipe { 127726ea1a8SJin Qian /* pipe ID - index into goldfish_pipe_dev::pipes array */ 128726ea1a8SJin Qian u32 id; 12946928cc6SRoman Kiryanov 130726ea1a8SJin Qian /* The wake flags pipe is waiting for 131726ea1a8SJin Qian * Note: not protected with any lock, uses atomic operations 132726ea1a8SJin Qian * and barriers to make it thread-safe. 133726ea1a8SJin Qian */ 134726ea1a8SJin Qian unsigned long flags; 13546928cc6SRoman Kiryanov 136726ea1a8SJin Qian /* wake flags host have signalled, 137726ea1a8SJin Qian * - protected by goldfish_pipe_dev::lock 138726ea1a8SJin Qian */ 139726ea1a8SJin Qian unsigned long signalled_flags; 140726ea1a8SJin Qian 141726ea1a8SJin Qian /* A pointer to command buffer */ 142726ea1a8SJin Qian struct goldfish_pipe_command *command_buffer; 143726ea1a8SJin Qian 144726ea1a8SJin Qian /* doubly linked list of signalled pipes, protected by 145726ea1a8SJin Qian * goldfish_pipe_dev::lock 146726ea1a8SJin Qian */ 147726ea1a8SJin Qian struct goldfish_pipe *prev_signalled; 148726ea1a8SJin Qian struct goldfish_pipe *next_signalled; 149726ea1a8SJin Qian 150726ea1a8SJin Qian /* 151726ea1a8SJin Qian * A pipe's own lock. Protects the following: 152726ea1a8SJin Qian * - *command_buffer - makes sure a command can safely write its 153726ea1a8SJin Qian * parameters to the host and read the results back. 154726ea1a8SJin Qian */ 155726ea1a8SJin Qian struct mutex lock; 156726ea1a8SJin Qian 157726ea1a8SJin Qian /* A wake queue for sleeping until host signals an event */ 158726ea1a8SJin Qian wait_queue_head_t wake_queue; 15946928cc6SRoman Kiryanov 160726ea1a8SJin Qian /* Pointer to the parent goldfish_pipe_dev instance */ 161726ea1a8SJin Qian struct goldfish_pipe_dev *dev; 16248a2d422SRoman Kiryanov 16348a2d422SRoman Kiryanov /* A buffer of pages, too large to fit into a stack frame */ 16448a2d422SRoman Kiryanov struct page *pages[MAX_BUFFERS_PER_COMMAND]; 165726ea1a8SJin Qian }; 166726ea1a8SJin Qian 167c89f2750SDavid 'Digit' Turner /* The global driver data. Holds a reference to the i/o page used to 168c89f2750SDavid 'Digit' Turner * communicate with the emulator, and a wake queue for blocked tasks 169c89f2750SDavid 'Digit' Turner * waiting to be awoken. 170c89f2750SDavid 'Digit' Turner */ 171c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev { 17208360e26SRoman Kiryanov /* A magic number to check if this is an instance of this struct */ 17308360e26SRoman Kiryanov void *magic; 17408360e26SRoman Kiryanov 175726ea1a8SJin Qian /* 176726ea1a8SJin Qian * Global device spinlock. Protects the following members: 177726ea1a8SJin Qian * - pipes, pipes_capacity 178726ea1a8SJin Qian * - [*pipes, *pipes + pipes_capacity) - array data 179726ea1a8SJin Qian * - first_signalled_pipe, 180726ea1a8SJin Qian * goldfish_pipe::prev_signalled, 181726ea1a8SJin Qian * goldfish_pipe::next_signalled, 182726ea1a8SJin Qian * goldfish_pipe::signalled_flags - all singnalled-related fields, 183726ea1a8SJin Qian * in all allocated pipes 184726ea1a8SJin Qian * - open_command_params - PIPE_CMD_OPEN-related buffers 185726ea1a8SJin Qian * 186726ea1a8SJin Qian * It looks like a lot of different fields, but the trick is that 187726ea1a8SJin Qian * the only operation that happens often is the signalled pipes array 188726ea1a8SJin Qian * manipulation. That's why it's OK for now to keep the rest of the 189726ea1a8SJin Qian * fields under the same lock. If we notice too much contention because 190726ea1a8SJin Qian * of PIPE_CMD_OPEN, then we should add a separate lock there. 191726ea1a8SJin Qian */ 192c89f2750SDavid 'Digit' Turner spinlock_t lock; 193726ea1a8SJin Qian 194726ea1a8SJin Qian /* 195726ea1a8SJin Qian * Array of the pipes of |pipes_capacity| elements, 196726ea1a8SJin Qian * indexed by goldfish_pipe::id 197726ea1a8SJin Qian */ 198726ea1a8SJin Qian struct goldfish_pipe **pipes; 199726ea1a8SJin Qian u32 pipes_capacity; 200726ea1a8SJin Qian 201726ea1a8SJin Qian /* Pointers to the buffers host uses for interaction with this driver */ 202726ea1a8SJin Qian struct goldfish_pipe_dev_buffers *buffers; 203726ea1a8SJin Qian 204726ea1a8SJin Qian /* Head of a doubly linked list of signalled pipes */ 205726ea1a8SJin Qian struct goldfish_pipe *first_signalled_pipe; 206726ea1a8SJin Qian 20725b97d57SRoman Kiryanov /* ptr to platform device's device struct */ 20825b97d57SRoman Kiryanov struct device *pdev_dev; 20925b97d57SRoman Kiryanov 210726ea1a8SJin Qian /* Some device-specific data */ 211c89f2750SDavid 'Digit' Turner int irq; 212726ea1a8SJin Qian int version; 213726ea1a8SJin Qian unsigned char __iomem *base; 214c394cc3bSRoman Kiryanov 215c394cc3bSRoman Kiryanov /* an irq tasklet to run goldfish_interrupt_task */ 216c394cc3bSRoman Kiryanov struct tasklet_struct irq_tasklet; 21743c2cc28SRoman Kiryanov 21843c2cc28SRoman Kiryanov struct miscdevice miscdev; 219c89f2750SDavid 'Digit' Turner }; 220c89f2750SDavid 'Digit' Turner 22192c320b9SRoman Kiryanov static int goldfish_pipe_cmd_locked(struct goldfish_pipe *pipe, 22292c320b9SRoman Kiryanov enum PipeCmdCode cmd) 223c89f2750SDavid 'Digit' Turner { 224726ea1a8SJin Qian pipe->command_buffer->cmd = cmd; 225726ea1a8SJin Qian /* failure by default */ 226726ea1a8SJin Qian pipe->command_buffer->status = PIPE_ERROR_INVAL; 227726ea1a8SJin Qian writel(pipe->id, pipe->dev->base + PIPE_REG_CMD); 228726ea1a8SJin Qian return pipe->command_buffer->status; 229726ea1a8SJin Qian } 230c89f2750SDavid 'Digit' Turner 23192c320b9SRoman Kiryanov static int goldfish_pipe_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) 232726ea1a8SJin Qian { 233726ea1a8SJin Qian int status; 234726ea1a8SJin Qian 235726ea1a8SJin Qian if (mutex_lock_interruptible(&pipe->lock)) 236726ea1a8SJin Qian return PIPE_ERROR_IO; 23792c320b9SRoman Kiryanov status = goldfish_pipe_cmd_locked(pipe, cmd); 238726ea1a8SJin Qian mutex_unlock(&pipe->lock); 239c89f2750SDavid 'Digit' Turner return status; 240c89f2750SDavid 'Digit' Turner } 241c89f2750SDavid 'Digit' Turner 242726ea1a8SJin Qian /* 243726ea1a8SJin Qian * This function converts an error code returned by the emulator through 244c89f2750SDavid 'Digit' Turner * the PIPE_REG_STATUS i/o register into a valid negative errno value. 245c89f2750SDavid 'Digit' Turner */ 246c89f2750SDavid 'Digit' Turner static int goldfish_pipe_error_convert(int status) 247c89f2750SDavid 'Digit' Turner { 248c89f2750SDavid 'Digit' Turner switch (status) { 249c89f2750SDavid 'Digit' Turner case PIPE_ERROR_AGAIN: 250c89f2750SDavid 'Digit' Turner return -EAGAIN; 251c89f2750SDavid 'Digit' Turner case PIPE_ERROR_NOMEM: 252c89f2750SDavid 'Digit' Turner return -ENOMEM; 253c89f2750SDavid 'Digit' Turner case PIPE_ERROR_IO: 254c89f2750SDavid 'Digit' Turner return -EIO; 255c89f2750SDavid 'Digit' Turner default: 256c89f2750SDavid 'Digit' Turner return -EINVAL; 257c89f2750SDavid 'Digit' Turner } 258c89f2750SDavid 'Digit' Turner } 259c89f2750SDavid 'Digit' Turner 26052bcc7d9SRoman Kiryanov static int pin_user_pages(unsigned long first_page, 26152bcc7d9SRoman Kiryanov unsigned long last_page, 26252bcc7d9SRoman Kiryanov unsigned int last_page_size, 26352bcc7d9SRoman Kiryanov int is_write, 264726ea1a8SJin Qian struct page *pages[MAX_BUFFERS_PER_COMMAND], 265726ea1a8SJin Qian unsigned int *iter_last_page_size) 266c89f2750SDavid 'Digit' Turner { 267726ea1a8SJin Qian int ret; 268726ea1a8SJin Qian int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; 269c89f2750SDavid 'Digit' Turner 270726ea1a8SJin Qian if (requested_pages > MAX_BUFFERS_PER_COMMAND) { 271726ea1a8SJin Qian requested_pages = MAX_BUFFERS_PER_COMMAND; 272726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 273726ea1a8SJin Qian } else { 274726ea1a8SJin Qian *iter_last_page_size = last_page_size; 275c89f2750SDavid 'Digit' Turner } 276c89f2750SDavid 'Digit' Turner 27752bcc7d9SRoman Kiryanov ret = get_user_pages_fast(first_page, requested_pages, !is_write, 27852bcc7d9SRoman Kiryanov pages); 279726ea1a8SJin Qian if (ret <= 0) 280c89f2750SDavid 'Digit' Turner return -EFAULT; 281726ea1a8SJin Qian if (ret < requested_pages) 282726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 283c89f2750SDavid 'Digit' Turner 2841d1021a0SRoman Kiryanov return ret; 285726ea1a8SJin Qian } 286726ea1a8SJin Qian 287726ea1a8SJin Qian static void release_user_pages(struct page **pages, int pages_count, 288726ea1a8SJin Qian int is_write, s32 consumed_size) 289726ea1a8SJin Qian { 290726ea1a8SJin Qian int i; 291726ea1a8SJin Qian 292726ea1a8SJin Qian for (i = 0; i < pages_count; i++) { 293726ea1a8SJin Qian if (!is_write && consumed_size > 0) 294726ea1a8SJin Qian set_page_dirty(pages[i]); 295726ea1a8SJin Qian put_page(pages[i]); 296726ea1a8SJin Qian } 297726ea1a8SJin Qian } 298726ea1a8SJin Qian 299726ea1a8SJin Qian /* Populate the call parameters, merging adjacent pages together */ 30052bcc7d9SRoman Kiryanov static void populate_rw_params(struct page **pages, 30152bcc7d9SRoman Kiryanov int pages_count, 30252bcc7d9SRoman Kiryanov unsigned long address, 30352bcc7d9SRoman Kiryanov unsigned long address_end, 30452bcc7d9SRoman Kiryanov unsigned long first_page, 30552bcc7d9SRoman Kiryanov unsigned long last_page, 30652bcc7d9SRoman Kiryanov unsigned int iter_last_page_size, 30752bcc7d9SRoman Kiryanov int is_write, 308726ea1a8SJin Qian struct goldfish_pipe_command *command) 309726ea1a8SJin Qian { 310726ea1a8SJin Qian /* 311726ea1a8SJin Qian * Process the first page separately - it's the only page that 312726ea1a8SJin Qian * needs special handling for its start address. 313726ea1a8SJin Qian */ 314726ea1a8SJin Qian unsigned long xaddr = page_to_phys(pages[0]); 315726ea1a8SJin Qian unsigned long xaddr_prev = xaddr; 316726ea1a8SJin Qian int buffer_idx = 0; 317726ea1a8SJin Qian int i = 1; 318726ea1a8SJin Qian int size_on_page = first_page == last_page 319726ea1a8SJin Qian ? (int)(address_end - address) 320726ea1a8SJin Qian : (PAGE_SIZE - (address & ~PAGE_MASK)); 321726ea1a8SJin Qian command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK)); 322726ea1a8SJin Qian command->rw_params.sizes[0] = size_on_page; 323726ea1a8SJin Qian for (; i < pages_count; ++i) { 324726ea1a8SJin Qian xaddr = page_to_phys(pages[i]); 325726ea1a8SJin Qian size_on_page = (i == pages_count - 1) ? 326726ea1a8SJin Qian iter_last_page_size : PAGE_SIZE; 327726ea1a8SJin Qian if (xaddr == xaddr_prev + PAGE_SIZE) { 328726ea1a8SJin Qian command->rw_params.sizes[buffer_idx] += size_on_page; 329726ea1a8SJin Qian } else { 330726ea1a8SJin Qian ++buffer_idx; 331726ea1a8SJin Qian command->rw_params.ptrs[buffer_idx] = (u64)xaddr; 332726ea1a8SJin Qian command->rw_params.sizes[buffer_idx] = size_on_page; 333726ea1a8SJin Qian } 334726ea1a8SJin Qian xaddr_prev = xaddr; 335726ea1a8SJin Qian } 336726ea1a8SJin Qian command->rw_params.buffers_count = buffer_idx + 1; 337726ea1a8SJin Qian } 338726ea1a8SJin Qian 339726ea1a8SJin Qian static int transfer_max_buffers(struct goldfish_pipe *pipe, 34052bcc7d9SRoman Kiryanov unsigned long address, 34152bcc7d9SRoman Kiryanov unsigned long address_end, 34252bcc7d9SRoman Kiryanov int is_write, 34352bcc7d9SRoman Kiryanov unsigned long last_page, 34452bcc7d9SRoman Kiryanov unsigned int last_page_size, 34552bcc7d9SRoman Kiryanov s32 *consumed_size, 34652bcc7d9SRoman Kiryanov int *status) 347726ea1a8SJin Qian { 348726ea1a8SJin Qian unsigned long first_page = address & PAGE_MASK; 349726ea1a8SJin Qian unsigned int iter_last_page_size; 35048a2d422SRoman Kiryanov int pages_count; 351726ea1a8SJin Qian 352726ea1a8SJin Qian /* Serialize access to the pipe command buffers */ 353c89f2750SDavid 'Digit' Turner if (mutex_lock_interruptible(&pipe->lock)) 354c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 355c89f2750SDavid 'Digit' Turner 35648a2d422SRoman Kiryanov pages_count = pin_user_pages(first_page, last_page, 35748a2d422SRoman Kiryanov last_page_size, is_write, 35848a2d422SRoman Kiryanov pipe->pages, &iter_last_page_size); 35948a2d422SRoman Kiryanov if (pages_count < 0) { 36048a2d422SRoman Kiryanov mutex_unlock(&pipe->lock); 36148a2d422SRoman Kiryanov return pages_count; 36248a2d422SRoman Kiryanov } 36348a2d422SRoman Kiryanov 36448a2d422SRoman Kiryanov populate_rw_params(pipe->pages, pages_count, address, address_end, 365726ea1a8SJin Qian first_page, last_page, iter_last_page_size, is_write, 366726ea1a8SJin Qian pipe->command_buffer); 367c89f2750SDavid 'Digit' Turner 368726ea1a8SJin Qian /* Transfer the data */ 36992c320b9SRoman Kiryanov *status = goldfish_pipe_cmd_locked(pipe, 370726ea1a8SJin Qian is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ); 371c89f2750SDavid 'Digit' Turner 372726ea1a8SJin Qian *consumed_size = pipe->command_buffer->rw_params.consumed_size; 3734f42071cSYu Ning 37448a2d422SRoman Kiryanov release_user_pages(pipe->pages, pages_count, is_write, *consumed_size); 375726ea1a8SJin Qian 376f563dab4SGreg Kroah-Hartman mutex_unlock(&pipe->lock); 377726ea1a8SJin Qian return 0; 378c89f2750SDavid 'Digit' Turner } 379c89f2750SDavid 'Digit' Turner 380726ea1a8SJin Qian static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write) 381726ea1a8SJin Qian { 38261b38f02SRoman Kiryanov u32 wake_bit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; 383c89f2750SDavid 'Digit' Turner 38461b38f02SRoman Kiryanov set_bit(wake_bit, &pipe->flags); 385c89f2750SDavid 'Digit' Turner 386c89f2750SDavid 'Digit' Turner /* Tell the emulator we're going to wait for a wake event */ 38792c320b9SRoman Kiryanov goldfish_pipe_cmd(pipe, 388726ea1a8SJin Qian is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ); 389c89f2750SDavid 'Digit' Turner 39061b38f02SRoman Kiryanov while (test_bit(wake_bit, &pipe->flags)) { 391562a74deSRoman Kiryanov if (wait_event_interruptible(pipe->wake_queue, 39261b38f02SRoman Kiryanov !test_bit(wake_bit, &pipe->flags))) 393c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 394c89f2750SDavid 'Digit' Turner 395c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 396c89f2750SDavid 'Digit' Turner return -EIO; 397c89f2750SDavid 'Digit' Turner } 398c89f2750SDavid 'Digit' Turner 399726ea1a8SJin Qian return 0; 400c89f2750SDavid 'Digit' Turner } 4012f3be882SChristoffer Dall 402726ea1a8SJin Qian static ssize_t goldfish_pipe_read_write(struct file *filp, 40352bcc7d9SRoman Kiryanov char __user *buffer, 40452bcc7d9SRoman Kiryanov size_t bufflen, 40552bcc7d9SRoman Kiryanov int is_write) 406726ea1a8SJin Qian { 407726ea1a8SJin Qian struct goldfish_pipe *pipe = filp->private_data; 408726ea1a8SJin Qian int count = 0, ret = -EINVAL; 409726ea1a8SJin Qian unsigned long address, address_end, last_page; 410726ea1a8SJin Qian unsigned int last_page_size; 411726ea1a8SJin Qian 412726ea1a8SJin Qian /* If the emulator already closed the pipe, no need to go further */ 413726ea1a8SJin Qian if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))) 414726ea1a8SJin Qian return -EIO; 415726ea1a8SJin Qian /* Null reads or writes succeeds */ 416726ea1a8SJin Qian if (unlikely(bufflen == 0)) 417726ea1a8SJin Qian return 0; 418726ea1a8SJin Qian /* Check the buffer range for access */ 419726ea1a8SJin Qian if (unlikely(!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, 420726ea1a8SJin Qian buffer, bufflen))) 421726ea1a8SJin Qian return -EFAULT; 422726ea1a8SJin Qian 423726ea1a8SJin Qian address = (unsigned long)buffer; 424726ea1a8SJin Qian address_end = address + bufflen; 425726ea1a8SJin Qian last_page = (address_end - 1) & PAGE_MASK; 426726ea1a8SJin Qian last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1; 427726ea1a8SJin Qian 428726ea1a8SJin Qian while (address < address_end) { 429726ea1a8SJin Qian s32 consumed_size; 430726ea1a8SJin Qian int status; 431726ea1a8SJin Qian 432726ea1a8SJin Qian ret = transfer_max_buffers(pipe, address, address_end, is_write, 43352bcc7d9SRoman Kiryanov last_page, last_page_size, 43452bcc7d9SRoman Kiryanov &consumed_size, &status); 4352f3be882SChristoffer Dall if (ret < 0) 436726ea1a8SJin Qian break; 437726ea1a8SJin Qian 438726ea1a8SJin Qian if (consumed_size > 0) { 439726ea1a8SJin Qian /* No matter what's the status, we've transferred 440726ea1a8SJin Qian * something. 441726ea1a8SJin Qian */ 442726ea1a8SJin Qian count += consumed_size; 443726ea1a8SJin Qian address += consumed_size; 444726ea1a8SJin Qian } 445726ea1a8SJin Qian if (status > 0) 446726ea1a8SJin Qian continue; 447726ea1a8SJin Qian if (status == 0) { 448726ea1a8SJin Qian /* EOF */ 449726ea1a8SJin Qian ret = 0; 450726ea1a8SJin Qian break; 451726ea1a8SJin Qian } 452726ea1a8SJin Qian if (count > 0) { 453726ea1a8SJin Qian /* 454726ea1a8SJin Qian * An error occurred, but we already transferred 455726ea1a8SJin Qian * something on one of the previous iterations. 456726ea1a8SJin Qian * Just return what we already copied and log this 457726ea1a8SJin Qian * err. 458726ea1a8SJin Qian */ 459726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN) 46025b97d57SRoman Kiryanov dev_err_ratelimited(pipe->dev->pdev_dev, 46125b97d57SRoman Kiryanov "backend error %d on %s\n", 462726ea1a8SJin Qian status, is_write ? "write" : "read"); 463726ea1a8SJin Qian break; 464726ea1a8SJin Qian } 465726ea1a8SJin Qian 466726ea1a8SJin Qian /* 467726ea1a8SJin Qian * If the error is not PIPE_ERROR_AGAIN, or if we are in 468726ea1a8SJin Qian * non-blocking mode, just return the error code. 469726ea1a8SJin Qian */ 470726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN || 471726ea1a8SJin Qian (filp->f_flags & O_NONBLOCK) != 0) { 472726ea1a8SJin Qian ret = goldfish_pipe_error_convert(status); 473726ea1a8SJin Qian break; 474726ea1a8SJin Qian } 475726ea1a8SJin Qian 476726ea1a8SJin Qian status = wait_for_host_signal(pipe, is_write); 477726ea1a8SJin Qian if (status < 0) 478726ea1a8SJin Qian return status; 479726ea1a8SJin Qian } 480726ea1a8SJin Qian 481726ea1a8SJin Qian if (count > 0) 4822f3be882SChristoffer Dall return count; 483726ea1a8SJin Qian return ret; 484c89f2750SDavid 'Digit' Turner } 485c89f2750SDavid 'Digit' Turner 486c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, 487c89f2750SDavid 'Digit' Turner size_t bufflen, loff_t *ppos) 488c89f2750SDavid 'Digit' Turner { 489726ea1a8SJin Qian return goldfish_pipe_read_write(filp, buffer, bufflen, 490726ea1a8SJin Qian /* is_write */ 0); 491c89f2750SDavid 'Digit' Turner } 492c89f2750SDavid 'Digit' Turner 493c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_write(struct file *filp, 494c89f2750SDavid 'Digit' Turner const char __user *buffer, size_t bufflen, 495c89f2750SDavid 'Digit' Turner loff_t *ppos) 496c89f2750SDavid 'Digit' Turner { 49752bcc7d9SRoman Kiryanov /* cast away the const */ 49852bcc7d9SRoman Kiryanov char __user *no_const_buffer = (char __user *)buffer; 49952bcc7d9SRoman Kiryanov 50052bcc7d9SRoman Kiryanov return goldfish_pipe_read_write(filp, no_const_buffer, bufflen, 501726ea1a8SJin Qian /* is_write */ 1); 502c89f2750SDavid 'Digit' Turner } 503c89f2750SDavid 'Digit' Turner 504afc9a42bSAl Viro static __poll_t goldfish_pipe_poll(struct file *filp, poll_table *wait) 505c89f2750SDavid 'Digit' Turner { 506c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 507afc9a42bSAl Viro __poll_t mask = 0; 508c89f2750SDavid 'Digit' Turner int status; 509c89f2750SDavid 'Digit' Turner 510c89f2750SDavid 'Digit' Turner poll_wait(filp, &pipe->wake_queue, wait); 511c89f2750SDavid 'Digit' Turner 51292c320b9SRoman Kiryanov status = goldfish_pipe_cmd(pipe, PIPE_CMD_POLL); 513726ea1a8SJin Qian if (status < 0) 514726ea1a8SJin Qian return -ERESTARTSYS; 515c89f2750SDavid 'Digit' Turner 516c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_IN) 517a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM; 518c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_OUT) 519a9a08845SLinus Torvalds mask |= EPOLLOUT | EPOLLWRNORM; 520c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_HUP) 521a9a08845SLinus Torvalds mask |= EPOLLHUP; 522c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 523a9a08845SLinus Torvalds mask |= EPOLLERR; 524c89f2750SDavid 'Digit' Turner 525c89f2750SDavid 'Digit' Turner return mask; 526c89f2750SDavid 'Digit' Turner } 527c89f2750SDavid 'Digit' Turner 528726ea1a8SJin Qian static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev, 529726ea1a8SJin Qian u32 id, u32 flags) 530c89f2750SDavid 'Digit' Turner { 531c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe; 53249a75c44SJun Tian 533726ea1a8SJin Qian if (WARN_ON(id >= dev->pipes_capacity)) 534726ea1a8SJin Qian return; 53525c72c78SJun Tian 536726ea1a8SJin Qian pipe = dev->pipes[id]; 537726ea1a8SJin Qian if (!pipe) 538726ea1a8SJin Qian return; 539726ea1a8SJin Qian pipe->signalled_flags |= flags; 540c89f2750SDavid 'Digit' Turner 541cc14057fSRoman Kiryanov if (pipe->prev_signalled || pipe->next_signalled || 542cc14057fSRoman Kiryanov dev->first_signalled_pipe == pipe) 543726ea1a8SJin Qian return; /* already in the list */ 544726ea1a8SJin Qian pipe->next_signalled = dev->first_signalled_pipe; 545726ea1a8SJin Qian if (dev->first_signalled_pipe) 546726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = pipe; 547726ea1a8SJin Qian dev->first_signalled_pipe = pipe; 548c89f2750SDavid 'Digit' Turner } 549726ea1a8SJin Qian 550726ea1a8SJin Qian static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev, 55153bdf668SRoman Kiryanov struct goldfish_pipe *pipe) 55253bdf668SRoman Kiryanov { 553726ea1a8SJin Qian if (pipe->prev_signalled) 554726ea1a8SJin Qian pipe->prev_signalled->next_signalled = pipe->next_signalled; 555726ea1a8SJin Qian if (pipe->next_signalled) 556726ea1a8SJin Qian pipe->next_signalled->prev_signalled = pipe->prev_signalled; 557726ea1a8SJin Qian if (pipe == dev->first_signalled_pipe) 558726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 559726ea1a8SJin Qian pipe->prev_signalled = NULL; 560726ea1a8SJin Qian pipe->next_signalled = NULL; 561726ea1a8SJin Qian } 562726ea1a8SJin Qian 563726ea1a8SJin Qian static struct goldfish_pipe *signalled_pipes_pop_front( 564726ea1a8SJin Qian struct goldfish_pipe_dev *dev, int *wakes) 565726ea1a8SJin Qian { 566726ea1a8SJin Qian struct goldfish_pipe *pipe; 567726ea1a8SJin Qian unsigned long flags; 568726ea1a8SJin Qian 569726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 570726ea1a8SJin Qian 571726ea1a8SJin Qian pipe = dev->first_signalled_pipe; 572726ea1a8SJin Qian if (pipe) { 573726ea1a8SJin Qian *wakes = pipe->signalled_flags; 574726ea1a8SJin Qian pipe->signalled_flags = 0; 575726ea1a8SJin Qian /* 576726ea1a8SJin Qian * This is an optimized version of 577726ea1a8SJin Qian * signalled_pipes_remove_locked() 578726ea1a8SJin Qian * - We want to make it as fast as possible to 579726ea1a8SJin Qian * wake the sleeping pipe operations faster. 580726ea1a8SJin Qian */ 581726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 582726ea1a8SJin Qian if (dev->first_signalled_pipe) 583726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = NULL; 584726ea1a8SJin Qian pipe->next_signalled = NULL; 585726ea1a8SJin Qian } 586726ea1a8SJin Qian 587726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 588726ea1a8SJin Qian return pipe; 589726ea1a8SJin Qian } 590726ea1a8SJin Qian 591c394cc3bSRoman Kiryanov static void goldfish_interrupt_task(unsigned long dev_addr) 592726ea1a8SJin Qian { 593726ea1a8SJin Qian /* Iterate over the signalled pipes and wake them one by one */ 594c394cc3bSRoman Kiryanov struct goldfish_pipe_dev *dev = (struct goldfish_pipe_dev *)dev_addr; 595726ea1a8SJin Qian struct goldfish_pipe *pipe; 596726ea1a8SJin Qian int wakes; 597726ea1a8SJin Qian 598c394cc3bSRoman Kiryanov while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) { 599726ea1a8SJin Qian if (wakes & PIPE_WAKE_CLOSED) { 600726ea1a8SJin Qian pipe->flags = 1 << BIT_CLOSED_ON_HOST; 601726ea1a8SJin Qian } else { 602c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_READ) 603c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_READ, &pipe->flags); 604c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_WRITE) 605c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); 606c89f2750SDavid 'Digit' Turner } 607726ea1a8SJin Qian /* 608726ea1a8SJin Qian * wake_up_interruptible() implies a write barrier, so don't 609726ea1a8SJin Qian * explicitly add another one here. 610726ea1a8SJin Qian */ 611726ea1a8SJin Qian wake_up_interruptible(&pipe->wake_queue); 612726ea1a8SJin Qian } 613726ea1a8SJin Qian } 614c89f2750SDavid 'Digit' Turner 61508360e26SRoman Kiryanov static void goldfish_pipe_device_deinit(struct platform_device *pdev, 61608360e26SRoman Kiryanov struct goldfish_pipe_dev *dev); 61708360e26SRoman Kiryanov 618726ea1a8SJin Qian /* 619726ea1a8SJin Qian * The general idea of the interrupt handling: 620726ea1a8SJin Qian * 621726ea1a8SJin Qian * 1. device raises an interrupt if there's at least one signalled pipe 622726ea1a8SJin Qian * 2. IRQ handler reads the signalled pipes and their count from the device 623726ea1a8SJin Qian * 3. device writes them into a shared buffer and returns the count 624726ea1a8SJin Qian * it only resets the IRQ if it has returned all signalled pipes, 625726ea1a8SJin Qian * otherwise it leaves it raised, so IRQ handler will be called 626726ea1a8SJin Qian * again for the next chunk 627726ea1a8SJin Qian * 4. IRQ handler adds all returned pipes to the device's signalled pipes list 628726ea1a8SJin Qian * 5. IRQ handler launches a tasklet to process the signalled pipes from the 629726ea1a8SJin Qian * list in a separate context 630726ea1a8SJin Qian */ 631726ea1a8SJin Qian static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) 632726ea1a8SJin Qian { 633726ea1a8SJin Qian u32 count; 634726ea1a8SJin Qian u32 i; 635726ea1a8SJin Qian unsigned long flags; 636726ea1a8SJin Qian struct goldfish_pipe_dev *dev = dev_id; 637726ea1a8SJin Qian 63808360e26SRoman Kiryanov if (dev->magic != &goldfish_pipe_device_deinit) 639726ea1a8SJin Qian return IRQ_NONE; 640726ea1a8SJin Qian 641726ea1a8SJin Qian /* Request the signalled pipes from the device */ 642726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 643726ea1a8SJin Qian 644726ea1a8SJin Qian count = readl(dev->base + PIPE_REG_GET_SIGNALLED); 645726ea1a8SJin Qian if (count == 0) { 646726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 647726ea1a8SJin Qian return IRQ_NONE; 648726ea1a8SJin Qian } 649726ea1a8SJin Qian if (count > MAX_SIGNALLED_PIPES) 650726ea1a8SJin Qian count = MAX_SIGNALLED_PIPES; 651726ea1a8SJin Qian 652726ea1a8SJin Qian for (i = 0; i < count; ++i) 653726ea1a8SJin Qian signalled_pipes_add_locked(dev, 654726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].id, 655726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].flags); 656726ea1a8SJin Qian 657726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 658726ea1a8SJin Qian 659c394cc3bSRoman Kiryanov tasklet_schedule(&dev->irq_tasklet); 660726ea1a8SJin Qian return IRQ_HANDLED; 661726ea1a8SJin Qian } 662726ea1a8SJin Qian 663726ea1a8SJin Qian static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) 664726ea1a8SJin Qian { 665726ea1a8SJin Qian int id; 666726ea1a8SJin Qian 667726ea1a8SJin Qian for (id = 0; id < dev->pipes_capacity; ++id) 668726ea1a8SJin Qian if (!dev->pipes[id]) 669726ea1a8SJin Qian return id; 670726ea1a8SJin Qian 671726ea1a8SJin Qian { 67284ae527aSRoman Kiryanov /* Reallocate the array. 67384ae527aSRoman Kiryanov * Since get_free_pipe_id_locked runs with interrupts disabled, 67484ae527aSRoman Kiryanov * we don't want to make calls that could lead to sleep. 67584ae527aSRoman Kiryanov */ 676726ea1a8SJin Qian u32 new_capacity = 2 * dev->pipes_capacity; 677726ea1a8SJin Qian struct goldfish_pipe **pipes = 6783eff8ecdSWei Yongjun kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC); 679726ea1a8SJin Qian if (!pipes) 680726ea1a8SJin Qian return -ENOMEM; 681726ea1a8SJin Qian memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); 682726ea1a8SJin Qian kfree(dev->pipes); 683726ea1a8SJin Qian dev->pipes = pipes; 684726ea1a8SJin Qian id = dev->pipes_capacity; 685726ea1a8SJin Qian dev->pipes_capacity = new_capacity; 686726ea1a8SJin Qian } 687726ea1a8SJin Qian return id; 688c89f2750SDavid 'Digit' Turner } 689c89f2750SDavid 'Digit' Turner 69008360e26SRoman Kiryanov /* A helper function to get the instance of goldfish_pipe_dev from file */ 69108360e26SRoman Kiryanov static struct goldfish_pipe_dev *to_goldfish_pipe_dev(struct file *file) 69208360e26SRoman Kiryanov { 69308360e26SRoman Kiryanov struct miscdevice *miscdev = file->private_data; 69408360e26SRoman Kiryanov 69508360e26SRoman Kiryanov return container_of(miscdev, struct goldfish_pipe_dev, miscdev); 69608360e26SRoman Kiryanov } 69708360e26SRoman Kiryanov 698c89f2750SDavid 'Digit' Turner /** 699c89f2750SDavid 'Digit' Turner * goldfish_pipe_open - open a channel to the AVD 700c89f2750SDavid 'Digit' Turner * @inode: inode of device 701c89f2750SDavid 'Digit' Turner * @file: file struct of opener 702c89f2750SDavid 'Digit' Turner * 703c89f2750SDavid 'Digit' Turner * Create a new pipe link between the emulator and the use application. 704c89f2750SDavid 'Digit' Turner * Each new request produces a new pipe. 705c89f2750SDavid 'Digit' Turner * 706c89f2750SDavid 'Digit' Turner * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit 707c89f2750SDavid 'Digit' Turner * right now so this is fine. A move to 64bit will need this addressing 708c89f2750SDavid 'Digit' Turner */ 709c89f2750SDavid 'Digit' Turner static int goldfish_pipe_open(struct inode *inode, struct file *file) 710c89f2750SDavid 'Digit' Turner { 71108360e26SRoman Kiryanov struct goldfish_pipe_dev *dev = to_goldfish_pipe_dev(file); 712726ea1a8SJin Qian unsigned long flags; 713726ea1a8SJin Qian int id; 714726ea1a8SJin Qian int status; 715c89f2750SDavid 'Digit' Turner 716c89f2750SDavid 'Digit' Turner /* Allocate new pipe kernel object */ 717726ea1a8SJin Qian struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); 718*6d7d725bSRoman Kiryanov 719bfb8e838SRoman Kiryanov if (!pipe) 720c89f2750SDavid 'Digit' Turner return -ENOMEM; 721c89f2750SDavid 'Digit' Turner 722c89f2750SDavid 'Digit' Turner pipe->dev = dev; 723c89f2750SDavid 'Digit' Turner mutex_init(&pipe->lock); 724c89f2750SDavid 'Digit' Turner init_waitqueue_head(&pipe->wake_queue); 725c89f2750SDavid 'Digit' Turner 726c89f2750SDavid 'Digit' Turner /* 727726ea1a8SJin Qian * Command buffer needs to be allocated on its own page to make sure 728726ea1a8SJin Qian * it is physically contiguous in host's address space. 729c89f2750SDavid 'Digit' Turner */ 730d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE); 731726ea1a8SJin Qian pipe->command_buffer = 732726ea1a8SJin Qian (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL); 733726ea1a8SJin Qian if (!pipe->command_buffer) { 734726ea1a8SJin Qian status = -ENOMEM; 735726ea1a8SJin Qian goto err_pipe; 736726ea1a8SJin Qian } 737c89f2750SDavid 'Digit' Turner 738726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 739726ea1a8SJin Qian 740726ea1a8SJin Qian id = get_free_pipe_id_locked(dev); 741726ea1a8SJin Qian if (id < 0) { 742726ea1a8SJin Qian status = id; 743726ea1a8SJin Qian goto err_id_locked; 744726ea1a8SJin Qian } 745726ea1a8SJin Qian 746726ea1a8SJin Qian dev->pipes[id] = pipe; 747726ea1a8SJin Qian pipe->id = id; 748726ea1a8SJin Qian pipe->command_buffer->id = id; 749726ea1a8SJin Qian 750726ea1a8SJin Qian /* Now tell the emulator we're opening a new pipe. */ 751726ea1a8SJin Qian dev->buffers->open_command_params.rw_params_max_count = 752726ea1a8SJin Qian MAX_BUFFERS_PER_COMMAND; 753726ea1a8SJin Qian dev->buffers->open_command_params.command_buffer_ptr = 754726ea1a8SJin Qian (u64)(unsigned long)__pa(pipe->command_buffer); 75592c320b9SRoman Kiryanov status = goldfish_pipe_cmd_locked(pipe, PIPE_CMD_OPEN); 756726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 757726ea1a8SJin Qian if (status < 0) 758726ea1a8SJin Qian goto err_cmd; 759726ea1a8SJin Qian /* All is done, save the pipe into the file's private data field */ 760726ea1a8SJin Qian file->private_data = pipe; 761726ea1a8SJin Qian return 0; 762726ea1a8SJin Qian 763726ea1a8SJin Qian err_cmd: 764726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 765726ea1a8SJin Qian dev->pipes[id] = NULL; 766726ea1a8SJin Qian err_id_locked: 767726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 768726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 769726ea1a8SJin Qian err_pipe: 770c89f2750SDavid 'Digit' Turner kfree(pipe); 771c89f2750SDavid 'Digit' Turner return status; 772c89f2750SDavid 'Digit' Turner } 773c89f2750SDavid 'Digit' Turner 774c89f2750SDavid 'Digit' Turner static int goldfish_pipe_release(struct inode *inode, struct file *filp) 775c89f2750SDavid 'Digit' Turner { 776726ea1a8SJin Qian unsigned long flags; 777c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 778726ea1a8SJin Qian struct goldfish_pipe_dev *dev = pipe->dev; 779c89f2750SDavid 'Digit' Turner 780c89f2750SDavid 'Digit' Turner /* The guest is closing the channel, so tell the emulator right now */ 78192c320b9SRoman Kiryanov goldfish_pipe_cmd(pipe, PIPE_CMD_CLOSE); 782726ea1a8SJin Qian 783726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 784726ea1a8SJin Qian dev->pipes[pipe->id] = NULL; 785726ea1a8SJin Qian signalled_pipes_remove_locked(dev, pipe); 786726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 787726ea1a8SJin Qian 788c89f2750SDavid 'Digit' Turner filp->private_data = NULL; 789726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 790726ea1a8SJin Qian kfree(pipe); 791c89f2750SDavid 'Digit' Turner return 0; 792c89f2750SDavid 'Digit' Turner } 793c89f2750SDavid 'Digit' Turner 794c89f2750SDavid 'Digit' Turner static const struct file_operations goldfish_pipe_fops = { 795c89f2750SDavid 'Digit' Turner .owner = THIS_MODULE, 796c89f2750SDavid 'Digit' Turner .read = goldfish_pipe_read, 797c89f2750SDavid 'Digit' Turner .write = goldfish_pipe_write, 798c89f2750SDavid 'Digit' Turner .poll = goldfish_pipe_poll, 799c89f2750SDavid 'Digit' Turner .open = goldfish_pipe_open, 800c89f2750SDavid 'Digit' Turner .release = goldfish_pipe_release, 801c89f2750SDavid 'Digit' Turner }; 802c89f2750SDavid 'Digit' Turner 80343c2cc28SRoman Kiryanov static void init_miscdevice(struct miscdevice *miscdev) 80443c2cc28SRoman Kiryanov { 80543c2cc28SRoman Kiryanov memset(miscdev, 0, sizeof(*miscdev)); 80643c2cc28SRoman Kiryanov 80743c2cc28SRoman Kiryanov miscdev->minor = MISC_DYNAMIC_MINOR; 80843c2cc28SRoman Kiryanov miscdev->name = "goldfish_pipe"; 80943c2cc28SRoman Kiryanov miscdev->fops = &goldfish_pipe_fops; 81043c2cc28SRoman Kiryanov } 811c89f2750SDavid 'Digit' Turner 812610a72b7SRoman Kiryanov static void write_pa_addr(void *addr, void __iomem *portl, void __iomem *porth) 813610a72b7SRoman Kiryanov { 814610a72b7SRoman Kiryanov const unsigned long paddr = __pa(addr); 815610a72b7SRoman Kiryanov 816610a72b7SRoman Kiryanov writel(upper_32_bits(paddr), porth); 817610a72b7SRoman Kiryanov writel(lower_32_bits(paddr), portl); 818610a72b7SRoman Kiryanov } 819610a72b7SRoman Kiryanov 82008360e26SRoman Kiryanov static int goldfish_pipe_device_init(struct platform_device *pdev, 82108360e26SRoman Kiryanov struct goldfish_pipe_dev *dev) 822726ea1a8SJin Qian { 823c394cc3bSRoman Kiryanov int err; 824c394cc3bSRoman Kiryanov 825c394cc3bSRoman Kiryanov tasklet_init(&dev->irq_tasklet, &goldfish_interrupt_task, 826c394cc3bSRoman Kiryanov (unsigned long)dev); 827c394cc3bSRoman Kiryanov 828c394cc3bSRoman Kiryanov err = devm_request_irq(&pdev->dev, dev->irq, 829726ea1a8SJin Qian goldfish_pipe_interrupt, 830726ea1a8SJin Qian IRQF_SHARED, "goldfish_pipe", dev); 831726ea1a8SJin Qian if (err) { 832726ea1a8SJin Qian dev_err(&pdev->dev, "unable to allocate IRQ for v2\n"); 833726ea1a8SJin Qian return err; 834726ea1a8SJin Qian } 835726ea1a8SJin Qian 83643c2cc28SRoman Kiryanov init_miscdevice(&dev->miscdev); 83743c2cc28SRoman Kiryanov err = misc_register(&dev->miscdev); 838726ea1a8SJin Qian if (err) { 839726ea1a8SJin Qian dev_err(&pdev->dev, "unable to register v2 device\n"); 840726ea1a8SJin Qian return err; 841726ea1a8SJin Qian } 842726ea1a8SJin Qian 84325b97d57SRoman Kiryanov dev->pdev_dev = &pdev->dev; 844726ea1a8SJin Qian dev->first_signalled_pipe = NULL; 845726ea1a8SJin Qian dev->pipes_capacity = INITIAL_PIPES_CAPACITY; 846726ea1a8SJin Qian dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), 847726ea1a8SJin Qian GFP_KERNEL); 84860a6e523SRoman Kiryanov if (!dev->pipes) { 84960a6e523SRoman Kiryanov misc_deregister(&dev->miscdev); 850726ea1a8SJin Qian return -ENOMEM; 85160a6e523SRoman Kiryanov } 852726ea1a8SJin Qian 853726ea1a8SJin Qian /* 854726ea1a8SJin Qian * We're going to pass two buffers, open_command_params and 855726ea1a8SJin Qian * signalled_pipe_buffers, to the host. This means each of those buffers 856726ea1a8SJin Qian * needs to be contained in a single physical page. The easiest choice 857726ea1a8SJin Qian * is to just allocate a page and place the buffers in it. 858726ea1a8SJin Qian */ 859d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_dev_buffers) > PAGE_SIZE); 8602ed43e53SRoman Kiryanov dev->buffers = (struct goldfish_pipe_dev_buffers *) 8612ed43e53SRoman Kiryanov __get_free_page(GFP_KERNEL); 8622ed43e53SRoman Kiryanov if (!dev->buffers) { 863726ea1a8SJin Qian kfree(dev->pipes); 86460a6e523SRoman Kiryanov misc_deregister(&dev->miscdev); 865726ea1a8SJin Qian return -ENOMEM; 866726ea1a8SJin Qian } 867726ea1a8SJin Qian 868726ea1a8SJin Qian /* Send the buffer addresses to the host */ 869610a72b7SRoman Kiryanov write_pa_addr(&dev->buffers->signalled_pipe_buffers, 870610a72b7SRoman Kiryanov dev->base + PIPE_REG_SIGNAL_BUFFER, 871726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH); 872610a72b7SRoman Kiryanov 873468e62f9SRoman Kiryanov writel(MAX_SIGNALLED_PIPES, 874726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT); 875726ea1a8SJin Qian 876610a72b7SRoman Kiryanov write_pa_addr(&dev->buffers->open_command_params, 877610a72b7SRoman Kiryanov dev->base + PIPE_REG_OPEN_BUFFER, 878726ea1a8SJin Qian dev->base + PIPE_REG_OPEN_BUFFER_HIGH); 879610a72b7SRoman Kiryanov 88008360e26SRoman Kiryanov platform_set_drvdata(pdev, dev); 881726ea1a8SJin Qian return 0; 882726ea1a8SJin Qian } 883726ea1a8SJin Qian 88408360e26SRoman Kiryanov static void goldfish_pipe_device_deinit(struct platform_device *pdev, 88508360e26SRoman Kiryanov struct goldfish_pipe_dev *dev) 886726ea1a8SJin Qian { 88708360e26SRoman Kiryanov misc_deregister(&dev->miscdev); 88808360e26SRoman Kiryanov tasklet_kill(&dev->irq_tasklet); 88908360e26SRoman Kiryanov kfree(dev->pipes); 89008360e26SRoman Kiryanov free_page((unsigned long)dev->buffers); 891726ea1a8SJin Qian } 892726ea1a8SJin Qian 893c89f2750SDavid 'Digit' Turner static int goldfish_pipe_probe(struct platform_device *pdev) 894c89f2750SDavid 'Digit' Turner { 895c89f2750SDavid 'Digit' Turner struct resource *r; 89608360e26SRoman Kiryanov struct goldfish_pipe_dev *dev; 897c89f2750SDavid 'Digit' Turner 89808360e26SRoman Kiryanov dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 89908360e26SRoman Kiryanov if (!dev) 90008360e26SRoman Kiryanov return -ENOMEM; 901c89f2750SDavid 'Digit' Turner 90208360e26SRoman Kiryanov dev->magic = &goldfish_pipe_device_deinit; 903c89f2750SDavid 'Digit' Turner spin_lock_init(&dev->lock); 904c89f2750SDavid 'Digit' Turner 905c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 906bfb8e838SRoman Kiryanov if (!r || resource_size(r) < PAGE_SIZE) { 907c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "can't allocate i/o page\n"); 908c89f2750SDavid 'Digit' Turner return -EINVAL; 909c89f2750SDavid 'Digit' Turner } 910c89f2750SDavid 'Digit' Turner dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); 911bfb8e838SRoman Kiryanov if (!dev->base) { 912c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "ioremap failed\n"); 913c89f2750SDavid 'Digit' Turner return -EINVAL; 914c89f2750SDavid 'Digit' Turner } 915c89f2750SDavid 'Digit' Turner 916c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 91708360e26SRoman Kiryanov if (!r) 91808360e26SRoman Kiryanov return -EINVAL; 91908360e26SRoman Kiryanov 920c89f2750SDavid 'Digit' Turner dev->irq = r->start; 921c89f2750SDavid 'Digit' Turner 922726ea1a8SJin Qian /* 923726ea1a8SJin Qian * Exchange the versions with the host device 924726ea1a8SJin Qian * 925726ea1a8SJin Qian * Note: v1 driver used to not report its version, so we write it before 926726ea1a8SJin Qian * reading device version back: this allows the host implementation to 927726ea1a8SJin Qian * detect the old driver (if there was no version write before read). 9284f42071cSYu Ning */ 929e6fb3193SRoman Kiryanov writel(PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION); 9304f42071cSYu Ning dev->version = readl(dev->base + PIPE_REG_VERSION); 931726ea1a8SJin Qian if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION)) 932726ea1a8SJin Qian return -EINVAL; 933726ea1a8SJin Qian 93408360e26SRoman Kiryanov return goldfish_pipe_device_init(pdev, dev); 935c89f2750SDavid 'Digit' Turner } 936c89f2750SDavid 'Digit' Turner 937c89f2750SDavid 'Digit' Turner static int goldfish_pipe_remove(struct platform_device *pdev) 938c89f2750SDavid 'Digit' Turner { 93908360e26SRoman Kiryanov struct goldfish_pipe_dev *dev = platform_get_drvdata(pdev); 94008360e26SRoman Kiryanov 94108360e26SRoman Kiryanov goldfish_pipe_device_deinit(pdev, dev); 942c89f2750SDavid 'Digit' Turner return 0; 943c89f2750SDavid 'Digit' Turner } 944c89f2750SDavid 'Digit' Turner 945d62f324bSJason Hu static const struct acpi_device_id goldfish_pipe_acpi_match[] = { 946d62f324bSJason Hu { "GFSH0003", 0 }, 947d62f324bSJason Hu { }, 948d62f324bSJason Hu }; 949d62f324bSJason Hu MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); 950d62f324bSJason Hu 95191a18a41SGreg Hackmann static const struct of_device_id goldfish_pipe_of_match[] = { 95291a18a41SGreg Hackmann { .compatible = "google,android-pipe", }, 95391a18a41SGreg Hackmann {}, 95491a18a41SGreg Hackmann }; 95591a18a41SGreg Hackmann MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); 95691a18a41SGreg Hackmann 957726ea1a8SJin Qian static struct platform_driver goldfish_pipe_driver = { 958c89f2750SDavid 'Digit' Turner .probe = goldfish_pipe_probe, 959c89f2750SDavid 'Digit' Turner .remove = goldfish_pipe_remove, 960c89f2750SDavid 'Digit' Turner .driver = { 96191a18a41SGreg Hackmann .name = "goldfish_pipe", 96291a18a41SGreg Hackmann .of_match_table = goldfish_pipe_of_match, 963d62f324bSJason Hu .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), 964c89f2750SDavid 'Digit' Turner } 965c89f2750SDavid 'Digit' Turner }; 966c89f2750SDavid 'Digit' Turner 967726ea1a8SJin Qian module_platform_driver(goldfish_pipe_driver); 968c89f2750SDavid 'Digit' Turner MODULE_AUTHOR("David Turner <digit@google.com>"); 969c3c4e307SRoman Kiryanov MODULE_LICENSE("GPL v2"); 970