struct iommu_domain *default_domain;
        struct iommu_domain *domain;
        struct list_head entry;
+       unsigned int owner_cnt;
+       void *owner;
 };
 
 struct group_device {
        mutex_lock(&group->mutex);
        iommu_alloc_default_domain(group, dev);
 
-       if (group->default_domain) {
+       /*
+        * If device joined an existing group which has been claimed, don't
+        * attach the default domain.
+        */
+       if (group->default_domain && !group->owner) {
                ret = __iommu_attach_device(group->default_domain, dev);
                if (ret) {
                        mutex_unlock(&group->mutex);
 {
        int ret;
 
-       if (group->default_domain && group->domain != group->default_domain)
+       if (group->domain && group->domain != group->default_domain)
                return -EBUSY;
 
        ret = __iommu_group_for_each_dev(group, domain,
 {
        int ret;
 
-       if (!group->default_domain) {
+       /*
+        * If the group has been claimed already, do not re-attach the default
+        * domain.
+        */
+       if (!group->default_domain || group->owner) {
                __iommu_group_for_each_dev(group, domain,
                                           iommu_group_do_detach_device);
                group->domain = NULL;
 
        return ret;
 }
+
+/**
+ * iommu_device_use_default_domain() - Device driver wants to handle device
+ *                                     DMA through the kernel DMA API.
+ * @dev: The device.
+ *
+ * The device driver about to bind @dev wants to do DMA through the kernel
+ * DMA API. Return 0 if it is allowed, otherwise an error.
+ */
+int iommu_device_use_default_domain(struct device *dev)
+{
+       struct iommu_group *group = iommu_group_get(dev);
+       int ret = 0;
+
+       if (!group)
+               return 0;
+
+       mutex_lock(&group->mutex);
+       if (group->owner_cnt) {
+               if (group->domain != group->default_domain ||
+                   group->owner) {
+                       ret = -EBUSY;
+                       goto unlock_out;
+               }
+       }
+
+       group->owner_cnt++;
+
+unlock_out:
+       mutex_unlock(&group->mutex);
+       iommu_group_put(group);
+
+       return ret;
+}
+
+/**
+ * iommu_device_unuse_default_domain() - Device driver stops handling device
+ *                                       DMA through the kernel DMA API.
+ * @dev: The device.
+ *
+ * The device driver doesn't want to do DMA through kernel DMA API anymore.
+ * It must be called after iommu_device_use_default_domain().
+ */
+void iommu_device_unuse_default_domain(struct device *dev)
+{
+       struct iommu_group *group = iommu_group_get(dev);
+
+       if (!group)
+               return;
+
+       mutex_lock(&group->mutex);
+       if (!WARN_ON(!group->owner_cnt))
+               group->owner_cnt--;
+
+       mutex_unlock(&group->mutex);
+       iommu_group_put(group);
+}
+
+/**
+ * iommu_group_claim_dma_owner() - Set DMA ownership of a group
+ * @group: The group.
+ * @owner: Caller specified pointer. Used for exclusive ownership.
+ *
+ * This is to support backward compatibility for vfio which manages
+ * the dma ownership in iommu_group level. New invocations on this
+ * interface should be prohibited.
+ */
+int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner)
+{
+       int ret = 0;
+
+       mutex_lock(&group->mutex);
+       if (group->owner_cnt) {
+               ret = -EPERM;
+               goto unlock_out;
+       } else {
+               if (group->domain && group->domain != group->default_domain) {
+                       ret = -EBUSY;
+                       goto unlock_out;
+               }
+
+               group->owner = owner;
+               if (group->domain)
+                       __iommu_detach_group(group->domain, group);
+       }
+
+       group->owner_cnt++;
+unlock_out:
+       mutex_unlock(&group->mutex);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_group_claim_dma_owner);
+
+/**
+ * iommu_group_release_dma_owner() - Release DMA ownership of a group
+ * @group: The group.
+ *
+ * Release the DMA ownership claimed by iommu_group_claim_dma_owner().
+ */
+void iommu_group_release_dma_owner(struct iommu_group *group)
+{
+       mutex_lock(&group->mutex);
+       if (WARN_ON(!group->owner_cnt || !group->owner))
+               goto unlock_out;
+
+       group->owner_cnt = 0;
+       /*
+        * The UNMANAGED domain should be detached before all USER
+        * owners have been released.
+        */
+       if (!WARN_ON(group->domain) && group->default_domain)
+               __iommu_attach_group(group->default_domain, group);
+       group->owner = NULL;
+unlock_out:
+       mutex_unlock(&group->mutex);
+}
+EXPORT_SYMBOL_GPL(iommu_group_release_dma_owner);
+
+/**
+ * iommu_group_dma_owner_claimed() - Query group dma ownership status
+ * @group: The group.
+ *
+ * This provides status query on a given group. It is racy and only for
+ * non-binding status reporting.
+ */
+bool iommu_group_dma_owner_claimed(struct iommu_group *group)
+{
+       unsigned int user;
+
+       mutex_lock(&group->mutex);
+       user = group->owner_cnt;
+       mutex_unlock(&group->mutex);
+
+       return user;
+}
+EXPORT_SYMBOL_GPL(iommu_group_dma_owner_claimed);
 
 void iommu_sva_unbind_device(struct iommu_sva *handle);
 u32 iommu_sva_get_pasid(struct iommu_sva *handle);
 
+int iommu_device_use_default_domain(struct device *dev);
+void iommu_device_unuse_default_domain(struct device *dev);
+
+int iommu_group_claim_dma_owner(struct iommu_group *group, void *owner);
+void iommu_group_release_dma_owner(struct iommu_group *group);
+bool iommu_group_dma_owner_claimed(struct iommu_group *group);
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
 {
        return NULL;
 }
+
+static inline int iommu_device_use_default_domain(struct device *dev)
+{
+       return 0;
+}
+
+static inline void iommu_device_unuse_default_domain(struct device *dev)
+{
+}
+
+static inline int
+iommu_group_claim_dma_owner(struct iommu_group *group, void *owner)
+{
+       return -ENODEV;
+}
+
+static inline void iommu_group_release_dma_owner(struct iommu_group *group)
+{
+}
+
+static inline bool iommu_group_dma_owner_claimed(struct iommu_group *group)
+{
+       return false;
+}
 #endif /* CONFIG_IOMMU_API */
 
 /**