|
@@ -310,6 +310,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
|
|
vmbus_release_relid(relid);
|
|
|
|
|
|
BUG_ON(!channel->rescind);
|
|
|
+ BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex));
|
|
|
|
|
|
if (channel->target_cpu != get_cpu()) {
|
|
|
put_cpu();
|
|
@@ -321,9 +322,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid)
|
|
|
}
|
|
|
|
|
|
if (channel->primary_channel == NULL) {
|
|
|
- mutex_lock(&vmbus_connection.channel_mutex);
|
|
|
list_del(&channel->listentry);
|
|
|
- mutex_unlock(&vmbus_connection.channel_mutex);
|
|
|
|
|
|
primary_channel = channel;
|
|
|
} else {
|
|
@@ -367,6 +366,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
|
|
bool fnew = true;
|
|
|
unsigned long flags;
|
|
|
u16 dev_type;
|
|
|
+ int ret;
|
|
|
|
|
|
/* Make sure this is a new offer */
|
|
|
mutex_lock(&vmbus_connection.channel_mutex);
|
|
@@ -449,7 +449,11 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
|
|
|
* binding which eventually invokes the device driver's AddDevice()
|
|
|
* 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",
|
|
|
newchannel->offermsg.child_relid);
|
|
|
kfree(newchannel->device_obj);
|
|
@@ -725,6 +729,8 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
|
|
struct device *dev;
|
|
|
|
|
|
rescind = (struct vmbus_channel_rescind_offer *)hdr;
|
|
|
+
|
|
|
+ mutex_lock(&vmbus_connection.channel_mutex);
|
|
|
channel = relid2channel(rescind->child_relid);
|
|
|
|
|
|
if (channel == NULL) {
|
|
@@ -733,7 +739,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
|
|
* vmbus_process_offer(), we have already invoked
|
|
|
* vmbus_release_relid() on error.
|
|
|
*/
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
spin_lock_irqsave(&channel->lock, flags);
|
|
@@ -743,7 +749,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
|
|
if (channel->device_obj) {
|
|
|
if (channel->chn_rescind_callback) {
|
|
|
channel->chn_rescind_callback(channel);
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
}
|
|
|
/*
|
|
|
* We will have to unregister this device from the
|
|
@@ -758,8 +764,25 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr)
|
|
|
hv_process_channel_removal(channel,
|
|
|
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 -
|
|
|
* This is invoked when all offers have been delivered.
|