vhost-blk: add set interrupt mode to poller

Change-Id: Ie599e445aca8241cf2f71e152ea92a5f92dd4dc5
Signed-off-by: Liu Xiaodong <xiaodong.liu@intel.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5788
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Liu Xiaodong 2020-12-31 08:07:31 -05:00 committed by Tomasz Zawadzki
parent 2d36f6f11c
commit db8ac562b3
3 changed files with 80 additions and 21 deletions

View File

@ -1289,10 +1289,6 @@ vhost_start_device_cb(int vid)
goto out;
}
if (spdk_interrupt_mode_is_enabled()) {
vsession->interrupt_mode = true;
}
vdev = vsession->vdev;
if (vsession->started) {
/* already started, nothing to do */
@ -1409,6 +1405,54 @@ out:
return rc;
}
void
vhost_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;
/* vring.desc and vring.desc_packed are in a union struct
* so q->vring.desc can replace q->vring.desc_packed.
*/
if (q->vring.desc == NULL || q->vring.size == 0) {
continue;
}
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));
if (rc < 0) {
SPDK_ERRLOG("failed to kick vring: %s.\n", spdk_strerror(errno));
}
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;
}
}
}
int
spdk_vhost_set_socket_path(const char *basename)
{

View File

@ -1064,6 +1064,14 @@ err:
return -1;
}
static void
vhost_blk_poller_set_interrupt_mode(struct spdk_poller *poller, void *cb_arg, bool interrupt_mode)
{
struct spdk_vhost_blk_session *bvsession = cb_arg;
vhost_session_set_interrupt_mode(&bvsession->vsession, interrupt_mode);
}
static struct spdk_vhost_blk_dev *
to_blk_dev(struct spdk_vhost_dev *vdev)
{
@ -1127,20 +1135,21 @@ vhost_session_bdev_remove_cb(struct spdk_vhost_dev *vdev,
struct spdk_vhost_blk_session *bvsession;
int rc;
bvsession = (struct spdk_vhost_blk_session *)vsession;
bvsession = to_blk_session(vsession);
if (bvsession->requestq_poller) {
spdk_poller_unregister(&bvsession->requestq_poller);
bvsession->requestq_poller = SPDK_POLLER_REGISTER(no_bdev_vdev_worker, bvsession, 0);
}
if (vsession->virtqueue[0].intr) {
vhost_blk_session_unregister_interrupts(bvsession);
rc = vhost_blk_session_register_interrupts(bvsession, no_bdev_vdev_vq_worker);
if (rc) {
SPDK_ERRLOG("%s: Interrupt register failed\n", vsession->name);
return -1;
if (vsession->virtqueue[0].intr) {
vhost_blk_session_unregister_interrupts(bvsession);
rc = vhost_blk_session_register_interrupts(bvsession, no_bdev_vdev_vq_worker);
if (rc) {
SPDK_ERRLOG("%s: Interrupt register failed\n", vsession->name);
return rc;
}
}
bvsession->requestq_poller = SPDK_POLLER_REGISTER(no_bdev_vdev_worker, bvsession, 0);
spdk_poller_register_interrupt(bvsession->requestq_poller, vhost_blk_poller_set_interrupt_mode,
bvsession);
}
return 0;
@ -1293,15 +1302,16 @@ vhost_blk_start_cb(struct spdk_vhost_dev *vdev,
SPDK_ERRLOG("%s: Interrupt register failed\n", vsession->name);
goto out;
}
SPDK_INFOLOG(vhost, "%s: started interrupt source on lcore %d\n",
vsession->name, spdk_env_get_current_core());
} else {
bvsession->requestq_poller = SPDK_POLLER_REGISTER(bvdev->bdev ? vdev_worker : no_bdev_vdev_worker,
bvsession, 0);
SPDK_INFOLOG(vhost, "%s: started poller on lcore %d\n",
vsession->name, spdk_env_get_current_core());
}
bvsession->requestq_poller = SPDK_POLLER_REGISTER(bvdev->bdev ? vdev_worker : no_bdev_vdev_worker,
bvsession, 0);
SPDK_INFOLOG(vhost, "%s: started poller on lcore %d\n",
vsession->name, spdk_env_get_current_core());
spdk_poller_register_interrupt(bvsession->requestq_poller, vhost_blk_poller_set_interrupt_mode,
bvsession);
out:
vhost_session_start_done(vsession, rc);
return rc;

View File

@ -416,6 +416,11 @@ int vhost_start_device_cb(int vid);
int vhost_stop_device_cb(int vid);
int vhost_destroy_connection_cb(int vid);
/*
* Set vhost session to run in interrupt or poll mode
*/
void vhost_session_set_interrupt_mode(struct spdk_vhost_session *vsession, bool interrupt_mode);
/*
* Memory registration functions used in start/stop device callbacks
*/