}
        iommu_mm->pasid = pasid;
        INIT_LIST_HEAD(&iommu_mm->sva_domains);
+       INIT_LIST_HEAD(&iommu_mm->sva_handles);
        /*
         * Make sure the write to mm->iommu_mm is not reordered in front of
         * initialization to iommu_mm fields. If it does, readers may see a
                goto out_unlock;
        }
 
+       list_for_each_entry(handle, &mm->iommu_mm->sva_handles, handle_item) {
+               if (handle->dev == dev) {
+                       refcount_inc(&handle->users);
+                       mutex_unlock(&iommu_sva_lock);
+                       return handle;
+               }
+       }
+
        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
        if (!handle) {
                ret = -ENOMEM;
        if (ret)
                goto out_free_domain;
        domain->users = 1;
+       refcount_set(&handle->users, 1);
        list_add(&domain->next, &mm->iommu_mm->sva_domains);
+       list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);
 
 out:
        mutex_unlock(&iommu_sva_lock);
        struct device *dev = handle->dev;
 
        mutex_lock(&iommu_sva_lock);
+       if (!refcount_dec_and_test(&handle->users)) {
+               mutex_unlock(&iommu_sva_lock);
+               return;
+       }
+       list_del(&handle->handle_item);
+
        iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
        if (--domain->users == 0) {
                list_del(&domain->next);
 
 struct iommu_sva {
        struct device                   *dev;
        struct iommu_domain             *domain;
+       struct list_head                handle_item;
+       refcount_t                      users;
 };
 
 struct iommu_mm_data {
        u32                     pasid;
        struct list_head        sva_domains;
+       struct list_head        sva_handles;
 };
 
 int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,