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 2601023369cSJohn Hubbard static int goldfish_pin_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 27757459435SJohn Hubbard ret = pin_user_pages_fast(first_page, requested_pages, 27873b0140bSIra Weiny !is_write ? FOLL_WRITE : 0, 27952bcc7d9SRoman Kiryanov pages); 280726ea1a8SJin Qian if (ret <= 0) 281c89f2750SDavid 'Digit' Turner return -EFAULT; 282726ea1a8SJin Qian if (ret < requested_pages) 283726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 284c89f2750SDavid 'Digit' Turner 2851d1021a0SRoman Kiryanov return ret; 286726ea1a8SJin Qian } 287726ea1a8SJin Qian 288726ea1a8SJin Qian /* Populate the call parameters, merging adjacent pages together */ 28952bcc7d9SRoman Kiryanov static void populate_rw_params(struct page **pages, 29052bcc7d9SRoman Kiryanov int pages_count, 29152bcc7d9SRoman Kiryanov unsigned long address, 29252bcc7d9SRoman Kiryanov unsigned long address_end, 29352bcc7d9SRoman Kiryanov unsigned long first_page, 29452bcc7d9SRoman Kiryanov unsigned long last_page, 29552bcc7d9SRoman Kiryanov unsigned int iter_last_page_size, 29652bcc7d9SRoman Kiryanov int is_write, 297726ea1a8SJin Qian struct goldfish_pipe_command *command) 298726ea1a8SJin Qian { 299726ea1a8SJin Qian /* 300726ea1a8SJin Qian * Process the first page separately - it's the only page that 301726ea1a8SJin Qian * needs special handling for its start address. 302726ea1a8SJin Qian */ 303726ea1a8SJin Qian unsigned long xaddr = page_to_phys(pages[0]); 304726ea1a8SJin Qian unsigned long xaddr_prev = xaddr; 305726ea1a8SJin Qian int buffer_idx = 0; 306726ea1a8SJin Qian int i = 1; 307726ea1a8SJin Qian int size_on_page = first_page == last_page 308726ea1a8SJin Qian ? (int)(address_end - address) 309726ea1a8SJin Qian : (PAGE_SIZE - (address & ~PAGE_MASK)); 310726ea1a8SJin Qian command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK)); 311726ea1a8SJin Qian command->rw_params.sizes[0] = size_on_page; 312726ea1a8SJin Qian for (; i < pages_count; ++i) { 313726ea1a8SJin Qian xaddr = page_to_phys(pages[i]); 314726ea1a8SJin Qian size_on_page = (i == pages_count - 1) ? 315726ea1a8SJin Qian iter_last_page_size : PAGE_SIZE; 316726ea1a8SJin Qian if (xaddr == xaddr_prev + PAGE_SIZE) { 317726ea1a8SJin Qian command->rw_params.sizes[buffer_idx] += size_on_page; 318726ea1a8SJin Qian } else { 319726ea1a8SJin Qian ++buffer_idx; 320726ea1a8SJin Qian command->rw_params.ptrs[buffer_idx] = (u64)xaddr; 321726ea1a8SJin Qian command->rw_params.sizes[buffer_idx] = size_on_page; 322726ea1a8SJin Qian } 323726ea1a8SJin Qian xaddr_prev = xaddr; 324726ea1a8SJin Qian } 325726ea1a8SJin Qian command->rw_params.buffers_count = buffer_idx + 1; 326726ea1a8SJin Qian } 327726ea1a8SJin Qian 328726ea1a8SJin Qian static int transfer_max_buffers(struct goldfish_pipe *pipe, 32952bcc7d9SRoman Kiryanov unsigned long address, 33052bcc7d9SRoman Kiryanov unsigned long address_end, 33152bcc7d9SRoman Kiryanov int is_write, 33252bcc7d9SRoman Kiryanov unsigned long last_page, 33352bcc7d9SRoman Kiryanov unsigned int last_page_size, 33452bcc7d9SRoman Kiryanov s32 *consumed_size, 33552bcc7d9SRoman Kiryanov int *status) 336726ea1a8SJin Qian { 337726ea1a8SJin Qian unsigned long first_page = address & PAGE_MASK; 338726ea1a8SJin Qian unsigned int iter_last_page_size; 33948a2d422SRoman Kiryanov int pages_count; 340726ea1a8SJin Qian 341726ea1a8SJin Qian /* Serialize access to the pipe command buffers */ 342c89f2750SDavid 'Digit' Turner if (mutex_lock_interruptible(&pipe->lock)) 343c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 344c89f2750SDavid 'Digit' Turner 3451023369cSJohn Hubbard pages_count = goldfish_pin_pages(first_page, last_page, 34648a2d422SRoman Kiryanov last_page_size, is_write, 34748a2d422SRoman Kiryanov pipe->pages, &iter_last_page_size); 34848a2d422SRoman Kiryanov if (pages_count < 0) { 34948a2d422SRoman Kiryanov mutex_unlock(&pipe->lock); 35048a2d422SRoman Kiryanov return pages_count; 35148a2d422SRoman Kiryanov } 35248a2d422SRoman Kiryanov 35348a2d422SRoman Kiryanov populate_rw_params(pipe->pages, pages_count, address, address_end, 354726ea1a8SJin Qian first_page, last_page, iter_last_page_size, is_write, 355726ea1a8SJin Qian pipe->command_buffer); 356c89f2750SDavid 'Digit' Turner 357726ea1a8SJin Qian /* Transfer the data */ 35892c320b9SRoman Kiryanov *status = goldfish_pipe_cmd_locked(pipe, 359726ea1a8SJin Qian is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ); 360c89f2750SDavid 'Digit' Turner 361726ea1a8SJin Qian *consumed_size = pipe->command_buffer->rw_params.consumed_size; 3624f42071cSYu Ning 363*f1f6a7ddSJohn Hubbard unpin_user_pages_dirty_lock(pipe->pages, pages_count, 36457459435SJohn Hubbard !is_write && *consumed_size > 0); 365726ea1a8SJin Qian 366f563dab4SGreg Kroah-Hartman mutex_unlock(&pipe->lock); 367726ea1a8SJin Qian return 0; 368c89f2750SDavid 'Digit' Turner } 369c89f2750SDavid 'Digit' Turner 370726ea1a8SJin Qian static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write) 371726ea1a8SJin Qian { 37261b38f02SRoman Kiryanov u32 wake_bit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; 373c89f2750SDavid 'Digit' Turner 37461b38f02SRoman Kiryanov set_bit(wake_bit, &pipe->flags); 375c89f2750SDavid 'Digit' Turner 376c89f2750SDavid 'Digit' Turner /* Tell the emulator we're going to wait for a wake event */ 37792c320b9SRoman Kiryanov goldfish_pipe_cmd(pipe, 378726ea1a8SJin Qian is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ); 379c89f2750SDavid 'Digit' Turner 38061b38f02SRoman Kiryanov while (test_bit(wake_bit, &pipe->flags)) { 381562a74deSRoman Kiryanov if (wait_event_interruptible(pipe->wake_queue, 38261b38f02SRoman Kiryanov !test_bit(wake_bit, &pipe->flags))) 383c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 384c89f2750SDavid 'Digit' Turner 385c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 386c89f2750SDavid 'Digit' Turner return -EIO; 387c89f2750SDavid 'Digit' Turner } 388c89f2750SDavid 'Digit' Turner 389726ea1a8SJin Qian return 0; 390c89f2750SDavid 'Digit' Turner } 3912f3be882SChristoffer Dall 392726ea1a8SJin Qian static ssize_t goldfish_pipe_read_write(struct file *filp, 39352bcc7d9SRoman Kiryanov char __user *buffer, 39452bcc7d9SRoman Kiryanov size_t bufflen, 39552bcc7d9SRoman Kiryanov int is_write) 396726ea1a8SJin Qian { 397726ea1a8SJin Qian struct goldfish_pipe *pipe = filp->private_data; 398726ea1a8SJin Qian int count = 0, ret = -EINVAL; 399726ea1a8SJin Qian unsigned long address, address_end, last_page; 400726ea1a8SJin Qian unsigned int last_page_size; 401726ea1a8SJin Qian 402726ea1a8SJin Qian /* If the emulator already closed the pipe, no need to go further */ 403726ea1a8SJin Qian if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))) 404726ea1a8SJin Qian return -EIO; 405726ea1a8SJin Qian /* Null reads or writes succeeds */ 406726ea1a8SJin Qian if (unlikely(bufflen == 0)) 407726ea1a8SJin Qian return 0; 408726ea1a8SJin Qian /* Check the buffer range for access */ 40996d4f267SLinus Torvalds if (unlikely(!access_ok(buffer, bufflen))) 410726ea1a8SJin Qian return -EFAULT; 411726ea1a8SJin Qian 412726ea1a8SJin Qian address = (unsigned long)buffer; 413726ea1a8SJin Qian address_end = address + bufflen; 414726ea1a8SJin Qian last_page = (address_end - 1) & PAGE_MASK; 415726ea1a8SJin Qian last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1; 416726ea1a8SJin Qian 417726ea1a8SJin Qian while (address < address_end) { 418726ea1a8SJin Qian s32 consumed_size; 419726ea1a8SJin Qian int status; 420726ea1a8SJin Qian 421726ea1a8SJin Qian ret = transfer_max_buffers(pipe, address, address_end, is_write, 42252bcc7d9SRoman Kiryanov last_page, last_page_size, 42352bcc7d9SRoman Kiryanov &consumed_size, &status); 4242f3be882SChristoffer Dall if (ret < 0) 425726ea1a8SJin Qian break; 426726ea1a8SJin Qian 427726ea1a8SJin Qian if (consumed_size > 0) { 428726ea1a8SJin Qian /* No matter what's the status, we've transferred 429726ea1a8SJin Qian * something. 430726ea1a8SJin Qian */ 431726ea1a8SJin Qian count += consumed_size; 432726ea1a8SJin Qian address += consumed_size; 433726ea1a8SJin Qian } 434726ea1a8SJin Qian if (status > 0) 435726ea1a8SJin Qian continue; 436726ea1a8SJin Qian if (status == 0) { 437726ea1a8SJin Qian /* EOF */ 438726ea1a8SJin Qian ret = 0; 439726ea1a8SJin Qian break; 440726ea1a8SJin Qian } 441726ea1a8SJin Qian if (count > 0) { 442726ea1a8SJin Qian /* 443726ea1a8SJin Qian * An error occurred, but we already transferred 444726ea1a8SJin Qian * something on one of the previous iterations. 445726ea1a8SJin Qian * Just return what we already copied and log this 446726ea1a8SJin Qian * err. 447726ea1a8SJin Qian */ 448726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN) 44925b97d57SRoman Kiryanov dev_err_ratelimited(pipe->dev->pdev_dev, 45025b97d57SRoman Kiryanov "backend error %d on %s\n", 451726ea1a8SJin Qian status, is_write ? "write" : "read"); 452726ea1a8SJin Qian break; 453726ea1a8SJin Qian } 454726ea1a8SJin Qian 455726ea1a8SJin Qian /* 456726ea1a8SJin Qian * If the error is not PIPE_ERROR_AGAIN, or if we are in 457726ea1a8SJin Qian * non-blocking mode, just return the error code. 458726ea1a8SJin Qian */ 459726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN || 460726ea1a8SJin Qian (filp->f_flags & O_NONBLOCK) != 0) { 461726ea1a8SJin Qian ret = goldfish_pipe_error_convert(status); 462726ea1a8SJin Qian break; 463726ea1a8SJin Qian } 464726ea1a8SJin Qian 465726ea1a8SJin Qian status = wait_for_host_signal(pipe, is_write); 466726ea1a8SJin Qian if (status < 0) 467726ea1a8SJin Qian return status; 468726ea1a8SJin Qian } 469726ea1a8SJin Qian 470726ea1a8SJin Qian if (count > 0) 4712f3be882SChristoffer Dall return count; 472726ea1a8SJin Qian return ret; 473c89f2750SDavid 'Digit' Turner } 474c89f2750SDavid 'Digit' Turner 475c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, 476c89f2750SDavid 'Digit' Turner size_t bufflen, loff_t *ppos) 477c89f2750SDavid 'Digit' Turner { 478726ea1a8SJin Qian return goldfish_pipe_read_write(filp, buffer, bufflen, 479726ea1a8SJin Qian /* is_write */ 0); 480c89f2750SDavid 'Digit' Turner } 481c89f2750SDavid 'Digit' Turner 482c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_write(struct file *filp, 483c89f2750SDavid 'Digit' Turner const char __user *buffer, size_t bufflen, 484c89f2750SDavid 'Digit' Turner loff_t *ppos) 485c89f2750SDavid 'Digit' Turner { 48652bcc7d9SRoman Kiryanov /* cast away the const */ 48752bcc7d9SRoman Kiryanov char __user *no_const_buffer = (char __user *)buffer; 48852bcc7d9SRoman Kiryanov 48952bcc7d9SRoman Kiryanov return goldfish_pipe_read_write(filp, no_const_buffer, bufflen, 490726ea1a8SJin Qian /* is_write */ 1); 491c89f2750SDavid 'Digit' Turner } 492c89f2750SDavid 'Digit' Turner 493afc9a42bSAl Viro static __poll_t goldfish_pipe_poll(struct file *filp, poll_table *wait) 494c89f2750SDavid 'Digit' Turner { 495c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 496afc9a42bSAl Viro __poll_t mask = 0; 497c89f2750SDavid 'Digit' Turner int status; 498c89f2750SDavid 'Digit' Turner 499c89f2750SDavid 'Digit' Turner poll_wait(filp, &pipe->wake_queue, wait); 500c89f2750SDavid 'Digit' Turner 50192c320b9SRoman Kiryanov status = goldfish_pipe_cmd(pipe, PIPE_CMD_POLL); 502726ea1a8SJin Qian if (status < 0) 503726ea1a8SJin Qian return -ERESTARTSYS; 504c89f2750SDavid 'Digit' Turner 505c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_IN) 506a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM; 507c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_OUT) 508a9a08845SLinus Torvalds mask |= EPOLLOUT | EPOLLWRNORM; 509c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_HUP) 510a9a08845SLinus Torvalds mask |= EPOLLHUP; 511c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 512a9a08845SLinus Torvalds mask |= EPOLLERR; 513c89f2750SDavid 'Digit' Turner 514c89f2750SDavid 'Digit' Turner return mask; 515c89f2750SDavid 'Digit' Turner } 516c89f2750SDavid 'Digit' Turner 517726ea1a8SJin Qian static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev, 518726ea1a8SJin Qian u32 id, u32 flags) 519c89f2750SDavid 'Digit' Turner { 520c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe; 52149a75c44SJun Tian 522726ea1a8SJin Qian if (WARN_ON(id >= dev->pipes_capacity)) 523726ea1a8SJin Qian return; 52425c72c78SJun Tian 525726ea1a8SJin Qian pipe = dev->pipes[id]; 526726ea1a8SJin Qian if (!pipe) 527726ea1a8SJin Qian return; 528726ea1a8SJin Qian pipe->signalled_flags |= flags; 529c89f2750SDavid 'Digit' Turner 530cc14057fSRoman Kiryanov if (pipe->prev_signalled || pipe->next_signalled || 531cc14057fSRoman Kiryanov dev->first_signalled_pipe == pipe) 532726ea1a8SJin Qian return; /* already in the list */ 533726ea1a8SJin Qian pipe->next_signalled = dev->first_signalled_pipe; 534726ea1a8SJin Qian if (dev->first_signalled_pipe) 535726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = pipe; 536726ea1a8SJin Qian dev->first_signalled_pipe = pipe; 537c89f2750SDavid 'Digit' Turner } 538726ea1a8SJin Qian 539726ea1a8SJin Qian static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev, 54053bdf668SRoman Kiryanov struct goldfish_pipe *pipe) 54153bdf668SRoman Kiryanov { 542726ea1a8SJin Qian if (pipe->prev_signalled) 543726ea1a8SJin Qian pipe->prev_signalled->next_signalled = pipe->next_signalled; 544726ea1a8SJin Qian if (pipe->next_signalled) 545726ea1a8SJin Qian pipe->next_signalled->prev_signalled = pipe->prev_signalled; 546726ea1a8SJin Qian if (pipe == dev->first_signalled_pipe) 547726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 548726ea1a8SJin Qian pipe->prev_signalled = NULL; 549726ea1a8SJin Qian pipe->next_signalled = NULL; 550726ea1a8SJin Qian } 551726ea1a8SJin Qian 552726ea1a8SJin Qian static struct goldfish_pipe *signalled_pipes_pop_front( 553726ea1a8SJin Qian struct goldfish_pipe_dev *dev, int *wakes) 554726ea1a8SJin Qian { 555726ea1a8SJin Qian struct goldfish_pipe *pipe; 556726ea1a8SJin Qian unsigned long flags; 557726ea1a8SJin Qian 558726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 559726ea1a8SJin Qian 560726ea1a8SJin Qian pipe = dev->first_signalled_pipe; 561726ea1a8SJin Qian if (pipe) { 562726ea1a8SJin Qian *wakes = pipe->signalled_flags; 563726ea1a8SJin Qian pipe->signalled_flags = 0; 564726ea1a8SJin Qian /* 565726ea1a8SJin Qian * This is an optimized version of 566726ea1a8SJin Qian * signalled_pipes_remove_locked() 567726ea1a8SJin Qian * - We want to make it as fast as possible to 568726ea1a8SJin Qian * wake the sleeping pipe operations faster. 569726ea1a8SJin Qian */ 570726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 571726ea1a8SJin Qian if (dev->first_signalled_pipe) 572726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = NULL; 573726ea1a8SJin Qian pipe->next_signalled = NULL; 574726ea1a8SJin Qian } 575726ea1a8SJin Qian 576726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 577726ea1a8SJin Qian return pipe; 578726ea1a8SJin Qian } 579726ea1a8SJin Qian 580c394cc3bSRoman Kiryanov static void goldfish_interrupt_task(unsigned long dev_addr) 581726ea1a8SJin Qian { 582726ea1a8SJin Qian /* Iterate over the signalled pipes and wake them one by one */ 583c394cc3bSRoman Kiryanov struct goldfish_pipe_dev *dev = (struct goldfish_pipe_dev *)dev_addr; 584726ea1a8SJin Qian struct goldfish_pipe *pipe; 585726ea1a8SJin Qian int wakes; 586726ea1a8SJin Qian 587c394cc3bSRoman Kiryanov while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) { 588726ea1a8SJin Qian if (wakes & PIPE_WAKE_CLOSED) { 589726ea1a8SJin Qian pipe->flags = 1 << BIT_CLOSED_ON_HOST; 590726ea1a8SJin Qian } else { 591c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_READ) 592c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_READ, &pipe->flags); 593c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_WRITE) 594c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); 595c89f2750SDavid 'Digit' Turner } 596726ea1a8SJin Qian /* 597726ea1a8SJin Qian * wake_up_interruptible() implies a write barrier, so don't 598726ea1a8SJin Qian * explicitly add another one here. 599726ea1a8SJin Qian */ 600726ea1a8SJin Qian wake_up_interruptible(&pipe->wake_queue); 601726ea1a8SJin Qian } 602726ea1a8SJin Qian } 603c89f2750SDavid 'Digit' Turner 60408360e26SRoman Kiryanov static void goldfish_pipe_device_deinit(struct platform_device *pdev, 60508360e26SRoman Kiryanov struct goldfish_pipe_dev *dev); 60608360e26SRoman Kiryanov 607726ea1a8SJin Qian /* 608726ea1a8SJin Qian * The general idea of the interrupt handling: 609726ea1a8SJin Qian * 610726ea1a8SJin Qian * 1. device raises an interrupt if there's at least one signalled pipe 611726ea1a8SJin Qian * 2. IRQ handler reads the signalled pipes and their count from the device 612726ea1a8SJin Qian * 3. device writes them into a shared buffer and returns the count 613726ea1a8SJin Qian * it only resets the IRQ if it has returned all signalled pipes, 614726ea1a8SJin Qian * otherwise it leaves it raised, so IRQ handler will be called 615726ea1a8SJin Qian * again for the next chunk 616726ea1a8SJin Qian * 4. IRQ handler adds all returned pipes to the device's signalled pipes list 617726ea1a8SJin Qian * 5. IRQ handler launches a tasklet to process the signalled pipes from the 618726ea1a8SJin Qian * list in a separate context 619726ea1a8SJin Qian */ 620726ea1a8SJin Qian static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) 621726ea1a8SJin Qian { 622726ea1a8SJin Qian u32 count; 623726ea1a8SJin Qian u32 i; 624726ea1a8SJin Qian unsigned long flags; 625726ea1a8SJin Qian struct goldfish_pipe_dev *dev = dev_id; 626726ea1a8SJin Qian 62708360e26SRoman Kiryanov if (dev->magic != &goldfish_pipe_device_deinit) 628726ea1a8SJin Qian return IRQ_NONE; 629726ea1a8SJin Qian 630726ea1a8SJin Qian /* Request the signalled pipes from the device */ 631726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 632726ea1a8SJin Qian 633726ea1a8SJin Qian count = readl(dev->base + PIPE_REG_GET_SIGNALLED); 634726ea1a8SJin Qian if (count == 0) { 635726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 636726ea1a8SJin Qian return IRQ_NONE; 637726ea1a8SJin Qian } 638726ea1a8SJin Qian if (count > MAX_SIGNALLED_PIPES) 639726ea1a8SJin Qian count = MAX_SIGNALLED_PIPES; 640726ea1a8SJin Qian 641726ea1a8SJin Qian for (i = 0; i < count; ++i) 642726ea1a8SJin Qian signalled_pipes_add_locked(dev, 643726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].id, 644726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].flags); 645726ea1a8SJin Qian 646726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 647726ea1a8SJin Qian 648c394cc3bSRoman Kiryanov tasklet_schedule(&dev->irq_tasklet); 649726ea1a8SJin Qian return IRQ_HANDLED; 650726ea1a8SJin Qian } 651726ea1a8SJin Qian 652726ea1a8SJin Qian static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) 653726ea1a8SJin Qian { 654726ea1a8SJin Qian int id; 655726ea1a8SJin Qian 656726ea1a8SJin Qian for (id = 0; id < dev->pipes_capacity; ++id) 657726ea1a8SJin Qian if (!dev->pipes[id]) 658726ea1a8SJin Qian return id; 659726ea1a8SJin Qian 660726ea1a8SJin Qian { 66184ae527aSRoman Kiryanov /* Reallocate the array. 66284ae527aSRoman Kiryanov * Since get_free_pipe_id_locked runs with interrupts disabled, 66384ae527aSRoman Kiryanov * we don't want to make calls that could lead to sleep. 66484ae527aSRoman Kiryanov */ 665726ea1a8SJin Qian u32 new_capacity = 2 * dev->pipes_capacity; 666726ea1a8SJin Qian struct goldfish_pipe **pipes = 6673eff8ecdSWei Yongjun kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC); 668726ea1a8SJin Qian if (!pipes) 669726ea1a8SJin Qian return -ENOMEM; 670726ea1a8SJin Qian memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); 671726ea1a8SJin Qian kfree(dev->pipes); 672726ea1a8SJin Qian dev->pipes = pipes; 673726ea1a8SJin Qian id = dev->pipes_capacity; 674726ea1a8SJin Qian dev->pipes_capacity = new_capacity; 675726ea1a8SJin Qian } 676726ea1a8SJin Qian return id; 677c89f2750SDavid 'Digit' Turner } 678c89f2750SDavid 'Digit' Turner 67908360e26SRoman Kiryanov /* A helper function to get the instance of goldfish_pipe_dev from file */ 68008360e26SRoman Kiryanov static struct goldfish_pipe_dev *to_goldfish_pipe_dev(struct file *file) 68108360e26SRoman Kiryanov { 68208360e26SRoman Kiryanov struct miscdevice *miscdev = file->private_data; 68308360e26SRoman Kiryanov 68408360e26SRoman Kiryanov return container_of(miscdev, struct goldfish_pipe_dev, miscdev); 68508360e26SRoman Kiryanov } 68608360e26SRoman Kiryanov 687c89f2750SDavid 'Digit' Turner /** 688c89f2750SDavid 'Digit' Turner * goldfish_pipe_open - open a channel to the AVD 689c89f2750SDavid 'Digit' Turner * @inode: inode of device 690c89f2750SDavid 'Digit' Turner * @file: file struct of opener 691c89f2750SDavid 'Digit' Turner * 692c89f2750SDavid 'Digit' Turner * Create a new pipe link between the emulator and the use application. 693c89f2750SDavid 'Digit' Turner * Each new request produces a new pipe. 694c89f2750SDavid 'Digit' Turner * 695c89f2750SDavid 'Digit' Turner * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit 696c89f2750SDavid 'Digit' Turner * right now so this is fine. A move to 64bit will need this addressing 697c89f2750SDavid 'Digit' Turner */ 698c89f2750SDavid 'Digit' Turner static int goldfish_pipe_open(struct inode *inode, struct file *file) 699c89f2750SDavid 'Digit' Turner { 70008360e26SRoman Kiryanov struct goldfish_pipe_dev *dev = to_goldfish_pipe_dev(file); 701726ea1a8SJin Qian unsigned long flags; 702726ea1a8SJin Qian int id; 703726ea1a8SJin Qian int status; 704c89f2750SDavid 'Digit' Turner 705c89f2750SDavid 'Digit' Turner /* Allocate new pipe kernel object */ 706726ea1a8SJin Qian struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); 7076d7d725bSRoman Kiryanov 708bfb8e838SRoman Kiryanov if (!pipe) 709c89f2750SDavid 'Digit' Turner return -ENOMEM; 710c89f2750SDavid 'Digit' Turner 711c89f2750SDavid 'Digit' Turner pipe->dev = dev; 712c89f2750SDavid 'Digit' Turner mutex_init(&pipe->lock); 713c89f2750SDavid 'Digit' Turner init_waitqueue_head(&pipe->wake_queue); 714c89f2750SDavid 'Digit' Turner 715c89f2750SDavid 'Digit' Turner /* 716726ea1a8SJin Qian * Command buffer needs to be allocated on its own page to make sure 717726ea1a8SJin Qian * it is physically contiguous in host's address space. 718c89f2750SDavid 'Digit' Turner */ 719d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE); 720726ea1a8SJin Qian pipe->command_buffer = 721726ea1a8SJin Qian (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL); 722726ea1a8SJin Qian if (!pipe->command_buffer) { 723726ea1a8SJin Qian status = -ENOMEM; 724726ea1a8SJin Qian goto err_pipe; 725726ea1a8SJin Qian } 726c89f2750SDavid 'Digit' Turner 727726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 728726ea1a8SJin Qian 729726ea1a8SJin Qian id = get_free_pipe_id_locked(dev); 730726ea1a8SJin Qian if (id < 0) { 731726ea1a8SJin Qian status = id; 732726ea1a8SJin Qian goto err_id_locked; 733726ea1a8SJin Qian } 734726ea1a8SJin Qian 735726ea1a8SJin Qian dev->pipes[id] = pipe; 736726ea1a8SJin Qian pipe->id = id; 737726ea1a8SJin Qian pipe->command_buffer->id = id; 738726ea1a8SJin Qian 739726ea1a8SJin Qian /* Now tell the emulator we're opening a new pipe. */ 740726ea1a8SJin Qian dev->buffers->open_command_params.rw_params_max_count = 741726ea1a8SJin Qian MAX_BUFFERS_PER_COMMAND; 742726ea1a8SJin Qian dev->buffers->open_command_params.command_buffer_ptr = 743726ea1a8SJin Qian (u64)(unsigned long)__pa(pipe->command_buffer); 74492c320b9SRoman Kiryanov status = goldfish_pipe_cmd_locked(pipe, PIPE_CMD_OPEN); 745726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 746726ea1a8SJin Qian if (status < 0) 747726ea1a8SJin Qian goto err_cmd; 748726ea1a8SJin Qian /* All is done, save the pipe into the file's private data field */ 749726ea1a8SJin Qian file->private_data = pipe; 750726ea1a8SJin Qian return 0; 751726ea1a8SJin Qian 752726ea1a8SJin Qian err_cmd: 753726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 754726ea1a8SJin Qian dev->pipes[id] = NULL; 755726ea1a8SJin Qian err_id_locked: 756726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 757726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 758726ea1a8SJin Qian err_pipe: 759c89f2750SDavid 'Digit' Turner kfree(pipe); 760c89f2750SDavid 'Digit' Turner return status; 761c89f2750SDavid 'Digit' Turner } 762c89f2750SDavid 'Digit' Turner 763c89f2750SDavid 'Digit' Turner static int goldfish_pipe_release(struct inode *inode, struct file *filp) 764c89f2750SDavid 'Digit' Turner { 765726ea1a8SJin Qian unsigned long flags; 766c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 767726ea1a8SJin Qian struct goldfish_pipe_dev *dev = pipe->dev; 768c89f2750SDavid 'Digit' Turner 769c89f2750SDavid 'Digit' Turner /* The guest is closing the channel, so tell the emulator right now */ 77092c320b9SRoman Kiryanov goldfish_pipe_cmd(pipe, PIPE_CMD_CLOSE); 771726ea1a8SJin Qian 772726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 773726ea1a8SJin Qian dev->pipes[pipe->id] = NULL; 774726ea1a8SJin Qian signalled_pipes_remove_locked(dev, pipe); 775726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 776726ea1a8SJin Qian 777c89f2750SDavid 'Digit' Turner filp->private_data = NULL; 778726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 779726ea1a8SJin Qian kfree(pipe); 780c89f2750SDavid 'Digit' Turner return 0; 781c89f2750SDavid 'Digit' Turner } 782c89f2750SDavid 'Digit' Turner 783c89f2750SDavid 'Digit' Turner static const struct file_operations goldfish_pipe_fops = { 784c89f2750SDavid 'Digit' Turner .owner = THIS_MODULE, 785c89f2750SDavid 'Digit' Turner .read = goldfish_pipe_read, 786c89f2750SDavid 'Digit' Turner .write = goldfish_pipe_write, 787c89f2750SDavid 'Digit' Turner .poll = goldfish_pipe_poll, 788c89f2750SDavid 'Digit' Turner .open = goldfish_pipe_open, 789c89f2750SDavid 'Digit' Turner .release = goldfish_pipe_release, 790c89f2750SDavid 'Digit' Turner }; 791c89f2750SDavid 'Digit' Turner 79243c2cc28SRoman Kiryanov static void init_miscdevice(struct miscdevice *miscdev) 79343c2cc28SRoman Kiryanov { 79443c2cc28SRoman Kiryanov memset(miscdev, 0, sizeof(*miscdev)); 79543c2cc28SRoman Kiryanov 79643c2cc28SRoman Kiryanov miscdev->minor = MISC_DYNAMIC_MINOR; 79743c2cc28SRoman Kiryanov miscdev->name = "goldfish_pipe"; 79843c2cc28SRoman Kiryanov miscdev->fops = &goldfish_pipe_fops; 79943c2cc28SRoman Kiryanov } 800c89f2750SDavid 'Digit' Turner 801610a72b7SRoman Kiryanov static void write_pa_addr(void *addr, void __iomem *portl, void __iomem *porth) 802610a72b7SRoman Kiryanov { 803610a72b7SRoman Kiryanov const unsigned long paddr = __pa(addr); 804610a72b7SRoman Kiryanov 805610a72b7SRoman Kiryanov writel(upper_32_bits(paddr), porth); 806610a72b7SRoman Kiryanov writel(lower_32_bits(paddr), portl); 807610a72b7SRoman Kiryanov } 808610a72b7SRoman Kiryanov 80908360e26SRoman Kiryanov static int goldfish_pipe_device_init(struct platform_device *pdev, 81008360e26SRoman Kiryanov struct goldfish_pipe_dev *dev) 811726ea1a8SJin Qian { 812c394cc3bSRoman Kiryanov int err; 813c394cc3bSRoman Kiryanov 814c394cc3bSRoman Kiryanov tasklet_init(&dev->irq_tasklet, &goldfish_interrupt_task, 815c394cc3bSRoman Kiryanov (unsigned long)dev); 816c394cc3bSRoman Kiryanov 817c394cc3bSRoman Kiryanov err = devm_request_irq(&pdev->dev, dev->irq, 818726ea1a8SJin Qian goldfish_pipe_interrupt, 819726ea1a8SJin Qian IRQF_SHARED, "goldfish_pipe", dev); 820726ea1a8SJin Qian if (err) { 821726ea1a8SJin Qian dev_err(&pdev->dev, "unable to allocate IRQ for v2\n"); 822726ea1a8SJin Qian return err; 823726ea1a8SJin Qian } 824726ea1a8SJin Qian 82543c2cc28SRoman Kiryanov init_miscdevice(&dev->miscdev); 82643c2cc28SRoman Kiryanov err = misc_register(&dev->miscdev); 827726ea1a8SJin Qian if (err) { 828726ea1a8SJin Qian dev_err(&pdev->dev, "unable to register v2 device\n"); 829726ea1a8SJin Qian return err; 830726ea1a8SJin Qian } 831726ea1a8SJin Qian 83225b97d57SRoman Kiryanov dev->pdev_dev = &pdev->dev; 833726ea1a8SJin Qian dev->first_signalled_pipe = NULL; 834726ea1a8SJin Qian dev->pipes_capacity = INITIAL_PIPES_CAPACITY; 835726ea1a8SJin Qian dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), 836726ea1a8SJin Qian GFP_KERNEL); 83760a6e523SRoman Kiryanov if (!dev->pipes) { 83860a6e523SRoman Kiryanov misc_deregister(&dev->miscdev); 839726ea1a8SJin Qian return -ENOMEM; 84060a6e523SRoman Kiryanov } 841726ea1a8SJin Qian 842726ea1a8SJin Qian /* 843726ea1a8SJin Qian * We're going to pass two buffers, open_command_params and 844726ea1a8SJin Qian * signalled_pipe_buffers, to the host. This means each of those buffers 845726ea1a8SJin Qian * needs to be contained in a single physical page. The easiest choice 846726ea1a8SJin Qian * is to just allocate a page and place the buffers in it. 847726ea1a8SJin Qian */ 848d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_dev_buffers) > PAGE_SIZE); 8492ed43e53SRoman Kiryanov dev->buffers = (struct goldfish_pipe_dev_buffers *) 8502ed43e53SRoman Kiryanov __get_free_page(GFP_KERNEL); 8512ed43e53SRoman Kiryanov if (!dev->buffers) { 852726ea1a8SJin Qian kfree(dev->pipes); 85360a6e523SRoman Kiryanov misc_deregister(&dev->miscdev); 854726ea1a8SJin Qian return -ENOMEM; 855726ea1a8SJin Qian } 856726ea1a8SJin Qian 857726ea1a8SJin Qian /* Send the buffer addresses to the host */ 858610a72b7SRoman Kiryanov write_pa_addr(&dev->buffers->signalled_pipe_buffers, 859610a72b7SRoman Kiryanov dev->base + PIPE_REG_SIGNAL_BUFFER, 860726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH); 861610a72b7SRoman Kiryanov 862468e62f9SRoman Kiryanov writel(MAX_SIGNALLED_PIPES, 863726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT); 864726ea1a8SJin Qian 865610a72b7SRoman Kiryanov write_pa_addr(&dev->buffers->open_command_params, 866610a72b7SRoman Kiryanov dev->base + PIPE_REG_OPEN_BUFFER, 867726ea1a8SJin Qian dev->base + PIPE_REG_OPEN_BUFFER_HIGH); 868610a72b7SRoman Kiryanov 86908360e26SRoman Kiryanov platform_set_drvdata(pdev, dev); 870726ea1a8SJin Qian return 0; 871726ea1a8SJin Qian } 872726ea1a8SJin Qian 87308360e26SRoman Kiryanov static void goldfish_pipe_device_deinit(struct platform_device *pdev, 87408360e26SRoman Kiryanov struct goldfish_pipe_dev *dev) 875726ea1a8SJin Qian { 87608360e26SRoman Kiryanov misc_deregister(&dev->miscdev); 87708360e26SRoman Kiryanov tasklet_kill(&dev->irq_tasklet); 87808360e26SRoman Kiryanov kfree(dev->pipes); 87908360e26SRoman Kiryanov free_page((unsigned long)dev->buffers); 880726ea1a8SJin Qian } 881726ea1a8SJin Qian 882c89f2750SDavid 'Digit' Turner static int goldfish_pipe_probe(struct platform_device *pdev) 883c89f2750SDavid 'Digit' Turner { 884c89f2750SDavid 'Digit' Turner struct resource *r; 88508360e26SRoman Kiryanov struct goldfish_pipe_dev *dev; 886c89f2750SDavid 'Digit' Turner 88708360e26SRoman Kiryanov dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 88808360e26SRoman Kiryanov if (!dev) 88908360e26SRoman Kiryanov return -ENOMEM; 890c89f2750SDavid 'Digit' Turner 89108360e26SRoman Kiryanov dev->magic = &goldfish_pipe_device_deinit; 892c89f2750SDavid 'Digit' Turner spin_lock_init(&dev->lock); 893c89f2750SDavid 'Digit' Turner 894c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 895bfb8e838SRoman Kiryanov if (!r || resource_size(r) < PAGE_SIZE) { 896c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "can't allocate i/o page\n"); 897c89f2750SDavid 'Digit' Turner return -EINVAL; 898c89f2750SDavid 'Digit' Turner } 899c89f2750SDavid 'Digit' Turner dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); 900bfb8e838SRoman Kiryanov if (!dev->base) { 901c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "ioremap failed\n"); 902c89f2750SDavid 'Digit' Turner return -EINVAL; 903c89f2750SDavid 'Digit' Turner } 904c89f2750SDavid 'Digit' Turner 905c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 90608360e26SRoman Kiryanov if (!r) 90708360e26SRoman Kiryanov return -EINVAL; 90808360e26SRoman Kiryanov 909c89f2750SDavid 'Digit' Turner dev->irq = r->start; 910c89f2750SDavid 'Digit' Turner 911726ea1a8SJin Qian /* 912726ea1a8SJin Qian * Exchange the versions with the host device 913726ea1a8SJin Qian * 914726ea1a8SJin Qian * Note: v1 driver used to not report its version, so we write it before 915726ea1a8SJin Qian * reading device version back: this allows the host implementation to 916726ea1a8SJin Qian * detect the old driver (if there was no version write before read). 9174f42071cSYu Ning */ 918e6fb3193SRoman Kiryanov writel(PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION); 9194f42071cSYu Ning dev->version = readl(dev->base + PIPE_REG_VERSION); 920726ea1a8SJin Qian if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION)) 921726ea1a8SJin Qian return -EINVAL; 922726ea1a8SJin Qian 92308360e26SRoman Kiryanov return goldfish_pipe_device_init(pdev, dev); 924c89f2750SDavid 'Digit' Turner } 925c89f2750SDavid 'Digit' Turner 926c89f2750SDavid 'Digit' Turner static int goldfish_pipe_remove(struct platform_device *pdev) 927c89f2750SDavid 'Digit' Turner { 92808360e26SRoman Kiryanov struct goldfish_pipe_dev *dev = platform_get_drvdata(pdev); 92908360e26SRoman Kiryanov 93008360e26SRoman Kiryanov goldfish_pipe_device_deinit(pdev, dev); 931c89f2750SDavid 'Digit' Turner return 0; 932c89f2750SDavid 'Digit' Turner } 933c89f2750SDavid 'Digit' Turner 934d62f324bSJason Hu static const struct acpi_device_id goldfish_pipe_acpi_match[] = { 935d62f324bSJason Hu { "GFSH0003", 0 }, 936d62f324bSJason Hu { }, 937d62f324bSJason Hu }; 938d62f324bSJason Hu MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); 939d62f324bSJason Hu 94091a18a41SGreg Hackmann static const struct of_device_id goldfish_pipe_of_match[] = { 94191a18a41SGreg Hackmann { .compatible = "google,android-pipe", }, 94291a18a41SGreg Hackmann {}, 94391a18a41SGreg Hackmann }; 94491a18a41SGreg Hackmann MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); 94591a18a41SGreg Hackmann 946726ea1a8SJin Qian static struct platform_driver goldfish_pipe_driver = { 947c89f2750SDavid 'Digit' Turner .probe = goldfish_pipe_probe, 948c89f2750SDavid 'Digit' Turner .remove = goldfish_pipe_remove, 949c89f2750SDavid 'Digit' Turner .driver = { 95091a18a41SGreg Hackmann .name = "goldfish_pipe", 95191a18a41SGreg Hackmann .of_match_table = goldfish_pipe_of_match, 952d62f324bSJason Hu .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), 953c89f2750SDavid 'Digit' Turner } 954c89f2750SDavid 'Digit' Turner }; 955c89f2750SDavid 'Digit' Turner 956726ea1a8SJin Qian module_platform_driver(goldfish_pipe_driver); 957c89f2750SDavid 'Digit' Turner MODULE_AUTHOR("David Turner <digit@google.com>"); 958c3c4e307SRoman Kiryanov MODULE_LICENSE("GPL v2"); 959