On Thu, Jun 26, 2025 at 12:34:51PM -0700, Nicolin Chen wrote:
> The iommu_hw_info can output via the out_data_type field the vendor data
> type from a driver, but this only allows driver to report one data type.
> 
> Now, with SMMUv3 having a Tegra241 CMDQV implementation, it has two sets
> of types and data structs to report.
> 
> One way to support that is to use the same type field bidirectionally.
> 
> Reuse the same field by adding an "in_data_type", allowing user space to
> request for a specific type and to get the corresponding data.
> 
> For backward compatibility, since the ioctl handler has never checked an
> input value, add an IOMMU_HW_INFO_FLAG_INPUT_TYPE to switch between the
> old output-only field and the new bidirectional field.
> 
> Reviewed-by: Kevin Tian <[email protected]>
> Reviewed-by: Jason Gunthorpe <[email protected]>
> Reviewed-by: Lu Baolu <[email protected]>
> Signed-off-by: Nicolin Chen <[email protected]>
> ---
>  include/uapi/linux/iommufd.h   | 20 +++++++++++++++++++-
>  drivers/iommu/iommufd/device.c |  9 ++++++---
>  2 files changed, 25 insertions(+), 4 deletions(-)
> 
> diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
> index 6ad361ff9b06..6ae9d2102154 100644
> --- a/include/uapi/linux/iommufd.h
> +++ b/include/uapi/linux/iommufd.h
> @@ -628,6 +628,15 @@ enum iommufd_hw_capabilities {
>       IOMMU_HW_CAP_PCI_PASID_PRIV = 1 << 2,
>  };
>  
> +/**
> + * enum iommufd_hw_info_flags - Flags for iommu_hw_info
> + * @IOMMU_HW_INFO_FLAG_INPUT_TYPE: If set, @in_data_type carries an input 
> type
> + *                                 for user space to request for a specific 
> info
> + */
> +enum iommufd_hw_info_flags {
> +     IOMMU_HW_INFO_FLAG_INPUT_TYPE = 1 << 0,
> +};
> +
>  /**
>   * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO)
>   * @size: sizeof(struct iommu_hw_info)
> @@ -637,6 +646,12 @@ enum iommufd_hw_capabilities {
>   *            data that kernel supports
>   * @data_uptr: User pointer to a user-space buffer used by the kernel to fill
>   *             the iommu type specific hardware information data
> + * @in_data_type: This shares the same field with @out_data_type, making it 
> be
> + *                a bidirectional field. When IOMMU_HW_INFO_FLAG_INPUT_TYPE 
> is
> + *                set, an input type carried via this @in_data_type field 
> will
> + *                be valid, requesting for the info data to the given type. 
> If
> + *                IOMMU_HW_INFO_FLAG_INPUT_TYPE is unset, any input value 
> will
> + *                be seen as IOMMU_HW_INFO_TYPE_DEFAULT
>   * @out_data_type: Output the iommu hardware info type as defined in the enum
>   *                 iommu_hw_info_type.
>   * @out_capabilities: Output the generic iommu capability info type as 
> defined
> @@ -666,7 +681,10 @@ struct iommu_hw_info {
>       __u32 dev_id;
>       __u32 data_len;
>       __aligned_u64 data_uptr;
> -     __u32 out_data_type;
> +     union {
> +             __u32 in_data_type;
> +             __u32 out_data_type;
> +     };
>       __u8 out_max_pasid_log2;
>       __u8 __reserved[3];
>       __aligned_u64 out_capabilities;
> diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
> index 64a51993e6a1..cbd86aabdd1c 100644
> --- a/drivers/iommu/iommufd/device.c
> +++ b/drivers/iommu/iommufd/device.c
> @@ -1506,6 +1506,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_access_rw, "IOMMUFD");
>  
>  int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
>  {
> +     const u32 SUPPORTED_FLAGS = IOMMU_HW_INFO_FLAG_INPUT_TYPE;
>       struct iommu_hw_info *cmd = ucmd->cmd;
>       void __user *user_ptr = u64_to_user_ptr(cmd->data_uptr);
>       const struct iommu_ops *ops;
> @@ -1515,12 +1516,14 @@ int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
>       void *data;
>       int rc;
>  
> -     if (cmd->flags || cmd->__reserved[0] || cmd->__reserved[1] ||
> -         cmd->__reserved[2])
> +     if (cmd->flags & ~SUPPORTED_FLAGS)
> +             return -EOPNOTSUPP;
> +     if (cmd->__reserved[0] || cmd->__reserved[1] || cmd->__reserved[2])
>               return -EOPNOTSUPP;
>  
>       /* Clear the type field since drivers don't support a random input */
> -     cmd->out_data_type = IOMMU_HW_INFO_TYPE_DEFAULT;
> +     if (!(cmd->flags & IOMMU_HW_INFO_FLAG_INPUT_TYPE))
> +             cmd->in_data_type = IOMMU_HW_INFO_TYPE_DEFAULT;
>  
>       idev = iommufd_get_device(ucmd, cmd->dev_id);
>       if (IS_ERR(idev))

Reviewed-by: Pranjal Shrivastava <[email protected]>

> -- 
> 2.43.0
> 

Reply via email to