iommu: Remove iommu_fwspec ops
Subsystems (11)
Robin Murphy
reviewerv3 cover iommu: Remove iommu_fwspec ops
v2: https://lore.kernel.org/linux-iommu/[email protected]/
Hi all,
Just a quick update with an extra patch to avoid the mediatek-v1 driver breaking (and I have now build-tested ARCH=arm to make sure, apologies for being lazy before...)
Thanks,
Robin.
Robin Murphy (5):
iommu/mediatek-v1: Clean up redundant fwspec checks
iommu: Resolve fwspec ops automatically
ACPI: Retire acpi_iommu_fwspec_ops()
OF: Simplify of_iommu_configure()
iommu: Remove iommu_fwspec ops
drivers/acpi/arm64/iort.c | 19 +++------- drivers/acpi/scan.c | 36 +++++-------------- drivers/acpi/viot.c | 11 ++---- drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 +- drivers/iommu/iommu-priv.h | 7 ++++ drivers/iommu/iommu.c | 20 +++++------ drivers/iommu/mtk_iommu_v1.c | 12 ++----- drivers/iommu/of_iommu.c | 50 ++++++++++----------------- drivers/iommu/tegra-smmu.c | 2 +- drivers/of/device.c | 30 ++++++---------- include/acpi/acpi_bus.h | 3 +- include/linux/iommu.h | 15 ++------ 12 files changed, 67 insertions(+), 141 deletions(-)
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v3 1/5 iommu/mediatek-v1: Clean up redundant fwspec checks
The driver explicitly clears any existing fwspec before calling mtk_iommu_v1_create_mapping(), but even if it didn't, the checks it's doing there duplicate what iommu_fwspec_init() would do anyway. Clean them up.
--- drivers/iommu/mtk_iommu_v1.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-)
drivers/iommu/mtk_iommu_v1.c +3 -9
@@ -401,7 +401,6 @@ static const struct iommu_ops mtk_iommu_v1_ops;static int mtk_iommu_v1_create_mapping (struct device *dev,const struct of_phandle_args *args) { -struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev);struct mtk_iommu_v1_data *data;struct platform_device *m4updev;struct dma_iommu_mapping *mtk_mapping;
@@ -413,14 +412,9 @@ static int mtk_iommu_v1_create_mapping(struct device *dev,return -EINVAL ; } -if (!fwspec) { - ret =iommu_fwspec_init (dev, &args->np->fwnode, &mtk_iommu_v1_ops); -if (ret) -return ret; - fwspec =dev_iommu_fwspec_get (dev); - }else if (dev_iommu_fwspec_get (dev)->ops != &mtk_iommu_v1_ops) { -return -EINVAL ; - } + ret =iommu_fwspec_init (dev, &args->np->fwnode, &mtk_iommu_v1_ops); +if (ret) +return ret;if (!dev_iommu_priv_get (dev)) {/* Get the m4u device */
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v3 2/5 iommu: Resolve fwspec ops automatically
In reply to Robin MurphyThere's no real need for callers to resolve ops from a fwnode in order to then pass both to iommu_fwspec_init() - it's simpler and more sensible for that to resolve the ops itself. This in turn means we can centralise the notion of checking for a present driver, and enforce that fwspecs aren't allocated unless and until we know they will be usable.
Also use this opportunity to modernise with some "new" helpers that arrived shortly after this code was first written; the generic fwnode_handle_get() clears up that ugly get/put mismatch, while of_fwnode_handle() can now abstract those open-coded dereferences.
---
v2: Add of_fwnode_handle() cleanup as well
--- drivers/acpi/arm64/iort.c | 19 +++++-------------- drivers/acpi/scan.c | 8 +++----- drivers/acpi/viot.c | 11 ++--------- drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 +-- drivers/iommu/iommu-priv.h | 2 ++ drivers/iommu/iommu.c | 9 ++++++--- drivers/iommu/mtk_iommu_v1.c | 2 +- drivers/iommu/of_iommu.c | 19 ++++++------------- drivers/iommu/tegra-smmu.c | 2 +- include/acpi/acpi_bus.h | 3 +-- include/linux/iommu.h | 13 ++----------- 11 files changed, 30 insertions(+), 61 deletions(-)
drivers/acpi/arm64/iort.c +5 -14
@@ -1221,10 +1221,10 @@ static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)static int iort_iommu_xlate (struct device *dev,struct acpi_iort_node *node,u32 streamid) { -const struct iommu_ops *ops;struct fwnode_handle *iort_fwnode; -if (!node) +/* If there's no SMMU driver at all, give up now */ +if (!node || !iort_iommu_driver_enabled (node->type))return -ENODEV ; iort_fwnode =iort_get_fwnode (node);
@@ -1232,19 +1232,10 @@ static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,return -ENODEV ;/* -* If the ops look-up fails, this means that either -* the SMMU drivers have not been probed yet or that -* the SMMU drivers are not built in the kernel; -* Depending on whether the SMMU drivers are built-in -* in the kernel or not, defer the IOMMU configuration -* or just abort it. +* If the SMMU drivers are enabled but not loaded/probed +* yet, this will defer. */ - ops =iommu_ops_from_fwnode (iort_fwnode); -if (!ops) -return iort_iommu_driver_enabled (node->type) ? - -EPROBE_DEFER : -ENODEV ; - -return acpi_iommu_fwspec_init (dev, streamid, iort_fwnode, ops); +return acpi_iommu_fwspec_init (dev, streamid, iort_fwnode); }struct iort_pci_alias_info {
drivers/acpi/scan.c +3 -5
@@ -1577,12 +1577,11 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)#ifdef CONFIG_IOMMU_API int acpi_iommu_fwspec_init (struct device *dev,u32 id, -struct fwnode_handle *fwnode, -const struct iommu_ops *ops) +struct fwnode_handle *fwnode) {int ret; - ret =iommu_fwspec_init (dev, fwnode, ops); + ret =iommu_fwspec_init (dev, fwnode);if (ret)return ret;
@@ -1639,8 +1638,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)#else /* !CONFIG_IOMMU_API */ int acpi_iommu_fwspec_init (struct device *dev,u32 id, -struct fwnode_handle *fwnode, -const struct iommu_ops *ops) +struct fwnode_handle *fwnode) {return -ENODEV ; }
drivers/acpi/viot.c +2 -9
@@ -307,21 +307,14 @@ void __init acpi_viot_init(void)static int viot_dev_iommu_init (struct device *dev,struct viot_iommu *viommu,u32 epid) { -const struct iommu_ops *ops; - -if (!viommu) +if (!viommu || !IS_ENABLED (CONFIG_VIRTIO_IOMMU ))return -ENODEV ;/* We're not translating ourself */ if (device_match_fwnode (dev, viommu->fwnode))return -EINVAL ; - ops =iommu_ops_from_fwnode (viommu->fwnode); -if (!ops) -return IS_ENABLED (CONFIG_VIRTIO_IOMMU ) ? - -EPROBE_DEFER : -ENODEV ; - -return acpi_iommu_fwspec_init (dev, epid, viommu->fwnode, ops); +return acpi_iommu_fwspec_init (dev, epid, viommu->fwnode); }static int viot_pci_dev_iommu_init (struct pci_dev *pdev,u16 dev_id,void *data)
drivers/iommu/arm/arm-smmu/arm-smmu.c +1 -2
@@ -178,8 +178,7 @@ static int arm_smmu_register_legacy_master(struct device *dev, it.cur_count =1 ; } - err =iommu_fwspec_init (dev, &smmu_dev->of_node->fwnode, - &arm_smmu_ops); + err =iommu_fwspec_init (dev,NULL );if (err)return err;
drivers/iommu/iommu-priv.h +2 -0
@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)return dev->iommu->iommu_dev->ops; } +const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode); +int iommu_group_replace_domain (struct iommu_group *group,struct iommu_domain *new_domain);
drivers/iommu/iommu.c +6 -3
@@ -2822,11 +2822,14 @@ const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnodereturn ops; } -int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode, -const struct iommu_ops *ops) +int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode) { +const struct iommu_ops *ops =iommu_ops_from_fwnode (iommu_fwnode);struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); +if (!ops) +return -EPROBE_DEFER ; +if (fwspec)return ops == fwspec->ops ?0 : -EINVAL ;
@@ -2838,7 +2841,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,if (!fwspec)return -ENOMEM ; -of_node_get (to_of_node (iommu_fwnode)); +fwnode_handle_get (iommu_fwnode); fwspec->iommu_fwnode = iommu_fwnode; fwspec->ops = ops;dev_iommu_fwspec_set (dev, fwspec);
drivers/iommu/mtk_iommu_v1.c +1 -1
@@ -412,7 +412,7 @@ static int mtk_iommu_v1_create_mapping(struct device *dev,return -EINVAL ; } - ret =iommu_fwspec_init (dev, &args->np->fwnode, &mtk_iommu_v1_ops); + ret =iommu_fwspec_init (dev,of_fwnode_handle (args->np));if (ret)return ret;
drivers/iommu/of_iommu.c +6 -13
@@ -21,26 +21,19 @@ static int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec) {const struct iommu_ops *ops; -struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;int ret; - ops =iommu_ops_from_fwnode (fwnode); -if ((ops && !ops->of_xlate) || - !of_device_is_available (iommu_spec->np)) +if (!of_device_is_available (iommu_spec->np))return -ENODEV ; - ret =iommu_fwspec_init (dev, fwnode, ops); + ret =iommu_fwspec_init (dev,of_fwnode_handle (iommu_spec->np)); +if (ret == -EPROBE_DEFER ) +return driver_deferred_probe_check_state (dev);if (ret)return ret; -/* -* The otherwise-empty fwspec handily serves to indicate the specific -* IOMMU device we're waiting for, which will be useful if we ever get -* a proper probe-ordering dependency mechanism in future. -*/ -if (!ops) -return driver_deferred_probe_check_state (dev); -if (!try_module_get (ops->owner)) + ops =dev_iommu_fwspec_get (dev)->ops; +if (!ops->of_xlate || !try_module_get (ops->owner))return -ENODEV ; ret = ops->of_xlate (dev, iommu_spec);
drivers/iommu/tegra-smmu.c +1 -1
@@ -837,7 +837,7 @@ static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev,const struct iommu_ops *ops = smmu->iommu.ops;int err; - err =iommu_fwspec_init (dev, &dev->of_node->fwnode, ops); + err =iommu_fwspec_init (dev,of_fwnode_handle (dev->of_node));if (err <0 ) {dev_err (dev,"failed to initialize fwspec: %d\n" , err);return err;
include/acpi/acpi_bus.h +1 -2
@@ -736,8 +736,7 @@ struct iommu_ops;bool acpi_dma_supported (const struct acpi_device *adev);enum dev_dma_attr acpi_get_dma_attr (struct acpi_device *adev);int acpi_iommu_fwspec_init (struct device *dev,u32 id, -struct fwnode_handle *fwnode, -const struct iommu_ops *ops); +struct fwnode_handle *fwnode);int acpi_dma_get_range (struct device *dev,const struct bus_dma_region **map);int acpi_dma_configure_id (struct device *dev,enum dev_dma_attr attr,const u32 *input_id);
include/linux/iommu.h +2 -11
@@ -1005,11 +1005,9 @@ struct iommu_mm_data {struct list_head sva_handles; }; -int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode, -const struct iommu_ops *ops); +int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode);void iommu_fwspec_free (struct device *dev);int iommu_fwspec_add_ids (struct device *dev,const u32 *ids,int num_ids); -const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode);static inline struct iommu_fwspec *dev_iommu_fwspec_get (struct device *dev) {
@@ -1315,8 +1313,7 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link) }static inline int iommu_fwspec_init (struct device *dev, -struct fwnode_handle *iommu_fwnode, -const struct iommu_ops *ops) +struct fwnode_handle *iommu_fwnode) {return -ENODEV ; }
@@ -1331,12 +1328,6 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,return -ENODEV ; } -static inline -const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode) -{ -return NULL ; -} -static inline int iommu_dev_enable_feature (struct device *dev,enum iommu_dev_features feat) {
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Jon Hunter
maintainerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
Hi Robin,
Quoted 290 lines · Robin Murphy
There's no real need for callers to resolve ops from a fwnode in order to then pass both to
iommu_fwspec_init()- it's simpler and more sensible for that to resolve the ops itself. This in turn means we can centralise the notion of checking for a present driver, and enforce that fwspecs aren't allocated unless and until we know they will be usable.Also use this opportunity to modernise with some "new" helpers that arrived shortly after this code was first written; the generic
fwnode_handle_get()clears up that ugly get/put mismatch, whileof_fwnode_handle()can now abstract those open-coded dereferences.Signed-off-by Robin Murphy <[email protected]>---
v2: Addof_fwnode_handle()cleanup as well--- drivers/acpi/arm64/iort.c | 19 +++++-------------- drivers/acpi/scan.c | 8 +++----- drivers/acpi/viot.c | 11 ++--------- drivers/iommu/arm/arm-smmu/arm-smmu.c | 3 +-- drivers/iommu/iommu-priv.h | 2 ++ drivers/iommu/iommu.c | 9 ++++++--- drivers/iommu/mtk_iommu_v1.c | 2 +- drivers/iommu/of_iommu.c | 19 ++++++------------- drivers/iommu/tegra-smmu.c | 2 +- include/acpi/acpi_bus.h | 3 +-- include/linux/iommu.h | 13 ++----------- 11 files changed, 30 insertions(+), 61 deletions(-)drivers/acpi/arm64/iort.c +5
-14@@ -1221,10 +1221,10 @@ static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node)static int iort_iommu_xlate (struct device *dev,struct acpi_iort_node *node,u32 streamid) { -const struct iommu_ops *ops;struct fwnode_handle *iort_fwnode; -if (!node) +/* If there's no SMMU driver at all, give up now */ +if (!node || !iort_iommu_driver_enabled (node->type))return -ENODEV ; iort_fwnode =iort_get_fwnode (node);@@ -1232,19 +1232,10 @@ static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node,return -ENODEV ;/* -* If the ops look-up fails, this means that either -* the SMMU drivers have not been probed yet or that -* the SMMU drivers are not built in the kernel; -* Depending on whether the SMMU drivers are built-in -* in the kernel or not, defer the IOMMU configuration -* or just abort it. +* If the SMMU drivers are enabled but not loaded/probed +* yet, this will defer. */ - ops =iommu_ops_from_fwnode (iort_fwnode); -if (!ops) -return iort_iommu_driver_enabled (node->type) ? - -EPROBE_DEFER : -ENODEV ; - -return acpi_iommu_fwspec_init (dev, streamid, iort_fwnode, ops); +return acpi_iommu_fwspec_init (dev, streamid, iort_fwnode); }struct iort_pci_alias_info {drivers/acpi/scan.c +3
-5@@ -1577,12 +1577,11 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map)#ifdef CONFIG_IOMMU_API int acpi_iommu_fwspec_init (struct device *dev,u32 id, -struct fwnode_handle *fwnode, -const struct iommu_ops *ops) +struct fwnode_handle *fwnode) {int ret; - ret =iommu_fwspec_init (dev, fwnode, ops); + ret =iommu_fwspec_init (dev, fwnode);if (ret)return ret;@@ -1639,8 +1638,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)#else /* !CONFIG_IOMMU_API */ int acpi_iommu_fwspec_init (struct device *dev,u32 id, -struct fwnode_handle *fwnode, -const struct iommu_ops *ops) +struct fwnode_handle *fwnode) {return -ENODEV ; }drivers/acpi/viot.c +2
-9@@ -307,21 +307,14 @@ void __init acpi_viot_init(void)static int viot_dev_iommu_init (struct device *dev,struct viot_iommu *viommu,u32 epid) { -const struct iommu_ops *ops; - -if (!viommu) +if (!viommu || !IS_ENABLED (CONFIG_VIRTIO_IOMMU ))return -ENODEV ;/* We're not translating ourself */ if (device_match_fwnode (dev, viommu->fwnode))return -EINVAL ; - ops =iommu_ops_from_fwnode (viommu->fwnode); -if (!ops) -return IS_ENABLED (CONFIG_VIRTIO_IOMMU ) ? - -EPROBE_DEFER : -ENODEV ; - -return acpi_iommu_fwspec_init (dev, epid, viommu->fwnode, ops); +return acpi_iommu_fwspec_init (dev, epid, viommu->fwnode); }static int viot_pci_dev_iommu_init (struct pci_dev *pdev,u16 dev_id,void *data)drivers/iommu/arm/arm-smmu/arm-smmu.c +1
-2@@ -178,8 +178,7 @@ static int arm_smmu_register_legacy_master(struct device *dev, it.cur_count =1 ; } - err =iommu_fwspec_init (dev, &smmu_dev->of_node->fwnode, - &arm_smmu_ops); + err =iommu_fwspec_init (dev,NULL );if (err)return err;drivers/iommu/iommu-priv.h +2
-0@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)return dev->iommu->iommu_dev->ops; } +const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode); +int iommu_group_replace_domain (struct iommu_group *group,struct iommu_domain *new_domain);drivers/iommu/iommu.c +6
-3@@ -2822,11 +2822,14 @@ const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnodereturn ops; } -int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode, -const struct iommu_ops *ops) +int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode) { +const struct iommu_ops *ops =iommu_ops_from_fwnode (iommu_fwnode);struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); +if (!ops) +return -EPROBE_DEFER ; +if (fwspec)return ops == fwspec->ops ?0 : -EINVAL ;@@ -2838,7 +2841,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,if (!fwspec)return -ENOMEM ; -of_node_get (to_of_node (iommu_fwnode)); +fwnode_handle_get (iommu_fwnode); fwspec->iommu_fwnode = iommu_fwnode; fwspec->ops = ops;dev_iommu_fwspec_set (dev, fwspec);drivers/iommu/mtk_iommu_v1.c +1
-1@@ -412,7 +412,7 @@ static int mtk_iommu_v1_create_mapping(struct device *dev,return -EINVAL ; } - ret =iommu_fwspec_init (dev, &args->np->fwnode, &mtk_iommu_v1_ops); + ret =iommu_fwspec_init (dev,of_fwnode_handle (args->np));if (ret)return ret;drivers/iommu/of_iommu.c +6
-13@@ -21,26 +21,19 @@ static int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec) {const struct iommu_ops *ops; -struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;int ret; - ops =iommu_ops_from_fwnode (fwnode); -if ((ops && !ops->of_xlate) || - !of_device_is_available (iommu_spec->np)) +if (!of_device_is_available (iommu_spec->np))return -ENODEV ; - ret =iommu_fwspec_init (dev, fwnode, ops); + ret =iommu_fwspec_init (dev,of_fwnode_handle (iommu_spec->np)); +if (ret == -EPROBE_DEFER ) +return driver_deferred_probe_check_state (dev);if (ret)return ret; -/* -* The otherwise-empty fwspec handily serves to indicate the specific -* IOMMU device we're waiting for, which will be useful if we ever get -* a proper probe-ordering dependency mechanism in future. -*/ -if (!ops) -return driver_deferred_probe_check_state (dev); -if (!try_module_get (ops->owner)) + ops =dev_iommu_fwspec_get (dev)->ops; +if (!ops->of_xlate || !try_module_get (ops->owner))return -ENODEV ; ret = ops->of_xlate (dev, iommu_spec);drivers/iommu/tegra-smmu.c +1
-1@@ -837,7 +837,7 @@ static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev,const struct iommu_ops *ops = smmu->iommu.ops;int err; - err =iommu_fwspec_init (dev, &dev->of_node->fwnode, ops); + err =iommu_fwspec_init (dev,of_fwnode_handle (dev->of_node));if (err <0 ) {dev_err (dev,"failed to initialize fwspec: %d\n" , err);return err;include/acpi/acpi_bus.h +1
-2@@ -736,8 +736,7 @@ struct iommu_ops;bool acpi_dma_supported (const struct acpi_device *adev);enum dev_dma_attr acpi_get_dma_attr (struct acpi_device *adev);int acpi_iommu_fwspec_init (struct device *dev,u32 id, -struct fwnode_handle *fwnode, -const struct iommu_ops *ops); +struct fwnode_handle *fwnode);int acpi_dma_get_range (struct device *dev,const struct bus_dma_region **map);int acpi_dma_configure_id (struct device *dev,enum dev_dma_attr attr,const u32 *input_id);include/linux/iommu.h +2
-5@@ -1005,11 +1005,9 @@ struct iommu_mm_data {struct list_head sva_handles; }; -int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode, -const struct iommu_ops *ops); +int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode);void iommu_fwspec_free (struct device *dev);int iommu_fwspec_add_ids (struct device *dev,const u32 *ids,int num_ids); -const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode);static inline struct iommu_fwspec *dev_iommu_fwspec_get (struct device *dev) {@@ -1315,8 +1313,7 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link) }static inline int iommu_fwspec_init (struct device *dev, -struct fwnode_handle *iommu_fwnode, -const struct iommu_ops *ops) +struct fwnode_handle *iommu_fwnode) {return -ENODEV ; }@@ -1331,12 +1328,6 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids,return -ENODEV ; }
include/linux/iommu.h static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids, · line 1333
Quoted 10 lines
include/linux/iommu.h +0
-6-static inline -const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode) -{ -return NULL ; -} -static inline int iommu_dev_enable_feature (struct device *dev,enum iommu_dev_features feat) {
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Cheers
Jon
Signature · 1 line
nvpublic
Robin Murphy
reviewerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
Quoted 298 lines · Jon Hunter
Hi Robin,
Quoted 288 lines · Robin Murphy
There's no real need for callers to resolve ops from a fwnode in order to then pass both to
iommu_fwspec_init()- it's simpler and more sensible for that to resolve the ops itself. This in turn means we can centralise the notion of checking for a present driver, and enforce that fwspecs aren't allocated unless and until we know they will be usable.Also use this opportunity to modernise with some "new" helpers that arrived shortly after this code was first written; the generic
fwnode_handle_get()clears up that ugly get/put mismatch, whileof_fwnode_handle()can now abstract those open-coded dereferences.Signed-off-by Robin Murphy <[email protected]>---
v2: Addof_fwnode_handle()cleanup as well
---
drivers/acpi/arm64/iort.c | 19 +++++-------------- drivers/acpi/scan.c | 8 +++----- drivers/acpi/viot.c | 11 ++---------drivers/iommu/arm/arm-smmu/arm-smmu.c| 3 +-- drivers/iommu/iommu-priv.h | 2 ++ drivers/iommu/iommu.c | 9 ++++++--- drivers/iommu/mtk_iommu_v1.c | 2 +- drivers/iommu/of_iommu.c | 19 ++++++------------- drivers/iommu/tegra-smmu.c | 2 +- include/acpi/acpi_bus.h | 3 +-- include/linux/iommu.h | 13 ++-----------11 files changed, 30 insertions(+), 61 deletions(-)drivers/acpi/arm64/iort.c +5
-14@@ -1221,10 +1221,10 @@ static bool iort_pci_rc_supports_ats(struct acpi_iort_node *node) static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node, u32 streamid) { - const struct iommu_ops *ops; struct fwnode_handle *iort_fwnode; - if (!node) + /* If there's no SMMU driver at all, give up now */ + if (!node || !iort_iommu_driver_enabled(node->type)) return -ENODEV; iort_fwnode = iort_get_fwnode(node);@@ -1232,19 +1232,10 @@ static int iort_iommu_xlate(struct device *dev, struct acpi_iort_node *node, return -ENODEV; /* - * If the ops look-up fails, this means that either - * the SMMU drivers have not been probed yet or that - * the SMMU drivers are not built in the kernel; - * Depending on whether the SMMU drivers are built-in - * in the kernel or not, defer the IOMMU configuration - * or just abort it. + * If the SMMU drivers are enabled but not loaded/probed + * yet, this will defer. */ - ops = iommu_ops_from_fwnode(iort_fwnode); - if (!ops) - return iort_iommu_driver_enabled(node->type) ? - -EPROBE_DEFER : -ENODEV; - - return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode, ops); + return acpi_iommu_fwspec_init(dev, streamid, iort_fwnode); } struct iort_pci_alias_info {drivers/acpi/scan.c +3
-5@@ -1577,12 +1577,11 @@ int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map) #ifdef CONFIG_IOMMU_API int acpi_iommu_fwspec_init(struct device *dev, u32 id, - struct fwnode_handle *fwnode, - const struct iommu_ops *ops) + struct fwnode_handle *fwnode) { int ret; - ret = iommu_fwspec_init(dev, fwnode, ops); + ret = iommu_fwspec_init(dev, fwnode); if (ret) return ret;@@ -1639,8 +1638,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in) #else /* !CONFIG_IOMMU_API */ int acpi_iommu_fwspec_init(struct device *dev, u32 id, - struct fwnode_handle *fwnode, - const struct iommu_ops *ops) + struct fwnode_handle *fwnode) { return -ENODEV; }drivers/acpi/viot.c +2
-9@@ -307,21 +307,14 @@ void __init acpi_viot_init(void) static int viot_dev_iommu_init(struct device *dev, struct viot_iommu *viommu, u32 epid) { - const struct iommu_ops *ops; - - if (!viommu) + if (!viommu || !IS_ENABLED(CONFIG_VIRTIO_IOMMU)) return -ENODEV; /* We're not translating ourself */ if (device_match_fwnode(dev, viommu->fwnode)) return -EINVAL; - ops = iommu_ops_from_fwnode(viommu->fwnode); - if (!ops) - return IS_ENABLED(CONFIG_VIRTIO_IOMMU) ? - -EPROBE_DEFER : -ENODEV; - - return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode, ops); + return acpi_iommu_fwspec_init(dev, epid, viommu->fwnode); } static int viot_pci_dev_iommu_init(struct pci_dev *pdev, u16 dev_id, void *data)drivers/iommu/arm/arm-smmu/arm-smmu.c +1
-2@@ -178,8 +178,7 @@ static int arm_smmu_register_legacy_master(structdevice *dev, it.cur_count = 1; } - err = iommu_fwspec_init(dev, &smmu_dev->of_node->fwnode, - &arm_smmu_ops); + err = iommu_fwspec_init(dev, NULL); if (err) return err;drivers/iommu/iommu-priv.h +2
-0@@ -17,6 +17,8 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev) return dev->iommu->iommu_dev->ops; } +const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode); + int iommu_group_replace_domain(struct iommu_group *group, struct iommu_domain *new_domain);drivers/iommu/iommu.c +6
-3@@ -2822,11 +2822,14 @@ const struct iommu_ops *iommu_ops_from_fwnode(const struct fwnode_handle *fwnode return ops; } -int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode, - const struct iommu_ops *ops) +int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode) { + const struct iommu_ops *ops = iommu_ops_from_fwnode(iommu_fwnode); struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev); + if (!ops) + return -EPROBE_DEFER; + if (fwspec) return ops == fwspec->ops ? 0 : -EINVAL;@@ -2838,7 +2841,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, if (!fwspec) return -ENOMEM; - of_node_get(to_of_node(iommu_fwnode)); + fwnode_handle_get(iommu_fwnode); fwspec->iommu_fwnode = iommu_fwnode; fwspec->ops = ops; dev_iommu_fwspec_set(dev, fwspec);drivers/iommu/mtk_iommu_v1.c +1
-1@@ -412,7 +412,7 @@ static int mtk_iommu_v1_create_mapping(structdevice *dev, return -EINVAL; } - ret = iommu_fwspec_init(dev, &args->np->fwnode, &mtk_iommu_v1_ops); + ret = iommu_fwspec_init(dev, of_fwnode_handle(args->np)); if (ret) return ret;drivers/iommu/of_iommu.c +4
-7@@ -21,26 +21,19 @@ static int of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec) { const struct iommu_ops *ops; - struct fwnode_handle *fwnode = &iommu_spec->np->fwnode; int ret; - ops = iommu_ops_from_fwnode(fwnode); - if ((ops && !ops->of_xlate) || - !of_device_is_available(iommu_spec->np)) + if (!of_device_is_available(iommu_spec->np)) return -ENODEV; - ret = iommu_fwspec_init(dev, fwnode, ops); + ret = iommu_fwspec_init(dev, of_fwnode_handle(iommu_spec->np)); + if (ret == -EPROBE_DEFER) + return driver_deferred_probe_check_state(dev); if (ret) return ret; - /* -* The otherwise-empty fwspec handily serves to indicate the specific
- * IOMMU device we're waiting for, which will be useful if we ever get
- * a proper probe-ordering dependency mechanism in future. - */
- if (!ops)
- returndriver_deferred_probe_check_state(dev); - if (!try_module_get(ops->owner))
+ ops = dev_iommu_fwspec_get(dev)->ops;
+ if (!ops->of_xlate || !try_module_get(ops->owner)) return-ENODEV;
ret =ops->of_xlate(dev, iommu_spec);drivers/iommu/tegra-smmu.c +1
-1@@ -837,7 +837,7 @@ static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev, const struct iommu_ops *ops = smmu->iommu.ops; int err; - err = iommu_fwspec_init(dev, &dev->of_node->fwnode, ops); + err = iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); if (err < 0) { dev_err(dev, "failed to initialize fwspec: %d\n", err); return err;include/acpi/acpi_bus.h +1
-2@@ -736,8 +736,7 @@ struct iommu_ops; bool acpi_dma_supported(const struct acpi_device *adev); enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev); int acpi_iommu_fwspec_init(struct device *dev, u32 id, - struct fwnode_handle *fwnode, - const struct iommu_ops *ops); + struct fwnode_handle *fwnode); int acpi_dma_get_range(struct device *dev, const struct bus_dma_region **map); int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr, const u32 *input_id);include/linux/iommu.h +1
-3@@ -1005,11 +1005,9 @@ struct iommu_mm_data { struct list_head sva_handles; }; -int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode, - const struct iommu_ops *ops); +int iommu_fwspec_init (struct device *dev,struct fwnode_handle *iommu_fwnode); void iommu_fwspec_free(struct device *dev); int iommu_fwspec_add_ids(struct device *dev, const u32 *ids, int num_ids); -const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode); static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev){
include/linux/iommu.h +1
-8@@ -1315,8 +1313,7 @@ static inline void iommu_device_unlink(struct device *dev, struct device *link) } static inline int iommu_fwspec_init(struct device *dev, - struct fwnode_handle *iommu_fwnode, - const struct iommu_ops *ops) + struct fwnode_handle *iommu_fwnode) { return -ENODEV; }@@ -1331,12 +1328,6 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids, return -ENODEV; } -static inline -const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode) -{ - return NULL; -} -Quoted 3 lines
static inline int
iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features feat){I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
Quoted 4 lines
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
I *think* it should probably just be a case of:
- err = iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node));
+ err = iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));
since smmu->dev appears to be the same one initially passed to iommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.
(Also now I'm wondering why I didn't just use dev_fwnode() there...)
Thanks,
Robin.
Jon Hunter
maintainerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
On 12/07/2024 12:48, Robin Murphy wrote:
...
Quoted 9 lines
Quoted 6 lines
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
Quoted 8 lines
I *think* it should probably just be a case of:
- err =
iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); + err =iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));since
smmu->devappears to be the same one initially passed toiommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.(Also now I'm wondering why I didn't just use
dev_fwnode()there...)
Yes making that change in the tegra-smmu driver does fix it.
Thanks!
Jon
Signature · 1 line
nvpublic
Will Deacon
maintainerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
Quoted 32 lines · Jon Hunter
On 12/07/2024 12:48, Robin Murphy wrote:
...
Quoted 27 lines
Quoted 4 lines
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
Quoted 8 lines
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
I *think* it should probably just be a case of:
- err =
iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); + err =iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));since
smmu->devappears to be the same one initially passed toiommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.
Quoted 4 lines
Quoted 1 line
(Also now I'm wondering why I didn't just use
dev_fwnode()there...)Yes making that change in the tegra-smmu driver does fix it.
Fantastic! I'll pick it up right now.
Cheers,
Will
Robin Murphy
reviewerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
In reply to Jon HunterQuoted 19 lines · Jon Hunter
On 12/07/2024 12:48, Robin Murphy wrote:
...
Quoted 14 lines
Quoted 6 lines
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
I *think* it should probably just be a case of:
- err =
iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); + err =iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));
Quoted 6 lines
Quoted 3 lines
since
smmu->devappears to be the same one initially passed toiommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.(Also now I'm wondering why I didn't just use
dev_fwnode()there...)Yes making that change in the tegra-smmu driver does fix it.
Ace, thanks for confirming! I was just writing a follow-up to say that I've pretty much convinced myself that this (proper diff below) should in fact be the right thing to do in general as well :)
Will, Joerg, would you prefer to have a standalone fix patch for the nvidia/tegra branch to then re-merge fwspec-ops-removal and fix up the conflict, or just a patch on top of fwspec-ops-removal as below?
Thanks,
Robin.
----->8-----
drivers/iommu/tegra-smmu.c +1 -1
@@ -837,7 +837,7 @@ static int tegra_smmu_configure(struct tegra_smmu *smmu, struct device *dev,const struct iommu_ops *ops = smmu->iommu.ops;int err; - err =iommu_fwspec_init (dev,of_fwnode_handle (dev->of_node)); + err =iommu_fwspec_init (dev,dev_fwnode (smmu->dev));if (err <0 ) {dev_err (dev,"failed to initialize fwspec: %d\n" , err);return err;
Will Deacon
maintainerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
Quoted 38 lines · Robin Murphy
Quoted 32 lines · Jon Hunter
On 12/07/2024 12:48, Robin Murphy wrote:
...
Quoted 27 lines
Quoted 4 lines
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
Quoted 8 lines
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
I *think* it should probably just be a case of:
- err =
iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); + err =iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));since
smmu->devappears to be the same one initially passed toiommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.Quoted 4 lines
Quoted 1 line
(Also now I'm wondering why I didn't just use
dev_fwnode()there...)Yes making that change in the tegra-smmu driver does fix it.
Quoted 7 lines
Ace, thanks for confirming! I was just writing a follow-up to say that I've pretty much convinced myself that this (proper diff below) should in fact be the right thing to do in general as well :)
Will, Joerg, would you prefer to have a standalone fix patch for the nvidia/tegra branch to then re-merge fwspec-ops-removal and fix up the conflict, or just a patch on top of fwspec-ops-removal as below?
I've just fixed it locally on the tegra branch, so I'll then just resolve the conflict with fwspec-ops-removal the right way. That way, we can backport the thing if we need to.
Cheers,
Will
Robin Murphy
reviewerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
Quoted 43 lines · Will Deacon
Quoted 42 lines · Robin Murphy
Quoted 32 lines · Jon Hunter
On 12/07/2024 12:48, Robin Murphy wrote:
...
Quoted 27 lines
Quoted 4 lines
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
Quoted 8 lines
��tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 ��nouveau 57000000.gpu: failed to initialize fwspec: -517
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
I *think* it should probably just be a case of:
-��� err =
iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); +��� err =iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));since
smmu->devappears to be the same one initially passed toiommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.Quoted 4 lines
Quoted 1 line
(Also now I'm wondering why I didn't just use
dev_fwnode()there...)Yes making that change in the tegra-smmu driver does fix it.
Ace, thanks for confirming! I was just writing a follow-up to say that I've pretty much convinced myself that this (proper diff below) should in fact be the right thing to do in general as well :)
Quoted 7 lines
Quoted 3 lines
Will, Joerg, would you prefer to have a standalone fix patch for the nvidia/tegra branch to then re-merge fwspec-ops-removal and fix up the conflict, or just a patch on top of fwspec-ops-removal as below?
I've just fixed it locally on the tegra branch, so I'll then just resolve the conflict with fwspec-ops-removal the right way. That way, we can backport the thing if we need to.
Cool, thanks for taking care of it!
Robin.
Will Deacon
maintainerRe: [PATCH v3 2/5] iommu: Resolve fwspec ops automatically
In reply to Robin MurphyQuoted 8 lines · Robin Murphy
Quoted 7 lines · Jon Hunter
I am seeing some failures on -next with some of our devices. Bisect is pointing to this commit. Looks like the host1x device is no longer probing successfully. I see the following ...
tegra-host1x 50000000.host1x: failed to initialize fwspec: -517 nouveau 57000000.gpu: failed to initialize fwspec: -517
Quoted 8 lines
Quoted 4 lines
The probe seems to be deferred forever. The above is seen on Tegra210 but Tegra30 and Tegra194 are also having the same problem. Interestingly it is not all devices and so make me wonder if we are missing something on these devices? Let me know if you have any thoughts.
Ugh, tegra-smmu has been doing a complete nonsense this whole time - on closer inspection, it's passing the fwnode of the *client device* where it should be that of the IOMMU device :(
Ha, so it is!
Quoted 9 lines
I *think* it should probably just be a case of:
(quoted diff) +1
-1- err = iommu_fwspec_init(dev, of_fwnode_handle(dev->of_node)); + err = iommu_fwspec_init(dev, of_fwnode_handle(smmu->dev->of_node));since
smmu->devappears to be the same one initially passed toiommu_device_register(), so it at least ought to match and work, but the SMMU device vs. MC device thing leaves me mildly wary of how correct it might be overall.
Jon -- any chance you could give this fix a go, please? I'm hesitant to drop the whole branch just for this, but we've basically run out of time for 6.11 and so knowing we have a working fix would be really helpful.
Cheers,
Will
Robin Murphy
reviewerPATCH v3 3/5 ACPI: Retire acpi_iommu_fwspec_ops()
In reply to Robin MurphyNow that iommu_fwspec_init() can signal for probe deferral directly, acpi_iommu_fwspec_ops() is unneeded and can be cleaned up.
--- drivers/acpi/scan.c | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-)
drivers/acpi/scan.c +5 -23
@@ -1588,26 +1588,14 @@ int acpi_iommu_fwspec_init(struct device *dev, u32 id,return iommu_fwspec_add_ids (dev, &id,1 ); } -static inline const struct iommu_ops *acpi_iommu_fwspec_ops (struct device *dev) -{ -struct iommu_fwspec *fwspec =dev_iommu_fwspec_get (dev); - -return fwspec ? fwspec->ops :NULL ; -} -static int acpi_iommu_configure_id (struct device *dev,const u32 *id_in) {int err; -const struct iommu_ops *ops;/* Serialise to make dev->iommu stable under our potential fwspec */ mutex_lock (&iommu_probe_device_lock); -/* -* If we already translated the fwspec there is nothing left to do, -* return the iommu_ops. -*/ - ops =acpi_iommu_fwspec_ops (dev); -if (ops) { +/* If we already translated the fwspec there is nothing left to do */ +if (dev_iommu_fwspec_get (dev)) {mutex_unlock (&iommu_probe_device_lock);return 0 ; }
@@ -1624,15 +1612,7 @@ static int acpi_iommu_configure_id(struct device *dev, const u32 *id_in)if (!err && dev->bus) err =iommu_probe_device (dev); -if (err == -EPROBE_DEFER ) -return err; -if (err) { -dev_dbg (dev,"Adding to IOMMU failed: %d\n" , err); -return err; - } -if (!acpi_iommu_fwspec_ops (dev)) -return -ENODEV ; - return 0; + return err; }#else /* !CONFIG_IOMMU_API */
@@ -1672,6 +1652,8 @@ int acpi_dma_configure_id(struct device *dev, enum dev_dma_attr attr, ret =acpi_iommu_configure_id (dev, input_id);if (ret == -EPROBE_DEFER )return -EPROBE_DEFER ; +if (ret) +dev_dbg (dev,"Adding to IOMMU failed: %d\n" , ret);arch_setup_dma_ops (dev, attr ==DEV_DMA_COHERENT );
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v3 4/5 OF: Simplify of_iommu_configure()
In reply to Robin MurphyWe no longer have a notion of partially-initialised fwspecs existing, and we also no longer need to use an iommu_ops pointer to return status to of_dma_configure(). Clean up the remains of those, which lends itself to clarifying the logic around the dma_range_map allocation as well.
--- drivers/iommu/of_iommu.c | 29 ++++++++++------------------- drivers/of/device.c | 30 +++++++++++------------------- 2 files changed, 21 insertions(+), 38 deletions(-)
drivers/iommu/of_iommu.c +10 -19
@@ -108,7 +108,6 @@ static int of_iommu_configure_device(struct device_node *master_np,int of_iommu_configure (struct device *dev,struct device_node *master_np,const u32 *id) { -struct iommu_fwspec *fwspec;int err;if (!master_np)
@@ -116,14 +115,9 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np,/* Serialise to make dev->iommu stable under our potential fwspec */ mutex_lock (&iommu_probe_device_lock); - fwspec =dev_iommu_fwspec_get (dev); -if (fwspec) { -if (fwspec->ops) { -mutex_unlock (&iommu_probe_device_lock); -return 0 ; - } -/* In the deferred case, start again from scratch */ -iommu_fwspec_free (dev); +if (dev_iommu_fwspec_get (dev)) { +mutex_unlock (&iommu_probe_device_lock); +return 0 ; }/*
@@ -143,20 +137,17 @@ int of_iommu_configure(struct device *dev, struct device_node *master_np, }else { err =of_iommu_configure_device (master_np, dev, id); } + +if (err) +iommu_fwspec_free (dev);mutex_unlock (&iommu_probe_device_lock); -if (err == -ENODEV || err == -EPROBE_DEFER ) -return err; -if (err) - goto err_log; +if (!err && dev->bus) + err =iommu_probe_device (dev); - err =iommu_probe_device (dev); -if (err) - goto err_log; -return 0 ; +if (err && err != -EPROBE_DEFER ) +dev_dbg (dev,"Adding to IOMMU failed: %d\n" , err); -err_log: -dev_dbg (dev,"Adding to IOMMU failed: %pe\n" ,ERR_PTR (err));return err; }
drivers/of/device.c +11 -19
@@ -96,8 +96,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,const struct bus_dma_region *map =NULL ;struct device_node *bus_np;u64 mask, end =0 ; -bool coherent; -int iommu_ret; +bool coherent, set_map = false;int ret;if (np == dev->of_node)
@@ -118,6 +117,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np, }else {/* Determine the overall bounds of all DMA regions */ end =dma_range_map_max (map); + set_map = true; }/*
@@ -144,7 +144,7 @@ int of_dma_configure_id(struct device *dev, struct device_node *np, dev->coherent_dma_mask &= mask; *dev->dma_mask &= mask;/* ...but only set bus limit and range map if we found valid dma-ranges earlier */ -if (!ret) { +if (set_map) { dev->bus_dma_limit = end; dev->dma_range_map = map; }
@@ -153,29 +153,21 @@ int of_dma_configure_id(struct device *dev, struct device_node *np,dev_dbg (dev,"device is%sdma coherent\n" , coherent ?" " :" not " ); - iommu_ret =of_iommu_configure (dev, np, id); -if (iommu_ret == -EPROBE_DEFER ) { + ret =of_iommu_configure (dev, np, id); +if (ret == -EPROBE_DEFER ) {/* Don't touch range map if it wasn't set from a valid dma-ranges */ -if (!ret) +if (set_map) dev->dma_range_map =NULL ;kfree (map);return -EPROBE_DEFER ; - }else if (iommu_ret == -ENODEV ) { -dev_dbg (dev,"device is not behind an iommu\n" ); - }else if (iommu_ret) { -dev_err (dev,"iommu configuration for device failed with %pe\n" , -ERR_PTR (iommu_ret)); - -/* -* Historically this routine doesn't fail driver probing -* due to errors in of_iommu_configure() -*/ - }else -dev_dbg (dev,"device is behind an iommu\n" ); + } +/* Take all other IOMMU errors to mean we'll just carry on without it */ +dev_dbg (dev,"device is%sbehind an iommu\n" , + !ret ?" " :" not " );arch_setup_dma_ops (dev, coherent); -if (iommu_ret) +if (ret)of_dma_set_restricted_buffer (dev, np);return 0 ;
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Robin Murphy
reviewerPATCH v3 5/5 iommu: Remove iommu_fwspec ops
In reply to Robin MurphyThe ops in iommu_fwspec are only needed for the early configuration and probe process, and by now are easy enough to derive on-demand in those couple of places which need them, so remove the redundant stored copy.
--- drivers/iommu/iommu-priv.h | 5 +++++ drivers/iommu/iommu.c | 11 ++--------- drivers/iommu/of_iommu.c | 4 +++- include/linux/iommu.h | 2 -- 4 files changed, 10 insertions(+), 12 deletions(-)
drivers/iommu/iommu-priv.h +5 -0
@@ -19,6 +19,11 @@ static inline const struct iommu_ops *dev_iommu_ops(struct device *dev)const struct iommu_ops *iommu_ops_from_fwnode (const struct fwnode_handle *fwnode); +static inline const struct iommu_ops *iommu_fwspec_ops (struct iommu_fwspec *fwspec) +{ +return iommu_ops_from_fwnode (fwspec ? fwspec->iommu_fwnode :NULL ); +} +int iommu_group_replace_domain (struct iommu_group *group,struct iommu_domain *new_domain);
drivers/iommu/iommu.c +2 -9
@@ -510,7 +510,6 @@ DEFINE_MUTEX(iommu_probe_device_lock);static int __iommu_probe_device (struct device *dev,struct list_head *group_list) {const struct iommu_ops *ops; -struct iommu_fwspec *fwspec;struct iommu_group *group;struct group_device *gdev;int ret;
@@ -523,12 +522,7 @@ static int __iommu_probe_device(struct device *dev, struct list_head *group_list* be present, and that any of their registered instances has suitable * ops for probing, and thus cheekily co-opt the same mechanism. */ - fwspec =dev_iommu_fwspec_get (dev); -if (fwspec && fwspec->ops) - ops = fwspec->ops; -else - ops =iommu_ops_from_fwnode (NULL ); - + ops =iommu_fwspec_ops (dev_iommu_fwspec_get (dev));if (!ops)return -ENODEV ;/*
@@ -2831,7 +2825,7 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode)return -EPROBE_DEFER ;if (fwspec) -return ops == fwspec->ops ?0 : -EINVAL ; +return ops ==iommu_fwspec_ops (fwspec) ?0 : -EINVAL ;if (!dev_iommu_get (dev))return -ENOMEM ;
@@ -2843,7 +2837,6 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode)fwnode_handle_get (iommu_fwnode); fwspec->iommu_fwnode = iommu_fwnode; - fwspec->ops = ops;dev_iommu_fwspec_set (dev, fwspec);return 0 ; }
drivers/iommu/of_iommu.c +3 -1
@@ -17,6 +17,8 @@#include <linux/slab.h> #include <linux/fsl/mc.h> +#include "iommu-priv.h" +static int of_iommu_xlate (struct device *dev,struct of_phandle_args *iommu_spec) {
@@ -32,7 +34,7 @@ static int of_iommu_xlate(struct device *dev,if (ret)return ret; - ops =dev_iommu_fwspec_get (dev)->ops; + ops =iommu_ops_from_fwnode (&iommu_spec->np->fwnode);if (!ops->of_xlate || !try_module_get (ops->owner))return -ENODEV ;
include/linux/iommu.h +0 -2
@@ -968,7 +968,6 @@ extern struct iommu_group *generic_single_device_group(struct device *dev);/** * struct iommu_fwspec - per-device IOMMU instance data -* @ops: ops for this device's IOMMU * @iommu_fwnode: firmware handle for this device's IOMMU * @flags: IOMMU_FWSPEC_* flags * @num_ids: number of associated device IDs
@@ -979,7 +978,6 @@ extern struct iommu_group *generic_single_device_group(struct device *dev);* consumers. */ struct iommu_fwspec { -const struct iommu_ops *ops;struct fwnode_handle *iommu_fwnode;u32 flags;unsigned int num_ids;
Signature · 1 line
2.39.2.101.g768bb238c484.dirty
Quoted 9 lines · Robin Murphy
v2: https://lore.kernel.org/linux-iommu/[email protected]/
Hi all,
Just a quick update with an extra patch to avoid the mediatek-v1 driver breaking (and I have now build-tested ARCH=arm to make sure, apologies for being lazy before...)
[...]
Applied to arm64 (fwspec-ops-removal), thanks!
[1/5] iommu/mediatek-v1: Clean up redundant fwspec checks
https://git.kernel.org/iommu/c/e7acc36f26b0 [2/5] iommu: Resolve fwspec ops automatically https://git.kernel.org/iommu/c/3f7c32091628 [3/5] ACPI: Retire acpi_iommu_fwspec_ops() https://git.kernel.org/iommu/c/78596b5c321c [4/5] OF: Simplify of_iommu_configure() https://git.kernel.org/iommu/c/5f937bc48a6a [5/5] iommu: Remove iommu_fwspec ops https://git.kernel.org/iommu/c/3e36c15fc1cc
Cheers,
Signature · 5 lines
Will https://fixes.arm64.dev https://next.arm64.dev https://will.arm64.dev