IOMMU Fixes for Linux v4.12-rc4

Including:
 
 	* Another compile-fix for my header cleanup
 
 	* A couple of fixes for the recently merged IOMMU probe
 	  deferal code
 
 	* Includes fixes for ACPI/IORT code necessary with
 	  IOMMU probe deferal
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABAgAGBQJZOyKuAAoJECvwRC2XARrjb1EP/iM+5lHWikgAZ7dbH+3oS3hE
 6tkevfr2+6SikuJp4rITtIXWDK3nSO/2kXbt6LqCVTFKuiszEHO1BDAep0ytIPzE
 63m8INBpSm+bs4QhdQUR5f8Ab8uFh/SPozZlxq3mxMf5QARvbbWeAiMH/iTl/HD7
 XlywryI9SD7fGHkdVWApCtUH6AoYv33c9jg9a/+7RngOjv3gvI0hHr4Omt0udf+8
 udS0WGNjsJy9HqtIzaaRCCe4rWqsgLzi9iCFe856P+smD9g9BoH2VgePbOzeOI4r
 IMnEcGBExFuEpx67lDseHYqg6R79lzlE/C1SyzcCOEbvvjMUL+/nqm+AjEMa5++w
 wL0gyiAZrUZjFhsr4QjQESsUDqlB7K7YHfLNLxwlC8vg9/4V7StoeOWhE+YVROLz
 1+MJ2Kv5wlZRN/B6wKCCRSAGnuMT02xXWxNRKfS7+sHPT8eJVWBEo6K+0WNGTkhq
 oFJCggBBllmlegt/IOKTe6jLzKN95UHz0NSoMoj1LIqCZOMFTPJwkV5976oPy0Ba
 uAoH5uJpai2yRIE15mHB23Bkc1SBE3pm7VC/4NeT4i7pyb8hnb4QwhmSD1vd7J+E
 ZApOSoptDWSF9al6LXzEZTjCMF85fY/JsG3+jdqY6zCacUK795gcyUZ/3al5+F4E
 r50a/SvSp90AxrZZcpT7
 =6dZB
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2017-06-09 22:30:55 -07:00
Родитель c7a1aefc47 d3e01c5159
Коммит 179145e631
7 изменённых файлов: 42 добавлений и 28 удалений

Просмотреть файл

@ -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,
} }
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)
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)
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,
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,
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)
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)
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)
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
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,
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)
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);
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)
{ {