From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6866D3BCD0A; Fri, 4 Sep 2026 05:57:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788501425; cv=none; b=jOD/Jp4B2Y5kx8qxI6s6ESR2RECS6b43IJbsUJxSpy2/T+h1O1pZIDOEALXptZ1mlTaTiyYovi7jn6xKXf2vn/6rgEdX03qGPJ9bfymDCAJg+XW52JILGOLLaE4PGmdq/+dnpu6d9RCInsKoWcJJv+4DffrkiPeKzVKyFcZARlk= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788501425; c=relaxed/simple; bh=NoNIfPjBTp0dnkStkJ1zXU7OfvmO9n6TV/PyG21Vn0E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZppAYg7gLZjvce2VcntRJ8rU4bOE9Hf68nOUDpFXtzeuSpx/PAmkDVnjuYINQzEZdP4l4neNZ2z97O7XqxIoF0tDfMx/bovzj1CLMLOVoxUMQxu2jL3TmJqbFkjBOrsnlhAUUiDUvKpMZxLRsqSlbJ/+y4d6TKV1katKnSq18SY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=sDXP774z; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="sDXP774z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B29BD1F00A3D; Fri, 4 Sep 2026 05:57:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1788501424; bh=zuj3ovKY5Se7yhSd2xqoL/jGBqXN7/VR8278XAj6zVc=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=sDXP774zoTOZCheyn09uKpT0SzvS5RfHWity27a1TLzUjcDIgoF+Wgr613ehs+ote ceHAjesZtN3g29zu3ckczOcNEqSyocthMk+NFhu/G4oy9CeH/j4b2GfrucRxp9OdT1 ploivsPH3C9ASwbsr73WTeTFpeSx31q7WEZPjWMU= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Jason Gunthorpe , Nicolin Chen , Shameer Kolothum , Jason Gunthorpe , Will Deacon Subject: [PATCH 6.18 406/552] iommu/arm-smmu-v3: Manage teardown with devm Date: Fri, 4 Sep 2026 06:59:23 +0200 Message-ID: <20260904045759.766342588@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260904045747.813364717@linuxfoundation.org> References: <20260904045747.813364717@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.18-stable review patch. If anyone has any objections, please let me know. ------------------ From: Shameer Kolothum commit 2bd22a0d40503a65d243b011de146603c8ce1cbc upstream. arm_smmu_device_remove() manually frees the IOPF queue, destroys the vmid_map and disables the device, while the IRQs and queues are devm managed. devm unwinds only after remove() returns, so the cleanup runs in the wrong order. The IOPF queue is freed before the event-queue IRQ whose handler uses it. Manage all of it with devm so the unwind order is correct. Free the IOPF queue and vmid_map via devm actions, and disable the device from one registered after arm_smmu_device_reset(). This is also a prerequisite for fixing a Tegra241 CMDQV CMD_SYNC use-after-free in the subsequent patch. Cc: stable@vger.kernel.org Suggested-by: Jason Gunthorpe Reviewed-by: Nicolin Chen Signed-off-by: Shameer Kolothum Reviewed-by: Jason Gunthorpe Signed-off-by: Will Deacon Signed-off-by: Greg Kroah-Hartman --- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 56 ++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 16 deletions(-) --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -3837,6 +3837,20 @@ int arm_smmu_cmdq_init(struct arm_smmu_d return 0; } +static void arm_smmu_free_iopf_action(void *data) +{ + struct iopf_queue *queue = data; + + iopf_queue_free(queue); +} + +static void arm_smmu_destroy_vmid_map(void *data) +{ + struct ida *ida = data; + + ida_destroy(ida); +} + static int arm_smmu_init_queues(struct arm_smmu_device *smmu) { int ret; @@ -3864,6 +3878,11 @@ static int arm_smmu_init_queues(struct a smmu->evtq.iopf = iopf_queue_alloc(dev_name(smmu->dev)); if (!smmu->evtq.iopf) return -ENOMEM; + ret = devm_add_action_or_reset(smmu->dev, + arm_smmu_free_iopf_action, + smmu->evtq.iopf); + if (ret) + return ret; } /* priq */ @@ -3942,7 +3961,8 @@ static int arm_smmu_init_strtab(struct a ida_init(&smmu->vmid_map); - return 0; + return devm_add_action_or_reset(smmu->dev, arm_smmu_destroy_vmid_map, + &smmu->vmid_map); } static int arm_smmu_init_structures(struct arm_smmu_device *smmu) @@ -4155,6 +4175,13 @@ static int arm_smmu_device_disable(struc return ret; } +static void arm_smmu_disable_action(void *data) +{ + struct arm_smmu_device *smmu = data; + + arm_smmu_device_disable(smmu); +} + static void arm_smmu_write_strtab(struct arm_smmu_device *smmu) { struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg; @@ -4878,7 +4905,7 @@ static int arm_smmu_device_probe(struct /* Initialise in-memory data structures */ ret = arm_smmu_init_structures(smmu); if (ret) - goto err_free_iopf; + return ret; /* Record our private device structure */ platform_set_drvdata(pdev, smmu); @@ -4888,30 +4915,30 @@ static int arm_smmu_device_probe(struct /* Reset the device */ ret = arm_smmu_device_reset(smmu); + if (ret) { + arm_smmu_device_disable(smmu); + return ret; + } + + /* Register last so it unwinds first, while the CMDQ is still up. */ + ret = devm_add_action_or_reset(smmu->dev, arm_smmu_disable_action, smmu); if (ret) - goto err_disable; + return ret; /* And we're up. Go go go! */ ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL, "smmu3.%pa", &ioaddr); if (ret) - goto err_disable; + return ret; ret = iommu_device_register(&smmu->iommu, &arm_smmu_ops, dev); if (ret) { dev_err(dev, "Failed to register iommu\n"); - goto err_free_sysfs; + iommu_device_sysfs_remove(&smmu->iommu); + return ret; } return 0; - -err_free_sysfs: - iommu_device_sysfs_remove(&smmu->iommu); -err_disable: - arm_smmu_device_disable(smmu); -err_free_iopf: - iopf_queue_free(smmu->evtq.iopf); - return ret; } static void arm_smmu_device_remove(struct platform_device *pdev) @@ -4920,9 +4947,6 @@ static void arm_smmu_device_remove(struc iommu_device_unregister(&smmu->iommu); iommu_device_sysfs_remove(&smmu->iommu); - arm_smmu_device_disable(smmu); - iopf_queue_free(smmu->evtq.iopf); - ida_destroy(&smmu->vmid_map); } static void arm_smmu_device_shutdown(struct platform_device *pdev)