Skip to content

Commit 918eb5c

Browse files
nwattersonwilldeacon
authored andcommitted
iommu/arm-smmu-v3: Add in-kernel support for NVIDIA Tegra241 (Grace) CMDQV
NVIDIA's Tegra241 Soc has a CMDQ-Virtualization (CMDQV) hardware, extending the standard ARM SMMU v3 IP to support multiple VCMDQs with virtualization capabilities. In terms of command queue, they are very like a standard SMMU CMDQ (or ECMDQs), but only support CS_NONE in the CS field of CMD_SYNC. Add a new tegra241-cmdqv driver, and insert its structure pointer into the existing arm_smmu_device, and then add related function calls in the SMMUv3 driver to interact with the CMDQV driver. In the CMDQV driver, add a minimal part for the in-kernel support: reserve VINTF0 for in-kernel use, and assign some of the VCMDQs to the VINTF0, and select one VCMDQ based on the current CPU ID to execute supported commands. This multi-queue design for in-kernel use gives some limited improvements: up to 20% reduction of invalidation time was measured by a multi-threaded DMA unmap benchmark, compared to a single queue. The other part of the CMDQV driver will be user-space support that gives a hypervisor running on the host OS to talk to the driver for virtualization use cases, allowing VMs to use VCMDQs without trappings, i.e. no VM Exits. This is designed based on IOMMUFD, and its RFC series is also under review. It will provide a guest OS a bigger improvement: 70% to 90% reductions of TLB invalidation time were measured by DMA unmap tests running in a guest, compared to nested SMMU CMDQ (with trappings). As the initial version, the CMDQV driver only supports ACPI configurations. Signed-off-by: Nate Watterson <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Co-developed-by: Nicolin Chen <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Link: https://lore.kernel.org/r/dce50490b2c10b7254fb36aa73ed7ffd812b283a.1724970714.git.nicolinc@nvidia.com Signed-off-by: Will Deacon <[email protected]>
1 parent 6de80d6 commit 918eb5c

File tree

6 files changed

+914
-1
lines changed

6 files changed

+914
-1
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22474,6 +22474,7 @@ M: Thierry Reding <[email protected]>
2247422474
R: Krishna Reddy <[email protected]>
2247522475
2247622476
S: Supported
22477+
F: drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
2247722478
F: drivers/iommu/arm/arm-smmu/arm-smmu-nvidia.c
2247822479
F: drivers/iommu/tegra*
2247922480

drivers/iommu/Kconfig

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,17 @@ config ARM_SMMU_V3_KUNIT_TEST
424424
Enable this option to unit-test arm-smmu-v3 driver functions.
425425

426426
If unsure, say N.
427+
428+
config TEGRA241_CMDQV
429+
bool "NVIDIA Tegra241 CMDQ-V extension support for ARM SMMUv3"
430+
depends on ACPI
431+
help
432+
Support for NVIDIA CMDQ-Virtualization extension for ARM SMMUv3. The
433+
CMDQ-V extension is similar to v3.3 ECMDQ for multi command queues
434+
support, except with virtualization capabilities.
435+
436+
Say Y here if your system is NVIDIA Tegra241 (Grace) or it has the same
437+
CMDQ-V extension.
427438
endif
428439

429440
config S390_IOMMU

drivers/iommu/arm/arm-smmu-v3/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
obj-$(CONFIG_ARM_SMMU_V3) += arm_smmu_v3.o
33
arm_smmu_v3-y := arm-smmu-v3.o
44
arm_smmu_v3-$(CONFIG_ARM_SMMU_V3_SVA) += arm-smmu-v3-sva.o
5+
arm_smmu_v3-$(CONFIG_TEGRA241_CMDQV) += tegra241-cmdqv.o
56

67
obj-$(CONFIG_ARM_SMMU_V3_KUNIT_TEST) += arm-smmu-v3-test.o

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4354,6 +4354,31 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
43544354
}
43554355

