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 { 172726ea1a8SJin Qian /* 173726ea1a8SJin Qian * Global device spinlock. Protects the following members: 174726ea1a8SJin Qian * - pipes, pipes_capacity 175726ea1a8SJin Qian * - [*pipes, *pipes + pipes_capacity) - array data 176726ea1a8SJin Qian * - first_signalled_pipe, 177726ea1a8SJin Qian * goldfish_pipe::prev_signalled, 178726ea1a8SJin Qian * goldfish_pipe::next_signalled, 179726ea1a8SJin Qian * goldfish_pipe::signalled_flags - all singnalled-related fields, 180726ea1a8SJin Qian * in all allocated pipes 181726ea1a8SJin Qian * - open_command_params - PIPE_CMD_OPEN-related buffers 182726ea1a8SJin Qian * 183726ea1a8SJin Qian * It looks like a lot of different fields, but the trick is that 184726ea1a8SJin Qian * the only operation that happens often is the signalled pipes array 185726ea1a8SJin Qian * manipulation. That's why it's OK for now to keep the rest of the 186726ea1a8SJin Qian * fields under the same lock. If we notice too much contention because 187726ea1a8SJin Qian * of PIPE_CMD_OPEN, then we should add a separate lock there. 188726ea1a8SJin Qian */ 189c89f2750SDavid 'Digit' Turner spinlock_t lock; 190726ea1a8SJin Qian 191726ea1a8SJin Qian /* 192726ea1a8SJin Qian * Array of the pipes of |pipes_capacity| elements, 193726ea1a8SJin Qian * indexed by goldfish_pipe::id 194726ea1a8SJin Qian */ 195726ea1a8SJin Qian struct goldfish_pipe **pipes; 196726ea1a8SJin Qian u32 pipes_capacity; 197726ea1a8SJin Qian 198726ea1a8SJin Qian /* Pointers to the buffers host uses for interaction with this driver */ 199726ea1a8SJin Qian struct goldfish_pipe_dev_buffers *buffers; 200726ea1a8SJin Qian 201726ea1a8SJin Qian /* Head of a doubly linked list of signalled pipes */ 202726ea1a8SJin Qian struct goldfish_pipe *first_signalled_pipe; 203726ea1a8SJin Qian 20425b97d57SRoman Kiryanov /* ptr to platform device's device struct */ 20525b97d57SRoman Kiryanov struct device *pdev_dev; 20625b97d57SRoman Kiryanov 207726ea1a8SJin Qian /* Some device-specific data */ 208c89f2750SDavid 'Digit' Turner int irq; 209726ea1a8SJin Qian int version; 210726ea1a8SJin Qian unsigned char __iomem *base; 211c394cc3bSRoman Kiryanov 212c394cc3bSRoman Kiryanov /* an irq tasklet to run goldfish_interrupt_task */ 213c394cc3bSRoman Kiryanov struct tasklet_struct irq_tasklet; 214*43c2cc28SRoman Kiryanov 215*43c2cc28SRoman Kiryanov struct miscdevice miscdev; 216c89f2750SDavid 'Digit' Turner }; 217c89f2750SDavid 'Digit' Turner 2183790e28cSWei Yongjun static struct goldfish_pipe_dev goldfish_pipe_dev; 219c89f2750SDavid 'Digit' Turner 22092c320b9SRoman Kiryanov static int goldfish_pipe_cmd_locked(struct goldfish_pipe *pipe, 22192c320b9SRoman Kiryanov enum PipeCmdCode cmd) 222c89f2750SDavid 'Digit' Turner { 223726ea1a8SJin Qian pipe->command_buffer->cmd = cmd; 224726ea1a8SJin Qian /* failure by default */ 225726ea1a8SJin Qian pipe->command_buffer->status = PIPE_ERROR_INVAL; 226726ea1a8SJin Qian writel(pipe->id, pipe->dev->base + PIPE_REG_CMD); 227726ea1a8SJin Qian return pipe->command_buffer->status; 228726ea1a8SJin Qian } 229c89f2750SDavid 'Digit' Turner 23092c320b9SRoman Kiryanov static int goldfish_pipe_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) 231726ea1a8SJin Qian { 232726ea1a8SJin Qian int status; 233726ea1a8SJin Qian 234726ea1a8SJin Qian if (mutex_lock_interruptible(&pipe->lock)) 235726ea1a8SJin Qian return PIPE_ERROR_IO; 23692c320b9SRoman Kiryanov status = goldfish_pipe_cmd_locked(pipe, cmd); 237726ea1a8SJin Qian mutex_unlock(&pipe->lock); 238c89f2750SDavid 'Digit' Turner return status; 239c89f2750SDavid 'Digit' Turner } 240c89f2750SDavid 'Digit' Turner 241726ea1a8SJin Qian /* 242726ea1a8SJin Qian * This function converts an error code returned by the emulator through 243c89f2750SDavid 'Digit' Turner * the PIPE_REG_STATUS i/o register into a valid negative errno value. 244c89f2750SDavid 'Digit' Turner */ 245c89f2750SDavid 'Digit' Turner static int goldfish_pipe_error_convert(int status) 246c89f2750SDavid 'Digit' Turner { 247c89f2750SDavid 'Digit' Turner switch (status) { 248c89f2750SDavid 'Digit' Turner case PIPE_ERROR_AGAIN: 249c89f2750SDavid 'Digit' Turner return -EAGAIN; 250c89f2750SDavid 'Digit' Turner case PIPE_ERROR_NOMEM: 251c89f2750SDavid 'Digit' Turner return -ENOMEM; 252c89f2750SDavid 'Digit' Turner case PIPE_ERROR_IO: 253c89f2750SDavid 'Digit' Turner return -EIO; 254c89f2750SDavid 'Digit' Turner default: 255c89f2750SDavid 'Digit' Turner return -EINVAL; 256c89f2750SDavid 'Digit' Turner } 257c89f2750SDavid 'Digit' Turner } 258c89f2750SDavid 'Digit' Turner 25952bcc7d9SRoman Kiryanov static int pin_user_pages(unsigned long first_page, 26052bcc7d9SRoman Kiryanov unsigned long last_page, 26152bcc7d9SRoman Kiryanov unsigned int last_page_size, 26252bcc7d9SRoman Kiryanov int is_write, 263726ea1a8SJin Qian struct page *pages[MAX_BUFFERS_PER_COMMAND], 264726ea1a8SJin Qian unsigned int *iter_last_page_size) 265c89f2750SDavid 'Digit' Turner { 266726ea1a8SJin Qian int ret; 267726ea1a8SJin Qian int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; 268c89f2750SDavid 'Digit' Turner 269726ea1a8SJin Qian if (requested_pages > MAX_BUFFERS_PER_COMMAND) { 270726ea1a8SJin Qian requested_pages = MAX_BUFFERS_PER_COMMAND; 271726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 272726ea1a8SJin Qian } else { 273726ea1a8SJin Qian *iter_last_page_size = last_page_size; 274c89f2750SDavid 'Digit' Turner } 275c89f2750SDavid 'Digit' Turner 27652bcc7d9SRoman Kiryanov ret = get_user_pages_fast(first_page, requested_pages, !is_write, 27752bcc7d9SRoman Kiryanov pages); 278726ea1a8SJin Qian if (ret <= 0) 279c89f2750SDavid 'Digit' Turner return -EFAULT; 280726ea1a8SJin Qian if (ret < requested_pages) 281726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 282c89f2750SDavid 'Digit' Turner 2831d1021a0SRoman Kiryanov return ret; 284726ea1a8SJin Qian } 285726ea1a8SJin Qian 286726ea1a8SJin Qian static void release_user_pages(struct page **pages, int pages_count, 287726ea1a8SJin Qian int is_write, s32 consumed_size) 288726ea1a8SJin Qian { 289726ea1a8SJin Qian int i; 290726ea1a8SJin Qian 291726ea1a8SJin Qian for (i = 0; i < pages_count; i++) { 292726ea1a8SJin Qian if (!is_write && consumed_size > 0) 293726ea1a8SJin Qian set_page_dirty(pages[i]); 294726ea1a8SJin Qian put_page(pages[i]); 295726ea1a8SJin Qian } 296726ea1a8SJin Qian } 297726ea1a8SJin Qian 298726ea1a8SJin Qian /* Populate the call parameters, merging adjacent pages together */ 29952bcc7d9SRoman Kiryanov static void populate_rw_params(struct page **pages, 30052bcc7d9SRoman Kiryanov int pages_count, 30152bcc7d9SRoman Kiryanov unsigned long address, 30252bcc7d9SRoman Kiryanov unsigned long address_end, 30352bcc7d9SRoman Kiryanov unsigned long first_page, 30452bcc7d9SRoman Kiryanov unsigned long last_page, 30552bcc7d9SRoman Kiryanov unsigned int iter_last_page_size, 30652bcc7d9SRoman Kiryanov int is_write, 307726ea1a8SJin Qian struct goldfish_pipe_command *command) 308726ea1a8SJin Qian { 309726ea1a8SJin Qian /* 310726ea1a8SJin Qian * Process the first page separately - it's the only page that 311726ea1a8SJin Qian * needs special handling for its start address. 312726ea1a8SJin Qian */ 313726ea1a8SJin Qian unsigned long xaddr = page_to_phys(pages[0]); 314726ea1a8SJin Qian unsigned long xaddr_prev = xaddr; 315726ea1a8SJin Qian int buffer_idx = 0; 316726ea1a8SJin Qian int i = 1; 317726ea1a8SJin Qian int size_on_page = first_page == last_page 318726ea1a8SJin Qian ? (int)(address_end - address) 319726ea1a8SJin Qian : (PAGE_SIZE - (address & ~PAGE_MASK)); 320726ea1a8SJin Qian command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK)); 321726ea1a8SJin Qian command->rw_params.sizes[0] = size_on_page; 322726ea1a8SJin Qian for (; i < pages_count; ++i) { 323726ea1a8SJin Qian xaddr = page_to_phys(pages[i]); 324726ea1a8SJin Qian size_on_page = (i == pages_count - 1) ? 325726ea1a8SJin Qian iter_last_page_size : PAGE_SIZE; 326726ea1a8SJin Qian if (xaddr == xaddr_prev + PAGE_SIZE) { 327726ea1a8SJin Qian command->rw_params.sizes[buffer_idx] += size_on_page; 328726ea1a8SJin Qian } else { 329726ea1a8SJin Qian ++buffer_idx; 330726ea1a8SJin Qian command->rw_params.ptrs[buffer_idx] = (u64)xaddr; 331726ea1a8SJin Qian command->rw_params.sizes[buffer_idx] = size_on_page; 332726ea1a8SJin Qian } 333726ea1a8SJin Qian xaddr_prev = xaddr; 334726ea1a8SJin Qian } 335726ea1a8SJin Qian command->rw_params.buffers_count = buffer_idx + 1; 336726ea1a8SJin Qian } 337726ea1a8SJin Qian 338726ea1a8SJin Qian static int transfer_max_buffers(struct goldfish_pipe *pipe, 33952bcc7d9SRoman Kiryanov unsigned long address, 34052bcc7d9SRoman Kiryanov unsigned long address_end, 34152bcc7d9SRoman Kiryanov int is_write, 34252bcc7d9SRoman Kiryanov unsigned long last_page, 34352bcc7d9SRoman Kiryanov unsigned int last_page_size, 34452bcc7d9SRoman Kiryanov s32 *consumed_size, 34552bcc7d9SRoman Kiryanov int *status) 346726ea1a8SJin Qian { 347726ea1a8SJin Qian unsigned long first_page = address & PAGE_MASK; 348726ea1a8SJin Qian unsigned int iter_last_page_size; 34948a2d422SRoman Kiryanov int pages_count; 350726ea1a8SJin Qian 351726ea1a8SJin Qian /* Serialize access to the pipe command buffers */ 352c89f2750SDavid 'Digit' Turner if (mutex_lock_interruptible(&pipe->lock)) 353c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 354c89f2750SDavid 'Digit' Turner 35548a2d422SRoman Kiryanov pages_count = pin_user_pages(first_page, last_page, 35648a2d422SRoman Kiryanov last_page_size, is_write, 35748a2d422SRoman Kiryanov pipe->pages, &iter_last_page_size); 35848a2d422SRoman Kiryanov if (pages_count < 0) { 35948a2d422SRoman Kiryanov mutex_unlock(&pipe->lock); 36048a2d422SRoman Kiryanov return pages_count; 36148a2d422SRoman Kiryanov } 36248a2d422SRoman Kiryanov 36348a2d422SRoman Kiryanov populate_rw_params(pipe->pages, pages_count, address, address_end, 364726ea1a8SJin Qian first_page, last_page, iter_last_page_size, is_write, 365726ea1a8SJin Qian pipe->command_buffer); 366c89f2750SDavid 'Digit' Turner 367726ea1a8SJin Qian /* Transfer the data */ 36892c320b9SRoman Kiryanov *status = goldfish_pipe_cmd_locked(pipe, 369726ea1a8SJin Qian is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ); 370c89f2750SDavid 'Digit' Turner 371726ea1a8SJin Qian *consumed_size = pipe->command_buffer->rw_params.consumed_size; 3724f42071cSYu Ning 37348a2d422SRoman Kiryanov release_user_pages(pipe->pages, pages_count, is_write, *consumed_size); 374726ea1a8SJin Qian 375f563dab4SGreg Kroah-Hartman mutex_unlock(&pipe->lock); 376726ea1a8SJin Qian return 0; 377c89f2750SDavid 'Digit' Turner } 378c89f2750SDavid 'Digit' Turner 379726ea1a8SJin Qian static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write) 380726ea1a8SJin Qian { 38161b38f02SRoman Kiryanov u32 wake_bit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; 382c89f2750SDavid 'Digit' Turner 38361b38f02SRoman Kiryanov set_bit(wake_bit, &pipe->flags); 384c89f2750SDavid 'Digit' Turner 385c89f2750SDavid 'Digit' Turner /* Tell the emulator we're going to wait for a wake event */ 38692c320b9SRoman Kiryanov goldfish_pipe_cmd(pipe, 387726ea1a8SJin Qian is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ); 388c89f2750SDavid 'Digit' Turner 38961b38f02SRoman Kiryanov while (test_bit(wake_bit, &pipe->flags)) { 390562a74deSRoman Kiryanov if (wait_event_interruptible(pipe->wake_queue, 39161b38f02SRoman Kiryanov !test_bit(wake_bit, &pipe->flags))) 392c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 393c89f2750SDavid 'Digit' Turner 394c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 395c89f2750SDavid 'Digit' Turner return -EIO; 396c89f2750SDavid 'Digit' Turner } 397c89f2750SDavid 'Digit' Turner 398726ea1a8SJin Qian return 0; 399c89f2750SDavid 'Digit' Turner } 4002f3be882SChristoffer Dall 401726ea1a8SJin Qian static ssize_t goldfish_pipe_read_write(struct file *filp, 40252bcc7d9SRoman Kiryanov char __user *buffer, 40352bcc7d9SRoman Kiryanov size_t bufflen, 40452bcc7d9SRoman Kiryanov int is_write) 405726ea1a8SJin Qian { 406726ea1a8SJin Qian struct goldfish_pipe *pipe = filp->private_data; 407726ea1a8SJin Qian int count = 0, ret = -EINVAL; 408726ea1a8SJin Qian unsigned long address, address_end, last_page; 409726ea1a8SJin Qian unsigned int last_page_size; 410726ea1a8SJin Qian 411726ea1a8SJin Qian /* If the emulator already closed the pipe, no need to go further */ 412726ea1a8SJin Qian if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))) 413726ea1a8SJin Qian return -EIO; 414726ea1a8SJin Qian /* Null reads or writes succeeds */ 415726ea1a8SJin Qian if (unlikely(bufflen == 0)) 416726ea1a8SJin Qian return 0; 417726ea1a8SJin Qian /* Check the buffer range for access */ 418726ea1a8SJin Qian if (unlikely(!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, 419726ea1a8SJin Qian buffer, bufflen))) 420726ea1a8SJin Qian return -EFAULT; 421726ea1a8SJin Qian 422726ea1a8SJin Qian address = (unsigned long)buffer; 423726ea1a8SJin Qian address_end = address + bufflen; 424726ea1a8SJin Qian last_page = (address_end - 1) & PAGE_MASK; 425726ea1a8SJin Qian last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1; 426726ea1a8SJin Qian 427726ea1a8SJin Qian while (address < address_end) { 428726ea1a8SJin Qian s32 consumed_size; 429726ea1a8SJin Qian int status; 430726ea1a8SJin Qian 431726ea1a8SJin Qian ret = transfer_max_buffers(pipe, address, address_end, is_write, 43252bcc7d9SRoman Kiryanov last_page, last_page_size, 43352bcc7d9SRoman Kiryanov &consumed_size, &status); 4342f3be882SChristoffer Dall if (ret < 0) 435726ea1a8SJin Qian break; 436726ea1a8SJin Qian 437726ea1a8SJin Qian if (consumed_size > 0) { 438726ea1a8SJin Qian /* No matter what's the status, we've transferred 439726ea1a8SJin Qian * something. 440726ea1a8SJin Qian */ 441726ea1a8SJin Qian count += consumed_size; 442726ea1a8SJin Qian address += consumed_size; 443726ea1a8SJin Qian } 444726ea1a8SJin Qian if (status > 0) 445726ea1a8SJin Qian continue; 446726ea1a8SJin Qian if (status == 0) { 447726ea1a8SJin Qian /* EOF */ 448726ea1a8SJin Qian ret = 0; 449726ea1a8SJin Qian break; 450726ea1a8SJin Qian } 451726ea1a8SJin Qian if (count > 0) { 452726ea1a8SJin Qian /* 453726ea1a8SJin Qian * An error occurred, but we already transferred 454726ea1a8SJin Qian * something on one of the previous iterations. 455726ea1a8SJin Qian * Just return what we already copied and log this 456726ea1a8SJin Qian * err. 457726ea1a8SJin Qian */ 458726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN) 45925b97d57SRoman Kiryanov dev_err_ratelimited(pipe->dev->pdev_dev, 46025b97d57SRoman Kiryanov "backend error %d on %s\n", 461726ea1a8SJin Qian status, is_write ? "write" : "read"); 462726ea1a8SJin Qian break; 463726ea1a8SJin Qian } 464726ea1a8SJin Qian 465726ea1a8SJin Qian /* 466726ea1a8SJin Qian * If the error is not PIPE_ERROR_AGAIN, or if we are in 467726ea1a8SJin Qian * non-blocking mode, just return the error code. 468726ea1a8SJin Qian */ 469726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN || 470726ea1a8SJin Qian (filp->f_flags & O_NONBLOCK) != 0) { 471726ea1a8SJin Qian ret = goldfish_pipe_error_convert(status); 472726ea1a8SJin Qian break; 473726ea1a8SJin Qian } 474726ea1a8SJin Qian 475726ea1a8SJin Qian status = wait_for_host_signal(pipe, is_write); 476726ea1a8SJin Qian if (status < 0) 477726ea1a8SJin Qian return status; 478726ea1a8SJin Qian } 479726ea1a8SJin Qian 480726ea1a8SJin Qian if (count > 0) 4812f3be882SChristoffer Dall return count; 482726ea1a8SJin Qian return ret; 483c89f2750SDavid 'Digit' Turner } 484c89f2750SDavid 'Digit' Turner 485c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, 486c89f2750SDavid 'Digit' Turner size_t bufflen, loff_t *ppos) 487c89f2750SDavid 'Digit' Turner { 488726ea1a8SJin Qian return goldfish_pipe_read_write(filp, buffer, bufflen, 489726ea1a8SJin Qian /* is_write */ 0); 490c89f2750SDavid 'Digit' Turner } 491c89f2750SDavid 'Digit' Turner 492c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_write(struct file *filp, 493c89f2750SDavid 'Digit' Turner const char __user *buffer, size_t bufflen, 494c89f2750SDavid 'Digit' Turner loff_t *ppos) 495c89f2750SDavid 'Digit' Turner { 49652bcc7d9SRoman Kiryanov /* cast away the const */ 49752bcc7d9SRoman Kiryanov char __user *no_const_buffer = (char __user *)buffer; 49852bcc7d9SRoman Kiryanov 49952bcc7d9SRoman Kiryanov return goldfish_pipe_read_write(filp, no_const_buffer, bufflen, 500726ea1a8SJin Qian /* is_write */ 1); 501c89f2750SDavid 'Digit' Turner } 502c89f2750SDavid 'Digit' Turner 503afc9a42bSAl Viro static __poll_t goldfish_pipe_poll(struct file *filp, poll_table *wait) 504c89f2750SDavid 'Digit' Turner { 505c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 506afc9a42bSAl Viro __poll_t mask = 0; 507c89f2750SDavid 'Digit' Turner int status; 508c89f2750SDavid 'Digit' Turner 509c89f2750SDavid 'Digit' Turner poll_wait(filp, &pipe->wake_queue, wait); 510c89f2750SDavid 'Digit' Turner 51192c320b9SRoman Kiryanov status = goldfish_pipe_cmd(pipe, PIPE_CMD_POLL); 512726ea1a8SJin Qian if (status < 0) 513726ea1a8SJin Qian return -ERESTARTSYS; 514c89f2750SDavid 'Digit' Turner 515c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_IN) 516a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM; 517c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_OUT) 518a9a08845SLinus Torvalds mask |= EPOLLOUT | EPOLLWRNORM; 519c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_HUP) 520a9a08845SLinus Torvalds mask |= EPOLLHUP; 521c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 522a9a08845SLinus Torvalds mask |= EPOLLERR; 523c89f2750SDavid 'Digit' Turner 524c89f2750SDavid 'Digit' Turner return mask; 525c89f2750SDavid 'Digit' Turner } 526c89f2750SDavid 'Digit' Turner 527726ea1a8SJin Qian static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev, 528726ea1a8SJin Qian u32 id, u32 flags) 529c89f2750SDavid 'Digit' Turner { 530c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe; 53149a75c44SJun Tian 532726ea1a8SJin Qian if (WARN_ON(id >= dev->pipes_capacity)) 533726ea1a8SJin Qian return; 53425c72c78SJun Tian 535726ea1a8SJin Qian pipe = dev->pipes[id]; 536726ea1a8SJin Qian if (!pipe) 537726ea1a8SJin Qian return; 538726ea1a8SJin Qian pipe->signalled_flags |= flags; 539c89f2750SDavid 'Digit' Turner 540cc14057fSRoman Kiryanov if (pipe->prev_signalled || pipe->next_signalled || 541cc14057fSRoman Kiryanov dev->first_signalled_pipe == pipe) 542726ea1a8SJin Qian return; /* already in the list */ 543726ea1a8SJin Qian pipe->next_signalled = dev->first_signalled_pipe; 544726ea1a8SJin Qian if (dev->first_signalled_pipe) 545726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = pipe; 546726ea1a8SJin Qian dev->first_signalled_pipe = pipe; 547c89f2750SDavid 'Digit' Turner } 548726ea1a8SJin Qian 549726ea1a8SJin Qian static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev, 55053bdf668SRoman Kiryanov struct goldfish_pipe *pipe) 55153bdf668SRoman Kiryanov { 552726ea1a8SJin Qian if (pipe->prev_signalled) 553726ea1a8SJin Qian pipe->prev_signalled->next_signalled = pipe->next_signalled; 554726ea1a8SJin Qian if (pipe->next_signalled) 555726ea1a8SJin Qian pipe->next_signalled->prev_signalled = pipe->prev_signalled; 556726ea1a8SJin Qian if (pipe == dev->first_signalled_pipe) 557726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 558726ea1a8SJin Qian pipe->prev_signalled = NULL; 559726ea1a8SJin Qian pipe->next_signalled = NULL; 560726ea1a8SJin Qian } 561726ea1a8SJin Qian 562726ea1a8SJin Qian static struct goldfish_pipe *signalled_pipes_pop_front( 563726ea1a8SJin Qian struct goldfish_pipe_dev *dev, int *wakes) 564726ea1a8SJin Qian { 565726ea1a8SJin Qian struct goldfish_pipe *pipe; 566726ea1a8SJin Qian unsigned long flags; 567726ea1a8SJin Qian 568726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 569726ea1a8SJin Qian 570726ea1a8SJin Qian pipe = dev->first_signalled_pipe; 571726ea1a8SJin Qian if (pipe) { 572726ea1a8SJin Qian *wakes = pipe->signalled_flags; 573726ea1a8SJin Qian pipe->signalled_flags = 0; 574726ea1a8SJin Qian /* 575726ea1a8SJin Qian * This is an optimized version of 576726ea1a8SJin Qian * signalled_pipes_remove_locked() 577726ea1a8SJin Qian * - We want to make it as fast as possible to 578726ea1a8SJin Qian * wake the sleeping pipe operations faster. 579726ea1a8SJin Qian */ 580726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 581726ea1a8SJin Qian if (dev->first_signalled_pipe) 582726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = NULL; 583726ea1a8SJin Qian pipe->next_signalled = NULL; 584726ea1a8SJin Qian } 585726ea1a8SJin Qian 586726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 587726ea1a8SJin Qian return pipe; 588726ea1a8SJin Qian } 589726ea1a8SJin Qian 590c394cc3bSRoman Kiryanov static void goldfish_interrupt_task(unsigned long dev_addr) 591726ea1a8SJin Qian { 592726ea1a8SJin Qian /* Iterate over the signalled pipes and wake them one by one */ 593c394cc3bSRoman Kiryanov struct goldfish_pipe_dev *dev = (struct goldfish_pipe_dev *)dev_addr; 594726ea1a8SJin Qian struct goldfish_pipe *pipe; 595726ea1a8SJin Qian int wakes; 596726ea1a8SJin Qian 597c394cc3bSRoman Kiryanov while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) { 598726ea1a8SJin Qian if (wakes & PIPE_WAKE_CLOSED) { 599726ea1a8SJin Qian pipe->flags = 1 << BIT_CLOSED_ON_HOST; 600726ea1a8SJin Qian } else { 601c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_READ) 602c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_READ, &pipe->flags); 603c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_WRITE) 604c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); 605c89f2750SDavid 'Digit' Turner } 606726ea1a8SJin Qian /* 607726ea1a8SJin Qian * wake_up_interruptible() implies a write barrier, so don't 608726ea1a8SJin Qian * explicitly add another one here. 609726ea1a8SJin Qian */ 610726ea1a8SJin Qian wake_up_interruptible(&pipe->wake_queue); 611726ea1a8SJin Qian } 612726ea1a8SJin Qian } 613c89f2750SDavid 'Digit' Turner 614726ea1a8SJin Qian /* 615726ea1a8SJin Qian * The general idea of the interrupt handling: 616726ea1a8SJin Qian * 617726ea1a8SJin Qian * 1. device raises an interrupt if there's at least one signalled pipe 618726ea1a8SJin Qian * 2. IRQ handler reads the signalled pipes and their count from the device 619726ea1a8SJin Qian * 3. device writes them into a shared buffer and returns the count 620726ea1a8SJin Qian * it only resets the IRQ if it has returned all signalled pipes, 621726ea1a8SJin Qian * otherwise it leaves it raised, so IRQ handler will be called 622726ea1a8SJin Qian * again for the next chunk 623726ea1a8SJin Qian * 4. IRQ handler adds all returned pipes to the device's signalled pipes list 624726ea1a8SJin Qian * 5. IRQ handler launches a tasklet to process the signalled pipes from the 625726ea1a8SJin Qian * list in a separate context 626726ea1a8SJin Qian */ 627726ea1a8SJin Qian static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) 628726ea1a8SJin Qian { 629726ea1a8SJin Qian u32 count; 630726ea1a8SJin Qian u32 i; 631726ea1a8SJin Qian unsigned long flags; 632726ea1a8SJin Qian struct goldfish_pipe_dev *dev = dev_id; 633726ea1a8SJin Qian 634869fd502SRoman Kiryanov if (dev != &goldfish_pipe_dev) 635726ea1a8SJin Qian return IRQ_NONE; 636726ea1a8SJin Qian 637726ea1a8SJin Qian /* Request the signalled pipes from the device */ 638726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 639726ea1a8SJin Qian 640726ea1a8SJin Qian count = readl(dev->base + PIPE_REG_GET_SIGNALLED); 641726ea1a8SJin Qian if (count == 0) { 642726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 643726ea1a8SJin Qian return IRQ_NONE; 644726ea1a8SJin Qian } 645726ea1a8SJin Qian if (count > MAX_SIGNALLED_PIPES) 646726ea1a8SJin Qian count = MAX_SIGNALLED_PIPES; 647726ea1a8SJin Qian 648726ea1a8SJin Qian for (i = 0; i < count; ++i) 649726ea1a8SJin Qian signalled_pipes_add_locked(dev, 650726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].id, 651726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].flags); 652726ea1a8SJin Qian 653726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 654726ea1a8SJin Qian 655c394cc3bSRoman Kiryanov tasklet_schedule(&dev->irq_tasklet); 656726ea1a8SJin Qian return IRQ_HANDLED; 657726ea1a8SJin Qian } 658726ea1a8SJin Qian 659726ea1a8SJin Qian static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) 660726ea1a8SJin Qian { 661726ea1a8SJin Qian int id; 662726ea1a8SJin Qian 663726ea1a8SJin Qian for (id = 0; id < dev->pipes_capacity; ++id) 664726ea1a8SJin Qian if (!dev->pipes[id]) 665726ea1a8SJin Qian return id; 666726ea1a8SJin Qian 667726ea1a8SJin Qian { 66884ae527aSRoman Kiryanov /* Reallocate the array. 66984ae527aSRoman Kiryanov * Since get_free_pipe_id_locked runs with interrupts disabled, 67084ae527aSRoman Kiryanov * we don't want to make calls that could lead to sleep. 67184ae527aSRoman Kiryanov */ 672726ea1a8SJin Qian u32 new_capacity = 2 * dev->pipes_capacity; 673726ea1a8SJin Qian struct goldfish_pipe **pipes = 6743eff8ecdSWei Yongjun kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC); 675726ea1a8SJin Qian if (!pipes) 676726ea1a8SJin Qian return -ENOMEM; 677726ea1a8SJin Qian memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); 678726ea1a8SJin Qian kfree(dev->pipes); 679726ea1a8SJin Qian dev->pipes = pipes; 680726ea1a8SJin Qian id = dev->pipes_capacity; 681726ea1a8SJin Qian dev->pipes_capacity = new_capacity; 682726ea1a8SJin Qian } 683726ea1a8SJin Qian return id; 684c89f2750SDavid 'Digit' Turner } 685c89f2750SDavid 'Digit' Turner 686c89f2750SDavid 'Digit' Turner /** 687c89f2750SDavid 'Digit' Turner * goldfish_pipe_open - open a channel to the AVD 688c89f2750SDavid 'Digit' Turner * @inode: inode of device 689c89f2750SDavid 'Digit' Turner * @file: file struct of opener 690c89f2750SDavid 'Digit' Turner * 691c89f2750SDavid 'Digit' Turner * Create a new pipe link between the emulator and the use application. 692c89f2750SDavid 'Digit' Turner * Each new request produces a new pipe. 693c89f2750SDavid 'Digit' Turner * 694c89f2750SDavid 'Digit' Turner * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit 695c89f2750SDavid 'Digit' Turner * right now so this is fine. A move to 64bit will need this addressing 696c89f2750SDavid 'Digit' Turner */ 697c89f2750SDavid 'Digit' Turner static int goldfish_pipe_open(struct inode *inode, struct file *file) 698c89f2750SDavid 'Digit' Turner { 699869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 700726ea1a8SJin Qian unsigned long flags; 701726ea1a8SJin Qian int id; 702726ea1a8SJin Qian int status; 703c89f2750SDavid 'Digit' Turner 704c89f2750SDavid 'Digit' Turner /* Allocate new pipe kernel object */ 705726ea1a8SJin Qian struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); 706bfb8e838SRoman Kiryanov if (!pipe) 707c89f2750SDavid 'Digit' Turner return -ENOMEM; 708c89f2750SDavid 'Digit' Turner 709c89f2750SDavid 'Digit' Turner pipe->dev = dev; 710c89f2750SDavid 'Digit' Turner mutex_init(&pipe->lock); 711c89f2750SDavid 'Digit' Turner init_waitqueue_head(&pipe->wake_queue); 712c89f2750SDavid 'Digit' Turner 713c89f2750SDavid 'Digit' Turner /* 714726ea1a8SJin Qian * Command buffer needs to be allocated on its own page to make sure 715726ea1a8SJin Qian * it is physically contiguous in host's address space. 716c89f2750SDavid 'Digit' Turner */ 717d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE); 718726ea1a8SJin Qian pipe->command_buffer = 719726ea1a8SJin Qian (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL); 720726ea1a8SJin Qian if (!pipe->command_buffer) { 721726ea1a8SJin Qian status = -ENOMEM; 722726ea1a8SJin Qian goto err_pipe; 723726ea1a8SJin Qian } 724c89f2750SDavid 'Digit' Turner 725726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 726726ea1a8SJin Qian 727726ea1a8SJin Qian id = get_free_pipe_id_locked(dev); 728726ea1a8SJin Qian if (id < 0) { 729726ea1a8SJin Qian status = id; 730726ea1a8SJin Qian goto err_id_locked; 731726ea1a8SJin Qian } 732726ea1a8SJin Qian 733726ea1a8SJin Qian dev->pipes[id] = pipe; 734726ea1a8SJin Qian pipe->id = id; 735726ea1a8SJin Qian pipe->command_buffer->id = id; 736726ea1a8SJin Qian 737726ea1a8SJin Qian /* Now tell the emulator we're opening a new pipe. */ 738726ea1a8SJin Qian dev->buffers->open_command_params.rw_params_max_count = 739726ea1a8SJin Qian MAX_BUFFERS_PER_COMMAND; 740726ea1a8SJin Qian dev->buffers->open_command_params.command_buffer_ptr = 741726ea1a8SJin Qian (u64)(unsigned long)__pa(pipe->command_buffer); 74292c320b9SRoman Kiryanov status = goldfish_pipe_cmd_locked(pipe, PIPE_CMD_OPEN); 743726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 744726ea1a8SJin Qian if (status < 0) 745726ea1a8SJin Qian goto err_cmd; 746726ea1a8SJin Qian /* All is done, save the pipe into the file's private data field */ 747726ea1a8SJin Qian file->private_data = pipe; 748726ea1a8SJin Qian return 0; 749726ea1a8SJin Qian 750726ea1a8SJin Qian err_cmd: 751726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 752726ea1a8SJin Qian dev->pipes[id] = NULL; 753726ea1a8SJin Qian err_id_locked: 754726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 755726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 756726ea1a8SJin Qian err_pipe: 757c89f2750SDavid 'Digit' Turner kfree(pipe); 758c89f2750SDavid 'Digit' Turner return status; 759c89f2750SDavid 'Digit' Turner } 760c89f2750SDavid 'Digit' Turner 761c89f2750SDavid 'Digit' Turner static int goldfish_pipe_release(struct inode *inode, struct file *filp) 762c89f2750SDavid 'Digit' Turner { 763726ea1a8SJin Qian unsigned long flags; 764c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 765726ea1a8SJin Qian struct goldfish_pipe_dev *dev = pipe->dev; 766c89f2750SDavid 'Digit' Turner 767c89f2750SDavid 'Digit' Turner /* The guest is closing the channel, so tell the emulator right now */ 76892c320b9SRoman Kiryanov goldfish_pipe_cmd(pipe, PIPE_CMD_CLOSE); 769726ea1a8SJin Qian 770726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 771726ea1a8SJin Qian dev->pipes[pipe->id] = NULL; 772726ea1a8SJin Qian signalled_pipes_remove_locked(dev, pipe); 773726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 774726ea1a8SJin Qian 775c89f2750SDavid 'Digit' Turner filp->private_data = NULL; 776726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 777726ea1a8SJin Qian kfree(pipe); 778c89f2750SDavid 'Digit' Turner return 0; 779c89f2750SDavid 'Digit' Turner } 780c89f2750SDavid 'Digit' Turner 781c89f2750SDavid 'Digit' Turner static const struct file_operations goldfish_pipe_fops = { 782c89f2750SDavid 'Digit' Turner .owner = THIS_MODULE, 783c89f2750SDavid 'Digit' Turner .read = goldfish_pipe_read, 784c89f2750SDavid 'Digit' Turner .write = goldfish_pipe_write, 785c89f2750SDavid 'Digit' Turner .poll = goldfish_pipe_poll, 786c89f2750SDavid 'Digit' Turner .open = goldfish_pipe_open, 787c89f2750SDavid 'Digit' Turner .release = goldfish_pipe_release, 788c89f2750SDavid 'Digit' Turner }; 789c89f2750SDavid 'Digit' Turner 790*43c2cc28SRoman Kiryanov static void init_miscdevice(struct miscdevice *miscdev) 791*43c2cc28SRoman Kiryanov { 792*43c2cc28SRoman Kiryanov memset(miscdev, 0, sizeof(*miscdev)); 793*43c2cc28SRoman Kiryanov 794*43c2cc28SRoman Kiryanov miscdev->minor = MISC_DYNAMIC_MINOR; 795*43c2cc28SRoman Kiryanov miscdev->name = "goldfish_pipe"; 796*43c2cc28SRoman Kiryanov miscdev->fops = &goldfish_pipe_fops; 797*43c2cc28SRoman Kiryanov } 798c89f2750SDavid 'Digit' Turner 799610a72b7SRoman Kiryanov static void write_pa_addr(void *addr, void __iomem *portl, void __iomem *porth) 800610a72b7SRoman Kiryanov { 801610a72b7SRoman Kiryanov const unsigned long paddr = __pa(addr); 802610a72b7SRoman Kiryanov 803610a72b7SRoman Kiryanov writel(upper_32_bits(paddr), porth); 804610a72b7SRoman Kiryanov writel(lower_32_bits(paddr), portl); 805610a72b7SRoman Kiryanov } 806610a72b7SRoman Kiryanov 807726ea1a8SJin Qian static int goldfish_pipe_device_init(struct platform_device *pdev) 808726ea1a8SJin Qian { 809869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 810c394cc3bSRoman Kiryanov int err; 811c394cc3bSRoman Kiryanov 812c394cc3bSRoman Kiryanov tasklet_init(&dev->irq_tasklet, &goldfish_interrupt_task, 813c394cc3bSRoman Kiryanov (unsigned long)dev); 814c394cc3bSRoman Kiryanov 815c394cc3bSRoman Kiryanov err = devm_request_irq(&pdev->dev, dev->irq, 816726ea1a8SJin Qian goldfish_pipe_interrupt, 817726ea1a8SJin Qian IRQF_SHARED, "goldfish_pipe", dev); 818726ea1a8SJin Qian if (err) { 819726ea1a8SJin Qian dev_err(&pdev->dev, "unable to allocate IRQ for v2\n"); 820726ea1a8SJin Qian return err; 821726ea1a8SJin Qian } 822726ea1a8SJin Qian 823*43c2cc28SRoman Kiryanov init_miscdevice(&dev->miscdev); 824*43c2cc28SRoman Kiryanov err = misc_register(&dev->miscdev); 825726ea1a8SJin Qian if (err) { 826726ea1a8SJin Qian dev_err(&pdev->dev, "unable to register v2 device\n"); 827726ea1a8SJin Qian return err; 828726ea1a8SJin Qian } 829726ea1a8SJin Qian 83025b97d57SRoman Kiryanov dev->pdev_dev = &pdev->dev; 831726ea1a8SJin Qian dev->first_signalled_pipe = NULL; 832726ea1a8SJin Qian dev->pipes_capacity = INITIAL_PIPES_CAPACITY; 833726ea1a8SJin Qian dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), 834726ea1a8SJin Qian GFP_KERNEL); 835726ea1a8SJin Qian if (!dev->pipes) 836726ea1a8SJin Qian return -ENOMEM; 837726ea1a8SJin Qian 838726ea1a8SJin Qian /* 839726ea1a8SJin Qian * We're going to pass two buffers, open_command_params and 840726ea1a8SJin Qian * signalled_pipe_buffers, to the host. This means each of those buffers 841726ea1a8SJin Qian * needs to be contained in a single physical page. The easiest choice 842726ea1a8SJin Qian * is to just allocate a page and place the buffers in it. 843726ea1a8SJin Qian */ 844d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_dev_buffers) > PAGE_SIZE); 8452ed43e53SRoman Kiryanov dev->buffers = (struct goldfish_pipe_dev_buffers *) 8462ed43e53SRoman Kiryanov __get_free_page(GFP_KERNEL); 8472ed43e53SRoman Kiryanov if (!dev->buffers) { 848726ea1a8SJin Qian kfree(dev->pipes); 849726ea1a8SJin Qian return -ENOMEM; 850726ea1a8SJin Qian } 851726ea1a8SJin Qian 852726ea1a8SJin Qian /* Send the buffer addresses to the host */ 853610a72b7SRoman Kiryanov write_pa_addr(&dev->buffers->signalled_pipe_buffers, 854610a72b7SRoman Kiryanov dev->base + PIPE_REG_SIGNAL_BUFFER, 855726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH); 856610a72b7SRoman Kiryanov 857468e62f9SRoman Kiryanov writel(MAX_SIGNALLED_PIPES, 858726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT); 859726ea1a8SJin Qian 860610a72b7SRoman Kiryanov write_pa_addr(&dev->buffers->open_command_params, 861610a72b7SRoman Kiryanov dev->base + PIPE_REG_OPEN_BUFFER, 862726ea1a8SJin Qian dev->base + PIPE_REG_OPEN_BUFFER_HIGH); 863610a72b7SRoman Kiryanov 864726ea1a8SJin Qian return 0; 865726ea1a8SJin Qian } 866726ea1a8SJin Qian 867726ea1a8SJin Qian static void goldfish_pipe_device_deinit(struct platform_device *pdev) 868726ea1a8SJin Qian { 869*43c2cc28SRoman Kiryanov misc_deregister(&goldfish_pipe_dev.miscdev); 870c394cc3bSRoman Kiryanov tasklet_kill(&goldfish_pipe_dev.irq_tasklet); 871869fd502SRoman Kiryanov kfree(goldfish_pipe_dev.pipes); 872869fd502SRoman Kiryanov free_page((unsigned long)goldfish_pipe_dev.buffers); 873726ea1a8SJin Qian } 874726ea1a8SJin Qian 875c89f2750SDavid 'Digit' Turner static int goldfish_pipe_probe(struct platform_device *pdev) 876c89f2750SDavid 'Digit' Turner { 877c89f2750SDavid 'Digit' Turner int err; 878c89f2750SDavid 'Digit' Turner struct resource *r; 879869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 880c89f2750SDavid 'Digit' Turner 881c89f2750SDavid 'Digit' Turner /* not thread safe, but this should not happen */ 882bfb8e838SRoman Kiryanov WARN_ON(dev->base); 883c89f2750SDavid 'Digit' Turner 884c89f2750SDavid 'Digit' Turner spin_lock_init(&dev->lock); 885c89f2750SDavid 'Digit' Turner 886c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 887bfb8e838SRoman Kiryanov if (!r || resource_size(r) < PAGE_SIZE) { 888c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "can't allocate i/o page\n"); 889c89f2750SDavid 'Digit' Turner return -EINVAL; 890c89f2750SDavid 'Digit' Turner } 891c89f2750SDavid 'Digit' Turner dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); 892bfb8e838SRoman Kiryanov if (!dev->base) { 893c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "ioremap failed\n"); 894c89f2750SDavid 'Digit' Turner return -EINVAL; 895c89f2750SDavid 'Digit' Turner } 896c89f2750SDavid 'Digit' Turner 897c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 898bfb8e838SRoman Kiryanov if (!r) { 899c89f2750SDavid 'Digit' Turner err = -EINVAL; 900c89f2750SDavid 'Digit' Turner goto error; 901c89f2750SDavid 'Digit' Turner } 902c89f2750SDavid 'Digit' Turner dev->irq = r->start; 903c89f2750SDavid 'Digit' Turner 904726ea1a8SJin Qian /* 905726ea1a8SJin Qian * Exchange the versions with the host device 906726ea1a8SJin Qian * 907726ea1a8SJin Qian * Note: v1 driver used to not report its version, so we write it before 908726ea1a8SJin Qian * reading device version back: this allows the host implementation to 909726ea1a8SJin Qian * detect the old driver (if there was no version write before read). 9104f42071cSYu Ning */ 911726ea1a8SJin Qian writel((u32)PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION); 9124f42071cSYu Ning dev->version = readl(dev->base + PIPE_REG_VERSION); 913726ea1a8SJin Qian if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION)) 914726ea1a8SJin Qian return -EINVAL; 915726ea1a8SJin Qian 916726ea1a8SJin Qian err = goldfish_pipe_device_init(pdev); 917726ea1a8SJin Qian if (!err) 918c89f2750SDavid 'Digit' Turner return 0; 919c89f2750SDavid 'Digit' Turner 920c89f2750SDavid 'Digit' Turner error: 921c89f2750SDavid 'Digit' Turner dev->base = NULL; 922c89f2750SDavid 'Digit' Turner return err; 923c89f2750SDavid 'Digit' Turner } 924c89f2750SDavid 'Digit' Turner 925c89f2750SDavid 'Digit' Turner static int goldfish_pipe_remove(struct platform_device *pdev) 926c89f2750SDavid 'Digit' Turner { 927869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 928726ea1a8SJin Qian goldfish_pipe_device_deinit(pdev); 929c89f2750SDavid 'Digit' Turner dev->base = NULL; 930c89f2750SDavid 'Digit' Turner return 0; 931c89f2750SDavid 'Digit' Turner } 932c89f2750SDavid 'Digit' Turner 933d62f324bSJason Hu static const struct acpi_device_id goldfish_pipe_acpi_match[] = { 934d62f324bSJason Hu { "GFSH0003", 0 }, 935d62f324bSJason Hu { }, 936d62f324bSJason Hu }; 937d62f324bSJason Hu MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); 938d62f324bSJason Hu 93991a18a41SGreg Hackmann static const struct of_device_id goldfish_pipe_of_match[] = { 94091a18a41SGreg Hackmann { .compatible = "google,android-pipe", }, 94191a18a41SGreg Hackmann {}, 94291a18a41SGreg Hackmann }; 94391a18a41SGreg Hackmann MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); 94491a18a41SGreg Hackmann 945726ea1a8SJin Qian static struct platform_driver goldfish_pipe_driver = { 946c89f2750SDavid 'Digit' Turner .probe = goldfish_pipe_probe, 947c89f2750SDavid 'Digit' Turner .remove = goldfish_pipe_remove, 948c89f2750SDavid 'Digit' Turner .driver = { 94991a18a41SGreg Hackmann .name = "goldfish_pipe", 95091a18a41SGreg Hackmann .of_match_table = goldfish_pipe_of_match, 951d62f324bSJason Hu .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), 952c89f2750SDavid 'Digit' Turner } 953c89f2750SDavid 'Digit' Turner }; 954c89f2750SDavid 'Digit' Turner 955726ea1a8SJin Qian module_platform_driver(goldfish_pipe_driver); 956c89f2750SDavid 'Digit' Turner MODULE_AUTHOR("David Turner <digit@google.com>"); 957c3c4e307SRoman Kiryanov MODULE_LICENSE("GPL v2"); 958