Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-block.git] / drivers / vhost / vdpa.c
index 135ad39958cc8f0597dc94cf9e6a47058d0cee71..8c1aefc865f0854ca7c07873a2c757c1688d30f0 100644 (file)
@@ -219,6 +219,28 @@ static int vhost_vdpa_reset(struct vhost_vdpa *v)
        return vdpa_reset(vdpa);
 }
 
+static long vhost_vdpa_bind_mm(struct vhost_vdpa *v)
+{
+       struct vdpa_device *vdpa = v->vdpa;
+       const struct vdpa_config_ops *ops = vdpa->config;
+
+       if (!vdpa->use_va || !ops->bind_mm)
+               return 0;
+
+       return ops->bind_mm(vdpa, v->vdev.mm);
+}
+
+static void vhost_vdpa_unbind_mm(struct vhost_vdpa *v)
+{
+       struct vdpa_device *vdpa = v->vdpa;
+       const struct vdpa_config_ops *ops = vdpa->config;
+
+       if (!vdpa->use_va || !ops->unbind_mm)
+               return;
+
+       ops->unbind_mm(vdpa);
+}
+
 static long vhost_vdpa_get_device_id(struct vhost_vdpa *v, u8 __user *argp)
 {
        struct vdpa_device *vdpa = v->vdpa;
@@ -599,9 +621,11 @@ static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
                if (vq->call_ctx.ctx) {
                        cb.callback = vhost_vdpa_virtqueue_cb;
                        cb.private = vq;
+                       cb.trigger = vq->call_ctx.ctx;
                } else {
                        cb.callback = NULL;
                        cb.private = NULL;
+                       cb.trigger = NULL;
                }
                ops->set_vq_cb(vdpa, idx, &cb);
                vhost_vdpa_setup_vq_irq(v, idx);
@@ -716,6 +740,17 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
                break;
        }
 
+       if (r)
+               goto out;
+
+       switch (cmd) {
+       case VHOST_SET_OWNER:
+               r = vhost_vdpa_bind_mm(v);
+               if (r)
+                       vhost_dev_reset_owner(d, NULL);
+               break;
+       }
+out:
        mutex_unlock(&d->mutex);
        return r;
 }
@@ -851,11 +886,7 @@ static void vhost_vdpa_unmap(struct vhost_vdpa *v,
                if (!v->in_batch)
                        ops->set_map(vdpa, asid, iotlb);
        }
-       /* If we are in the middle of batch processing, delay the free
-        * of AS until BATCH_END.
-        */
-       if (!v->in_batch && !iotlb->nmaps)
-               vhost_vdpa_remove_as(v, asid);
+
 }
 
 static int vhost_vdpa_va_map(struct vhost_vdpa *v,
@@ -1112,8 +1143,6 @@ static int vhost_vdpa_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
                if (v->in_batch && ops->set_map)
                        ops->set_map(vdpa, asid, iotlb);
                v->in_batch = false;
-               if (!iotlb->nmaps)
-                       vhost_vdpa_remove_as(v, asid);
                break;
        default:
                r = -EINVAL;
@@ -1287,6 +1316,7 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
        vhost_vdpa_clean_irq(v);
        vhost_vdpa_reset(v);
        vhost_dev_stop(&v->vdev);
+       vhost_vdpa_unbind_mm(v);
        vhost_vdpa_config_put(v);
        vhost_vdpa_cleanup(v);
        mutex_unlock(&d->mutex);