The logic is unused since commit 509879bdb30b8 ("Drivers: hv: Introduce a policy for controlling channel affinity"). This logic assumes that a channel target_cpu doesn't change during the lifetime of a channel, but this assumption is incompatible with the new functionality that allows changing the vCPU a channel will interrupt.
Unified · Split
| @@ -433,14 +433,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel) · 432 unmodified lines | |||
| 433 | spin_unlock_irqrestore(&primary_channel->lock, flags); | 433 | spin_unlock_irqrestore(&primary_channel->lock, flags); |
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | /* | ||
| 437 | * We need to free the bit for init_vp_index() to work in the case | ||
| 438 | * of sub-channel, when we reload drivers like hv_netvsc. | ||
| 439 | */ | ||
| 440 | if (channel->affinity_policy == HV_LOCALIZED) | ||
| 441 | cpumask_clear_cpu(channel->target_cpu, | ||
| 442 | &primary_channel->alloced_cpus_in_node); | ||
| 443 | |||
| 444 | /* | 436 | /* |
| 445 | * Upon suspend, an in-use hv_sock channel is marked as "rescinded" and | 437 | * Upon suspend, an in-use hv_sock channel is marked as "rescinded" and |
| 446 | * the relid is invalidated; after hibernation, when the user-space app | 438 | * the relid is invalidated; after hibernation, when the user-space app |
| @@ -662,20 +654,21 @@ static DEFINE_SPINLOCK(bind_channel_to_cpu_lock); · 215 unmodified lines | |||
| 662 | /* | 654 | /* |
| 663 | * Starting with Win8, we can statically distribute the incoming | 655 | * Starting with Win8, we can statically distribute the incoming |
| 664 | * channel interrupt load by binding a channel to VCPU. | 656 | * channel interrupt load by binding a channel to VCPU. |
| 665 | * We distribute the interrupt loads to one or more NUMA nodes based on | ||
| 666 | * the channel's affinity_policy. | ||
| 667 | * | 657 | * |
| 668 | * For pre-win8 hosts or non-performance critical channels we assign the | 658 | * For pre-win8 hosts or non-performance critical channels we assign the |
| 669 | * first CPU in the first NUMA node. | 659 | * first CPU in the first NUMA node. |
| 660 | * | ||
| 661 | * Starting with win8, performance critical channels will be distributed | ||
| 662 | * evenly among all the available NUMA nodes. Once the node is assigned, | ||
| 663 | * we will assign the CPU based on a simple round robin scheme. | ||
| 670 | */ | 664 | */ |
| 671 | static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) | 665 | static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) |
| 672 | { | 666 | { |
| 673 | u32 cur_cpu; | ||
| 674 | bool perf_chn = vmbus_devs[dev_type].perf_device; | 667 | bool perf_chn = vmbus_devs[dev_type].perf_device; |
| 675 | struct vmbus_channel *primary = channel->primary_channel; | ||
| 676 | int next_node; | ||
| 677 | cpumask_var_t available_mask; | 668 | cpumask_var_t available_mask; |
| 678 | struct cpumask *alloced_mask; | 669 | struct cpumask *alloced_mask; |
| 670 | u32 target_cpu; | ||
| 671 | int numa_node; | ||
| 679 | 672 | ||
| 680 | if ((vmbus_proto_version == VERSION_WS2008) || | 673 | if ((vmbus_proto_version == VERSION_WS2008) || |
| 681 | (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) || | 674 | (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) || |
| @@ -693,31 +686,27 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) · 11 unmodified lines | |||
| 693 | return; | 686 | return; |
| 694 | } | 687 | } |
| 695 | 688 | ||
| 696 | spin_lock(&bind_channel_to_cpu_lock); | ||
| 697 | |||
| 698 | /* | 689 | /* |
| 699 | * Based on the channel affinity policy, we will assign the NUMA | 690 | * Serializes the accesses to the global variable next_numa_node_id. |
| 700 | * nodes. | 691 | * See also the header comment of the spin lock declaration. |
| 701 | */ | 692 | */ |
| 693 | spin_lock(&bind_channel_to_cpu_lock); | ||
| 702 | 694 | ||
| 703 | if ((channel->affinity_policy == HV_BALANCED) || (!primary)) { | 695 | while (true) { |
| 704 | while (true) { | 696 | numa_node = next_numa_node_id++; |
| 705 | next_node = next_numa_node_id++; | 697 | if (numa_node == nr_node_ids) { |
| 706 | if (next_node == nr_node_ids) { | 698 | next_numa_node_id = 0; |
| 707 | next_node = next_numa_node_id = 0; | 699 | continue; |
| 708 | continue; | ||
| 709 | } | ||
| 710 | if (cpumask_empty(cpumask_of_node(next_node))) | ||
| 711 | continue; | ||
| 712 | break; | ||
| 713 | } | 700 | } |
| 714 | channel->numa_node = next_node; | 701 | if (cpumask_empty(cpumask_of_node(numa_node))) |
| 715 | primary = channel; | 702 | continue; |
| 703 | break; | ||
| 716 | } | 704 | } |
| 717 | alloced_mask = &hv_context.hv_numa_map[primary->numa_node]; | 705 | channel->numa_node = numa_node; |
| 706 | alloced_mask = &hv_context.hv_numa_map[numa_node]; | ||
| 718 | 707 | ||
| 719 | if (cpumask_weight(alloced_mask) == | 708 | if (cpumask_weight(alloced_mask) == |
| 720 | cpumask_weight(cpumask_of_node(primary->numa_node))) { | 709 | cpumask_weight(cpumask_of_node(numa_node))) { |
| 721 | /* | 710 | /* |
| 722 | * We have cycled through all the CPUs in the node; | 711 | * We have cycled through all the CPUs in the node; |
| 723 | * reset the alloced map. | 712 | * reset the alloced map. |
| @@ -725,57 +714,13 @@ static void init_vp_index(struct vmbus_channel *channel, u16 dev_type) · 1 unmodified line | |||
| 725 | cpumask_clear(alloced_mask); | 714 | cpumask_clear(alloced_mask); |
| 726 | } | 715 | } |
| 727 | 716 | ||
| 728 | cpumask_xor(available_mask, alloced_mask, | 717 | cpumask_xor(available_mask, alloced_mask, cpumask_of_node(numa_node)); |
| 729 | cpumask_of_node(primary->numa_node)); | ||
| 730 | 718 | ||
| 731 | cur_cpu = -1; | 719 | target_cpu = cpumask_first(available_mask); |
| 732 | 720 | cpumask_set_cpu(target_cpu, alloced_mask); | |
| 733 | if (primary->affinity_policy == HV_LOCALIZED) { | ||
| 734 | /* | ||
| 735 | * Normally Hyper-V host doesn't create more subchannels | ||
| 736 | * than there are VCPUs on the node but it is possible when not | ||
| 737 | * all present VCPUs on the node are initialized by guest. | ||
| 738 | * Clear the alloced_cpus_in_node to start over. | ||
| 739 | */ | ||
| 740 | if (cpumask_equal(&primary->alloced_cpus_in_node, | ||
| 741 | cpumask_of_node(primary->numa_node))) | ||
| 742 | cpumask_clear(&primary->alloced_cpus_in_node); | ||
| 743 | } | ||
| 744 | |||
| 745 | while (true) { | ||
| 746 | cur_cpu = cpumask_next(cur_cpu, available_mask); | ||
| 747 | if (cur_cpu >= nr_cpu_ids) { | ||
| 748 | cur_cpu = -1; | ||
| 749 | cpumask_copy(available_mask, | ||
| 750 | cpumask_of_node(primary->numa_node)); | ||
| 751 | continue; | ||
| 752 | } | ||
| 753 | |||
| 754 | if (primary->affinity_policy == HV_LOCALIZED) { | ||
| 755 | /* | ||
| 756 | * NOTE: in the case of sub-channel, we clear the | ||
| 757 | * sub-channel related bit(s) in | ||
| 758 | * primary->alloced_cpus_in_node in | ||
| 759 | * hv_process_channel_removal(), so when we | ||
| 760 | * reload drivers like hv_netvsc in SMP guest, here | ||
| 761 | * we're able to re-allocate | ||
| 762 | * bit from primary->alloced_cpus_in_node. | ||
| 763 | */ | ||
| 764 | if (!cpumask_test_cpu(cur_cpu, | ||
| 765 | &primary->alloced_cpus_in_node)) { | ||
| 766 | cpumask_set_cpu(cur_cpu, | ||
| 767 | &primary->alloced_cpus_in_node); | ||
| 768 | cpumask_set_cpu(cur_cpu, alloced_mask); | ||
| 769 | break; | ||
| 770 | } | ||
| 771 | } else { | ||
| 772 | cpumask_set_cpu(cur_cpu, alloced_mask); | ||
| 773 | break; | ||
| 774 | } | ||
| 775 | } | ||
| 776 | 721 | ||
| 777 | channel->target_cpu = cur_cpu; | 722 | channel->target_cpu = target_cpu; |
| 778 | channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu); | 723 | channel->target_vp = hv_cpu_number_to_vp_number(target_cpu); |
| 779 | 724 | ||
| 780 | spin_unlock(&bind_channel_to_cpu_lock); | 725 | spin_unlock(&bind_channel_to_cpu_lock); |
| 781 | 726 | ||
| @@ -689,11 +689,6 @@ union hv_connection_id { · 688 unmodified lines | |||
| 689 | } u; | 689 | } u; |
| 690 | }; | 690 | }; |
| 691 | 691 | ||
| 692 | enum hv_numa_policy { | ||
| 693 | HV_BALANCED = 0, | ||
| 694 | HV_LOCALIZED, | ||
| 695 | }; | ||
| 696 | |||
| 697 | enum vmbus_device_type { | 692 | enum vmbus_device_type { |
| 698 | HV_IDE = 0, | 693 | HV_IDE = 0, |
| 699 | HV_SCSI, | 694 | HV_SCSI, |
| @@ -808,10 +803,6 @@ struct vmbus_channel { · 108 unmodified lines | |||
| 808 | u32 target_vp; | 803 | u32 target_vp; |
| 809 | /* The corresponding CPUID in the guest */ | 804 | /* The corresponding CPUID in the guest */ |
| 810 | u32 target_cpu; | 805 | u32 target_cpu; |
| 811 | /* | ||
| 812 | * State to manage the CPU affiliation of channels. | ||
| 813 | */ | ||
| 814 | struct cpumask alloced_cpus_in_node; | ||
| 815 | int numa_node; | 806 | int numa_node; |
| 816 | /* | 807 | /* |
| 817 | * Support for sub-channels. For high performance devices, | 808 | * Support for sub-channels. For high performance devices, |
| @@ -898,18 +889,6 @@ struct vmbus_channel { · 80 unmodified lines | |||
| 898 | */ | 889 | */ |
| 899 | bool low_latency; | 890 | bool low_latency; |
| 900 | 891 | ||
| 901 | /* | ||
| 902 | * NUMA distribution policy: | ||
| 903 | * We support two policies: | ||
| 904 | * 1) Balanced: Here all performance critical channels are | ||
| 905 | * distributed evenly amongst all the NUMA nodes. | ||
| 906 | * This policy will be the default policy. | ||
| 907 | * 2) Localized: All channels of a given instance of a | ||
| 908 | * performance critical service will be assigned CPUs | ||
| 909 | * within a selected NUMA node. | ||
| 910 | */ | ||
| 911 | enum hv_numa_policy affinity_policy; | ||
| 912 | |||
| 913 | bool probe_done; | 892 | bool probe_done; |
| 914 | 893 | ||
| 915 | /* | 894 | /* |
| @@ -965,12 +944,6 @@ static inline bool is_sub_channel(const struct vmbus_channel *c) · 49 unmodified lines | |||
| 965 | return c->offermsg.offer.sub_channel_index != 0; | 944 | return c->offermsg.offer.sub_channel_index != 0; |
| 966 | } | 945 | } |
| 967 | 946 | ||
| 968 | static inline void set_channel_affinity_state(struct vmbus_channel *c, | ||
| 969 | enum hv_numa_policy policy) | ||
| 970 | { | ||
| 971 | c->affinity_policy = policy; | ||
| 972 | } | ||
| 973 | |||
| 974 | static inline void set_channel_read_mode(struct vmbus_channel *c, | 947 | static inline void set_channel_read_mode(struct vmbus_channel *c, |
| 975 | enum hv_callback_mode mode) | 948 | enum hv_callback_mode mode) |
| 976 | { | 949 | { |