diff options
Diffstat (limited to 'drivers/hv')
| -rw-r--r-- | drivers/hv/channel.c | 16 | ||||
| -rw-r--r-- | drivers/hv/channel_mgmt.c | 11 | ||||
| -rw-r--r-- | drivers/hv/connection.c | 11 |
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 | } |
| 472 | EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); | 472 | EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); |
| 473 | 473 | ||
| 474 | static void reset_channel_cb(void *arg) | ||
| 475 | { | ||
| 476 | struct vmbus_channel *channel = arg; | ||
| 477 | |||
| 478 | channel->onchannel_callback = NULL; | ||
| 479 | } | ||
| 480 | |||
| 474 | static void vmbus_close_internal(struct vmbus_channel *channel) | 481 | static 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 | */ |
| 368 | static u32 get_vp_index(uuid_le *type_guid) | 368 | static 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) | |||
| 277 | static void process_chn_event(u32 relid) | 277 | static 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 | /* |
