diff options
Diffstat (limited to 'arch/arm/mm/dma-mapping.c')
| -rw-r--r-- | arch/arm/mm/dma-mapping.c | 53 | 
1 files changed, 38 insertions, 15 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 7864797609b3..a673c7f7e208 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -1940,13 +1940,32 @@ void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)  }  EXPORT_SYMBOL_GPL(arm_iommu_release_mapping); +static int __arm_iommu_attach_device(struct device *dev, +				     struct dma_iommu_mapping *mapping) +{ +	int err; + +	err = iommu_attach_device(mapping->domain, dev); +	if (err) +		return err; + +	kref_get(&mapping->kref); +	dev->archdata.mapping = mapping; + +	pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev)); +	return 0; +} +  /**   * arm_iommu_attach_device   * @dev: valid struct device pointer   * @mapping: io address space mapping structure (returned from   *	arm_iommu_create_mapping)   * - * Attaches specified io address space mapping to the provided device, + * Attaches specified io address space mapping to the provided device. + * This replaces the dma operations (dma_map_ops pointer) with the + * IOMMU aware version. + *   * More than one client might be attached to the same io address space   * mapping.   */ @@ -1955,25 +1974,16 @@ int arm_iommu_attach_device(struct device *dev,  {  	int err; -	err = iommu_attach_device(mapping->domain, dev); +	err = __arm_iommu_attach_device(dev, mapping);  	if (err)  		return err; -	kref_get(&mapping->kref); -	dev->archdata.mapping = mapping; - -	pr_debug("Attached IOMMU controller to %s device.\n", dev_name(dev)); +	set_dma_ops(dev, &iommu_ops);  	return 0;  }  EXPORT_SYMBOL_GPL(arm_iommu_attach_device); -/** - * arm_iommu_detach_device - * @dev: valid struct device pointer - * - * Detaches the provided device from a previously attached map. - */ -void arm_iommu_detach_device(struct device *dev) +static void __arm_iommu_detach_device(struct device *dev)  {  	struct dma_iommu_mapping *mapping; @@ -1989,6 +1999,19 @@ void arm_iommu_detach_device(struct device *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);  static struct dma_map_ops *arm_get_iommu_dma_map_ops(bool coherent) @@ -2011,7 +2034,7 @@ static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,  		return false;  	} -	if (arm_iommu_attach_device(dev, mapping)) { +	if (__arm_iommu_attach_device(dev, mapping)) {  		pr_warn("Failed to attached device %s to IOMMU_mapping\n",  				dev_name(dev));  		arm_iommu_release_mapping(mapping); @@ -2025,7 +2048,7 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)  {  	struct dma_iommu_mapping *mapping = dev->archdata.mapping; -	arm_iommu_detach_device(dev); +	__arm_iommu_detach_device(dev);  	arm_iommu_release_mapping(mapping);  }  | 
