]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/of/device.c
iommu: of: Handle IOMMU lookup failure with deferred probing or error
[linux.git] / drivers / of / device.c
index b1e6bebda3f3a0ebee3b09085b6bb1a500f6249e..8bd3d8c09435a1f88afc1b09d0d9713ea22236f8 100644 (file)
@@ -82,7 +82,7 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-void of_dma_configure(struct device *dev, struct device_node *np)
+int of_dma_configure(struct device *dev, struct device_node *np)
 {
        u64 dma_addr, paddr, size;
        int ret;
@@ -107,7 +107,7 @@ void of_dma_configure(struct device *dev, struct device_node *np)
        ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
        if (ret < 0) {
                dma_addr = offset = 0;
-               size = dev->coherent_dma_mask + 1;
+               size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
        } else {
                offset = PFN_DOWN(paddr - dma_addr);
 
@@ -123,7 +123,7 @@ void of_dma_configure(struct device *dev, struct device_node *np)
 
                if (!size) {
                        dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
-                       return;
+                       return -EINVAL;
                }
                dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
        }
@@ -144,13 +144,30 @@ void of_dma_configure(struct device *dev, struct device_node *np)
                coherent ? " " : " not ");
 
        iommu = of_iommu_configure(dev, np);
+       if (IS_ERR(iommu))
+               return PTR_ERR(iommu);
+
        dev_dbg(dev, "device is%sbehind an iommu\n",
                iommu ? " " : " not ");
 
        arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(of_dma_configure);
 
+/**
+ * of_dma_deconfigure - Clean up DMA configuration
+ * @dev:       Device for which to clean up DMA configuration
+ *
+ * Clean up all configuration performed by of_dma_configure_ops() and free all
+ * resources that have been allocated.
+ */
+void of_dma_deconfigure(struct device *dev)
+{
+       arch_teardown_dma_ops(dev);
+}
+
 int of_device_register(struct platform_device *pdev)
 {
        device_initialize(&pdev->dev);