Commit 85d9aa70 authored by Dexuan Cui's avatar Dexuan Cui Committed by Greg Kroah-Hartman

Drivers: hv: vmbus: add an API vmbus_hvsock_device_unregister()

The hvsock driver needs this API to release all the resources related
to the channel.
Signed-off-by: default avatarDexuan Cui <decui@microsoft.com>
Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 499e8401
...@@ -310,6 +310,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) ...@@ -310,6 +310,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
vmbus_release_relid(relid); vmbus_release_relid(relid);
BUG_ON(!channel->rescind); BUG_ON(!channel->rescind);
BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
if (channel->target_cpu != get_cpu()) { if (channel->target_cpu != get_cpu()) {
put_cpu(); put_cpu();
...@@ -321,9 +322,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) ...@@ -321,9 +322,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
} }
if (channel->primary_channel == NULL) { if (channel->primary_channel == NULL) {
mutex_lock(&vmbus_connection.channel_mutex);
list_del(&channel->listentry); list_del(&channel->listentry);
mutex_unlock(&vmbus_connection.channel_mutex);
primary_channel = channel; primary_channel = channel;
} else { } else {
...@@ -367,6 +366,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) ...@@ -367,6 +366,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
bool fnew = true; bool fnew = true;
unsigned long flags; unsigned long flags;
u16 dev_type; u16 dev_type;
int ret;
/* Make sure this is a new offer */ /* Make sure this is a new offer */
mutex_lock(&vmbus_connection.channel_mutex); mutex_lock(&vmbus_connection.channel_mutex);
...@@ -449,7 +449,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) ...@@ -449,7 +449,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
* binding which eventually invokes the device driver's AddDevice() * binding which eventually invokes the device driver's AddDevice()
* method. * method.
*/ */
if (vmbus_device_register(newchannel->device_obj) != 0) { mutex_lock(&vmbus_connection.channel_mutex);
ret = vmbus_device_register(newchannel->device_obj);
mutex_unlock(&vmbus_connection.channel_mutex);
if (ret != 0) {
pr_err("unable to add child device object (relid %d)\n", pr_err("unable to add child device object (relid %d)\n",
newchannel->offermsg.child_relid); newchannel->offermsg.child_relid);
kfree(newchannel->device_obj); kfree(newchannel->device_obj);
...@@ -725,6 +729,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) ...@@ -725,6 +729,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
struct device *dev; struct device *dev;
rescind = (struct vmbus_channel_rescind_offer *)hdr; rescind = (struct vmbus_channel_rescind_offer *)hdr;
mutex_lock(&vmbus_connection.channel_mutex);
channel = relid2channel(rescind->child_relid); channel = relid2channel(rescind->child_relid);
if (channel == NULL) { if (channel == NULL) {
...@@ -733,7 +739,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) ...@@ -733,7 +739,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
* vmbus_process_offer(), we have already invoked * vmbus_process_offer(), we have already invoked
* vmbus_release_relid() on error. * vmbus_release_relid() on error.
*/ */
return; goto out;
} }
spin_lock_irqsave(&channel->lock, flags); spin_lock_irqsave(&channel->lock, flags);
...@@ -743,7 +749,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) ...@@ -743,7 +749,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
if (channel->device_obj) { if (channel->device_obj) {
if (channel->chn_rescind_callback) { if (channel->chn_rescind_callback) {
channel->chn_rescind_callback(channel); channel->chn_rescind_callback(channel);
return; goto out;
} }
/* /*
* We will have to unregister this device from the * We will have to unregister this device from the
...@@ -758,7 +764,24 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) ...@@ -758,7 +764,24 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
hv_process_channel_removal(channel, hv_process_channel_removal(channel,
channel->offermsg.child_relid); channel->offermsg.child_relid);
} }
out:
mutex_unlock(&vmbus_connection.channel_mutex);
}
void vmbus_hvsock_device_unregister(struct vmbus_channel *channel)
{
mutex_lock(&vmbus_connection.channel_mutex);
BUG_ON(!is_hvsock_channel(channel));
channel->rescind = true;
vmbus_device_unregister(channel->device_obj);
mutex_unlock(&vmbus_connection.channel_mutex);
} }
EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister);
/* /*
* vmbus_onoffers_delivered - * vmbus_onoffers_delivered -
......
...@@ -288,7 +288,8 @@ struct vmbus_channel *relid2channel(u32 relid) ...@@ -288,7 +288,8 @@ struct vmbus_channel *relid2channel(u32 relid)
struct list_head *cur, *tmp; struct list_head *cur, *tmp;
struct vmbus_channel *cur_sc; struct vmbus_channel *cur_sc;
mutex_lock(&vmbus_connection.channel_mutex); BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) {
if (channel->offermsg.child_relid == relid) { if (channel->offermsg.child_relid == relid) {
found_channel = channel; found_channel = channel;
...@@ -307,7 +308,6 @@ struct vmbus_channel *relid2channel(u32 relid) ...@@ -307,7 +308,6 @@ struct vmbus_channel *relid2channel(u32 relid)
} }
} }
} }
mutex_unlock(&vmbus_connection.channel_mutex);
return found_channel; return found_channel;
} }
......
...@@ -1069,6 +1069,8 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver, ...@@ -1069,6 +1069,8 @@ int __must_check __vmbus_driver_register(struct hv_driver *hv_driver,
const char *mod_name); const char *mod_name);
void vmbus_driver_unregister(struct hv_driver *hv_driver); void vmbus_driver_unregister(struct hv_driver *hv_driver);
void vmbus_hvsock_device_unregister(struct vmbus_channel *channel);
int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj, int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
resource_size_t min, resource_size_t max, resource_size_t min, resource_size_t max,
resource_size_t size, resource_size_t align, resource_size_t size, resource_size_t align,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment