diff options
author | Stefano Garzarella <sgarzare@redhat.com> | 2019-11-14 12:57:47 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2019-11-15 05:12:18 +0300 |
commit | b1bba80a4376aef34de2b57bfb8834bd095703ed (patch) | |
tree | b22280bc8b8e0f8789bfeb7f4013e0c670be2ca4 /drivers/misc | |
parent | c0cfa2d8a788fcf45df5bf4070ab2474c88d543a (diff) | |
download | linux-b1bba80a4376aef34de2b57bfb8834bd095703ed.tar.xz |
vsock/vmci: register vmci_transport only when VMCI guest/host are active
To allow other transports to be loaded with vmci_transport,
we register the vmci_transport as G2H or H2G only when a VMCI guest
or host is active.
To do that, this patch adds a callback registered in the vmci driver
that will be called when the host or guest becomes active.
This callback will register the vmci_transport in the VSOCK core.
Cc: Jorgen Hansen <jhansen@vmware.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/vmw_vmci/vmci_driver.c | 67 | ||||
-rw-r--r-- | drivers/misc/vmw_vmci/vmci_driver.h | 2 | ||||
-rw-r--r-- | drivers/misc/vmw_vmci/vmci_guest.c | 2 | ||||
-rw-r--r-- | drivers/misc/vmw_vmci/vmci_host.c | 7 |
4 files changed, 78 insertions, 0 deletions
diff --git a/drivers/misc/vmw_vmci/vmci_driver.c b/drivers/misc/vmw_vmci/vmci_driver.c index 819e35995d32..95fed4664a2d 100644 --- a/drivers/misc/vmw_vmci/vmci_driver.c +++ b/drivers/misc/vmw_vmci/vmci_driver.c @@ -28,6 +28,10 @@ MODULE_PARM_DESC(disable_guest, static bool vmci_guest_personality_initialized; static bool vmci_host_personality_initialized; +static DEFINE_MUTEX(vmci_vsock_mutex); /* protects vmci_vsock_transport_cb */ +static vmci_vsock_cb vmci_vsock_transport_cb; +bool vmci_vsock_cb_host_called; + /* * vmci_get_context_id() - Gets the current context ID. * @@ -45,6 +49,69 @@ u32 vmci_get_context_id(void) } EXPORT_SYMBOL_GPL(vmci_get_context_id); +/* + * vmci_register_vsock_callback() - Register the VSOCK vmci_transport callback. + * + * The callback will be called when the first host or guest becomes active, + * or if they are already active when this function is called. + * To unregister the callback, call this function with NULL parameter. + * + * Returns 0 on success. -EBUSY if a callback is already registered. + */ +int vmci_register_vsock_callback(vmci_vsock_cb callback) +{ + int err = 0; + + mutex_lock(&vmci_vsock_mutex); + + if (vmci_vsock_transport_cb && callback) { + err = -EBUSY; + goto out; + } + + vmci_vsock_transport_cb = callback; + + if (!vmci_vsock_transport_cb) { + vmci_vsock_cb_host_called = false; + goto out; + } + + if (vmci_guest_code_active()) + vmci_vsock_transport_cb(false); + + if (vmci_host_users() > 0) { + vmci_vsock_cb_host_called = true; + vmci_vsock_transport_cb(true); + } + +out: + mutex_unlock(&vmci_vsock_mutex); + return err; +} +EXPORT_SYMBOL_GPL(vmci_register_vsock_callback); + +void vmci_call_vsock_callback(bool is_host) +{ + mutex_lock(&vmci_vsock_mutex); + + if (!vmci_vsock_transport_cb) + goto out; + + /* In the host, this function could be called multiple times, + * but we want to register it only once. + */ + if (is_host) { + if (vmci_vsock_cb_host_called) + goto out; + + vmci_vsock_cb_host_called = true; + } + + vmci_vsock_transport_cb(is_host); +out: + mutex_unlock(&vmci_vsock_mutex); +} + static int __init vmci_drv_init(void) { int vmci_err; diff --git a/drivers/misc/vmw_vmci/vmci_driver.h b/drivers/misc/vmw_vmci/vmci_driver.h index aab81b67670c..990682480bf6 100644 --- a/drivers/misc/vmw_vmci/vmci_driver.h +++ b/drivers/misc/vmw_vmci/vmci_driver.h @@ -36,10 +36,12 @@ extern struct pci_dev *vmci_pdev; u32 vmci_get_context_id(void); int vmci_send_datagram(struct vmci_datagram *dg); +void vmci_call_vsock_callback(bool is_host); int vmci_host_init(void); void vmci_host_exit(void); bool vmci_host_code_active(void); +int vmci_host_users(void); int vmci_guest_init(void); void vmci_guest_exit(void); diff --git a/drivers/misc/vmw_vmci/vmci_guest.c b/drivers/misc/vmw_vmci/vmci_guest.c index 7a84a48c75da..cc8eeb361fcd 100644 --- a/drivers/misc/vmw_vmci/vmci_guest.c +++ b/drivers/misc/vmw_vmci/vmci_guest.c @@ -637,6 +637,8 @@ static int vmci_guest_probe_device(struct pci_dev *pdev, vmci_dev->iobase + VMCI_CONTROL_ADDR); pci_set_drvdata(pdev, vmci_dev); + + vmci_call_vsock_callback(false); return 0; err_free_irq: diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index 833e2bd248a5..ff3c396146ff 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -108,6 +108,11 @@ bool vmci_host_code_active(void) atomic_read(&vmci_host_active_users) > 0); } +int vmci_host_users(void) +{ + return atomic_read(&vmci_host_active_users); +} + /* * Called on open of /dev/vmci. */ @@ -338,6 +343,8 @@ static int vmci_host_do_init_context(struct vmci_host_dev *vmci_host_dev, vmci_host_dev->ct_type = VMCIOBJ_CONTEXT; atomic_inc(&vmci_host_active_users); + vmci_call_vsock_callback(true); + retval = 0; out: |