577 lines
16 KiB
Diff
577 lines
16 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Hao Li <hao.l.li@intel.com>
|
|
Date: Thu, 25 Jan 2018 10:12:26 -0500
|
|
Subject: [PATCH] VBS-K: added VHM wrapper APIs
|
|
|
|
This patch added 3 VHM wrapper APIs to the VBS-K framework:
|
|
- long virtio_dev_register(struct virtio_dev_info *dev);
|
|
- long virtio_dev_deregister(struct virtio_dev_info *dev);
|
|
- int virtio_vq_index_get(struct virtio_dev_info *dev, int req_cnt);
|
|
|
|
VBS-K modules could use the APIs above to register kick callback
|
|
handlers to VHM.
|
|
|
|
This patch also updated the reference driver with the new APIs
|
|
usage.
|
|
|
|
Change-Id: I6a92a36eb785d55c1a4aa09bba46c67ed5dd2194
|
|
Signed-off-by: Hao Li <hao.l.li@intel.com>
|
|
---
|
|
drivers/vbs/vbs.c | 121 ++++++++++++++++++++++++
|
|
drivers/vbs/vbs_rng.c | 199 ++++++++++------------------------------
|
|
include/linux/vbs/vbs.h | 16 +++-
|
|
3 files changed, 181 insertions(+), 155 deletions(-)
|
|
|
|
diff --git a/drivers/vbs/vbs.c b/drivers/vbs/vbs.c
|
|
index 1e7a964..9d96f45 100644
|
|
--- a/drivers/vbs/vbs.c
|
|
+++ b/drivers/vbs/vbs.c
|
|
@@ -67,6 +67,127 @@
|
|
#include <linux/vbs/vbs.h>
|
|
#include <linux/vbs/vq.h>
|
|
|
|
+long virtio_dev_register(struct virtio_dev_info *dev)
|
|
+{
|
|
+ struct vm_info info;
|
|
+ int ret;
|
|
+
|
|
+ pr_debug("vmid is %d\n", dev->_ctx.vmid);
|
|
+
|
|
+ if (dev->dev_notify == NULL) {
|
|
+ pr_err("%s dev_notify empty!\n", dev->name);
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * dev->name is 32 chars while vhm only accepts 16 chars
|
|
+ * at most, so we make sure there will be a NULL
|
|
+ * terminator for the chars.
|
|
+ */
|
|
+ dev->name[15] = '\0';
|
|
+ dev->_ctx.vhm_client_id =
|
|
+ acrn_ioreq_create_client(dev->_ctx.vmid,
|
|
+ dev->dev_notify,
|
|
+ dev->name);
|
|
+ if (dev->_ctx.vhm_client_id < 0) {
|
|
+ pr_err("failed to create client of acrn ioreq!\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ ret = acrn_ioreq_add_iorange(dev->_ctx.vhm_client_id,
|
|
+ dev->io_range_type ? REQ_MMIO : REQ_PORTIO,
|
|
+ dev->io_range_start,
|
|
+ dev->io_range_start + dev->io_range_len - 1);
|
|
+ if (ret < 0) {
|
|
+ pr_err("failed to add iorange to acrn ioreq!\n");
|
|
+ goto err;
|
|
+ }
|
|
+
|
|
+ /* feed up max_cpu and req_buf */
|
|
+ ret = vhm_get_vm_info(dev->_ctx.vmid, &info);
|
|
+ if (ret < 0) {
|
|
+ pr_err("failed in vhm_get_vm_info!\n");
|
|
+ goto range_err;
|
|
+ }
|
|
+ dev->_ctx.max_vcpu = info.max_vcpu;
|
|
+
|
|
+ dev->_ctx.req_buf = acrn_ioreq_get_reqbuf(dev->_ctx.vhm_client_id);
|
|
+ if (dev->_ctx.req_buf == NULL) {
|
|
+ pr_err("failed in acrn_ioreq_get_reqbuf!\n");
|
|
+ goto range_err;
|
|
+ }
|
|
+
|
|
+ acrn_ioreq_attach_client(dev->_ctx.vhm_client_id, 0);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+range_err:
|
|
+ acrn_ioreq_del_iorange(dev->_ctx.vhm_client_id,
|
|
+ dev->io_range_type ? REQ_MMIO : REQ_PORTIO,
|
|
+ dev->io_range_start,
|
|
+ dev->io_range_start + dev->io_range_len);
|
|
+
|
|
+err:
|
|
+ acrn_ioreq_destroy_client(dev->_ctx.vhm_client_id);
|
|
+
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+long virtio_dev_deregister(struct virtio_dev_info *dev)
|
|
+{
|
|
+ acrn_ioreq_del_iorange(dev->_ctx.vhm_client_id,
|
|
+ dev->io_range_type ? REQ_MMIO : REQ_PORTIO,
|
|
+ dev->io_range_start,
|
|
+ dev->io_range_start + dev->io_range_len);
|
|
+
|
|
+ acrn_ioreq_destroy_client(dev->_ctx.vhm_client_id);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int virtio_vq_index_get(struct virtio_dev_info *dev, int req_cnt)
|
|
+{
|
|
+ int val = -1;
|
|
+ struct vhm_request *req;
|
|
+ int i;
|
|
+
|
|
+ if (unlikely(req_cnt <= 0))
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (dev == NULL) {
|
|
+ pr_err("%s: dev is NULL!\n", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < dev->_ctx.max_vcpu; i++) {
|
|
+ req = &dev->_ctx.req_buf[i];
|
|
+ if (req->valid && req->processed == REQ_STATE_PROCESSING &&
|
|
+ req->client == dev->_ctx.vhm_client_id) {
|
|
+ if (req->reqs.pio_request.direction == REQUEST_READ) {
|
|
+ /* currently we handle kick only,
|
|
+ * so read will return 0
|
|
+ */
|
|
+ pr_debug("%s: read request!\n", __func__);
|
|
+ if (dev->io_range_type == PIO_RANGE)
|
|
+ req->reqs.pio_request.value = 0;
|
|
+ else
|
|
+ req->reqs.mmio_request.value = 0;
|
|
+ } else {
|
|
+ pr_debug("%s: write request! type %d\n",
|
|
+ __func__, req->type);
|
|
+ if (dev->io_range_type == PIO_RANGE)
|
|
+ val = req->reqs.pio_request.value;
|
|
+ else
|
|
+ val = req->reqs.mmio_request.value;
|
|
+ }
|
|
+ req->processed = REQ_STATE_SUCCESS;
|
|
+ acrn_ioreq_complete_request(dev->_ctx.vhm_client_id, i);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
static long virtio_vqs_info_set(struct virtio_dev_info *dev,
|
|
struct vbs_vqs_info __user *i)
|
|
{
|
|
diff --git a/drivers/vbs/vbs_rng.c b/drivers/vbs/vbs_rng.c
|
|
index f2234e7..87965ba 100644
|
|
--- a/drivers/vbs/vbs_rng.c
|
|
+++ b/drivers/vbs/vbs_rng.c
|
|
@@ -74,8 +74,6 @@
|
|
|
|
#include <linux/vbs/vq.h>
|
|
#include <linux/vbs/vbs.h>
|
|
-#include <linux/vhm/acrn_common.h>
|
|
-#include <linux/vhm/acrn_vhm_ioreq.h>
|
|
#include <linux/hashtable.h>
|
|
|
|
enum {
|
|
@@ -96,26 +94,14 @@ enum {
|
|
struct vbs_rng {
|
|
struct virtio_dev_info dev;
|
|
struct virtio_vq_info vqs[VBS_K_RNG_VQ_MAX];
|
|
- int vhm_client_id;
|
|
/* Below could be device specific members */
|
|
struct hwrng hwrng;
|
|
-};
|
|
-
|
|
-/*
|
|
- * Each VBS-K module might serve multiple connections from multiple
|
|
- * guests/device models/VBS-Us, so better to maintain the connections
|
|
- * in a list, and here we use hashtalble as an example.
|
|
- */
|
|
-struct vbs_rng_client {
|
|
- struct vbs_rng *rng;
|
|
- int vhm_client_id;
|
|
- int max_vcpu;
|
|
- struct vhm_request *req_buf;
|
|
-};
|
|
-
|
|
-/* instances malloced/freed by hashtable routines */
|
|
-struct vbs_rng_hash_entry {
|
|
- struct vbs_rng_client *info;
|
|
+ /*
|
|
+ * Each VBS-K module might serve multiple connections
|
|
+ * from multiple guests/device models/VBS-Us, so better
|
|
+ * to maintain the connections in a list, and here we
|
|
+ * use hashtable as an example.
|
|
+ */
|
|
struct hlist_node node;
|
|
};
|
|
|
|
@@ -149,30 +135,20 @@ static void vbs_rng_hash_init(void)
|
|
vbs_rng_hash_initialized = 1;
|
|
}
|
|
|
|
-static int vbs_rng_hash_add(struct vbs_rng_client *client)
|
|
+static int vbs_rng_hash_add(struct vbs_rng *entry)
|
|
{
|
|
- struct vbs_rng_hash_entry *entry;
|
|
-
|
|
if (!vbs_rng_hash_initialized) {
|
|
pr_err("RNG hash table not initialized!\n");
|
|
return -1;
|
|
}
|
|
|
|
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
|
|
- if (!entry) {
|
|
- pr_err("Failed to alloc memory for rng hash entry!\n");
|
|
- return -1;
|
|
- }
|
|
-
|
|
- entry->info = client;
|
|
-
|
|
- hash_add(HASH_NAME, &entry->node, entry->info->vhm_client_id);
|
|
+ hash_add(HASH_NAME, &entry->node, virtio_dev_client_id(&entry->dev));
|
|
return 0;
|
|
}
|
|
|
|
-static struct vbs_rng_client *vbs_rng_hash_find(int client_id)
|
|
+static struct vbs_rng *vbs_rng_hash_find(int client_id)
|
|
{
|
|
- struct vbs_rng_hash_entry *entry;
|
|
+ struct vbs_rng *entry;
|
|
int bkt;
|
|
|
|
if (!vbs_rng_hash_initialized) {
|
|
@@ -181,8 +157,8 @@ static struct vbs_rng_client *vbs_rng_hash_find(int client_id)
|
|
}
|
|
|
|
hash_for_each(HASH_NAME, bkt, entry, node)
|
|
- if (entry->info->vhm_client_id == client_id)
|
|
- return entry->info;
|
|
+ if (virtio_dev_client_id(&entry->dev) == client_id)
|
|
+ return entry;
|
|
|
|
pr_err("Not found item matching client_id!\n");
|
|
return NULL;
|
|
@@ -190,7 +166,7 @@ static struct vbs_rng_client *vbs_rng_hash_find(int client_id)
|
|
|
|
static int vbs_rng_hash_del(int client_id)
|
|
{
|
|
- struct vbs_rng_hash_entry *entry;
|
|
+ struct vbs_rng *entry;
|
|
int bkt;
|
|
|
|
if (!vbs_rng_hash_initialized) {
|
|
@@ -199,9 +175,8 @@ static int vbs_rng_hash_del(int client_id)
|
|
}
|
|
|
|
hash_for_each(HASH_NAME, bkt, entry, node)
|
|
- if (entry->info->vhm_client_id == client_id) {
|
|
+ if (virtio_dev_client_id(&entry->dev) == client_id) {
|
|
hash_del(&entry->node);
|
|
- kfree(entry);
|
|
return 0;
|
|
}
|
|
|
|
@@ -212,7 +187,7 @@ static int vbs_rng_hash_del(int client_id)
|
|
|
|
static int vbs_rng_hash_del_all(void)
|
|
{
|
|
- struct vbs_rng_hash_entry *entry;
|
|
+ struct vbs_rng *entry;
|
|
int bkt;
|
|
|
|
if (!vbs_rng_hash_initialized) {
|
|
@@ -221,75 +196,11 @@ static int vbs_rng_hash_del_all(void)
|
|
}
|
|
|
|
hash_for_each(HASH_NAME, bkt, entry, node)
|
|
- if (1) {
|
|
- hash_del(&entry->node);
|
|
- kfree(entry);
|
|
- }
|
|
+ hash_del(&entry->node);
|
|
|
|
return 0;
|
|
}
|
|
|
|
-static int register_vhm_client(struct virtio_dev_info *dev)
|
|
-{
|
|
- unsigned int vmid;
|
|
- struct vm_info info;
|
|
- struct vbs_rng_client *client;
|
|
- int ret;
|
|
-
|
|
- client = kcalloc(1, sizeof(*client), GFP_KERNEL);
|
|
- if (!client) {
|
|
- pr_err("failed to malloc vbs_rng_client!\n");
|
|
- return -EINVAL;
|
|
- }
|
|
-
|
|
- client->rng = container_of(dev, struct vbs_rng, dev);
|
|
- vmid = dev->_ctx.vmid;
|
|
- pr_debug("vmid is %d\n", vmid);
|
|
-
|
|
- client->vhm_client_id = acrn_ioreq_create_client(vmid, handle_kick,
|
|
- "vbs_rng kick init\n");
|
|
- if (client->vhm_client_id < 0) {
|
|
- pr_err("failed to create client of acrn ioreq!\n");
|
|
- goto err;
|
|
- }
|
|
-
|
|
- ret = acrn_ioreq_add_iorange(client->vhm_client_id,
|
|
- dev->io_range_type ? REQ_MMIO : REQ_PORTIO,
|
|
- dev->io_range_start,
|
|
- dev->io_range_start + dev->io_range_len);
|
|
- if (ret < 0) {
|
|
- pr_err("failed to add iorange to acrn ioreq!\n");
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* feed up max_cpu and req_buf */
|
|
- ret = vhm_get_vm_info(vmid, &info);
|
|
- if (ret < 0) {
|
|
- pr_err("failed in vhm_get_vm_info!\n");
|
|
- goto err;
|
|
- }
|
|
- client->max_vcpu = info.max_vcpu;
|
|
-
|
|
- client->req_buf = acrn_ioreq_get_reqbuf(client->vhm_client_id);
|
|
- if (client->req_buf == NULL) {
|
|
- pr_err("failed in acrn_ioreq_get_reqbuf!\n");
|
|
- goto err;
|
|
- }
|
|
-
|
|
- /* just attach once as vhm will kick kthread */
|
|
- acrn_ioreq_attach_client(client->vhm_client_id, 0);
|
|
-
|
|
- client->rng->vhm_client_id = client->vhm_client_id;
|
|
- vbs_rng_hash_add(client);
|
|
-
|
|
- return 0;
|
|
-err:
|
|
- acrn_ioreq_destroy_client(client->vhm_client_id);
|
|
- kfree(client);
|
|
-
|
|
- return -EINVAL;
|
|
-}
|
|
-
|
|
static void handle_vq_kick(struct vbs_rng *rng, int vq_idx)
|
|
{
|
|
struct iovec iov;
|
|
@@ -309,8 +220,6 @@ static void handle_vq_kick(struct vbs_rng *rng, int vq_idx)
|
|
|
|
vq = &(sc->vqs[vq_idx]);
|
|
|
|
- pr_debug("before vq_has_desc!\n");
|
|
-
|
|
while (virtio_vq_has_descs(vq)) {
|
|
virtio_vq_getchain(vq, &idx, &iov, 1, NULL);
|
|
|
|
@@ -334,47 +243,25 @@ static void handle_vq_kick(struct vbs_rng *rng, int vq_idx)
|
|
static int handle_kick(int client_id, int req_cnt)
|
|
{
|
|
int val = -1;
|
|
- struct vhm_request *req;
|
|
- struct vbs_rng_client *client;
|
|
- int i;
|
|
+ struct vbs_rng *rng;
|
|
|
|
if (unlikely(req_cnt <= 0))
|
|
return -EINVAL;
|
|
|
|
- pr_debug("%s!\n", __func__);
|
|
+ pr_debug("%s: handle kick!\n", __func__);
|
|
|
|
- client = vbs_rng_hash_find(client_id);
|
|
- if (!client) {
|
|
- pr_err("Ooops! client %d not found!\n", client_id);
|
|
+ rng = vbs_rng_hash_find(client_id);
|
|
+ if (rng == NULL) {
|
|
+ pr_err("%s: client %d not found!\n",
|
|
+ __func__, client_id);
|
|
return -EINVAL;
|
|
}
|
|
|
|
- for (i = 0; i < client->max_vcpu; i++) {
|
|
- req = &client->req_buf[i];
|
|
- if (req->valid && req->processed == REQ_STATE_PROCESSING &&
|
|
- req->client == client->vhm_client_id) {
|
|
- if (req->reqs.pio_request.direction == REQUEST_READ)
|
|
- /* currently we handle kick only,
|
|
- * so read will return 0
|
|
- */
|
|
- req->reqs.pio_request.value = 0;
|
|
- else
|
|
- val = req->reqs.pio_request.value;
|
|
- pr_debug("%s: ioreq type %d, direction %d, "
|
|
- "addr 0x%lx, size 0x%lx, value 0x%x\n",
|
|
- __func__,
|
|
- req->type,
|
|
- req->reqs.pio_request.direction,
|
|
- req->reqs.pio_request.address,
|
|
- req->reqs.pio_request.size,
|
|
- req->reqs.pio_request.value);
|
|
- req->processed = REQ_STATE_SUCCESS;
|
|
- acrn_ioreq_complete_request(client->vhm_client_id, i);
|
|
- }
|
|
- }
|
|
+ val = virtio_vq_index_get(&rng->dev, req_cnt);
|
|
|
|
if (val >= 0)
|
|
- handle_vq_kick(client->rng, val);
|
|
+ handle_vq_kick(rng, val);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -385,15 +272,15 @@ static int vbs_rng_open(struct inode *inode, struct file *f)
|
|
struct virtio_vq_info *vqs;
|
|
int i;
|
|
|
|
- pr_debug("%s!\n", __func__);
|
|
-
|
|
rng = kmalloc(sizeof(*rng), GFP_KERNEL);
|
|
- if (!rng) {
|
|
+ if (rng == NULL) {
|
|
pr_err("Failed to allocate memory for vbs_rng!\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
dev = &rng->dev;
|
|
+ strncpy(dev->name, "vbs_rng", VBS_NAME_LEN);
|
|
+ dev->dev_notify = handle_kick;
|
|
vqs = (struct virtio_vq_info *)&rng->vqs;
|
|
|
|
for (i = 0; i < VBS_K_RNG_VQ_MAX; i++) {
|
|
@@ -411,6 +298,8 @@ static int vbs_rng_open(struct inode *inode, struct file *f)
|
|
virtio_dev_init(dev, vqs, VBS_K_RNG_VQ_MAX);
|
|
|
|
f->private_data = rng;
|
|
+
|
|
+ /* init a hash table to maintain multi-connections */
|
|
vbs_rng_hash_init();
|
|
|
|
return 0;
|
|
@@ -419,14 +308,10 @@ static int vbs_rng_open(struct inode *inode, struct file *f)
|
|
static int vbs_rng_release(struct inode *inode, struct file *f)
|
|
{
|
|
struct vbs_rng *rng = f->private_data;
|
|
- struct vbs_rng_client *client;
|
|
int i;
|
|
|
|
- pr_debug("%s!\n", __func__);
|
|
-
|
|
- client = vbs_rng_hash_find(rng->vhm_client_id);
|
|
- if (!client)
|
|
- pr_err("%s: UNLIKELY not found client!\n",
|
|
+ if (!rng)
|
|
+ pr_err("%s: UNLIKELY rng NULL!\n",
|
|
__func__);
|
|
|
|
vbs_rng_stop(rng);
|
|
@@ -437,16 +322,16 @@ static int vbs_rng_release(struct inode *inode, struct file *f)
|
|
/* device specific release */
|
|
vbs_rng_reset(rng);
|
|
|
|
- pr_debug("vbs_rng_connection cnt is %d\n", vbs_rng_connection_cnt);
|
|
+ pr_debug("vbs_rng_connection cnt is %d\n",
|
|
+ vbs_rng_connection_cnt);
|
|
|
|
- if (client && vbs_rng_connection_cnt--)
|
|
- vbs_rng_hash_del(client->vhm_client_id);
|
|
+ if (rng && vbs_rng_connection_cnt--)
|
|
+ vbs_rng_hash_del(virtio_dev_client_id(&rng->dev));
|
|
if (!vbs_rng_connection_cnt) {
|
|
pr_debug("vbs_rng remove all hash entries\n");
|
|
vbs_rng_hash_del_all();
|
|
}
|
|
|
|
- kfree(client);
|
|
kfree(rng);
|
|
|
|
pr_debug("%s done\n", __func__);
|
|
@@ -488,7 +373,8 @@ static long vbs_rng_ioctl(struct file *f, unsigned int ioctl,
|
|
* return vhost_net_set_features(n, features);
|
|
*/
|
|
case VBS_SET_VQ:
|
|
- /* we handle this here because we want to register VHM client
|
|
+ /*
|
|
+ * we handle this here because we want to register VHM client
|
|
* after handling VBS_K_SET_VQ request
|
|
*/
|
|
pr_debug("VBS_K_SET_VQ ioctl:\n");
|
|
@@ -498,10 +384,16 @@ static long vbs_rng_ioctl(struct file *f, unsigned int ioctl,
|
|
return -EFAULT;
|
|
}
|
|
/* Register VHM client */
|
|
- if (register_vhm_client(&rng->dev) < 0) {
|
|
+ if (virtio_dev_register(&rng->dev) < 0) {
|
|
pr_err("failed to register VHM client!\n");
|
|
return -EFAULT;
|
|
}
|
|
+ /* Added to local hash table */
|
|
+ if (vbs_rng_hash_add(rng) < 0) {
|
|
+ pr_err("failed to add to hashtable!\n");
|
|
+ return -EFAULT;
|
|
+ }
|
|
+ /* Increment counter */
|
|
vbs_rng_connection_cnt++;
|
|
return r;
|
|
default:
|
|
@@ -544,6 +436,7 @@ static void vbs_rng_stop_vq(struct vbs_rng *rng,
|
|
/* device specific function */
|
|
static void vbs_rng_stop(struct vbs_rng *rng)
|
|
{
|
|
+ virtio_dev_deregister(&rng->dev);
|
|
}
|
|
|
|
/* device specific function */
|
|
diff --git a/include/linux/vbs/vbs.h b/include/linux/vbs/vbs.h
|
|
index 715c491..b2e185e 100644
|
|
--- a/include/linux/vbs/vbs.h
|
|
+++ b/include/linux/vbs/vbs.h
|
|
@@ -63,6 +63,8 @@
|
|
#define _VBS_H_
|
|
|
|
#include <linux/vbs/vbs_common_if.h>
|
|
+#include <linux/vhm/acrn_common.h>
|
|
+#include <linux/vhm/acrn_vhm_ioreq.h>
|
|
|
|
/*
|
|
* VBS-K device needs to handle frontend driver's kick in kernel.
|
|
@@ -78,6 +80,9 @@ enum IORangeType {
|
|
struct ctx {
|
|
/* VHM required info */
|
|
int vmid;
|
|
+ int vhm_client_id;
|
|
+ int max_vcpu;
|
|
+ struct vhm_request *req_buf;
|
|
};
|
|
|
|
struct virtio_desc { /* AKA vring_desc */
|
|
@@ -138,12 +143,16 @@ struct virtio_dev_info {
|
|
enum IORangeType io_range_type; /* IO range type, PIO or MMIO */
|
|
|
|
/* members created in kernel space VBS */
|
|
- void (*dev_notify)(void *, struct virtio_vq_info *);
|
|
- /* device-wide notification */
|
|
+ int (*dev_notify)(int, int); /* device-wide notification */
|
|
struct virtio_vq_info *vqs; /* virtqueue(s) */
|
|
int curq; /* current virtqueue index */
|
|
};
|
|
|
|
+static inline int virtio_dev_client_id(struct virtio_dev_info *dev)
|
|
+{
|
|
+ return dev->_ctx.vhm_client_id;
|
|
+}
|
|
+
|
|
/* VBS Runtime Control APIs */
|
|
long virtio_dev_init(struct virtio_dev_info *dev, struct virtio_vq_info *vqs,
|
|
int nvq);
|
|
@@ -151,5 +160,8 @@ long virtio_dev_ioctl(struct virtio_dev_info *dev, unsigned int ioctl,
|
|
void __user *argp);
|
|
long virtio_vqs_ioctl(struct virtio_dev_info *dev, unsigned int ioctl,
|
|
void __user *argp);
|
|
+long virtio_dev_register(struct virtio_dev_info *dev);
|
|
+long virtio_dev_deregister(struct virtio_dev_info *dev);
|
|
+int virtio_vq_index_get(struct virtio_dev_info *dev, int req_cnt);
|
|
|
|
#endif
|
|
--
|
|
2.21.0
|
|
|