Message ID | 20230104125725.271850-11-baolu.lu@linux.intel.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4e01:0:0:0:0:0 with SMTP id p1csp5133980wrt; Wed, 4 Jan 2023 05:09:13 -0800 (PST) X-Google-Smtp-Source: AMrXdXu0tODM+uAg//1ENt5H/2qIv9psbkLgF1mZiBpbDUwLChYcOOgxTLUsiBi8n3+Oyntcrj8K X-Received: by 2002:a17:90a:5d08:b0:219:4578:6409 with SMTP id s8-20020a17090a5d0800b0021945786409mr51264392pji.41.1672837753444; Wed, 04 Jan 2023 05:09:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1672837753; cv=none; d=google.com; s=arc-20160816; b=vv6gdk5T4GU6XwxabH9Nmo6i6/YJGsevZFrNMHYz+D5STf6OdamRdNbaHQ3RyZgPD6 AMHhoGqpu0ViZFV76PJeBl2WzqGikHD5ZNeQym0OVAW3/68IF0ffIUZC8yC2uNV9KxFg Hiy0XoQIosM80ActsEiBdynsZzRXuh6mDM5NWL6MOQmv0LABw7OGOVrD3f4lTk4CjIPF f0rdnIF4om7RkSmQVHHl4Cz8w9kQaWbGQpl/ZBn/TVnMnorkCJU2sU7KuZxyCh0whS1r QljCLjffsYjajBdePqfDoE6LjnXx5AxL/sCUno+TbCWmZQQCulsfYPyL4i2+HTGfr90C ciCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=5VH2S4nI3FNargaYEhSNXwqpoV08iAbdsxF7HU55tvQ=; b=YvWVOs8Mtfk4wn1bwnGQj+GYFUSGmj5VNn4Z6zx2SjBaba23eLxcPiCgmtOmcUGloQ RW/VhOjdrCfsdsSAbFJt0E1aYVJl6UJ7R/FdlgscPmtxtVkUYRfB7K37ZCeQcnCcLQbG NgyQzZ/eDZuz+mJC6fa/gE1mwicaq8xaFs9dA/ybJ3axNSqFxIe6umZtHtxBmb+gd4JK 3njwRaqmbswAPjwgNKWhXWpu6VhxXfUaY5DjlcTwGjRYdzzH0/wTxHuIcQL9Ha4162Ni weniIq1AA+7tIpAL9K2/V/VtiOK6ivSLOmK2E8eCoyIC+hw9KLtEn34mCHVA1xM0THP8 bc1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=lWpQjES+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id i21-20020a17090adc1500b00223b1092804si37670603pjv.163.2023.01.04.05.08.50; Wed, 04 Jan 2023 05:09:13 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=lWpQjES+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239305AbjADNH2 (ORCPT <rfc822;tmhikaru@gmail.com> + 99 others); Wed, 4 Jan 2023 08:07:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239294AbjADNGu (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Wed, 4 Jan 2023 08:06:50 -0500 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 097F7E45 for <linux-kernel@vger.kernel.org>; Wed, 4 Jan 2023 05:06:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1672837588; x=1704373588; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=1DSM4fHz5l5HcYyLuKZ27aWJHPiNFSeHrlfd99N8Mho=; b=lWpQjES+ZHcguUi0H5ibzy0IZwpUPiM6OBjo6PAjrR63okVYveqfZpR0 J8mNPR9HCid+Kko/ihZS33gw+YpdHZ9fV+zBdnHC1ce5DxUd2XIyCORza MjxgGDopdPxmAGe25JijzpniQBbleqd3xYnMryUYIHkltm0nK3c8V5/qF ssO1xojZa6Uoty7Vqn9jronKGjA4KJs2AVgtJWPre8FtX0gJVhlv4mpdL QMdaC06BKF0anrF6KyA+nCP0uKrio5zRAYd0bMIzyzKnxIoKanoV0wzD8 Qq7BcAY9Y+/XInH+xQ+FoUrvrhsX1N3NEJFC1yiyO5Xp7LPBd59lCdrU5 w==; X-IronPort-AV: E=McAfee;i="6500,9779,10579"; a="320639955" X-IronPort-AV: E=Sophos;i="5.96,299,1665471600"; d="scan'208";a="320639955" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 04 Jan 2023 05:06:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10579"; a="797529106" X-IronPort-AV: E=Sophos;i="5.96,299,1665471600"; d="scan'208";a="797529106" Received: from allen-box.sh.intel.com ([10.239.159.48]) by fmsmga001.fm.intel.com with ESMTP; 04 Jan 2023 05:06:21 -0800 From: Lu Baolu <baolu.lu@linux.intel.com> To: Joerg Roedel <joro@8bytes.org>, Jason Gunthorpe <jgg@nvidia.com>, Christoph Hellwig <hch@infradead.org>, Kevin Tian <kevin.tian@intel.com>, Will Deacon <will@kernel.org>, Robin Murphy <robin.murphy@arm.com>, Jean-Philippe Brucker <jean-philippe@linaro.org> Cc: Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>, Hector Martin <marcan@marcan.st>, Sven Peter <sven@svenpeter.dev>, Rob Clark <robdclark@gmail.com>, Marek Szyprowski <m.szyprowski@samsung.com>, Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, Andy Gross <agross@kernel.org>, Bjorn Andersson <andersson@kernel.org>, Yong Wu <yong.wu@mediatek.com>, Matthias Brugger <matthias.bgg@gmail.com>, Heiko Stuebner <heiko@sntech.de>, Matthew Rosato <mjrosato@linux.ibm.com>, Orson Zhai <orsonzhai@gmail.com>, Baolin Wang <baolin.wang@linux.alibaba.com>, Chunyan Zhang <zhang.lyra@gmail.com>, Chen-Yu Tsai <wens@csie.org>, Thierry Reding <thierry.reding@gmail.com>, iommu@lists.linux.dev, linux-kernel@vger.kernel.org, Lu Baolu <baolu.lu@linux.intel.com> Subject: [PATCH v4 10/19] iommu: Add set_platform_dma_ops iommu ops Date: Wed, 4 Jan 2023 20:57:16 +0800 Message-Id: <20230104125725.271850-11-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230104125725.271850-1-baolu.lu@linux.intel.com> References: <20230104125725.271850-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.3 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1754097520453765468?= X-GMAIL-MSGID: =?utf-8?q?1754097520453765468?= |
Series |
iommu: Retire detach_dev callback
|
|
Commit Message
Baolu Lu
Jan. 4, 2023, 12:57 p.m. UTC
When VFIO finishes assigning a device to user space and calls iommu_group_release_dma_owner() to return the device to kernel, the IOMMU core will attach the default domain to the device. Unfortunately, some IOMMU drivers don't support default domain, hence in the end, the core calls .detach_dev instead. This adds set_platform_dma_ops iommu ops to make it clear that what it does is returning control back to the platform DMA ops. Suggested-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> --- include/linux/iommu.h | 4 ++++ drivers/iommu/iommu.c | 23 +++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-)
Comments
On Wed, Jan 04, 2023 at 08:57:16PM +0800, Lu Baolu wrote: > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > index de91dd88705b..4e35a9f94873 100644 > --- a/drivers/iommu/iommu.c > +++ b/drivers/iommu/iommu.c > @@ -2163,6 +2163,17 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) > return 0; > } > > +static int iommu_group_do_set_platform_dma(struct device *dev, void *data) > +{ > + const struct iommu_ops *ops = dev_iommu_ops(dev); > + > + if (!ops->set_platform_dma_ops) > + return -EINVAL; > + > + ops->set_platform_dma_ops(dev); > + return 0; > +} > + > static int __iommu_group_set_domain(struct iommu_group *group, > struct iommu_domain *new_domain) > { > @@ -2177,10 +2188,14 @@ static int __iommu_group_set_domain(struct iommu_group *group, > * platform specific behavior. > */ > if (!new_domain) { > - if (WARN_ON(!group->domain->ops->detach_dev)) > - return -EINVAL; This should still have the WARN_ON.. if (WARN_ON(!group->domain->ops->detach_dev && !dev_iommu_ops(dev)->set_platform_dma_ops) Jason
Hi Jason, On 2023/1/4 21:17, Jason Gunthorpe wrote: > On Wed, Jan 04, 2023 at 08:57:16PM +0800, Lu Baolu wrote: > >> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c >> index de91dd88705b..4e35a9f94873 100644 >> --- a/drivers/iommu/iommu.c >> +++ b/drivers/iommu/iommu.c >> @@ -2163,6 +2163,17 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) >> return 0; >> } >> >> +static int iommu_group_do_set_platform_dma(struct device *dev, void *data) >> +{ >> + const struct iommu_ops *ops = dev_iommu_ops(dev); >> + >> + if (!ops->set_platform_dma_ops) >> + return -EINVAL; >> + >> + ops->set_platform_dma_ops(dev); >> + return 0; >> +} >> + >> static int __iommu_group_set_domain(struct iommu_group *group, >> struct iommu_domain *new_domain) >> { >> @@ -2177,10 +2188,14 @@ static int __iommu_group_set_domain(struct iommu_group *group, >> * platform specific behavior. >> */ >> if (!new_domain) { >> - if (WARN_ON(!group->domain->ops->detach_dev)) >> - return -EINVAL; > This should still have the WARN_ON.. > > if (WARN_ON(!group->domain->ops->detach_dev && !dev_iommu_ops(dev)->set_platform_dma_ops) This has been implicitly included in the code. iommu_group_do_set_platform_dma() returns -EINVAL if the iommu driver doesn't support set_platform_dma_ops (otherwise always return success). Then, the domain->ops->detach_dev is required and a WARN_ON was there. if (!new_domain) { ret = __iommu_group_for_each_dev(group, NULL, iommu_group_do_set_platform_dma); if (ret) { if (WARN_ON(!group->domain->ops->detach_dev)) return -EINVAL; __iommu_group_for_each_dev(group, group->domain, iommu_group_do_detach_device); } group->domain = NULL; return 0; } Perhaps I should add a comment to explain this? -- Best regards, baolu
On Thu, Jan 05, 2023 at 01:58:42PM +0800, Baolu Lu wrote: > Hi Jason, > > On 2023/1/4 21:17, Jason Gunthorpe wrote: > > On Wed, Jan 04, 2023 at 08:57:16PM +0800, Lu Baolu wrote: > > > > > diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c > > > index de91dd88705b..4e35a9f94873 100644 > > > --- a/drivers/iommu/iommu.c > > > +++ b/drivers/iommu/iommu.c > > > @@ -2163,6 +2163,17 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) > > > return 0; > > > } > > > +static int iommu_group_do_set_platform_dma(struct device *dev, void *data) > > > +{ > > > + const struct iommu_ops *ops = dev_iommu_ops(dev); > > > + > > > + if (!ops->set_platform_dma_ops) > > > + return -EINVAL; > > > + > > > + ops->set_platform_dma_ops(dev); > > > + return 0; > > > +} > > > + > > > static int __iommu_group_set_domain(struct iommu_group *group, > > > struct iommu_domain *new_domain) > > > { > > > @@ -2177,10 +2188,14 @@ static int __iommu_group_set_domain(struct iommu_group *group, > > > * platform specific behavior. > > > */ > > > if (!new_domain) { > > > - if (WARN_ON(!group->domain->ops->detach_dev)) > > > - return -EINVAL; > > This should still have the WARN_ON.. > > > > if (WARN_ON(!group->domain->ops->detach_dev && !dev_iommu_ops(dev)->set_platform_dma_ops) > > This has been implicitly included in the code. > > iommu_group_do_set_platform_dma() returns -EINVAL if the iommu driver > doesn't support set_platform_dma_ops (otherwise always return success). > Then, the domain->ops->detach_dev is required and a WARN_ON was there. > > if (!new_domain) { > ret = __iommu_group_for_each_dev(group, NULL, > iommu_group_do_set_platform_dma); > if (ret) { > if (WARN_ON(!group->domain->ops->detach_dev)) > return -EINVAL; > __iommu_group_for_each_dev(group, group->domain, > iommu_group_do_detach_device); > } > group->domain = NULL; > return 0; > } > > Perhaps I should add a comment to explain this? But you delete this later when you remove this. I think testing the op directly is much clearer, get rid of the whole ret and EINVAL thinig: if (dev_iommu_ops(dev)->set_platform_dma_ops) __iommu_group_for_each_dev(group, NULL, iommu_group_do_set_platform_dma); // Can't fail! else if (group->domain->ops->detach_dev) __iommu_group_for_each_dev(group, group->domain, iommu_group_do_detach_device); else WARN(true) Jason
On 1/5/23 9:15 PM, Jason Gunthorpe wrote: > On Thu, Jan 05, 2023 at 01:58:42PM +0800, Baolu Lu wrote: >> Hi Jason, >> >> On 2023/1/4 21:17, Jason Gunthorpe wrote: >>> On Wed, Jan 04, 2023 at 08:57:16PM +0800, Lu Baolu wrote: >>> >>>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c >>>> index de91dd88705b..4e35a9f94873 100644 >>>> --- a/drivers/iommu/iommu.c >>>> +++ b/drivers/iommu/iommu.c >>>> @@ -2163,6 +2163,17 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) >>>> return 0; >>>> } >>>> +static int iommu_group_do_set_platform_dma(struct device *dev, void *data) >>>> +{ >>>> + const struct iommu_ops *ops = dev_iommu_ops(dev); >>>> + >>>> + if (!ops->set_platform_dma_ops) >>>> + return -EINVAL; >>>> + >>>> + ops->set_platform_dma_ops(dev); >>>> + return 0; >>>> +} >>>> + >>>> static int __iommu_group_set_domain(struct iommu_group *group, >>>> struct iommu_domain *new_domain) >>>> { >>>> @@ -2177,10 +2188,14 @@ static int __iommu_group_set_domain(struct iommu_group *group, >>>> * platform specific behavior. >>>> */ >>>> if (!new_domain) { >>>> - if (WARN_ON(!group->domain->ops->detach_dev)) >>>> - return -EINVAL; >>> This should still have the WARN_ON.. >>> >>> if (WARN_ON(!group->domain->ops->detach_dev && !dev_iommu_ops(dev)->set_platform_dma_ops) >> This has been implicitly included in the code. >> >> iommu_group_do_set_platform_dma() returns -EINVAL if the iommu driver >> doesn't support set_platform_dma_ops (otherwise always return success). >> Then, the domain->ops->detach_dev is required and a WARN_ON was there. >> >> if (!new_domain) { >> ret = __iommu_group_for_each_dev(group, NULL, >> iommu_group_do_set_platform_dma); >> if (ret) { >> if (WARN_ON(!group->domain->ops->detach_dev)) >> return -EINVAL; >> __iommu_group_for_each_dev(group, group->domain, >> iommu_group_do_detach_device); >> } >> group->domain = NULL; >> return 0; >> } >> >> Perhaps I should add a comment to explain this? > But you delete this later when you remove this. > > I think testing the op directly is much clearer, get rid of the whole > ret and EINVAL thinig: > > if (dev_iommu_ops(dev)->set_platform_dma_ops) > __iommu_group_for_each_dev(group, NULL, > iommu_group_do_set_platform_dma); // Can't fail! > else if (group->domain->ops->detach_dev) > __iommu_group_for_each_dev(group, group->domain, > iommu_group_do_detach_device); > else > WARN(true) Above looks good to me. Thanks! I have updated this part of code like below: @@ -2177,10 +2188,20 @@ static int __iommu_group_set_domain(struct iommu_group *group, * platform specific behavior. */ if (!new_domain) { - if (WARN_ON(!group->domain->ops->detach_dev)) - return -EINVAL; - __iommu_group_for_each_dev(group, group->domain, - iommu_group_do_detach_device); + struct group_device *grp_dev; + + grp_dev = list_first_entry(&group->devices, + struct group_device, list); + + if (dev_iommu_ops(grp_dev->dev)->set_platform_dma_ops) + __iommu_group_for_each_dev(group, NULL, + iommu_group_do_set_platform_dma); + else if (group->domain->ops->detach_dev) + __iommu_group_for_each_dev(group, group->domain, + iommu_group_do_detach_device); + else + WARN_ON_ONCE(1); + group->domain = NULL; return 0; } -- Best regards, baolu
On Fri, Jan 06, 2023 at 02:07:32PM +0800, Baolu Lu wrote: > Above looks good to me. Thanks! I have updated this part of code like > below: > > @@ -2177,10 +2188,20 @@ static int __iommu_group_set_domain(struct > iommu_group *group, > * platform specific behavior. > */ > if (!new_domain) { > - if (WARN_ON(!group->domain->ops->detach_dev)) > - return -EINVAL; > - __iommu_group_for_each_dev(group, group->domain, > - iommu_group_do_detach_device); > + struct group_device *grp_dev; > + > + grp_dev = list_first_entry(&group->devices, > + struct group_device, list); It seems OK - I hope we naturally can't ever get in a situation where a group has disjoint iommu drivers. Jason
On 1/6/2023 10:26 PM, Jason Gunthorpe wrote: > On Fri, Jan 06, 2023 at 02:07:32PM +0800, Baolu Lu wrote: > >> Above looks good to me. Thanks! I have updated this part of code like >> below: >> >> @@ -2177,10 +2188,20 @@ static int __iommu_group_set_domain(struct >> iommu_group *group, >> * platform specific behavior. >> */ >> if (!new_domain) { >> - if (WARN_ON(!group->domain->ops->detach_dev)) >> - return -EINVAL; >> - __iommu_group_for_each_dev(group, group->domain, >> - iommu_group_do_detach_device); >> + struct group_device *grp_dev; >> + >> + grp_dev = list_first_entry(&group->devices, >> + struct group_device, list); > It seems OK - I hope we naturally can't ever get in a situation where > a group has disjoint iommu drivers. The final code after cleanup looks like below. We will WARN_ON the lack of callback in the iommu_group_do_set_platform_dma() helper. 2152 static int iommu_group_do_set_platform_dma(struct device *dev, void *data) 2153 { 2154 const struct iommu_ops *ops = dev_iommu_ops(dev); 2155 2156 if (!WARN_ON(!ops->set_platform_dma_ops)) 2157 ops->set_platform_dma_ops(dev); 2158 2159 return 0; 2160 } 2161 2162 static int __iommu_group_set_domain(struct iommu_group *group, 2163 struct iommu_domain *new_domain) 2164 { 2165 int ret; 2166 2167 if (group->domain == new_domain) 2168 return 0; 2169 2170 /* 2171 * New drivers should support default domains, so set_platform_dma() 2172 * op will never be called. Otherwise the NULL domain represents some 2173 * platform specific behavior. 2174 */ 2175 if (!new_domain) { 2176 __iommu_group_for_each_dev(group, NULL, 2177 iommu_group_do_set_platform_dma); 2178 group->domain = NULL; 2179 return 0; 2180 } How do you like this? -- Best regards, baolu
On Sat, Jan 07, 2023 at 10:48:31AM +0800, Baolu Lu wrote: > On 1/6/2023 10:26 PM, Jason Gunthorpe wrote: > > On Fri, Jan 06, 2023 at 02:07:32PM +0800, Baolu Lu wrote: > > > > > Above looks good to me. Thanks! I have updated this part of code like > > > below: > > > > > > @@ -2177,10 +2188,20 @@ static int __iommu_group_set_domain(struct > > > iommu_group *group, > > > * platform specific behavior. > > > */ > > > if (!new_domain) { > > > - if (WARN_ON(!group->domain->ops->detach_dev)) > > > - return -EINVAL; > > > - __iommu_group_for_each_dev(group, group->domain, > > > - iommu_group_do_detach_device); > > > + struct group_device *grp_dev; > > > + > > > + grp_dev = list_first_entry(&group->devices, > > > + struct group_device, list); > > It seems OK - I hope we naturally can't ever get in a situation where > > a group has disjoint iommu drivers. > > The final code after cleanup looks like below. We will WARN_ON the lack > of callback in the iommu_group_do_set_platform_dma() helper. Yeah OK Jason
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 46e1347bfa22..7b3e3775b069 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -228,6 +228,9 @@ struct iommu_iotlb_gather { * @release_device: Remove device from iommu driver handling * @probe_finalize: Do final setup work after the device is added to an IOMMU * group and attached to the groups domain + * @set_platform_dma_ops: Returning control back to the platform DMA ops. This op + * is to support old IOMMU drivers, new drivers should use + * default domains, and the common IOMMU DMA ops. * @device_group: find iommu group for a particular device * @get_resv_regions: Request list of reserved regions for a device * @of_xlate: add OF master IDs to iommu grouping @@ -256,6 +259,7 @@ struct iommu_ops { struct iommu_device *(*probe_device)(struct device *dev); void (*release_device)(struct device *dev); void (*probe_finalize)(struct device *dev); + void (*set_platform_dma_ops)(struct device *dev); struct iommu_group *(*device_group)(struct device *dev); /* Request/Free a list of reserved regions for a device */ diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index de91dd88705b..4e35a9f94873 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2163,6 +2163,17 @@ static int iommu_group_do_detach_device(struct device *dev, void *data) return 0; } +static int iommu_group_do_set_platform_dma(struct device *dev, void *data) +{ + const struct iommu_ops *ops = dev_iommu_ops(dev); + + if (!ops->set_platform_dma_ops) + return -EINVAL; + + ops->set_platform_dma_ops(dev); + return 0; +} + static int __iommu_group_set_domain(struct iommu_group *group, struct iommu_domain *new_domain) { @@ -2177,10 +2188,14 @@ static int __iommu_group_set_domain(struct iommu_group *group, * platform specific behavior. */ if (!new_domain) { - if (WARN_ON(!group->domain->ops->detach_dev)) - return -EINVAL; - __iommu_group_for_each_dev(group, group->domain, - iommu_group_do_detach_device); + ret = __iommu_group_for_each_dev(group, NULL, + iommu_group_do_set_platform_dma); + if (ret) { + if (WARN_ON(!group->domain->ops->detach_dev)) + return -EINVAL; + __iommu_group_for_each_dev(group, group->domain, + iommu_group_do_detach_device); + } group->domain = NULL; return 0; }