[PATCH 04/30] ACPI: IORT: Remove fwspec from the reserved region code
Rafael J. Wysocki
rafael at kernel.org
Thu Nov 30 05:23:02 PST 2023
On Thu, Nov 30, 2023 at 2:10 AM Jason Gunthorpe <jgg at nvidia.com> wrote:
>
> iort_iommu_get_resv_regions() needs access to the parsed id array that is
> currently stored in the iommu_fwspec.
>
> Instead of getting this from the fwspec inside the iort code have the
> caller pass it in.
>
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki at intel.com>
> ---
> drivers/acpi/arm64/iort.c | 88 ++++++++++++++++++++++++---------------
> drivers/iommu/dma-iommu.c | 7 +++-
> include/linux/acpi_iort.h | 8 +++-
> 3 files changed, 65 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 5c9b4c23f96a87..93e30f2f5004f0 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c
> @@ -946,11 +946,19 @@ static u32 *iort_rmr_alloc_sids(u32 *sids, u32 count, u32 id_start,
> return new_sids;
> }
>
> -static bool iort_rmr_has_dev(struct device *dev, u32 id_start,
> +struct iort_resv_args {
> + struct device *dev;
> + struct list_head *head;
> + struct fwnode_handle *iommu_fwnode;
> + const u32 *fw_ids;
> + unsigned int fw_num_ids;
> +};
> +
> +static bool iort_rmr_has_dev(struct iort_resv_args *args, u32 id_start,
> u32 id_count)
> {
> + struct device *dev = args->dev;
> int i;
> - struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>
> /*
> * Make sure the kernel has preserved the boot firmware PCIe
> @@ -965,18 +973,18 @@ static bool iort_rmr_has_dev(struct device *dev, u32 id_start,
> return false;
> }
>
> - for (i = 0; i < fwspec->num_ids; i++) {
> - if (fwspec->ids[i] >= id_start &&
> - fwspec->ids[i] <= id_start + id_count)
> + for (i = 0; i < args->fw_num_ids; i++) {
> + if (args->fw_ids[i] >= id_start &&
> + args->fw_ids[i] <= id_start + id_count)
> return true;
> }
>
> return false;
> }
>
> -static void iort_node_get_rmr_info(struct acpi_iort_node *node,
> - struct acpi_iort_node *iommu,
> - struct device *dev, struct list_head *head)
> +static void iort_node_get_rmr_info(struct iort_resv_args *args,
> + struct acpi_iort_node *node,
> + struct acpi_iort_node *iommu)
> {
> struct acpi_iort_node *smmu = NULL;
> struct acpi_iort_rmr *rmr;
> @@ -1013,8 +1021,8 @@ static void iort_node_get_rmr_info(struct acpi_iort_node *node,
> continue;
>
> /* If dev is valid, check RMR node corresponds to the dev SID */
> - if (dev && !iort_rmr_has_dev(dev, map->output_base,
> - map->id_count))
> + if (args->dev &&
> + !iort_rmr_has_dev(args, map->output_base, map->id_count))
> continue;
>
> /* Retrieve SIDs associated with the Node. */
> @@ -1029,12 +1037,12 @@ static void iort_node_get_rmr_info(struct acpi_iort_node *node,
> if (!sids)
> return;
>
> - iort_get_rmrs(node, smmu, sids, num_sids, head);
> + iort_get_rmrs(node, smmu, sids, num_sids, args->head);
> kfree(sids);
> }
>
> -static void iort_find_rmrs(struct acpi_iort_node *iommu, struct device *dev,
> - struct list_head *head)
> +static void iort_find_rmrs(struct iort_resv_args *args,
> + struct acpi_iort_node *iommu)
> {
> struct acpi_table_iort *iort;
> struct acpi_iort_node *iort_node, *iort_end;
> @@ -1057,7 +1065,7 @@ static void iort_find_rmrs(struct acpi_iort_node *iommu, struct device *dev,
> return;
>
> if (iort_node->type == ACPI_IORT_NODE_RMR)
> - iort_node_get_rmr_info(iort_node, iommu, dev, head);
> + iort_node_get_rmr_info(args, iort_node, iommu);
>
> iort_node = ACPI_ADD_PTR(struct acpi_iort_node, iort_node,
> iort_node->length);
> @@ -1069,25 +1077,23 @@ static void iort_find_rmrs(struct acpi_iort_node *iommu, struct device *dev,
> * If dev is NULL, the function populates all the RMRs associated with the
> * given IOMMU.
> */
> -static void iort_iommu_rmr_get_resv_regions(struct fwnode_handle *iommu_fwnode,
> - struct device *dev,
> - struct list_head *head)
> +static void iort_iommu_rmr_get_resv_regions(struct iort_resv_args *args)
> {
> struct acpi_iort_node *iommu;
>
> - iommu = iort_get_iort_node(iommu_fwnode);
> + iommu = iort_get_iort_node(args->iommu_fwnode);
> if (!iommu)
> return;
>
> - iort_find_rmrs(iommu, dev, head);
> + iort_find_rmrs(args, iommu);
> }
>
> -static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
> +static struct acpi_iort_node *
> +iort_get_msi_resv_iommu(struct iort_resv_args *args)
> {
> struct acpi_iort_node *iommu;
> - struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>
> - iommu = iort_get_iort_node(fwspec->iommu_fwnode);
> + iommu = iort_get_iort_node(args->iommu_fwnode);
>
> if (iommu && (iommu->type == ACPI_IORT_NODE_SMMU_V3)) {
> struct acpi_iort_smmu_v3 *smmu;
> @@ -1105,15 +1111,13 @@ static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
> * The ITS interrupt translation spaces (ITS_base + SZ_64K, SZ_64K)
> * associated with the device are the HW MSI reserved regions.
> */
> -static void iort_iommu_msi_get_resv_regions(struct device *dev,
> - struct list_head *head)
> +static void iort_iommu_msi_get_resv_regions(struct iort_resv_args *args)
> {
> - struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> struct acpi_iort_its_group *its;
> struct acpi_iort_node *iommu_node, *its_node = NULL;
> int i;
>
> - iommu_node = iort_get_msi_resv_iommu(dev);
> + iommu_node = iort_get_msi_resv_iommu(args);
> if (!iommu_node)
> return;
>
> @@ -1126,9 +1130,9 @@ static void iort_iommu_msi_get_resv_regions(struct device *dev,
> * a given PCI or named component may map IDs to.
> */
>
> - for (i = 0; i < fwspec->num_ids; i++) {
> + for (i = 0; i < args->fw_num_ids; i++) {
> its_node = iort_node_map_id(iommu_node,
> - fwspec->ids[i],
> + args->fw_ids[i],
> NULL, IORT_MSI_TYPE);
> if (its_node)
> break;
> @@ -1151,7 +1155,7 @@ static void iort_iommu_msi_get_resv_regions(struct device *dev,
> prot, IOMMU_RESV_MSI,
> GFP_KERNEL);
> if (region)
> - list_add_tail(®ion->list, head);
> + list_add_tail(®ion->list, args->head);
> }
> }
> }
> @@ -1160,13 +1164,24 @@ static void iort_iommu_msi_get_resv_regions(struct device *dev,
> * iort_iommu_get_resv_regions - Generic helper to retrieve reserved regions.
> * @dev: Device from iommu_get_resv_regions()
> * @head: Reserved region list from iommu_get_resv_regions()
> + * @iommu_fwnode: fwnode that describes the iommu connection for the device
> + * @fw_ids: Parsed IDs
> + * @fw_num_ids: Length of fw_ids
> */
> -void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head,
> + struct fwnode_handle *iommu_fwnode,
> + const u32 *fw_ids, unsigned int fw_num_ids)
> {
> - struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> + struct iort_resv_args args = {
> + .dev = dev,
> + .head = head,
> + .iommu_fwnode = iommu_fwnode,
> + .fw_ids = fw_ids,
> + .fw_num_ids = fw_num_ids,
> + };
>
> - iort_iommu_msi_get_resv_regions(dev, head);
> - iort_iommu_rmr_get_resv_regions(fwspec->iommu_fwnode, dev, head);
> + iort_iommu_msi_get_resv_regions(&args);
> + iort_iommu_rmr_get_resv_regions(&args);
> }
>
> /**
> @@ -1178,7 +1193,12 @@ void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
> void iort_get_rmr_sids(struct fwnode_handle *iommu_fwnode,
> struct list_head *head)
> {
> - iort_iommu_rmr_get_resv_regions(iommu_fwnode, NULL, head);
> + struct iort_resv_args args = {
> + .head = head,
> + .iommu_fwnode = iommu_fwnode,
> + };
> +
> + iort_iommu_rmr_get_resv_regions(&args);
> }
> EXPORT_SYMBOL_GPL(iort_get_rmr_sids);
>
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
> index 85163a83df2f68..d644b0502ef48e 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -468,9 +468,12 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
> */
> void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
> {
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
>
> - if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
> - iort_iommu_get_resv_regions(dev, list);
> + if (!is_of_node(fwspec->iommu_fwnode)) {
> + iort_iommu_get_resv_regions(dev, list, fwspec->iommu_fwnode,
> + fwspec->ids, fwspec->num_ids);
> + }
>
> if (dev->of_node)
> of_iommu_get_resv_regions(dev, list);
> diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
> index 5423abff9b6b09..13f0cefb930693 100644
> --- a/include/linux/acpi_iort.h
> +++ b/include/linux/acpi_iort.h
> @@ -53,7 +53,9 @@ void iort_put_rmr_sids(struct fwnode_handle *iommu_fwnode,
> /* IOMMU interface */
> int iort_dma_get_ranges(struct device *dev, u64 *size);
> int iort_iommu_configure_id(struct device *dev, const u32 *id_in);
> -void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head);
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head,
> + struct fwnode_handle *iommu_fwnode,
> + const u32 *fw_ids, unsigned int fw_num_ids);
> phys_addr_t acpi_iort_dma_get_max_cpu_address(void);
> #else
> static inline u32 iort_msi_map_id(struct device *dev, u32 id)
> @@ -72,7 +74,9 @@ static inline int iort_dma_get_ranges(struct device *dev, u64 *size)
> static inline int iort_iommu_configure_id(struct device *dev, const u32 *id_in)
> { return -ENODEV; }
> static inline
> -void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head)
> +void iort_iommu_get_resv_regions(struct device *dev, struct list_head *head,
> + struct fwnode_handle *iommu_fwnode,
> + const u32 *fw_ids, unsigned int fw_num_ids)
> { }
>
> static inline phys_addr_t acpi_iort_dma_get_max_cpu_address(void)
> --
> 2.42.0
>
More information about the Linux-mediatek
mailing list