[{"id":3682826,"web_url":"http://patchwork.ozlabs.org/comment/3682826/","msgid":"<4389deb3-2c25-45ce-bbd5-ae36760d2619@intel.com>","list_archive_url":null,"date":"2026-04-27T16:37:33","subject":"Re: [PATCH v4 3/3] iommu/arm-smmu-v3: Allow ATS to be always on","submitter":{"id":13225,"url":"http://patchwork.ozlabs.org/api/people/13225/","name":"Dave Jiang","email":"dave.jiang@intel.com"},"content":"On 4/26/26 10:54 PM, Nicolin Chen wrote:\n> When a device's default substream attaches to an identity domain, the SMMU\n> driver currently sets the device's STE between two modes:\n> \n>   Mode 1: Cfg=Translate, S1DSS=Bypass, EATS=1\n>   Mode 2: Cfg=bypass (EATS is ignored by HW)\n> \n> When there is an active PASID (non-default substream), mode 1 is used. And\n> when there is no PASID support or no active PASID, mode 2 is used.\n> \n> The driver will also downgrade an STE from mode 1 to mode 2, when the last\n> active substream becomes inactive.\n> \n> However, there are PCIe devices that demand ATS to be always on. For these\n> devices, their STEs have to use the mode 1 as HW ignores EATS with mode 2.\n> \n> Change the driver accordingly:\n>   - always use the mode 1\n>   - never downgrade to mode 2\n>   - allocate and retain a CD table (see note below)\n> \n> Note that these devices might not support PASID, i.e. doing non-PASID ATS.\n> In such a case, the ssid_bits is set to 0. However, s1cdmax must be set to\n> a !0 value in order to keep the S1DSS field effective. Thus, when a master\n> requires ats_always_on, set its s1cdmax to at least 1, meaning that the CD\n> table will have a dummy entry (SSID=1) that will never be used.\n> \n> Now for these devices, arm_smmu_cdtab_allocated() will always return true,\n> v.s. false prior to this change. When its default substream is attached to\n> an IDENTITY domain, its first CD is NULL in the table, which is a totally\n> valid case. Thus, add \"!master->ats_always_on\" to the condition.\n> \n> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>\n> Tested-by: Nirmoy Das <nirmoyd@nvidia.com>\n> Acked-by: Nirmoy Das <nirmoyd@nvidia.com>\n> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>\n> Reviewed-by: Kevin Tian <kevin.tian@intel.com>\n> Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>\n\nReviewed-by: Dave Jiang <dave.jiang@intel.com>\n\n\n> ---\n>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h |  1 +\n>  drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 75 ++++++++++++++++++---\n>  2 files changed, 68 insertions(+), 8 deletions(-)\n> \n> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h\n> index ef42df4753ec4..8c3600f4364c5 100644\n> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h\n> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h\n> @@ -943,6 +943,7 @@ struct arm_smmu_master {\n>  \tbool\t\t\t\tats_enabled : 1;\n>  \tbool\t\t\t\tste_ats_enabled : 1;\n>  \tbool\t\t\t\tstall_enabled;\n> +\tbool\t\t\t\tats_always_on;\n>  \tunsigned int\t\t\tssid_bits;\n>  \tunsigned int\t\t\tiopf_refcount;\n>  };\n> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c\n> index e8d7dbe495f03..d478f148cd34b 100644\n> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c\n> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c\n> @@ -1742,8 +1742,11 @@ void arm_smmu_clear_cd(struct arm_smmu_master *master, ioasid_t ssid)\n>  \tif (!arm_smmu_cdtab_allocated(&master->cd_table))\n>  \t\treturn;\n>  \tcdptr = arm_smmu_get_cd_ptr(master, ssid);\n> -\tif (WARN_ON(!cdptr))\n> +\tif (!cdptr) {\n> +\t\t/* Only ats_always_on allows a NULL CD on default substream */\n> +\t\tWARN_ON(!master->ats_always_on || ssid);\n>  \t\treturn;\n> +\t}\n>  \tarm_smmu_write_cd_entry(master, ssid, cdptr, &target);\n>  }\n>  \n> @@ -1756,6 +1759,22 @@ static int arm_smmu_alloc_cd_tables(struct arm_smmu_master *master)\n>  \tstruct arm_smmu_ctx_desc_cfg *cd_table = &master->cd_table;\n>  \n>  \tcd_table->s1cdmax = master->ssid_bits;\n> +\n> +\t/*\n> +\t * When a device doesn't support PASID (non default SSID), ssid_bits is\n> +\t * set to 0. This also sets S1CDMAX to 0, which disables the substreams\n> +\t * and ignores the S1DSS field.\n> +\t *\n> +\t * On the other hand, if a device demands ATS to be always on even when\n> +\t * its default substream is IOMMU bypassed, it has to use EATS that is\n> +\t * only effective with an STE (CFG=S1translate, S1DSS=Bypass). For such\n> +\t * use cases, S1CDMAX has to be !0, in order to make use of S1DSS/EATS.\n> +\t *\n> +\t * Set S1CDMAX no lower than 1. This would add a dummy substream in the\n> +\t * CD table but it should never be used by an actual CD.\n> +\t */\n> +\tif (master->ats_always_on)\n> +\t\tcd_table->s1cdmax = max_t(u8, cd_table->s1cdmax, 1);\n>  \tmax_contexts = 1 << cd_table->s1cdmax;\n>  \n>  \tif (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||\n> @@ -3851,7 +3870,8 @@ static int arm_smmu_blocking_set_dev_pasid(struct iommu_domain *new_domain,\n>  \t * When the last user of the CD table goes away downgrade the STE back\n>  \t * to a non-cd_table one, by re-attaching its sid_domain.\n>  \t */\n> -\tif (!arm_smmu_ssids_in_use(&master->cd_table)) {\n> +\tif (!master->ats_always_on &&\n> +\t    !arm_smmu_ssids_in_use(&master->cd_table)) {\n>  \t\tstruct iommu_domain *sid_domain =\n>  \t\t\tiommu_driver_get_domain_for_dev(master->dev);\n>  \n> @@ -3875,6 +3895,8 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,\n>  \t\t.old_domain = old_domain,\n>  \t\t.ssid = IOMMU_NO_PASID,\n>  \t};\n> +\tbool ats_always_on = master->ats_always_on &&\n> +\t\t\t     s1dss != STRTAB_STE_1_S1DSS_TERMINATE;\n>  \n>  \t/*\n>  \t * Do not allow any ASID to be changed while are working on the STE,\n> @@ -3886,7 +3908,7 @@ static void arm_smmu_attach_dev_ste(struct iommu_domain *domain,\n>  \t * If the CD table is not in use we can use the provided STE, otherwise\n>  \t * we use a cdtable STE with the provided S1DSS.\n>  \t */\n> -\tif (arm_smmu_ssids_in_use(&master->cd_table)) {\n> +\tif (ats_always_on || arm_smmu_ssids_in_use(&master->cd_table)) {\n>  \t\t/*\n>  \t\t * If a CD table has to be present then we need to run with ATS\n>  \t\t * on because we have to assume a PASID is using ATS. For\n> @@ -4215,6 +4237,42 @@ static void arm_smmu_remove_master(struct arm_smmu_master *master)\n>  \tkfree(master->build_invs);\n>  }\n>  \n> +static int arm_smmu_master_prepare_ats(struct arm_smmu_master *master)\n> +{\n> +\tbool s1p = master->smmu->features & ARM_SMMU_FEAT_TRANS_S1;\n> +\tunsigned int stu = __ffs(master->smmu->pgsize_bitmap);\n> +\tstruct pci_dev *pdev;\n> +\tint ret;\n> +\n> +\tif (!arm_smmu_ats_supported(master))\n> +\t\treturn 0;\n> +\n> +\tpdev = to_pci_dev(master->dev);\n> +\n> +\tif (!pci_ats_always_on(pdev))\n> +\t\tgoto out_prepare;\n> +\n> +\t/*\n> +\t * S1DSS is required for ATS to be always on for identity domain cases.\n> +\t * However, the S1DSS field is ignored if !IDR0_S1P or !IDR1_SSIDSIZE.\n> +\t */\n> +\tif (!s1p || !master->smmu->ssid_bits) {\n> +\t\tdev_info_once(master->dev,\n> +\t\t\t      \"SMMU doesn't support ATS to be always on\\n\");\n> +\t\tgoto out_prepare;\n> +\t}\n> +\n> +\tmaster->ats_always_on = true;\n> +\n> +\tret = arm_smmu_alloc_cd_tables(master);\n> +\tif (ret)\n> +\t\treturn ret;\n> +\n> +out_prepare:\n> +\tpci_prepare_ats(pdev, stu);\n> +\treturn 0;\n> +}\n> +\n>  static struct iommu_device *arm_smmu_probe_device(struct device *dev)\n>  {\n>  \tint ret;\n> @@ -4263,14 +4321,15 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)\n>  \t    smmu->features & ARM_SMMU_FEAT_STALL_FORCE)\n>  \t\tmaster->stall_enabled = true;\n>  \n> -\tif (dev_is_pci(dev)) {\n> -\t\tunsigned int stu = __ffs(smmu->pgsize_bitmap);\n> -\n> -\t\tpci_prepare_ats(to_pci_dev(dev), stu);\n> -\t}\n> +\tret = arm_smmu_master_prepare_ats(master);\n> +\tif (ret)\n> +\t\tgoto err_disable_pasid;\n>  \n>  \treturn &smmu->iommu;\n>  \n> +err_disable_pasid:\n> +\tarm_smmu_disable_pasid(master);\n> +\tarm_smmu_remove_master(master);\n>  err_free_master:\n>  \tkfree(master);\n>  \treturn ERR_PTR(ret);","headers":{"Return-Path":"\n <linux-pci+bounces-53235-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-pci@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256\n header.s=Intel header.b=O5k4jZRL;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c0a:e001:db::12fc:5321; helo=sea.lore.kernel.org;\n envelope-from=linux-pci+bounces-53235-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com\n header.b=\"O5k4jZRL\"","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=192.198.163.19","smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=intel.com","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=intel.com"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org\n [IPv6:2600:3c0a:e001:db::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g48Wv5SGrz1yHX\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 28 Apr 2026 02:43:23 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 380CF301E3F2\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 27 Apr 2026 16:37:39 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id D2BFC3C661A;\n\tMon, 27 Apr 2026 16:37:38 +0000 (UTC)","from mgamail.intel.com (mgamail.intel.com [192.198.163.19])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 812207083C;\n\tMon, 27 Apr 2026 16:37:36 +0000 (UTC)","from fmviesa004.fm.intel.com ([10.60.135.144])\n  by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 27 Apr 2026 09:37:36 -0700","from msatwood-mobl.amr.corp.intel.com (HELO [10.125.108.172])\n ([10.125.108.172])\n  by fmviesa004-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 27 Apr 2026 09:37:34 -0700"],"ARC-Seal":"i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777307858; cv=none;\n b=sJSmXtKA9tIZ7Y5kOP7uDqRQM5aiIMe5oXdz/NA7yU7K1O0bSI0b8+ZNolDe1TrgFYp+vxqukzPr+Uq5+WQhg7iBumU421CjjIpIrXfP47b63Ldw1Ds0ahGBz6S+11S3J+emts2vEqg3LTpFQcZKUU8CnIKgTSeEiB+WSVdeVnU=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777307858; c=relaxed/simple;\n\tbh=YIh4WeN8QUAy34rQE95nzKe8DABTjUVlxtRPaQcJnk4=;\n\th=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From:\n\t In-Reply-To:Content-Type;\n b=fk+TSDi6s5QZBikgXT2BkwKBxhXaqDjZJ8N8OnE/UsuoA8eZlvKiZIWH0ph/PTJoedHGCh+hbnx15tlZL18U3abvWc5bxjygJOph6trwZePGxcVaQIINt31idGlOk7d+38ctz9+0nGIW2iL5CZqBMCfprwvbLeMmcoeWPfMM908=","ARC-Authentication-Results":"i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=intel.com;\n spf=pass smtp.mailfrom=intel.com;\n dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com\n header.b=O5k4jZRL; arc=none smtp.client-ip=192.198.163.19","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple;\n  d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n  t=1777307856; x=1808843856;\n  h=message-id:date:mime-version:subject:to:cc:references:\n   from:in-reply-to:content-transfer-encoding;\n  bh=YIh4WeN8QUAy34rQE95nzKe8DABTjUVlxtRPaQcJnk4=;\n  b=O5k4jZRLxsIY/8pNfZ79qgBRZjQQV7GWzrpBMeJfDgFSiYoyACf2cyoV\n   LnSesCx5JLgV3KGPRkBhFBDWEsk2BaTfkXvhJ5xasiviYLXbXlk6TdE2Y\n   5QrTkU9rAoq79buWbV1gFmMYH/8ICeVn2swh4pzQbzg7FhlhXwmiQedaG\n   4m8Deam15tZemK9212ALjzeiVdkQPl+VpcalKa1lt2TdVscVjLiwYUakz\n   XQzkySMT01Ui0oH/Mhxce68F+i8/h4LMsjmq1rUw6W5iUsat6teIwHsh7\n   3kAzJCQ7hgECw53sRs5unzFiPrwiybt5py4Er/JOYSMwWd1tVpR14EzGM\n   g==;","X-CSE-ConnectionGUID":["nEAEmDe0QgulIc0wRb6rfA==","n0jX+b1ESp2QJU2StdRyxA=="],"X-CSE-MsgGUID":["57bALsCqSMyxATz0k4XaIg==","m5gUBWOhT5Gq4mf82ZIymw=="],"X-IronPort-AV":["E=McAfee;i=\"6800,10657,11769\"; a=\"77231917\"","E=Sophos;i=\"6.23,202,1770624000\";\n   d=\"scan'208\";a=\"77231917\"","E=Sophos;i=\"6.23,202,1770624000\";\n   d=\"scan'208\";a=\"235438818\""],"X-ExtLoop1":"1","Message-ID":"<4389deb3-2c25-45ce-bbd5-ae36760d2619@intel.com>","Date":"Mon, 27 Apr 2026 09:37:33 -0700","Precedence":"bulk","X-Mailing-List":"linux-pci@vger.kernel.org","List-Id":"<linux-pci.vger.kernel.org>","List-Subscribe":"<mailto:linux-pci+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-pci+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [PATCH v4 3/3] iommu/arm-smmu-v3: Allow ATS to be always on","To":"Nicolin Chen <nicolinc@nvidia.com>, jgg@nvidia.com, will@kernel.org,\n robin.murphy@arm.com, bhelgaas@google.com","Cc":"joro@8bytes.org, praan@google.com, baolu.lu@linux.intel.com,\n kevin.tian@intel.com, miko.lenczewski@arm.com,\n linux-arm-kernel@lists.infradead.org, iommu@lists.linux.dev,\n linux-kernel@vger.kernel.org, linux-pci@vger.kernel.org,\n dan.j.williams@intel.com, jonathan.cameron@huawei.com, vsethi@nvidia.com,\n linux-cxl@vger.kernel.org, nirmoyd@nvidia.com","References":"<cover.1777269009.git.nicolinc@nvidia.com>\n <7403163ebf59380f88c7503b3adf0dae07428df8.1777269009.git.nicolinc@nvidia.com>","Content-Language":"en-US","From":"Dave Jiang <dave.jiang@intel.com>","In-Reply-To":"\n <7403163ebf59380f88c7503b3adf0dae07428df8.1777269009.git.nicolinc@nvidia.com>","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"7bit"}}]