Received: by 2002:a25:6193:0:0:0:0:0 with SMTP id v141csp3935382ybb; Mon, 23 Mar 2020 10:21:46 -0700 (PDT) X-Google-Smtp-Source: ADFU+vuxgugb04cPptbIYBVxiURUJ5OwvJIa1L+0M+vnxJwAJQL82iQn0vitGd3uLWJCrwOlFr/o X-Received: by 2002:a05:6830:1610:: with SMTP id g16mr6128623otr.358.1584984106003; Mon, 23 Mar 2020 10:21:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1584984105; cv=none; d=google.com; s=arc-20160816; b=SnlEMZlKfqBsKG2kvT33uglVfV975tWQ7+1qPldCYGardiCTMD351DX6GBTaaAyst2 Kc7EDeEaer1cNFyCMJVNtiHd9f/lW1Zvi+iYeT4daCSZEEtliRoHQj9d1qajXRXg7HWN PhDdtRTtkxExfZAWib0ROnAIbXNPVF09tpJPM1IaKwv7Mu00K1gvqYbJtVHUsf3VoWml d1dkvRuaUaTlRUJlSeeuoPCbD4ogedH/EbMu8JOlIYUqH2Jo4b8ztp7oKEXokF0WEVw6 Y0PoBIdZI20klo9wTUTYbRb48JWV0DYL4FOWGU/uKxHGXi/uIubC2rqkmTEKEZ0uDQYz mM5Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=S4MCNikQ5i0434+cYvqE/DVdvbba7XoRQQa2vfF8NPo=; b=k3h4hguDR9QwoJcYj5Y8cdh+GJJmli727FTC8fIFG1juus6zu0IG9HthOKeMRXtScJ K0G7OvNTrqH7T9lYCjv02XHaEJ4ZHp3tf2DPkIqVgN5CNW4sfb2cPhP1ZLTIFhT3jLjf MlHz1g62tiBWuYwpvEUqdv4ibY9vZs+EztZOLx8swX2RuOWGKU0fWXIBeM8IhzyR5ST8 xAUVgfCB0rk090Krju2Gv7ZBZzqfw3BxSRZAGlNyBs6VkZQQMcpxcqpue+EDvRU+13Uu supHNcHdVS63ID4Jh1Sp+oGbGSl3R550/+E85YhOBf6gLlFsUexFCoudL4N4w9uL323D SNeQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z10si8144827otq.214.2020.03.23.10.21.30; Mon, 23 Mar 2020 10:21:45 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=nxp.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727718AbgCWRTf (ORCPT + 99 others); Mon, 23 Mar 2020 13:19:35 -0400 Received: from inva020.nxp.com ([92.121.34.13]:50604 "EHLO inva020.nxp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727915AbgCWRTe (ORCPT ); Mon, 23 Mar 2020 13:19:34 -0400 Received: from inva020.nxp.com (localhost [127.0.0.1]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id 0A0CE1A18A0; Mon, 23 Mar 2020 18:19:32 +0100 (CET) Received: from inva024.eu-rdc02.nxp.com (inva024.eu-rdc02.nxp.com [134.27.226.22]) by inva020.eu-rdc02.nxp.com (Postfix) with ESMTP id F189B1A14C9; Mon, 23 Mar 2020 18:19:31 +0100 (CET) Received: from fsr-ub1864-111.ea.freescale.net (fsr-ub1864-111.ea.freescale.net [10.171.82.141]) by inva024.eu-rdc02.nxp.com (Postfix) with ESMTP id 7E2742035C; Mon, 23 Mar 2020 18:19:31 +0100 (CET) From: Diana Craciun To: kvm@vger.kernel.org, alex.williamson@redhat.com, laurentiu.tudor@nxp.com, linux-arm-kernel@lists.infradead.org, bharatb.yadav@gmail.com Cc: linux-kernel@vger.kernel.org, Diana Craciun , Bharat Bhushan Subject: [PATCH 9/9] vfio/fsl-mc: Add read/write support for fsl-mc devices Date: Mon, 23 Mar 2020 19:19:11 +0200 Message-Id: <20200323171911.27178-10-diana.craciun@oss.nxp.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200323171911.27178-1-diana.craciun@oss.nxp.com> References: <20200323171911.27178-1-diana.craciun@oss.nxp.com> X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Diana Craciun The software uses a memory-mapped I/O command interface (MC portals) to communicate with the MC hardware. This command interface is used to discover, enumerate, configure and remove DPAA2 objects. The DPAA2 objects use MSIs, so the command interface needs to be emulated such that the correct MSI is configured in the hardware (the guest has the virtual MSIs). This patch is adding read/write support for fsl-mc devices. The mc commands are emulated by the userspace. The host is just passing the correct command to the hardware. Also the current patch limits userspace to write complete 64byte command once and read 64byte response by one ioctl. Signed-off-by: Bharat Bhushan Signed-off-by: Diana Craciun --- drivers/vfio/fsl-mc/vfio_fsl_mc.c | 122 +++++++++++++++++++++- drivers/vfio/fsl-mc/vfio_fsl_mc_private.h | 1 + 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc.c b/drivers/vfio/fsl-mc/vfio_fsl_mc.c index ceb9d6b06624..107b4ab7b2d8 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc.c +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "vfio_fsl_mc_private.h" @@ -114,6 +115,11 @@ static int vfio_fsl_mc_regions_init(struct vfio_fsl_mc_device *vdev) static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev) { + int i; + + for (i = 0; i < vdev->num_regions; i++) + iounmap(vdev->regions[i].ioaddr); + vdev->num_regions = 0; kfree(vdev->regions); } @@ -307,13 +313,125 @@ static long vfio_fsl_mc_ioctl(void *device_data, unsigned int cmd, static ssize_t vfio_fsl_mc_read(void *device_data, char __user *buf, size_t count, loff_t *ppos) { - return -EINVAL; + struct vfio_fsl_mc_device *vdev = device_data; + unsigned int index = VFIO_FSL_MC_OFFSET_TO_INDEX(*ppos); + loff_t off = *ppos & VFIO_FSL_MC_OFFSET_MASK; + struct vfio_fsl_mc_region *region; + u64 data[8]; + int i; + + /* Read ioctl supported only for DPRC and DPMCP device */ + if (strcmp(vdev->mc_dev->obj_desc.type, "dprc") && + strcmp(vdev->mc_dev->obj_desc.type, "dpmcp")) + return -EINVAL; + + if (index >= vdev->num_regions) + return -EINVAL; + + region = &vdev->regions[index]; + + if (!(region->flags & VFIO_REGION_INFO_FLAG_READ)) + return -EINVAL; + + if (!region->ioaddr) { + region->ioaddr = ioremap(region->addr, region->size); + if (!region->ioaddr) + return -ENOMEM; + } + + if (count != 64 || off != 0) + return -EINVAL; + + for (i = 7; i >= 0; i--) + data[i] = readq(region->ioaddr + i * sizeof(uint64_t)); + + if (copy_to_user(buf, data, 64)) + return -EFAULT; + + return count; +} + +#define MC_CMD_COMPLETION_TIMEOUT_MS 5000 +#define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS 500 + +static int vfio_fsl_mc_send_command(void __iomem *ioaddr, uint64_t *cmd_data) +{ + int i; + enum mc_cmd_status status; + unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000; + + /* Write at command parameter into portal */ + for (i = 7; i >= 1; i--) + writeq_relaxed(cmd_data[i], ioaddr + i * sizeof(uint64_t)); + + /* Write command header in the end */ + writeq(cmd_data[0], ioaddr); + + /* Wait for response before returning to user-space + * This can be optimized in future to even prepare response + * before returning to user-space and avoid read ioctl. + */ + for (;;) { + u64 header; + struct mc_cmd_header *resp_hdr; + + header = cpu_to_le64(readq_relaxed(ioaddr)); + + resp_hdr = (struct mc_cmd_header *)&header; + status = (enum mc_cmd_status)resp_hdr->status; + if (status != MC_CMD_STATUS_READY) + break; + + udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS); + timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS; + if (timeout_usecs == 0) + return -ETIMEDOUT; + } + + return 0; } static ssize_t vfio_fsl_mc_write(void *device_data, const char __user *buf, size_t count, loff_t *ppos) { - return -EINVAL; + struct vfio_fsl_mc_device *vdev = device_data; + unsigned int index = VFIO_FSL_MC_OFFSET_TO_INDEX(*ppos); + loff_t off = *ppos & VFIO_FSL_MC_OFFSET_MASK; + struct vfio_fsl_mc_region *region; + u64 data[8]; + int ret; + + /* Write ioctl supported only for DPRC and DPMCP device */ + if (strcmp(vdev->mc_dev->obj_desc.type, "dprc") && + strcmp(vdev->mc_dev->obj_desc.type, "dpmcp")) + return -EINVAL; + + if (index >= vdev->num_regions) + return -EINVAL; + + region = &vdev->regions[index]; + + if (!(region->flags & VFIO_REGION_INFO_FLAG_WRITE)) + return -EINVAL; + + if (!region->ioaddr) { + region->ioaddr = ioremap(region->addr, region->size); + if (!region->ioaddr) + return -ENOMEM; + } + + if (count != 64 || off != 0) + return -EINVAL; + + if (copy_from_user(&data, buf, 64)) + return -EFAULT; + + ret = vfio_fsl_mc_send_command(region->ioaddr, data); + if (ret) + return ret; + + return count; + } static int vfio_fsl_mc_mmap_mmio(struct vfio_fsl_mc_region region, diff --git a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h index cac0b205c3d4..70824c4b10d6 100644 --- a/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h +++ b/drivers/vfio/fsl-mc/vfio_fsl_mc_private.h @@ -34,6 +34,7 @@ struct vfio_fsl_mc_region { u32 type; u64 addr; resource_size_t size; + void __iomem *ioaddr; }; struct vfio_fsl_mc_device { -- 2.17.1