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 50726ea1a8SJin Qian 51c89f2750SDavid 'Digit' Turner #include <linux/module.h> 52ac316725SRandy Dunlap #include <linux/mod_devicetable.h> 53c89f2750SDavid 'Digit' Turner #include <linux/interrupt.h> 54c89f2750SDavid 'Digit' Turner #include <linux/kernel.h> 55c89f2750SDavid 'Digit' Turner #include <linux/spinlock.h> 56c89f2750SDavid 'Digit' Turner #include <linux/miscdevice.h> 57c89f2750SDavid 'Digit' Turner #include <linux/platform_device.h> 58c89f2750SDavid 'Digit' Turner #include <linux/poll.h> 59c89f2750SDavid 'Digit' Turner #include <linux/sched.h> 60c89f2750SDavid 'Digit' Turner #include <linux/bitops.h> 61c89f2750SDavid 'Digit' Turner #include <linux/slab.h> 62c89f2750SDavid 'Digit' Turner #include <linux/io.h> 63a99698faSAlan #include <linux/goldfish.h> 641d427da1SShraddha Barke #include <linux/dma-mapping.h> 652f3be882SChristoffer Dall #include <linux/mm.h> 66d62f324bSJason Hu #include <linux/acpi.h> 67d23069a5SRoman Kiryanov #include <linux/bug.h> 6895577010SRoman Kiryanov #include "goldfish_pipe_qemu.h" 69c89f2750SDavid 'Digit' Turner 70c89f2750SDavid 'Digit' Turner /* 71726ea1a8SJin Qian * Update this when something changes in the driver's behavior so the host 72726ea1a8SJin Qian * can benefit from knowing it 73726ea1a8SJin Qian */ 74726ea1a8SJin Qian enum { 75726ea1a8SJin Qian PIPE_DRIVER_VERSION = 2, 76726ea1a8SJin Qian PIPE_CURRENT_DEVICE_VERSION = 2 77726ea1a8SJin Qian }; 78726ea1a8SJin Qian 79726ea1a8SJin Qian enum { 80726ea1a8SJin Qian MAX_BUFFERS_PER_COMMAND = 336, 81726ea1a8SJin Qian MAX_SIGNALLED_PIPES = 64, 82726ea1a8SJin Qian INITIAL_PIPES_CAPACITY = 64 83726ea1a8SJin Qian }; 84726ea1a8SJin Qian 85726ea1a8SJin Qian struct goldfish_pipe_dev; 86726ea1a8SJin Qian struct goldfish_pipe; 87726ea1a8SJin Qian struct goldfish_pipe_command; 88726ea1a8SJin Qian 89726ea1a8SJin Qian /* A per-pipe command structure, shared with the host */ 90726ea1a8SJin Qian struct goldfish_pipe_command { 91726ea1a8SJin Qian s32 cmd; /* PipeCmdCode, guest -> host */ 92726ea1a8SJin Qian s32 id; /* pipe id, guest -> host */ 93726ea1a8SJin Qian s32 status; /* command execution status, host -> guest */ 94726ea1a8SJin Qian s32 reserved; /* to pad to 64-bit boundary */ 95726ea1a8SJin Qian union { 96726ea1a8SJin Qian /* Parameters for PIPE_CMD_{READ,WRITE} */ 97726ea1a8SJin Qian struct { 98726ea1a8SJin Qian /* number of buffers, guest -> host */ 99726ea1a8SJin Qian u32 buffers_count; 100726ea1a8SJin Qian /* number of consumed bytes, host -> guest */ 101726ea1a8SJin Qian s32 consumed_size; 102726ea1a8SJin Qian /* buffer pointers, guest -> host */ 103726ea1a8SJin Qian u64 ptrs[MAX_BUFFERS_PER_COMMAND]; 104726ea1a8SJin Qian /* buffer sizes, guest -> host */ 105726ea1a8SJin Qian u32 sizes[MAX_BUFFERS_PER_COMMAND]; 106726ea1a8SJin Qian } rw_params; 107726ea1a8SJin Qian }; 108726ea1a8SJin Qian }; 109726ea1a8SJin Qian 110726ea1a8SJin Qian /* A single signalled pipe information */ 111726ea1a8SJin Qian struct signalled_pipe_buffer { 112726ea1a8SJin Qian u32 id; 113c89f2750SDavid 'Digit' Turner u32 flags; 114c89f2750SDavid 'Digit' Turner }; 115c89f2750SDavid 'Digit' Turner 116726ea1a8SJin Qian /* Parameters for the PIPE_CMD_OPEN command */ 117726ea1a8SJin Qian struct open_command_param { 118726ea1a8SJin Qian u64 command_buffer_ptr; 119726ea1a8SJin Qian u32 rw_params_max_count; 120726ea1a8SJin Qian }; 121726ea1a8SJin Qian 122726ea1a8SJin Qian /* Device-level set of buffers shared with the host */ 123726ea1a8SJin Qian struct goldfish_pipe_dev_buffers { 124726ea1a8SJin Qian struct open_command_param open_command_params; 125726ea1a8SJin Qian struct signalled_pipe_buffer signalled_pipe_buffers[ 126726ea1a8SJin Qian MAX_SIGNALLED_PIPES]; 127726ea1a8SJin Qian }; 128726ea1a8SJin Qian 129726ea1a8SJin Qian /* This data type models a given pipe instance */ 130726ea1a8SJin Qian struct goldfish_pipe { 131726ea1a8SJin Qian /* pipe ID - index into goldfish_pipe_dev::pipes array */ 132726ea1a8SJin Qian u32 id; 13346928cc6SRoman Kiryanov 134726ea1a8SJin Qian /* The wake flags pipe is waiting for 135726ea1a8SJin Qian * Note: not protected with any lock, uses atomic operations 136726ea1a8SJin Qian * and barriers to make it thread-safe. 137726ea1a8SJin Qian */ 138726ea1a8SJin Qian unsigned long flags; 13946928cc6SRoman Kiryanov 140726ea1a8SJin Qian /* wake flags host have signalled, 141726ea1a8SJin Qian * - protected by goldfish_pipe_dev::lock 142726ea1a8SJin Qian */ 143726ea1a8SJin Qian unsigned long signalled_flags; 144726ea1a8SJin Qian 145726ea1a8SJin Qian /* A pointer to command buffer */ 146726ea1a8SJin Qian struct goldfish_pipe_command *command_buffer; 147726ea1a8SJin Qian 148726ea1a8SJin Qian /* doubly linked list of signalled pipes, protected by 149726ea1a8SJin Qian * goldfish_pipe_dev::lock 150726ea1a8SJin Qian */ 151726ea1a8SJin Qian struct goldfish_pipe *prev_signalled; 152726ea1a8SJin Qian struct goldfish_pipe *next_signalled; 153726ea1a8SJin Qian 154726ea1a8SJin Qian /* 155726ea1a8SJin Qian * A pipe's own lock. Protects the following: 156726ea1a8SJin Qian * - *command_buffer - makes sure a command can safely write its 157726ea1a8SJin Qian * parameters to the host and read the results back. 158726ea1a8SJin Qian */ 159726ea1a8SJin Qian struct mutex lock; 160726ea1a8SJin Qian 161726ea1a8SJin Qian /* A wake queue for sleeping until host signals an event */ 162726ea1a8SJin Qian wait_queue_head_t wake_queue; 16346928cc6SRoman Kiryanov 164726ea1a8SJin Qian /* Pointer to the parent goldfish_pipe_dev instance */ 165726ea1a8SJin Qian struct goldfish_pipe_dev *dev; 166726ea1a8SJin Qian }; 167726ea1a8SJin Qian 168c89f2750SDavid 'Digit' Turner /* The global driver data. Holds a reference to the i/o page used to 169c89f2750SDavid 'Digit' Turner * communicate with the emulator, and a wake queue for blocked tasks 170c89f2750SDavid 'Digit' Turner * waiting to be awoken. 171c89f2750SDavid 'Digit' Turner */ 172c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev { 173726ea1a8SJin Qian /* 174726ea1a8SJin Qian * Global device spinlock. Protects the following members: 175726ea1a8SJin Qian * - pipes, pipes_capacity 176726ea1a8SJin Qian * - [*pipes, *pipes + pipes_capacity) - array data 177726ea1a8SJin Qian * - first_signalled_pipe, 178726ea1a8SJin Qian * goldfish_pipe::prev_signalled, 179726ea1a8SJin Qian * goldfish_pipe::next_signalled, 180726ea1a8SJin Qian * goldfish_pipe::signalled_flags - all singnalled-related fields, 181726ea1a8SJin Qian * in all allocated pipes 182726ea1a8SJin Qian * - open_command_params - PIPE_CMD_OPEN-related buffers 183726ea1a8SJin Qian * 184726ea1a8SJin Qian * It looks like a lot of different fields, but the trick is that 185726ea1a8SJin Qian * the only operation that happens often is the signalled pipes array 186726ea1a8SJin Qian * manipulation. That's why it's OK for now to keep the rest of the 187726ea1a8SJin Qian * fields under the same lock. If we notice too much contention because 188726ea1a8SJin Qian * of PIPE_CMD_OPEN, then we should add a separate lock there. 189726ea1a8SJin Qian */ 190c89f2750SDavid 'Digit' Turner spinlock_t lock; 191726ea1a8SJin Qian 192726ea1a8SJin Qian /* 193726ea1a8SJin Qian * Array of the pipes of |pipes_capacity| elements, 194726ea1a8SJin Qian * indexed by goldfish_pipe::id 195726ea1a8SJin Qian */ 196726ea1a8SJin Qian struct goldfish_pipe **pipes; 197726ea1a8SJin Qian u32 pipes_capacity; 198726ea1a8SJin Qian 199726ea1a8SJin Qian /* Pointers to the buffers host uses for interaction with this driver */ 200726ea1a8SJin Qian struct goldfish_pipe_dev_buffers *buffers; 201726ea1a8SJin Qian 202726ea1a8SJin Qian /* Head of a doubly linked list of signalled pipes */ 203726ea1a8SJin Qian struct goldfish_pipe *first_signalled_pipe; 204726ea1a8SJin Qian 20525b97d57SRoman Kiryanov /* ptr to platform device's device struct */ 20625b97d57SRoman Kiryanov struct device *pdev_dev; 20725b97d57SRoman Kiryanov 208726ea1a8SJin Qian /* Some device-specific data */ 209c89f2750SDavid 'Digit' Turner int irq; 210726ea1a8SJin Qian int version; 211726ea1a8SJin Qian unsigned char __iomem *base; 212c89f2750SDavid 'Digit' Turner }; 213c89f2750SDavid 'Digit' Turner 214869fd502SRoman Kiryanov struct goldfish_pipe_dev goldfish_pipe_dev; 215c89f2750SDavid 'Digit' Turner 216726ea1a8SJin Qian static int goldfish_cmd_locked(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) 217c89f2750SDavid 'Digit' Turner { 218726ea1a8SJin Qian pipe->command_buffer->cmd = cmd; 219726ea1a8SJin Qian /* failure by default */ 220726ea1a8SJin Qian pipe->command_buffer->status = PIPE_ERROR_INVAL; 221726ea1a8SJin Qian writel(pipe->id, pipe->dev->base + PIPE_REG_CMD); 222726ea1a8SJin Qian return pipe->command_buffer->status; 223726ea1a8SJin Qian } 224c89f2750SDavid 'Digit' Turner 225726ea1a8SJin Qian static int goldfish_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) 226726ea1a8SJin Qian { 227726ea1a8SJin Qian int status; 228726ea1a8SJin Qian 229726ea1a8SJin Qian if (mutex_lock_interruptible(&pipe->lock)) 230726ea1a8SJin Qian return PIPE_ERROR_IO; 231726ea1a8SJin Qian status = goldfish_cmd_locked(pipe, cmd); 232726ea1a8SJin Qian mutex_unlock(&pipe->lock); 233c89f2750SDavid 'Digit' Turner return status; 234c89f2750SDavid 'Digit' Turner } 235c89f2750SDavid 'Digit' Turner 236726ea1a8SJin Qian /* 237726ea1a8SJin Qian * This function converts an error code returned by the emulator through 238c89f2750SDavid 'Digit' Turner * the PIPE_REG_STATUS i/o register into a valid negative errno value. 239c89f2750SDavid 'Digit' Turner */ 240c89f2750SDavid 'Digit' Turner static int goldfish_pipe_error_convert(int status) 241c89f2750SDavid 'Digit' Turner { 242c89f2750SDavid 'Digit' Turner switch (status) { 243c89f2750SDavid 'Digit' Turner case PIPE_ERROR_AGAIN: 244c89f2750SDavid 'Digit' Turner return -EAGAIN; 245c89f2750SDavid 'Digit' Turner case PIPE_ERROR_NOMEM: 246c89f2750SDavid 'Digit' Turner return -ENOMEM; 247c89f2750SDavid 'Digit' Turner case PIPE_ERROR_IO: 248c89f2750SDavid 'Digit' Turner return -EIO; 249c89f2750SDavid 'Digit' Turner default: 250c89f2750SDavid 'Digit' Turner return -EINVAL; 251c89f2750SDavid 'Digit' Turner } 252c89f2750SDavid 'Digit' Turner } 253c89f2750SDavid 'Digit' Turner 254726ea1a8SJin Qian static int pin_user_pages(unsigned long first_page, unsigned long last_page, 255726ea1a8SJin Qian unsigned int last_page_size, int is_write, 256726ea1a8SJin Qian struct page *pages[MAX_BUFFERS_PER_COMMAND], 257726ea1a8SJin Qian unsigned int *iter_last_page_size) 258c89f2750SDavid 'Digit' Turner { 259726ea1a8SJin Qian int ret; 260726ea1a8SJin Qian int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; 261c89f2750SDavid 'Digit' Turner 262726ea1a8SJin Qian if (requested_pages > MAX_BUFFERS_PER_COMMAND) { 263726ea1a8SJin Qian requested_pages = MAX_BUFFERS_PER_COMMAND; 264726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 265726ea1a8SJin Qian } else { 266726ea1a8SJin Qian *iter_last_page_size = last_page_size; 267c89f2750SDavid 'Digit' Turner } 268c89f2750SDavid 'Digit' Turner 269726ea1a8SJin Qian ret = get_user_pages_fast( 270726ea1a8SJin Qian first_page, requested_pages, !is_write, pages); 271726ea1a8SJin Qian if (ret <= 0) 272c89f2750SDavid 'Digit' Turner return -EFAULT; 273726ea1a8SJin Qian if (ret < requested_pages) 274726ea1a8SJin Qian *iter_last_page_size = PAGE_SIZE; 275726ea1a8SJin Qian return ret; 276c89f2750SDavid 'Digit' Turner 277726ea1a8SJin Qian } 278726ea1a8SJin Qian 279726ea1a8SJin Qian static void release_user_pages(struct page **pages, int pages_count, 280726ea1a8SJin Qian int is_write, s32 consumed_size) 281726ea1a8SJin Qian { 282726ea1a8SJin Qian int i; 283726ea1a8SJin Qian 284726ea1a8SJin Qian for (i = 0; i < pages_count; i++) { 285726ea1a8SJin Qian if (!is_write && consumed_size > 0) 286726ea1a8SJin Qian set_page_dirty(pages[i]); 287726ea1a8SJin Qian put_page(pages[i]); 288726ea1a8SJin Qian } 289726ea1a8SJin Qian } 290726ea1a8SJin Qian 291726ea1a8SJin Qian /* Populate the call parameters, merging adjacent pages together */ 292726ea1a8SJin Qian static void populate_rw_params( 293726ea1a8SJin Qian struct page **pages, int pages_count, 294726ea1a8SJin Qian unsigned long address, unsigned long address_end, 295726ea1a8SJin Qian unsigned long first_page, unsigned long last_page, 296726ea1a8SJin Qian unsigned int iter_last_page_size, 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, 329726ea1a8SJin Qian unsigned long address, unsigned long address_end, int is_write, 330726ea1a8SJin Qian unsigned long last_page, unsigned int last_page_size, 331726ea1a8SJin Qian s32 *consumed_size, int *status) 332726ea1a8SJin Qian { 333f563dab4SGreg Kroah-Hartman static struct page *pages[MAX_BUFFERS_PER_COMMAND]; 334726ea1a8SJin Qian unsigned long first_page = address & PAGE_MASK; 335726ea1a8SJin Qian unsigned int iter_last_page_size; 336726ea1a8SJin Qian int pages_count = pin_user_pages(first_page, last_page, 337726ea1a8SJin Qian last_page_size, is_write, 338726ea1a8SJin Qian pages, &iter_last_page_size); 339726ea1a8SJin Qian 340726ea1a8SJin Qian if (pages_count < 0) 341726ea1a8SJin Qian return pages_count; 342726ea1a8SJin Qian 343726ea1a8SJin Qian /* Serialize access to the pipe command buffers */ 344c89f2750SDavid 'Digit' Turner if (mutex_lock_interruptible(&pipe->lock)) 345c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 346c89f2750SDavid 'Digit' Turner 347726ea1a8SJin Qian populate_rw_params(pages, pages_count, address, address_end, 348726ea1a8SJin Qian first_page, last_page, iter_last_page_size, is_write, 349726ea1a8SJin Qian pipe->command_buffer); 350c89f2750SDavid 'Digit' Turner 351726ea1a8SJin Qian /* Transfer the data */ 352726ea1a8SJin Qian *status = goldfish_cmd_locked(pipe, 353726ea1a8SJin Qian is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ); 354c89f2750SDavid 'Digit' Turner 355726ea1a8SJin Qian *consumed_size = pipe->command_buffer->rw_params.consumed_size; 3564f42071cSYu Ning 357726ea1a8SJin Qian release_user_pages(pages, pages_count, is_write, *consumed_size); 358726ea1a8SJin Qian 359f563dab4SGreg Kroah-Hartman mutex_unlock(&pipe->lock); 360f563dab4SGreg Kroah-Hartman 361726ea1a8SJin Qian return 0; 362c89f2750SDavid 'Digit' Turner } 363c89f2750SDavid 'Digit' Turner 364726ea1a8SJin Qian static int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write) 365726ea1a8SJin Qian { 366726ea1a8SJin Qian u32 wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; 367c89f2750SDavid 'Digit' Turner 368c89f2750SDavid 'Digit' Turner set_bit(wakeBit, &pipe->flags); 369c89f2750SDavid 'Digit' Turner 370c89f2750SDavid 'Digit' Turner /* Tell the emulator we're going to wait for a wake event */ 371726ea1a8SJin Qian (void)goldfish_cmd(pipe, 372726ea1a8SJin Qian is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ); 373c89f2750SDavid 'Digit' Turner 374c89f2750SDavid 'Digit' Turner while (test_bit(wakeBit, &pipe->flags)) { 375c89f2750SDavid 'Digit' Turner if (wait_event_interruptible( 376c89f2750SDavid 'Digit' Turner pipe->wake_queue, 377c89f2750SDavid 'Digit' Turner !test_bit(wakeBit, &pipe->flags))) 378c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 379c89f2750SDavid 'Digit' Turner 380c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 381c89f2750SDavid 'Digit' Turner return -EIO; 382c89f2750SDavid 'Digit' Turner } 383c89f2750SDavid 'Digit' Turner 384726ea1a8SJin Qian return 0; 385c89f2750SDavid 'Digit' Turner } 3862f3be882SChristoffer Dall 387726ea1a8SJin Qian static ssize_t goldfish_pipe_read_write(struct file *filp, 388726ea1a8SJin Qian char __user *buffer, size_t bufflen, int is_write) 389726ea1a8SJin Qian { 390726ea1a8SJin Qian struct goldfish_pipe *pipe = filp->private_data; 391726ea1a8SJin Qian int count = 0, ret = -EINVAL; 392726ea1a8SJin Qian unsigned long address, address_end, last_page; 393726ea1a8SJin Qian unsigned int last_page_size; 394726ea1a8SJin Qian 395726ea1a8SJin Qian /* If the emulator already closed the pipe, no need to go further */ 396726ea1a8SJin Qian if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))) 397726ea1a8SJin Qian return -EIO; 398726ea1a8SJin Qian /* Null reads or writes succeeds */ 399726ea1a8SJin Qian if (unlikely(bufflen == 0)) 400726ea1a8SJin Qian return 0; 401726ea1a8SJin Qian /* Check the buffer range for access */ 402726ea1a8SJin Qian if (unlikely(!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, 403726ea1a8SJin Qian buffer, bufflen))) 404726ea1a8SJin Qian return -EFAULT; 405726ea1a8SJin Qian 406726ea1a8SJin Qian address = (unsigned long)buffer; 407726ea1a8SJin Qian address_end = address + bufflen; 408726ea1a8SJin Qian last_page = (address_end - 1) & PAGE_MASK; 409726ea1a8SJin Qian last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1; 410726ea1a8SJin Qian 411726ea1a8SJin Qian while (address < address_end) { 412726ea1a8SJin Qian s32 consumed_size; 413726ea1a8SJin Qian int status; 414726ea1a8SJin Qian 415726ea1a8SJin Qian ret = transfer_max_buffers(pipe, address, address_end, is_write, 416726ea1a8SJin Qian last_page, last_page_size, &consumed_size, 417726ea1a8SJin Qian &status); 4182f3be882SChristoffer Dall if (ret < 0) 419726ea1a8SJin Qian break; 420726ea1a8SJin Qian 421726ea1a8SJin Qian if (consumed_size > 0) { 422726ea1a8SJin Qian /* No matter what's the status, we've transferred 423726ea1a8SJin Qian * something. 424726ea1a8SJin Qian */ 425726ea1a8SJin Qian count += consumed_size; 426726ea1a8SJin Qian address += consumed_size; 427726ea1a8SJin Qian } 428726ea1a8SJin Qian if (status > 0) 429726ea1a8SJin Qian continue; 430726ea1a8SJin Qian if (status == 0) { 431726ea1a8SJin Qian /* EOF */ 432726ea1a8SJin Qian ret = 0; 433726ea1a8SJin Qian break; 434726ea1a8SJin Qian } 435726ea1a8SJin Qian if (count > 0) { 436726ea1a8SJin Qian /* 437726ea1a8SJin Qian * An error occurred, but we already transferred 438726ea1a8SJin Qian * something on one of the previous iterations. 439726ea1a8SJin Qian * Just return what we already copied and log this 440726ea1a8SJin Qian * err. 441726ea1a8SJin Qian */ 442726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN) 44325b97d57SRoman Kiryanov dev_err_ratelimited(pipe->dev->pdev_dev, 44425b97d57SRoman Kiryanov "backend error %d on %s\n", 445726ea1a8SJin Qian status, is_write ? "write" : "read"); 446726ea1a8SJin Qian break; 447726ea1a8SJin Qian } 448726ea1a8SJin Qian 449726ea1a8SJin Qian /* 450726ea1a8SJin Qian * If the error is not PIPE_ERROR_AGAIN, or if we are in 451726ea1a8SJin Qian * non-blocking mode, just return the error code. 452726ea1a8SJin Qian */ 453726ea1a8SJin Qian if (status != PIPE_ERROR_AGAIN || 454726ea1a8SJin Qian (filp->f_flags & O_NONBLOCK) != 0) { 455726ea1a8SJin Qian ret = goldfish_pipe_error_convert(status); 456726ea1a8SJin Qian break; 457726ea1a8SJin Qian } 458726ea1a8SJin Qian 459726ea1a8SJin Qian status = wait_for_host_signal(pipe, is_write); 460726ea1a8SJin Qian if (status < 0) 461726ea1a8SJin Qian return status; 462726ea1a8SJin Qian } 463726ea1a8SJin Qian 464726ea1a8SJin Qian if (count > 0) 4652f3be882SChristoffer Dall return count; 466726ea1a8SJin Qian return ret; 467c89f2750SDavid 'Digit' Turner } 468c89f2750SDavid 'Digit' Turner 469c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, 470c89f2750SDavid 'Digit' Turner size_t bufflen, loff_t *ppos) 471c89f2750SDavid 'Digit' Turner { 472726ea1a8SJin Qian return goldfish_pipe_read_write(filp, buffer, bufflen, 473726ea1a8SJin Qian /* is_write */ 0); 474c89f2750SDavid 'Digit' Turner } 475c89f2750SDavid 'Digit' Turner 476c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_write(struct file *filp, 477c89f2750SDavid 'Digit' Turner const char __user *buffer, size_t bufflen, 478c89f2750SDavid 'Digit' Turner loff_t *ppos) 479c89f2750SDavid 'Digit' Turner { 480726ea1a8SJin Qian return goldfish_pipe_read_write(filp, 481726ea1a8SJin Qian /* cast away the const */(char __user *)buffer, bufflen, 482726ea1a8SJin Qian /* is_write */ 1); 483c89f2750SDavid 'Digit' Turner } 484c89f2750SDavid 'Digit' Turner 485afc9a42bSAl Viro static __poll_t goldfish_pipe_poll(struct file *filp, poll_table *wait) 486c89f2750SDavid 'Digit' Turner { 487c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 488afc9a42bSAl Viro __poll_t mask = 0; 489c89f2750SDavid 'Digit' Turner int status; 490c89f2750SDavid 'Digit' Turner 491c89f2750SDavid 'Digit' Turner poll_wait(filp, &pipe->wake_queue, wait); 492c89f2750SDavid 'Digit' Turner 493726ea1a8SJin Qian status = goldfish_cmd(pipe, PIPE_CMD_POLL); 494726ea1a8SJin Qian if (status < 0) 495726ea1a8SJin Qian return -ERESTARTSYS; 496c89f2750SDavid 'Digit' Turner 497c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_IN) 498a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM; 499c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_OUT) 500a9a08845SLinus Torvalds mask |= EPOLLOUT | EPOLLWRNORM; 501c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_HUP) 502a9a08845SLinus Torvalds mask |= EPOLLHUP; 503c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 504a9a08845SLinus Torvalds mask |= EPOLLERR; 505c89f2750SDavid 'Digit' Turner 506c89f2750SDavid 'Digit' Turner return mask; 507c89f2750SDavid 'Digit' Turner } 508c89f2750SDavid 'Digit' Turner 509726ea1a8SJin Qian static void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev, 510726ea1a8SJin Qian u32 id, u32 flags) 511c89f2750SDavid 'Digit' Turner { 512c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe; 51349a75c44SJun Tian 514726ea1a8SJin Qian if (WARN_ON(id >= dev->pipes_capacity)) 515726ea1a8SJin Qian return; 51625c72c78SJun Tian 517726ea1a8SJin Qian pipe = dev->pipes[id]; 518726ea1a8SJin Qian if (!pipe) 519726ea1a8SJin Qian return; 520726ea1a8SJin Qian pipe->signalled_flags |= flags; 521c89f2750SDavid 'Digit' Turner 522726ea1a8SJin Qian if (pipe->prev_signalled || pipe->next_signalled 523726ea1a8SJin Qian || dev->first_signalled_pipe == pipe) 524726ea1a8SJin Qian return; /* already in the list */ 525726ea1a8SJin Qian pipe->next_signalled = dev->first_signalled_pipe; 526726ea1a8SJin Qian if (dev->first_signalled_pipe) 527726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = pipe; 528726ea1a8SJin Qian dev->first_signalled_pipe = pipe; 529c89f2750SDavid 'Digit' Turner } 530726ea1a8SJin Qian 531726ea1a8SJin Qian static void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev, 53253bdf668SRoman Kiryanov struct goldfish_pipe *pipe) 53353bdf668SRoman Kiryanov { 534726ea1a8SJin Qian if (pipe->prev_signalled) 535726ea1a8SJin Qian pipe->prev_signalled->next_signalled = pipe->next_signalled; 536726ea1a8SJin Qian if (pipe->next_signalled) 537726ea1a8SJin Qian pipe->next_signalled->prev_signalled = pipe->prev_signalled; 538726ea1a8SJin Qian if (pipe == dev->first_signalled_pipe) 539726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 540726ea1a8SJin Qian pipe->prev_signalled = NULL; 541726ea1a8SJin Qian pipe->next_signalled = NULL; 542726ea1a8SJin Qian } 543726ea1a8SJin Qian 544726ea1a8SJin Qian static struct goldfish_pipe *signalled_pipes_pop_front( 545726ea1a8SJin Qian struct goldfish_pipe_dev *dev, int *wakes) 546726ea1a8SJin Qian { 547726ea1a8SJin Qian struct goldfish_pipe *pipe; 548726ea1a8SJin Qian unsigned long flags; 549726ea1a8SJin Qian 550726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 551726ea1a8SJin Qian 552726ea1a8SJin Qian pipe = dev->first_signalled_pipe; 553726ea1a8SJin Qian if (pipe) { 554726ea1a8SJin Qian *wakes = pipe->signalled_flags; 555726ea1a8SJin Qian pipe->signalled_flags = 0; 556726ea1a8SJin Qian /* 557726ea1a8SJin Qian * This is an optimized version of 558726ea1a8SJin Qian * signalled_pipes_remove_locked() 559726ea1a8SJin Qian * - We want to make it as fast as possible to 560726ea1a8SJin Qian * wake the sleeping pipe operations faster. 561726ea1a8SJin Qian */ 562726ea1a8SJin Qian dev->first_signalled_pipe = pipe->next_signalled; 563726ea1a8SJin Qian if (dev->first_signalled_pipe) 564726ea1a8SJin Qian dev->first_signalled_pipe->prev_signalled = NULL; 565726ea1a8SJin Qian pipe->next_signalled = NULL; 566726ea1a8SJin Qian } 567726ea1a8SJin Qian 568726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 569726ea1a8SJin Qian return pipe; 570726ea1a8SJin Qian } 571726ea1a8SJin Qian 572726ea1a8SJin Qian static void goldfish_interrupt_task(unsigned long unused) 573726ea1a8SJin Qian { 574726ea1a8SJin Qian /* Iterate over the signalled pipes and wake them one by one */ 575726ea1a8SJin Qian struct goldfish_pipe *pipe; 576726ea1a8SJin Qian int wakes; 577726ea1a8SJin Qian 578869fd502SRoman Kiryanov while ((pipe = signalled_pipes_pop_front(&goldfish_pipe_dev, &wakes)) != 579869fd502SRoman Kiryanov NULL) { 580726ea1a8SJin Qian if (wakes & PIPE_WAKE_CLOSED) { 581726ea1a8SJin Qian pipe->flags = 1 << BIT_CLOSED_ON_HOST; 582726ea1a8SJin Qian } else { 583c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_READ) 584c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_READ, &pipe->flags); 585c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_WRITE) 586c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); 587c89f2750SDavid 'Digit' Turner } 588726ea1a8SJin Qian /* 589726ea1a8SJin Qian * wake_up_interruptible() implies a write barrier, so don't 590726ea1a8SJin Qian * explicitly add another one here. 591726ea1a8SJin Qian */ 592726ea1a8SJin Qian wake_up_interruptible(&pipe->wake_queue); 593726ea1a8SJin Qian } 594726ea1a8SJin Qian } 595ea4ba866SColin Ian King static DECLARE_TASKLET(goldfish_interrupt_tasklet, goldfish_interrupt_task, 0); 596c89f2750SDavid 'Digit' Turner 597726ea1a8SJin Qian /* 598726ea1a8SJin Qian * The general idea of the interrupt handling: 599726ea1a8SJin Qian * 600726ea1a8SJin Qian * 1. device raises an interrupt if there's at least one signalled pipe 601726ea1a8SJin Qian * 2. IRQ handler reads the signalled pipes and their count from the device 602726ea1a8SJin Qian * 3. device writes them into a shared buffer and returns the count 603726ea1a8SJin Qian * it only resets the IRQ if it has returned all signalled pipes, 604726ea1a8SJin Qian * otherwise it leaves it raised, so IRQ handler will be called 605726ea1a8SJin Qian * again for the next chunk 606726ea1a8SJin Qian * 4. IRQ handler adds all returned pipes to the device's signalled pipes list 607726ea1a8SJin Qian * 5. IRQ handler launches a tasklet to process the signalled pipes from the 608726ea1a8SJin Qian * list in a separate context 609726ea1a8SJin Qian */ 610726ea1a8SJin Qian static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) 611726ea1a8SJin Qian { 612726ea1a8SJin Qian u32 count; 613726ea1a8SJin Qian u32 i; 614726ea1a8SJin Qian unsigned long flags; 615726ea1a8SJin Qian struct goldfish_pipe_dev *dev = dev_id; 616726ea1a8SJin Qian 617869fd502SRoman Kiryanov if (dev != &goldfish_pipe_dev) 618726ea1a8SJin Qian return IRQ_NONE; 619726ea1a8SJin Qian 620726ea1a8SJin Qian /* Request the signalled pipes from the device */ 621726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 622726ea1a8SJin Qian 623726ea1a8SJin Qian count = readl(dev->base + PIPE_REG_GET_SIGNALLED); 624726ea1a8SJin Qian if (count == 0) { 625726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 626726ea1a8SJin Qian return IRQ_NONE; 627726ea1a8SJin Qian } 628726ea1a8SJin Qian if (count > MAX_SIGNALLED_PIPES) 629726ea1a8SJin Qian count = MAX_SIGNALLED_PIPES; 630726ea1a8SJin Qian 631726ea1a8SJin Qian for (i = 0; i < count; ++i) 632726ea1a8SJin Qian signalled_pipes_add_locked(dev, 633726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].id, 634726ea1a8SJin Qian dev->buffers->signalled_pipe_buffers[i].flags); 635726ea1a8SJin Qian 636726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 637726ea1a8SJin Qian 638726ea1a8SJin Qian tasklet_schedule(&goldfish_interrupt_tasklet); 639726ea1a8SJin Qian return IRQ_HANDLED; 640726ea1a8SJin Qian } 641726ea1a8SJin Qian 642726ea1a8SJin Qian static int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) 643726ea1a8SJin Qian { 644726ea1a8SJin Qian int id; 645726ea1a8SJin Qian 646726ea1a8SJin Qian for (id = 0; id < dev->pipes_capacity; ++id) 647726ea1a8SJin Qian if (!dev->pipes[id]) 648726ea1a8SJin Qian return id; 649726ea1a8SJin Qian 650726ea1a8SJin Qian { 65184ae527aSRoman Kiryanov /* Reallocate the array. 65284ae527aSRoman Kiryanov * Since get_free_pipe_id_locked runs with interrupts disabled, 65384ae527aSRoman Kiryanov * we don't want to make calls that could lead to sleep. 65484ae527aSRoman Kiryanov */ 655726ea1a8SJin Qian u32 new_capacity = 2 * dev->pipes_capacity; 656726ea1a8SJin Qian struct goldfish_pipe **pipes = 6573eff8ecdSWei Yongjun kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC); 658726ea1a8SJin Qian if (!pipes) 659726ea1a8SJin Qian return -ENOMEM; 660726ea1a8SJin Qian memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); 661726ea1a8SJin Qian kfree(dev->pipes); 662726ea1a8SJin Qian dev->pipes = pipes; 663726ea1a8SJin Qian id = dev->pipes_capacity; 664726ea1a8SJin Qian dev->pipes_capacity = new_capacity; 665726ea1a8SJin Qian } 666726ea1a8SJin Qian return id; 667c89f2750SDavid 'Digit' Turner } 668c89f2750SDavid 'Digit' Turner 669c89f2750SDavid 'Digit' Turner /** 670c89f2750SDavid 'Digit' Turner * goldfish_pipe_open - open a channel to the AVD 671c89f2750SDavid 'Digit' Turner * @inode: inode of device 672c89f2750SDavid 'Digit' Turner * @file: file struct of opener 673c89f2750SDavid 'Digit' Turner * 674c89f2750SDavid 'Digit' Turner * Create a new pipe link between the emulator and the use application. 675c89f2750SDavid 'Digit' Turner * Each new request produces a new pipe. 676c89f2750SDavid 'Digit' Turner * 677c89f2750SDavid 'Digit' Turner * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit 678c89f2750SDavid 'Digit' Turner * right now so this is fine. A move to 64bit will need this addressing 679c89f2750SDavid 'Digit' Turner */ 680c89f2750SDavid 'Digit' Turner static int goldfish_pipe_open(struct inode *inode, struct file *file) 681c89f2750SDavid 'Digit' Turner { 682869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 683726ea1a8SJin Qian unsigned long flags; 684726ea1a8SJin Qian int id; 685726ea1a8SJin Qian int status; 686c89f2750SDavid 'Digit' Turner 687c89f2750SDavid 'Digit' Turner /* Allocate new pipe kernel object */ 688726ea1a8SJin Qian struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); 689c89f2750SDavid 'Digit' Turner if (pipe == NULL) 690c89f2750SDavid 'Digit' Turner return -ENOMEM; 691c89f2750SDavid 'Digit' Turner 692c89f2750SDavid 'Digit' Turner pipe->dev = dev; 693c89f2750SDavid 'Digit' Turner mutex_init(&pipe->lock); 694c89f2750SDavid 'Digit' Turner init_waitqueue_head(&pipe->wake_queue); 695c89f2750SDavid 'Digit' Turner 696c89f2750SDavid 'Digit' Turner /* 697726ea1a8SJin Qian * Command buffer needs to be allocated on its own page to make sure 698726ea1a8SJin Qian * it is physically contiguous in host's address space. 699c89f2750SDavid 'Digit' Turner */ 700d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE); 701726ea1a8SJin Qian pipe->command_buffer = 702726ea1a8SJin Qian (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL); 703726ea1a8SJin Qian if (!pipe->command_buffer) { 704726ea1a8SJin Qian status = -ENOMEM; 705726ea1a8SJin Qian goto err_pipe; 706726ea1a8SJin Qian } 707c89f2750SDavid 'Digit' Turner 708726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 709726ea1a8SJin Qian 710726ea1a8SJin Qian id = get_free_pipe_id_locked(dev); 711726ea1a8SJin Qian if (id < 0) { 712726ea1a8SJin Qian status = id; 713726ea1a8SJin Qian goto err_id_locked; 714726ea1a8SJin Qian } 715726ea1a8SJin Qian 716726ea1a8SJin Qian dev->pipes[id] = pipe; 717726ea1a8SJin Qian pipe->id = id; 718726ea1a8SJin Qian pipe->command_buffer->id = id; 719726ea1a8SJin Qian 720726ea1a8SJin Qian /* Now tell the emulator we're opening a new pipe. */ 721726ea1a8SJin Qian dev->buffers->open_command_params.rw_params_max_count = 722726ea1a8SJin Qian MAX_BUFFERS_PER_COMMAND; 723726ea1a8SJin Qian dev->buffers->open_command_params.command_buffer_ptr = 724726ea1a8SJin Qian (u64)(unsigned long)__pa(pipe->command_buffer); 725726ea1a8SJin Qian status = goldfish_cmd_locked(pipe, PIPE_CMD_OPEN); 726726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 727726ea1a8SJin Qian if (status < 0) 728726ea1a8SJin Qian goto err_cmd; 729726ea1a8SJin Qian /* All is done, save the pipe into the file's private data field */ 730726ea1a8SJin Qian file->private_data = pipe; 731726ea1a8SJin Qian return 0; 732726ea1a8SJin Qian 733726ea1a8SJin Qian err_cmd: 734726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 735726ea1a8SJin Qian dev->pipes[id] = NULL; 736726ea1a8SJin Qian err_id_locked: 737726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 738726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 739726ea1a8SJin Qian err_pipe: 740c89f2750SDavid 'Digit' Turner kfree(pipe); 741c89f2750SDavid 'Digit' Turner return status; 742c89f2750SDavid 'Digit' Turner } 743c89f2750SDavid 'Digit' Turner 744c89f2750SDavid 'Digit' Turner static int goldfish_pipe_release(struct inode *inode, struct file *filp) 745c89f2750SDavid 'Digit' Turner { 746726ea1a8SJin Qian unsigned long flags; 747c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 748726ea1a8SJin Qian struct goldfish_pipe_dev *dev = pipe->dev; 749c89f2750SDavid 'Digit' Turner 750c89f2750SDavid 'Digit' Turner /* The guest is closing the channel, so tell the emulator right now */ 751726ea1a8SJin Qian (void)goldfish_cmd(pipe, PIPE_CMD_CLOSE); 752726ea1a8SJin Qian 753726ea1a8SJin Qian spin_lock_irqsave(&dev->lock, flags); 754726ea1a8SJin Qian dev->pipes[pipe->id] = NULL; 755726ea1a8SJin Qian signalled_pipes_remove_locked(dev, pipe); 756726ea1a8SJin Qian spin_unlock_irqrestore(&dev->lock, flags); 757726ea1a8SJin Qian 758c89f2750SDavid 'Digit' Turner filp->private_data = NULL; 759726ea1a8SJin Qian free_page((unsigned long)pipe->command_buffer); 760726ea1a8SJin Qian kfree(pipe); 761c89f2750SDavid 'Digit' Turner return 0; 762c89f2750SDavid 'Digit' Turner } 763c89f2750SDavid 'Digit' Turner 764c89f2750SDavid 'Digit' Turner static const struct file_operations goldfish_pipe_fops = { 765c89f2750SDavid 'Digit' Turner .owner = THIS_MODULE, 766c89f2750SDavid 'Digit' Turner .read = goldfish_pipe_read, 767c89f2750SDavid 'Digit' Turner .write = goldfish_pipe_write, 768c89f2750SDavid 'Digit' Turner .poll = goldfish_pipe_poll, 769c89f2750SDavid 'Digit' Turner .open = goldfish_pipe_open, 770c89f2750SDavid 'Digit' Turner .release = goldfish_pipe_release, 771c89f2750SDavid 'Digit' Turner }; 772c89f2750SDavid 'Digit' Turner 773869fd502SRoman Kiryanov static struct miscdevice goldfish_pipe_miscdev = { 774c89f2750SDavid 'Digit' Turner .minor = MISC_DYNAMIC_MINOR, 775c89f2750SDavid 'Digit' Turner .name = "goldfish_pipe", 776c89f2750SDavid 'Digit' Turner .fops = &goldfish_pipe_fops, 777c89f2750SDavid 'Digit' Turner }; 778c89f2750SDavid 'Digit' Turner 779726ea1a8SJin Qian static int goldfish_pipe_device_init(struct platform_device *pdev) 780726ea1a8SJin Qian { 781869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 782726ea1a8SJin Qian int err = devm_request_irq(&pdev->dev, dev->irq, 783726ea1a8SJin Qian goldfish_pipe_interrupt, 784726ea1a8SJin Qian IRQF_SHARED, "goldfish_pipe", dev); 785726ea1a8SJin Qian if (err) { 786726ea1a8SJin Qian dev_err(&pdev->dev, "unable to allocate IRQ for v2\n"); 787726ea1a8SJin Qian return err; 788726ea1a8SJin Qian } 789726ea1a8SJin Qian 790869fd502SRoman Kiryanov err = misc_register(&goldfish_pipe_miscdev); 791726ea1a8SJin Qian if (err) { 792726ea1a8SJin Qian dev_err(&pdev->dev, "unable to register v2 device\n"); 793726ea1a8SJin Qian return err; 794726ea1a8SJin Qian } 795726ea1a8SJin Qian 79625b97d57SRoman Kiryanov dev->pdev_dev = &pdev->dev; 797726ea1a8SJin Qian dev->first_signalled_pipe = NULL; 798726ea1a8SJin Qian dev->pipes_capacity = INITIAL_PIPES_CAPACITY; 799726ea1a8SJin Qian dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), 800726ea1a8SJin Qian GFP_KERNEL); 801726ea1a8SJin Qian if (!dev->pipes) 802726ea1a8SJin Qian return -ENOMEM; 803726ea1a8SJin Qian 804726ea1a8SJin Qian /* 805726ea1a8SJin Qian * We're going to pass two buffers, open_command_params and 806726ea1a8SJin Qian * signalled_pipe_buffers, to the host. This means each of those buffers 807726ea1a8SJin Qian * needs to be contained in a single physical page. The easiest choice 808726ea1a8SJin Qian * is to just allocate a page and place the buffers in it. 809726ea1a8SJin Qian */ 810d23069a5SRoman Kiryanov BUILD_BUG_ON(sizeof(struct goldfish_pipe_dev_buffers) > PAGE_SIZE); 811*2ed43e53SRoman Kiryanov dev->buffers = (struct goldfish_pipe_dev_buffers *) 812*2ed43e53SRoman Kiryanov __get_free_page(GFP_KERNEL); 813*2ed43e53SRoman Kiryanov if (!dev->buffers) { 814726ea1a8SJin Qian kfree(dev->pipes); 815726ea1a8SJin Qian return -ENOMEM; 816726ea1a8SJin Qian } 817726ea1a8SJin Qian 818726ea1a8SJin Qian /* Send the buffer addresses to the host */ 819726ea1a8SJin Qian { 820726ea1a8SJin Qian u64 paddr = __pa(&dev->buffers->signalled_pipe_buffers); 821726ea1a8SJin Qian 822726ea1a8SJin Qian writel((u32)(unsigned long)(paddr >> 32), 823726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH); 824726ea1a8SJin Qian writel((u32)(unsigned long)paddr, 825726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER); 826726ea1a8SJin Qian writel((u32)MAX_SIGNALLED_PIPES, 827726ea1a8SJin Qian dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT); 828726ea1a8SJin Qian 829726ea1a8SJin Qian paddr = __pa(&dev->buffers->open_command_params); 830726ea1a8SJin Qian writel((u32)(unsigned long)(paddr >> 32), 831726ea1a8SJin Qian dev->base + PIPE_REG_OPEN_BUFFER_HIGH); 832726ea1a8SJin Qian writel((u32)(unsigned long)paddr, 833726ea1a8SJin Qian dev->base + PIPE_REG_OPEN_BUFFER); 834726ea1a8SJin Qian } 835726ea1a8SJin Qian return 0; 836726ea1a8SJin Qian } 837726ea1a8SJin Qian 838726ea1a8SJin Qian static void goldfish_pipe_device_deinit(struct platform_device *pdev) 839726ea1a8SJin Qian { 840869fd502SRoman Kiryanov misc_deregister(&goldfish_pipe_miscdev); 841869fd502SRoman Kiryanov kfree(goldfish_pipe_dev.pipes); 842869fd502SRoman Kiryanov free_page((unsigned long)goldfish_pipe_dev.buffers); 843726ea1a8SJin Qian } 844726ea1a8SJin Qian 845c89f2750SDavid 'Digit' Turner static int goldfish_pipe_probe(struct platform_device *pdev) 846c89f2750SDavid 'Digit' Turner { 847c89f2750SDavid 'Digit' Turner int err; 848c89f2750SDavid 'Digit' Turner struct resource *r; 849869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 850c89f2750SDavid 'Digit' Turner 851c89f2750SDavid 'Digit' Turner /* not thread safe, but this should not happen */ 852c89f2750SDavid 'Digit' Turner WARN_ON(dev->base != NULL); 853c89f2750SDavid 'Digit' Turner 854c89f2750SDavid 'Digit' Turner spin_lock_init(&dev->lock); 855c89f2750SDavid 'Digit' Turner 856c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 857c89f2750SDavid 'Digit' Turner if (r == NULL || resource_size(r) < PAGE_SIZE) { 858c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "can't allocate i/o page\n"); 859c89f2750SDavid 'Digit' Turner return -EINVAL; 860c89f2750SDavid 'Digit' Turner } 861c89f2750SDavid 'Digit' Turner dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); 862c89f2750SDavid 'Digit' Turner if (dev->base == NULL) { 863c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "ioremap failed\n"); 864c89f2750SDavid 'Digit' Turner return -EINVAL; 865c89f2750SDavid 'Digit' Turner } 866c89f2750SDavid 'Digit' Turner 867c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 868c89f2750SDavid 'Digit' Turner if (r == NULL) { 869c89f2750SDavid 'Digit' Turner err = -EINVAL; 870c89f2750SDavid 'Digit' Turner goto error; 871c89f2750SDavid 'Digit' Turner } 872c89f2750SDavid 'Digit' Turner dev->irq = r->start; 873c89f2750SDavid 'Digit' Turner 874726ea1a8SJin Qian /* 875726ea1a8SJin Qian * Exchange the versions with the host device 876726ea1a8SJin Qian * 877726ea1a8SJin Qian * Note: v1 driver used to not report its version, so we write it before 878726ea1a8SJin Qian * reading device version back: this allows the host implementation to 879726ea1a8SJin Qian * detect the old driver (if there was no version write before read). 8804f42071cSYu Ning */ 881726ea1a8SJin Qian writel((u32)PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION); 8824f42071cSYu Ning dev->version = readl(dev->base + PIPE_REG_VERSION); 883726ea1a8SJin Qian if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION)) 884726ea1a8SJin Qian return -EINVAL; 885726ea1a8SJin Qian 886726ea1a8SJin Qian err = goldfish_pipe_device_init(pdev); 887726ea1a8SJin Qian if (!err) 888c89f2750SDavid 'Digit' Turner return 0; 889c89f2750SDavid 'Digit' Turner 890c89f2750SDavid 'Digit' Turner error: 891c89f2750SDavid 'Digit' Turner dev->base = NULL; 892c89f2750SDavid 'Digit' Turner return err; 893c89f2750SDavid 'Digit' Turner } 894c89f2750SDavid 'Digit' Turner 895c89f2750SDavid 'Digit' Turner static int goldfish_pipe_remove(struct platform_device *pdev) 896c89f2750SDavid 'Digit' Turner { 897869fd502SRoman Kiryanov struct goldfish_pipe_dev *dev = &goldfish_pipe_dev; 898726ea1a8SJin Qian goldfish_pipe_device_deinit(pdev); 899c89f2750SDavid 'Digit' Turner dev->base = NULL; 900c89f2750SDavid 'Digit' Turner return 0; 901c89f2750SDavid 'Digit' Turner } 902c89f2750SDavid 'Digit' Turner 903d62f324bSJason Hu static const struct acpi_device_id goldfish_pipe_acpi_match[] = { 904d62f324bSJason Hu { "GFSH0003", 0 }, 905d62f324bSJason Hu { }, 906d62f324bSJason Hu }; 907d62f324bSJason Hu MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); 908d62f324bSJason Hu 90991a18a41SGreg Hackmann static const struct of_device_id goldfish_pipe_of_match[] = { 91091a18a41SGreg Hackmann { .compatible = "google,android-pipe", }, 91191a18a41SGreg Hackmann {}, 91291a18a41SGreg Hackmann }; 91391a18a41SGreg Hackmann MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); 91491a18a41SGreg Hackmann 915726ea1a8SJin Qian static struct platform_driver goldfish_pipe_driver = { 916c89f2750SDavid 'Digit' Turner .probe = goldfish_pipe_probe, 917c89f2750SDavid 'Digit' Turner .remove = goldfish_pipe_remove, 918c89f2750SDavid 'Digit' Turner .driver = { 91991a18a41SGreg Hackmann .name = "goldfish_pipe", 92091a18a41SGreg Hackmann .of_match_table = goldfish_pipe_of_match, 921d62f324bSJason Hu .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), 922c89f2750SDavid 'Digit' Turner } 923c89f2750SDavid 'Digit' Turner }; 924c89f2750SDavid 'Digit' Turner 925726ea1a8SJin Qian module_platform_driver(goldfish_pipe_driver); 926c89f2750SDavid 'Digit' Turner MODULE_AUTHOR("David Turner <digit@google.com>"); 927c3c4e307SRoman Kiryanov MODULE_LICENSE("GPL v2"); 928