Commit 179145e6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'iommu-fixes-v4.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu

Pull IOMMU fixes from Joerg Roedel:

 - another compile-fix for my header cleanup

 - a couple of fixes for the recently merged IOMMU probe deferal code

 - fixes for ACPI/IORT code necessary with IOMMU probe deferal

* tag 'iommu-fixes-v4.12-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  arm: dma-mapping: Reset the device's dma_ops
  ACPI/IORT: Move the check to get iommu_ops from translated fwspec
  ARM: dma-mapping: Don't tear down third-party mappings
  ACPI/IORT: Ignore all errors except EPROBE_DEFER
  iommu/of: Ignore all errors except EPROBE_DEFER
  iommu/of: Fix check for returning EPROBE_DEFER
  iommu/dma: Fix function declaration
parents c7a1aefc d3e01c51
...@@ -19,7 +19,8 @@ struct dev_archdata { ...@@ -19,7 +19,8 @@ struct dev_archdata {
#ifdef CONFIG_XEN #ifdef CONFIG_XEN
const struct dma_map_ops *dev_dma_ops; const struct dma_map_ops *dev_dma_ops;
#endif #endif
bool dma_coherent; unsigned int dma_coherent:1;
unsigned int dma_ops_setup:1;
}; };
struct omap_device; struct omap_device;
......
...@@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev, ...@@ -2311,7 +2311,14 @@ int arm_iommu_attach_device(struct device *dev,
} }
EXPORT_SYMBOL_GPL(arm_iommu_attach_device); EXPORT_SYMBOL_GPL(arm_iommu_attach_device);
static void __arm_iommu_detach_device(struct device *dev) /**
* arm_iommu_detach_device
* @dev: valid struct device pointer
*
* Detaches the provided device from a previously attached map.
* This voids the dma operations (dma_map_ops pointer)
*/
void arm_iommu_detach_device(struct device *dev)
{ {
struct dma_iommu_mapping *mapping; struct dma_iommu_mapping *mapping;
...@@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device *dev) ...@@ -2324,22 +2331,10 @@ static void __arm_iommu_detach_device(struct device *dev)
iommu_detach_device(mapping->domain, dev); iommu_detach_device(mapping->domain, dev);
kref_put(&mapping->kref, release_iommu_mapping); kref_put(&mapping->kref, release_iommu_mapping);
to_dma_iommu_mapping(dev) = NULL; to_dma_iommu_mapping(dev) = NULL;
set_dma_ops(dev, NULL);
pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev)); pr_debug("Detached IOMMU controller from %s device.\n", dev_name(dev));
} }
/**
* arm_iommu_detach_device
* @dev: valid struct device pointer
*
* Detaches the provided device from a previously attached map.
* This voids the dma operations (dma_map_ops pointer)
*/
void arm_iommu_detach_device(struct device *dev)
{
__arm_iommu_detach_device(dev);
set_dma_ops(dev, NULL);
}
EXPORT_SYMBOL_GPL(arm_iommu_detach_device); EXPORT_SYMBOL_GPL(arm_iommu_detach_device);
static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) static const struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent)
...@@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev) ...@@ -2379,7 +2374,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)
if (!mapping) if (!mapping)
return; return;
__arm_iommu_detach_device(dev); arm_iommu_detach_device(dev);
arm_iommu_release_mapping(mapping); arm_iommu_release_mapping(mapping);
} }
...@@ -2430,9 +2425,13 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size, ...@@ -2430,9 +2425,13 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
dev->dma_ops = xen_dma_ops; dev->dma_ops = xen_dma_ops;
} }
#endif #endif
dev->archdata.dma_ops_setup = true;
} }
void arch_teardown_dma_ops(struct device *dev) void arch_teardown_dma_ops(struct device *dev)
{ {
if (!dev->archdata.dma_ops_setup)
return;
arm_teardown_iommu_dma_ops(dev); arm_teardown_iommu_dma_ops(dev);
} }
...@@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev, ...@@ -666,14 +666,6 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
int ret = -ENODEV; int ret = -ENODEV;
struct fwnode_handle *iort_fwnode; struct fwnode_handle *iort_fwnode;
/*
* If we already translated the fwspec there
* is nothing left to do, return the iommu_ops.
*/
ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
if (ops)
return ops;
if (node) { if (node) {
iort_fwnode = iort_get_fwnode(node); iort_fwnode = iort_get_fwnode(node);
if (!iort_fwnode) if (!iort_fwnode)
...@@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) ...@@ -735,6 +727,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
u32 streamid = 0; u32 streamid = 0;
int err; int err;
/*
* If we already translated the fwspec there
* is nothing left to do, return the iommu_ops.
*/
ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
if (ops)
return ops;
if (dev_is_pci(dev)) { if (dev_is_pci(dev)) {
struct pci_bus *bus = to_pci_dev(dev)->bus; struct pci_bus *bus = to_pci_dev(dev)->bus;
u32 rid; u32 rid;
...@@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) ...@@ -782,6 +782,12 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
if (err) if (err)
ops = ERR_PTR(err); ops = ERR_PTR(err);
/* Ignore all other errors apart from EPROBE_DEFER */
if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
ops = NULL;
}
return ops; return ops;
} }
......
...@@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr) ...@@ -1371,8 +1371,8 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
iort_set_dma_mask(dev); iort_set_dma_mask(dev);
iommu = iort_iommu_configure(dev); iommu = iort_iommu_configure(dev);
if (IS_ERR(iommu)) if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
return PTR_ERR(iommu); return -EPROBE_DEFER;
size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
/* /*
......
...@@ -118,6 +118,7 @@ static const struct iommu_ops ...@@ -118,6 +118,7 @@ static const struct iommu_ops
ops = iommu_ops_from_fwnode(fwnode); ops = iommu_ops_from_fwnode(fwnode);
if ((ops && !ops->of_xlate) || if ((ops && !ops->of_xlate) ||
!of_device_is_available(iommu_spec->np) ||
(!ops && !of_iommu_driver_present(iommu_spec->np))) (!ops && !of_iommu_driver_present(iommu_spec->np)))
return NULL; return NULL;
...@@ -236,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, ...@@ -236,6 +237,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
ops = ERR_PTR(err); ops = ERR_PTR(err);
} }
/* Ignore all other errors apart from EPROBE_DEFER */
if (IS_ERR(ops) && (PTR_ERR(ops) != -EPROBE_DEFER)) {
dev_dbg(dev, "Adding to IOMMU failed: %ld\n", PTR_ERR(ops));
ops = NULL;
}
return ops; return ops;
} }
......
...@@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node *np) ...@@ -144,8 +144,8 @@ int of_dma_configure(struct device *dev, struct device_node *np)
coherent ? " " : " not "); coherent ? " " : " not ");
iommu = of_iommu_configure(dev, np); iommu = of_iommu_configure(dev, np);
if (IS_ERR(iommu)) if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
return PTR_ERR(iommu); return -EPROBE_DEFER;
dev_dbg(dev, "device is%sbehind an iommu\n", dev_dbg(dev, "device is%sbehind an iommu\n",
iommu ? " " : " not "); iommu ? " " : " not ");
......
...@@ -78,6 +78,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list); ...@@ -78,6 +78,7 @@ void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
struct iommu_domain; struct iommu_domain;
struct msi_msg; struct msi_msg;
struct device;
static inline int iommu_dma_init(void) static inline int iommu_dma_init(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment