|
22 | 22 | #include <linux/nospec.h>
|
23 | 23 | #include <linux/vhost.h>
|
24 | 24 | #include <linux/virtio_net.h>
|
| 25 | +#include <linux/kernel.h> |
25 | 26 |
|
26 | 27 | #include "vhost.h"
|
27 | 28 |
|
@@ -71,6 +72,7 @@ struct vhost_vdpa {
|
71 | 72 | int nvqs;
|
72 | 73 | int virtio_id;
|
73 | 74 | int minor;
|
| 75 | + struct eventfd_ctx *config_ctx; |
74 | 76 | };
|
75 | 77 |
|
76 | 78 | static DEFINE_IDA(vhost_vdpa_ida);
|
@@ -102,6 +104,17 @@ static irqreturn_t vhost_vdpa_virtqueue_cb(void *private)
|
102 | 104 | return IRQ_HANDLED;
|
103 | 105 | }
|
104 | 106 |
|
| 107 | +static irqreturn_t vhost_vdpa_config_cb(void *private) |
| 108 | +{ |
| 109 | + struct vhost_vdpa *v = private; |
| 110 | + struct eventfd_ctx *config_ctx = v->config_ctx; |
| 111 | + |
| 112 | + if (config_ctx) |
| 113 | + eventfd_signal(config_ctx, 1); |
| 114 | + |
| 115 | + return IRQ_HANDLED; |
| 116 | +} |
| 117 | + |
105 | 118 | static void vhost_vdpa_reset(struct vhost_vdpa *v)
|
106 | 119 | {
|
107 | 120 | struct vdpa_device *vdpa = v->vdpa;
|
@@ -289,6 +302,36 @@ static long vhost_vdpa_get_vring_num(struct vhost_vdpa *v, u16 __user *argp)
|
289 | 302 | return 0;
|
290 | 303 | }
|
291 | 304 |
|
| 305 | +static void vhost_vdpa_config_put(struct vhost_vdpa *v) |
| 306 | +{ |
| 307 | + if (v->config_ctx) |
| 308 | + eventfd_ctx_put(v->config_ctx); |
| 309 | +} |
| 310 | + |
| 311 | +static long vhost_vdpa_set_config_call(struct vhost_vdpa *v, u32 __user *argp) |
| 312 | +{ |
| 313 | + struct vdpa_callback cb; |
| 314 | + int fd; |
| 315 | + struct eventfd_ctx *ctx; |
| 316 | + |
| 317 | + cb.callback = vhost_vdpa_config_cb; |
| 318 | + cb.private = v->vdpa; |
| 319 | + if (copy_from_user(&fd, argp, sizeof(fd))) |
| 320 | + return -EFAULT; |
| 321 | + |
| 322 | + ctx = fd == VHOST_FILE_UNBIND ? NULL : eventfd_ctx_fdget(fd); |
| 323 | + swap(ctx, v->config_ctx); |
| 324 | + |
| 325 | + if (!IS_ERR_OR_NULL(ctx)) |
| 326 | + eventfd_ctx_put(ctx); |
| 327 | + |
| 328 | + if (IS_ERR(v->config_ctx)) |
| 329 | + return PTR_ERR(v->config_ctx); |
| 330 | + |
| 331 | + v->vdpa->config->set_config_cb(v->vdpa, &cb); |
| 332 | + |
| 333 | + return 0; |
| 334 | +} |
292 | 335 | static long vhost_vdpa_vring_ioctl(struct vhost_vdpa *v, unsigned int cmd,
|
293 | 336 | void __user *argp)
|
294 | 337 | {
|
@@ -396,6 +439,9 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep,
|
396 | 439 | case VHOST_SET_LOG_FD:
|
397 | 440 | r = -ENOIOCTLCMD;
|
398 | 441 | break;
|
| 442 | + case VHOST_VDPA_SET_CONFIG_CALL: |
| 443 | + r = vhost_vdpa_set_config_call(v, argp); |
| 444 | + break; |
399 | 445 | default:
|
400 | 446 | r = vhost_dev_ioctl(&v->vdev, cmd, argp);
|
401 | 447 | if (r == -ENOIOCTLCMD)
|
@@ -730,6 +776,7 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep)
|
730 | 776 | vhost_dev_stop(&v->vdev);
|
731 | 777 | vhost_vdpa_iotlb_free(v);
|
732 | 778 | vhost_vdpa_free_domain(v);
|
| 779 | + vhost_vdpa_config_put(v); |
733 | 780 | vhost_dev_cleanup(&v->vdev);
|
734 | 781 | kfree(v->vdev.vqs);
|
735 | 782 | mutex_unlock(&d->mutex);
|
|
0 commit comments