diff options
Diffstat (limited to 'drivers/scsi/storvsc_drv.c')
| -rw-r--r-- | drivers/scsi/storvsc_drv.c | 61 |
1 files changed, 30 insertions, 31 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index f03dc03a42c3..8f88348ebe42 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c | |||
| @@ -446,7 +446,6 @@ struct storvsc_device { | |||
| 446 | 446 | ||
| 447 | bool destroy; | 447 | bool destroy; |
| 448 | bool drain_notify; | 448 | bool drain_notify; |
| 449 | bool open_sub_channel; | ||
| 450 | atomic_t num_outstanding_req; | 449 | atomic_t num_outstanding_req; |
| 451 | struct Scsi_Host *host; | 450 | struct Scsi_Host *host; |
| 452 | 451 | ||
| @@ -636,33 +635,38 @@ get_in_err: | |||
| 636 | static void handle_sc_creation(struct vmbus_channel *new_sc) | 635 | static void handle_sc_creation(struct vmbus_channel *new_sc) |
| 637 | { | 636 | { |
| 638 | struct hv_device *device = new_sc->primary_channel->device_obj; | 637 | struct hv_device *device = new_sc->primary_channel->device_obj; |
| 638 | struct device *dev = &device->device; | ||
| 639 | struct storvsc_device *stor_device; | 639 | struct storvsc_device *stor_device; |
| 640 | struct vmstorage_channel_properties props; | 640 | struct vmstorage_channel_properties props; |
| 641 | int ret; | ||
| 641 | 642 | ||
| 642 | stor_device = get_out_stor_device(device); | 643 | stor_device = get_out_stor_device(device); |
| 643 | if (!stor_device) | 644 | if (!stor_device) |
| 644 | return; | 645 | return; |
| 645 | 646 | ||
| 646 | if (stor_device->open_sub_channel == false) | ||
| 647 | return; | ||
| 648 | |||
| 649 | memset(&props, 0, sizeof(struct vmstorage_channel_properties)); | 647 | memset(&props, 0, sizeof(struct vmstorage_channel_properties)); |
| 650 | 648 | ||
| 651 | vmbus_open(new_sc, | 649 | ret = vmbus_open(new_sc, |
| 652 | storvsc_ringbuffer_size, | 650 | storvsc_ringbuffer_size, |
| 653 | storvsc_ringbuffer_size, | 651 | storvsc_ringbuffer_size, |
| 654 | (void *)&props, | 652 | (void *)&props, |
| 655 | sizeof(struct vmstorage_channel_properties), | 653 | sizeof(struct vmstorage_channel_properties), |
| 656 | storvsc_on_channel_callback, new_sc); | 654 | storvsc_on_channel_callback, new_sc); |
| 657 | 655 | ||
| 658 | if (new_sc->state == CHANNEL_OPENED_STATE) { | 656 | /* In case vmbus_open() fails, we don't use the sub-channel. */ |
| 659 | stor_device->stor_chns[new_sc->target_cpu] = new_sc; | 657 | if (ret != 0) { |
| 660 | cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus); | 658 | dev_err(dev, "Failed to open sub-channel: err=%d\n", ret); |
| 659 | return; | ||
| 661 | } | 660 | } |
| 661 | |||
| 662 | /* Add the sub-channel to the array of available channels. */ | ||
| 663 | stor_device->stor_chns[new_sc->target_cpu] = new_sc; | ||
| 664 | cpumask_set_cpu(new_sc->target_cpu, &stor_device->alloced_cpus); | ||
| 662 | } | 665 | } |
| 663 | 666 | ||
| 664 | static void handle_multichannel_storage(struct hv_device *device, int max_chns) | 667 | static void handle_multichannel_storage(struct hv_device *device, int max_chns) |
| 665 | { | 668 | { |
| 669 | struct device *dev = &device->device; | ||
| 666 | struct storvsc_device *stor_device; | 670 | struct storvsc_device *stor_device; |
| 667 | int num_cpus = num_online_cpus(); | 671 | int num_cpus = num_online_cpus(); |
| 668 | int num_sc; | 672 | int num_sc; |
| @@ -679,22 +683,12 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) | |||
| 679 | request = &stor_device->init_request; | 683 | request = &stor_device->init_request; |
| 680 | vstor_packet = &request->vstor_packet; | 684 | vstor_packet = &request->vstor_packet; |
| 681 | 685 | ||
| 682 | stor_device->open_sub_channel = true; | ||
| 683 | /* | 686 | /* |
| 684 | * Establish a handler for dealing with subchannels. | 687 | * Establish a handler for dealing with subchannels. |
| 685 | */ | 688 | */ |
| 686 | vmbus_set_sc_create_callback(device->channel, handle_sc_creation); | 689 | vmbus_set_sc_create_callback(device->channel, handle_sc_creation); |
| 687 | 690 | ||
| 688 | /* | 691 | /* |
| 689 | * Check to see if sub-channels have already been created. This | ||
| 690 | * can happen when this driver is re-loaded after unloading. | ||
| 691 | */ | ||
| 692 | |||
| 693 | if (vmbus_are_subchannels_present(device->channel)) | ||
| 694 | return; | ||
| 695 | |||
| 696 | stor_device->open_sub_channel = false; | ||
| 697 | /* | ||
| 698 | * Request the host to create sub-channels. | 692 | * Request the host to create sub-channels. |
| 699 | */ | 693 | */ |
| 700 | memset(request, 0, sizeof(struct storvsc_cmd_request)); | 694 | memset(request, 0, sizeof(struct storvsc_cmd_request)); |
| @@ -710,23 +704,29 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) | |||
| 710 | VM_PKT_DATA_INBAND, | 704 | VM_PKT_DATA_INBAND, |
| 711 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 705 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
| 712 | 706 | ||
| 713 | if (ret != 0) | 707 | if (ret != 0) { |
| 708 | dev_err(dev, "Failed to create sub-channel: err=%d\n", ret); | ||
| 714 | return; | 709 | return; |
| 710 | } | ||
| 715 | 711 | ||
| 716 | t = wait_for_completion_timeout(&request->wait_event, 10*HZ); | 712 | t = wait_for_completion_timeout(&request->wait_event, 10*HZ); |
| 717 | if (t == 0) | 713 | if (t == 0) { |
| 714 | dev_err(dev, "Failed to create sub-channel: timed out\n"); | ||
| 718 | return; | 715 | return; |
| 716 | } | ||
| 719 | 717 | ||
| 720 | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || | 718 | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || |
| 721 | vstor_packet->status != 0) | 719 | vstor_packet->status != 0) { |
| 720 | dev_err(dev, "Failed to create sub-channel: op=%d, sts=%d\n", | ||
| 721 | vstor_packet->operation, vstor_packet->status); | ||
| 722 | return; | 722 | return; |
| 723 | } | ||
| 723 | 724 | ||
| 724 | /* | 725 | /* |
| 725 | * Now that we created the sub-channels, invoke the check; this | 726 | * We need to do nothing here, because vmbus_process_offer() |
| 726 | * may trigger the callback. | 727 | * invokes channel->sc_creation_callback, which will open and use |
| 728 | * the sub-channel(s). | ||
| 727 | */ | 729 | */ |
| 728 | stor_device->open_sub_channel = true; | ||
| 729 | vmbus_are_subchannels_present(device->channel); | ||
| 730 | } | 730 | } |
| 731 | 731 | ||
| 732 | static void cache_wwn(struct storvsc_device *stor_device, | 732 | static void cache_wwn(struct storvsc_device *stor_device, |
| @@ -1794,7 +1794,6 @@ static int storvsc_probe(struct hv_device *device, | |||
| 1794 | } | 1794 | } |
| 1795 | 1795 | ||
| 1796 | stor_device->destroy = false; | 1796 | stor_device->destroy = false; |
| 1797 | stor_device->open_sub_channel = false; | ||
| 1798 | init_waitqueue_head(&stor_device->waiting_to_drain); | 1797 | init_waitqueue_head(&stor_device->waiting_to_drain); |
| 1799 | stor_device->device = device; | 1798 | stor_device->device = device; |
| 1800 | stor_device->host = host; | 1799 | stor_device->host = host; |
