aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv/channel.c')
-rw-r--r--drivers/hv/channel.c50
1 files changed, 46 insertions, 4 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 0b122f8c7005..6de6c98ce6eb 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -116,6 +116,15 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
116 unsigned long flags; 116 unsigned long flags;
117 int ret, t, err = 0; 117 int ret, t, err = 0;
118 118
119 spin_lock_irqsave(&newchannel->sc_lock, flags);
120 if (newchannel->state == CHANNEL_OPEN_STATE) {
121 newchannel->state = CHANNEL_OPENING_STATE;
122 } else {
123 spin_unlock_irqrestore(&newchannel->sc_lock, flags);
124 return -EINVAL;
125 }
126 spin_unlock_irqrestore(&newchannel->sc_lock, flags);
127
119 newchannel->onchannel_callback = onchannelcallback; 128 newchannel->onchannel_callback = onchannelcallback;
120 newchannel->channel_callback_context = context; 129 newchannel->channel_callback_context = context;
121 130
@@ -216,6 +225,9 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
216 list_del(&open_info->msglistentry); 225 list_del(&open_info->msglistentry);
217 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 226 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
218 227
228 if (err == 0)
229 newchannel->state = CHANNEL_OPENED_STATE;
230
219 kfree(open_info); 231 kfree(open_info);
220 return err; 232 return err;
221 233
@@ -500,15 +512,14 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
500} 512}
501EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); 513EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
502 514
503/* 515static void vmbus_close_internal(struct vmbus_channel *channel)
504 * vmbus_close - Close the specified channel
505 */
506void vmbus_close(struct vmbus_channel *channel)
507{ 516{
508 struct vmbus_channel_close_channel *msg; 517 struct vmbus_channel_close_channel *msg;
509 int ret; 518 int ret;
510 unsigned long flags; 519 unsigned long flags;
511 520
521 channel->state = CHANNEL_OPEN_STATE;
522 channel->sc_creation_callback = NULL;
512 /* Stop callback and cancel the timer asap */ 523 /* Stop callback and cancel the timer asap */
513 spin_lock_irqsave(&channel->inbound_lock, flags); 524 spin_lock_irqsave(&channel->inbound_lock, flags);
514 channel->onchannel_callback = NULL; 525 channel->onchannel_callback = NULL;
@@ -538,6 +549,37 @@ void vmbus_close(struct vmbus_channel *channel)
538 549
539 550
540} 551}
552
553/*
554 * vmbus_close - Close the specified channel
555 */
556void vmbus_close(struct vmbus_channel *channel)
557{
558 struct list_head *cur, *tmp;
559 struct vmbus_channel *cur_channel;
560
561 if (channel->primary_channel != NULL) {
562 /*
563 * We will only close sub-channels when
564 * the primary is closed.
565 */
566 return;
567 }
568 /*
569 * Close all the sub-channels first and then close the
570 * primary channel.
571 */
572 list_for_each_safe(cur, tmp, &channel->sc_list) {
573 cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
574 if (cur_channel->state != CHANNEL_OPENED_STATE)
575 continue;
576 vmbus_close_internal(cur_channel);
577 }
578 /*
579 * Now close the primary.
580 */
581 vmbus_close_internal(channel);
582}
541EXPORT_SYMBOL_GPL(vmbus_close); 583EXPORT_SYMBOL_GPL(vmbus_close);
542 584
543/** 585/**