| @@ -407,7 +407,15 @@ void hv_process_channel_removal(struct vmbus_channel *channel) · 406 unmodified lines |
| 407 | cpumask_clear_cpu(channel->target_cpu, | 407 | cpumask_clear_cpu(channel->target_cpu, |
| 408 | &primary_channel->alloced_cpus_in_node); | 408 | &primary_channel->alloced_cpus_in_node); |
| 409 | | 409 | |
| 410 | vmbus_release_relid(channel->offermsg.child_relid); | 410 | /* |
| | 411 | * Upon suspend, an in-use hv_sock channel is marked as "rescinded" and |
| | 412 | * the relid is invalidated; after hibernation, when the user-space app |
| | 413 | * destroys the channel, the relid is INVALID_RELID, and in this case |
| | 414 | * it's unnecessary and unsafe to release the old relid, since the same |
| | 415 | * relid can refer to a completely different channel now. |
| | 416 | */ |
| | 417 | if (channel->offermsg.child_relid != INVALID_RELID) |
| | 418 | vmbus_release_relid(channel->offermsg.child_relid); |
| 411 | | 419 | |
| 412 | free_channel(channel); | 420 | free_channel(channel); |
| 413 | } | 421 | } |
| @@ -851,6 +859,36 @@ void vmbus_initiate_unload(bool crash) · 437 unmodified lines |
| 851 | vmbus_wait_for_unload(); | 859 | vmbus_wait_for_unload(); |
| 852 | } | 860 | } |
| 853 | | 861 | |
| | 862 | static void check_ready_for_resume_event(void) |
| | 863 | { |
| | 864 | /* |
| | 865 | * If all the old primary channels have been fixed up, then it's safe |
| | 866 | * to resume. |
| | 867 | */ |
| | 868 | if (atomic_dec_and_test(&vmbus_connection.nr_chan_fixup_on_resume)) |
| | 869 | complete(&vmbus_connection.ready_for_resume_event); |
| | 870 | } |
| | 871 | |
| | 872 | static void vmbus_setup_channel_state(struct vmbus_channel *channel, |
| | 873 | struct vmbus_channel_offer_channel *offer) |
| | 874 | { |
| | 875 | /* |
| | 876 | * Setup state for signalling the host. |
| | 877 | */ |
| | 878 | channel->sig_event = VMBUS_EVENT_CONNECTION_ID; |
| | 879 | |
| | 880 | if (vmbus_proto_version != VERSION_WS2008) { |
| | 881 | channel->is_dedicated_interrupt = |
| | 882 | (offer->is_dedicated_interrupt != 0); |
| | 883 | channel->sig_event = offer->connection_id; |
| | 884 | } |
| | 885 | |
| | 886 | memcpy(&channel->offermsg, offer, |
| | 887 | sizeof(struct vmbus_channel_offer_channel)); |
| | 888 | channel->monitor_grp = (u8)offer->monitorid / 32; |
| | 889 | channel->monitor_bit = (u8)offer->monitorid % 32; |
| | 890 | } |
| | 891 | |
| 854 | /* | 892 | /* |
| 855 | * find_primary_channel_by_offer - Get the channel object given the new offer. | 893 | * find_primary_channel_by_offer - Get the channel object given the new offer. |
| 856 | * This is only used in the resume path of hibernation. | 894 | * This is only used in the resume path of hibernation. |
| @@ -902,14 +940,29 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) · 45 unmodified lines |
| 902 | atomic_dec(&vmbus_connection.offer_in_progress); | 940 | atomic_dec(&vmbus_connection.offer_in_progress); |
| 903 | | 941 | |
| 904 | /* | 942 | /* |
| 905 | * We're resuming from hibernation: we expect the host to send | 943 | * We're resuming from hibernation: all the sub-channel and |
| 906 | * exactly the same offers that we had before the hibernation. | 944 | * hv_sock channels we had before the hibernation should have |
| | 945 | * been cleaned up, and now we must be seeing a re-offered |
| | 946 | * primary channel that we had before the hibernation. |
| 907 | */ | 947 | */ |
| | 948 | |
| | 949 | WARN_ON(oldchannel->offermsg.child_relid != INVALID_RELID); |
| | 950 | /* Fix up the relid. */ |
| | 951 | oldchannel->offermsg.child_relid = offer->child_relid; |
| | 952 | |
| 908 | offer_sz = sizeof(*offer); | 953 | offer_sz = sizeof(*offer); |
| 909 | if (memcmp(offer, &oldchannel->offermsg, offer_sz) == 0) | 954 | if (memcmp(offer, &oldchannel->offermsg, offer_sz) == 0) { |
| | 955 | check_ready_for_resume_event(); |
| 910 | return; | 956 | return; |
| | 957 | } |
| 911 | | 958 | |
| 912 | pr_debug("Mismatched offer from the host (relid=%d)\n", | 959 | /* |
| | 960 | * This is not an error, since the host can also change the |
| | 961 | * other field(s) of the offer, e.g. on WS RS5 (Build 17763), |
| | 962 | * the offer->connection_id of the Mellanox VF vmbus device |
| | 963 | * can change when the host reoffers the device upon resume. |
| | 964 | */ |
| | 965 | pr_debug("vmbus offer changed: relid=%d\n", |
| 913 | offer->child_relid); | 966 | offer->child_relid); |
| 914 | | 967 | |
| 915 | print_hex_dump_debug("Old vmbus offer: ", DUMP_PREFIX_OFFSET, | 968 | print_hex_dump_debug("Old vmbus offer: ", DUMP_PREFIX_OFFSET, |
| @@ -917,6 +970,12 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) · 1 unmodified line |
| 917 | false); | 970 | false); |
| 918 | print_hex_dump_debug("New vmbus offer: ", DUMP_PREFIX_OFFSET, | 971 | print_hex_dump_debug("New vmbus offer: ", DUMP_PREFIX_OFFSET, |
| 919 | 16, 4, offer, offer_sz, false); | 972 | 16, 4, offer, offer_sz, false); |
| | 973 | |
| | 974 | /* Fix up the old channel. */ |
| | 975 | vmbus_setup_channel_state(oldchannel, offer); |
| | 976 | |
| | 977 | check_ready_for_resume_event(); |
| | 978 | |
| 920 | return; | 979 | return; |
| 921 | } | 980 | } |
| 922 | | 981 | |
| @@ -929,21 +988,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) · 6 unmodified lines |
| 929 | return; | 988 | return; |
| 930 | } | 989 | } |
| 931 | | 990 | |
| 932 | /* | 991 | vmbus_setup_channel_state(newchannel, offer); |
| 933 | * Setup state for signalling the host. | | |
| 934 | */ | | |
| 935 | newchannel->sig_event = VMBUS_EVENT_CONNECTION_ID; | | |
| 936 | | | |
| 937 | if (vmbus_proto_version != VERSION_WS2008) { | | |
| 938 | newchannel->is_dedicated_interrupt = | | |
| 939 | (offer->is_dedicated_interrupt != 0); | | |
| 940 | newchannel->sig_event = offer->connection_id; | | |
| 941 | } | | |
| 942 | | | |
| 943 | memcpy(&newchannel->offermsg, offer, | | |
| 944 | sizeof(struct vmbus_channel_offer_channel)); | | |
| 945 | newchannel->monitor_grp = (u8)offer->monitorid / 32; | | |
| 946 | newchannel->monitor_bit = (u8)offer->monitorid % 32; | | |
| 947 | | 992 | |
| 948 | vmbus_process_offer(newchannel); | 993 | vmbus_process_offer(newchannel); |
| 949 | } | 994 | } |