From nobody Fri Sep 12 06:30:11 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1191FC636CC for ; Mon, 13 Feb 2023 07:58:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229603AbjBMH6W (ORCPT ); Mon, 13 Feb 2023 02:58:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46690 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229939AbjBMH6S (ORCPT ); Mon, 13 Feb 2023 02:58:18 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 68DA4125A5 for ; Sun, 12 Feb 2023 23:58:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1676275096; x=1707811096; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=2Rrie2bPqPi5V+Iz3CI03igARGPvTfvHLhvvVc+LOMs=; b=GoCPvHYsNojra/bYA3NVeNo5Yo/qftY+vxrdrpIH3yv25svsRcxr6uSz glq1zNSDZn+bzPqP5fngLpuBiPwRk2loSNlB4e2TCcz+jVs1etmzvYxJP kKYJq1GyE4+IPLAh0sHQvVKHnMScPOoik040buaUwRl6bgQeV9uH9UFvJ sGTUR+yDMbaOK0e4eXNxLQYqLDp3+beEufyTRrCH9Nzv3Ld1ZwRtOGFvl 7wt+Y7ssKJlHH+w4nuvh25TPjtwMshNA5KmLRFjcJS8mjEnMAMbu0F41/ k7xkbB57xlvrXgNVs/2vHImb0ILMHPWRqeFxKfvMJefD3pf/fStPerdcH A==; X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="417058757" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="417058757" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Feb 2023 23:58:16 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="842684803" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="842684803" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga005.jf.intel.com with ESMTP; 12 Feb 2023 23:58:13 -0800 From: Lu Baolu To: iommu@lists.linux.dev Cc: Joerg Roedel , Jason Gunthorpe , Christoph Hellwig , Kevin Tian , Will Deacon , Robin Murphy , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH 1/4] iommu: Add dev_iommu->ops_rwsem Date: Mon, 13 Feb 2023 15:49:38 +0800 Message-Id: <20230213074941.919324-2-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230213074941.919324-1-baolu.lu@linux.intel.com> References: <20230213074941.919324-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a RW semaphore to make sure that iommu_ops of a device is consistent in any non-driver-oriented path, such as a store operation on the iommu group sysfs node. Add a pair of helpers to freeze and unfreeze the iommu ops of all devices in an iommu group, and use them in iommu_group_store_type(). Signed-off-by: Lu Baolu --- include/linux/iommu.h | 3 +++ drivers/iommu/iommu.c | 53 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 3589d1b8f922..a4204e1bfef3 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -402,6 +402,8 @@ struct iommu_fault_param { * @fwspec: IOMMU fwspec data * @iommu_dev: IOMMU device this device is linked to * @priv: IOMMU Driver private data + * @ops_rwsem: RW semaphore to synchronize between device release + * path and the sysfs interfaces. * @max_pasids: number of PASIDs this device can consume * @attach_deferred: the dma domain attachment is deferred * @@ -415,6 +417,7 @@ struct dev_iommu { struct iommu_fwspec *fwspec; struct iommu_device *iommu_dev; void *priv; + struct rw_semaphore ops_rwsem; u32 max_pasids; u32 attach_deferred:1; }; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 5f1dc9aaba52..4f71dcd2621b 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -267,6 +267,7 @@ static struct dev_iommu *dev_iommu_get(struct device *d= ev) return NULL; =20 mutex_init(¶m->lock); + init_rwsem(¶m->ops_rwsem); dev->iommu =3D param; return param; } @@ -461,12 +462,19 @@ void iommu_release_device(struct device *dev) =20 iommu_device_unlink(dev->iommu->iommu_dev, dev); =20 + /* + * The device's iommu_ops will be released in .release_device + * callback. Hold ops_rwsem to avoid use after release. + */ + down_write(&dev->iommu->ops_rwsem); ops =3D dev_iommu_ops(dev); if (ops->release_device) ops->release_device(dev); + module_put(ops->owner); + dev->iommu->iommu_dev =3D NULL; + up_write(&dev->iommu->ops_rwsem); =20 iommu_group_remove_device(dev); - module_put(ops->owner); dev_iommu_free(dev); } =20 @@ -2911,6 +2919,46 @@ static int iommu_change_dev_def_domain(struct iommu_= group *group, return ret; } =20 +static int iommu_group_freeze_dev_ops(struct iommu_group *group) +{ + struct group_device *device; + struct device *dev; + + mutex_lock(&group->mutex); + list_for_each_entry(device, &group->devices, list) { + dev =3D device->dev; + down_read(&dev->iommu->ops_rwsem); + /* .release_device has been called. */ + if (!dev->iommu->iommu_dev) { + up_read(&dev->iommu->ops_rwsem); + goto restore_out; + } + } + mutex_unlock(&group->mutex); + + return 0; + +restore_out: + list_for_each_entry(device, &group->devices, list) { + if (device->dev =3D=3D dev) + break; + up_read(&device->dev->iommu->ops_rwsem); + } + mutex_unlock(&group->mutex); + + return -EINVAL; +} + +static void iommu_group_unfreeze_dev_ops(struct iommu_group *group) +{ + struct group_device *device; + + mutex_lock(&group->mutex); + list_for_each_entry(device, &group->devices, list) + up_read(&device->dev->iommu->ops_rwsem); + mutex_unlock(&group->mutex); +} + /* * Changing the default domain through sysfs requires the users to unbind = the * drivers from the devices in the iommu group, except for a DMA -> DMA-FQ @@ -2988,6 +3036,8 @@ static ssize_t iommu_group_store_type(struct iommu_gr= oup *group, */ mutex_unlock(&group->mutex); =20 + iommu_group_freeze_dev_ops(group); + /* Check if the device in the group still has a driver bound to it */ device_lock(dev); if (device_is_bound(dev) && !(req_type =3D=3D IOMMU_DOMAIN_DMA_FQ && @@ -3002,6 +3052,7 @@ static ssize_t iommu_group_store_type(struct iommu_gr= oup *group, =20 out: device_unlock(dev); + iommu_group_unfreeze_dev_ops(group); put_device(dev); =20 return ret; --=20 2.34.1 From nobody Fri Sep 12 06:30:11 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7289CC636CC for ; Mon, 13 Feb 2023 07:58:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229953AbjBMH6a (ORCPT ); Mon, 13 Feb 2023 02:58:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46938 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229747AbjBMH6X (ORCPT ); Mon, 13 Feb 2023 02:58:23 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1AC684EE8 for ; Sun, 12 Feb 2023 23:58:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1676275099; x=1707811099; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AazWd96xxOSoSDyvZpaQLi9s44x2C1YOu7YcySHmaWw=; b=njK/FKk/1ET1BQz9vbmL0Z9czc4Xl6Cj4ohlu9cQZRun3c42H+mEwGZO tbC4L231KL63zRk3GsWhskmEoIzHekbV0YMr65T4dtV13KWjQDLfUefpO 2k7lOlSV6rNuVbqQ/MEfb3o1CONqlalImg2TVtXBtM226OFCpBRiSLQN2 N64nSFY12Am8dRZ6Ew+JfsLsRjzgaWXhWrNMU5AR1OkezFKsBfB7CyWe6 zomoY8RIZOAlT/soDH83ywrIWhQVo8G5w3IqTwSTNesdIXckrFaYcDxKM 1dayHrQsIDIDD6f7mYGtO46+uaAPWEdoYtfTSLs9bMq1mLab0jO/n7VLC g==; X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="417058772" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="417058772" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Feb 2023 23:58:18 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="842684807" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="842684807" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga005.jf.intel.com with ESMTP; 12 Feb 2023 23:58:16 -0800 From: Lu Baolu To: iommu@lists.linux.dev Cc: Joerg Roedel , Jason Gunthorpe , Christoph Hellwig , Kevin Tian , Will Deacon , Robin Murphy , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH 2/4] iommu: Use group ownership to avoid driver attachment Date: Mon, 13 Feb 2023 15:49:39 +0800 Message-Id: <20230213074941.919324-3-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230213074941.919324-1-baolu.lu@linux.intel.com> References: <20230213074941.919324-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The iommu_group_store_type() requires the devices in the iommu group are not bound to any device driver during the whole operation. The existing code locks the device with device_lock(dev) and use device_is_bound() to check whether any driver is bound to device. In fact, this can be achieved through the DMA ownership helpers. Replace them with iommu_group_claim/release_dma_owner() helpers. Signed-off-by: Lu Baolu --- drivers/iommu/iommu.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 4f71dcd2621b..6547cb38480c 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2807,12 +2807,6 @@ static int iommu_change_dev_def_domain(struct iommu_= group *group, =20 mutex_lock(&group->mutex); =20 - if (group->default_domain !=3D group->domain) { - dev_err_ratelimited(prev_dev, "Group not assigned to default domain\n"); - ret =3D -EBUSY; - goto out; - } - /* * iommu group wasn't locked while acquiring device lock in * iommu_group_store_type(). So, make sure that the device count hasn't @@ -2971,6 +2965,7 @@ static void iommu_group_unfreeze_dev_ops(struct iommu= _group *group) static ssize_t iommu_group_store_type(struct iommu_group *group, const char *buf, size_t count) { + bool group_owner_claimed =3D false; struct group_device *grp_dev; struct device *dev; int ret, req_type; @@ -2992,6 +2987,14 @@ static ssize_t iommu_group_store_type(struct iommu_g= roup *group, else return -EINVAL; =20 + if (req_type !=3D IOMMU_DOMAIN_DMA_FQ || + group->default_domain->type !=3D IOMMU_DOMAIN_DMA) { + ret =3D iommu_group_claim_dma_owner(group, (void *)buf); + if (ret) + return ret; + group_owner_claimed =3D true; + } + /* * Lock/Unlock the group mutex here before device lock to * 1. Make sure that the iommu group has only one device (this is a @@ -3001,6 +3004,8 @@ static ssize_t iommu_group_store_type(struct iommu_gr= oup *group, mutex_lock(&group->mutex); if (iommu_group_device_count(group) !=3D 1) { mutex_unlock(&group->mutex); + if (group_owner_claimed) + iommu_group_release_dma_owner(group); pr_err_ratelimited("Cannot change default domain: Group has more than on= e device\n"); return -EINVAL; } @@ -3038,22 +3043,16 @@ static ssize_t iommu_group_store_type(struct iommu_= group *group, =20 iommu_group_freeze_dev_ops(group); =20 - /* Check if the device in the group still has a driver bound to it */ device_lock(dev); - if (device_is_bound(dev) && !(req_type =3D=3D IOMMU_DOMAIN_DMA_FQ && - group->default_domain->type =3D=3D IOMMU_DOMAIN_DMA)) { - pr_err_ratelimited("Device is still bound to driver\n"); - ret =3D -EBUSY; - goto out; - } =20 ret =3D iommu_change_dev_def_domain(group, dev, req_type); ret =3D ret ?: count; =20 -out: device_unlock(dev); iommu_group_unfreeze_dev_ops(group); put_device(dev); + if (group_owner_claimed) + iommu_group_release_dma_owner(group); =20 return ret; } --=20 2.34.1 From nobody Fri Sep 12 06:30:11 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4F40C636CC for ; Mon, 13 Feb 2023 07:58:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229961AbjBMH6f (ORCPT ); Mon, 13 Feb 2023 02:58:35 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46622 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229628AbjBMH61 (ORCPT ); Mon, 13 Feb 2023 02:58:27 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E8DCB12847 for ; Sun, 12 Feb 2023 23:58:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1676275101; x=1707811101; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=7ES7z2AGJUYYSi8+q2JnrnEZVheTtSStbFLmnP3Q4p4=; b=BhyVwuQgQ6iOAM7pjt+LEF9UBhvVSerTGLvqRLnp/vsWv/HZMHYDpNMN etJbLDYCmcDZtaxN6PAZry44DTsZm4mOgtjj7jZS19h3r8EjPVQrtfg61 3jo3/0M1LrGKGeqnFyH05zvxmnrRIvqcJRNNTs+2RMUvZYEZCIIGi0qM+ ZLf/e4l21N3/IHowE43o+vbdR/s3gUH2mWnjexguNKhC+RFMKMrJwRIb3 QmKU7svGwUdER1ipQFOILZrRqZbOPyxG6G7mo77pPIGd3C2bceIr3Mr7d M8d3R9mahBRLqmRfR7EHdVLfV1I/QHODFaIOewnfUysJHBImVzG/gUXKH g==; X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="417058786" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="417058786" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Feb 2023 23:58:21 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="842684811" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="842684811" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga005.jf.intel.com with ESMTP; 12 Feb 2023 23:58:18 -0800 From: Lu Baolu To: iommu@lists.linux.dev Cc: Joerg Roedel , Jason Gunthorpe , Christoph Hellwig , Kevin Tian , Will Deacon , Robin Murphy , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH 3/4] iommu: Remove unnecessary device_lock() Date: Mon, 13 Feb 2023 15:49:40 +0800 Message-Id: <20230213074941.919324-4-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230213074941.919324-1-baolu.lu@linux.intel.com> References: <20230213074941.919324-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" device_lock() was used in iommu_group_store_type() to prevent the devices in an iommu group from being attached by any device driver. On the other hand, in order to avoid lock race between group->mutex and device_lock(), it limited the usage scenario to the singleton groups. We have used the DMA ownership framework to avoid driver attachment and ensured that device ops are always valid, there's no need to lock device anymore. Remove use of device_lock() and the singleton group limitation. Signed-off-by: Lu Baolu --- drivers/iommu/iommu.c | 78 ++++--------------------------------------- 1 file changed, 6 insertions(+), 72 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 6547cb38480c..1e69def20a67 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2786,8 +2786,6 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature); * Changes the default domain of an iommu group that has *only* one device * * @group: The group for which the default domain should be changed - * @prev_dev: The device in the group (this is used to make sure that the = device - * hasn't changed after the caller has called this function) * @type: The type of the new default domain that gets associated with the= group * * Returns 0 on success and error code on failure @@ -2797,8 +2795,7 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature); * group's default domain type through /sys/kernel/iommu_groups//type * Please take a closer look if intended to use for other purposes. */ -static int iommu_change_dev_def_domain(struct iommu_group *group, - struct device *prev_dev, int type) +static int iommu_change_dev_def_domain(struct iommu_group *group, int type) { struct iommu_domain *prev_dom; struct group_device *grp_dev; @@ -2821,7 +2818,7 @@ static int iommu_change_dev_def_domain(struct iommu_g= roup *group, * waiting for T1 to release other device locks. */ if (iommu_group_device_count(group) !=3D 1) { - dev_err_ratelimited(prev_dev, "Cannot change default domain: Group has m= ore than one device\n"); + pr_err_ratelimited("Cannot change default domain: Group has more than on= e device\n"); ret =3D -EINVAL; goto out; } @@ -2830,12 +2827,6 @@ static int iommu_change_dev_def_domain(struct iommu_= group *group, grp_dev =3D list_first_entry(&group->devices, struct group_device, list); dev =3D grp_dev->dev; =20 - if (prev_dev !=3D dev) { - dev_err_ratelimited(prev_dev, "Cannot change default domain: Device has = been changed\n"); - ret =3D -EBUSY; - goto out; - } - prev_dom =3D group->default_domain; if (!prev_dom) { ret =3D -EINVAL; @@ -2851,8 +2842,8 @@ static int iommu_change_dev_def_domain(struct iommu_g= roup *group, */ type =3D dev_def_dom ? : iommu_def_domain_type; } else if (dev_def_dom && type !=3D dev_def_dom) { - dev_err_ratelimited(prev_dev, "Device cannot be in %s domain\n", - iommu_domain_type_str(type)); + pr_err_ratelimited("Device cannot be in %s domain\n", + iommu_domain_type_str(type)); ret =3D -EINVAL; goto out; } @@ -2959,15 +2950,11 @@ static void iommu_group_unfreeze_dev_ops(struct iom= mu_group *group) * transition. Return failure if this isn't met. * * We need to consider the race between this and the device release path. - * device_lock(dev) is used here to guarantee that the device release path - * will not be entered at the same time. */ static ssize_t iommu_group_store_type(struct iommu_group *group, const char *buf, size_t count) { bool group_owner_claimed =3D false; - struct group_device *grp_dev; - struct device *dev; int ret, req_type; =20 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) @@ -2995,66 +2982,13 @@ static ssize_t iommu_group_store_type(struct iommu_= group *group, group_owner_claimed =3D true; } =20 - /* - * Lock/Unlock the group mutex here before device lock to - * 1. Make sure that the iommu group has only one device (this is a - * prerequisite for step 2) - * 2. Get struct *dev which is needed to lock device - */ - mutex_lock(&group->mutex); - if (iommu_group_device_count(group) !=3D 1) { - mutex_unlock(&group->mutex); - if (group_owner_claimed) - iommu_group_release_dma_owner(group); - pr_err_ratelimited("Cannot change default domain: Group has more than on= e device\n"); - return -EINVAL; - } - - /* Since group has only one device */ - grp_dev =3D list_first_entry(&group->devices, struct group_device, list); - dev =3D grp_dev->dev; - get_device(dev); - - /* - * Don't hold the group mutex because taking group mutex first and then - * the device lock could potentially cause a deadlock as below. Assume - * two threads T1 and T2. T1 is trying to change default domain of an - * iommu group and T2 is trying to hot unplug a device or release [1] VF - * of a PCIe device which is in the same iommu group. T1 takes group - * mutex and before it could take device lock assume T2 has taken device - * lock and is yet to take group mutex. Now, both the threads will be - * waiting for the other thread to release lock. Below, lock order was - * suggested. - * device_lock(dev); - * mutex_lock(&group->mutex); - * iommu_change_dev_def_domain(); - * mutex_unlock(&group->mutex); - * device_unlock(dev); - * - * [1] Typical device release path - * device_lock() from device/driver core code - * -> bus_notifier() - * -> iommu_bus_notifier() - * -> iommu_release_device() - * -> ops->release_device() vendor driver calls back iommu core code - * -> mutex_lock() from iommu core code - */ - mutex_unlock(&group->mutex); - iommu_group_freeze_dev_ops(group); - - device_lock(dev); - - ret =3D iommu_change_dev_def_domain(group, dev, req_type); - ret =3D ret ?: count; - - device_unlock(dev); + ret =3D iommu_change_dev_def_domain(group, req_type); iommu_group_unfreeze_dev_ops(group); - put_device(dev); if (group_owner_claimed) iommu_group_release_dma_owner(group); =20 - return ret; + return ret ?: count; } =20 static bool iommu_is_default_domain(struct iommu_group *group) --=20 2.34.1 From nobody Fri Sep 12 06:30:11 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A460C636D4 for ; Mon, 13 Feb 2023 07:58:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229489AbjBMH6j (ORCPT ); Mon, 13 Feb 2023 02:58:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:46874 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229729AbjBMH62 (ORCPT ); Mon, 13 Feb 2023 02:58:28 -0500 Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8B07212F17 for ; Sun, 12 Feb 2023 23:58:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1676275104; x=1707811104; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qmT4qJz3GuvC6rtOcQlp46cw8Mqcw48l+c2mWYJTzmI=; b=n4pQ3LrxvEqna4gcl/CW/KgPEFT9lOcqOoZpG4lNmL350secm2U+at1Y zGnYSQ6nsMRrRkSowr3TnpLwqfDhGcSPwFfpcnBNs5B78ksSW9ZqTZ/VX xZtfb0NIl9hUgwk2jy8ieahAKpL4WagSKWHKg/wQmATP0HazKQXIT6IDS lwcecFvSZPZefP/0RjLC6GYiA1tDaWOyf9pCqNeFmxHEkqjwVjA+Q8ZJk 7879odm7DdpDWqy5OQZsh67kK8fMBw1lMgXdhFIkR7lvGUXJWQZaywNko 6XI9VosIOPwGvxiKhqbwnENWL07H8CVmWzPkEJrl9MpFJa7UUZjw90ru7 Q==; X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="417058801" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="417058801" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Feb 2023 23:58:24 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10619"; a="842684816" X-IronPort-AV: E=Sophos;i="5.97,293,1669104000"; d="scan'208";a="842684816" Received: from allen-box.sh.intel.com ([10.239.159.48]) by orsmga005.jf.intel.com with ESMTP; 12 Feb 2023 23:58:21 -0800 From: Lu Baolu To: iommu@lists.linux.dev Cc: Joerg Roedel , Jason Gunthorpe , Christoph Hellwig , Kevin Tian , Will Deacon , Robin Murphy , linux-kernel@vger.kernel.org, Lu Baolu Subject: [PATCH 4/4] iommu: Cleanup iommu_change_dev_def_domain() Date: Mon, 13 Feb 2023 15:49:41 +0800 Message-Id: <20230213074941.919324-5-baolu.lu@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230213074941.919324-1-baolu.lu@linux.intel.com> References: <20230213074941.919324-1-baolu.lu@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" As the singleton group limitation has been removed, cleanup the code in iommu_change_dev_def_domain() accordingly. Signed-off-by: Lu Baolu --- drivers/iommu/iommu.c | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 1e69def20a67..67b978403a05 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -2783,7 +2783,7 @@ int iommu_dev_disable_feature(struct device *dev, enu= m iommu_dev_features feat) EXPORT_SYMBOL_GPL(iommu_dev_disable_feature); =20 /* - * Changes the default domain of an iommu group that has *only* one device + * Changes the default domain of an iommu group * * @group: The group for which the default domain should be changed * @type: The type of the new default domain that gets associated with the= group @@ -2797,33 +2797,14 @@ EXPORT_SYMBOL_GPL(iommu_dev_disable_feature); */ static int iommu_change_dev_def_domain(struct iommu_group *group, int type) { + struct __group_domain_type gtype =3D {NULL, 0}; struct iommu_domain *prev_dom; struct group_device *grp_dev; - int ret, dev_def_dom; struct device *dev; + int ret; =20 mutex_lock(&group->mutex); =20 - /* - * iommu group wasn't locked while acquiring device lock in - * iommu_group_store_type(). So, make sure that the device count hasn't - * changed while acquiring device lock. - * - * Changing default domain of an iommu group with two or more devices - * isn't supported because there could be a potential deadlock. Consider - * the following scenario. T1 is trying to acquire device locks of all - * the devices in the group and before it could acquire all of them, - * there could be another thread T2 (from different sub-system and use - * case) that has already acquired some of the device locks and might be - * waiting for T1 to release other device locks. - */ - if (iommu_group_device_count(group) !=3D 1) { - pr_err_ratelimited("Cannot change default domain: Group has more than on= e device\n"); - ret =3D -EINVAL; - goto out; - } - - /* Since group has only one device */ grp_dev =3D list_first_entry(&group->devices, struct group_device, list); dev =3D grp_dev->dev; =20 @@ -2833,15 +2814,16 @@ static int iommu_change_dev_def_domain(struct iommu= _group *group, int type) goto out; } =20 - dev_def_dom =3D iommu_get_def_domain_type(dev); + __iommu_group_for_each_dev(group, >ype, + probe_get_default_domain_type); if (!type) { /* * If the user hasn't requested any specific type of domain and * if the device supports both the domains, then default to the * domain the device was booted with */ - type =3D dev_def_dom ? : iommu_def_domain_type; - } else if (dev_def_dom && type !=3D dev_def_dom) { + type =3D gtype.type ? : iommu_def_domain_type; + } else if (gtype.type && type !=3D gtype.type) { pr_err_ratelimited("Device cannot be in %s domain\n", iommu_domain_type_str(type)); ret =3D -EINVAL; @@ -2870,16 +2852,14 @@ static int iommu_change_dev_def_domain(struct iommu= _group *group, int type) if (ret) goto out; =20 - ret =3D iommu_create_device_direct_mappings(group, dev); + ret =3D iommu_group_create_direct_mappings(group); if (ret) goto free_new_domain; =20 - ret =3D __iommu_attach_device(group->default_domain, dev); + ret =3D __iommu_attach_group(group->default_domain, group); if (ret) goto free_new_domain; =20 - group->domain =3D group->default_domain; - /* * Release the mutex here because ops->probe_finalize() call-back of * some vendor IOMMU drivers calls arm_iommu_attach_device() which @@ -2889,7 +2869,7 @@ static int iommu_change_dev_def_domain(struct iommu_g= roup *group, int type) mutex_unlock(&group->mutex); =20 /* Make sure dma_ops is appropriatley set */ - iommu_group_do_probe_finalize(dev, group->default_domain); + __iommu_group_dma_finalize(group); iommu_domain_free(prev_dom); return 0; =20 @@ -2897,7 +2877,6 @@ static int iommu_change_dev_def_domain(struct iommu_g= roup *group, int type) iommu_domain_free(group->default_domain); group->default_domain =3D prev_dom; group->domain =3D prev_dom; - out: mutex_unlock(&group->mutex); =20 --=20 2.34.1