From patchwork Thu Oct 15 08:30:43 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhen Lei X-Patchwork-Id: 54991 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f197.google.com (mail-lb0-f197.google.com [209.85.217.197]) by patches.linaro.org (Postfix) with ESMTPS id B51FF2301F for ; Thu, 15 Oct 2015 08:45:53 +0000 (UTC) Received: by lbbpc3 with SMTP id pc3sf6770464lbb.2 for ; Thu, 15 Oct 2015 01:45:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:content-type:sender:precedence :list-id:x-original-sender:x-original-authentication-results :mailing-list:list-post:list-help:list-archive:list-unsubscribe; bh=l6M3h3c9E66agd1TmFDbuQk8teC2ASvFeTLBl3v5aRs=; b=AHG8WbAC9sxQC2TFxvaHzHr0d5lQ58ZZvao1eNY2e3dNz8qwZMcp0CEens2fri5MGL kR9BLUKY0nUcNKOSDswopRr3Geo7PuGmuj0frvtzxCUvzcqqTjr7WVQUIUgLrFZpKSBb NLF+9tfD9IQyzzgUYUe9wlJs3Ym39ldd0lncXJ4LTgXUplDqncfuujiCzM54K84AAUZv UvDSp/QOQBws/S5wpw9v9p8MeyygDZwQFB8NBJdF9T74YwUYsZ4zIkbvmTC3BGQYUbLS rkRaRNo7b0f2gdZBS3LeO4hOvuzA96Ho5TVMH1s43zYFHp1LszBhnx0mnWGFjheN9HNQ 2MWA== X-Gm-Message-State: ALoCoQnY0SHwv7+i3NxCd/UFuLoCwjPQI+6clRg67Q2F1XA0domVRJeS1QbW1ZOK6b1NUhmk7/4Y X-Received: by 10.180.10.202 with SMTP id k10mr6613201wib.2.1444898752646; Thu, 15 Oct 2015 01:45:52 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.88.67 with SMTP id m64ls117878lfb.103.gmail; Thu, 15 Oct 2015 01:45:52 -0700 (PDT) X-Received: by 10.112.17.34 with SMTP id l2mr3802417lbd.117.1444898752310; Thu, 15 Oct 2015 01:45:52 -0700 (PDT) Received: from mail-lb0-f175.google.com (mail-lb0-f175.google.com. [209.85.217.175]) by mx.google.com with ESMTPS id h21si8409199lfb.104.2015.10.15.01.45.51 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 15 Oct 2015 01:45:51 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) client-ip=209.85.217.175; Received: by lbwr8 with SMTP id r8so63582790lbw.2 for ; Thu, 15 Oct 2015 01:45:51 -0700 (PDT) X-Received: by 10.112.135.9 with SMTP id po9mr3939592lbb.56.1444898751818; Thu, 15 Oct 2015 01:45:51 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp483192lbq; Thu, 15 Oct 2015 01:45:50 -0700 (PDT) X-Received: by 10.107.46.136 with SMTP id u8mr5461388iou.69.1444898750769; Thu, 15 Oct 2015 01:45:50 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p8si18553252igj.24.2015.10.15.01.45.49; Thu, 15 Oct 2015 01:45:50 -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; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752019AbbJOIpq (ORCPT + 30 others); Thu, 15 Oct 2015 04:45:46 -0400 Received: from szxga03-in.huawei.com ([119.145.14.66]:5035 "EHLO szxga03-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751098AbbJOIpn (ORCPT ); Thu, 15 Oct 2015 04:45:43 -0400 Received: from 172.24.1.50 (EHLO szxeml428-hub.china.huawei.com) ([172.24.1.50]) by szxrg03-dlp.huawei.com (MOS 4.4.3-GA FastPath queued) with ESMTP id BOY18724; Thu, 15 Oct 2015 16:36:23 +0800 (CST) Received: from localhost (10.177.23.164) by szxeml428-hub.china.huawei.com (10.82.67.183) with Microsoft SMTP Server id 14.3.235.1; Thu, 15 Oct 2015 16:36:13 +0800 From: Zhen Lei To: Catalin Marinas , Will Deacon , Joerg Roedel , linux-arm-kernel , iommu , Robin Murphy , Laurent Pinchart , linux-kernel CC: Zefan Li , Xinwei Hu , "Tianhong Ding" , Hanjun Guo , Zhen Lei Subject: [PATCH v4 1/5] iommu/arm-smmu: to support probe deferral Date: Thu, 15 Oct 2015 16:30:43 +0800 Message-ID: <1444897847-18040-2-git-send-email-thunder.leizhen@huawei.com> X-Mailer: git-send-email 1.9.5.msysgit.1 In-Reply-To: <1444897847-18040-1-git-send-email-thunder.leizhen@huawei.com> References: <1444897847-18040-1-git-send-email-thunder.leizhen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.177.23.164] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020205.561F67A3.001C, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-05-26 15:14:31, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 5bee99a35ab0d80f7318b9392ea3bca9 Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: thunder.leizhen@huawei.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.175 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , For pci devices, only the root nodes have "iommus" property. So we should traverse all of its sub nodes in of_xlate. There exists two cases: Case 1: .add_device(sub node) happened before .of_xlate(root node) Case 2: .add_device(sub node) happened after .of_xlate(root node) (1).add_device if (!root->archdata.iommu) return -ENODEV; (2).of_xlate root->archdata.iommu = smmu; /* * Probe the pci devices deferred in phase (1) */ (3).add_device /* * After phase (2), it's not NULL */ if (!root->archdata.iommu) return -ENODEV; __arm_smmu_add_pci_device(pdev, root->archdata.iommu); Signed-off-by: Zhen Lei --- drivers/iommu/arm-smmu-v3.c | 110 +++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 27 deletions(-) -- 2.5.0 -- 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/ diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 5a36ef7..3a54af1 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1742,29 +1743,15 @@ static void __arm_smmu_release_pci_iommudata(void *data) kfree(data); } -static struct arm_smmu_device *arm_smmu_get_for_pci_dev(struct pci_dev *pdev) +static struct device *arm_smmu_get_pci_dev_root(struct pci_dev *pdev) { - struct device_node *of_node; - struct platform_device *smmu_pdev; - struct arm_smmu_device *smmu = NULL; struct pci_bus *bus = pdev->bus; /* Walk up to the root bus */ while (!pci_is_root_bus(bus)) bus = bus->parent; - /* Follow the "iommus" phandle from the host controller */ - of_node = of_parse_phandle(bus->bridge->parent->of_node, "iommus", 0); - if (!of_node) - return NULL; - - /* See if we can find an SMMU corresponding to the phandle */ - smmu_pdev = of_find_device_by_node(of_node); - if (smmu_pdev) - smmu = platform_get_drvdata(smmu_pdev); - - of_node_put(of_node); - return smmu; + return bus->bridge->parent; } static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid) @@ -1777,27 +1764,21 @@ static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid) return sid < limit; } -static int arm_smmu_add_device(struct device *dev) +static int __arm_smmu_add_device(struct device *dev, u32 sid) { int i, ret; - u32 sid, *sids; - struct pci_dev *pdev; + u32 *sids; struct iommu_group *group; struct arm_smmu_group *smmu_group; struct arm_smmu_device *smmu; - /* We only support PCI, for now */ - if (!dev_is_pci(dev)) - return -ENODEV; - - pdev = to_pci_dev(dev); group = iommu_group_get_for_dev(dev); if (IS_ERR(group)) return PTR_ERR(group); smmu_group = iommu_group_get_iommudata(group); if (!smmu_group) { - smmu = arm_smmu_get_for_pci_dev(pdev); + smmu = dev->archdata.iommu; if (!smmu) { ret = -ENOENT; goto out_put_group; @@ -1817,8 +1798,6 @@ static int arm_smmu_add_device(struct device *dev) smmu = smmu_group->smmu; } - /* Assume SID == RID until firmware tells us otherwise */ - pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, &sid); for (i = 0; i < smmu_group->num_sids; ++i) { /* If we already know about this SID, then we're done */ if (smmu_group->sids[i] == sid) @@ -1855,11 +1834,43 @@ static int arm_smmu_add_device(struct device *dev) out_put_group: iommu_group_put(group); + dev_err(dev, "failed to add into SMMU\n"); return ret; } +static int __arm_smmu_add_pci_device(struct pci_dev *pdev, void *smmu) +{ + u32 sid; + struct device *dev = &pdev->dev; + + /* Assume SID == RID until firmware tells us otherwise */ + pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, &sid); + + dev->archdata.iommu = smmu; + + return __arm_smmu_add_device(dev, sid); +} + +static int arm_smmu_add_device(struct device *dev) +{ + struct pci_dev *pdev; + struct device *root; + + /* only support pci devices hotplug */ + if (!dev_is_pci(dev)) + return -ENODEV; + + pdev = to_pci_dev(dev); + root = arm_smmu_get_pci_dev_root(pdev); + if (!root->archdata.iommu) + return -ENODEV; + + return __arm_smmu_add_pci_device(pdev, root->archdata.iommu); +} + static void arm_smmu_remove_device(struct device *dev) { + dev->archdata.iommu = NULL; iommu_group_remove_device(dev); } @@ -1907,7 +1918,49 @@ out_unlock: return ret; } +static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args) +{ + int ret; + struct platform_device *pdev; + struct arm_smmu_device *smmu; + + pdev = of_find_device_by_node(args->np); + if (!pdev) + return -EINVAL; + + smmu = platform_get_drvdata(pdev); + + if (!dev->archdata.iommu) + dev->archdata.iommu = smmu; + + if (dev->archdata.iommu != smmu) { + dev_err(dev, "behinds more than one smmu\n"); + return -EINVAL; + } + + /* We only support PCI, for now */ + if (!dev_is_pci(dev)) { + return -ENODEV; + } else { + struct device *root; + struct pci_dev *pdev = NULL; + + for_each_pci_dev(pdev) { + root = arm_smmu_get_pci_dev_root(pdev); + if (root->of_node != dev->of_node) + continue; + + ret = __arm_smmu_add_pci_device(pdev, smmu); + if (ret) + return ret; + } + } + + return 0; +} + static struct iommu_ops arm_smmu_ops = { + .of_xlate = arm_smmu_of_xlate, .capable = arm_smmu_capable, .domain_alloc = arm_smmu_domain_alloc, .domain_free = arm_smmu_domain_free, @@ -2687,6 +2740,7 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev) /* Record our private device structure */ platform_set_drvdata(pdev, smmu); + of_iommu_set_ops(smmu->dev->of_node, &arm_smmu_ops); /* Reset the device */ ret = arm_smmu_device_reset(smmu); @@ -2750,6 +2804,8 @@ static void __exit arm_smmu_exit(void) subsys_initcall(arm_smmu_init); module_exit(arm_smmu_exit); +IOMMU_OF_DECLARE(arm_smmu_v3, "arm,smmu-v3", NULL); + MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); MODULE_AUTHOR("Will Deacon "); MODULE_LICENSE("GPL v2");