1c89f2750SDavid 'Digit' Turner /* 2c89f2750SDavid 'Digit' Turner * Copyright (C) 2011 Google, Inc. 3c89f2750SDavid 'Digit' Turner * Copyright (C) 2012 Intel, Inc. 4c89f2750SDavid 'Digit' Turner * Copyright (C) 2013 Intel, Inc. 52f3be882SChristoffer Dall * Copyright (C) 2014 Linaro Limited 6c89f2750SDavid 'Digit' Turner * 7c89f2750SDavid 'Digit' Turner * This software is licensed under the terms of the GNU General Public 8c89f2750SDavid 'Digit' Turner * License version 2, as published by the Free Software Foundation, and 9c89f2750SDavid 'Digit' Turner * may be copied, distributed, and modified under those terms. 10c89f2750SDavid 'Digit' Turner * 11c89f2750SDavid 'Digit' Turner * This program is distributed in the hope that it will be useful, 12c89f2750SDavid 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of 13c89f2750SDavid 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14c89f2750SDavid 'Digit' Turner * GNU General Public License for more details. 15c89f2750SDavid 'Digit' Turner * 16c89f2750SDavid 'Digit' Turner */ 17c89f2750SDavid 'Digit' Turner 18c89f2750SDavid 'Digit' Turner /* This source file contains the implementation of a special device driver 19c89f2750SDavid 'Digit' Turner * that intends to provide a *very* fast communication channel between the 20c89f2750SDavid 'Digit' Turner * guest system and the QEMU emulator. 21c89f2750SDavid 'Digit' Turner * 22c89f2750SDavid 'Digit' Turner * Usage from the guest is simply the following (error handling simplified): 23c89f2750SDavid 'Digit' Turner * 24c89f2750SDavid 'Digit' Turner * int fd = open("/dev/qemu_pipe",O_RDWR); 25c89f2750SDavid 'Digit' Turner * .... write() or read() through the pipe. 26c89f2750SDavid 'Digit' Turner * 27c89f2750SDavid 'Digit' Turner * This driver doesn't deal with the exact protocol used during the session. 28c89f2750SDavid 'Digit' Turner * It is intended to be as simple as something like: 29c89f2750SDavid 'Digit' Turner * 30c89f2750SDavid 'Digit' Turner * // do this _just_ after opening the fd to connect to a specific 31c89f2750SDavid 'Digit' Turner * // emulator service. 32c89f2750SDavid 'Digit' Turner * const char* msg = "<pipename>"; 33c89f2750SDavid 'Digit' Turner * if (write(fd, msg, strlen(msg)+1) < 0) { 34c89f2750SDavid 'Digit' Turner * ... could not connect to <pipename> service 35c89f2750SDavid 'Digit' Turner * close(fd); 36c89f2750SDavid 'Digit' Turner * } 37c89f2750SDavid 'Digit' Turner * 38c89f2750SDavid 'Digit' Turner * // after this, simply read() and write() to communicate with the 39c89f2750SDavid 'Digit' Turner * // service. Exact protocol details left as an exercise to the reader. 40c89f2750SDavid 'Digit' Turner * 41c89f2750SDavid 'Digit' Turner * This driver is very fast because it doesn't copy any data through 42c89f2750SDavid 'Digit' Turner * intermediate buffers, since the emulator is capable of translating 43c89f2750SDavid 'Digit' Turner * guest user addresses into host ones. 44c89f2750SDavid 'Digit' Turner * 45c89f2750SDavid 'Digit' Turner * Note that we must however ensure that each user page involved in the 46c89f2750SDavid 'Digit' Turner * exchange is properly mapped during a transfer. 47c89f2750SDavid 'Digit' Turner */ 48c89f2750SDavid 'Digit' Turner 49c89f2750SDavid 'Digit' Turner #include <linux/module.h> 50c89f2750SDavid 'Digit' Turner #include <linux/interrupt.h> 51c89f2750SDavid 'Digit' Turner #include <linux/kernel.h> 52c89f2750SDavid 'Digit' Turner #include <linux/spinlock.h> 53c89f2750SDavid 'Digit' Turner #include <linux/miscdevice.h> 54c89f2750SDavid 'Digit' Turner #include <linux/platform_device.h> 55c89f2750SDavid 'Digit' Turner #include <linux/poll.h> 56c89f2750SDavid 'Digit' Turner #include <linux/sched.h> 57c89f2750SDavid 'Digit' Turner #include <linux/bitops.h> 58c89f2750SDavid 'Digit' Turner #include <linux/slab.h> 59c89f2750SDavid 'Digit' Turner #include <linux/io.h> 60a99698faSAlan #include <linux/goldfish.h> 612f3be882SChristoffer Dall #include <linux/mm.h> 62*d62f324bSJason Hu #include <linux/acpi.h> 63c89f2750SDavid 'Digit' Turner 64c89f2750SDavid 'Digit' Turner /* 65c89f2750SDavid 'Digit' Turner * IMPORTANT: The following constants must match the ones used and defined 66c89f2750SDavid 'Digit' Turner * in external/qemu/hw/goldfish_pipe.c in the Android source tree. 67c89f2750SDavid 'Digit' Turner */ 68c89f2750SDavid 'Digit' Turner 69c89f2750SDavid 'Digit' Turner /* pipe device registers */ 70c89f2750SDavid 'Digit' Turner #define PIPE_REG_COMMAND 0x00 /* write: value = command */ 71c89f2750SDavid 'Digit' Turner #define PIPE_REG_STATUS 0x04 /* read */ 72c89f2750SDavid 'Digit' Turner #define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */ 7349a75c44SJun Tian #define PIPE_REG_CHANNEL_HIGH 0x30 /* read/write: channel id */ 74c89f2750SDavid 'Digit' Turner #define PIPE_REG_SIZE 0x0c /* read/write: buffer size */ 75c89f2750SDavid 'Digit' Turner #define PIPE_REG_ADDRESS 0x10 /* write: physical address */ 7649a75c44SJun Tian #define PIPE_REG_ADDRESS_HIGH 0x34 /* write: physical address */ 77c89f2750SDavid 'Digit' Turner #define PIPE_REG_WAKES 0x14 /* read: wake flags */ 78c89f2750SDavid 'Digit' Turner #define PIPE_REG_PARAMS_ADDR_LOW 0x18 /* read/write: batch data address */ 79c89f2750SDavid 'Digit' Turner #define PIPE_REG_PARAMS_ADDR_HIGH 0x1c /* read/write: batch data address */ 80c89f2750SDavid 'Digit' Turner #define PIPE_REG_ACCESS_PARAMS 0x20 /* write: batch access */ 814f42071cSYu Ning #define PIPE_REG_VERSION 0x24 /* read: device version */ 82c89f2750SDavid 'Digit' Turner 83c89f2750SDavid 'Digit' Turner /* list of commands for PIPE_REG_COMMAND */ 84c89f2750SDavid 'Digit' Turner #define CMD_OPEN 1 /* open new channel */ 85c89f2750SDavid 'Digit' Turner #define CMD_CLOSE 2 /* close channel (from guest) */ 86c89f2750SDavid 'Digit' Turner #define CMD_POLL 3 /* poll read/write status */ 87c89f2750SDavid 'Digit' Turner 88c89f2750SDavid 'Digit' Turner /* List of bitflags returned in status of CMD_POLL command */ 89c89f2750SDavid 'Digit' Turner #define PIPE_POLL_IN (1 << 0) 90c89f2750SDavid 'Digit' Turner #define PIPE_POLL_OUT (1 << 1) 91c89f2750SDavid 'Digit' Turner #define PIPE_POLL_HUP (1 << 2) 92c89f2750SDavid 'Digit' Turner 93c89f2750SDavid 'Digit' Turner /* The following commands are related to write operations */ 94c89f2750SDavid 'Digit' Turner #define CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */ 95c89f2750SDavid 'Digit' Turner #define CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing 96c89f2750SDavid 'Digit' Turner is possible */ 97c89f2750SDavid 'Digit' Turner #define CMD_READ_BUFFER 6 /* receive a user buffer from the emulator */ 98c89f2750SDavid 'Digit' Turner #define CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading 99c89f2750SDavid 'Digit' Turner * is possible */ 100c89f2750SDavid 'Digit' Turner 101c89f2750SDavid 'Digit' Turner /* Possible status values used to signal errors - see goldfish_pipe_error_convert */ 102c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_INVAL -1 103c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_AGAIN -2 104c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_NOMEM -3 105c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_IO -4 106c89f2750SDavid 'Digit' Turner 107c89f2750SDavid 'Digit' Turner /* Bit-flags used to signal events from the emulator */ 108c89f2750SDavid 'Digit' Turner #define PIPE_WAKE_CLOSED (1 << 0) /* emulator closed pipe */ 109c89f2750SDavid 'Digit' Turner #define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */ 110c89f2750SDavid 'Digit' Turner #define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */ 111c89f2750SDavid 'Digit' Turner 112c89f2750SDavid 'Digit' Turner struct access_params { 11349a75c44SJun Tian unsigned long channel; 114c89f2750SDavid 'Digit' Turner u32 size; 11549a75c44SJun Tian unsigned long address; 116c89f2750SDavid 'Digit' Turner u32 cmd; 117c89f2750SDavid 'Digit' Turner u32 result; 118c89f2750SDavid 'Digit' Turner /* reserved for future extension */ 119c89f2750SDavid 'Digit' Turner u32 flags; 120c89f2750SDavid 'Digit' Turner }; 121c89f2750SDavid 'Digit' Turner 122c89f2750SDavid 'Digit' Turner /* The global driver data. Holds a reference to the i/o page used to 123c89f2750SDavid 'Digit' Turner * communicate with the emulator, and a wake queue for blocked tasks 124c89f2750SDavid 'Digit' Turner * waiting to be awoken. 125c89f2750SDavid 'Digit' Turner */ 126c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev { 127c89f2750SDavid 'Digit' Turner spinlock_t lock; 128c89f2750SDavid 'Digit' Turner unsigned char __iomem *base; 129c89f2750SDavid 'Digit' Turner struct access_params *aps; 130c89f2750SDavid 'Digit' Turner int irq; 1314f42071cSYu Ning u32 version; 132c89f2750SDavid 'Digit' Turner }; 133c89f2750SDavid 'Digit' Turner 134c89f2750SDavid 'Digit' Turner static struct goldfish_pipe_dev pipe_dev[1]; 135c89f2750SDavid 'Digit' Turner 136c89f2750SDavid 'Digit' Turner /* This data type models a given pipe instance */ 137c89f2750SDavid 'Digit' Turner struct goldfish_pipe { 138c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev; 139c89f2750SDavid 'Digit' Turner struct mutex lock; 140c89f2750SDavid 'Digit' Turner unsigned long flags; 141c89f2750SDavid 'Digit' Turner wait_queue_head_t wake_queue; 142c89f2750SDavid 'Digit' Turner }; 143c89f2750SDavid 'Digit' Turner 144c89f2750SDavid 'Digit' Turner 145c89f2750SDavid 'Digit' Turner /* Bit flags for the 'flags' field */ 146c89f2750SDavid 'Digit' Turner enum { 147c89f2750SDavid 'Digit' Turner BIT_CLOSED_ON_HOST = 0, /* pipe closed by host */ 148c89f2750SDavid 'Digit' Turner BIT_WAKE_ON_WRITE = 1, /* want to be woken on writes */ 149c89f2750SDavid 'Digit' Turner BIT_WAKE_ON_READ = 2, /* want to be woken on reads */ 150c89f2750SDavid 'Digit' Turner }; 151c89f2750SDavid 'Digit' Turner 152c89f2750SDavid 'Digit' Turner 153c89f2750SDavid 'Digit' Turner static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd) 154c89f2750SDavid 'Digit' Turner { 155c89f2750SDavid 'Digit' Turner unsigned long flags; 156c89f2750SDavid 'Digit' Turner u32 status; 157c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = pipe->dev; 158c89f2750SDavid 'Digit' Turner 159c89f2750SDavid 'Digit' Turner spin_lock_irqsave(&dev->lock, flags); 16007d783fdSPeter Senna Tschudin gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, 161a99698faSAlan dev->base + PIPE_REG_CHANNEL_HIGH); 162c89f2750SDavid 'Digit' Turner writel(cmd, dev->base + PIPE_REG_COMMAND); 163c89f2750SDavid 'Digit' Turner status = readl(dev->base + PIPE_REG_STATUS); 164c89f2750SDavid 'Digit' Turner spin_unlock_irqrestore(&dev->lock, flags); 165c89f2750SDavid 'Digit' Turner return status; 166c89f2750SDavid 'Digit' Turner } 167c89f2750SDavid 'Digit' Turner 168c89f2750SDavid 'Digit' Turner static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd) 169c89f2750SDavid 'Digit' Turner { 170c89f2750SDavid 'Digit' Turner unsigned long flags; 171c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = pipe->dev; 172c89f2750SDavid 'Digit' Turner 173c89f2750SDavid 'Digit' Turner spin_lock_irqsave(&dev->lock, flags); 17407d783fdSPeter Senna Tschudin gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, 175a99698faSAlan dev->base + PIPE_REG_CHANNEL_HIGH); 176c89f2750SDavid 'Digit' Turner writel(cmd, dev->base + PIPE_REG_COMMAND); 177c89f2750SDavid 'Digit' Turner spin_unlock_irqrestore(&dev->lock, flags); 178c89f2750SDavid 'Digit' Turner } 179c89f2750SDavid 'Digit' Turner 180c89f2750SDavid 'Digit' Turner /* This function converts an error code returned by the emulator through 181c89f2750SDavid 'Digit' Turner * the PIPE_REG_STATUS i/o register into a valid negative errno value. 182c89f2750SDavid 'Digit' Turner */ 183c89f2750SDavid 'Digit' Turner static int goldfish_pipe_error_convert(int status) 184c89f2750SDavid 'Digit' Turner { 185c89f2750SDavid 'Digit' Turner switch (status) { 186c89f2750SDavid 'Digit' Turner case PIPE_ERROR_AGAIN: 187c89f2750SDavid 'Digit' Turner return -EAGAIN; 188c89f2750SDavid 'Digit' Turner case PIPE_ERROR_NOMEM: 189c89f2750SDavid 'Digit' Turner return -ENOMEM; 190c89f2750SDavid 'Digit' Turner case PIPE_ERROR_IO: 191c89f2750SDavid 'Digit' Turner return -EIO; 192c89f2750SDavid 'Digit' Turner default: 193c89f2750SDavid 'Digit' Turner return -EINVAL; 194c89f2750SDavid 'Digit' Turner } 195c89f2750SDavid 'Digit' Turner } 196c89f2750SDavid 'Digit' Turner 197c89f2750SDavid 'Digit' Turner /* 198c89f2750SDavid 'Digit' Turner * Notice: QEMU will return 0 for un-known register access, indicating 199c89f2750SDavid 'Digit' Turner * param_acess is supported or not 200c89f2750SDavid 'Digit' Turner */ 201c89f2750SDavid 'Digit' Turner static int valid_batchbuffer_addr(struct goldfish_pipe_dev *dev, 202c89f2750SDavid 'Digit' Turner struct access_params *aps) 203c89f2750SDavid 'Digit' Turner { 204c89f2750SDavid 'Digit' Turner u32 aph, apl; 205c89f2750SDavid 'Digit' Turner u64 paddr; 206c89f2750SDavid 'Digit' Turner aph = readl(dev->base + PIPE_REG_PARAMS_ADDR_HIGH); 207c89f2750SDavid 'Digit' Turner apl = readl(dev->base + PIPE_REG_PARAMS_ADDR_LOW); 208c89f2750SDavid 'Digit' Turner 209c89f2750SDavid 'Digit' Turner paddr = ((u64)aph << 32) | apl; 210c89f2750SDavid 'Digit' Turner if (paddr != (__pa(aps))) 211c89f2750SDavid 'Digit' Turner return 0; 212c89f2750SDavid 'Digit' Turner return 1; 213c89f2750SDavid 'Digit' Turner } 214c89f2750SDavid 'Digit' Turner 215c89f2750SDavid 'Digit' Turner /* 0 on success */ 216c89f2750SDavid 'Digit' Turner static int setup_access_params_addr(struct platform_device *pdev, 217c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev) 218c89f2750SDavid 'Digit' Turner { 219c89f2750SDavid 'Digit' Turner u64 paddr; 220c89f2750SDavid 'Digit' Turner struct access_params *aps; 221c89f2750SDavid 'Digit' Turner 222c89f2750SDavid 'Digit' Turner aps = devm_kzalloc(&pdev->dev, sizeof(struct access_params), GFP_KERNEL); 223c89f2750SDavid 'Digit' Turner if (!aps) 224c89f2750SDavid 'Digit' Turner return -1; 225c89f2750SDavid 'Digit' Turner 226c89f2750SDavid 'Digit' Turner /* FIXME */ 227c89f2750SDavid 'Digit' Turner paddr = __pa(aps); 228c89f2750SDavid 'Digit' Turner writel((u32)(paddr >> 32), dev->base + PIPE_REG_PARAMS_ADDR_HIGH); 229c89f2750SDavid 'Digit' Turner writel((u32)paddr, dev->base + PIPE_REG_PARAMS_ADDR_LOW); 230c89f2750SDavid 'Digit' Turner 231c89f2750SDavid 'Digit' Turner if (valid_batchbuffer_addr(dev, aps)) { 232c89f2750SDavid 'Digit' Turner dev->aps = aps; 233c89f2750SDavid 'Digit' Turner return 0; 234c89f2750SDavid 'Digit' Turner } else 235c89f2750SDavid 'Digit' Turner return -1; 236c89f2750SDavid 'Digit' Turner } 237c89f2750SDavid 'Digit' Turner 238c89f2750SDavid 'Digit' Turner /* A value that will not be set by qemu emulator */ 239c89f2750SDavid 'Digit' Turner #define INITIAL_BATCH_RESULT (0xdeadbeaf) 240c89f2750SDavid 'Digit' Turner static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, 241c89f2750SDavid 'Digit' Turner unsigned long address, unsigned long avail, 242c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe, int *status) 243c89f2750SDavid 'Digit' Turner { 244c89f2750SDavid 'Digit' Turner struct access_params *aps = dev->aps; 245c89f2750SDavid 'Digit' Turner 246c89f2750SDavid 'Digit' Turner if (aps == NULL) 247c89f2750SDavid 'Digit' Turner return -1; 248c89f2750SDavid 'Digit' Turner 249c89f2750SDavid 'Digit' Turner aps->result = INITIAL_BATCH_RESULT; 250c89f2750SDavid 'Digit' Turner aps->channel = (unsigned long)pipe; 251c89f2750SDavid 'Digit' Turner aps->size = avail; 252c89f2750SDavid 'Digit' Turner aps->address = address; 253c89f2750SDavid 'Digit' Turner aps->cmd = cmd; 254c89f2750SDavid 'Digit' Turner writel(cmd, dev->base + PIPE_REG_ACCESS_PARAMS); 255c89f2750SDavid 'Digit' Turner /* 256c89f2750SDavid 'Digit' Turner * If the aps->result has not changed, that means 257c89f2750SDavid 'Digit' Turner * that the batch command failed 258c89f2750SDavid 'Digit' Turner */ 259c89f2750SDavid 'Digit' Turner if (aps->result == INITIAL_BATCH_RESULT) 260c89f2750SDavid 'Digit' Turner return -1; 261c89f2750SDavid 'Digit' Turner *status = aps->result; 262c89f2750SDavid 'Digit' Turner return 0; 263c89f2750SDavid 'Digit' Turner } 264c89f2750SDavid 'Digit' Turner 265c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, 266c89f2750SDavid 'Digit' Turner size_t bufflen, int is_write) 267c89f2750SDavid 'Digit' Turner { 268c89f2750SDavid 'Digit' Turner unsigned long irq_flags; 269c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 270c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = pipe->dev; 271c89f2750SDavid 'Digit' Turner unsigned long address, address_end; 2722f3be882SChristoffer Dall int count = 0, ret = -EINVAL; 273c89f2750SDavid 'Digit' Turner 274c89f2750SDavid 'Digit' Turner /* If the emulator already closed the pipe, no need to go further */ 275c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 276c89f2750SDavid 'Digit' Turner return -EIO; 277c89f2750SDavid 'Digit' Turner 278c89f2750SDavid 'Digit' Turner /* Null reads or writes succeeds */ 2793411d035SJoe Perches if (unlikely(bufflen == 0)) 280c89f2750SDavid 'Digit' Turner return 0; 281c89f2750SDavid 'Digit' Turner 282c89f2750SDavid 'Digit' Turner /* Check the buffer range for access */ 283c89f2750SDavid 'Digit' Turner if (!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ, 284c89f2750SDavid 'Digit' Turner buffer, bufflen)) 285c89f2750SDavid 'Digit' Turner return -EFAULT; 286c89f2750SDavid 'Digit' Turner 287c89f2750SDavid 'Digit' Turner /* Serialize access to the pipe */ 288c89f2750SDavid 'Digit' Turner if (mutex_lock_interruptible(&pipe->lock)) 289c89f2750SDavid 'Digit' Turner return -ERESTARTSYS; 290c89f2750SDavid 'Digit' Turner 291c89f2750SDavid 'Digit' Turner address = (unsigned long)(void *)buffer; 292c89f2750SDavid 'Digit' Turner address_end = address + bufflen; 293c89f2750SDavid 'Digit' Turner 294c89f2750SDavid 'Digit' Turner while (address < address_end) { 295c89f2750SDavid 'Digit' Turner unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE; 296c89f2750SDavid 'Digit' Turner unsigned long next = page_end < address_end ? page_end 297c89f2750SDavid 'Digit' Turner : address_end; 298c89f2750SDavid 'Digit' Turner unsigned long avail = next - address; 299c89f2750SDavid 'Digit' Turner int status, wakeBit; 3002f3be882SChristoffer Dall struct page *page; 301c89f2750SDavid 'Digit' Turner 3024f42071cSYu Ning /* Either vaddr or paddr depending on the device version */ 3034f42071cSYu Ning unsigned long xaddr; 3044f42071cSYu Ning 3052f3be882SChristoffer Dall /* 3062f3be882SChristoffer Dall * We grab the pages on a page-by-page basis in case user 3072f3be882SChristoffer Dall * space gives us a potentially huge buffer but the read only 3082f3be882SChristoffer Dall * returns a small amount, then there's no need to pin that 3092f3be882SChristoffer Dall * much memory to the process. 3102f3be882SChristoffer Dall */ 3114f42071cSYu Ning down_read(¤t->mm->mmap_sem); 3122f3be882SChristoffer Dall ret = get_user_pages(current, current->mm, address, 1, 3132f3be882SChristoffer Dall !is_write, 0, &page, NULL); 3144f42071cSYu Ning up_read(¤t->mm->mmap_sem); 3152f3be882SChristoffer Dall if (ret < 0) 3162f3be882SChristoffer Dall return ret; 317c89f2750SDavid 'Digit' Turner 3184f42071cSYu Ning if (dev->version) { 3194f42071cSYu Ning /* Device version 1 or newer (qemu-android) expects the 3204f42071cSYu Ning * physical address. 3214f42071cSYu Ning */ 3224f42071cSYu Ning xaddr = page_to_phys(page) | (address & ~PAGE_MASK); 3234f42071cSYu Ning } else { 3244f42071cSYu Ning /* Device version 0 (classic emulator) expects the 3254f42071cSYu Ning * virtual address. 3264f42071cSYu Ning */ 3274f42071cSYu Ning xaddr = address; 3284f42071cSYu Ning } 3294f42071cSYu Ning 330c89f2750SDavid 'Digit' Turner /* Now, try to transfer the bytes in the current page */ 331c89f2750SDavid 'Digit' Turner spin_lock_irqsave(&dev->lock, irq_flags); 33223c5ee21SAlex Bennée if (access_with_param(dev, 33323c5ee21SAlex Bennée is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, 3344f42071cSYu Ning xaddr, avail, pipe, &status)) { 33507d783fdSPeter Senna Tschudin gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, 336a99698faSAlan dev->base + PIPE_REG_CHANNEL_HIGH); 337c89f2750SDavid 'Digit' Turner writel(avail, dev->base + PIPE_REG_SIZE); 3384f42071cSYu Ning gf_write_ptr((void *)xaddr, 33907d783fdSPeter Senna Tschudin dev->base + PIPE_REG_ADDRESS, 340a99698faSAlan dev->base + PIPE_REG_ADDRESS_HIGH); 34123c5ee21SAlex Bennée writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER, 342c89f2750SDavid 'Digit' Turner dev->base + PIPE_REG_COMMAND); 343c89f2750SDavid 'Digit' Turner status = readl(dev->base + PIPE_REG_STATUS); 344c89f2750SDavid 'Digit' Turner } 345c89f2750SDavid 'Digit' Turner spin_unlock_irqrestore(&dev->lock, irq_flags); 346c89f2750SDavid 'Digit' Turner 3472f3be882SChristoffer Dall if (status > 0 && !is_write) 3482f3be882SChristoffer Dall set_page_dirty(page); 3492f3be882SChristoffer Dall put_page(page); 3502f3be882SChristoffer Dall 351c89f2750SDavid 'Digit' Turner if (status > 0) { /* Correct transfer */ 3522f3be882SChristoffer Dall count += status; 353c89f2750SDavid 'Digit' Turner address += status; 354c89f2750SDavid 'Digit' Turner continue; 3552f3be882SChristoffer Dall } else if (status == 0) { /* EOF */ 3562f3be882SChristoffer Dall ret = 0; 3572f3be882SChristoffer Dall break; 3582f3be882SChristoffer Dall } else if (status < 0 && count > 0) { 3592f3be882SChristoffer Dall /* 3602f3be882SChristoffer Dall * An error occurred and we already transferred 3612f3be882SChristoffer Dall * something on one of the previous pages. 3622f3be882SChristoffer Dall * Just return what we already copied and log this 3632f3be882SChristoffer Dall * err. 3642f3be882SChristoffer Dall * 3652f3be882SChristoffer Dall * Note: This seems like an incorrect approach but 3662f3be882SChristoffer Dall * cannot change it until we check if any user space 3672f3be882SChristoffer Dall * ABI relies on this behavior. 3682f3be882SChristoffer Dall */ 36925dd0f40SGreg Hackmann if (status != PIPE_ERROR_AGAIN) 37025dd0f40SGreg Hackmann pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n", 3712f3be882SChristoffer Dall status, is_write ? "write" : "read"); 3722f3be882SChristoffer Dall ret = 0; 3732f3be882SChristoffer Dall break; 374c89f2750SDavid 'Digit' Turner } 375c89f2750SDavid 'Digit' Turner 3762f3be882SChristoffer Dall /* 3772f3be882SChristoffer Dall * If the error is not PIPE_ERROR_AGAIN, or if we are not in 378c89f2750SDavid 'Digit' Turner * non-blocking mode, just return the error code. 379c89f2750SDavid 'Digit' Turner */ 380c89f2750SDavid 'Digit' Turner if (status != PIPE_ERROR_AGAIN || 381c89f2750SDavid 'Digit' Turner (filp->f_flags & O_NONBLOCK) != 0) { 382c89f2750SDavid 'Digit' Turner ret = goldfish_pipe_error_convert(status); 383c89f2750SDavid 'Digit' Turner break; 384c89f2750SDavid 'Digit' Turner } 385c89f2750SDavid 'Digit' Turner 3862f3be882SChristoffer Dall /* 3872f3be882SChristoffer Dall * The backend blocked the read/write, wait until the backend 3882f3be882SChristoffer Dall * tells us it's ready to process more data. 389c89f2750SDavid 'Digit' Turner */ 390c89f2750SDavid 'Digit' Turner wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ; 391c89f2750SDavid 'Digit' Turner set_bit(wakeBit, &pipe->flags); 392c89f2750SDavid 'Digit' Turner 393c89f2750SDavid 'Digit' Turner /* Tell the emulator we're going to wait for a wake event */ 39423c5ee21SAlex Bennée goldfish_cmd(pipe, 39523c5ee21SAlex Bennée is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ); 396c89f2750SDavid 'Digit' Turner 397c89f2750SDavid 'Digit' Turner /* Unlock the pipe, then wait for the wake signal */ 398c89f2750SDavid 'Digit' Turner mutex_unlock(&pipe->lock); 399c89f2750SDavid 'Digit' Turner 400c89f2750SDavid 'Digit' Turner while (test_bit(wakeBit, &pipe->flags)) { 401c89f2750SDavid 'Digit' Turner if (wait_event_interruptible( 402c89f2750SDavid 'Digit' Turner pipe->wake_queue, 4032f3be882SChristoffer Dall !test_bit(wakeBit, &pipe->flags))) { 4042f3be882SChristoffer Dall ret = -ERESTARTSYS; 4052f3be882SChristoffer Dall break; 4062f3be882SChristoffer Dall } 407c89f2750SDavid 'Digit' Turner 4082f3be882SChristoffer Dall if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) { 4092f3be882SChristoffer Dall ret = -EIO; 4102f3be882SChristoffer Dall break; 4112f3be882SChristoffer Dall } 412c89f2750SDavid 'Digit' Turner } 413c89f2750SDavid 'Digit' Turner 414c89f2750SDavid 'Digit' Turner /* Try to re-acquire the lock */ 4152f3be882SChristoffer Dall if (mutex_lock_interruptible(&pipe->lock)) { 4162f3be882SChristoffer Dall ret = -ERESTARTSYS; 4172f3be882SChristoffer Dall break; 4182f3be882SChristoffer Dall } 419c89f2750SDavid 'Digit' Turner } 420c89f2750SDavid 'Digit' Turner mutex_unlock(&pipe->lock); 4212f3be882SChristoffer Dall 4222f3be882SChristoffer Dall if (ret < 0) 423c89f2750SDavid 'Digit' Turner return ret; 4242f3be882SChristoffer Dall else 4252f3be882SChristoffer Dall return count; 426c89f2750SDavid 'Digit' Turner } 427c89f2750SDavid 'Digit' Turner 428c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer, 429c89f2750SDavid 'Digit' Turner size_t bufflen, loff_t *ppos) 430c89f2750SDavid 'Digit' Turner { 431c89f2750SDavid 'Digit' Turner return goldfish_pipe_read_write(filp, buffer, bufflen, 0); 432c89f2750SDavid 'Digit' Turner } 433c89f2750SDavid 'Digit' Turner 434c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_write(struct file *filp, 435c89f2750SDavid 'Digit' Turner const char __user *buffer, size_t bufflen, 436c89f2750SDavid 'Digit' Turner loff_t *ppos) 437c89f2750SDavid 'Digit' Turner { 438c89f2750SDavid 'Digit' Turner return goldfish_pipe_read_write(filp, (char __user *)buffer, 439c89f2750SDavid 'Digit' Turner bufflen, 1); 440c89f2750SDavid 'Digit' Turner } 441c89f2750SDavid 'Digit' Turner 442c89f2750SDavid 'Digit' Turner 443c89f2750SDavid 'Digit' Turner static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait) 444c89f2750SDavid 'Digit' Turner { 445c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 446c89f2750SDavid 'Digit' Turner unsigned int mask = 0; 447c89f2750SDavid 'Digit' Turner int status; 448c89f2750SDavid 'Digit' Turner 449c89f2750SDavid 'Digit' Turner mutex_lock(&pipe->lock); 450c89f2750SDavid 'Digit' Turner 451c89f2750SDavid 'Digit' Turner poll_wait(filp, &pipe->wake_queue, wait); 452c89f2750SDavid 'Digit' Turner 453c89f2750SDavid 'Digit' Turner status = goldfish_cmd_status(pipe, CMD_POLL); 454c89f2750SDavid 'Digit' Turner 455c89f2750SDavid 'Digit' Turner mutex_unlock(&pipe->lock); 456c89f2750SDavid 'Digit' Turner 457c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_IN) 458c89f2750SDavid 'Digit' Turner mask |= POLLIN | POLLRDNORM; 459c89f2750SDavid 'Digit' Turner 460c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_OUT) 461c89f2750SDavid 'Digit' Turner mask |= POLLOUT | POLLWRNORM; 462c89f2750SDavid 'Digit' Turner 463c89f2750SDavid 'Digit' Turner if (status & PIPE_POLL_HUP) 464c89f2750SDavid 'Digit' Turner mask |= POLLHUP; 465c89f2750SDavid 'Digit' Turner 466c89f2750SDavid 'Digit' Turner if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) 467c89f2750SDavid 'Digit' Turner mask |= POLLERR; 468c89f2750SDavid 'Digit' Turner 469c89f2750SDavid 'Digit' Turner return mask; 470c89f2750SDavid 'Digit' Turner } 471c89f2750SDavid 'Digit' Turner 472c89f2750SDavid 'Digit' Turner static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id) 473c89f2750SDavid 'Digit' Turner { 474c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = dev_id; 475c89f2750SDavid 'Digit' Turner unsigned long irq_flags; 476c89f2750SDavid 'Digit' Turner int count = 0; 477c89f2750SDavid 'Digit' Turner 4782f3be882SChristoffer Dall /* 4792f3be882SChristoffer Dall * We're going to read from the emulator a list of (channel,flags) 4802f3be882SChristoffer Dall * pairs corresponding to the wake events that occurred on each 481c89f2750SDavid 'Digit' Turner * blocked pipe (i.e. channel). 482c89f2750SDavid 'Digit' Turner */ 483c89f2750SDavid 'Digit' Turner spin_lock_irqsave(&dev->lock, irq_flags); 484c89f2750SDavid 'Digit' Turner for (;;) { 485c89f2750SDavid 'Digit' Turner /* First read the channel, 0 means the end of the list */ 486c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe; 487c89f2750SDavid 'Digit' Turner unsigned long wakes; 48849a75c44SJun Tian unsigned long channel = 0; 48949a75c44SJun Tian 49049a75c44SJun Tian #ifdef CONFIG_64BIT 49149a75c44SJun Tian channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32; 49225c72c78SJun Tian 49325c72c78SJun Tian if (channel == 0) 49425c72c78SJun Tian break; 49549a75c44SJun Tian #endif 49649a75c44SJun Tian channel |= readl(dev->base + PIPE_REG_CHANNEL); 497c89f2750SDavid 'Digit' Turner 498c89f2750SDavid 'Digit' Turner if (channel == 0) 499c89f2750SDavid 'Digit' Turner break; 500c89f2750SDavid 'Digit' Turner 501c89f2750SDavid 'Digit' Turner /* Convert channel to struct pipe pointer + read wake flags */ 502c89f2750SDavid 'Digit' Turner wakes = readl(dev->base + PIPE_REG_WAKES); 503c89f2750SDavid 'Digit' Turner pipe = (struct goldfish_pipe *)(ptrdiff_t)channel; 504c89f2750SDavid 'Digit' Turner 505c89f2750SDavid 'Digit' Turner /* Did the emulator just closed a pipe? */ 506c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_CLOSED) { 507c89f2750SDavid 'Digit' Turner set_bit(BIT_CLOSED_ON_HOST, &pipe->flags); 508c89f2750SDavid 'Digit' Turner wakes |= PIPE_WAKE_READ | PIPE_WAKE_WRITE; 509c89f2750SDavid 'Digit' Turner } 510c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_READ) 511c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_READ, &pipe->flags); 512c89f2750SDavid 'Digit' Turner if (wakes & PIPE_WAKE_WRITE) 513c89f2750SDavid 'Digit' Turner clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags); 514c89f2750SDavid 'Digit' Turner 515c89f2750SDavid 'Digit' Turner wake_up_interruptible(&pipe->wake_queue); 516c89f2750SDavid 'Digit' Turner count++; 517c89f2750SDavid 'Digit' Turner } 518c89f2750SDavid 'Digit' Turner spin_unlock_irqrestore(&dev->lock, irq_flags); 519c89f2750SDavid 'Digit' Turner 520c89f2750SDavid 'Digit' Turner return (count == 0) ? IRQ_NONE : IRQ_HANDLED; 521c89f2750SDavid 'Digit' Turner } 522c89f2750SDavid 'Digit' Turner 523c89f2750SDavid 'Digit' Turner /** 524c89f2750SDavid 'Digit' Turner * goldfish_pipe_open - open a channel to the AVD 525c89f2750SDavid 'Digit' Turner * @inode: inode of device 526c89f2750SDavid 'Digit' Turner * @file: file struct of opener 527c89f2750SDavid 'Digit' Turner * 528c89f2750SDavid 'Digit' Turner * Create a new pipe link between the emulator and the use application. 529c89f2750SDavid 'Digit' Turner * Each new request produces a new pipe. 530c89f2750SDavid 'Digit' Turner * 531c89f2750SDavid 'Digit' Turner * Note: we use the pipe ID as a mux. All goldfish emulations are 32bit 532c89f2750SDavid 'Digit' Turner * right now so this is fine. A move to 64bit will need this addressing 533c89f2750SDavid 'Digit' Turner */ 534c89f2750SDavid 'Digit' Turner static int goldfish_pipe_open(struct inode *inode, struct file *file) 535c89f2750SDavid 'Digit' Turner { 536c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe; 537c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = pipe_dev; 538c89f2750SDavid 'Digit' Turner int32_t status; 539c89f2750SDavid 'Digit' Turner 540c89f2750SDavid 'Digit' Turner /* Allocate new pipe kernel object */ 541c89f2750SDavid 'Digit' Turner pipe = kzalloc(sizeof(*pipe), GFP_KERNEL); 542c89f2750SDavid 'Digit' Turner if (pipe == NULL) 543c89f2750SDavid 'Digit' Turner return -ENOMEM; 544c89f2750SDavid 'Digit' Turner 545c89f2750SDavid 'Digit' Turner pipe->dev = dev; 546c89f2750SDavid 'Digit' Turner mutex_init(&pipe->lock); 547c89f2750SDavid 'Digit' Turner init_waitqueue_head(&pipe->wake_queue); 548c89f2750SDavid 'Digit' Turner 549c89f2750SDavid 'Digit' Turner /* 550c89f2750SDavid 'Digit' Turner * Now, tell the emulator we're opening a new pipe. We use the 551c89f2750SDavid 'Digit' Turner * pipe object's address as the channel identifier for simplicity. 552c89f2750SDavid 'Digit' Turner */ 553c89f2750SDavid 'Digit' Turner 554c89f2750SDavid 'Digit' Turner status = goldfish_cmd_status(pipe, CMD_OPEN); 555c89f2750SDavid 'Digit' Turner if (status < 0) { 556c89f2750SDavid 'Digit' Turner kfree(pipe); 557c89f2750SDavid 'Digit' Turner return status; 558c89f2750SDavid 'Digit' Turner } 559c89f2750SDavid 'Digit' Turner 560c89f2750SDavid 'Digit' Turner /* All is done, save the pipe into the file's private data field */ 561c89f2750SDavid 'Digit' Turner file->private_data = pipe; 562c89f2750SDavid 'Digit' Turner return 0; 563c89f2750SDavid 'Digit' Turner } 564c89f2750SDavid 'Digit' Turner 565c89f2750SDavid 'Digit' Turner static int goldfish_pipe_release(struct inode *inode, struct file *filp) 566c89f2750SDavid 'Digit' Turner { 567c89f2750SDavid 'Digit' Turner struct goldfish_pipe *pipe = filp->private_data; 568c89f2750SDavid 'Digit' Turner 569c89f2750SDavid 'Digit' Turner /* The guest is closing the channel, so tell the emulator right now */ 570c89f2750SDavid 'Digit' Turner goldfish_cmd(pipe, CMD_CLOSE); 571c89f2750SDavid 'Digit' Turner kfree(pipe); 572c89f2750SDavid 'Digit' Turner filp->private_data = NULL; 573c89f2750SDavid 'Digit' Turner return 0; 574c89f2750SDavid 'Digit' Turner } 575c89f2750SDavid 'Digit' Turner 576c89f2750SDavid 'Digit' Turner static const struct file_operations goldfish_pipe_fops = { 577c89f2750SDavid 'Digit' Turner .owner = THIS_MODULE, 578c89f2750SDavid 'Digit' Turner .read = goldfish_pipe_read, 579c89f2750SDavid 'Digit' Turner .write = goldfish_pipe_write, 580c89f2750SDavid 'Digit' Turner .poll = goldfish_pipe_poll, 581c89f2750SDavid 'Digit' Turner .open = goldfish_pipe_open, 582c89f2750SDavid 'Digit' Turner .release = goldfish_pipe_release, 583c89f2750SDavid 'Digit' Turner }; 584c89f2750SDavid 'Digit' Turner 585c89f2750SDavid 'Digit' Turner static struct miscdevice goldfish_pipe_device = { 586c89f2750SDavid 'Digit' Turner .minor = MISC_DYNAMIC_MINOR, 587c89f2750SDavid 'Digit' Turner .name = "goldfish_pipe", 588c89f2750SDavid 'Digit' Turner .fops = &goldfish_pipe_fops, 589c89f2750SDavid 'Digit' Turner }; 590c89f2750SDavid 'Digit' Turner 591c89f2750SDavid 'Digit' Turner static int goldfish_pipe_probe(struct platform_device *pdev) 592c89f2750SDavid 'Digit' Turner { 593c89f2750SDavid 'Digit' Turner int err; 594c89f2750SDavid 'Digit' Turner struct resource *r; 595c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = pipe_dev; 596c89f2750SDavid 'Digit' Turner 597c89f2750SDavid 'Digit' Turner /* not thread safe, but this should not happen */ 598c89f2750SDavid 'Digit' Turner WARN_ON(dev->base != NULL); 599c89f2750SDavid 'Digit' Turner 600c89f2750SDavid 'Digit' Turner spin_lock_init(&dev->lock); 601c89f2750SDavid 'Digit' Turner 602c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 603c89f2750SDavid 'Digit' Turner if (r == NULL || resource_size(r) < PAGE_SIZE) { 604c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "can't allocate i/o page\n"); 605c89f2750SDavid 'Digit' Turner return -EINVAL; 606c89f2750SDavid 'Digit' Turner } 607c89f2750SDavid 'Digit' Turner dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE); 608c89f2750SDavid 'Digit' Turner if (dev->base == NULL) { 609c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "ioremap failed\n"); 610c89f2750SDavid 'Digit' Turner return -EINVAL; 611c89f2750SDavid 'Digit' Turner } 612c89f2750SDavid 'Digit' Turner 613c89f2750SDavid 'Digit' Turner r = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 614c89f2750SDavid 'Digit' Turner if (r == NULL) { 615c89f2750SDavid 'Digit' Turner err = -EINVAL; 616c89f2750SDavid 'Digit' Turner goto error; 617c89f2750SDavid 'Digit' Turner } 618c89f2750SDavid 'Digit' Turner dev->irq = r->start; 619c89f2750SDavid 'Digit' Turner 620c89f2750SDavid 'Digit' Turner err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt, 621c89f2750SDavid 'Digit' Turner IRQF_SHARED, "goldfish_pipe", dev); 622c89f2750SDavid 'Digit' Turner if (err) { 623c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "unable to allocate IRQ\n"); 624c89f2750SDavid 'Digit' Turner goto error; 625c89f2750SDavid 'Digit' Turner } 626c89f2750SDavid 'Digit' Turner 627c89f2750SDavid 'Digit' Turner err = misc_register(&goldfish_pipe_device); 628c89f2750SDavid 'Digit' Turner if (err) { 629c89f2750SDavid 'Digit' Turner dev_err(&pdev->dev, "unable to register device\n"); 630c89f2750SDavid 'Digit' Turner goto error; 631c89f2750SDavid 'Digit' Turner } 632c89f2750SDavid 'Digit' Turner setup_access_params_addr(pdev, dev); 6334f42071cSYu Ning 6344f42071cSYu Ning /* Although the pipe device in the classic Android emulator does not 6354f42071cSYu Ning * recognize the 'version' register, it won't treat this as an error 6364f42071cSYu Ning * either and will simply return 0, which is fine. 6374f42071cSYu Ning */ 6384f42071cSYu Ning dev->version = readl(dev->base + PIPE_REG_VERSION); 639c89f2750SDavid 'Digit' Turner return 0; 640c89f2750SDavid 'Digit' Turner 641c89f2750SDavid 'Digit' Turner error: 642c89f2750SDavid 'Digit' Turner dev->base = NULL; 643c89f2750SDavid 'Digit' Turner return err; 644c89f2750SDavid 'Digit' Turner } 645c89f2750SDavid 'Digit' Turner 646c89f2750SDavid 'Digit' Turner static int goldfish_pipe_remove(struct platform_device *pdev) 647c89f2750SDavid 'Digit' Turner { 648c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev *dev = pipe_dev; 649c89f2750SDavid 'Digit' Turner misc_deregister(&goldfish_pipe_device); 650c89f2750SDavid 'Digit' Turner dev->base = NULL; 651c89f2750SDavid 'Digit' Turner return 0; 652c89f2750SDavid 'Digit' Turner } 653c89f2750SDavid 'Digit' Turner 654*d62f324bSJason Hu static const struct acpi_device_id goldfish_pipe_acpi_match[] = { 655*d62f324bSJason Hu { "GFSH0003", 0 }, 656*d62f324bSJason Hu { }, 657*d62f324bSJason Hu }; 658*d62f324bSJason Hu MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match); 659*d62f324bSJason Hu 66091a18a41SGreg Hackmann static const struct of_device_id goldfish_pipe_of_match[] = { 66191a18a41SGreg Hackmann { .compatible = "google,android-pipe", }, 66291a18a41SGreg Hackmann {}, 66391a18a41SGreg Hackmann }; 66491a18a41SGreg Hackmann MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match); 66591a18a41SGreg Hackmann 666c89f2750SDavid 'Digit' Turner static struct platform_driver goldfish_pipe = { 667c89f2750SDavid 'Digit' Turner .probe = goldfish_pipe_probe, 668c89f2750SDavid 'Digit' Turner .remove = goldfish_pipe_remove, 669c89f2750SDavid 'Digit' Turner .driver = { 67091a18a41SGreg Hackmann .name = "goldfish_pipe", 67191a18a41SGreg Hackmann .owner = THIS_MODULE, 67291a18a41SGreg Hackmann .of_match_table = goldfish_pipe_of_match, 673*d62f324bSJason Hu .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match), 674c89f2750SDavid 'Digit' Turner } 675c89f2750SDavid 'Digit' Turner }; 676c89f2750SDavid 'Digit' Turner 677c89f2750SDavid 'Digit' Turner module_platform_driver(goldfish_pipe); 678c89f2750SDavid 'Digit' Turner MODULE_AUTHOR("David Turner <digit@google.com>"); 679c89f2750SDavid 'Digit' Turner MODULE_LICENSE("GPL"); 680