43564356
#ifdef CONFIG_ACPI
4357+
#ifdef CONFIG_TEGRA241_CMDQV
4358+
static void acpi_smmu_dsdt_probe_tegra241_cmdqv(struct acpi_iort_node *node,
4359+
struct arm_smmu_device *smmu)
4360+
{
4361+
const char *uid = kasprintf(GFP_KERNEL, "%u", node->identifier);
4362+
struct acpi_device *adev;
4363+
4364+
/* Look for an NVDA200C node whose _UID matches the SMMU node ID */
4365+
adev = acpi_dev_get_first_match_dev("NVDA200C", uid, -1);
4366+
if (adev) {
4367+
/* Tegra241 CMDQV driver is responsible for put_device() */
4368+
smmu->impl_dev = &adev->dev;
4369+
smmu->options |= ARM_SMMU_OPT_TEGRA241_CMDQV;
4370+
dev_info(smmu->dev, "found companion CMDQV device: %s\n",
4371+
dev_name(smmu->impl_dev));
4372+
}
4373+
kfree(uid);
4374+
}
4375+
#else
4376+
static void acpi_smmu_dsdt_probe_tegra241_cmdqv(struct acpi_iort_node *node,
4377+
struct arm_smmu_device *smmu)
4378+
{
4379+
}
4380+
#endif
4381+
43574382
static int acpi_smmu_iort_probe_model(struct acpi_iort_node *node,
43584383
struct arm_smmu_device *smmu)
43594384
{
@@ -4368,6 +4393,11 @@ static int acpi_smmu_iort_probe_model(struct acpi_iort_node *node,
43684393
smmu->options |= ARM_SMMU_OPT_SKIP_PREFETCH;
43694394
break;
43704395
case ACPI_IORT_SMMU_V3_GENERIC:
4396+
/*
4397+
* Tegra241 implementation stores its SMMU options and impl_dev
4398+
* in DSDT. Thus, go through the ACPI tables unconditionally.
4399+
*/
4400+
acpi_smmu_dsdt_probe_tegra241_cmdqv(node, smmu);
43714401
break;
43724402
}
43734403

@@ -4497,7 +4527,8 @@ static struct arm_smmu_device *arm_smmu_impl_probe(struct arm_smmu_device *smmu)
44974527
struct arm_smmu_device *new_smmu = ERR_PTR(-ENODEV);
44984528
int ret;
44994529

4500-
/* Add impl probe */
4530+
if (smmu->impl_dev && (smmu->options & ARM_SMMU_OPT_TEGRA241_CMDQV))
4531+
new_smmu = tegra241_cmdqv_probe(smmu);
45014532

45024533
if (new_smmu == ERR_PTR(-ENODEV))
45034534
return smmu;

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,7 @@ struct arm_smmu_impl_ops {
641641
/* An SMMUv3 instance */
642642
struct arm_smmu_device {
643643
struct device *dev;
644+
struct device *impl_dev;
644645
const struct arm_smmu_impl_ops *impl_ops;
645646

646647
void __iomem *base;
@@ -882,4 +883,14 @@ static inline void arm_smmu_sva_notifier_synchronize(void) {}
882883
#define arm_smmu_sva_domain_alloc NULL
883884

884885
#endif /* CONFIG_ARM_SMMU_V3_SVA */
886+
887+
#ifdef CONFIG_TEGRA241_CMDQV
888+
struct arm_smmu_device *tegra241_cmdqv_probe(struct arm_smmu_device *smmu);
889+
#else /* CONFIG_TEGRA241_CMDQV */
890+
static inline struct arm_smmu_device *
891+
tegra241_cmdqv_probe(struct arm_smmu_device *smmu)
892+
{
893+
return ERR_PTR(-ENODEV);
894+
}
895+
#endif /* CONFIG_TEGRA241_CMDQV */
885896
#endif /* _ARM_SMMU_V3_H */

0 commit comments

Comments
 (0)