18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012 Intel, Inc. 48c2ecf20Sopenharmony_ci * Copyright (C) 2013 Intel, Inc. 58c2ecf20Sopenharmony_ci * Copyright (C) 2014 Linaro Limited 68c2ecf20Sopenharmony_ci * Copyright (C) 2011-2016 Google, Inc. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * This software is licensed under the terms of the GNU General Public 98c2ecf20Sopenharmony_ci * License version 2, as published by the Free Software Foundation, and 108c2ecf20Sopenharmony_ci * may be copied, distributed, and modified under those terms. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This program is distributed in the hope that it will be useful, 138c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 148c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158c2ecf20Sopenharmony_ci * GNU General Public License for more details. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* This source file contains the implementation of a special device driver 208c2ecf20Sopenharmony_ci * that intends to provide a *very* fast communication channel between the 218c2ecf20Sopenharmony_ci * guest system and the QEMU emulator. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * Usage from the guest is simply the following (error handling simplified): 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * int fd = open("/dev/qemu_pipe",O_RDWR); 268c2ecf20Sopenharmony_ci * .... write() or read() through the pipe. 278c2ecf20Sopenharmony_ci * 288c2ecf20Sopenharmony_ci * This driver doesn't deal with the exact protocol used during the session. 298c2ecf20Sopenharmony_ci * It is intended to be as simple as something like: 308c2ecf20Sopenharmony_ci * 318c2ecf20Sopenharmony_ci * // do this _just_ after opening the fd to connect to a specific 328c2ecf20Sopenharmony_ci * // emulator service. 338c2ecf20Sopenharmony_ci * const char* msg = "<pipename>"; 348c2ecf20Sopenharmony_ci * if (write(fd, msg, strlen(msg)+1) < 0) { 358c2ecf20Sopenharmony_ci * ... could not connect to <pipename> service 368c2ecf20Sopenharmony_ci * close(fd); 378c2ecf20Sopenharmony_ci * } 388c2ecf20Sopenharmony_ci * 398c2ecf20Sopenharmony_ci * // after this, simply read() and write() to communicate with the 408c2ecf20Sopenharmony_ci * // service. Exact protocol details left as an exercise to the reader. 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * This driver is very fast because it doesn't copy any data through 438c2ecf20Sopenharmony_ci * intermediate buffers, since the emulator is capable of translating 448c2ecf20Sopenharmony_ci * guest user addresses into host ones. 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * Note that we must however ensure that each user page involved in the 478c2ecf20Sopenharmony_ci * exchange is properly mapped during a transfer. 488c2ecf20Sopenharmony_ci */ 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci#include <linux/module.h> 518c2ecf20Sopenharmony_ci#include <linux/mod_devicetable.h> 528c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 538c2ecf20Sopenharmony_ci#include <linux/kernel.h> 548c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 558c2ecf20Sopenharmony_ci#include <linux/miscdevice.h> 568c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 578c2ecf20Sopenharmony_ci#include <linux/poll.h> 588c2ecf20Sopenharmony_ci#include <linux/sched.h> 598c2ecf20Sopenharmony_ci#include <linux/bitops.h> 608c2ecf20Sopenharmony_ci#include <linux/slab.h> 618c2ecf20Sopenharmony_ci#include <linux/io.h> 628c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 638c2ecf20Sopenharmony_ci#include <linux/mm.h> 648c2ecf20Sopenharmony_ci#include <linux/acpi.h> 658c2ecf20Sopenharmony_ci#include <linux/bug.h> 668c2ecf20Sopenharmony_ci#include "goldfish_pipe_qemu.h" 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* 698c2ecf20Sopenharmony_ci * Update this when something changes in the driver's behavior so the host 708c2ecf20Sopenharmony_ci * can benefit from knowing it 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_cienum { 738c2ecf20Sopenharmony_ci PIPE_DRIVER_VERSION = 2, 748c2ecf20Sopenharmony_ci PIPE_CURRENT_DEVICE_VERSION = 2 758c2ecf20Sopenharmony_ci}; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cienum { 788c2ecf20Sopenharmony_ci MAX_BUFFERS_PER_COMMAND = 336, 798c2ecf20Sopenharmony_ci MAX_SIGNALLED_PIPES = 64, 808c2ecf20Sopenharmony_ci INITIAL_PIPES_CAPACITY = 64 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistruct goldfish_pipe_dev; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* A per-pipe command structure, shared with the host */ 868c2ecf20Sopenharmony_cistruct goldfish_pipe_command { 878c2ecf20Sopenharmony_ci s32 cmd; /* PipeCmdCode, guest -> host */ 888c2ecf20Sopenharmony_ci s32 id; /* pipe id, guest -> host */ 898c2ecf20Sopenharmony_ci s32 status; /* command execution status, host -> guest */ 908c2ecf20Sopenharmony_ci s32 reserved; /* to pad to 64-bit boundary */ 918c2ecf20Sopenharmony_ci union { 928c2ecf20Sopenharmony_ci /* Parameters for PIPE_CMD_{READ,WRITE} */ 938c2ecf20Sopenharmony_ci struct { 948c2ecf20Sopenharmony_ci /* number of buffers, guest -> host */ 958c2ecf20Sopenharmony_ci u32 buffers_count; 968c2ecf20Sopenharmony_ci /* number of consumed bytes, host -> guest */ 978c2ecf20Sopenharmony_ci s32 consumed_size; 988c2ecf20Sopenharmony_ci /* buffer pointers, guest -> host */ 998c2ecf20Sopenharmony_ci u64 ptrs[MAX_BUFFERS_PER_COMMAND]; 1008c2ecf20Sopenharmony_ci /* buffer sizes, guest -> host */ 1018c2ecf20Sopenharmony_ci u32 sizes[MAX_BUFFERS_PER_COMMAND]; 1028c2ecf20Sopenharmony_ci } rw_params; 1038c2ecf20Sopenharmony_ci }; 1048c2ecf20Sopenharmony_ci}; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* A single signalled pipe information */ 1078c2ecf20Sopenharmony_cistruct signalled_pipe_buffer { 1088c2ecf20Sopenharmony_ci u32 id; 1098c2ecf20Sopenharmony_ci u32 flags; 1108c2ecf20Sopenharmony_ci}; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/* Parameters for the PIPE_CMD_OPEN command */ 1138c2ecf20Sopenharmony_cistruct open_command_param { 1148c2ecf20Sopenharmony_ci u64 command_buffer_ptr; 1158c2ecf20Sopenharmony_ci u32 rw_params_max_count; 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/* Device-level set of buffers shared with the host */ 1198c2ecf20Sopenharmony_cistruct goldfish_pipe_dev_buffers { 1208c2ecf20Sopenharmony_ci struct open_command_param open_command_params; 1218c2ecf20Sopenharmony_ci struct signalled_pipe_buffer 1228c2ecf20Sopenharmony_ci signalled_pipe_buffers[MAX_SIGNALLED_PIPES]; 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* This data type models a given pipe instance */ 1268c2ecf20Sopenharmony_cistruct goldfish_pipe { 1278c2ecf20Sopenharmony_ci /* pipe ID - index into goldfish_pipe_dev::pipes array */ 1288c2ecf20Sopenharmony_ci u32 id; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* The wake flags pipe is waiting for 1318c2ecf20Sopenharmony_ci * Note: not protected with any lock, uses atomic operations 1328c2ecf20Sopenharmony_ci * and barriers to make it thread-safe. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci unsigned long flags; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* wake flags host have signalled, 1378c2ecf20Sopenharmony_ci * - protected by goldfish_pipe_dev::lock 1388c2ecf20Sopenharmony_ci */ 1398c2ecf20Sopenharmony_ci unsigned long signalled_flags; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci /* A pointer to command buffer */ 1428c2ecf20Sopenharmony_ci struct goldfish_pipe_command *command_buffer; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci /* doubly linked list of signalled pipes, protected by 1458c2ecf20Sopenharmony_ci * goldfish_pipe_dev::lock 1468c2ecf20Sopenharmony_ci */ 1478c2ecf20Sopenharmony_ci struct goldfish_pipe *prev_signalled; 1488c2ecf20Sopenharmony_ci struct goldfish_pipe *next_signalled; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci /* 1518c2ecf20Sopenharmony_ci * A pipe's own lock. Protects the following: 1528c2ecf20Sopenharmony_ci * - *command_buffer - makes sure a command can safely write its 1538c2ecf20Sopenharmony_ci * parameters to the host and read the results back. 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ci struct mutex lock; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* A wake queue for sleeping until host signals an event */ 1588c2ecf20Sopenharmony_ci wait_queue_head_t wake_queue; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* Pointer to the parent goldfish_pipe_dev instance */ 1618c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev; 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* A buffer of pages, too large to fit into a stack frame */ 1648c2ecf20Sopenharmony_ci struct page *pages[MAX_BUFFERS_PER_COMMAND]; 1658c2ecf20Sopenharmony_ci}; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* The global driver data. Holds a reference to the i/o page used to 1688c2ecf20Sopenharmony_ci * communicate with the emulator, and a wake queue for blocked tasks 1698c2ecf20Sopenharmony_ci * waiting to be awoken. 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_cistruct goldfish_pipe_dev { 1728c2ecf20Sopenharmony_ci /* A magic number to check if this is an instance of this struct */ 1738c2ecf20Sopenharmony_ci void *magic; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* 1768c2ecf20Sopenharmony_ci * Global device spinlock. Protects the following members: 1778c2ecf20Sopenharmony_ci * - pipes, pipes_capacity 1788c2ecf20Sopenharmony_ci * - [*pipes, *pipes + pipes_capacity) - array data 1798c2ecf20Sopenharmony_ci * - first_signalled_pipe, 1808c2ecf20Sopenharmony_ci * goldfish_pipe::prev_signalled, 1818c2ecf20Sopenharmony_ci * goldfish_pipe::next_signalled, 1828c2ecf20Sopenharmony_ci * goldfish_pipe::signalled_flags - all singnalled-related fields, 1838c2ecf20Sopenharmony_ci * in all allocated pipes 1848c2ecf20Sopenharmony_ci * - open_command_params - PIPE_CMD_OPEN-related buffers 1858c2ecf20Sopenharmony_ci * 1868c2ecf20Sopenharmony_ci * It looks like a lot of different fields, but the trick is that 1878c2ecf20Sopenharmony_ci * the only operation that happens often is the signalled pipes array 1888c2ecf20Sopenharmony_ci * manipulation. That's why it's OK for now to keep the rest of the 1898c2ecf20Sopenharmony_ci * fields under the same lock. If we notice too much contention because 1908c2ecf20Sopenharmony_ci * of PIPE_CMD_OPEN, then we should add a separate lock there. 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ci spinlock_t lock; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci /* 1958c2ecf20Sopenharmony_ci * Array of the pipes of |pipes_capacity| elements, 1968c2ecf20Sopenharmony_ci * indexed by goldfish_pipe::id 1978c2ecf20Sopenharmony_ci */ 1988c2ecf20Sopenharmony_ci struct goldfish_pipe **pipes; 1998c2ecf20Sopenharmony_ci u32 pipes_capacity; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* Pointers to the buffers host uses for interaction with this driver */ 2028c2ecf20Sopenharmony_ci struct goldfish_pipe_dev_buffers *buffers; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* Head of a doubly linked list of signalled pipes */ 2058c2ecf20Sopenharmony_ci struct goldfish_pipe *first_signalled_pipe; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* ptr to platform device's device struct */ 2088c2ecf20Sopenharmony_ci struct device *pdev_dev; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci /* Some device-specific data */ 2118c2ecf20Sopenharmony_ci int irq; 2128c2ecf20Sopenharmony_ci int version; 2138c2ecf20Sopenharmony_ci unsigned char __iomem *base; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci /* an irq tasklet to run goldfish_interrupt_task */ 2168c2ecf20Sopenharmony_ci struct tasklet_struct irq_tasklet; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci struct miscdevice miscdev; 2198c2ecf20Sopenharmony_ci}; 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic int goldfish_pipe_cmd_locked(struct goldfish_pipe *pipe, 2228c2ecf20Sopenharmony_ci enum PipeCmdCode cmd) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci pipe->command_buffer->cmd = cmd; 2258c2ecf20Sopenharmony_ci /* failure by default */ 2268c2ecf20Sopenharmony_ci pipe->command_buffer->status = PIPE_ERROR_INVAL; 2278c2ecf20Sopenharmony_ci writel(pipe->id, pipe->dev->base + PIPE_REG_CMD); 2288c2ecf20Sopenharmony_ci return pipe->command_buffer->status; 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic int goldfish_pipe_cmd(struct goldfish_pipe *pipe, enum PipeCmdCode cmd) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci int status; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&pipe->lock)) 2368c2ecf20Sopenharmony_ci return PIPE_ERROR_IO; 2378c2ecf20Sopenharmony_ci status = goldfish_pipe_cmd_locked(pipe, cmd); 2388c2ecf20Sopenharmony_ci mutex_unlock(&pipe->lock); 2398c2ecf20Sopenharmony_ci return status; 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci/* 2438c2ecf20Sopenharmony_ci * This function converts an error code returned by the emulator through 2448c2ecf20Sopenharmony_ci * the PIPE_REG_STATUS i/o register into a valid negative errno value. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_cistatic int goldfish_pipe_error_convert(int status) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci switch (status) { 2498c2ecf20Sopenharmony_ci case PIPE_ERROR_AGAIN: 2508c2ecf20Sopenharmony_ci return -EAGAIN; 2518c2ecf20Sopenharmony_ci case PIPE_ERROR_NOMEM: 2528c2ecf20Sopenharmony_ci return -ENOMEM; 2538c2ecf20Sopenharmony_ci case PIPE_ERROR_IO: 2548c2ecf20Sopenharmony_ci return -EIO; 2558c2ecf20Sopenharmony_ci default: 2568c2ecf20Sopenharmony_ci return -EINVAL; 2578c2ecf20Sopenharmony_ci } 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int goldfish_pin_pages(unsigned long first_page, 2618c2ecf20Sopenharmony_ci unsigned long last_page, 2628c2ecf20Sopenharmony_ci unsigned int last_page_size, 2638c2ecf20Sopenharmony_ci int is_write, 2648c2ecf20Sopenharmony_ci struct page *pages[MAX_BUFFERS_PER_COMMAND], 2658c2ecf20Sopenharmony_ci unsigned int *iter_last_page_size) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci int ret; 2688c2ecf20Sopenharmony_ci int requested_pages = ((last_page - first_page) >> PAGE_SHIFT) + 1; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (requested_pages > MAX_BUFFERS_PER_COMMAND) { 2718c2ecf20Sopenharmony_ci requested_pages = MAX_BUFFERS_PER_COMMAND; 2728c2ecf20Sopenharmony_ci *iter_last_page_size = PAGE_SIZE; 2738c2ecf20Sopenharmony_ci } else { 2748c2ecf20Sopenharmony_ci *iter_last_page_size = last_page_size; 2758c2ecf20Sopenharmony_ci } 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci ret = pin_user_pages_fast(first_page, requested_pages, 2788c2ecf20Sopenharmony_ci !is_write ? FOLL_WRITE : 0, 2798c2ecf20Sopenharmony_ci pages); 2808c2ecf20Sopenharmony_ci if (ret <= 0) 2818c2ecf20Sopenharmony_ci return -EFAULT; 2828c2ecf20Sopenharmony_ci if (ret < requested_pages) 2838c2ecf20Sopenharmony_ci *iter_last_page_size = PAGE_SIZE; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci return ret; 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci/* Populate the call parameters, merging adjacent pages together */ 2898c2ecf20Sopenharmony_cistatic void populate_rw_params(struct page **pages, 2908c2ecf20Sopenharmony_ci int pages_count, 2918c2ecf20Sopenharmony_ci unsigned long address, 2928c2ecf20Sopenharmony_ci unsigned long address_end, 2938c2ecf20Sopenharmony_ci unsigned long first_page, 2948c2ecf20Sopenharmony_ci unsigned long last_page, 2958c2ecf20Sopenharmony_ci unsigned int iter_last_page_size, 2968c2ecf20Sopenharmony_ci int is_write, 2978c2ecf20Sopenharmony_ci struct goldfish_pipe_command *command) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci /* 3008c2ecf20Sopenharmony_ci * Process the first page separately - it's the only page that 3018c2ecf20Sopenharmony_ci * needs special handling for its start address. 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_ci unsigned long xaddr = page_to_phys(pages[0]); 3048c2ecf20Sopenharmony_ci unsigned long xaddr_prev = xaddr; 3058c2ecf20Sopenharmony_ci int buffer_idx = 0; 3068c2ecf20Sopenharmony_ci int i = 1; 3078c2ecf20Sopenharmony_ci int size_on_page = first_page == last_page 3088c2ecf20Sopenharmony_ci ? (int)(address_end - address) 3098c2ecf20Sopenharmony_ci : (PAGE_SIZE - (address & ~PAGE_MASK)); 3108c2ecf20Sopenharmony_ci command->rw_params.ptrs[0] = (u64)(xaddr | (address & ~PAGE_MASK)); 3118c2ecf20Sopenharmony_ci command->rw_params.sizes[0] = size_on_page; 3128c2ecf20Sopenharmony_ci for (; i < pages_count; ++i) { 3138c2ecf20Sopenharmony_ci xaddr = page_to_phys(pages[i]); 3148c2ecf20Sopenharmony_ci size_on_page = (i == pages_count - 1) ? 3158c2ecf20Sopenharmony_ci iter_last_page_size : PAGE_SIZE; 3168c2ecf20Sopenharmony_ci if (xaddr == xaddr_prev + PAGE_SIZE) { 3178c2ecf20Sopenharmony_ci command->rw_params.sizes[buffer_idx] += size_on_page; 3188c2ecf20Sopenharmony_ci } else { 3198c2ecf20Sopenharmony_ci ++buffer_idx; 3208c2ecf20Sopenharmony_ci command->rw_params.ptrs[buffer_idx] = (u64)xaddr; 3218c2ecf20Sopenharmony_ci command->rw_params.sizes[buffer_idx] = size_on_page; 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci xaddr_prev = xaddr; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci command->rw_params.buffers_count = buffer_idx + 1; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic int transfer_max_buffers(struct goldfish_pipe *pipe, 3298c2ecf20Sopenharmony_ci unsigned long address, 3308c2ecf20Sopenharmony_ci unsigned long address_end, 3318c2ecf20Sopenharmony_ci int is_write, 3328c2ecf20Sopenharmony_ci unsigned long last_page, 3338c2ecf20Sopenharmony_ci unsigned int last_page_size, 3348c2ecf20Sopenharmony_ci s32 *consumed_size, 3358c2ecf20Sopenharmony_ci int *status) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci unsigned long first_page = address & PAGE_MASK; 3388c2ecf20Sopenharmony_ci unsigned int iter_last_page_size; 3398c2ecf20Sopenharmony_ci int pages_count; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* Serialize access to the pipe command buffers */ 3428c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&pipe->lock)) 3438c2ecf20Sopenharmony_ci return -ERESTARTSYS; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci pages_count = goldfish_pin_pages(first_page, last_page, 3468c2ecf20Sopenharmony_ci last_page_size, is_write, 3478c2ecf20Sopenharmony_ci pipe->pages, &iter_last_page_size); 3488c2ecf20Sopenharmony_ci if (pages_count < 0) { 3498c2ecf20Sopenharmony_ci mutex_unlock(&pipe->lock); 3508c2ecf20Sopenharmony_ci return pages_count; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci populate_rw_params(pipe->pages, pages_count, address, address_end, 3548c2ecf20Sopenharmony_ci first_page, last_page, iter_last_page_size, is_write, 3558c2ecf20Sopenharmony_ci pipe->command_buffer); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci /* Transfer the data */ 3588c2ecf20Sopenharmony_ci *status = goldfish_pipe_cmd_locked(pipe, 3598c2ecf20Sopenharmony_ci is_write ? PIPE_CMD_WRITE : PIPE_CMD_READ); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci *consumed_size = pipe->command_buffer->rw_params.consumed_size; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci unpin_user_pages_dirty_lock(pipe->pages, pages_count, 3648c2ecf20Sopenharmony_ci !is_write && *consumed_size > 0); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci mutex_unlock(&pipe->lock); 3678c2ecf20Sopenharmony_ci return 0; 3688c2ecf20Sopenharmony_ci} 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_cistatic int wait_for_host_signal(struct goldfish_pipe *pipe, int is_write) 3718c2ecf20Sopenharmony_ci{ 3728c2ecf20Sopenharmony_ci u32 wake_bit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci set_bit(wake_bit, &pipe->flags); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* Tell the emulator we're going to wait for a wake event */ 3778c2ecf20Sopenharmony_ci goldfish_pipe_cmd(pipe, 3788c2ecf20Sopenharmony_ci is_write ? PIPE_CMD_WAKE_ON_WRITE : PIPE_CMD_WAKE_ON_READ); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci while (test_bit(wake_bit, &pipe->flags)) { 3818c2ecf20Sopenharmony_ci if (wait_event_interruptible(pipe->wake_queue, 3828c2ecf20Sopenharmony_ci !test_bit(wake_bit, &pipe->flags))) 3838c2ecf20Sopenharmony_ci return -ERESTARTSYS; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 3868c2ecf20Sopenharmony_ci return -EIO; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci return 0; 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic ssize_t goldfish_pipe_read_write(struct file *filp, 3938c2ecf20Sopenharmony_ci char __user *buffer, 3948c2ecf20Sopenharmony_ci size_t bufflen, 3958c2ecf20Sopenharmony_ci int is_write) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe = filp->private_data; 3988c2ecf20Sopenharmony_ci int count = 0, ret = -EINVAL; 3998c2ecf20Sopenharmony_ci unsigned long address, address_end, last_page; 4008c2ecf20Sopenharmony_ci unsigned int last_page_size; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* If the emulator already closed the pipe, no need to go further */ 4038c2ecf20Sopenharmony_ci if (unlikely(test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))) 4048c2ecf20Sopenharmony_ci return -EIO; 4058c2ecf20Sopenharmony_ci /* Null reads or writes succeeds */ 4068c2ecf20Sopenharmony_ci if (unlikely(bufflen == 0)) 4078c2ecf20Sopenharmony_ci return 0; 4088c2ecf20Sopenharmony_ci /* Check the buffer range for access */ 4098c2ecf20Sopenharmony_ci if (unlikely(!access_ok(buffer, bufflen))) 4108c2ecf20Sopenharmony_ci return -EFAULT; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci address = (unsigned long)buffer; 4138c2ecf20Sopenharmony_ci address_end = address + bufflen; 4148c2ecf20Sopenharmony_ci last_page = (address_end - 1) & PAGE_MASK; 4158c2ecf20Sopenharmony_ci last_page_size = ((address_end - 1) & ~PAGE_MASK) + 1; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci while (address < address_end) { 4188c2ecf20Sopenharmony_ci s32 consumed_size; 4198c2ecf20Sopenharmony_ci int status; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci ret = transfer_max_buffers(pipe, address, address_end, is_write, 4228c2ecf20Sopenharmony_ci last_page, last_page_size, 4238c2ecf20Sopenharmony_ci &consumed_size, &status); 4248c2ecf20Sopenharmony_ci if (ret < 0) 4258c2ecf20Sopenharmony_ci break; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci if (consumed_size > 0) { 4288c2ecf20Sopenharmony_ci /* No matter what's the status, we've transferred 4298c2ecf20Sopenharmony_ci * something. 4308c2ecf20Sopenharmony_ci */ 4318c2ecf20Sopenharmony_ci count += consumed_size; 4328c2ecf20Sopenharmony_ci address += consumed_size; 4338c2ecf20Sopenharmony_ci } 4348c2ecf20Sopenharmony_ci if (status > 0) 4358c2ecf20Sopenharmony_ci continue; 4368c2ecf20Sopenharmony_ci if (status == 0) { 4378c2ecf20Sopenharmony_ci /* EOF */ 4388c2ecf20Sopenharmony_ci ret = 0; 4398c2ecf20Sopenharmony_ci break; 4408c2ecf20Sopenharmony_ci } 4418c2ecf20Sopenharmony_ci if (count > 0) { 4428c2ecf20Sopenharmony_ci /* 4438c2ecf20Sopenharmony_ci * An error occurred, but we already transferred 4448c2ecf20Sopenharmony_ci * something on one of the previous iterations. 4458c2ecf20Sopenharmony_ci * Just return what we already copied and log this 4468c2ecf20Sopenharmony_ci * err. 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_ci if (status != PIPE_ERROR_AGAIN) 4498c2ecf20Sopenharmony_ci dev_err_ratelimited(pipe->dev->pdev_dev, 4508c2ecf20Sopenharmony_ci "backend error %d on %s\n", 4518c2ecf20Sopenharmony_ci status, is_write ? "write" : "read"); 4528c2ecf20Sopenharmony_ci break; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci /* 4568c2ecf20Sopenharmony_ci * If the error is not PIPE_ERROR_AGAIN, or if we are in 4578c2ecf20Sopenharmony_ci * non-blocking mode, just return the error code. 4588c2ecf20Sopenharmony_ci */ 4598c2ecf20Sopenharmony_ci if (status != PIPE_ERROR_AGAIN || 4608c2ecf20Sopenharmony_ci (filp->f_flags & O_NONBLOCK) != 0) { 4618c2ecf20Sopenharmony_ci ret = goldfish_pipe_error_convert(status); 4628c2ecf20Sopenharmony_ci break; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci status = wait_for_host_signal(pipe, is_write); 4668c2ecf20Sopenharmony_ci if (status < 0) 4678c2ecf20Sopenharmony_ci return status; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci if (count > 0) 4718c2ecf20Sopenharmony_ci return count; 4728c2ecf20Sopenharmony_ci return ret; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, 4768c2ecf20Sopenharmony_ci size_t bufflen, loff_t *ppos) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci return goldfish_pipe_read_write(filp, buffer, bufflen, 4798c2ecf20Sopenharmony_ci /* is_write */ 0); 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_cistatic ssize_t goldfish_pipe_write(struct file *filp, 4838c2ecf20Sopenharmony_ci const char __user *buffer, size_t bufflen, 4848c2ecf20Sopenharmony_ci loff_t *ppos) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci /* cast away the const */ 4878c2ecf20Sopenharmony_ci char __user *no_const_buffer = (char __user *)buffer; 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci return goldfish_pipe_read_write(filp, no_const_buffer, bufflen, 4908c2ecf20Sopenharmony_ci /* is_write */ 1); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic __poll_t goldfish_pipe_poll(struct file *filp, poll_table *wait) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe = filp->private_data; 4968c2ecf20Sopenharmony_ci __poll_t mask = 0; 4978c2ecf20Sopenharmony_ci int status; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci poll_wait(filp, &pipe->wake_queue, wait); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci status = goldfish_pipe_cmd(pipe, PIPE_CMD_POLL); 5028c2ecf20Sopenharmony_ci if (status < 0) 5038c2ecf20Sopenharmony_ci return -ERESTARTSYS; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (status & PIPE_POLL_IN) 5068c2ecf20Sopenharmony_ci mask |= EPOLLIN | EPOLLRDNORM; 5078c2ecf20Sopenharmony_ci if (status & PIPE_POLL_OUT) 5088c2ecf20Sopenharmony_ci mask |= EPOLLOUT | EPOLLWRNORM; 5098c2ecf20Sopenharmony_ci if (status & PIPE_POLL_HUP) 5108c2ecf20Sopenharmony_ci mask |= EPOLLHUP; 5118c2ecf20Sopenharmony_ci if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 5128c2ecf20Sopenharmony_ci mask |= EPOLLERR; 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci return mask; 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_cistatic void signalled_pipes_add_locked(struct goldfish_pipe_dev *dev, 5188c2ecf20Sopenharmony_ci u32 id, u32 flags) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci if (WARN_ON(id >= dev->pipes_capacity)) 5238c2ecf20Sopenharmony_ci return; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci pipe = dev->pipes[id]; 5268c2ecf20Sopenharmony_ci if (!pipe) 5278c2ecf20Sopenharmony_ci return; 5288c2ecf20Sopenharmony_ci pipe->signalled_flags |= flags; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci if (pipe->prev_signalled || pipe->next_signalled || 5318c2ecf20Sopenharmony_ci dev->first_signalled_pipe == pipe) 5328c2ecf20Sopenharmony_ci return; /* already in the list */ 5338c2ecf20Sopenharmony_ci pipe->next_signalled = dev->first_signalled_pipe; 5348c2ecf20Sopenharmony_ci if (dev->first_signalled_pipe) 5358c2ecf20Sopenharmony_ci dev->first_signalled_pipe->prev_signalled = pipe; 5368c2ecf20Sopenharmony_ci dev->first_signalled_pipe = pipe; 5378c2ecf20Sopenharmony_ci} 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_cistatic void signalled_pipes_remove_locked(struct goldfish_pipe_dev *dev, 5408c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci if (pipe->prev_signalled) 5438c2ecf20Sopenharmony_ci pipe->prev_signalled->next_signalled = pipe->next_signalled; 5448c2ecf20Sopenharmony_ci if (pipe->next_signalled) 5458c2ecf20Sopenharmony_ci pipe->next_signalled->prev_signalled = pipe->prev_signalled; 5468c2ecf20Sopenharmony_ci if (pipe == dev->first_signalled_pipe) 5478c2ecf20Sopenharmony_ci dev->first_signalled_pipe = pipe->next_signalled; 5488c2ecf20Sopenharmony_ci pipe->prev_signalled = NULL; 5498c2ecf20Sopenharmony_ci pipe->next_signalled = NULL; 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_cistatic struct goldfish_pipe *signalled_pipes_pop_front( 5538c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev, int *wakes) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe; 5568c2ecf20Sopenharmony_ci unsigned long flags; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci pipe = dev->first_signalled_pipe; 5618c2ecf20Sopenharmony_ci if (pipe) { 5628c2ecf20Sopenharmony_ci *wakes = pipe->signalled_flags; 5638c2ecf20Sopenharmony_ci pipe->signalled_flags = 0; 5648c2ecf20Sopenharmony_ci /* 5658c2ecf20Sopenharmony_ci * This is an optimized version of 5668c2ecf20Sopenharmony_ci * signalled_pipes_remove_locked() 5678c2ecf20Sopenharmony_ci * - We want to make it as fast as possible to 5688c2ecf20Sopenharmony_ci * wake the sleeping pipe operations faster. 5698c2ecf20Sopenharmony_ci */ 5708c2ecf20Sopenharmony_ci dev->first_signalled_pipe = pipe->next_signalled; 5718c2ecf20Sopenharmony_ci if (dev->first_signalled_pipe) 5728c2ecf20Sopenharmony_ci dev->first_signalled_pipe->prev_signalled = NULL; 5738c2ecf20Sopenharmony_ci pipe->next_signalled = NULL; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 5778c2ecf20Sopenharmony_ci return pipe; 5788c2ecf20Sopenharmony_ci} 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_cistatic void goldfish_interrupt_task(unsigned long dev_addr) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci /* Iterate over the signalled pipes and wake them one by one */ 5838c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev = (struct goldfish_pipe_dev *)dev_addr; 5848c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe; 5858c2ecf20Sopenharmony_ci int wakes; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci while ((pipe = signalled_pipes_pop_front(dev, &wakes)) != NULL) { 5888c2ecf20Sopenharmony_ci if (wakes & PIPE_WAKE_CLOSED) { 5898c2ecf20Sopenharmony_ci pipe->flags = 1 << BIT_CLOSED_ON_HOST; 5908c2ecf20Sopenharmony_ci } else { 5918c2ecf20Sopenharmony_ci if (wakes & PIPE_WAKE_READ) 5928c2ecf20Sopenharmony_ci clear_bit(BIT_WAKE_ON_READ, &pipe->flags); 5938c2ecf20Sopenharmony_ci if (wakes & PIPE_WAKE_WRITE) 5948c2ecf20Sopenharmony_ci clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); 5958c2ecf20Sopenharmony_ci } 5968c2ecf20Sopenharmony_ci /* 5978c2ecf20Sopenharmony_ci * wake_up_interruptible() implies a write barrier, so don't 5988c2ecf20Sopenharmony_ci * explicitly add another one here. 5998c2ecf20Sopenharmony_ci */ 6008c2ecf20Sopenharmony_ci wake_up_interruptible(&pipe->wake_queue); 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic void goldfish_pipe_device_deinit(struct platform_device *pdev, 6058c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci/* 6088c2ecf20Sopenharmony_ci * The general idea of the interrupt handling: 6098c2ecf20Sopenharmony_ci * 6108c2ecf20Sopenharmony_ci * 1. device raises an interrupt if there's at least one signalled pipe 6118c2ecf20Sopenharmony_ci * 2. IRQ handler reads the signalled pipes and their count from the device 6128c2ecf20Sopenharmony_ci * 3. device writes them into a shared buffer and returns the count 6138c2ecf20Sopenharmony_ci * it only resets the IRQ if it has returned all signalled pipes, 6148c2ecf20Sopenharmony_ci * otherwise it leaves it raised, so IRQ handler will be called 6158c2ecf20Sopenharmony_ci * again for the next chunk 6168c2ecf20Sopenharmony_ci * 4. IRQ handler adds all returned pipes to the device's signalled pipes list 6178c2ecf20Sopenharmony_ci * 5. IRQ handler launches a tasklet to process the signalled pipes from the 6188c2ecf20Sopenharmony_ci * list in a separate context 6198c2ecf20Sopenharmony_ci */ 6208c2ecf20Sopenharmony_cistatic irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci u32 count; 6238c2ecf20Sopenharmony_ci u32 i; 6248c2ecf20Sopenharmony_ci unsigned long flags; 6258c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev = dev_id; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci if (dev->magic != &goldfish_pipe_device_deinit) 6288c2ecf20Sopenharmony_ci return IRQ_NONE; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci /* Request the signalled pipes from the device */ 6318c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci count = readl(dev->base + PIPE_REG_GET_SIGNALLED); 6348c2ecf20Sopenharmony_ci if (count == 0) { 6358c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 6368c2ecf20Sopenharmony_ci return IRQ_NONE; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci if (count > MAX_SIGNALLED_PIPES) 6398c2ecf20Sopenharmony_ci count = MAX_SIGNALLED_PIPES; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci for (i = 0; i < count; ++i) 6428c2ecf20Sopenharmony_ci signalled_pipes_add_locked(dev, 6438c2ecf20Sopenharmony_ci dev->buffers->signalled_pipe_buffers[i].id, 6448c2ecf20Sopenharmony_ci dev->buffers->signalled_pipe_buffers[i].flags); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci tasklet_schedule(&dev->irq_tasklet); 6498c2ecf20Sopenharmony_ci return IRQ_HANDLED; 6508c2ecf20Sopenharmony_ci} 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_cistatic int get_free_pipe_id_locked(struct goldfish_pipe_dev *dev) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci int id; 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci for (id = 0; id < dev->pipes_capacity; ++id) 6578c2ecf20Sopenharmony_ci if (!dev->pipes[id]) 6588c2ecf20Sopenharmony_ci return id; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci { 6618c2ecf20Sopenharmony_ci /* Reallocate the array. 6628c2ecf20Sopenharmony_ci * Since get_free_pipe_id_locked runs with interrupts disabled, 6638c2ecf20Sopenharmony_ci * we don't want to make calls that could lead to sleep. 6648c2ecf20Sopenharmony_ci */ 6658c2ecf20Sopenharmony_ci u32 new_capacity = 2 * dev->pipes_capacity; 6668c2ecf20Sopenharmony_ci struct goldfish_pipe **pipes = 6678c2ecf20Sopenharmony_ci kcalloc(new_capacity, sizeof(*pipes), GFP_ATOMIC); 6688c2ecf20Sopenharmony_ci if (!pipes) 6698c2ecf20Sopenharmony_ci return -ENOMEM; 6708c2ecf20Sopenharmony_ci memcpy(pipes, dev->pipes, sizeof(*pipes) * dev->pipes_capacity); 6718c2ecf20Sopenharmony_ci kfree(dev->pipes); 6728c2ecf20Sopenharmony_ci dev->pipes = pipes; 6738c2ecf20Sopenharmony_ci id = dev->pipes_capacity; 6748c2ecf20Sopenharmony_ci dev->pipes_capacity = new_capacity; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci return id; 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci/* A helper function to get the instance of goldfish_pipe_dev from file */ 6808c2ecf20Sopenharmony_cistatic struct goldfish_pipe_dev *to_goldfish_pipe_dev(struct file *file) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci struct miscdevice *miscdev = file->private_data; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci return container_of(miscdev, struct goldfish_pipe_dev, miscdev); 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_ci/** 6888c2ecf20Sopenharmony_ci * goldfish_pipe_open - open a channel to the AVD 6898c2ecf20Sopenharmony_ci * @inode: inode of device 6908c2ecf20Sopenharmony_ci * @file: file struct of opener 6918c2ecf20Sopenharmony_ci * 6928c2ecf20Sopenharmony_ci * Create a new pipe link between the emulator and the use application. 6938c2ecf20Sopenharmony_ci * Each new request produces a new pipe. 6948c2ecf20Sopenharmony_ci * 6958c2ecf20Sopenharmony_ci * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit 6968c2ecf20Sopenharmony_ci * right now so this is fine. A move to 64bit will need this addressing 6978c2ecf20Sopenharmony_ci */ 6988c2ecf20Sopenharmony_cistatic int goldfish_pipe_open(struct inode *inode, struct file *file) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev = to_goldfish_pipe_dev(file); 7018c2ecf20Sopenharmony_ci unsigned long flags; 7028c2ecf20Sopenharmony_ci int id; 7038c2ecf20Sopenharmony_ci int status; 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci /* Allocate new pipe kernel object */ 7068c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (!pipe) 7098c2ecf20Sopenharmony_ci return -ENOMEM; 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci pipe->dev = dev; 7128c2ecf20Sopenharmony_ci mutex_init(&pipe->lock); 7138c2ecf20Sopenharmony_ci init_waitqueue_head(&pipe->wake_queue); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* 7168c2ecf20Sopenharmony_ci * Command buffer needs to be allocated on its own page to make sure 7178c2ecf20Sopenharmony_ci * it is physically contiguous in host's address space. 7188c2ecf20Sopenharmony_ci */ 7198c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct goldfish_pipe_command) > PAGE_SIZE); 7208c2ecf20Sopenharmony_ci pipe->command_buffer = 7218c2ecf20Sopenharmony_ci (struct goldfish_pipe_command *)__get_free_page(GFP_KERNEL); 7228c2ecf20Sopenharmony_ci if (!pipe->command_buffer) { 7238c2ecf20Sopenharmony_ci status = -ENOMEM; 7248c2ecf20Sopenharmony_ci goto err_pipe; 7258c2ecf20Sopenharmony_ci } 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci id = get_free_pipe_id_locked(dev); 7308c2ecf20Sopenharmony_ci if (id < 0) { 7318c2ecf20Sopenharmony_ci status = id; 7328c2ecf20Sopenharmony_ci goto err_id_locked; 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci dev->pipes[id] = pipe; 7368c2ecf20Sopenharmony_ci pipe->id = id; 7378c2ecf20Sopenharmony_ci pipe->command_buffer->id = id; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* Now tell the emulator we're opening a new pipe. */ 7408c2ecf20Sopenharmony_ci dev->buffers->open_command_params.rw_params_max_count = 7418c2ecf20Sopenharmony_ci MAX_BUFFERS_PER_COMMAND; 7428c2ecf20Sopenharmony_ci dev->buffers->open_command_params.command_buffer_ptr = 7438c2ecf20Sopenharmony_ci (u64)(unsigned long)__pa(pipe->command_buffer); 7448c2ecf20Sopenharmony_ci status = goldfish_pipe_cmd_locked(pipe, PIPE_CMD_OPEN); 7458c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 7468c2ecf20Sopenharmony_ci if (status < 0) 7478c2ecf20Sopenharmony_ci goto err_cmd; 7488c2ecf20Sopenharmony_ci /* All is done, save the pipe into the file's private data field */ 7498c2ecf20Sopenharmony_ci file->private_data = pipe; 7508c2ecf20Sopenharmony_ci return 0; 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cierr_cmd: 7538c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 7548c2ecf20Sopenharmony_ci dev->pipes[id] = NULL; 7558c2ecf20Sopenharmony_cierr_id_locked: 7568c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 7578c2ecf20Sopenharmony_ci free_page((unsigned long)pipe->command_buffer); 7588c2ecf20Sopenharmony_cierr_pipe: 7598c2ecf20Sopenharmony_ci kfree(pipe); 7608c2ecf20Sopenharmony_ci return status; 7618c2ecf20Sopenharmony_ci} 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_cistatic int goldfish_pipe_release(struct inode *inode, struct file *filp) 7648c2ecf20Sopenharmony_ci{ 7658c2ecf20Sopenharmony_ci unsigned long flags; 7668c2ecf20Sopenharmony_ci struct goldfish_pipe *pipe = filp->private_data; 7678c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev = pipe->dev; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* The guest is closing the channel, so tell the emulator right now */ 7708c2ecf20Sopenharmony_ci goldfish_pipe_cmd(pipe, PIPE_CMD_CLOSE); 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci spin_lock_irqsave(&dev->lock, flags); 7738c2ecf20Sopenharmony_ci dev->pipes[pipe->id] = NULL; 7748c2ecf20Sopenharmony_ci signalled_pipes_remove_locked(dev, pipe); 7758c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&dev->lock, flags); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci filp->private_data = NULL; 7788c2ecf20Sopenharmony_ci free_page((unsigned long)pipe->command_buffer); 7798c2ecf20Sopenharmony_ci kfree(pipe); 7808c2ecf20Sopenharmony_ci return 0; 7818c2ecf20Sopenharmony_ci} 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_cistatic const struct file_operations goldfish_pipe_fops = { 7848c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 7858c2ecf20Sopenharmony_ci .read = goldfish_pipe_read, 7868c2ecf20Sopenharmony_ci .write = goldfish_pipe_write, 7878c2ecf20Sopenharmony_ci .poll = goldfish_pipe_poll, 7888c2ecf20Sopenharmony_ci .open = goldfish_pipe_open, 7898c2ecf20Sopenharmony_ci .release = goldfish_pipe_release, 7908c2ecf20Sopenharmony_ci}; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_cistatic void init_miscdevice(struct miscdevice *miscdev) 7938c2ecf20Sopenharmony_ci{ 7948c2ecf20Sopenharmony_ci memset(miscdev, 0, sizeof(*miscdev)); 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci miscdev->minor = MISC_DYNAMIC_MINOR; 7978c2ecf20Sopenharmony_ci miscdev->name = "goldfish_pipe"; 7988c2ecf20Sopenharmony_ci miscdev->fops = &goldfish_pipe_fops; 7998c2ecf20Sopenharmony_ci} 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cistatic void write_pa_addr(void *addr, void __iomem *portl, void __iomem *porth) 8028c2ecf20Sopenharmony_ci{ 8038c2ecf20Sopenharmony_ci const unsigned long paddr = __pa(addr); 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci writel(upper_32_bits(paddr), porth); 8068c2ecf20Sopenharmony_ci writel(lower_32_bits(paddr), portl); 8078c2ecf20Sopenharmony_ci} 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_cistatic int goldfish_pipe_device_init(struct platform_device *pdev, 8108c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev) 8118c2ecf20Sopenharmony_ci{ 8128c2ecf20Sopenharmony_ci int err; 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci tasklet_init(&dev->irq_tasklet, &goldfish_interrupt_task, 8158c2ecf20Sopenharmony_ci (unsigned long)dev); 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci err = devm_request_irq(&pdev->dev, dev->irq, 8188c2ecf20Sopenharmony_ci goldfish_pipe_interrupt, 8198c2ecf20Sopenharmony_ci IRQF_SHARED, "goldfish_pipe", dev); 8208c2ecf20Sopenharmony_ci if (err) { 8218c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "unable to allocate IRQ for v2\n"); 8228c2ecf20Sopenharmony_ci return err; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci init_miscdevice(&dev->miscdev); 8268c2ecf20Sopenharmony_ci err = misc_register(&dev->miscdev); 8278c2ecf20Sopenharmony_ci if (err) { 8288c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "unable to register v2 device\n"); 8298c2ecf20Sopenharmony_ci return err; 8308c2ecf20Sopenharmony_ci } 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci dev->pdev_dev = &pdev->dev; 8338c2ecf20Sopenharmony_ci dev->first_signalled_pipe = NULL; 8348c2ecf20Sopenharmony_ci dev->pipes_capacity = INITIAL_PIPES_CAPACITY; 8358c2ecf20Sopenharmony_ci dev->pipes = kcalloc(dev->pipes_capacity, sizeof(*dev->pipes), 8368c2ecf20Sopenharmony_ci GFP_KERNEL); 8378c2ecf20Sopenharmony_ci if (!dev->pipes) { 8388c2ecf20Sopenharmony_ci misc_deregister(&dev->miscdev); 8398c2ecf20Sopenharmony_ci return -ENOMEM; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci /* 8438c2ecf20Sopenharmony_ci * We're going to pass two buffers, open_command_params and 8448c2ecf20Sopenharmony_ci * signalled_pipe_buffers, to the host. This means each of those buffers 8458c2ecf20Sopenharmony_ci * needs to be contained in a single physical page. The easiest choice 8468c2ecf20Sopenharmony_ci * is to just allocate a page and place the buffers in it. 8478c2ecf20Sopenharmony_ci */ 8488c2ecf20Sopenharmony_ci BUILD_BUG_ON(sizeof(struct goldfish_pipe_dev_buffers) > PAGE_SIZE); 8498c2ecf20Sopenharmony_ci dev->buffers = (struct goldfish_pipe_dev_buffers *) 8508c2ecf20Sopenharmony_ci __get_free_page(GFP_KERNEL); 8518c2ecf20Sopenharmony_ci if (!dev->buffers) { 8528c2ecf20Sopenharmony_ci kfree(dev->pipes); 8538c2ecf20Sopenharmony_ci misc_deregister(&dev->miscdev); 8548c2ecf20Sopenharmony_ci return -ENOMEM; 8558c2ecf20Sopenharmony_ci } 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci /* Send the buffer addresses to the host */ 8588c2ecf20Sopenharmony_ci write_pa_addr(&dev->buffers->signalled_pipe_buffers, 8598c2ecf20Sopenharmony_ci dev->base + PIPE_REG_SIGNAL_BUFFER, 8608c2ecf20Sopenharmony_ci dev->base + PIPE_REG_SIGNAL_BUFFER_HIGH); 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci writel(MAX_SIGNALLED_PIPES, 8638c2ecf20Sopenharmony_ci dev->base + PIPE_REG_SIGNAL_BUFFER_COUNT); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci write_pa_addr(&dev->buffers->open_command_params, 8668c2ecf20Sopenharmony_ci dev->base + PIPE_REG_OPEN_BUFFER, 8678c2ecf20Sopenharmony_ci dev->base + PIPE_REG_OPEN_BUFFER_HIGH); 8688c2ecf20Sopenharmony_ci 8698c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, dev); 8708c2ecf20Sopenharmony_ci return 0; 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_cistatic void goldfish_pipe_device_deinit(struct platform_device *pdev, 8748c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev) 8758c2ecf20Sopenharmony_ci{ 8768c2ecf20Sopenharmony_ci misc_deregister(&dev->miscdev); 8778c2ecf20Sopenharmony_ci tasklet_kill(&dev->irq_tasklet); 8788c2ecf20Sopenharmony_ci kfree(dev->pipes); 8798c2ecf20Sopenharmony_ci free_page((unsigned long)dev->buffers); 8808c2ecf20Sopenharmony_ci} 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_cistatic int goldfish_pipe_probe(struct platform_device *pdev) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci struct resource *r; 8858c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); 8888c2ecf20Sopenharmony_ci if (!dev) 8898c2ecf20Sopenharmony_ci return -ENOMEM; 8908c2ecf20Sopenharmony_ci 8918c2ecf20Sopenharmony_ci dev->magic = &goldfish_pipe_device_deinit; 8928c2ecf20Sopenharmony_ci spin_lock_init(&dev->lock); 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8958c2ecf20Sopenharmony_ci if (!r || resource_size(r) < PAGE_SIZE) { 8968c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "can't allocate i/o page\n"); 8978c2ecf20Sopenharmony_ci return -EINVAL; 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); 9008c2ecf20Sopenharmony_ci if (!dev->base) { 9018c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "ioremap failed\n"); 9028c2ecf20Sopenharmony_ci return -EINVAL; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci 9058c2ecf20Sopenharmony_ci r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 9068c2ecf20Sopenharmony_ci if (!r) 9078c2ecf20Sopenharmony_ci return -EINVAL; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci dev->irq = r->start; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci /* 9128c2ecf20Sopenharmony_ci * Exchange the versions with the host device 9138c2ecf20Sopenharmony_ci * 9148c2ecf20Sopenharmony_ci * Note: v1 driver used to not report its version, so we write it before 9158c2ecf20Sopenharmony_ci * reading device version back: this allows the host implementation to 9168c2ecf20Sopenharmony_ci * detect the old driver (if there was no version write before read). 9178c2ecf20Sopenharmony_ci */ 9188c2ecf20Sopenharmony_ci writel(PIPE_DRIVER_VERSION, dev->base + PIPE_REG_VERSION); 9198c2ecf20Sopenharmony_ci dev->version = readl(dev->base + PIPE_REG_VERSION); 9208c2ecf20Sopenharmony_ci if (WARN_ON(dev->version < PIPE_CURRENT_DEVICE_VERSION)) 9218c2ecf20Sopenharmony_ci return -EINVAL; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci return goldfish_pipe_device_init(pdev, dev); 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cistatic int goldfish_pipe_remove(struct platform_device *pdev) 9278c2ecf20Sopenharmony_ci{ 9288c2ecf20Sopenharmony_ci struct goldfish_pipe_dev *dev = platform_get_drvdata(pdev); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci goldfish_pipe_device_deinit(pdev, dev); 9318c2ecf20Sopenharmony_ci return 0; 9328c2ecf20Sopenharmony_ci} 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_cistatic const struct acpi_device_id goldfish_pipe_acpi_match[] = { 9358c2ecf20Sopenharmony_ci { "GFSH0003", 0 }, 9368c2ecf20Sopenharmony_ci { }, 9378c2ecf20Sopenharmony_ci}; 9388c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic const struct of_device_id goldfish_pipe_of_match[] = { 9418c2ecf20Sopenharmony_ci { .compatible = "google,android-pipe", }, 9428c2ecf20Sopenharmony_ci {}, 9438c2ecf20Sopenharmony_ci}; 9448c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_cistatic struct platform_driver goldfish_pipe_driver = { 9478c2ecf20Sopenharmony_ci .probe = goldfish_pipe_probe, 9488c2ecf20Sopenharmony_ci .remove = goldfish_pipe_remove, 9498c2ecf20Sopenharmony_ci .driver = { 9508c2ecf20Sopenharmony_ci .name = "goldfish_pipe", 9518c2ecf20Sopenharmony_ci .of_match_table = goldfish_pipe_of_match, 9528c2ecf20Sopenharmony_ci .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), 9538c2ecf20Sopenharmony_ci } 9548c2ecf20Sopenharmony_ci}; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_cimodule_platform_driver(goldfish_pipe_driver); 9578c2ecf20Sopenharmony_ciMODULE_AUTHOR("David Turner <digit@google.com>"); 9588c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 959