Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757433AbbKFPwN (ORCPT ); Fri, 6 Nov 2015 10:52:13 -0500 Received: from mail-pa0-f47.google.com ([209.85.220.47]:34761 "EHLO mail-pa0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756636AbbKFPwM (ORCPT ); Fri, 6 Nov 2015 10:52:12 -0500 From: yalin wang To: yalin.wang2010@gmail.com, gregkh@linuxfoundation.org, peter.senna@gmail.com, joe@perches.com, dan.carpenter@oracle.com, linux-kernel@vger.kernel.org Subject: [PATCH] goldfish: fix goldfish_pipe driver BUG Date: Fri, 6 Nov 2015 23:51:55 +0800 Message-Id: <1446825115-23505-1-git-send-email-yalin.wang2010@gmail.com> X-Mailer: git-send-email 1.9.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4400 Lines: 121 goldfish_pipe_read_write() should pass the buffer's physical address to qemu, so that host can copy access data correctly, currently, the drier write a virtual address into address register, host can not get correct data, then adbd daemon can not work in guest. Also I comment off access_with_param() function, seems not used, we don't need use this function in goldfish_pipe_read_write(). Signed-off-by: yalin wang --- drivers/platform/goldfish/goldfish_pipe.c | 56 +++++++++++++++++++------------ 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 55b6d7c..bdf6f11 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -112,16 +112,27 @@ #define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */ #define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */ +#ifdef CONFIG_64BIT struct access_params { - unsigned long channel; - u32 size; - unsigned long address; - u32 cmd; - u32 result; + uint64_t channel; /* 0x00 */ + uint32_t size; /* 0x08 */ + uint64_t address; /* 0x0c */ + uint32_t cmd; /* 0x14 */ + uint32_t result; /* 0x18 */ /* reserved for future extension */ - u32 flags; + uint32_t flags; /* 0x1c */ }; - +#else +struct access_params { + uint32_t channel; /* 0x00 */ + uint32_t size; /* 0x04 */ + uint32_t address; /* 0x08 */ + uint32_t cmd; /* 0x0c */ + uint32_t result; /* 0x10 */ + /* reserved for future extension */ + uint32_t flags; /* 0x14 */ +}; +#endif /* The global driver data. Holds a reference to the i/o page used to * communicate with the emulator, and a wake queue for blocked tasks * waiting to be awoken. @@ -237,6 +248,7 @@ static int setup_access_params_addr(struct platform_device *pdev, return -1; } +#if 0 /* A value that will not be set by qemu emulator */ #define INITIAL_BATCH_RESULT (0xdeadbeaf) static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, @@ -263,6 +275,7 @@ static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd, *status = aps->result; return 0; } +#endif /* This function is used for both reading from and writing to a given * pipe. @@ -304,6 +317,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, : address_end; unsigned long avail = next - address; int status, wakeBit; + struct page *page; + phys_addr_t phys_addr; /* Ensure that the corresponding page is properly mapped */ /* FIXME: this isn't safe or sufficient - use get_user_pages */ @@ -323,23 +338,22 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, break; } } - + if (get_user_pages_unlocked(current, current->active_mm, + address, 1, !is_write, 0, &page) != 1) + return -EINVAL; + phys_addr = page_to_phys(page) + offset_in_page(address); /* Now, try to transfer the bytes in the current page */ spin_lock_irqsave(&dev->lock, irq_flags); - if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset, - address, avail, pipe, &status)) { - gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, - dev->base + PIPE_REG_CHANNEL_HIGH); - writel(avail, dev->base + PIPE_REG_SIZE); - gf_write_ptr((void *)address, - dev->base + PIPE_REG_ADDRESS, - dev->base + PIPE_REG_ADDRESS_HIGH); - writel(CMD_WRITE_BUFFER + cmd_offset, - dev->base + PIPE_REG_COMMAND); - status = readl(dev->base + PIPE_REG_STATUS); - } + gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL, + dev->base + PIPE_REG_CHANNEL_HIGH); + writel(avail, dev->base + PIPE_REG_SIZE); + gf_write_ptr((void *)phys_addr, dev->base + PIPE_REG_ADDRESS, + dev->base + PIPE_REG_ADDRESS_HIGH); + writel(CMD_WRITE_BUFFER + cmd_offset, + dev->base + PIPE_REG_COMMAND); + status = readl(dev->base + PIPE_REG_STATUS); spin_unlock_irqrestore(&dev->lock, irq_flags); - + put_page(page); if (status > 0) { /* Correct transfer */ ret += status; address += status; -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/