aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hv')
-rw-r--r--drivers/hv/channel.c16
-rw-r--r--drivers/hv/channel_mgmt.c11
-rw-r--r--drivers/hv/connection.c11
3 files changed, 23 insertions, 15 deletions
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 602ca86a6488..740edec161bb 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -471,18 +471,26 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle)
471} 471}
472EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); 472EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl);
473 473
474static void reset_channel_cb(void *arg)
475{
476 struct vmbus_channel *channel = arg;
477
478 channel->onchannel_callback = NULL;
479}
480
474static void vmbus_close_internal(struct vmbus_channel *channel) 481static void vmbus_close_internal(struct vmbus_channel *channel)
475{ 482{
476 struct vmbus_channel_close_channel *msg; 483 struct vmbus_channel_close_channel *msg;
477 int ret; 484 int ret;
478 unsigned long flags;
479 485
480 channel->state = CHANNEL_OPEN_STATE; 486 channel->state = CHANNEL_OPEN_STATE;
481 channel->sc_creation_callback = NULL; 487 channel->sc_creation_callback = NULL;
482 /* Stop callback and cancel the timer asap */ 488 /* Stop callback and cancel the timer asap */
483 spin_lock_irqsave(&channel->inbound_lock, flags); 489 if (channel->target_cpu != smp_processor_id())
484 channel->onchannel_callback = NULL; 490 smp_call_function_single(channel->target_cpu, reset_channel_cb,
485 spin_unlock_irqrestore(&channel->inbound_lock, flags); 491 channel, true);
492 else
493 reset_channel_cb(channel);
486 494
487 /* Send a closing message */ 495 /* Send a closing message */
488 496
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index fa920469bf10..6f7fdd9a7e77 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -365,7 +365,7 @@ static u32 next_vp;
365 * performance critical channels (IDE, SCSI and Network) will be uniformly 365 * performance critical channels (IDE, SCSI and Network) will be uniformly
366 * distributed across all available CPUs. 366 * distributed across all available CPUs.
367 */ 367 */
368static u32 get_vp_index(uuid_le *type_guid) 368static void init_vp_index(struct vmbus_channel *channel, uuid_le *type_guid)
369{ 369{
370 u32 cur_cpu; 370 u32 cur_cpu;
371 int i; 371 int i;
@@ -387,10 +387,13 @@ static u32 get_vp_index(uuid_le *type_guid)
387 * Also if the channel is not a performance critical 387 * Also if the channel is not a performance critical
388 * channel, bind it to cpu 0. 388 * channel, bind it to cpu 0.
389 */ 389 */
390 return 0; 390 channel->target_cpu = 0;
391 channel->target_vp = 0;
392 return;
391 } 393 }
392 cur_cpu = (++next_vp % max_cpus); 394 cur_cpu = (++next_vp % max_cpus);
393 return hv_context.vp_index[cur_cpu]; 395 channel->target_cpu = cur_cpu;
396 channel->target_vp = hv_context.vp_index[cur_cpu];
394} 397}
395 398
396/* 399/*
@@ -438,7 +441,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
438 offer->connection_id; 441 offer->connection_id;
439 } 442 }
440 443
441 newchannel->target_vp = get_vp_index(&offer->offer.if_type); 444 init_vp_index(newchannel, &offer->offer.if_type);
442 445
443 memcpy(&newchannel->offermsg, offer, 446 memcpy(&newchannel->offermsg, offer,
444 sizeof(struct vmbus_channel_offer_channel)); 447 sizeof(struct vmbus_channel_offer_channel));
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index 2e7801af466e..df2363ea017f 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -277,7 +277,6 @@ struct vmbus_channel *relid2channel(u32 relid)
277static void process_chn_event(u32 relid) 277static void process_chn_event(u32 relid)
278{ 278{
279 struct vmbus_channel *channel; 279 struct vmbus_channel *channel;
280 unsigned long flags;
281 void *arg; 280 void *arg;
282 bool read_state; 281 bool read_state;
283 u32 bytes_to_read; 282 u32 bytes_to_read;
@@ -296,13 +295,12 @@ static void process_chn_event(u32 relid)
296 /* 295 /*
297 * A channel once created is persistent even when there 296 * A channel once created is persistent even when there
298 * is no driver handling the device. An unloading driver 297 * is no driver handling the device. An unloading driver
299 * sets the onchannel_callback to NULL under the 298 * sets the onchannel_callback to NULL on the same CPU
300 * protection of the channel inbound_lock. Thus, checking 299 * as where this interrupt is handled (in an interrupt context).
301 * and invoking the driver specific callback takes care of 300 * Thus, checking and invoking the driver specific callback takes
302 * orderly unloading of the driver. 301 * care of orderly unloading of the driver.
303 */ 302 */
304 303
305 spin_lock_irqsave(&channel->inbound_lock, flags);
306 if (channel->onchannel_callback != NULL) { 304 if (channel->onchannel_callback != NULL) {
307 arg = channel->channel_callback_context; 305 arg = channel->channel_callback_context;
308 read_state = channel->batched_reading; 306 read_state = channel->batched_reading;
@@ -327,7 +325,6 @@ static void process_chn_event(u32 relid)
327 pr_err("no channel callback for relid - %u\n", relid); 325 pr_err("no channel callback for relid - %u\n", relid);
328 } 326 }
329 327
330 spin_unlock_irqrestore(&channel->inbound_lock, flags);
331} 328}
332 329
333/* 330/*