return 0;
}
+static int iommu_group_do_set_platform_dma(struct device *dev, void *data)
+{
+ const struct iommu_ops *ops = dev_iommu_ops(dev);
+
+ if (!WARN_ON(!ops->set_platform_dma_ops))
+ ops->set_platform_dma_ops(dev);
+
+ return 0;
+}
+
static int __iommu_group_set_domain(struct iommu_group *group,
struct iommu_domain *new_domain)
{
* platform specific behavior.
*/
if (!new_domain) {
- if (WARN_ON(!group->domain->ops->detach_dev))
- return -EINVAL;
- __iommu_group_for_each_dev(group, group->domain,
- iommu_group_do_detach_device);
+ struct group_device *grp_dev;
+
+ grp_dev = list_first_entry(&group->devices,
+ struct group_device, list);
+
+ if (dev_iommu_ops(grp_dev->dev)->set_platform_dma_ops)
+ __iommu_group_for_each_dev(group, NULL,
+ iommu_group_do_set_platform_dma);
+ else if (group->domain->ops->detach_dev)
+ __iommu_group_for_each_dev(group, group->domain,
+ iommu_group_do_detach_device);
+ else
+ WARN_ON_ONCE(1);
+
group->domain = NULL;
return 0;
}
* @release_device: Remove device from iommu driver handling
* @probe_finalize: Do final setup work after the device is added to an IOMMU
* group and attached to the groups domain
+ * @set_platform_dma_ops: Returning control back to the platform DMA ops. This op
+ * is to support old IOMMU drivers, new drivers should use
+ * default domains, and the common IOMMU DMA ops.
* @device_group: find iommu group for a particular device
* @get_resv_regions: Request list of reserved regions for a device
* @of_xlate: add OF master IDs to iommu grouping
struct iommu_device *(*probe_device)(struct device *dev);
void (*release_device)(struct device *dev);
void (*probe_finalize)(struct device *dev);
+ void (*set_platform_dma_ops)(struct device *dev);
struct iommu_group *(*device_group)(struct device *dev);
/* Request/Free a list of reserved regions for a device */