Message ID | 2-v1-f82a05539a64+5042-iommu_fwspec_p2_jgg@nvidia.com (mailing list archive) |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | Make a new API for drivers to use to get their FW | expand |
On Thu, Nov 30, 2023 at 2:11 AM Jason Gunthorpe <jgg@nvidia.com> wrote: > > Similar to of_iommu_for_each_id() this parses the VIOT ACPI description > and invokes a function over each entry in the table. > > Have viot_iommu_configure() use the new function to call > viot_dev_iommu_init(). > > Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> > --- > drivers/acpi/viot.c | 54 +++++++++++++++++++++++---------------- > include/linux/acpi_viot.h | 11 ++++++++ > 2 files changed, 43 insertions(+), 22 deletions(-) > > diff --git a/drivers/acpi/viot.c b/drivers/acpi/viot.c > index c8025921c129b2..7ab35ef05c84e0 100644 > --- a/drivers/acpi/viot.c > +++ b/drivers/acpi/viot.c > @@ -25,13 +25,6 @@ > #include <linux/pci.h> > #include <linux/platform_device.h> > > -struct viot_iommu { > - /* Node offset within the table */ > - unsigned int offset; > - struct fwnode_handle *fwnode; > - struct list_head list; > -}; > - > struct viot_endpoint { > union { > /* PCI range */ > @@ -304,10 +297,10 @@ void __init acpi_viot_init(void) > acpi_put_table(hdr); > } > > -static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu, > - u32 epid) > +static int viot_dev_iommu_init(struct viot_iommu *viommu, u32 epid, void *info) > { > const struct iommu_ops *ops; > + struct device *dev = info; > > if (!viommu) > return -ENODEV; > @@ -324,11 +317,17 @@ static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu, > return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode, ops); > } > > -static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) > +struct viot_pci_iommu_alias_info { > + struct device *dev; > + viot_for_each_fn fn; > + void *info; > +}; > + > +static int __for_each_pci_alias(struct pci_dev *pdev, u16 dev_id, void *data) > { > u32 epid; > struct viot_endpoint *ep; > - struct device *aliased_dev = data; > + struct viot_pci_iommu_alias_info *info = data; > u32 domain_nr = pci_domain_nr(pdev->bus); > > list_for_each_entry(ep, &viot_pci_ranges, list) { > @@ -339,14 +338,14 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) > epid = ((domain_nr - ep->segment_start) << 16) + > dev_id - ep->bdf_start + ep->endpoint_id; > > - return viot_dev_iommu_init(aliased_dev, ep->viommu, > - epid); > + return info->fn(ep->viommu, epid, info->info); > } > } > return -ENODEV; > } > > -static int viot_mmio_dev_iommu_init(struct platform_device *pdev) > +static int __for_each_platform(struct platform_device *pdev, > + viot_for_each_fn fn, void *info) > { > struct resource *mem; > struct viot_endpoint *ep; > @@ -357,12 +356,28 @@ static int viot_mmio_dev_iommu_init(struct platform_device *pdev) > > list_for_each_entry(ep, &viot_mmio_endpoints, list) { > if (ep->address == mem->start) > - return viot_dev_iommu_init(&pdev->dev, ep->viommu, > - ep->endpoint_id); > + return fn(ep->viommu, ep->endpoint_id, info); > } > return -ENODEV; > } > > +int viot_iommu_for_each_id(struct device *dev, viot_for_each_fn fn, void *info) > +{ > + if (dev_is_pci(dev)) { > + struct viot_pci_iommu_alias_info pci_info = { > + .dev = dev, > + .fn = fn, > + .info = info, > + }; > + return pci_for_each_dma_alias(to_pci_dev(dev), > + __for_each_pci_alias, &pci_info); > + } > + > + if (dev_is_platform(dev)) > + return __for_each_platform(to_platform_device(dev), fn, info); > + return -ENODEV; > +} > + > /** > * viot_iommu_configure - Setup IOMMU ops for an endpoint described by VIOT > * @dev: the endpoint > @@ -371,10 +386,5 @@ static int viot_mmio_dev_iommu_init(struct platform_device *pdev) > */ > int viot_iommu_configure(struct device *dev) > { > - if (dev_is_pci(dev)) > - return pci_for_each_dma_alias(to_pci_dev(dev), > - viot_pci_dev_iommu_init, dev); > - else if (dev_is_platform(dev)) > - return viot_mmio_dev_iommu_init(to_platform_device(dev)); > - return -ENODEV; > + return viot_iommu_for_each_id(dev, viot_dev_iommu_init, dev); > } > diff --git a/include/linux/acpi_viot.h b/include/linux/acpi_viot.h > index a5a12243156377..fce4eefcae4aad 100644 > --- a/include/linux/acpi_viot.h > +++ b/include/linux/acpi_viot.h > @@ -5,6 +5,17 @@ > > #include <linux/acpi.h> > > +struct viot_iommu { > + /* Node offset within the table */ > + unsigned int offset; > + struct fwnode_handle *fwnode; > + struct list_head list; > +}; > + > +typedef int (*viot_for_each_fn)(struct viot_iommu *viommu, u32 epid, > + void *info); > +int viot_iommu_for_each_id(struct device *dev, viot_for_each_fn fn, void *info); > + > #ifdef CONFIG_ACPI_VIOT > void __init acpi_viot_early_init(void); > void __init acpi_viot_init(void); > -- > 2.42.0 >
diff --git a/drivers/acpi/viot.c b/drivers/acpi/viot.c index c8025921c129b2..7ab35ef05c84e0 100644 --- a/drivers/acpi/viot.c +++ b/drivers/acpi/viot.c @@ -25,13 +25,6 @@ #include <linux/pci.h> #include <linux/platform_device.h> -struct viot_iommu { - /* Node offset within the table */ - unsigned int offset; - struct fwnode_handle *fwnode; - struct list_head list; -}; - struct viot_endpoint { union { /* PCI range */ @@ -304,10 +297,10 @@ void __init acpi_viot_init(void) acpi_put_table(hdr); } -static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu, - u32 epid) +static int viot_dev_iommu_init(struct viot_iommu *viommu, u32 epid, void *info) { const struct iommu_ops *ops; + struct device *dev = info; if (!viommu) return -ENODEV; @@ -324,11 +317,17 @@ static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu, return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode, ops); } -static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) +struct viot_pci_iommu_alias_info { + struct device *dev; + viot_for_each_fn fn; + void *info; +}; + +static int __for_each_pci_alias(struct pci_dev *pdev, u16 dev_id, void *data) { u32 epid; struct viot_endpoint *ep; - struct device *aliased_dev = data; + struct viot_pci_iommu_alias_info *info = data; u32 domain_nr = pci_domain_nr(pdev->bus); list_for_each_entry(ep, &viot_pci_ranges, list) { @@ -339,14 +338,14 @@ static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data) epid = ((domain_nr - ep->segment_start) << 16) + dev_id - ep->bdf_start + ep->endpoint_id; - return viot_dev_iommu_init(aliased_dev, ep->viommu, - epid); + return info->fn(ep->viommu, epid, info->info); } } return -ENODEV; } -static int viot_mmio_dev_iommu_init(struct platform_device *pdev) +static int __for_each_platform(struct platform_device *pdev, + viot_for_each_fn fn, void *info) { struct resource *mem; struct viot_endpoint *ep; @@ -357,12 +356,28 @@ static int viot_mmio_dev_iommu_init(struct platform_device *pdev) list_for_each_entry(ep, &viot_mmio_endpoints, list) { if (ep->address == mem->start) - return viot_dev_iommu_init(&pdev->dev, ep->viommu, - ep->endpoint_id); + return fn(ep->viommu, ep->endpoint_id, info); } return -ENODEV; } +int viot_iommu_for_each_id(struct device *dev, viot_for_each_fn fn, void *info) +{ + if (dev_is_pci(dev)) { + struct viot_pci_iommu_alias_info pci_info = { + .dev = dev, + .fn = fn, + .info = info, + }; + return pci_for_each_dma_alias(to_pci_dev(dev), + __for_each_pci_alias, &pci_info); + } + + if (dev_is_platform(dev)) + return __for_each_platform(to_platform_device(dev), fn, info); + return -ENODEV; +} + /** * viot_iommu_configure - Setup IOMMU ops for an endpoint described by VIOT * @dev: the endpoint @@ -371,10 +386,5 @@ static int viot_mmio_dev_iommu_init(struct platform_device *pdev) */ int viot_iommu_configure(struct device *dev) { - if (dev_is_pci(dev)) - return pci_for_each_dma_alias(to_pci_dev(dev), - viot_pci_dev_iommu_init, dev); - else if (dev_is_platform(dev)) - return viot_mmio_dev_iommu_init(to_platform_device(dev)); - return -ENODEV; + return viot_iommu_for_each_id(dev, viot_dev_iommu_init, dev); } diff --git a/include/linux/acpi_viot.h b/include/linux/acpi_viot.h index a5a12243156377..fce4eefcae4aad 100644 --- a/include/linux/acpi_viot.h +++ b/include/linux/acpi_viot.h @@ -5,6 +5,17 @@ #include <linux/acpi.h> +struct viot_iommu { + /* Node offset within the table */ + unsigned int offset; + struct fwnode_handle *fwnode; + struct list_head list; +}; + +typedef int (*viot_for_each_fn)(struct viot_iommu *viommu, u32 epid, + void *info); +int viot_iommu_for_each_id(struct device *dev, viot_for_each_fn fn, void *info); + #ifdef CONFIG_ACPI_VIOT void __init acpi_viot_early_init(void); void __init acpi_viot_init(void);
Similar to of_iommu_for_each_id() this parses the VIOT ACPI description and invokes a function over each entry in the table. Have viot_iommu_configure() use the new function to call viot_dev_iommu_init(). Signed-off-by: Jason Gunthorpe <jgg@nvidia.com> --- drivers/acpi/viot.c | 54 +++++++++++++++++++++++---------------- include/linux/acpi_viot.h | 11 ++++++++ 2 files changed, 43 insertions(+), 22 deletions(-)