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();
        }
 
        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 {
        bool fnew = true;
        unsigned long flags;
        u16 dev_type;
+       int ret;
 
        /* Make sure this is a new offer */
        mutex_lock(&vmbus_connection.channel_mutex);
         * 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);
        struct device *dev;
 
        rescind = (struct vmbus_channel_rescind_offer *)hdr;
+
+       mutex_lock(&vmbus_connection.channel_mutex);
        channel = relid2channel(rescind->child_relid);
 
        if (channel == NULL) {
                 * vmbus_process_offer(), we have already invoked
                 * vmbus_release_relid() on error.
                 */
-               return;
+               goto out;
        }
 
        spin_lock_irqsave(&channel->lock, flags);
        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
                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.
 
        struct list_head *cur, *tmp;
        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) {
                if (channel->offermsg.child_relid == relid) {
                        found_channel = channel;
                        }
                }
        }
-       mutex_unlock(&vmbus_connection.channel_mutex);
 
        return found_channel;
 }