diff options
Diffstat (limited to 'drivers/hv/channel.c')
-rw-r--r-- | drivers/hv/channel.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 19f0cf37e0ed..ba0a092ae085 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c | |||
@@ -659,22 +659,28 @@ void vmbus_close(struct vmbus_channel *channel) | |||
659 | */ | 659 | */ |
660 | return; | 660 | return; |
661 | } | 661 | } |
662 | mutex_lock(&vmbus_connection.channel_mutex); | ||
663 | /* | 662 | /* |
664 | * Close all the sub-channels first and then close the | 663 | * Close all the sub-channels first and then close the |
665 | * primary channel. | 664 | * primary channel. |
666 | */ | 665 | */ |
667 | list_for_each_safe(cur, tmp, &channel->sc_list) { | 666 | list_for_each_safe(cur, tmp, &channel->sc_list) { |
668 | cur_channel = list_entry(cur, struct vmbus_channel, sc_list); | 667 | cur_channel = list_entry(cur, struct vmbus_channel, sc_list); |
669 | vmbus_close_internal(cur_channel); | ||
670 | if (cur_channel->rescind) { | 668 | if (cur_channel->rescind) { |
669 | wait_for_completion(&cur_channel->rescind_event); | ||
670 | mutex_lock(&vmbus_connection.channel_mutex); | ||
671 | vmbus_close_internal(cur_channel); | ||
671 | hv_process_channel_removal( | 672 | hv_process_channel_removal( |
672 | cur_channel->offermsg.child_relid); | 673 | cur_channel->offermsg.child_relid); |
674 | } else { | ||
675 | mutex_lock(&vmbus_connection.channel_mutex); | ||
676 | vmbus_close_internal(cur_channel); | ||
673 | } | 677 | } |
678 | mutex_unlock(&vmbus_connection.channel_mutex); | ||
674 | } | 679 | } |
675 | /* | 680 | /* |
676 | * Now close the primary. | 681 | * Now close the primary. |
677 | */ | 682 | */ |
683 | mutex_lock(&vmbus_connection.channel_mutex); | ||
678 | vmbus_close_internal(channel); | 684 | vmbus_close_internal(channel); |
679 | mutex_unlock(&vmbus_connection.channel_mutex); | 685 | mutex_unlock(&vmbus_connection.channel_mutex); |
680 | } | 686 | } |