Message ID | 4-v1-f82a05539a64+5042-iommu_fwspec_p2_jgg@nvidia.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Make a new API for drivers to use to get their FW | expand |
On Thu, Nov 30, 2023 at 2:10 AM Jason Gunthorpe <jgg@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@nvidia.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@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 >
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)
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@nvidia.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(-)