From patchwork Wed Sep 27 13:32:39 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shameerali Kolothum Thodi X-Patchwork-Id: 114371 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp5050533qgf; Wed, 27 Sep 2017 06:35:21 -0700 (PDT) X-Google-Smtp-Source: AOwi7QD5/tC7NLwwyTzU0RnWUoonX0ddMUuKp+oMd4L1sJW/Dbgzi+AasYNIkfoT2KbJQ90TZ9Cf X-Received: by 10.84.217.129 with SMTP id p1mr1292152pli.87.1506519321092; Wed, 27 Sep 2017 06:35:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1506519321; cv=none; d=google.com; s=arc-20160816; b=gI/9eGpx+u3nWaNEkLnB3JrKu29qlXJ4sOozPN0/zmNDWz0gQn+31FFh3aZ8Zq8z84 wNRmgtPzBWOjER42GEjDPthNKKYKZ94fJeYDPDXPyKCb2wvB3EowpAXhgz+a8pvWqg+b fl9FdJZG6rHBZNjQ6J7RzFZ+/wbw3aCudae3RhkRlIyIMv4wOwDuxApX3Q5xhXXH7h8k jDWz45Zj+WwrbQjmuaXxwK83B7dp5Bb4wOAK+jnLiNu8AwhPl6hAN8WmjCGJm2LzFzvk 6Jk/EHeyvvt+HjqiUfpGmntXiu6oFyOYV112lTyVZY1p+a+w3Nyr3xRsHDN3ucuN6GuF l+nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:arc-authentication-results; bh=P0Ei9YHJIJ8q7BYziLaiwZd/ELIrqt8uECRJlvkAqzk=; b=Ulh4W1lm3O4rtShEmnEEkOM/Xo68EBgwZtQ8/4grTK/XtCqBd9q6U1FEITvGR2+BIO 7Nu7Y3g34r7leVfggpIh4V1doQov1eU2nX2sH1vteROMkhWwu9gbPgBl3wIcV1XZZetx MuafybAkzwSppQgMOX2tyt9ZA9LxPKbDH3oaLT3CHRmkZEvaZ/5WbYENFtz7/RsI/Y34 ofwzbOdyK8H/Skavy1f0WLcnFQ1ug9ooUoASTDGYOvF+48z6vDwvvg0upFKzXMlMNLxO 87rnMPoSIUNucxuqSY2crSaMQKwn+rx1mMBYZTiqq8eN0FtjB5+IPYHU2X6F8KzqAPmx fiKw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u9si7660961pge.139.2017.09.27.06.35.20; Wed, 27 Sep 2017 06:35:21 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of devicetree-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 devicetree-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=devicetree-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752835AbdI0NfU (ORCPT + 6 others); Wed, 27 Sep 2017 09:35:20 -0400 Received: from szxga05-in.huawei.com ([45.249.212.191]:7059 "EHLO szxga05-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751959AbdI0NfT (ORCPT ); Wed, 27 Sep 2017 09:35:19 -0400 Received: from 172.30.72.58 (EHLO DGGEMS401-HUB.china.huawei.com) ([172.30.72.58]) by dggrg05-dlp.huawei.com (MOS 4.4.6-GA FastPath queued) with ESMTP id DID21045; Wed, 27 Sep 2017 21:35:16 +0800 (CST) Received: from S00345302A-PC.china.huawei.com (10.203.177.212) by DGGEMS401-HUB.china.huawei.com (10.3.19.201) with Microsoft SMTP Server id 14.3.301.0; Wed, 27 Sep 2017 21:35:08 +0800 From: Shameer Kolothum To: , , , , , , , CC: , , , , , , , , , , Shameer Kolothum Subject: [PATCH v8 3/5] iommu/of: Add msi address regions reservation helper Date: Wed, 27 Sep 2017 14:32:39 +0100 Message-ID: <20170927133241.21036-4-shameerali.kolothum.thodi@huawei.com> X-Mailer: git-send-email 2.12.0.windows.1 In-Reply-To: <20170927133241.21036-1-shameerali.kolothum.thodi@huawei.com> References: <20170927133241.21036-1-shameerali.kolothum.thodi@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.203.177.212] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090202.59CBA914.01C8, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2014-11-16 11:51:01, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 6ecd795c30fff79cfb60a13e0fa29c86 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: John Garry On some platforms msi-controller address regions have to be excluded from normal IOVA allocation in that they are detected and decoded in a HW specific way by system components and so they cannot be considered normal IOVA address space. Add a helper function that retrieves msi address regions through device tree msi mapping, so that these regions will not be translated by IOMMU and will be excluded from IOVA allocations. Signed-off-by: John Garry [Shameer: Modified msi-parent retrieval logic] Signed-off-by: Shameer Kolothum --- drivers/iommu/of_iommu.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of_iommu.h | 10 +++++ 2 files changed, 105 insertions(+) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index e60e3db..ffd7fb7 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -138,6 +139,14 @@ static int of_iommu_xlate(struct device *dev, return ops->of_xlate(dev, iommu_spec); } +static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data) +{ + u32 *rid = data; + + *rid = alias; + return 0; +} + struct of_pci_iommu_alias_info { struct device *dev; struct device_node *np; @@ -163,6 +172,73 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data) return info->np == pdev->bus->dev.of_node; } +static int of_iommu_alloc_resv_region(struct device_node *np, + struct list_head *head) +{ + int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO; + struct iommu_resv_region *region; + struct resource res; + int err; + + err = of_address_to_resource(np, 0, &res); + if (err) + return err; + + region = iommu_alloc_resv_region(res.start, resource_size(&res), + prot, IOMMU_RESV_MSI); + if (!region) + return -ENOMEM; + + list_add_tail(®ion->list, head); + + return 0; +} + +static int of_pci_msi_get_resv_regions(struct device *dev, + struct list_head *head) +{ + struct device_node *msi_np; + struct device *pdev; + u32 rid; + int err, resv = 0; + + pci_for_each_dma_alias(to_pci_dev(dev), __get_pci_rid, &rid); + + for_each_node_with_property(msi_np, "msi-controller") { + for (pdev = dev; pdev; pdev = pdev->parent) { + if (!of_pci_map_rid(pdev->of_node, rid, "msi-map", + "msi-map-mask", &msi_np, NULL)) { + + err = of_iommu_alloc_resv_region(msi_np, head); + if (err) + return err; + resv++; + } + } + } + + return resv; +} + +static int of_platform_msi_get_resv_regions(struct device *dev, + struct list_head *head) +{ + struct of_phandle_args args; + int err, resv = 0; + + while (!of_parse_phandle_with_args(dev->of_node, "msi-parent", + "#msi-cells", resv, &args)) { + + err = of_iommu_alloc_resv_region(args.np, head); + of_node_put(args.np); + if (err) + return err; + resv++; + } + + return resv; +} + const struct iommu_ops *of_iommu_configure(struct device *dev, struct device_node *master_np) { @@ -235,6 +311,25 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, return ops; } +/** + * of_iommu_msi_get_resv_regions - Reserved region driver helper + * @dev: Device from iommu_get_resv_regions() + * @head: Reserved region list from iommu_get_resv_regions() + * + * Returns: Number of reserved regions on success (0 if no associated + * msi parent), appropriate error value otherwise. + */ +int of_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head) +{ + + if (dev_is_pci(dev)) + return of_pci_msi_get_resv_regions(dev, head); + else if (dev->of_node) + return of_platform_msi_get_resv_regions(dev, head); + + return 0; +} + static int __init of_iommu_init(void) { struct device_node *np; diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index 13394ac..9267772 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -14,6 +14,9 @@ extern int of_get_dma_window(struct device_node *dn, const char *prefix, extern const struct iommu_ops *of_iommu_configure(struct device *dev, struct device_node *master_np); +extern int of_iommu_msi_get_resv_regions(struct device *dev, + struct list_head *head); + #else static inline int of_get_dma_window(struct device_node *dn, const char *prefix, @@ -29,6 +32,13 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, return NULL; } +static int of_iommu_msi_get_resv_regions(struct device *dev, + struct list_head *head) +{ + return -ENODEV; +} + + #endif /* CONFIG_OF_IOMMU */ extern struct of_device_id __iommu_of_table;