aboutsummaryrefslogtreecommitdiff
path: root/hw/rdma/rdma_backend.c
diff options
context:
space:
mode:
authorYuval Shaia <yuval.shaia@oracle.com>2018-08-05 18:35:06 +0300
committerMarcel Apfelbaum <marcel.apfelbaum@gmail.com>2018-08-18 17:59:23 +0300
commit751522275a800c0d1c215b386a17f537bc76cd37 (patch)
treecbfce1b87af6243747e21f21a6625d2df1b94ea7 /hw/rdma/rdma_backend.c
parent0abaa41d936becd914a16ee1fe2a981d96d19428 (diff)
hw/rdma: Make distinction between device init and start modes
There are certain operations that are well considered as part of device configuration while others are needed only when "start" command is triggered by the guest driver. An example of device initialization step is msix_init and example of "device start" stage is the creation of a CQ completion handler thread. Driver expects such distinction - implement it. Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com> Reviewed-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com> Message-Id: <20180805153518.2983-2-yuval.shaia@oracle.com> Signed-off-by: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
Diffstat (limited to 'hw/rdma/rdma_backend.c')
-rw-r--r--hw/rdma/rdma_backend.c96
1 files changed, 77 insertions, 19 deletions
diff --git a/hw/rdma/rdma_backend.c b/hw/rdma/rdma_backend.c
index e9ced6f9ef..647e16399f 100644
--- a/hw/rdma/rdma_backend.c
+++ b/hw/rdma/rdma_backend.c
@@ -35,6 +35,7 @@
#define VENDOR_ERR_MR_SMALL 0x208
#define THR_NAME_LEN 16
+#define THR_POLL_TO 5000
typedef struct BackendCtx {
uint64_t req_id;
@@ -91,35 +92,82 @@ static void *comp_handler_thread(void *arg)
int rc;
struct ibv_cq *ev_cq;
void *ev_ctx;
+ int flags;
+ GPollFD pfds[1];
+
+ /* Change to non-blocking mode */
+ flags = fcntl(backend_dev->channel->fd, F_GETFL);
+ rc = fcntl(backend_dev->channel->fd, F_SETFL, flags | O_NONBLOCK);
+ if (rc < 0) {
+ pr_dbg("Fail to change to non-blocking mode\n");
+ return NULL;
+ }
pr_dbg("Starting\n");
+ pfds[0].fd = backend_dev->channel->fd;
+ pfds[0].events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+
+ backend_dev->comp_thread.is_running = true;
+
while (backend_dev->comp_thread.run) {
- pr_dbg("Waiting for completion on channel %p\n", backend_dev->channel);
- rc = ibv_get_cq_event(backend_dev->channel, &ev_cq, &ev_ctx);
- pr_dbg("ibv_get_cq_event=%d\n", rc);
- if (unlikely(rc)) {
- pr_dbg("---> ibv_get_cq_event (%d)\n", rc);
- continue;
- }
+ do {
+ rc = qemu_poll_ns(pfds, 1, THR_POLL_TO * (int64_t)SCALE_MS);
+ } while (!rc && backend_dev->comp_thread.run);
+
+ if (backend_dev->comp_thread.run) {
+ pr_dbg("Waiting for completion on channel %p\n", backend_dev->channel);
+ rc = ibv_get_cq_event(backend_dev->channel, &ev_cq, &ev_ctx);
+ pr_dbg("ibv_get_cq_event=%d\n", rc);
+ if (unlikely(rc)) {
+ pr_dbg("---> ibv_get_cq_event (%d)\n", rc);
+ continue;
+ }
- rc = ibv_req_notify_cq(ev_cq, 0);
- if (unlikely(rc)) {
- pr_dbg("Error %d from ibv_req_notify_cq\n", rc);
- }
+ rc = ibv_req_notify_cq(ev_cq, 0);
+ if (unlikely(rc)) {
+ pr_dbg("Error %d from ibv_req_notify_cq\n", rc);
+ }
- poll_cq(backend_dev->rdma_dev_res, ev_cq);
+ poll_cq(backend_dev->rdma_dev_res, ev_cq);
- ibv_ack_cq_events(ev_cq, 1);
+ ibv_ack_cq_events(ev_cq, 1);
+ }
}
pr_dbg("Going down\n");
/* TODO: Post cqe for all remaining buffs that were posted */
+ backend_dev->comp_thread.is_running = false;
+
+ qemu_thread_exit(0);
+
return NULL;
}
+static void stop_comp_thread(RdmaBackendDev *backend_dev)
+{
+ backend_dev->comp_thread.run = false;
+ while (backend_dev->comp_thread.is_running) {
+ pr_dbg("Waiting for thread to complete\n");
+ sleep(THR_POLL_TO / SCALE_US / 2);
+ }
+}
+
+static void start_comp_thread(RdmaBackendDev *backend_dev)
+{
+ char thread_name[THR_NAME_LEN] = {0};
+
+ stop_comp_thread(backend_dev);
+
+ snprintf(thread_name, sizeof(thread_name), "rdma_comp_%s",
+ ibv_get_device_name(backend_dev->ib_dev));
+ backend_dev->comp_thread.run = true;
+ qemu_thread_create(&backend_dev->comp_thread.thread, thread_name,
+ comp_handler_thread, backend_dev, QEMU_THREAD_DETACHED);
+}
+
void rdma_backend_register_comp_handler(void (*handler)(int status,
unsigned int vendor_err, void *ctx))
{
@@ -706,7 +754,6 @@ int rdma_backend_init(RdmaBackendDev *backend_dev,
int i;
int ret = 0;
int num_ibv_devices;
- char thread_name[THR_NAME_LEN] = {0};
struct ibv_device **dev_list;
struct ibv_port_attr port_attr;
@@ -800,11 +847,8 @@ int rdma_backend_init(RdmaBackendDev *backend_dev,
pr_dbg("interface_id=0x%" PRIx64 "\n",
be64_to_cpu(backend_dev->gid.global.interface_id));
- snprintf(thread_name, sizeof(thread_name), "rdma_comp_%s",
- ibv_get_device_name(backend_dev->ib_dev));
- backend_dev->comp_thread.run = true;
- qemu_thread_create(&backend_dev->comp_thread.thread, thread_name,
- comp_handler_thread, backend_dev, QEMU_THREAD_DETACHED);
+ backend_dev->comp_thread.run = false;
+ backend_dev->comp_thread.is_running = false;
ah_cache_init();
@@ -823,8 +867,22 @@ out:
return ret;
}
+
+void rdma_backend_start(RdmaBackendDev *backend_dev)
+{
+ pr_dbg("Starting rdma_backend\n");
+ start_comp_thread(backend_dev);
+}
+
+void rdma_backend_stop(RdmaBackendDev *backend_dev)
+{
+ pr_dbg("Stopping rdma_backend\n");
+ stop_comp_thread(backend_dev);
+}
+
void rdma_backend_fini(RdmaBackendDev *backend_dev)
{
+ rdma_backend_stop(backend_dev);
g_hash_table_destroy(ah_hash);
ibv_destroy_comp_channel(backend_dev->channel);
ibv_close_device(backend_dev->context);