Use IOMMU_GET_HW_INFO to check whether the host supports Tegra241 CMDQV.
Validate the returned data type, version, number of vCMDQs and SIDs per
VM. Fail the probe if the host does not meet the expected requirements.
Signed-off-by: Shameer Kolothum <skolothumtho@nvidia.com>
---
hw/arm/tegra241-cmdqv.h | 5 +++++
hw/arm/tegra241-cmdqv.c | 32 ++++++++++++++++++++++++++++++--
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/hw/arm/tegra241-cmdqv.h b/hw/arm/tegra241-cmdqv.h
index 07e10e86ee..312064a081 100644
--- a/hw/arm/tegra241-cmdqv.h
+++ b/hw/arm/tegra241-cmdqv.h
@@ -10,6 +10,11 @@
#ifndef HW_ARM_TEGRA241_CMDQV_H
#define HW_ARM_TEGRA241_CMDQV_H
+#define TEGRA241_CMDQV_VERSION 1
+#define TEGRA241_CMDQV_NUM_CMDQ_LOG2 1
+#define TEGRA241_CMDQV_MAX_CMDQ (1U << TEGRA241_CMDQV_NUM_CMDQ_LOG2)
+#define TEGRA241_CMDQV_NUM_SID_PER_VM_LOG2 4
+
const SMMUv3AccelCmdqvOps *tegra241_cmdqv_get_ops(void);
#endif /* HW_ARM_TEGRA241_CMDQV_H */
diff --git a/hw/arm/tegra241-cmdqv.c b/hw/arm/tegra241-cmdqv.c
index ad5a0d4611..a270fa7ce4 100644
--- a/hw/arm/tegra241-cmdqv.c
+++ b/hw/arm/tegra241-cmdqv.c
@@ -38,8 +38,36 @@ static bool tegra241_cmdqv_init(SMMUv3State *s, Error **errp)
static bool tegra241_cmdqv_probe(SMMUv3State *s, HostIOMMUDeviceIOMMUFD *idev,
Error **errp)
{
- error_setg(errp, "NVIDIA Tegra241 CMDQV is unsupported");
- return false;
+ uint32_t data_type = IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV;
+ struct iommu_hw_info_tegra241_cmdqv cmdqv_info;
+ uint64_t caps;
+
+ if (!iommufd_backend_get_device_info(idev->iommufd, idev->devid, &data_type,
+ &cmdqv_info, sizeof(cmdqv_info), &caps,
+ NULL, errp)) {
+ return false;
+ }
+ if (data_type != IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV) {
+ error_setg(errp, "Host CMDQV: unexpected data type %u (expected %u)",
+ data_type, IOMMU_HW_INFO_TYPE_TEGRA241_CMDQV);
+ return false;
+ }
+ if (cmdqv_info.version != TEGRA241_CMDQV_VERSION) {
+ error_setg(errp, "Host CMDQV: unsupported version %u (expected %u)",
+ cmdqv_info.version, TEGRA241_CMDQV_VERSION);
+ return false;
+ }
+ if (cmdqv_info.log2vcmdqs < TEGRA241_CMDQV_NUM_CMDQ_LOG2) {
+ error_setg(errp, "Host CMDQV: insufficient vCMDQs log2=%u (need >= %u)",
+ cmdqv_info.log2vcmdqs, TEGRA241_CMDQV_NUM_CMDQ_LOG2);
+ return false;
+ }
+ if (cmdqv_info.log2vsids < TEGRA241_CMDQV_NUM_SID_PER_VM_LOG2) {
+ error_setg(errp, "Host CMDQV: insufficient SIDs log2=%u (need >= %u)",
+ cmdqv_info.log2vsids, TEGRA241_CMDQV_NUM_SID_PER_VM_LOG2);
+ return false;
+ }
+ return true;
}
static const SMMUv3AccelCmdqvOps tegra241_cmdqv_ops = {
--
2.43.0