diff --git a/lib/vhost/rte_vhost_user.c b/lib/vhost/rte_vhost_user.c index a91f6f7c1..85562e564 100644 --- a/lib/vhost/rte_vhost_user.c +++ b/lib/vhost/rte_vhost_user.c @@ -1098,17 +1098,27 @@ enable_device_vq(struct spdk_vhost_session *vsession, uint16_t qid) q->packed.used_phase = q->last_used_idx >> 15; q->last_used_idx = q->last_used_idx & 0x7FFF; - if (!vsession->interrupt_mode) { + if (!spdk_interrupt_mode_is_enabled()) { /* Disable I/O submission notifications, we'll be polling. */ q->vring.device_event->flags = VRING_PACKED_EVENT_FLAG_DISABLE; + } else { + /* Enable I/O submission notifications, we'll be interrupting. */ + q->vring.device_event->flags = VRING_PACKED_EVENT_FLAG_ENABLE; } } else { - if (!vsession->interrupt_mode) { + if (!spdk_interrupt_mode_is_enabled()) { /* Disable I/O submission notifications, we'll be polling. */ q->vring.used->flags = VRING_USED_F_NO_NOTIFY; + } else { + /* Enable I/O submission notifications, we'll be interrupting. */ + q->vring.used->flags = 0; } } + if (spdk_interrupt_mode_is_enabled() && backend->register_vq_interrupt) { + backend->register_vq_interrupt(vsession, q); + } + q->packed.packed_ring = packed_ring; vsession->max_queues = spdk_max(vsession->max_queues, qid + 1); @@ -1405,11 +1415,8 @@ void vhost_user_session_set_interrupt_mode(struct spdk_vhost_session *vsession, bool interrupt_mode) { uint16_t i; - bool packed_ring; int rc = 0; - packed_ring = ((vsession->negotiated_features & (1ULL << VIRTIO_F_RING_PACKED)) != 0); - for (i = 0; i < vsession->max_queues; i++) { struct spdk_vhost_virtqueue *q = &vsession->virtqueue[i]; uint64_t num_events = 1; @@ -1422,12 +1429,6 @@ vhost_user_session_set_interrupt_mode(struct spdk_vhost_session *vsession, bool } if (interrupt_mode) { - /* Enable I/O submission notifications, we'll be interrupting. */ - if (packed_ring) { - * (volatile uint16_t *) &q->vring.device_event->flags = VRING_PACKED_EVENT_FLAG_ENABLE; - } else { - * (volatile uint16_t *) &q->vring.used->flags = 0; - } /* In case of race condition, always kick vring when switch to intr */ rc = write(q->vring.kickfd, &num_events, sizeof(num_events)); @@ -1437,19 +1438,12 @@ vhost_user_session_set_interrupt_mode(struct spdk_vhost_session *vsession, bool vsession->interrupt_mode = true; } else { - /* Disable I/O submission notifications, we'll be polling. */ - if (packed_ring) { - * (volatile uint16_t *) &q->vring.device_event->flags = VRING_PACKED_EVENT_FLAG_DISABLE; - } else { - * (volatile uint16_t *) &q->vring.used->flags = VRING_USED_F_NO_NOTIFY; - } vsession->interrupt_mode = false; } } } - static int extern_vhost_pre_msg_handler(int vid, void *_msg) { diff --git a/lib/vhost/vhost_blk.c b/lib/vhost/vhost_blk.c index af9fb7b87..50898643b 100644 --- a/lib/vhost/vhost_blk.c +++ b/lib/vhost/vhost_blk.c @@ -1070,9 +1070,35 @@ vhost_blk_session_unregister_interrupts(struct spdk_vhost_blk_session *bvsession } } +static void +_vhost_blk_vq_register_interrupt(void *arg) +{ + struct spdk_vhost_virtqueue *vq = arg; + struct spdk_vhost_session *vsession = vq->vsession; + struct spdk_vhost_blk_dev *bvdev = to_blk_dev(vsession->vdev); + + if (bvdev->bdev) { + vq->intr = spdk_interrupt_register(vq->vring.kickfd, vdev_vq_worker, vq, "vdev_vq_worker"); + } else { + vq->intr = spdk_interrupt_register(vq->vring.kickfd, no_bdev_vdev_vq_worker, vq, + "no_bdev_vdev_vq_worker"); + } + + if (vq->intr == NULL) { + SPDK_ERRLOG("Fail to register req notifier handler.\n"); + assert(false); + } +} + +static void +vhost_blk_vq_register_interrupt(struct spdk_vhost_session *vsession, + struct spdk_vhost_virtqueue *vq) +{ + spdk_thread_send_msg(vsession->vdev->thread, _vhost_blk_vq_register_interrupt, vq); +} + static int -vhost_blk_session_register_interrupts(struct spdk_vhost_blk_session *bvsession, - spdk_interrupt_fn fn, const char *name) +vhost_blk_session_register_no_bdev_interrupts(struct spdk_vhost_blk_session *bvsession) { struct spdk_vhost_session *vsession = &bvsession->vsession; struct spdk_vhost_virtqueue *vq = NULL; @@ -1083,19 +1109,18 @@ vhost_blk_session_register_interrupts(struct spdk_vhost_blk_session *bvsession, vq = &vsession->virtqueue[i]; SPDK_DEBUGLOG(vhost_blk, "Register vq[%d]'s kickfd is %d\n", i, vq->vring.kickfd); - - vq->intr = spdk_interrupt_register(vq->vring.kickfd, fn, vq, name); + vq->intr = spdk_interrupt_register(vq->vring.kickfd, no_bdev_vdev_vq_worker, vq, + "no_bdev_vdev_vq_worker"); if (vq->intr == NULL) { - SPDK_ERRLOG("Fail to register req notifier handler.\n"); goto err; } + } return 0; err: vhost_blk_session_unregister_interrupts(bvsession); - return -1; } @@ -1157,10 +1182,9 @@ vhost_user_session_bdev_remove_cb(struct spdk_vhost_dev *vdev, bvsession = to_blk_session(vsession); if (bvsession->requestq_poller) { spdk_poller_unregister(&bvsession->requestq_poller); - if (vsession->virtqueue[0].intr) { + if (vsession->interrupt_mode) { vhost_blk_session_unregister_interrupts(bvsession); - rc = vhost_blk_session_register_interrupts(bvsession, no_bdev_vdev_vq_worker, - "no_bdev_vdev_vq_worker"); + rc = vhost_blk_session_register_no_bdev_interrupts(bvsession); if (rc) { SPDK_ERRLOG("%s: Interrupt register failed\n", vsession->name); return rc; @@ -1292,7 +1316,7 @@ vhost_blk_start(struct spdk_vhost_dev *vdev, { struct spdk_vhost_blk_session *bvsession = to_blk_session(vsession); struct spdk_vhost_blk_dev *bvdev; - int i, rc = 0; + int i; /* return if start is already in progress */ if (bvsession->requestq_poller) { @@ -1324,23 +1348,6 @@ vhost_blk_start(struct spdk_vhost_dev *vdev, } } - if (spdk_interrupt_mode_is_enabled()) { - if (bvdev->bdev) { - rc = vhost_blk_session_register_interrupts(bvsession, - vdev_vq_worker, - "vdev_vq_worker"); - } else { - rc = vhost_blk_session_register_interrupts(bvsession, - no_bdev_vdev_vq_worker, - "no_bdev_vdev_vq_worker"); - } - - if (rc) { - SPDK_ERRLOG("%s: Interrupt register failed\n", vsession->name); - return rc; - } - } - if (bvdev->bdev) { bvsession->requestq_poller = SPDK_POLLER_REGISTER(vdev_worker, bvsession, 0); } else { @@ -1409,10 +1416,7 @@ vhost_blk_stop(struct spdk_vhost_dev *vdev, } spdk_poller_unregister(&bvsession->requestq_poller); - - if (vsession->virtqueue[0].intr) { - vhost_blk_session_unregister_interrupts(bvsession); - } + vhost_blk_session_unregister_interrupts(bvsession); /* vhost_user_session_send_event timeout is 3 seconds, here set retry within 4 seconds */ bvsession->vsession.stop_retry_count = 4000; @@ -1558,6 +1562,7 @@ static const struct spdk_vhost_user_dev_backend vhost_blk_user_device_backend = .start_session = vhost_blk_start, .stop_session = vhost_blk_stop, .alloc_vq_tasks = alloc_vq_task_pool, + .register_vq_interrupt = vhost_blk_vq_register_interrupt, }; static const struct spdk_vhost_dev_backend vhost_blk_device_backend = { diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index 1fe18df89..56ffead07 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -224,6 +224,7 @@ struct spdk_vhost_user_dev_backend { spdk_vhost_session_fn start_session; spdk_vhost_session_fn stop_session; int (*alloc_vq_tasks)(struct spdk_vhost_session *vsession, uint16_t qid); + void (*register_vq_interrupt)(struct spdk_vhost_session *vsession, struct spdk_vhost_virtqueue *vq); }; enum vhost_backend_type {