summaryrefslogtreecommitdiff |
diff options
author | Hannes Reinecke <hare@suse.de> | 2015-04-30 13:15:16 +0200 |
---|---|---|
committer | Hannes Reinecke <hare@suse.de> | 2015-04-30 13:15:16 +0200 |
commit | c86eb37868b984771fb99ee68d52af103c8539eb (patch) | |
tree | 8206d91983a2935a61afdc842097fe5ccf6a9741 | |
parent | 6a838b13bbb1290d46b51a4f3a4032e60b6a725c (diff) | |
parent | d4f05af2af8e36c1aefb7c52bf201a2f8bacbd87 (diff) |
Merge branch 'SLE11-SP4' of kerncvs.suse.de:/home/git/kernel-source into SLE11-SP4rpm-3.0.101-58
53 files changed, 4272 insertions, 0 deletions
diff --git a/patches.suse/msft-hv-0742-hyperv-Implement-netvsc_get_channels-ethool-op.patch b/patches.suse/msft-hv-0742-hyperv-Implement-netvsc_get_channels-ethool-op.patch new file mode 100644 index 0000000000..5b7473d510 --- /dev/null +++ b/patches.suse/msft-hv-0742-hyperv-Implement-netvsc_get_channels-ethool-op.patch @@ -0,0 +1,101 @@ +From: Andrew Schwartzmeyer <andrew@schwartzmeyer.com> +Date: Thu, 26 Feb 2015 16:27:14 -0800 +Patch-mainline: v4.1-rc1 +Subject: hyperv: Implement netvsc_get_channels() ethool op +Git-commit: 59995370dbca7636c105ddadc0447fab86ad3887 +References: fate#317533 + +This adds support for reporting the actual and maximum combined channels +count of the hv_netvsc driver via 'ethtool --show-channels'. + +This required adding 'max_chn' to 'struct netvsc_device', and assigning +it 'rsscap.num_recv_que' in 'rndis_filter_device_add'. Now we can access +the combined maximum channel count via 'struct netvsc_device' in the +ethtool callback. + +Signed-off-by: Andrew Schwartzmeyer <andrew@schwartzmeyer.com> +Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Acked-by: <ohering@suse.de> +--- + drivers/net/hyperv/hyperv_net.h | 1 + + drivers/net/hyperv/netvsc_drv.c | 14 ++++++++++++++ + drivers/net/hyperv/rndis_filter.c | 6 +++++- + 3 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h +index 384ca4f..4815843 100644 +--- a/drivers/net/hyperv/hyperv_net.h ++++ b/drivers/net/hyperv/hyperv_net.h +@@ -634,6 +634,7 @@ struct netvsc_device { + + struct vmbus_channel *chn_table[NR_CPUS]; + u32 send_table[VRSS_SEND_TAB_SIZE]; ++ u32 max_chn; + u32 num_chn; + atomic_t queue_sends[NR_CPUS]; + +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index 15d82ed..a06bd66 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -687,6 +687,19 @@ static void netvsc_get_drvinfo(struct net_device *net, + strcpy(info->fw_version, "N/A"); + } + ++static void netvsc_get_channels(struct net_device *net, ++ struct ethtool_channels *channel) ++{ ++ struct net_device_context *net_device_ctx = netdev_priv(net); ++ struct hv_device *dev = net_device_ctx->device_ctx; ++ struct netvsc_device *nvdev = hv_get_drvdata(dev); ++ ++ if (nvdev) { ++ channel->max_combined = nvdev->max_chn; ++ channel->combined_count = nvdev->num_chn; ++ } ++} ++ + static int netvsc_change_mtu(struct net_device *ndev, int mtu) + { + struct net_device_context *ndevctx = netdev_priv(ndev); +@@ -760,6 +773,7 @@ static void netvsc_poll_controller(struct net_device *net) + static const struct ethtool_ops ethtool_ops = { + .get_drvinfo = netvsc_get_drvinfo, + .get_link = ethtool_op_get_link, ++ .get_channels = netvsc_get_channels, + }; + + static const struct net_device_ops device_ops = { +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +index 7816d98..ca81de0 100644 +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1027,6 +1027,7 @@ int rndis_filter_device_add(struct hv_device *dev, + + /* Initialize the rndis device */ + net_device = hv_get_drvdata(dev); ++ net_device->max_chn = 1; + net_device->num_chn = 1; + + net_device->extension = rndis_device; +@@ -1094,6 +1095,7 @@ int rndis_filter_device_add(struct hv_device *dev, + if (ret || rsscap.num_recv_que < 2) + goto out; + ++ net_device->max_chn = rsscap.num_recv_que; + net_device->num_chn = (num_online_cpus() < rsscap.num_recv_que) ? + num_online_cpus() : rsscap.num_recv_que; + if (net_device->num_chn == 1) +@@ -1140,8 +1142,10 @@ int rndis_filter_device_add(struct hv_device *dev, + ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn); + + out: +- if (ret) ++ if (ret) { ++ net_device->max_chn = 1; + net_device->num_chn = 1; ++ } + return 0; /* return 0 because primary channel can be used alone */ + + err_dev_remv: diff --git a/patches.suse/msft-hv-0743-Drivers-hv-vmbus-prevent-cpu-offlining-on-newer-hype.patch b/patches.suse/msft-hv-0743-Drivers-hv-vmbus-prevent-cpu-offlining-on-newer-hype.patch new file mode 100644 index 0000000000..c2cb55f1c1 --- /dev/null +++ b/patches.suse/msft-hv-0743-Drivers-hv-vmbus-prevent-cpu-offlining-on-newer-hype.patch @@ -0,0 +1,96 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Feb 2015 11:25:51 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: prevent cpu offlining on newer hypervisors +Git-commit: e513229b4c386e6c9f66298c13fde92f73e6e1ac +References: fate#317533 + +When an SMP Hyper-V guest is running on top of 2012R2 Server and secondary +cpus are sent offline (with echo 0 > /sys/devices/system/cpu/cpu$cpu/online) +the system freeze is observed. This happens due to the fact that on newer +hypervisors (Win8, WS2012R2, ...) vmbus channel handlers are distributed +across all cpus (see init_vp_index() function in drivers/hv/channel_mgmt.c) +and on cpu offlining nobody reassigns them to CPU0. Prevent cpu offlining +when vmbus is loaded until the issue is fixed host-side. + +This patch also disables hibernation but it is OK as it is also broken (MCE +error is hit on resume). Suspend still works. + +Tested with WS2008R2 and WS2012R2. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/vmbus_drv.c | 36 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 36 insertions(+) + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index f518b8d7..3b18a66 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -33,6 +33,7 @@ + #include <linux/hyperv.h> + #include <linux/kernel_stat.h> + #include <linux/clockchips.h> ++#include <linux/cpu.h> + #include <asm/hyperv.h> + #include <asm/hypervisor.h> + #include <asm/mshyperv.h> +@@ -704,6 +705,39 @@ static void vmbus_isr(void) + desc->action->handler(irq, desc->action->dev_id); + } + ++#ifdef CONFIG_HOTPLUG_CPU ++static int hyperv_cpu_disable(void) ++{ ++ return -ENOSYS; ++} ++ ++static void hv_cpu_hotplug_quirk(bool vmbus_loaded) ++{ ++ static void *previous_cpu_disable; ++ ++ /* ++ * Offlining a CPU when running on newer hypervisors (WS2012R2, Win8, ++ * ...) is not supported at this moment as channel interrupts are ++ * distributed across all of them. ++ */ ++ ++ if ((vmbus_proto_version == VERSION_WS2008) || ++ (vmbus_proto_version == VERSION_WIN7)) ++ return; ++ ++ if (vmbus_loaded) { ++ previous_cpu_disable = smp_ops.cpu_disable; ++ smp_ops.cpu_disable = hyperv_cpu_disable; ++ pr_notice("CPU offlining is not supported by hypervisor\n"); ++ } else if (previous_cpu_disable) ++ smp_ops.cpu_disable = previous_cpu_disable; ++} ++#else ++static void hv_cpu_hotplug_quirk(bool vmbus_loaded) ++{ ++} ++#endif ++ + /* + * vmbus_bus_init -Main vmbus driver initialization routine. + * +@@ -744,6 +778,7 @@ static int vmbus_bus_init(int irq) + if (ret) + goto err_alloc; + ++ hv_cpu_hotplug_quirk(true); + vmbus_request_offers(); + + return 0; +@@ -997,6 +1032,7 @@ static void __exit vmbus_exit(void) + bus_unregister(&hv_bus); + hv_cleanup(); + acpi_bus_unregister_driver(&vmbus_acpi_driver); ++ hv_cpu_hotplug_quirk(false); + } + + diff --git a/patches.suse/msft-hv-0744-Drivers-hv-vmbus-rename-channel-work-queues.patch b/patches.suse/msft-hv-0744-Drivers-hv-vmbus-rename-channel-work-queues.patch new file mode 100644 index 0000000000..c276610076 --- /dev/null +++ b/patches.suse/msft-hv-0744-Drivers-hv-vmbus-rename-channel-work-queues.patch @@ -0,0 +1,81 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Feb 2015 11:25:52 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: rename channel work queues +Git-commit: bc63b6f634d91a0b2a7f3ba4f266e55fec369de3 +References: fate#317533 + +All channel work queues are named 'hv_vmbus_ctl', this makes them +indistinguishable in ps output and makes it hard to link to the corresponding +vmbus device. Rename them to hv_vmbus_ctl/N and make vmbus device names match, +e.g. now vmbus_1 device is served by hv_vmbus_ctl/1 work queue. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 5 ++++- + drivers/hv/vmbus_drv.c | 6 ++---- + include/linux/hyperv.h | 3 +++ + 3 files changed, 9 insertions(+), 5 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 3736f71..ba4b25f 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -139,19 +139,22 @@ EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); + */ + static struct vmbus_channel *alloc_channel(void) + { ++ static atomic_t chan_num = ATOMIC_INIT(0); + struct vmbus_channel *channel; + + channel = kzalloc(sizeof(*channel), GFP_ATOMIC); + if (!channel) + return NULL; + ++ channel->id = atomic_inc_return(&chan_num); + spin_lock_init(&channel->inbound_lock); + spin_lock_init(&channel->lock); + + INIT_LIST_HEAD(&channel->sc_list); + INIT_LIST_HEAD(&channel->percpu_list); + +- channel->controlwq = create_workqueue("hv_vmbus_ctl"); ++ channel->controlwq = alloc_workqueue("hv_vmbus_ctl/%d", WQ_MEM_RECLAIM, ++ 1, channel->id); + if (!channel->controlwq) { + kfree(channel); + return NULL; +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 3b18a66..e334ccc 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -875,10 +875,8 @@ int vmbus_device_register(struct hv_device *child_device_obj) + { + int ret = 0; + +- static atomic_t device_num = ATOMIC_INIT(0); +- +- dev_set_name(&child_device_obj->device, "vmbus_0_%d", +- atomic_inc_return(&device_num)); ++ dev_set_name(&child_device_obj->device, "vmbus_%d", ++ child_device_obj->channel->id); + + child_device_obj->device.bus = &hv_bus; + child_device_obj->device.parent = &hv_acpi_dev->dev; +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 5a2ba67..26a32b7 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -646,6 +646,9 @@ struct hv_input_signal_event_buffer { + }; + + struct vmbus_channel { ++ /* Unique channel id */ ++ int id; ++ + struct list_head listentry; + + struct hv_device *device_obj; diff --git a/patches.suse/msft-hv-0745-Drivers-hv-vmbus-avoid-double-kfree-for-device_obj.patch b/patches.suse/msft-hv-0745-Drivers-hv-vmbus-avoid-double-kfree-for-device_obj.patch new file mode 100644 index 0000000000..fb3d8b0e53 --- /dev/null +++ b/patches.suse/msft-hv-0745-Drivers-hv-vmbus-avoid-double-kfree-for-device_obj.patch @@ -0,0 +1,48 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Feb 2015 11:25:53 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: avoid double kfree for device_obj +Git-commit: adcde069a85cb6674bdcf5f49f434d18b2db6e58 +References: fate#317533 + +On driver shutdown device_obj is being freed twice: +1) In vmbus_free_channels() +2) vmbus_device_release() (which is being triggered by device_unregister() in + vmbus_device_unregister(). +This double kfree leads to the following sporadic crash on driver unload: + +[ 23.469876] general protection fault: 0000 [#1] SMP +[ 23.470036] Modules linked in: hv_vmbus(-) +[ 23.470036] CPU: 2 PID: 213 Comm: rmmod Not tainted 3.19.0-rc5_bug923184+ #488 +[ 23.470036] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS 090006 05/23/2012 +[ 23.470036] task: ffff880036ef1cb0 ti: ffff880036ce8000 task.ti: ffff880036ce8000 +[ 23.470036] RIP: 0010:[<ffffffff811d2e1b>] [<ffffffff811d2e1b>] __kmalloc_node_track_caller+0xdb/0x1e0 +[ 23.470036] RSP: 0018:ffff880036cebcc8 EFLAGS: 00010246 +... + +When this crash does not happen on driver unload the similar one is expected if +we try to load hv_vmbus again. + +Remove kfree from vmbus_free_channels() as freeing it from +vmbus_device_release() seems right. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index ba4b25f..36bacc7 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -262,7 +262,6 @@ void vmbus_free_channels(void) + + list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { + vmbus_device_unregister(channel->device_obj); +- kfree(channel->device_obj); + free_channel(channel); + } + } diff --git a/patches.suse/msft-hv-0746-Drivers-hv-vmbus-teardown-hv_vmbus_con-workqueue-and.patch b/patches.suse/msft-hv-0746-Drivers-hv-vmbus-teardown-hv_vmbus_con-workqueue-and.patch new file mode 100644 index 0000000000..1247eded21 --- /dev/null +++ b/patches.suse/msft-hv-0746-Drivers-hv-vmbus-teardown-hv_vmbus_con-workqueue-and.patch @@ -0,0 +1,125 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Feb 2015 11:25:54 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: teardown hv_vmbus_con workqueue and vmbus_connection pages on shutdown +Git-commit: 09a196288ec4617a920e051af6651ce03968c8b9 +References: fate#317533 + +We need to destroy hv_vmbus_con on module shutdown, otherwise the following +crash is sometimes observed: + +[ 76.569845] hv_vmbus: Hyper-V Host Build:9600-6.3-17-0.17039; Vmbus version:3.0 +[ 82.598859] BUG: unable to handle kernel paging request at ffffffffa0003480 +[ 82.599287] IP: [<ffffffffa0003480>] 0xffffffffa0003480 +[ 82.599287] PGD 1f34067 PUD 1f35063 PMD 3f72d067 PTE 0 +[ 82.599287] Oops: 0010 [#1] SMP +[ 82.599287] Modules linked in: [last unloaded: hv_vmbus] +[ 82.599287] CPU: 0 PID: 26 Comm: kworker/0:1 Not tainted 3.19.0-rc5_bug923184+ #488 +[ 82.599287] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v1.0 11/26/2012 +[ 82.599287] Workqueue: hv_vmbus_con 0xffffffffa0003480 +[ 82.599287] task: ffff88007b6ddfa0 ti: ffff88007f8f8000 task.ti: ffff88007f8f8000 +[ 82.599287] RIP: 0010:[<ffffffffa0003480>] [<ffffffffa0003480>] 0xffffffffa0003480 +[ 82.599287] RSP: 0018:ffff88007f8fbe00 EFLAGS: 00010202 +... + +To avoid memory leaks we need to free monitor_pages and int_page for +vmbus_connection. Implement vmbus_disconnect() function by separating cleanup +path from vmbus_connect(). + +As we use hv_vmbus_con to release channels (see free_channel() in channel_mgmt.c) +we need to make sure the work was done before we remove the queue, do that with +drain_workqueue(). We also need to avoid handling messages which can (potentially) +create new channels, so set vmbus_connection.conn_state = DISCONNECTED at the very +beginning of vmbus_exit() and check for that in vmbus_onmessage_work(). + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/connection.c | 17 ++++++++++++----- + drivers/hv/hyperv_vmbus.h | 1 + + drivers/hv/vmbus_drv.c | 6 ++++++ + 3 files changed, 19 insertions(+), 5 deletions(-) + +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index a63a795..c4acd1c 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -216,10 +216,21 @@ int vmbus_connect(void) + + cleanup: + pr_err("Unable to connect to host\n"); ++ + vmbus_connection.conn_state = DISCONNECTED; ++ vmbus_disconnect(); ++ ++ kfree(msginfo); ++ ++ return ret; ++} + +- if (vmbus_connection.work_queue) ++void vmbus_disconnect(void) ++{ ++ if (vmbus_connection.work_queue) { ++ drain_workqueue(vmbus_connection.work_queue); + destroy_workqueue(vmbus_connection.work_queue); ++ } + + if (vmbus_connection.int_page) { + free_pages((unsigned long)vmbus_connection.int_page, 0); +@@ -230,10 +241,6 @@ cleanup: + free_pages((unsigned long)vmbus_connection.monitor_pages[1], 0); + vmbus_connection.monitor_pages[0] = NULL; + vmbus_connection.monitor_pages[1] = NULL; +- +- kfree(msginfo); +- +- return ret; + } + + /* +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index 44b1c94..6cf2de9 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -692,6 +692,7 @@ void vmbus_free_channels(void); + /* Connection interface */ + + int vmbus_connect(void); ++void vmbus_disconnect(void); + + int vmbus_post_msg(void *buffer, size_t buflen); + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index e334ccc..76db97d 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -574,6 +574,10 @@ static void vmbus_onmessage_work(struct work_struct *work) + { + struct onmessage_work_context *ctx; + ++ /* Do not process messages if we're in DISCONNECTED state */ ++ if (vmbus_connection.conn_state == DISCONNECTED) ++ return; ++ + ctx = container_of(work, struct onmessage_work_context, + work); + vmbus_onmessage(&ctx->msg); +@@ -897,13 +901,14 @@ cleanup: + + static void __exit vmbus_exit(void) + { +- ++ vmbus_connection.conn_state = DISCONNECTED; + free_irq(irq, hv_acpi_dev); + vmbus_free_channels(); + bus_unregister(&hv_bus); + hv_cleanup(); + acpi_bus_unregister_driver(&vmbus_acpi_driver); + hv_cpu_hotplug_quirk(false); ++ vmbus_disconnect(); + } + + diff --git a/patches.suse/msft-hv-0747-drivers-hv-vmbus-Teardown-synthetic-interrupt-contro.patch b/patches.suse/msft-hv-0747-drivers-hv-vmbus-Teardown-synthetic-interrupt-contro.patch new file mode 100644 index 0000000000..cdad0e006c --- /dev/null +++ b/patches.suse/msft-hv-0747-drivers-hv-vmbus-Teardown-synthetic-interrupt-contro.patch @@ -0,0 +1,93 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Feb 2015 11:25:55 -0800 +Patch-mainline: v4.1-rc1 +Subject: drivers: hv: vmbus: Teardown synthetic interrupt controllers on module unload +Git-commit: e72e7ac583ee8adddbc668cdefde7d7d3021be79 +References: fate#317533 + +SynIC has to be switched off when we unload the module, otherwise registered +memory pages can get corrupted after (as Hyper-V host still writes there) and +we see the following crashes for random processes: + +[ 89.116774] BUG: Bad page map in process sh pte:4989c716 pmd:36f81067 +[ 89.159454] addr:0000000000437000 vm_flags:00000875 anon_vma: (null) mapping:ffff88007bba55a0 index:37 +[ 89.226146] vma->vm_ops->fault: filemap_fault+0x0/0x410 +[ 89.257776] vma->vm_file->f_op->mmap: generic_file_mmap+0x0/0x60 +[ 89.297570] CPU: 0 PID: 215 Comm: sh Tainted: G B 3.19.0-rc5_bug923184+ #488 +[ 89.353738] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS 090006 05/23/2012 +[ 89.409138] 0000000000000000 000000004e083d7b ffff880036e9fa18 ffffffff81a68d31 +[ 89.468724] 0000000000000000 0000000000437000 ffff880036e9fa68 ffffffff811a1e3a +[ 89.519233] 000000004989c716 0000000000000037 ffffea0001edc340 0000000000437000 +[ 89.575751] Call Trace: +[ 89.591060] [<ffffffff81a68d31>] dump_stack+0x45/0x57 +[ 89.625164] [<ffffffff811a1e3a>] print_bad_pte+0x1aa/0x250 +[ 89.667234] [<ffffffff811a2c95>] vm_normal_page+0x55/0xa0 +[ 89.703818] [<ffffffff811a3105>] unmap_page_range+0x425/0x8a0 +[ 89.737982] [<ffffffff811a3601>] unmap_single_vma+0x81/0xf0 +[ 89.780385] [<ffffffff81184320>] ? lru_deactivate_fn+0x190/0x190 +[ 89.820130] [<ffffffff811a4131>] unmap_vmas+0x51/0xa0 +[ 89.860168] [<ffffffff811ad12c>] exit_mmap+0xac/0x1a0 +[ 89.890588] [<ffffffff810763c3>] mmput+0x63/0x100 +[ 89.919205] [<ffffffff811eba48>] flush_old_exec+0x3f8/0x8b0 +[ 89.962135] [<ffffffff8123b5bb>] load_elf_binary+0x32b/0x1260 +[ 89.998581] [<ffffffff811a14f2>] ? get_user_pages+0x52/0x60 + +hv_synic_cleanup() function exists but noone calls it now. Do the following: +- call hv_synic_cleanup() on each cpu from vmbus_exit(); +- write global disable bit through MSR; +- use hv_synic_free_cpu() to avoid memory leask and code duplication. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv.c | 9 +++++++-- + drivers/hv/vmbus_drv.c | 4 ++++ + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c +index 50e51a5..39531dc 100644 +--- a/drivers/hv/hv.c ++++ b/drivers/hv/hv.c +@@ -477,6 +477,7 @@ void hv_synic_cleanup(void *arg) + union hv_synic_sint shared_sint; + union hv_synic_simp simp; + union hv_synic_siefp siefp; ++ union hv_synic_scontrol sctrl; + int cpu = smp_processor_id(); + + if (!hv_context.synic_initialized) +@@ -502,6 +503,10 @@ void hv_synic_cleanup(void *arg) + + wrmsrl(HV_X64_MSR_SIEFP, siefp.as_uint64); + +- free_page((unsigned long)hv_context.synic_message_page[cpu]); +- free_page((unsigned long)hv_context.synic_event_page[cpu]); ++ /* Disable the global synic bit */ ++ rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); ++ sctrl.enable = 0; ++ wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64); ++ ++ hv_synic_free_cpu(cpu); + } +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 76db97d..d8233d4 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -1029,11 +1029,15 @@ cleanup: + + static void __exit vmbus_exit(void) + { ++ int cpu; ++ + vmbus_connection.conn_state = DISCONNECTED; + free_irq(irq, hv_acpi_dev); + vmbus_free_channels(); + bus_unregister(&hv_bus); + hv_cleanup(); ++ for_each_online_cpu(cpu) ++ smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1); + acpi_bus_unregister_driver(&vmbus_acpi_driver); + hv_cpu_hotplug_quirk(false); + vmbus_disconnect(); diff --git a/patches.suse/msft-hv-0748-Drivers-hv-vmbus-Teardown-clockevent-devices-on-modu.patch b/patches.suse/msft-hv-0748-Drivers-hv-vmbus-Teardown-clockevent-devices-on-modu.patch new file mode 100644 index 0000000000..f0fd58ed0f --- /dev/null +++ b/patches.suse/msft-hv-0748-Drivers-hv-vmbus-Teardown-clockevent-devices-on-modu.patch @@ -0,0 +1,106 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Feb 2015 11:25:57 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Teardown clockevent devices on module unload +Git-commit: e086748c655ab99bac91b87d1bb59d9cc45867b9 +References: fate#317533 + +Newly introduced clockevent devices made it impossible to unload hv_vmbus +module as clockevents_config_and_register() takes additional reverence to +the module. To make it possible again we do the following: +- avoid setting dev->owner for clockevent devices; +- implement hv_synic_clockevents_cleanup() doing clockevents_unbind_device(); +- call it from vmbus_exit(). + +In theory hv_synic_clockevents_cleanup() can be merged with hv_synic_cleanup(), +however, we call hv_synic_cleanup() from smp_call_function_single() and this +doesn't work for clockevents_unbind_device() as it does such call on its own. I +opted for a separate function. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv.c | 25 ++++++++++++++++++++++++- + drivers/hv/hyperv_vmbus.h | 2 ++ + drivers/hv/vmbus_drv.c | 1 + + 3 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c +index 39531dc..d3943bc 100644 +--- a/drivers/hv/hv.c ++++ b/drivers/hv/hv.c +@@ -312,7 +312,11 @@ static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu) + dev->features = CLOCK_EVT_FEAT_ONESHOT; + dev->cpumask = cpumask_of(cpu); + dev->rating = 1000; +- /* dev->owner = THIS_MODULE; */ ++ /* ++ * Avoid settint dev->owner = THIS_MODULE deliberately as doing so will ++ * result in clockevents_config_and_register() taking additional ++ * references to the hv_vmbus module making it impossible to unload. ++ */ + + dev->set_mode = hv_ce_setmode; + dev->set_next_event = hv_ce_set_next_event; +@@ -470,6 +474,22 @@ void hv_synic_init(void *arg) + } + + /* ++ * hv_synic_clockevents_cleanup - Cleanup clockevent devices ++ */ ++void hv_synic_clockevents_cleanup(void) ++{ ++#if 0 ++ int cpu; ++ ++ if (!(ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)) ++ return; ++ ++ for_each_online_cpu(cpu) ++ clockevents_unbind_device(hv_context.clk_evt[cpu], cpu); ++#endif ++} ++ ++/* + * hv_synic_cleanup - Cleanup routine for hv_synic_init(). + */ + void hv_synic_cleanup(void *arg) +@@ -483,6 +501,11 @@ void hv_synic_cleanup(void *arg) + if (!hv_context.synic_initialized) + return; + ++ /* Turn off clockevent device */ ++ if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE) ++ hv_ce_setmode(CLOCK_EVT_MODE_SHUTDOWN, ++ hv_context.clk_evt[cpu]); ++ + rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); + + shared_sint.masked = 1; +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index 6cf2de9..b055e53 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -572,6 +572,8 @@ extern void hv_synic_init(void *irqarg); + + extern void hv_synic_cleanup(void *arg); + ++extern void hv_synic_clockevents_cleanup(void); ++ + /* + * Host version information. + */ +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index d8233d4..6d99aa5 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -1032,6 +1032,7 @@ static void __exit vmbus_exit(void) + int cpu; + + vmbus_connection.conn_state = DISCONNECTED; ++ hv_synic_clockevents_cleanup(); + free_irq(irq, hv_acpi_dev); + vmbus_free_channels(); + bus_unregister(&hv_bus); diff --git a/patches.suse/msft-hv-0749-hv-hv_util-move-vmbus_open-to-a-later-place.patch b/patches.suse/msft-hv-0749-hv-hv_util-move-vmbus_open-to-a-later-place.patch new file mode 100644 index 0000000000..06676030f1 --- /dev/null +++ b/patches.suse/msft-hv-0749-hv-hv_util-move-vmbus_open-to-a-later-place.patch @@ -0,0 +1,53 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Fri, 27 Feb 2015 11:25:58 -0800 +Patch-mainline: v4.1-rc1 +Subject: hv: hv_util: move vmbus_open() to a later place +Git-commit: 1896566372579939eb86414ea3d664f18d5e909c +References: fate#317533 + +Before the line vmbus_open() returns, srv->util_cb can be already running +and the variables, like util_fw_version, are needed by the srv->util_cb. + +So we have to make sure the variables are initialized before the vmbus_open(). + +CC: "K. Y. Srinivasan" <kys@microsoft.com> +Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Reviewed-by: Jason Wang <jasowang@redhat.com> +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_util.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c +index 3b9c9ef..c5be773 100644 +--- a/drivers/hv/hv_util.c ++++ b/drivers/hv/hv_util.c +@@ -340,12 +340,8 @@ static int util_probe(struct hv_device *dev, + + set_channel_read_state(dev->channel, false); + +- ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0, +- srv->util_cb, dev->channel); +- if (ret) +- goto error; +- + hv_set_drvdata(dev, srv); ++ + /* + * Based on the host; initialize the framework and + * service version numbers we will negotiate. +@@ -365,6 +361,11 @@ static int util_probe(struct hv_device *dev, + hb_srv_version = HB_VERSION; + } + ++ ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0, ++ srv->util_cb, dev->channel); ++ if (ret) ++ goto error; ++ + return 0; + + error: diff --git a/patches.suse/msft-hv-0750-hv-vmbus_post_msg-retry-the-hypercall-on-some-transi.patch b/patches.suse/msft-hv-0750-hv-vmbus_post_msg-retry-the-hypercall-on-some-transi.patch new file mode 100644 index 0000000000..d4211e3ab3 --- /dev/null +++ b/patches.suse/msft-hv-0750-hv-vmbus_post_msg-retry-the-hypercall-on-some-transi.patch @@ -0,0 +1,73 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Fri, 27 Feb 2015 11:25:59 -0800 +Patch-mainline: v4.1-rc1 +Subject: hv: vmbus_post_msg: retry the hypercall on some transient errors +Git-commit: 89f9f6796d41e10e224b0cb0027ddd78cb881f65 +References: fate#317533 + +I got HV_STATUS_INVALID_CONNECTION_ID on Hyper-V 2008 R2 when keeping running +"rmmod hv_netvsc; modprobe hv_netvsc; rmmod hv_utils; modprobe hv_utils" +in a Linux guest. Looks the host has some kind of throttling mechanism if +some kinds of hypercalls are sent too frequently. +Without the patch, the driver can occasionally fail to load. + +Also let's retry HV_STATUS_INSUFFICIENT_MEMORY, though we didn't get it +before. + +Removed 'case -ENOMEM', since the hypervisor doesn't return this. + +CC: "K. Y. Srinivasan" <kys@microsoft.com> +Reviewed-by: Jason Wang <jasowang@redhat.com> +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + arch/x86/include/asm/hyperv.h | 2 ++ + drivers/hv/connection.c | 11 +++++++++-- + 2 files changed, 11 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/include/asm/hyperv.h b/arch/x86/include/asm/hyperv.h +index 90c458e..ce6068d 100644 +--- a/arch/x86/include/asm/hyperv.h ++++ b/arch/x86/include/asm/hyperv.h +@@ -225,6 +225,8 @@ + #define HV_STATUS_INVALID_HYPERCALL_CODE 2 + #define HV_STATUS_INVALID_HYPERCALL_INPUT 3 + #define HV_STATUS_INVALID_ALIGNMENT 4 ++#define HV_STATUS_INSUFFICIENT_MEMORY 11 ++#define HV_STATUS_INVALID_CONNECTION_ID 18 + #define HV_STATUS_INSUFFICIENT_BUFFERS 19 + + #endif +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index c4acd1c..af2388f 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -440,9 +440,16 @@ int vmbus_post_msg(void *buffer, size_t buflen) + ret = hv_post_message(conn_id, 1, buffer, buflen); + + switch (ret) { ++ case HV_STATUS_INVALID_CONNECTION_ID: ++ /* ++ * We could get this if we send messages too ++ * frequently. ++ */ ++ ret = -EAGAIN; ++ break; ++ case HV_STATUS_INSUFFICIENT_MEMORY: + case HV_STATUS_INSUFFICIENT_BUFFERS: + ret = -ENOMEM; +- case -ENOMEM: + break; + case HV_STATUS_SUCCESS: + return ret; +@@ -452,7 +459,7 @@ int vmbus_post_msg(void *buffer, size_t buflen) + } + + retries++; +- msleep(100); ++ msleep(1000); + } + return ret; + } diff --git a/patches.suse/msft-hv-0751-hv-vmbus_open-reset-the-channel-state-on-ENOMEM.patch b/patches.suse/msft-hv-0751-hv-vmbus_open-reset-the-channel-state-on-ENOMEM.patch new file mode 100644 index 0000000000..33f172c0f4 --- /dev/null +++ b/patches.suse/msft-hv-0751-hv-vmbus_open-reset-the-channel-state-on-ENOMEM.patch @@ -0,0 +1,47 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Fri, 27 Feb 2015 11:26:00 -0800 +Patch-mainline: v4.1-rc1 +Subject: hv: vmbus_open(): reset the channel state on ENOMEM +Git-commit: ac0d12b7cee73b4b4b769ea58c62ec7042c6be13 +References: fate#317533 + +Without this patch, the state is put to CHANNEL_OPENING_STATE, and when +the driver is loaded next time, vmbus_open() will fail immediately due to +newchannel->state != CHANNEL_OPEN_STATE. + +CC: "K. Y. Srinivasan" <kys@microsoft.com> +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Reviewed-by: Jason Wang <jasowang@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index 2978f5e..26dcf26 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -89,9 +89,10 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + out = (void *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, + get_order(send_ringbuffer_size + recv_ringbuffer_size)); + +- if (!out) +- return -ENOMEM; +- ++ if (!out) { ++ err = -ENOMEM; ++ goto error0; ++ } + + in = (void *)((unsigned long)out + send_ringbuffer_size); + +@@ -199,6 +200,7 @@ error0: + free_pages((unsigned long)out, + get_order(send_ringbuffer_size + recv_ringbuffer_size)); + kfree(open_info); ++ newchannel->state = CHANNEL_OPEN_STATE; + return err; + } + EXPORT_SYMBOL_GPL(vmbus_open); diff --git a/patches.suse/msft-hv-0752-hv-channel-match-var-type-to-return-type-of-wait_for.patch b/patches.suse/msft-hv-0752-hv-channel-match-var-type-to-return-type-of-wait_for.patch new file mode 100644 index 0000000000..06f740acda --- /dev/null +++ b/patches.suse/msft-hv-0752-hv-channel-match-var-type-to-return-type-of-wait_for.patch @@ -0,0 +1,32 @@ +From: Nicholas Mc Guire <der.herr@hofr.at> +Date: Fri, 27 Feb 2015 11:26:01 -0800 +Patch-mainline: v4.1-rc1 +Subject: hv: channel: match var type to return type of wait_for_completion +Git-commit: 08a9513f7417d6dff9a1ab0c163900f503ff84eb +References: fate#317533 + +return type of wait_for_completion_timeout is unsigned long not int, this +patch changes the type of t from int to unsigned long. + +Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index 26dcf26..f687995 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -71,7 +71,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + struct vmbus_channel_msginfo *open_info = NULL; + void *in, *out; + unsigned long flags; +- int ret, t, err = 0; ++ int ret, err = 0; ++ unsigned long t; + + spin_lock_irqsave(&newchannel->lock, flags); + if (newchannel->state == CHANNEL_OPEN_STATE) { diff --git a/patches.suse/msft-hv-0753-hv-channel_mgmt-match-var-type-to-return-type-of-wai.patch b/patches.suse/msft-hv-0753-hv-channel_mgmt-match-var-type-to-return-type-of-wai.patch new file mode 100644 index 0000000000..a773e89e6b --- /dev/null +++ b/patches.suse/msft-hv-0753-hv-channel_mgmt-match-var-type-to-return-type-of-wai.patch @@ -0,0 +1,32 @@ +From: Nicholas Mc Guire <der.herr@hofr.at> +Date: Fri, 27 Feb 2015 11:26:02 -0800 +Patch-mainline: v4.1-rc1 +Subject: hv: channel_mgmt: match var type to return type of wait_for_completion +Git-commit: 51e5181d20086c0b26e871deffeff3ff47cf5c4b +References: fate#317533 + +return type of wait_for_completion_timeout is unsigned long not int, this +patch changes the type of t from int to unsigned long. + +Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 36bacc7..6be93f0 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -789,7 +789,8 @@ int vmbus_request_offers(void) + { + struct vmbus_channel_message_header *msg; + struct vmbus_channel_msginfo *msginfo; +- int ret, t; ++ int ret; ++ unsigned long t; + + msginfo = kmalloc(sizeof(*msginfo) + + sizeof(struct vmbus_channel_message_header), diff --git a/patches.suse/msft-hv-0754-hv-hv_balloon-match-var-type-to-return-type-of-wait_.patch b/patches.suse/msft-hv-0754-hv-hv_balloon-match-var-type-to-return-type-of-wait_.patch new file mode 100644 index 0000000000..dd414759df --- /dev/null +++ b/patches.suse/msft-hv-0754-hv-hv_balloon-match-var-type-to-return-type-of-wait_.patch @@ -0,0 +1,32 @@ +From: Nicholas Mc Guire <der.herr@hofr.at> +Date: Fri, 27 Feb 2015 11:26:03 -0800 +Patch-mainline: v4.1-rc1 +Subject: hv: hv_balloon: match var type to return type of wait_for_completion +Git-commit: b057b3ad16e1c6e21e234cd7f5c61c525da97f17 +References: fate#317533 + +return type of wait_for_completion_timeout is unsigned long not int, this +patch changes the type of t from int to unsigned long. + +Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index ff16938..965c37a 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1414,7 +1414,8 @@ static void balloon_onchannelcallback(void *context) + static int balloon_probe(struct hv_device *dev, + const struct hv_vmbus_device_id *dev_id) + { +- int ret, t; ++ int ret; ++ unsigned long t; + struct dm_version_request version_req; + struct dm_capabilities cap_msg; + diff --git a/patches.suse/msft-hv-0755-Drivers-hv-vmbus-Fix-a-bug-in-the-error-path-in-vmbu.patch b/patches.suse/msft-hv-0755-Drivers-hv-vmbus-Fix-a-bug-in-the-error-path-in-vmbu.patch new file mode 100644 index 0000000000..26312fab8b --- /dev/null +++ b/patches.suse/msft-hv-0755-Drivers-hv-vmbus-Fix-a-bug-in-the-error-path-in-vmbu.patch @@ -0,0 +1,50 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Fri, 27 Feb 2015 11:26:04 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Fix a bug in the error path in vmbus_open() +Git-commit: 40384e4bbeb9f2651fe9bffc0062d9f31ef625bf +References: fate#317533 + +Correctly rollback state if the failure occurs after we have handed over +the ownership of the buffer to the host. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index f687995..bf0cf8f 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -137,7 +137,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + GFP_KERNEL); + if (!open_info) { + err = -ENOMEM; +- goto error0; ++ goto error_gpadl; + } + + init_completion(&open_info->waitevent); +@@ -153,7 +153,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, + + if (userdatalen > MAX_USER_DEFINED_BYTES) { + err = -EINVAL; +- goto error0; ++ goto error_gpadl; + } + + if (userdatalen) +@@ -197,6 +197,9 @@ error1: + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + ++error_gpadl: ++ vmbus_teardown_gpadl(newchannel, newchannel->ringbuffer_gpadlhandle); ++ + error0: + free_pages((unsigned long)out, + get_order(send_ringbuffer_size + recv_ringbuffer_size)); diff --git a/patches.suse/msft-hv-0756-Drivers-hv-vmbus-Add-support-for-the-NetworkDirect-G.patch b/patches.suse/msft-hv-0756-Drivers-hv-vmbus-Add-support-for-the-NetworkDirect-G.patch new file mode 100644 index 0000000000..fba5595d14 --- /dev/null +++ b/patches.suse/msft-hv-0756-Drivers-hv-vmbus-Add-support-for-the-NetworkDirect-G.patch @@ -0,0 +1,52 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Fri, 27 Feb 2015 11:26:05 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Add support for the NetworkDirect GUID +Git-commit: 04653a009a63d6a91c60a5449ea97e3ed5e1dc29 +References: fate#317533 + +NetworkDirect is a service that supports guest RDMA. +Define the GUID for this service. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 2 ++ + include/linux/hyperv.h | 10 ++++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 6be93f0..0ba6b5c 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -413,6 +413,8 @@ static const struct hv_vmbus_device_id hp_devs[] = { + { HV_SCSI_GUID, }, + /* Network */ + { HV_NIC_GUID, }, ++ /* NetworkDirect Guest RDMA */ ++ { HV_ND_GUID, }, + }; + + +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 26a32b7..7d976ac 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1110,6 +1110,16 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver); + } + + /* ++ * NetworkDirect. This is the guest RDMA service. ++ * {8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501} ++ */ ++#define HV_ND_GUID \ ++ .guid = { \ ++ 0x3d, 0xaf, 0x2e, 0x8c, 0xa7, 0x32, 0x09, 0x4b, \ ++ 0xab, 0x99, 0xbd, 0x1f, 0x1c, 0x86, 0xb5, 0x01 \ ++ } ++ ++/* + * Common header for Hyper-V ICs + */ + diff --git a/patches.suse/msft-hv-0757-Drivers-hv-vmbus-Properly-handle-child-device-remove.patch b/patches.suse/msft-hv-0757-Drivers-hv-vmbus-Properly-handle-child-device-remove.patch new file mode 100644 index 0000000000..a8f74eb0ae --- /dev/null +++ b/patches.suse/msft-hv-0757-Drivers-hv-vmbus-Properly-handle-child-device-remove.patch @@ -0,0 +1,45 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:18:16 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Properly handle child device remove +Git-commit: d15a0301c4157884d1a48a5d76b9ac3e36d71242 +References: fate#317533 + +Handle the case when the device may be removed when the device has no driver +attached to it. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/vmbus_drv.c | 15 +++++++++------ + 1 file changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 6d99aa5..a12666d 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -508,14 +508,17 @@ static int vmbus_probe(struct device *child_device) + */ + static int vmbus_remove(struct device *child_device) + { +- struct hv_driver *drv = drv_to_hv_drv(child_device->driver); ++ struct hv_driver *drv; + struct hv_device *dev = device_to_hv_device(child_device); + +- if (drv->remove) +- drv->remove(dev); +- else +- pr_err("remove not set for driver %s\n", +- dev_name(child_device)); ++ if (child_device->driver) { ++ drv = drv_to_hv_drv(child_device->driver); ++ if (drv->remove) ++ drv->remove(dev); ++ else ++ pr_err("remove not set for driver %s\n", ++ dev_name(child_device)); ++ } + + return 0; + } diff --git a/patches.suse/msft-hv-0758-Drivers-hv-vmbus-Introduce-a-function-to-remove-a-re.patch b/patches.suse/msft-hv-0758-Drivers-hv-vmbus-Introduce-a-function-to-remove-a-re.patch new file mode 100644 index 0000000000..e0027382dd --- /dev/null +++ b/patches.suse/msft-hv-0758-Drivers-hv-vmbus-Introduce-a-function-to-remove-a-re.patch @@ -0,0 +1,157 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:18:17 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Introduce a function to remove a rescinded offer +Git-commit: ed6cfcc5fdf2ebca320b6f74c836e555e18216e1 +References: fate#317533 + +In response to a rescind message, we need to remove the channel and the +corresponding device. Cleanup this code path by factoring out the code +to remove a channel. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 9 +++++++++ + drivers/hv/channel_mgmt.c | 49 +++++++++++++++++++++++++++++------------------ + drivers/hv/vmbus_drv.c | 11 ++++++++++- + include/linux/hyperv.h | 1 + + 4 files changed, 50 insertions(+), 20 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index bf0cf8f..9b79aca 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -501,6 +501,15 @@ static int vmbus_close_internal(struct vmbus_channel *channel) + put_cpu(); + } + ++ /* ++ * If the channel has been rescinded; process device removal. ++ */ ++ if (channel->rescind) { ++ hv_process_channel_removal(channel, ++ channel->offermsg.child_relid); ++ return 0; ++ } ++ + /* Send a closing message */ + + msg = &channel->close_msg.msg; +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 0ba6b5c..b933891 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -207,33 +207,21 @@ static void percpu_channel_deq(void *arg) + list_del(&channel->percpu_list); + } + +-/* +- * vmbus_process_rescind_offer - +- * Rescind the offer by initiating a device removal +- */ +-static void vmbus_process_rescind_offer(struct work_struct *work) ++ ++void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) + { +- struct vmbus_channel *channel = container_of(work, +- struct vmbus_channel, +- work); ++ struct vmbus_channel_relid_released msg; + unsigned long flags; + struct vmbus_channel *primary_channel; +- struct vmbus_channel_relid_released msg; +- struct device *dev; +- +- if (channel->device_obj) { +- dev = get_device(&channel->device_obj->device); +- if (dev) { +- vmbus_device_unregister(channel->device_obj); +- put_device(dev); +- } +- } + + memset(&msg, 0, sizeof(struct vmbus_channel_relid_released)); +- msg.child_relid = channel->offermsg.child_relid; ++ msg.child_relid = relid; + msg.header.msgtype = CHANNELMSG_RELID_RELEASED; + vmbus_post_msg(&msg, sizeof(struct vmbus_channel_relid_released)); + ++ if (channel == NULL) ++ return; ++ + if (channel->target_cpu != get_cpu()) { + put_cpu(); + smp_call_function_single(channel->target_cpu, +@@ -256,6 +244,29 @@ static void vmbus_process_rescind_offer(struct work_struct *work) + free_channel(channel); + } + ++/* ++ * vmbus_process_rescind_offer - ++ * Rescind the offer by initiating a device removal ++ */ ++static void vmbus_process_rescind_offer(struct work_struct *work) ++{ ++ struct vmbus_channel *channel = container_of(work, ++ struct vmbus_channel, ++ work); ++ struct device *dev; ++ ++ if (channel->device_obj) { ++ dev = get_device(&channel->device_obj->device); ++ if (dev) { ++ vmbus_device_unregister(channel->device_obj); ++ put_device(dev); ++ } ++ } else { ++ hv_process_channel_removal(channel, ++ channel->offermsg.child_relid); ++ } ++} ++ + void vmbus_free_channels(void) + { + struct vmbus_channel *channel; +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index a12666d..2b7b51d 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -510,14 +510,23 @@ static int vmbus_remove(struct device *child_device) + { + struct hv_driver *drv; + struct hv_device *dev = device_to_hv_device(child_device); ++ u32 relid = dev->channel->offermsg.child_relid; + + if (child_device->driver) { + drv = drv_to_hv_drv(child_device->driver); + if (drv->remove) + drv->remove(dev); +- else ++ else { ++ hv_process_channel_removal(dev->channel, relid); + pr_err("remove not set for driver %s\n", + dev_name(child_device)); ++ } ++ } else { ++ /* ++ * We don't have a driver for this device; deal with the ++ * rescind message by removing the channel. ++ */ ++ hv_process_channel_removal(dev->channel, relid); + } + + return 0; +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 7d976ac..dd92a85 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -1226,6 +1226,7 @@ void hv_kvp_onchannelcallback(void *); + int hv_vss_init(struct hv_util_service *); + void hv_vss_deinit(void); + void hv_vss_onchannelcallback(void *); ++void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid); + + extern struct resource hyperv_mmio; + diff --git a/patches.suse/msft-hv-0759-Drivers-hv-vmbus-Handle-both-rescind-and-offer-messa.patch b/patches.suse/msft-hv-0759-Drivers-hv-vmbus-Handle-both-rescind-and-offer-messa.patch new file mode 100644 index 0000000000..d0bc62f2f8 --- /dev/null +++ b/patches.suse/msft-hv-0759-Drivers-hv-vmbus-Handle-both-rescind-and-offer-messa.patch @@ -0,0 +1,192 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:18:18 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Handle both rescind and offer messages in the same context +Git-commit: 2dd37cb81580dce6dfb8c5a7d5c37b904a188ae7 +References: fate#317533 + +Execute both ressind and offer messages in the same work context. This serializes these +operations and naturally addresses the various corner cases. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 115 +++++++++++++++++++++++++--------------------- + 1 file changed, 62 insertions(+), 53 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index b933891..f8528e1 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -134,6 +134,34 @@ fw_error: + + EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); + ++static void vmbus_process_device_unregister(struct work_struct *work) ++{ ++ struct device *dev; ++ struct vmbus_channel *channel = container_of(work, ++ struct vmbus_channel, ++ work); ++ ++ dev = get_device(&channel->device_obj->device); ++ if (dev) { ++ vmbus_device_unregister(channel->device_obj); ++ put_device(dev); ++ } ++} ++ ++static void vmbus_sc_creation_cb(struct work_struct *work) ++{ ++ struct vmbus_channel *newchannel = container_of(work, ++ struct vmbus_channel, ++ work); ++ struct vmbus_channel *primary_channel = newchannel->primary_channel; ++ ++ /* ++ * On entry sc_creation_callback has been already verified to ++ * be non-NULL. ++ */ ++ primary_channel->sc_creation_callback(newchannel); ++} ++ + /* + * alloc_channel - Allocate and initialize a vmbus channel object + */ +@@ -244,29 +272,6 @@ void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) + free_channel(channel); + } + +-/* +- * vmbus_process_rescind_offer - +- * Rescind the offer by initiating a device removal +- */ +-static void vmbus_process_rescind_offer(struct work_struct *work) +-{ +- struct vmbus_channel *channel = container_of(work, +- struct vmbus_channel, +- work); +- struct device *dev; +- +- if (channel->device_obj) { +- dev = get_device(&channel->device_obj->device); +- if (dev) { +- vmbus_device_unregister(channel->device_obj); +- put_device(dev); +- } +- } else { +- hv_process_channel_removal(channel, +- channel->offermsg.child_relid); +- } +-} +- + void vmbus_free_channels(void) + { + struct vmbus_channel *channel; +@@ -281,11 +286,8 @@ void vmbus_free_channels(void) + * vmbus_process_offer - Process the offer by creating a channel/device + * associated with this offer + */ +-static void vmbus_process_offer(struct work_struct *work) ++static void vmbus_process_offer(struct vmbus_channel *newchannel) + { +- struct vmbus_channel *newchannel = container_of(work, +- struct vmbus_channel, +- work); + struct vmbus_channel *channel; + bool fnew = true; + bool enq = false; +@@ -349,9 +351,19 @@ static void vmbus_process_offer(struct work_struct *work) + + newchannel->state = CHANNEL_OPEN_STATE; + if (channel->sc_creation_callback != NULL) +- channel->sc_creation_callback(newchannel); +- +- goto done_init_rescind; ++ /* ++ * We need to invoke the sub-channel creation ++ * callback; invoke this in a seperate work ++ * context since we are currently running on ++ * the global work context in which we handle ++ * messages from the host. ++ */ ++ INIT_WORK(&newchannel->work, ++ vmbus_sc_creation_cb); ++ queue_work(newchannel->controlwq, ++ &newchannel->work); ++ ++ return; + } + + goto err_free_chan; +@@ -392,15 +404,9 @@ static void vmbus_process_offer(struct work_struct *work) + kfree(newchannel->device_obj); + goto err_free_chan; + } +-done_init_rescind: +- spin_lock_irqsave(&newchannel->lock, flags); +- /* The next possible work is rescind handling */ +- INIT_WORK(&newchannel->work, vmbus_process_rescind_offer); +- /* Check if rescind offer was already received */ +- if (newchannel->rescind) +- queue_work(newchannel->controlwq, &newchannel->work); +- spin_unlock_irqrestore(&newchannel->lock, flags); ++ + return; ++ + err_free_chan: + free_channel(newchannel); + } +@@ -526,8 +532,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) + newchannel->monitor_grp = (u8)offer->monitorid / 32; + newchannel->monitor_bit = (u8)offer->monitorid % 32; + +- INIT_WORK(&newchannel->work, vmbus_process_offer); +- queue_work(newchannel->controlwq, &newchannel->work); ++ vmbus_process_offer(newchannel); + } + + /* +@@ -544,24 +549,28 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + rescind = (struct vmbus_channel_rescind_offer *)hdr; + channel = relid2channel(rescind->child_relid); + +- if (channel == NULL) +- /* Just return here, no channel found */ ++ if (channel == NULL) { ++ hv_process_channel_removal(NULL, rescind->child_relid); + return; ++ } + + spin_lock_irqsave(&channel->lock, flags); + channel->rescind = true; +- /* +- * channel->work.func != vmbus_process_rescind_offer means we are still +- * processing offer request and the rescind offer processing should be +- * postponed. It will be done at the very end of vmbus_process_offer() +- * as rescind flag is being checked there. +- */ +- if (channel->work.func == vmbus_process_rescind_offer) +- /* work is initialized for vmbus_process_rescind_offer() from +- * vmbus_process_offer() where the channel got created */ +- queue_work(channel->controlwq, &channel->work); +- + spin_unlock_irqrestore(&channel->lock, flags); ++ ++ if (channel->device_obj) { ++ /* ++ * We will have to unregister this device from the ++ * driver core. Do this in the per-channel work context. ++ * Note that we are currently executing on the global ++ * workq for handling messages from the host. ++ */ ++ INIT_WORK(&channel->work, vmbus_process_device_unregister); ++ queue_work(channel->controlwq, &channel->work); ++ } else { ++ hv_process_channel_removal(channel, ++ channel->offermsg.child_relid); ++ } + } + + /* diff --git a/patches.suse/msft-hv-0760-Drivers-hv-vmbus-Remove-the-channel-from-the-channel.patch b/patches.suse/msft-hv-0760-Drivers-hv-vmbus-Remove-the-channel-from-the-channel.patch new file mode 100644 index 0000000000..21b1981395 --- /dev/null +++ b/patches.suse/msft-hv-0760-Drivers-hv-vmbus-Remove-the-channel-from-the-channel.patch @@ -0,0 +1,60 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:18:19 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Remove the channel from the channel list(s) on failure +Git-commit: 5b1e5b530753e660080d402b81b88684893157d5 +References: fate#317533 + +Properly rollback state in vmbus_pocess_offer() in the failure paths. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 21 ++++++++++++++++----- + 1 file changed, 16 insertions(+), 5 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index f8528e1..b1e5a5f 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -386,7 +386,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + &newchannel->offermsg.offer.if_instance, + newchannel); + if (!newchannel->device_obj) +- goto err_free_chan; ++ goto err_deq_chan; + + /* + * Add the new device to the bus. This will kick off device-driver +@@ -398,15 +398,26 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + pr_err("unable to add child device object (relid %d)\n", + newchannel->offermsg.child_relid); + +- spin_lock_irqsave(&vmbus_connection.channel_lock, flags); +- list_del(&newchannel->listentry); +- spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); + kfree(newchannel->device_obj); +- goto err_free_chan; ++ goto err_deq_chan; + } + + return; + ++err_deq_chan: ++ spin_lock_irqsave(&vmbus_connection.channel_lock, flags); ++ list_del(&newchannel->listentry); ++ spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); ++ ++ if (newchannel->target_cpu != get_cpu()) { ++ put_cpu(); ++ smp_call_function_single(newchannel->target_cpu, ++ percpu_channel_deq, newchannel, true); ++ } else { ++ percpu_channel_deq(newchannel); ++ put_cpu(); ++ } ++ + err_free_chan: + free_channel(newchannel); + } diff --git a/patches.suse/msft-hv-0761-Drivers-hv-util-On-device-remove-close-the-channel-a.patch b/patches.suse/msft-hv-0761-Drivers-hv-util-On-device-remove-close-the-channel-a.patch new file mode 100644 index 0000000000..cd5ac12f94 --- /dev/null +++ b/patches.suse/msft-hv-0761-Drivers-hv-util-On-device-remove-close-the-channel-a.patch @@ -0,0 +1,32 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:18:20 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: util: On device remove, close the channel after de-initializing the service +Git-commit: 5380b383ba10915e61e3db09341cf8193f0601ad +References: fate#317533 + +When the offer is rescinded, vmbus_close() can free up the channel; +deinitialize the service before closing the channel. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c +index c5be773..7994ec2 100644 +--- a/drivers/hv/hv_util.c ++++ b/drivers/hv/hv_util.c +@@ -380,9 +380,9 @@ static int util_remove(struct hv_device *dev) + { + struct hv_util_service *srv = hv_get_drvdata(dev); + +- vmbus_close(dev->channel); + if (srv->util_deinit) + srv->util_deinit(); ++ vmbus_close(dev->channel); + kfree(srv->recv_buffer); + + return 0; diff --git a/patches.suse/msft-hv-0762-Drivers-hv-vmbus-Get-rid-of-some-unnecessary-message.patch b/patches.suse/msft-hv-0762-Drivers-hv-vmbus-Get-rid-of-some-unnecessary-message.patch new file mode 100644 index 0000000000..674a027449 --- /dev/null +++ b/patches.suse/msft-hv-0762-Drivers-hv-vmbus-Get-rid-of-some-unnecessary-message.patch @@ -0,0 +1,46 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:18:21 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Get rid of some unnecessary messages +Git-commit: 37f492ce8148d84261cdb9fe1e925199f47531ae +References: fate#317533 + +Currently we log messages when either we are not able to map an ID to a +channel or when the channel does not have a callback associated +(in the channel interrupt handling path). These messages don't add +any value, get rid of them. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/connection.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index af2388f..583d7d4 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -318,10 +318,8 @@ static void process_chn_event(u32 relid) + */ + channel = pcpu_relid2channel(relid); + +- if (!channel) { +- pr_err("channel not found for relid - %u\n", relid); ++ if (!channel) + return; +- } + + /* + * A channel once created is persistent even when there +@@ -356,10 +354,7 @@ static void process_chn_event(u32 relid) + else + bytes_to_read = 0; + } while (read_state && (bytes_to_read != 0)); +- } else { +- pr_err("no channel callback for relid - %u\n", relid); + } +- + } + + /* diff --git a/patches.suse/msft-hv-0763-Drivers-hv-hv_balloon-eliminate-the-trylock-path-in-.patch b/patches.suse/msft-hv-0763-Drivers-hv-hv_balloon-eliminate-the-trylock-path-in-.patch new file mode 100644 index 0000000000..a78ceb7ca5 --- /dev/null +++ b/patches.suse/msft-hv-0763-Drivers-hv-hv_balloon-eliminate-the-trylock-path-in-.patch @@ -0,0 +1,142 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Sat, 28 Feb 2015 11:38:58 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: eliminate the trylock path in acquire/release_region_mutex +Git-commit: b05d8d9ef5ef21d1b18440430f950304836e1aaa +References: fate#317533 + +When many memory regions are being added and automatically onlined the +following lockup is sometimes observed: + +INFO: task udevd:1872 blocked for more than 120 seconds. +... +Call Trace: + [<ffffffff816ec0bc>] schedule_timeout+0x22c/0x350 + [<ffffffff816eb98f>] wait_for_common+0x10f/0x160 + [<ffffffff81067650>] ? default_wake_function+0x0/0x20 + [<ffffffff816eb9fd>] wait_for_completion+0x1d/0x20 + [<ffffffff8144cb9c>] hv_memory_notifier+0xdc/0x120 + [<ffffffff816f298c>] notifier_call_chain+0x4c/0x70 +... + +When several memory blocks are going online simultaneously we got several +hv_memory_notifier() trying to acquire the ha_region_mutex. When this mutex is +being held by hot_add_req() all these competing acquire_region_mutex() do +mutex_trylock, fail, and queue themselves into wait_for_completion(..). However +when we do complete() from release_region_mutex() only one of them wakes up. +This could be solved by changing complete() -> complete_all() memory onlining +can be delayed as well, in that case we can still get several +hv_memory_notifier() runners at the same time trying to grab the mutex. +Only one of them will succeed and the others will hang for forever as +complete() is not being called. We don't see this issue often because we have +5sec onlining timeout in hv_mem_hot_add() and usually all udev events arrive +in this time frame. + +Get rid of the trylock path, waiting on the mutex is supposed to provide the +required serialization. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 35 ++++++----------------------------- + 1 file changed, 6 insertions(+), 29 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 965c37a..ea3d33c 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -534,7 +534,6 @@ struct hv_dynmem_device { + struct task_struct *thread; + + struct mutex ha_region_mutex; +- struct completion waiter_event; + + /* + * A list of hot-add regions. +@@ -554,38 +553,17 @@ static struct hv_dynmem_device dm_device; + static void post_status(struct hv_dynmem_device *dm); + + #ifdef CONFIG_MEMORY_HOTPLUG +-static void acquire_region_mutex(bool trylock) +-{ +- if (trylock) { +- reinit_completion(&dm_device.waiter_event); +- while (!mutex_trylock(&dm_device.ha_region_mutex)) +- wait_for_completion(&dm_device.waiter_event); +- } else { +- mutex_lock(&dm_device.ha_region_mutex); +- } +-} +- +-static void release_region_mutex(bool trylock) +-{ +- if (trylock) { +- mutex_unlock(&dm_device.ha_region_mutex); +- } else { +- mutex_unlock(&dm_device.ha_region_mutex); +- complete(&dm_device.waiter_event); +- } +-} +- + static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, + void *v) + { + switch (val) { + case MEM_GOING_ONLINE: +- acquire_region_mutex(true); ++ mutex_lock(&dm_device.ha_region_mutex); + break; + + case MEM_ONLINE: + case MEM_CANCEL_ONLINE: +- release_region_mutex(true); ++ mutex_unlock(&dm_device.ha_region_mutex); + if (dm_device.ha_waiting) { + dm_device.ha_waiting = false; + complete(&dm_device.ol_waitevent); +@@ -646,7 +624,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, + init_completion(&dm_device.ol_waitevent); + dm_device.ha_waiting = true; + +- release_region_mutex(false); ++ mutex_unlock(&dm_device.ha_region_mutex); + nid = memory_add_physaddr_to_nid(PFN_PHYS(start_pfn)); + ret = add_memory(nid, PFN_PHYS((start_pfn)), + (HA_CHUNK << PAGE_SHIFT)); +@@ -675,7 +653,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, + * have not been "onlined" within the allowed time. + */ + wait_for_completion_timeout(&dm_device.ol_waitevent, 5*HZ); +- acquire_region_mutex(false); ++ mutex_lock(&dm_device.ha_region_mutex); + post_status(&dm_device); + } + +@@ -886,7 +864,7 @@ static void hot_add_req(struct work_struct *dummy) + resp.hdr.size = sizeof(struct dm_hot_add_response); + + #ifdef CONFIG_MEMORY_HOTPLUG +- acquire_region_mutex(false); ++ mutex_lock(&dm_device.ha_region_mutex); + pg_start = dm->ha_wrk.ha_page_range.finfo.start_page; + pfn_cnt = dm->ha_wrk.ha_page_range.finfo.page_cnt; + +@@ -918,7 +896,7 @@ static void hot_add_req(struct work_struct *dummy) + if (do_hot_add) + resp.page_count = process_hot_add(pg_start, pfn_cnt, + rg_start, rg_sz); +- release_region_mutex(false); ++ mutex_unlock(&dm_device.ha_region_mutex); + #endif + /* + * The result field of the response structure has the +@@ -1440,7 +1418,6 @@ static int balloon_probe(struct hv_device *dev, + dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7; + init_completion(&dm_device.host_event); + init_completion(&dm_device.config_event); +- init_completion(&dm_device.waiter_event); + INIT_LIST_HEAD(&dm_device.ha_region_list); + mutex_init(&dm_device.ha_region_mutex); + INIT_WORK(&dm_device.balloon_wrk.wrk, balloon_up); diff --git a/patches.suse/msft-hv-0764-Drivers-hv-hv_balloon-report-offline-pages-as-being-.patch b/patches.suse/msft-hv-0764-Drivers-hv-hv_balloon-report-offline-pages-as-being-.patch new file mode 100644 index 0000000000..a32448b93d --- /dev/null +++ b/patches.suse/msft-hv-0764-Drivers-hv-hv_balloon-report-offline-pages-as-being-.patch @@ -0,0 +1,104 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Sat, 28 Feb 2015 11:38:59 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: report offline pages as being used +Git-commit: 549fd280b145e2154db5a7d06981d041f8bbf597 +References: fate#317533 + +When hot-added memory pages are not brought online or when some memory blocks +are sent offline the subsequent ballooning process kills the guest with OOM +killer. This happens as we don't report these pages as neither used nor free +and apparently host algorithm considers them as being unused. Keep track of +all online/offline operations and report all currently offline pages as being +used so host won't try to balloon them out. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 33 ++++++++++++++++++++++++--------- + 1 file changed, 24 insertions(+), 9 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index ea3d33c..53932b3 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -503,6 +503,8 @@ struct hv_dynmem_device { + * Number of pages we have currently ballooned out. + */ + unsigned int num_pages_ballooned; ++ unsigned int num_pages_onlined; ++ unsigned int num_pages_added; + + /* + * State to manage the ballooning (up) operation. +@@ -556,12 +558,15 @@ static void post_status(struct hv_dynmem_device *dm); + static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, + void *v) + { ++ struct memory_notify *mem = (struct memory_notify *)v; ++ + switch (val) { + case MEM_GOING_ONLINE: + mutex_lock(&dm_device.ha_region_mutex); + break; + + case MEM_ONLINE: ++ dm_device.num_pages_onlined += mem->nr_pages; + case MEM_CANCEL_ONLINE: + mutex_unlock(&dm_device.ha_region_mutex); + if (dm_device.ha_waiting) { +@@ -570,8 +575,12 @@ static int hv_memory_notifier(struct notifier_block *nb, unsigned long val, + } + break; + +- case MEM_GOING_OFFLINE: + case MEM_OFFLINE: ++ mutex_lock(&dm_device.ha_region_mutex); ++ dm_device.num_pages_onlined -= mem->nr_pages; ++ mutex_unlock(&dm_device.ha_region_mutex); ++ break; ++ case MEM_GOING_OFFLINE: + case MEM_CANCEL_OFFLINE: + break; + } +@@ -896,6 +905,8 @@ static void hot_add_req(struct work_struct *dummy) + if (do_hot_add) + resp.page_count = process_hot_add(pg_start, pfn_cnt, + rg_start, rg_sz); ++ ++ dm->num_pages_added += resp.page_count; + mutex_unlock(&dm_device.ha_region_mutex); + #endif + /* +@@ -1009,17 +1020,21 @@ static void post_status(struct hv_dynmem_device *dm) + status.hdr.trans_id = atomic_inc_return(&trans_id); + + /* +- * The host expects the guest to report free memory. +- * Further, the host expects the pressure information to +- * include the ballooned out pages. +- * For a given amount of memory that we are managing, we +- * need to compute a floor below which we should not balloon. +- * Compute this and add it to the pressure report. ++ * The host expects the guest to report free and committed memory. ++ * Furthermore, the host expects the pressure information to include ++ * the ballooned out pages. For a given amount of memory that we are ++ * managing we need to compute a floor below which we should not ++ * balloon. Compute this and add it to the pressure report. ++ * We also need to report all offline pages (num_pages_added - ++ * num_pages_onlined) as committed to the host, otherwise it can try ++ * asking us to balloon them out. + */ + status.num_avail = val.freeram; + status.num_committed = vm_memory_committed() + +- dm->num_pages_ballooned + +- compute_balloon_floor(); ++ dm->num_pages_ballooned + ++ (dm->num_pages_added > dm->num_pages_onlined ? ++ dm->num_pages_added - dm->num_pages_onlined : 0) + ++ compute_balloon_floor(); + + /* + * If our transaction ID is no longer current, just don't diff --git a/patches.suse/msft-hv-0765-Drivers-hv-hv_balloon-refuse-to-balloon-below-the-fl.patch b/patches.suse/msft-hv-0765-Drivers-hv-hv_balloon-refuse-to-balloon-below-the-fl.patch new file mode 100644 index 0000000000..51ff1adf3e --- /dev/null +++ b/patches.suse/msft-hv-0765-Drivers-hv-hv_balloon-refuse-to-balloon-below-the-fl.patch @@ -0,0 +1,48 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Sat, 28 Feb 2015 11:39:00 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: refuse to balloon below the floor +Git-commit: 530d15b907038735d4cb008dc5caae7ce4dfc985 +References: fate#317533 + +When host asks us to balloon up we need to be sure we're not committing suicide +by overballooning. Use already existent 'floor' metric as our lowest possible +value for free ram. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 53932b3..c5bb872 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1138,6 +1138,8 @@ static void balloon_up(struct work_struct *dummy) + bool alloc_error; + bool done = false; + int i; ++ struct sysinfo val; ++ unsigned long floor; + + /* The host balloons pages in 2M granularity. */ + WARN_ON_ONCE(num_pages % PAGES_IN_2M != 0); +@@ -1148,6 +1150,15 @@ static void balloon_up(struct work_struct *dummy) + */ + alloc_unit = 512; + ++ si_meminfo(&val); ++ floor = compute_balloon_floor(); ++ ++ /* Refuse to balloon below the floor, keep the 2M granularity. */ ++ if (val.freeram - num_pages < floor) { ++ num_pages = val.freeram > floor ? (val.freeram - floor) : 0; ++ num_pages -= num_pages % PAGES_IN_2M; ++ } ++ + while (!done) { + bl_resp = (struct dm_balloon_response *)send_buffer; + memset(send_buffer, 0, PAGE_SIZE); diff --git a/patches.suse/msft-hv-0766-Drivers-hv-vmbus-Add-support-for-VMBus-panic-notifie.patch b/patches.suse/msft-hv-0766-Drivers-hv-vmbus-Add-support-for-VMBus-panic-notifie.patch new file mode 100644 index 0000000000..24c3bfdccb --- /dev/null +++ b/patches.suse/msft-hv-0766-Drivers-hv-vmbus-Add-support-for-VMBus-panic-notifie.patch @@ -0,0 +1,113 @@ +From: Nick Meier <nmeier@microsoft.com> +Date: Sat, 28 Feb 2015 11:39:01 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Add support for VMBus panic notifier handler +Git-commit: 96c1d0581d00f7abe033350edb021a9d947d8d81 +References: fate#317533 + +Hyper-V allows a guest to notify the Hyper-V host that a panic +condition occured. This notification can include up to five 64 +bit values. These 64 bit values are written into crash MSRs. +Once the data has been written into the crash MSRs, the host is +then notified by writing into a Crash Control MSR. On the Hyper-V +host, the panic notification data is captured in the Windows Event +log as a 18590 event. + +Crash MSRs are defined in appendix H of the Hypervisor Top Level +Functional Specification. At the time of this patch, v4.0 is the +current functional spec. The URL for the v4.0 document is: + +http://download.microsoft.com/download/A/B/4/AB43A34E-BDD0-4FA6-BDEF-79EEF16E880B/Hypervisor Top Level Functional Specification v4.0.docx + +Signed-off-by: Nick Meier <nmeier@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hyperv_vmbus.h | 11 +++++++++++ + drivers/hv/vmbus_drv.c | 36 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 47 insertions(+) + +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index b055e53..88af4ec 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -49,6 +49,17 @@ enum hv_cpuid_function { + HVCPUID_IMPLEMENTATION_LIMITS = 0x40000005, + }; + ++#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE 0x400 ++ ++#define HV_X64_MSR_CRASH_P0 0x40000100 ++#define HV_X64_MSR_CRASH_P1 0x40000101 ++#define HV_X64_MSR_CRASH_P2 0x40000102 ++#define HV_X64_MSR_CRASH_P3 0x40000103 ++#define HV_X64_MSR_CRASH_P4 0x40000104 ++#define HV_X64_MSR_CRASH_CTL 0x40000105 ++ ++#define HV_CRASH_CTL_CRASH_NOTIFY 0x8000000000000000 ++ + /* Define version of the synthetic interrupt controller. */ + #define HV_SYNIC_VERSION (1) + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 2b7b51d..526fa8b 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -37,6 +37,8 @@ + #include <asm/hyperv.h> + #include <asm/hypervisor.h> + #include <asm/mshyperv.h> ++#include <linux/notifier.h> ++#include <linux/ptrace.h> + #include "hyperv_vmbus.h" + + +@@ -45,6 +47,31 @@ static struct tasklet_struct msg_dpc; + static struct completion probe_event; + static int irq; + ++ ++int hyperv_panic_event(struct notifier_block *nb, ++ unsigned long event, void *ptr) ++{ ++ struct pt_regs *regs; ++ ++ regs = task_pt_regs(current); ++ ++ wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip); ++ wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax); ++ wrmsrl(HV_X64_MSR_CRASH_P2, regs->bx); ++ wrmsrl(HV_X64_MSR_CRASH_P3, regs->cx); ++ wrmsrl(HV_X64_MSR_CRASH_P4, regs->dx); ++ ++ /* ++ * Let Hyper-V know there is crash data available ++ */ ++ wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY); ++ return NOTIFY_DONE; ++} ++ ++static struct notifier_block hyperv_panic_block = { ++ .notifier_call = hyperv_panic_event, ++}; ++ + struct resource hyperv_mmio = { + .name = "hyperv mmio", + .flags = IORESOURCE_MEM, +@@ -795,6 +822,15 @@ static int vmbus_bus_init(int irq) + goto err_alloc; + + hv_cpu_hotplug_quirk(true); ++ ++ /* ++ * Only register if the crash MSRs are available ++ */ ++ if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { ++ atomic_notifier_chain_register(&panic_notifier_list, ++ &hyperv_panic_block); ++ } ++ + vmbus_request_offers(); + + return 0; diff --git a/patches.suse/msft-hv-0767-Drivers-hv-vmbus-Use-a-round-robin-algorithm-for-pic.patch b/patches.suse/msft-hv-0767-Drivers-hv-vmbus-Use-a-round-robin-algorithm-for-pic.patch new file mode 100644 index 0000000000..02ae86bf72 --- /dev/null +++ b/patches.suse/msft-hv-0767-Drivers-hv-vmbus-Use-a-round-robin-algorithm-for-pic.patch @@ -0,0 +1,101 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:39:02 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Use a round-robin algorithm for picking the outgoing channel +Git-commit: a13e8bbe851a96a0e78c2bd599bc34082fa697cd +References: fate#317533 + +The current algorithm for picking an outgoing channel was not distributing +the load well. Implement a simple round-robin scheme to ensure good +distribution of the outgoing traffic. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Reviewed-by: Long Li <longli@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 30 +++++++++++++++--------------- + include/linux/hyperv.h | 3 +++ + 2 files changed, 18 insertions(+), 15 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index b1e5a5f..6117891 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -350,6 +350,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + } + + newchannel->state = CHANNEL_OPEN_STATE; ++ channel->num_sc++; + if (channel->sc_creation_callback != NULL) + /* + * We need to invoke the sub-channel creation +@@ -862,9 +863,8 @@ cleanup: + + /* + * Retrieve the (sub) channel on which to send an outgoing request. +- * When a primary channel has multiple sub-channels, we choose a +- * channel whose VCPU binding is closest to the VCPU on which +- * this call is being made. ++ * When a primary channel has multiple sub-channels, we try to ++ * distribute the load equally amongst all available channels. + */ + struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) + { +@@ -872,11 +872,19 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) + int cur_cpu; + struct vmbus_channel *cur_channel; + struct vmbus_channel *outgoing_channel = primary; +- int cpu_distance, new_cpu_distance; ++ int next_channel; ++ int i = 1; + + if (list_empty(&primary->sc_list)) + return outgoing_channel; + ++ next_channel = primary->next_oc++; ++ ++ if (next_channel > (primary->num_sc)) { ++ primary->next_oc = 0; ++ return outgoing_channel; ++ } ++ + cur_cpu = hv_context.vp_index[get_cpu()]; + put_cpu(); + list_for_each_safe(cur, tmp, &primary->sc_list) { +@@ -887,18 +895,10 @@ struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary) + if (cur_channel->target_vp == cur_cpu) + return cur_channel; + +- cpu_distance = ((outgoing_channel->target_vp > cur_cpu) ? +- (outgoing_channel->target_vp - cur_cpu) : +- (cur_cpu - outgoing_channel->target_vp)); +- +- new_cpu_distance = ((cur_channel->target_vp > cur_cpu) ? +- (cur_channel->target_vp - cur_cpu) : +- (cur_cpu - cur_channel->target_vp)); +- +- if (cpu_distance < new_cpu_distance) +- continue; ++ if (i == next_channel) ++ return cur_channel; + +- outgoing_channel = cur_channel; ++ i++; + } + + return outgoing_channel; +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index dd92a85..1ca5824 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -761,6 +761,9 @@ struct vmbus_channel { + * link up channels based on their CPU affinity. + */ + struct list_head percpu_list; ++ ++ int num_sc; ++ int next_oc; + }; + + static inline void set_channel_read_state(struct vmbus_channel *c, bool state) diff --git a/patches.suse/msft-hv-0768-Drivers-hv-vmbus-Suport-an-API-to-send-pagebuffers-w.patch b/patches.suse/msft-hv-0768-Drivers-hv-vmbus-Suport-an-API-to-send-pagebuffers-w.patch new file mode 100644 index 0000000000..b2d1d5baa4 --- /dev/null +++ b/patches.suse/msft-hv-0768-Drivers-hv-vmbus-Suport-an-API-to-send-pagebuffers-w.patch @@ -0,0 +1,104 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:39:03 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Suport an API to send pagebuffers with additional control +Git-commit: 87e93d61708fe2c44875d1ecdb174aad070dbd08 +References: fate#317533 + +Implement an API for sending pagebuffers that gives more control to the client +in terms of setting the vmbus flags as well as deciding when to +notify the host. This will be useful for enabling batch processing. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 33 +++++++++++++++++++++++++++------ + include/linux/hyperv.h | 9 +++++++++ + 2 files changed, 36 insertions(+), 6 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index 9b79aca..f060d1f 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -636,13 +636,18 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, + EXPORT_SYMBOL(vmbus_sendpacket); + + /* +- * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer +- * packets using a GPADL Direct packet type. ++ * vmbus_sendpacket_pagebuffer_ctl - Send a range of single-page buffer ++ * packets using a GPADL Direct packet type. This interface allows you ++ * to control notifying the host. This will be useful for sending ++ * batched data. Also the sender can control the send flags ++ * explicitly. + */ +-int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, ++int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, + struct hv_page_buffer pagebuffers[], + u32 pagecount, void *buffer, u32 bufferlen, +- u64 requestid) ++ u64 requestid, ++ u32 flags, ++ bool kick_q) + { + int ret; + int i; +@@ -670,7 +675,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, + + /* Setup the descriptor */ + desc.type = VM_PKT_DATA_USING_GPA_DIRECT; +- desc.flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; ++ desc.flags = flags; + desc.dataoffset8 = descsize >> 3; /* in 8-bytes grandularity */ + desc.length8 = (u16)(packetlen_aligned >> 3); + desc.transactionid = requestid; +@@ -691,11 +696,27 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, + + ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); + +- if (ret == 0 && signal) ++ if ((ret == 0) && kick_q && signal) + vmbus_setevent(channel); + + return ret; + } ++ ++/* ++ * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer ++ * packets using a GPADL Direct packet type. ++ */ ++int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, ++ struct hv_page_buffer pagebuffers[], ++ u32 pagecount, void *buffer, u32 bufferlen, ++ u64 requestid) ++{ ++ u32 flags = VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED; ++ return vmbus_sendpacket_pagebuffer_ctl(channel, pagebuffers, pagecount, ++ buffer, bufferlen, requestid, ++ flags, true); ++ ++} + EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer); + + /* +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 1ca5824..86e1a7a 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -874,6 +874,15 @@ extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, + u32 bufferlen, + u64 requestid); + ++extern int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, ++ struct hv_page_buffer pagebuffers[], ++ u32 pagecount, ++ void *buffer, ++ u32 bufferlen, ++ u64 requestid, ++ u32 flags, ++ bool kick_q); ++ + extern int vmbus_sendpacket_multipagebuffer(struct vmbus_channel *channel, + struct hv_multipage_buffer *mpb, + void *buffer, diff --git a/patches.suse/msft-hv-0769-Drivers-hv-vmbus-Suport-an-API-to-send-packet-with-a.patch b/patches.suse/msft-hv-0769-Drivers-hv-vmbus-Suport-an-API-to-send-packet-with-a.patch new file mode 100644 index 0000000000..49ecc72841 --- /dev/null +++ b/patches.suse/msft-hv-0769-Drivers-hv-vmbus-Suport-an-API-to-send-packet-with-a.patch @@ -0,0 +1,104 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Sat, 28 Feb 2015 11:39:04 -0800 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Suport an API to send packet with additional control +Git-commit: e9395e3f8952110bda60b54ad03ec52c6e9c7dbd +References: fate#317533 + +Implement an API that gives additional control on the what VMBUS flags will be +set as well as if the host needs to be signalled. This API will be +useful for clients that want to batch up requests to the host. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 43 ++++++++++++++++++++++++++----------------- + include/linux/hyperv.h | 8 ++++++++ + 2 files changed, 34 insertions(+), 17 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index f060d1f..da53180 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -584,23 +584,9 @@ void vmbus_close(struct vmbus_channel *channel) + } + EXPORT_SYMBOL_GPL(vmbus_close); + +-/** +- * vmbus_sendpacket() - Send the specified buffer on the given channel +- * @channel: Pointer to vmbus_channel structure. +- * @buffer: Pointer to the buffer you want to receive the data into. +- * @bufferlen: Maximum size of what the the buffer will hold +- * @requestid: Identifier of the request +- * @type: Type of packet that is being send e.g. negotiate, time +- * packet etc. +- * +- * Sends data in @buffer directly to hyper-v via the vmbus +- * This will send the data unparsed to hyper-v. +- * +- * Mainly used by Hyper-V drivers. +- */ +-int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, ++int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer, + u32 bufferlen, u64 requestid, +- enum vmbus_packet_type type, u32 flags) ++ enum vmbus_packet_type type, u32 flags, bool kick_q) + { + struct vmpacket_descriptor desc; + u32 packetlen = sizeof(struct vmpacket_descriptor) + bufferlen; +@@ -628,11 +614,34 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, + + ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); + +- if (ret == 0 && signal) ++ if ((ret == 0) && kick_q && signal) + vmbus_setevent(channel); + + return ret; + } ++EXPORT_SYMBOL(vmbus_sendpacket_ctl); ++ ++/** ++ * vmbus_sendpacket() - Send the specified buffer on the given channel ++ * @channel: Pointer to vmbus_channel structure. ++ * @buffer: Pointer to the buffer you want to receive the data into. ++ * @bufferlen: Maximum size of what the the buffer will hold ++ * @requestid: Identifier of the request ++ * @type: Type of packet that is being send e.g. negotiate, time ++ * packet etc. ++ * ++ * Sends data in @buffer directly to hyper-v via the vmbus ++ * This will send the data unparsed to hyper-v. ++ * ++ * Mainly used by Hyper-V drivers. ++ */ ++int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer, ++ u32 bufferlen, u64 requestid, ++ enum vmbus_packet_type type, u32 flags) ++{ ++ return vmbus_sendpacket_ctl(channel, buffer, bufferlen, requestid, ++ type, flags, true); ++} + EXPORT_SYMBOL(vmbus_sendpacket); + + /* +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 86e1a7a..80e444b 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -867,6 +867,14 @@ extern int vmbus_sendpacket(struct vmbus_channel *channel, + enum vmbus_packet_type type, + u32 flags); + ++extern int vmbus_sendpacket_ctl(struct vmbus_channel *channel, ++ void *buffer, ++ u32 bufferLen, ++ u64 requestid, ++ enum vmbus_packet_type type, ++ u32 flags, ++ bool kick_q); ++ + extern int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel, + struct hv_page_buffer pagebuffers[], + u32 pagecount, diff --git a/patches.suse/msft-hv-0770-mei-bus-can-be-static.patch b/patches.suse/msft-hv-0770-mei-bus-can-be-static.patch new file mode 100644 index 0000000000..0c174e7d98 --- /dev/null +++ b/patches.suse/msft-hv-0770-mei-bus-can-be-static.patch @@ -0,0 +1,32 @@ +From: kbuild test robot <fengguang.wu@intel.com> +Date: Mon, 2 Mar 2015 11:49:23 +0800 +Patch-mainline: v4.1-rc1 +Subject: mei: bus: () can be static +Git-commit: ed99d846f1774e14c8705819c12469eb3855b54e +References: fate#317533 + +drivers/hv/vmbus_drv.c:51:5: sparse: symbol 'hyperv_panic_event' was not declared. Should it be static? +drivers/hv/vmbus_drv.c:51:5: sparse: symbol 'hyperv_panic_event' was not declared. Should it be static? +drivers/hv/vmbus_drv.c:51:5: sparse: symbol 'hyperv_panic_event' was not declared. Should it be static? +drivers/hv/vmbus_drv.c:51:5: sparse: symbol 'hyperv_panic_event' was not declared. Should it be static? + +Signed-off-by: Fengguang Wu <fengguang.wu@intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/vmbus_drv.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 526fa8b..8313e25 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -48,7 +48,7 @@ static struct completion probe_event; + static int irq; + + +-int hyperv_panic_event(struct notifier_block *nb, ++static int hyperv_panic_event(struct notifier_block *nb, + unsigned long event, void *ptr) + { + struct pt_regs *regs; diff --git a/patches.suse/msft-hv-0771-hyperv-hyperv_fb-match-wait_for_completion_timeout-r.patch b/patches.suse/msft-hv-0771-hyperv-hyperv_fb-match-wait_for_completion_timeout-r.patch new file mode 100644 index 0000000000..cc2bb222ef --- /dev/null +++ b/patches.suse/msft-hv-0771-hyperv-hyperv_fb-match-wait_for_completion_timeout-r.patch @@ -0,0 +1,42 @@ +From: Nicholas Mc Guire <der.herr@hofr.at> +Date: Thu, 29 Jan 2015 11:24:16 +0100 +Patch-mainline: v4.1-rc1 +Subject: hyperv: hyperv_fb: match wait_for_completion_timeout return type +Git-commit: 7dea97e0379dbb2983a9f009c7cdaeb6bbe4c98e +References: fate#317533 + +The return type of wait_for_completion_timeout is unsigned long not +int. This patch fixes up the declarations only. + +Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at> +Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> +Acked-by: <ohering@suse.de> +--- + drivers/video/hyperv_fb.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/drivers/video/hyperv_fb.c b/drivers/video/hyperv_fb.c +index 4254336..807ee22 100644 +--- a/drivers/video/hyperv_fb.c ++++ b/drivers/video/hyperv_fb.c +@@ -415,7 +415,8 @@ static int synthvid_negotiate_ver(struct hv_device *hdev, u32 ver) + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; +- int t, ret = 0; ++ int ret = 0; ++ unsigned long t; + + memset(msg, 0, sizeof(struct synthvid_msg)); + msg->vid_hdr.type = SYNTHVID_VERSION_REQUEST; +@@ -488,7 +489,8 @@ static int synthvid_send_config(struct hv_device *hdev) + struct fb_info *info = hv_get_drvdata(hdev); + struct hvfb_par *par = info->par; + struct synthvid_msg *msg = (struct synthvid_msg *)par->init_buf; +- int t, ret = 0; ++ int ret = 0; ++ unsigned long t; + + /* Send VRAM location */ + memset(msg, 0, sizeof(struct synthvid_msg)); diff --git a/patches.suse/msft-hv-0772-Drivers-hv-vmbus-Perform-device-register-in-the-per-.patch b/patches.suse/msft-hv-0772-Drivers-hv-vmbus-Perform-device-register-in-the-per-.patch new file mode 100644 index 0000000000..0fed24b283 --- /dev/null +++ b/patches.suse/msft-hv-0772-Drivers-hv-vmbus-Perform-device-register-in-the-per-.patch @@ -0,0 +1,281 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Wed, 18 Mar 2015 12:29:21 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Perform device register in the per-channel work element +Git-commit: fde25d25dbd997067058f7d4c2ff31600157e6f2 +References: fate#317533 + +This patch is a continuation of the rescind handling cleanup work. We cannot +block in the global message handling work context especially if we are blocking +waiting for the host to wake us up. I would like to thank +Dexuan Cui <decui@microsoft.com> for observing this problem. + +The current char-next branch is broken and this patch fixes +the bug. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 143 ++++++++++++++++++++++++++++++++-------------- + drivers/hv/connection.c | 6 +- + drivers/hv/hyperv_vmbus.h | 2 +- + 3 files changed, 107 insertions(+), 44 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 6117891..5f8e47b 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -23,6 +23,7 @@ + #include <linux/kernel.h> + #include <linux/sched.h> + #include <linux/wait.h> ++#include <linux/delay.h> + #include <linux/mm.h> + #include <linux/slab.h> + #include <linux/list.h> +@@ -37,6 +38,10 @@ struct vmbus_channel_message_table_entry { + void (*message_handler)(struct vmbus_channel_message_header *msg); + }; + ++struct vmbus_rescind_work { ++ struct work_struct work; ++ struct vmbus_channel *channel; ++}; + + /** + * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message +@@ -134,20 +139,6 @@ fw_error: + + EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); + +-static void vmbus_process_device_unregister(struct work_struct *work) +-{ +- struct device *dev; +- struct vmbus_channel *channel = container_of(work, +- struct vmbus_channel, +- work); +- +- dev = get_device(&channel->device_obj->device); +- if (dev) { +- vmbus_device_unregister(channel->device_obj); +- put_device(dev); +- } +-} +- + static void vmbus_sc_creation_cb(struct work_struct *work) + { + struct vmbus_channel *newchannel = container_of(work, +@@ -220,6 +211,40 @@ static void free_channel(struct vmbus_channel *channel) + queue_work(vmbus_connection.work_queue, &channel->work); + } + ++static void process_rescind_fn(struct work_struct *work) ++{ ++ struct vmbus_rescind_work *rc_work; ++ struct vmbus_channel *channel; ++ struct device *dev; ++ ++ rc_work = container_of(work, struct vmbus_rescind_work, work); ++ channel = rc_work->channel; ++ ++ /* ++ * We have already acquired a reference on the channel ++ * and so it cannot vanish underneath us. ++ * It is possible (while very unlikely) that we may ++ * get here while the processing of the initial offer ++ * is still not complete. Deal with this situation by ++ * just waiting until the channel is in the correct state. ++ */ ++ ++ while (channel->work.func != release_channel) ++ msleep(1000); ++ ++ if (channel->device_obj) { ++ dev = get_device(&channel->device_obj->device); ++ if (dev) { ++ vmbus_device_unregister(channel->device_obj); ++ put_device(dev); ++ } ++ } else { ++ hv_process_channel_removal(channel, ++ channel->offermsg.child_relid); ++ } ++ kfree(work); ++} ++ + static void percpu_channel_enq(void *arg) + { + struct vmbus_channel *channel = arg; +@@ -282,6 +307,46 @@ void vmbus_free_channels(void) + } + } + ++static void vmbus_do_device_register(struct work_struct *work) ++{ ++ struct hv_device *device_obj; ++ int ret; ++ unsigned long flags; ++ struct vmbus_channel *newchannel = container_of(work, ++ struct vmbus_channel, ++ work); ++ ++ ret = vmbus_device_register(newchannel->device_obj); ++ if (ret != 0) { ++ pr_err("unable to add child device object (relid %d)\n", ++ newchannel->offermsg.child_relid); ++ spin_lock_irqsave(&vmbus_connection.channel_lock, flags); ++ list_del(&newchannel->listentry); ++ device_obj = newchannel->device_obj; ++ newchannel->device_obj = NULL; ++ spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); ++ ++ if (newchannel->target_cpu != get_cpu()) { ++ put_cpu(); ++ smp_call_function_single(newchannel->target_cpu, ++ percpu_channel_deq, newchannel, true); ++ } else { ++ percpu_channel_deq(newchannel); ++ put_cpu(); ++ } ++ ++ kfree(device_obj); ++ if (!newchannel->rescind) { ++ free_channel(newchannel); ++ return; ++ } ++ } ++ /* ++ * The next state for this channel is to be freed. ++ */ ++ INIT_WORK(&newchannel->work, release_channel); ++} ++ + /* + * vmbus_process_offer - Process the offer by creating a channel/device + * associated with this offer +@@ -291,7 +356,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + struct vmbus_channel *channel; + bool fnew = true; + bool enq = false; +- int ret; + unsigned long flags; + + /* Make sure this is a new offer */ +@@ -393,16 +457,13 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + * Add the new device to the bus. This will kick off device-driver + * binding which eventually invokes the device driver's AddDevice() + * method. ++ * Invoke this call on the per-channel work context. ++ * Until we return from this function, rescind offer message ++ * cannot be processed as we are running on the global message ++ * handling work. + */ +- ret = vmbus_device_register(newchannel->device_obj); +- if (ret != 0) { +- pr_err("unable to add child device object (relid %d)\n", +- newchannel->offermsg.child_relid); +- +- kfree(newchannel->device_obj); +- goto err_deq_chan; +- } +- ++ INIT_WORK(&newchannel->work, vmbus_do_device_register); ++ queue_work(newchannel->controlwq, &newchannel->work); + return; + + err_deq_chan: +@@ -556,33 +617,31 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + { + struct vmbus_channel_rescind_offer *rescind; + struct vmbus_channel *channel; +- unsigned long flags; ++ struct vmbus_rescind_work *rc_work; + + rescind = (struct vmbus_channel_rescind_offer *)hdr; +- channel = relid2channel(rescind->child_relid); ++ channel = relid2channel(rescind->child_relid, true); + + if (channel == NULL) { + hv_process_channel_removal(NULL, rescind->child_relid); + return; + } + +- spin_lock_irqsave(&channel->lock, flags); +- channel->rescind = true; +- spin_unlock_irqrestore(&channel->lock, flags); +- +- if (channel->device_obj) { +- /* +- * We will have to unregister this device from the +- * driver core. Do this in the per-channel work context. +- * Note that we are currently executing on the global +- * workq for handling messages from the host. +- */ +- INIT_WORK(&channel->work, vmbus_process_device_unregister); +- queue_work(channel->controlwq, &channel->work); +- } else { +- hv_process_channel_removal(channel, +- channel->offermsg.child_relid); ++ /* ++ * We have acquired a reference on the channel and have posted ++ * the rescind state. Perform further cleanup in a work context ++ * that is different from the global work context in which ++ * we process messages from the host (we are currently executing ++ * on that global context. ++ */ ++ rc_work = kzalloc(sizeof(struct vmbus_rescind_work), GFP_KERNEL); ++ if (!rc_work) { ++ pr_err("Unable to allocate memory for rescind processing "); ++ return; + } ++ rc_work->channel = channel; ++ INIT_WORK(&rc_work->work, process_rescind_fn); ++ schedule_work(&rc_work->work); + } + + /* +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index 583d7d4..8bcd307 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -270,7 +270,7 @@ static struct vmbus_channel *pcpu_relid2channel(u32 relid) + * relid2channel - Get the channel object given its + * child relative id (ie channel id) + */ +-struct vmbus_channel *relid2channel(u32 relid) ++struct vmbus_channel *relid2channel(u32 relid, bool rescind) + { + struct vmbus_channel *channel; + struct vmbus_channel *found_channel = NULL; +@@ -282,6 +282,8 @@ struct vmbus_channel *relid2channel(u32 relid) + list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { + if (channel->offermsg.child_relid == relid) { + found_channel = channel; ++ if (rescind) ++ found_channel->rescind = true; + break; + } else if (!list_empty(&channel->sc_list)) { + /* +@@ -292,6 +294,8 @@ struct vmbus_channel *relid2channel(u32 relid) + sc_list); + if (cur_sc->offermsg.child_relid == relid) { + found_channel = cur_sc; ++ if (rescind) ++ found_channel->rescind = true; + break; + } + } +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index 88af4ec..6339589 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -698,7 +698,7 @@ void vmbus_device_unregister(struct hv_device *device_obj); + /* VmbusChildDeviceDestroy( */ + /* struct hv_device *); */ + +-struct vmbus_channel *relid2channel(u32 relid); ++struct vmbus_channel *relid2channel(u32 relid, bool rescind); + + void vmbus_free_channels(void); + diff --git a/patches.suse/msft-hv-0773-Drivers-hv-hv_balloon-keep-locks-balanced-on-add_mem.patch b/patches.suse/msft-hv-0773-Drivers-hv-hv_balloon-keep-locks-balanced-on-add_mem.patch new file mode 100644 index 0000000000..8046e3d48b --- /dev/null +++ b/patches.suse/msft-hv-0773-Drivers-hv-hv_balloon-keep-locks-balanced-on-add_mem.patch @@ -0,0 +1,45 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Wed, 18 Mar 2015 12:29:22 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: keep locks balanced on add_memory() failure +Git-commit: f3f6eb80872becdbce07f7d2670d3f8ae5119752 +References: fate#317533 + +When add_memory() fails the following BUG is observed: +[ 743.646107] hv_balloon: hot_add memory failed error is -17 +[ 743.679973] +[ 743.680930] ===================================== +[ 743.680930] [ BUG: bad unlock balance detected! ] +[ 743.680930] 3.19.0-rc5_bug1131426+ #552 Not tainted +[ 743.680930] ------------------------------------- +[ 743.680930] kworker/0:2/255 is trying to release lock (&dm_device.ha_region_mutex) at: +[ 743.680930] [<ffffffff81aae5fe>] mutex_unlock+0xe/0x10 +[ 743.680930] but there are no more locks to release! + +This happens as we don't acquire ha_region_mutex and hot_add_req() expects us +to as it does unconditional mutex_unlock(). Acquire the lock on the error path. + +The current char-next branch is broken and this patch fixes +the bug. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Acked-by: Jason Wang <jasowang@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index c5bb872..f1f17c5 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -652,6 +652,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size, + } + has->ha_end_pfn -= HA_CHUNK; + has->covered_end_pfn -= processed_pfn; ++ mutex_lock(&dm_device.ha_region_mutex); + break; + } + diff --git a/patches.suse/msft-hv-0774-Drivers-hv-hv_balloon-don-t-lose-memory-when-onlinin.patch b/patches.suse/msft-hv-0774-Drivers-hv-hv_balloon-don-t-lose-memory-when-onlinin.patch new file mode 100644 index 0000000000..a75772b885 --- /dev/null +++ b/patches.suse/msft-hv-0774-Drivers-hv-hv_balloon-don-t-lose-memory-when-onlinin.patch @@ -0,0 +1,132 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Wed, 18 Mar 2015 12:29:23 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: don't lose memory when onlining order is not natural +Git-commit: 5abbbb75d733793b1637441691de95b7665cee85 +References: fate#317533 + +Memory blocks can be onlined in random order. When this order is not natural +some memory pages are not onlined because of the redundant check in +hv_online_page(). + +Here is a real world scenario: +1) Host tries to hot-add the following (process_hot_add): + pg_start=rg_start=0x48000, pfn_cnt=111616, rg_size=262144 + +2) This results in adding 4 memory blocks: +[ 109.057866] init_memory_mapping: [mem 0x48000000-0x4fffffff] +[ 114.102698] init_memory_mapping: [mem 0x50000000-0x57ffffff] +[ 119.168039] init_memory_mapping: [mem 0x58000000-0x5fffffff] +[ 124.233053] init_memory_mapping: [mem 0x60000000-0x67ffffff] +The last one is incomplete but we have special has->covered_end_pfn counter to +avoid onlining non-backed frames and hv_bring_pgs_online() function to bring +them online later on. + +3) Now we have 4 offline memory blocks: /sys/devices/system/memory/memory9-12 +$ for f in /sys/devices/system/memory/memory*/state; do echo $f `cat $f`; done | grep -v onlin +/sys/devices/system/memory/memory10/state offline +/sys/devices/system/memory/memory11/state offline +/sys/devices/system/memory/memory12/state offline +/sys/devices/system/memory/memory9/state offline + +4) We bring them online in non-natural order: +$grep MemTotal /proc/meminfo +MemTotal: 966348 kB +$echo online > /sys/devices/system/memory/memory12/state && grep MemTotal /proc/meminfo +MemTotal: 1019596 kB +$echo online > /sys/devices/system/memory/memory11/state && grep MemTotal /proc/meminfo +MemTotal: 1150668 kB +$echo online > /sys/devices/system/memory/memory9/state && grep MemTotal /proc/meminfo +MemTotal: 1150668 kB + +As you can see memory9 block gives us zero additional memory. We can also +observe a huge discrepancy between host- and guest-reported memory sizes. + +The root cause of the issue is the redundant pg >= covered_start_pfn check (and +covered_start_pfn advancing) in hv_online_page(). When upper memory block in +being onlined before the lower one (memory12 and memory11 in the above case) we +advance the covered_start_pfn pointer and all memory9 pages do not pass the +check. If the assumption that host always gives us requests in sequential order +and pg_start always equals rg_start when the first request for the new HA +region is received (that's the case in my testing) is correct than we can get +rid of covered_start_pfn and pg >= start_pfn check in hv_online_page() is +sufficient. + +The current char-next branch is broken and this patch fixes +the bug. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 14 ++++---------- + 1 file changed, 4 insertions(+), 10 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index f1f17c5..014256a 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -428,14 +428,13 @@ struct dm_info_msg { + * currently hot added. We hot add in multiples of 128M + * chunks; it is possible that we may not be able to bring + * online all the pages in the region. The range +- * covered_start_pfn : covered_end_pfn defines the pages that can ++ * covered_end_pfn defines the pages that can + * be brough online. + */ + + struct hv_hotadd_state { + struct list_head list; + unsigned long start_pfn; +- unsigned long covered_start_pfn; + unsigned long covered_end_pfn; + unsigned long ha_end_pfn; + unsigned long end_pfn; +@@ -679,8 +678,7 @@ static void hv_online_page(struct page *pg) + + list_for_each(cur, &dm_device.ha_region_list) { + has = list_entry(cur, struct hv_hotadd_state, list); +- cur_start_pgp = (unsigned long) +- pfn_to_page(has->covered_start_pfn); ++ cur_start_pgp = (unsigned long)pfn_to_page(has->start_pfn); + cur_end_pgp = (unsigned long)pfn_to_page(has->covered_end_pfn); + + if (((unsigned long)pg >= cur_start_pgp) && +@@ -692,7 +690,6 @@ static void hv_online_page(struct page *pg) + __online_page_set_limits(pg); + __online_page_increment_counters(pg); + __online_page_free(pg); +- has->covered_start_pfn++; + } + } + } +@@ -736,10 +733,9 @@ static bool pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt) + * is, update it. + */ + +- if (has->covered_end_pfn != start_pfn) { ++ if (has->covered_end_pfn != start_pfn) + has->covered_end_pfn = start_pfn; +- has->covered_start_pfn = start_pfn; +- } ++ + return true; + + } +@@ -784,7 +780,6 @@ static unsigned long handle_pg_range(unsigned long pg_start, + pgs_ol = pfn_cnt; + hv_bring_pgs_online(start_pfn, pgs_ol); + has->covered_end_pfn += pgs_ol; +- has->covered_start_pfn += pgs_ol; + pfn_cnt -= pgs_ol; + } + +@@ -845,7 +840,6 @@ static unsigned long process_hot_add(unsigned long pg_start, + list_add_tail(&ha_region->list, &dm_device.ha_region_list); + ha_region->start_pfn = rg_start; + ha_region->ha_end_pfn = rg_start; +- ha_region->covered_start_pfn = pg_start; + ha_region->covered_end_pfn = pg_start; + ha_region->end_pfn = rg_start + rg_size; + } diff --git a/patches.suse/msft-hv-0775-Drivers-hv-vmbus-Correcting-truncation-error-for-con.patch b/patches.suse/msft-hv-0775-Drivers-hv-vmbus-Correcting-truncation-error-for-con.patch new file mode 100644 index 0000000000..0f0078502b --- /dev/null +++ b/patches.suse/msft-hv-0775-Drivers-hv-vmbus-Correcting-truncation-error-for-con.patch @@ -0,0 +1,51 @@ +From: Nick Meier <nmeier@microsoft.com> +Date: Wed, 18 Mar 2015 12:29:24 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Correcting truncation error for constant HV_CRASH_CTL_CRASH_NOTIFY +Git-commit: 5ef5b6927f14f29cacd78fa1fb861661a5367f13 +References: fate#317533 + +HV_CRASH_CTL_CRASH_NOTIFY is a 64 bit number. Depending on the usage context, +the value may be truncated. This patch is in response from the following +email from Wu Fengguang <fengguang.wu@intel.com>: + + From: Wu Fengguang <fengguang.wu@intel.com> + Subject: [char-misc:char-misc-testing 25/45] drivers/hv/vmbus_drv.c:67:9: sparse: + constant 0x8000000000000000 is so big it is unsigned long + + tree: git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git char-misc-testing + head: b3de8e3719e582f3182bb504295e4a8e43c8c96f + commit: 96c1d0581d00f7abe033350edb021a9d947d8d81 [25/45] Drivers: hv: vmbus: Add support for VMBus panic notifier handler + reproduce: + # apt-get install sparse + git checkout 96c1d0581d00f7abe033350edb021a9d947d8d81 + make ARCH=x86_64 allmodconfig + make C=1 CF=-D__CHECK_ENDIAN__ + + sparse warnings: (new ones prefixed by >>) + + drivers/hv/vmbus_drv.c:67:9: sparse: constant 0x8000000000000000 is so big it is unsigned long + ... + +Signed-off-by: Nick Meier <nmeier@microsoft.com> +Reported-by: Wu Fengguang <fengguang.wu@intel.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hyperv_vmbus.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index 6339589..c8e27e0 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -58,7 +58,7 @@ enum hv_cpuid_function { + #define HV_X64_MSR_CRASH_P4 0x40000104 + #define HV_X64_MSR_CRASH_CTL 0x40000105 + +-#define HV_CRASH_CTL_CRASH_NOTIFY 0x8000000000000000 ++#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63) + + /* Define version of the synthetic interrupt controller. */ + #define HV_SYNIC_VERSION (1) diff --git a/patches.suse/msft-hv-0776-hv-vmbus-missing-curly-braces-in-vmbus_process_offer.patch b/patches.suse/msft-hv-0776-hv-vmbus-missing-curly-braces-in-vmbus_process_offer.patch new file mode 100644 index 0000000000..372f287b0c --- /dev/null +++ b/patches.suse/msft-hv-0776-hv-vmbus-missing-curly-braces-in-vmbus_process_offer.patch @@ -0,0 +1,39 @@ +From: Dan Carpenter <dan.carpenter@oracle.com> +Date: Wed, 18 Mar 2015 12:29:25 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv: vmbus: missing curly braces in vmbus_process_offer() +Git-commit: 177757423fde68a6ce773d2b67b468fbd8367bbc +References: fate#317533 + +The indenting makes it clear that there were curly braces intended here. + +Fixes: 2dd37cb81580 ('Drivers: hv: vmbus: Handle both rescind and offer messages in the same context') +Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 5f8e47b..25dbbaf 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -415,7 +415,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + + newchannel->state = CHANNEL_OPEN_STATE; + channel->num_sc++; +- if (channel->sc_creation_callback != NULL) ++ if (channel->sc_creation_callback != NULL) { + /* + * We need to invoke the sub-channel creation + * callback; invoke this in a seperate work +@@ -427,6 +427,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + vmbus_sc_creation_cb); + queue_work(newchannel->controlwq, + &newchannel->work); ++ } + + return; + } diff --git a/patches.suse/msft-hv-0778-Drivers-hv-vmbus-Fix-a-bug-in-rescind-processing-in-.patch b/patches.suse/msft-hv-0778-Drivers-hv-vmbus-Fix-a-bug-in-rescind-processing-in-.patch new file mode 100644 index 0000000000..92d241a9b5 --- /dev/null +++ b/patches.suse/msft-hv-0778-Drivers-hv-vmbus-Fix-a-bug-in-rescind-processing-in-.patch @@ -0,0 +1,56 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Wed, 18 Mar 2015 12:29:27 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Fix a bug in rescind processing in vmbus_close_internal() +Git-commit: f2eddbc9f1a466329c68f3b75e89cfacd2792365 +References: fate#317533 + +When a channel has been rescinded, the close operation is a noop. +Restructure the code so we deal with the rescind condition after +we properly cleanup the channel. I would like to thank +Dexuan Cui <decui@microsoft.com> for observing this problem. +The current code leaks memory when the channel is rescinded. + +The current char-next branch is broken and this patch fixes +the bug. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index da53180..2c8206d 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -501,15 +501,6 @@ static int vmbus_close_internal(struct vmbus_channel *channel) + put_cpu(); + } + +- /* +- * If the channel has been rescinded; process device removal. +- */ +- if (channel->rescind) { +- hv_process_channel_removal(channel, +- channel->offermsg.child_relid); +- return 0; +- } +- + /* Send a closing message */ + + msg = &channel->close_msg.msg; +@@ -549,6 +540,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel) + free_pages((unsigned long)channel->ringbuffer_pages, + get_order(channel->ringbuffer_pagecount * PAGE_SIZE)); + ++ /* ++ * If the channel has been rescinded; process device removal. ++ */ ++ if (channel->rescind) ++ hv_process_channel_removal(channel, ++ channel->offermsg.child_relid); + return ret; + } + diff --git a/patches.suse/msft-hv-0779-hv-hypervvssd-call-endmntent-before-call-setmntent-a.patch b/patches.suse/msft-hv-0779-hv-hypervvssd-call-endmntent-before-call-setmntent-a.patch new file mode 100644 index 0000000000..49df1b3684 --- /dev/null +++ b/patches.suse/msft-hv-0779-hv-hypervvssd-call-endmntent-before-call-setmntent-a.patch @@ -0,0 +1,61 @@ +From: Vaughan Cao <vaughan.cao@oracle.com> +Date: Wed, 18 Mar 2015 12:29:28 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv: hypervvssd: call endmntent before call setmntent again +Git-commit: 4ce50e9491c5c92baf8bb7af85eb25398d3f70af +References: fate#317533 + +If freeze fails, vss_operate will re-enter itself to thaw. But it forgets +to call endmntent() before it recalls setmntent() again. + +Signed-off-by: Vaughan Cao <vaughan.cao@oracle.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + tools/hv/hv_vss_daemon.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c +index 5e63f70..506dd01 100644 +--- a/tools/hv/hv_vss_daemon.c ++++ b/tools/hv/hv_vss_daemon.c +@@ -81,6 +81,7 @@ static int vss_operate(int operation) + char match[] = "/dev/"; + FILE *mounts; + struct mntent *ent; ++ char errdir[1024] = {0}; + unsigned int cmd; + int error = 0, root_seen = 0, save_errno = 0; + +@@ -115,6 +116,8 @@ static int vss_operate(int operation) + goto err; + } + ++ endmntent(mounts); ++ + if (root_seen) { + error |= vss_do_freeze("/", cmd); + if (error && operation == VSS_OP_FREEZE) +@@ -124,16 +127,19 @@ static int vss_operate(int operation) + goto out; + err: + save_errno = errno; ++ if (ent) { ++ strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1); ++ endmntent(mounts); ++ } + vss_operate(VSS_OP_THAW); + /* Call syslog after we thaw all filesystems */ + if (ent) + syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s", +- ent->mnt_dir, save_errno, strerror(save_errno)); ++ errdir, save_errno, strerror(save_errno)); + else + syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno, + strerror(save_errno)); + out: +- endmntent(mounts); + return error; + } + diff --git a/patches.suse/msft-hv-0780-Drivers-hv-vmbus-Export-the-vmbus_sendpacket_pagebuf.patch b/patches.suse/msft-hv-0780-Drivers-hv-vmbus-Export-the-vmbus_sendpacket_pagebuf.patch new file mode 100644 index 0000000000..c3e33d45af --- /dev/null +++ b/patches.suse/msft-hv-0780-Drivers-hv-vmbus-Export-the-vmbus_sendpacket_pagebuf.patch @@ -0,0 +1,29 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Wed, 18 Mar 2015 12:29:29 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Export the vmbus_sendpacket_pagebuffer_ctl() +Git-commit: b3a19b36ad7450d4c8caeb7d9f623af3da32a578 +References: fate#317533 + +Export the vmbus_sendpacket_pagebuffer_ctl() interface. This export will be +used by the netvsc driver. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index 2c8206d..fddd3b5 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -707,6 +707,7 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, + + return ret; + } ++EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer_ctl); + + /* + * vmbus_sendpacket_pagebuffer - Send a range of single-page buffer diff --git a/patches.suse/msft-hv-0781-Drivers-hv-vmbus-Fix-a-siganlling-host-signalling-is.patch b/patches.suse/msft-hv-0781-Drivers-hv-vmbus-Fix-a-siganlling-host-signalling-is.patch new file mode 100644 index 0000000000..5825e5d584 --- /dev/null +++ b/patches.suse/msft-hv-0781-Drivers-hv-vmbus-Fix-a-siganlling-host-signalling-is.patch @@ -0,0 +1,65 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Wed, 18 Mar 2015 12:29:30 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Fix a siganlling host signalling issue +Git-commit: 5f5cc81733baf7b67a039a931dae282e53bf97b9 +References: fate#317533 + +Handle the case when the write to the ringbuffer fails. In this case, +unconditionally signal the host. Since we may have deferred signalling +the host based on the kick_q parameter, signalling the host +unconditionally in this case deals with the issue. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel.c | 28 ++++++++++++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c +index fddd3b5..54da66d 100644 +--- a/drivers/hv/channel.c ++++ b/drivers/hv/channel.c +@@ -611,7 +611,19 @@ int vmbus_sendpacket_ctl(struct vmbus_channel *channel, void *buffer, + + ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); + +- if ((ret == 0) && kick_q && signal) ++ /* ++ * Signalling the host is conditional on many factors: ++ * 1. The ring state changed from being empty to non-empty. ++ * This is tracked by the variable "signal". ++ * 2. The variable kick_q tracks if more data will be placed ++ * on the ring. We will not signal if more data is ++ * to be placed. ++ * ++ * If we cannot write to the ring-buffer; signal the host ++ * even if we may not have written anything. This is a rare ++ * enough condition that it should not matter. ++ */ ++ if (((ret == 0) && kick_q && signal) || (ret)) + vmbus_setevent(channel); + + return ret; +@@ -702,7 +714,19 @@ int vmbus_sendpacket_pagebuffer_ctl(struct vmbus_channel *channel, + + ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal); + +- if ((ret == 0) && kick_q && signal) ++ /* ++ * Signalling the host is conditional on many factors: ++ * 1. The ring state changed from being empty to non-empty. ++ * This is tracked by the variable "signal". ++ * 2. The variable kick_q tracks if more data will be placed ++ * on the ring. We will not signal if more data is ++ * to be placed. ++ * ++ * If we cannot write to the ring-buffer; signal the host ++ * even if we may not have written anything. This is a rare ++ * enough condition that it should not matter. ++ */ ++ if (((ret == 0) && kick_q && signal) || (ret)) + vmbus_setevent(channel); + + return ret; diff --git a/patches.suse/msft-hv-0782-Drivers-hv-vmbus-Don-t-wait-after-requesting-offers.patch b/patches.suse/msft-hv-0782-Drivers-hv-vmbus-Don-t-wait-after-requesting-offers.patch new file mode 100644 index 0000000000..96bb1d89e5 --- /dev/null +++ b/patches.suse/msft-hv-0782-Drivers-hv-vmbus-Don-t-wait-after-requesting-offers.patch @@ -0,0 +1,54 @@ +From: "K. Y. Srinivasan" <kys@microsoft.com> +Date: Thu, 19 Mar 2015 08:11:34 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: vmbus: Don't wait after requesting offers +Git-commit: 73cffdb65e679b98893f484063462c045adcf212 +References: fate#317533 + +Don't wait after sending request for offers to the host. This wait is +unnecessary and simply adds 5 seconds to the boot time. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Cc: <stable@vger.kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 11 ----------- + 1 file changed, 11 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 25dbbaf..bb39705 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -884,7 +884,6 @@ int vmbus_request_offers(void) + struct vmbus_channel_message_header *msg; + struct vmbus_channel_msginfo *msginfo; + int ret; +- unsigned long t; + + msginfo = kmalloc(sizeof(*msginfo) + + sizeof(struct vmbus_channel_message_header), +@@ -892,8 +891,6 @@ int vmbus_request_offers(void) + if (!msginfo) + return -ENOMEM; + +- init_completion(&msginfo->waitevent); +- + msg = (struct vmbus_channel_message_header *)msginfo->msg; + + msg->msgtype = CHANNELMSG_REQUESTOFFERS; +@@ -907,14 +904,6 @@ int vmbus_request_offers(void) + goto cleanup; + } + +- t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); +- if (t == 0) { +- ret = -ETIMEDOUT; +- goto cleanup; +- } +- +- +- + cleanup: + kfree(msginfo); + diff --git a/patches.suse/msft-hv-0784-hv_netvsc-remove-vmbus_are_subchannels_present-in-rn.patch b/patches.suse/msft-hv-0784-hv_netvsc-remove-vmbus_are_subchannels_present-in-rn.patch new file mode 100644 index 0000000000..7a73cdfcc4 --- /dev/null +++ b/patches.suse/msft-hv-0784-hv_netvsc-remove-vmbus_are_subchannels_present-in-rn.patch @@ -0,0 +1,31 @@ +From: Haiyang Zhang <haiyangz@microsoft.com> +Date: Thu, 26 Mar 2015 16:20:58 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv_netvsc: remove vmbus_are_subchannels_present() in rndis_filter_device_add() +Git-commit: 5ce58c2f13eaa8ca6d7e1041175433bd8cc55756 +References: fate#317533 + +The vmbus_are_subchannels_present() also involves opening the channels, which +may be too early at this point. Checking for subchannels is not necessary here. +So this patch removes it. Subchannels will be opened when offer messages arrive. + +Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Acked-by: <ohering@suse.de> +--- + drivers/net/hyperv/rndis_filter.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c +index a2b185a..fdfab1f 100644 +--- a/drivers/net/hyperv/rndis_filter.c ++++ b/drivers/net/hyperv/rndis_filter.c +@@ -1141,8 +1141,6 @@ int rndis_filter_device_add(struct hv_device *dev, + net_device->num_chn = 1 + + init_packet->msg.v5_msg.subchn_comp.num_subchannels; + +- vmbus_are_subchannels_present(dev->channel); +- + ret = rndis_filter_set_rss_param(rndis_device, net_device->num_chn); + + out: diff --git a/patches.suse/msft-hv-0785-hv_netvsc-Cleanup-the-test-for-freeing-skb-when-we-u.patch b/patches.suse/msft-hv-0785-hv_netvsc-Cleanup-the-test-for-freeing-skb-when-we-u.patch new file mode 100644 index 0000000000..c223372c5a --- /dev/null +++ b/patches.suse/msft-hv-0785-hv_netvsc-Cleanup-the-test-for-freeing-skb-when-we-u.patch @@ -0,0 +1,47 @@ +From: KY Srinivasan <kys@microsoft.com> +Date: Sun, 29 Mar 2015 21:08:41 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv_netvsc: Cleanup the test for freeing skb when we use sendbuf mechanism +Git-commit: cbacec76bcd03ff21b37ac331e652b5a8f3ea644 +References: fate#317533 + +In preparation for embedding the rndis state and other packet state into +the skb, cleanup the test for freeing the skb. + +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: David S. Miller <davem@davemloft.net> +Acked-by: <ohering@suse.de> +--- + drivers/net/hyperv/netvsc.c | 1 + + drivers/net/hyperv/netvsc_drv.c | 3 +-- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c +index b81bd37..ecbd813 100644 +--- a/drivers/net/hyperv/netvsc.c ++++ b/drivers/net/hyperv/netvsc.c +@@ -870,6 +870,7 @@ int netvsc_send(struct hv_device *device, + skb = (struct sk_buff *) + (unsigned long)packet->send_completion_tid; + packet->page_buf_cnt = 0; ++ packet->send_completion_tid = 0; + } + } + packet->send_buf_index = section_index; +diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c +index 0c99818..75beb89 100644 +--- a/drivers/net/hyperv/netvsc_drv.c ++++ b/drivers/net/hyperv/netvsc_drv.c +@@ -234,11 +234,10 @@ static void netvsc_xmit_completion(void *context) + struct hv_netvsc_packet *packet = (struct hv_netvsc_packet *)context; + struct sk_buff *skb = (struct sk_buff *) + (unsigned long)packet->send_completion_tid; +- u32 index = packet->send_buf_index; + + kfree(packet); + +- if (skb && (index == NETVSC_INVALID_INDEX)) ++ if (skb) + dev_kfree_skb_any(skb); + } + diff --git a/patches.suse/msft-hv-0787-hv-run-non-blocking-message-handlers-in-the-dispatch.patch b/patches.suse/msft-hv-0787-hv-run-non-blocking-message-handlers-in-the-dispatch.patch new file mode 100644 index 0000000000..7edfbd9fb5 --- /dev/null +++ b/patches.suse/msft-hv-0787-hv-run-non-blocking-message-handlers-in-the-dispatch.patch @@ -0,0 +1,166 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Fri, 27 Mar 2015 09:10:08 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv: run non-blocking message handlers in the dispatch tasklet +Git-commit: 652594c7dfd9bf6392e3a727bc69d89a2562d953 +References: fate#317533 + +A work item in vmbus_connection.work_queue can sleep, waiting for a new +host message (usually it is some kind of "completion" message). Currently +the new message will be handled in the same workqueue, but since work items +in the workqueue is serialized, we actually have no chance to handle +the new message if the current work item is sleeping -- as as result, the +current work item will hang forever. + +K. Y. has posted the below fix to resolve the issue: +Drivers: hv: vmbus: Perform device register in the per-channel work element + +Actually we can simplify the fix by directly running non-blocking message +handlers in the dispatch tasklet (inspired by K. Y.). + +This patch is the fundamental change. The following 2 patches will simplify +the message offering and rescind-offering handling a lot. + +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Cc: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 41 ++++++++++++++++++----------------------- + drivers/hv/hyperv_vmbus.h | 17 +++++++++++++++++ + drivers/hv/vmbus_drv.c | 21 ++++++++++++++++++--- + 3 files changed, 53 insertions(+), 26 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index bb39705..287f07b 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -33,11 +33,6 @@ + + #include "hyperv_vmbus.h" + +-struct vmbus_channel_message_table_entry { +- enum vmbus_channel_message_type message_type; +- void (*message_handler)(struct vmbus_channel_message_header *msg); +-}; +- + struct vmbus_rescind_work { + struct work_struct work; + struct vmbus_channel *channel; +@@ -827,25 +822,25 @@ static void vmbus_onversion_response( + } + + /* Channel message dispatch table */ +-static struct vmbus_channel_message_table_entry ++struct vmbus_channel_message_table_entry + channel_message_table[CHANNELMSG_COUNT] = { +- {CHANNELMSG_INVALID, NULL}, +- {CHANNELMSG_OFFERCHANNEL, vmbus_onoffer}, +- {CHANNELMSG_RESCIND_CHANNELOFFER, vmbus_onoffer_rescind}, +- {CHANNELMSG_REQUESTOFFERS, NULL}, +- {CHANNELMSG_ALLOFFERS_DELIVERED, vmbus_onoffers_delivered}, +- {CHANNELMSG_OPENCHANNEL, NULL}, +- {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result}, +- {CHANNELMSG_CLOSECHANNEL, NULL}, +- {CHANNELMSG_GPADL_HEADER, NULL}, +- {CHANNELMSG_GPADL_BODY, NULL}, +- {CHANNELMSG_GPADL_CREATED, vmbus_ongpadl_created}, +- {CHANNELMSG_GPADL_TEARDOWN, NULL}, +- {CHANNELMSG_GPADL_TORNDOWN, vmbus_ongpadl_torndown}, +- {CHANNELMSG_RELID_RELEASED, NULL}, +- {CHANNELMSG_INITIATE_CONTACT, NULL}, +- {CHANNELMSG_VERSION_RESPONSE, vmbus_onversion_response}, +- {CHANNELMSG_UNLOAD, NULL}, ++ {CHANNELMSG_INVALID, 0, NULL}, ++ {CHANNELMSG_OFFERCHANNEL, 0, vmbus_onoffer}, ++ {CHANNELMSG_RESCIND_CHANNELOFFER, 0, vmbus_onoffer_rescind}, ++ {CHANNELMSG_REQUESTOFFERS, 0, NULL}, ++ {CHANNELMSG_ALLOFFERS_DELIVERED, 1, vmbus_onoffers_delivered}, ++ {CHANNELMSG_OPENCHANNEL, 0, NULL}, ++ {CHANNELMSG_OPENCHANNEL_RESULT, 1, vmbus_onopen_result}, ++ {CHANNELMSG_CLOSECHANNEL, 0, NULL}, ++ {CHANNELMSG_GPADL_HEADER, 0, NULL}, ++ {CHANNELMSG_GPADL_BODY, 0, NULL}, ++ {CHANNELMSG_GPADL_CREATED, 1, vmbus_ongpadl_created}, ++ {CHANNELMSG_GPADL_TEARDOWN, 0, NULL}, ++ {CHANNELMSG_GPADL_TORNDOWN, 1, vmbus_ongpadl_torndown}, ++ {CHANNELMSG_RELID_RELEASED, 0, NULL}, ++ {CHANNELMSG_INITIATE_CONTACT, 0, NULL}, ++ {CHANNELMSG_VERSION_RESPONSE, 1, vmbus_onversion_response}, ++ {CHANNELMSG_UNLOAD, 0, NULL}, + }; + + /* +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index c8e27e0..f40a5a9 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -685,6 +685,23 @@ struct vmbus_msginfo { + + extern struct vmbus_connection vmbus_connection; + ++enum vmbus_message_handler_type { ++ /* The related handler can sleep. */ ++ VMHT_BLOCKING = 0, ++ ++ /* The related handler must NOT sleep. */ ++ VMHT_NON_BLOCKING = 1, ++}; ++ ++struct vmbus_channel_message_table_entry { ++ enum vmbus_channel_message_type message_type; ++ enum vmbus_message_handler_type handler_type; ++ void (*message_handler)(struct vmbus_channel_message_header *msg); ++}; ++ ++extern struct vmbus_channel_message_table_entry ++ channel_message_table[CHANNELMSG_COUNT]; ++ + /* General vmbus interface */ + + struct hv_device *vmbus_device_create(const uuid_le *type, +diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c +index 8313e25..c85235e 100644 +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -657,21 +657,36 @@ static void vmbus_on_msg_dpc(unsigned long data) + void *page_addr = hv_context.synic_message_page[cpu]; + struct hv_message *msg = (struct hv_message *)page_addr + + VMBUS_MESSAGE_SINT; ++ struct vmbus_channel_message_header *hdr; ++ struct vmbus_channel_message_table_entry *entry; + struct onmessage_work_context *ctx; + + while (1) { +- if (msg->header.message_type == HVMSG_NONE) { ++ if (msg->header.message_type == HVMSG_NONE) + /* no msg */ + break; +- } else { ++ ++ hdr = (struct vmbus_channel_message_header *)msg->u.payload; ++ ++ if (hdr->msgtype >= CHANNELMSG_COUNT) { ++ WARN_ONCE(1, "unknown msgtype=%d\n", hdr->msgtype); ++ goto msg_handled; ++ } ++ ++ entry = &channel_message_table[hdr->msgtype]; ++ if (entry->handler_type == VMHT_BLOCKING) { + ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); + if (ctx == NULL) + continue; ++ + INIT_WORK(&ctx->work, vmbus_onmessage_work); + memcpy(&ctx->msg, msg, sizeof(*msg)); ++ + queue_work(vmbus_connection.work_queue, &ctx->work); +- } ++ } else ++ entry->message_handler(hdr); + ++msg_handled: + msg->header.message_type = HVMSG_NONE; + + /* diff --git a/patches.suse/msft-hv-0788-hv-don-t-schedule-new-works-in-vmbus_onoffer-vmbus_o.patch b/patches.suse/msft-hv-0788-hv-don-t-schedule-new-works-in-vmbus_onoffer-vmbus_o.patch new file mode 100644 index 0000000000..49b5d8fe88 --- /dev/null +++ b/patches.suse/msft-hv-0788-hv-don-t-schedule-new-works-in-vmbus_onoffer-vmbus_o.patch @@ -0,0 +1,295 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Fri, 27 Mar 2015 09:10:09 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv: don't schedule new works in vmbus_onoffer()/vmbus_onoffer_rescind() +Git-commit: d43e2fe7da320310834467a3fd87a10adb25a221 +References: fate#317533 + +Since the 2 fucntions can safely run in vmbus_connection.work_queue without +hang, we don't need to schedule new work items into the per-channel workqueue. + +Actally we can even remove the per-channel workqueue now -- we'll do it +in the next patch. + +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Cc: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 157 +++++++++------------------------------------- + drivers/hv/connection.c | 6 +- + drivers/hv/hyperv_vmbus.h | 2 +- + 3 files changed, 30 insertions(+), 135 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index 287f07b..d69864d 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -23,7 +23,6 @@ + #include <linux/kernel.h> + #include <linux/sched.h> + #include <linux/wait.h> +-#include <linux/delay.h> + #include <linux/mm.h> + #include <linux/slab.h> + #include <linux/list.h> +@@ -33,11 +32,6 @@ + + #include "hyperv_vmbus.h" + +-struct vmbus_rescind_work { +- struct work_struct work; +- struct vmbus_channel *channel; +-}; +- + /** + * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message + * @icmsghdrp: Pointer to msg header structure +@@ -134,20 +128,6 @@ fw_error: + + EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); + +-static void vmbus_sc_creation_cb(struct work_struct *work) +-{ +- struct vmbus_channel *newchannel = container_of(work, +- struct vmbus_channel, +- work); +- struct vmbus_channel *primary_channel = newchannel->primary_channel; +- +- /* +- * On entry sc_creation_callback has been already verified to +- * be non-NULL. +- */ +- primary_channel->sc_creation_callback(newchannel); +-} +- + /* + * alloc_channel - Allocate and initialize a vmbus channel object + */ +@@ -206,40 +186,6 @@ static void free_channel(struct vmbus_channel *channel) + queue_work(vmbus_connection.work_queue, &channel->work); + } + +-static void process_rescind_fn(struct work_struct *work) +-{ +- struct vmbus_rescind_work *rc_work; +- struct vmbus_channel *channel; +- struct device *dev; +- +- rc_work = container_of(work, struct vmbus_rescind_work, work); +- channel = rc_work->channel; +- +- /* +- * We have already acquired a reference on the channel +- * and so it cannot vanish underneath us. +- * It is possible (while very unlikely) that we may +- * get here while the processing of the initial offer +- * is still not complete. Deal with this situation by +- * just waiting until the channel is in the correct state. +- */ +- +- while (channel->work.func != release_channel) +- msleep(1000); +- +- if (channel->device_obj) { +- dev = get_device(&channel->device_obj->device); +- if (dev) { +- vmbus_device_unregister(channel->device_obj); +- put_device(dev); +- } +- } else { +- hv_process_channel_removal(channel, +- channel->offermsg.child_relid); +- } +- kfree(work); +-} +- + static void percpu_channel_enq(void *arg) + { + struct vmbus_channel *channel = arg; +@@ -302,46 +248,6 @@ void vmbus_free_channels(void) + } + } + +-static void vmbus_do_device_register(struct work_struct *work) +-{ +- struct hv_device *device_obj; +- int ret; +- unsigned long flags; +- struct vmbus_channel *newchannel = container_of(work, +- struct vmbus_channel, +- work); +- +- ret = vmbus_device_register(newchannel->device_obj); +- if (ret != 0) { +- pr_err("unable to add child device object (relid %d)\n", +- newchannel->offermsg.child_relid); +- spin_lock_irqsave(&vmbus_connection.channel_lock, flags); +- list_del(&newchannel->listentry); +- device_obj = newchannel->device_obj; +- newchannel->device_obj = NULL; +- spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); +- +- if (newchannel->target_cpu != get_cpu()) { +- put_cpu(); +- smp_call_function_single(newchannel->target_cpu, +- percpu_channel_deq, newchannel, true); +- } else { +- percpu_channel_deq(newchannel); +- put_cpu(); +- } +- +- kfree(device_obj); +- if (!newchannel->rescind) { +- free_channel(newchannel); +- return; +- } +- } +- /* +- * The next state for this channel is to be freed. +- */ +- INIT_WORK(&newchannel->work, release_channel); +-} +- + /* + * vmbus_process_offer - Process the offer by creating a channel/device + * associated with this offer +@@ -410,19 +316,8 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + + newchannel->state = CHANNEL_OPEN_STATE; + channel->num_sc++; +- if (channel->sc_creation_callback != NULL) { +- /* +- * We need to invoke the sub-channel creation +- * callback; invoke this in a seperate work +- * context since we are currently running on +- * the global work context in which we handle +- * messages from the host. +- */ +- INIT_WORK(&newchannel->work, +- vmbus_sc_creation_cb); +- queue_work(newchannel->controlwq, +- &newchannel->work); +- } ++ if (channel->sc_creation_callback != NULL) ++ channel->sc_creation_callback(newchannel); + + return; + } +@@ -453,13 +348,13 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) + * Add the new device to the bus. This will kick off device-driver + * binding which eventually invokes the device driver's AddDevice() + * method. +- * Invoke this call on the per-channel work context. +- * Until we return from this function, rescind offer message +- * cannot be processed as we are running on the global message +- * handling work. + */ +- INIT_WORK(&newchannel->work, vmbus_do_device_register); +- queue_work(newchannel->controlwq, &newchannel->work); ++ if (vmbus_device_register(newchannel->device_obj) != 0) { ++ pr_err("unable to add child device object (relid %d)\n", ++ newchannel->offermsg.child_relid); ++ kfree(newchannel->device_obj); ++ goto err_deq_chan; ++ } + return; + + err_deq_chan: +@@ -613,31 +508,35 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) + { + struct vmbus_channel_rescind_offer *rescind; + struct vmbus_channel *channel; +- struct vmbus_rescind_work *rc_work; ++ unsigned long flags; ++ struct device *dev; + + rescind = (struct vmbus_channel_rescind_offer *)hdr; +- channel = relid2channel(rescind->child_relid, true); ++ channel = relid2channel(rescind->child_relid); + + if (channel == NULL) { + hv_process_channel_removal(NULL, rescind->child_relid); + return; + } + +- /* +- * We have acquired a reference on the channel and have posted +- * the rescind state. Perform further cleanup in a work context +- * that is different from the global work context in which +- * we process messages from the host (we are currently executing +- * on that global context. +- */ +- rc_work = kzalloc(sizeof(struct vmbus_rescind_work), GFP_KERNEL); +- if (!rc_work) { +- pr_err("Unable to allocate memory for rescind processing "); +- return; ++ spin_lock_irqsave(&channel->lock, flags); ++ channel->rescind = true; ++ spin_unlock_irqrestore(&channel->lock, flags); ++ ++ if (channel->device_obj) { ++ /* ++ * We will have to unregister this device from the ++ * driver core. ++ */ ++ dev = get_device(&channel->device_obj->device); ++ if (dev) { ++ vmbus_device_unregister(channel->device_obj); ++ put_device(dev); ++ } ++ } else { ++ hv_process_channel_removal(channel, ++ channel->offermsg.child_relid); + } +- rc_work->channel = channel; +- INIT_WORK(&rc_work->work, process_rescind_fn); +- schedule_work(&rc_work->work); + } + + /* +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index 8bcd307..583d7d4 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -270,7 +270,7 @@ static struct vmbus_channel *pcpu_relid2channel(u32 relid) + * relid2channel - Get the channel object given its + * child relative id (ie channel id) + */ +-struct vmbus_channel *relid2channel(u32 relid, bool rescind) ++struct vmbus_channel *relid2channel(u32 relid) + { + struct vmbus_channel *channel; + struct vmbus_channel *found_channel = NULL; +@@ -282,8 +282,6 @@ struct vmbus_channel *relid2channel(u32 relid, bool rescind) + list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { + if (channel->offermsg.child_relid == relid) { + found_channel = channel; +- if (rescind) +- found_channel->rescind = true; + break; + } else if (!list_empty(&channel->sc_list)) { + /* +@@ -294,8 +292,6 @@ struct vmbus_channel *relid2channel(u32 relid, bool rescind) + sc_list); + if (cur_sc->offermsg.child_relid == relid) { + found_channel = cur_sc; +- if (rescind) +- found_channel->rescind = true; + break; + } + } +diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h +index f40a5a9..887287a 100644 +--- a/drivers/hv/hyperv_vmbus.h ++++ b/drivers/hv/hyperv_vmbus.h +@@ -715,7 +715,7 @@ void vmbus_device_unregister(struct hv_device *device_obj); + /* VmbusChildDeviceDestroy( */ + /* struct hv_device *); */ + +-struct vmbus_channel *relid2channel(u32 relid, bool rescind); ++struct vmbus_channel *relid2channel(u32 relid); + + void vmbus_free_channels(void); + diff --git a/patches.suse/msft-hv-0789-hv-remove-the-per-channel-workqueue.patch b/patches.suse/msft-hv-0789-hv-remove-the-per-channel-workqueue.patch new file mode 100644 index 0000000000..8a85b42485 --- /dev/null +++ b/patches.suse/msft-hv-0789-hv-remove-the-per-channel-workqueue.patch @@ -0,0 +1,90 @@ +From: Dexuan Cui <decui@microsoft.com> +Date: Fri, 27 Mar 2015 09:10:10 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv: remove the per-channel workqueue +Git-commit: aadc3780f31865edc84c587ab718a33a8eeeb09d +References: fate#317533 + +It's not necessary any longer, since we can safely run the blocking +message handlers in vmbus_connection.work_queue now. + +Signed-off-by: Dexuan Cui <decui@microsoft.com> +Cc: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/channel_mgmt.c | 30 +----------------------------- + include/linux/hyperv.h | 3 --- + 2 files changed, 1 insertion(+), 32 deletions(-) + +diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c +index d69864d..0eeb1b3 100644 +--- a/drivers/hv/channel_mgmt.c ++++ b/drivers/hv/channel_mgmt.c +@@ -147,43 +147,15 @@ static struct vmbus_channel *alloc_channel(void) + INIT_LIST_HEAD(&channel->sc_list); + INIT_LIST_HEAD(&channel->percpu_list); + +- channel->controlwq = alloc_workqueue("hv_vmbus_ctl/%d", WQ_MEM_RECLAIM, +- 1, channel->id); +- if (!channel->controlwq) { +- kfree(channel); +- return NULL; +- } +- + return channel; + } + + /* +- * release_hannel - Release the vmbus channel object itself +- */ +-static void release_channel(struct work_struct *work) +-{ +- struct vmbus_channel *channel = container_of(work, +- struct vmbus_channel, +- work); +- +- destroy_workqueue(channel->controlwq); +- +- kfree(channel); +-} +- +-/* + * free_channel - Release the resources used by the vmbus channel object + */ + static void free_channel(struct vmbus_channel *channel) + { +- +- /* +- * We have to release the channel's workqueue/thread in the vmbus's +- * workqueue/thread context +- * ie we can't destroy ourselves. +- */ +- INIT_WORK(&channel->work, release_channel); +- queue_work(vmbus_connection.work_queue, &channel->work); ++ kfree(channel); + } + + static void percpu_channel_enq(void *arg) +diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h +index 80e444b..902c37a 100644 +--- a/include/linux/hyperv.h ++++ b/include/linux/hyperv.h +@@ -653,8 +653,6 @@ struct vmbus_channel { + + struct hv_device *device_obj; + +- struct work_struct work; +- + enum vmbus_channel_state state; + + struct vmbus_channel_offer_channel offermsg; +@@ -675,7 +673,6 @@ struct vmbus_channel { + struct hv_ring_buffer_info outbound; /* send to parent */ + struct hv_ring_buffer_info inbound; /* receive from parent */ + spinlock_t inbound_lock; +- struct workqueue_struct *controlwq; + + struct vmbus_close_msg close_msg; + diff --git a/patches.suse/msft-hv-0790-Drivers-hv-hv_balloon-do-not-online-pages-in-offline.patch b/patches.suse/msft-hv-0790-Drivers-hv-hv_balloon-do-not-online-pages-in-offline.patch new file mode 100644 index 0000000000..a91339657f --- /dev/null +++ b/patches.suse/msft-hv-0790-Drivers-hv-hv_balloon-do-not-online-pages-in-offline.patch @@ -0,0 +1,51 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Mar 2015 09:10:11 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: do not online pages in offline blocks +Git-commit: d6cbd2c3a3db437708520c66f285c69ef028ac1f +References: fate#317533 + +Currently we add memory in 128Mb blocks but the request from host can be +aligned differently. In such case we add a partially backed block and +when this block goes online we skip onlining pages which are not backed +(hv_online_page() callback serves this purpose). When we receive next +request for the same host add region we online pages which were not backed +before with hv_bring_pgs_online(). However, we don't check if the the block +in question was onlined and online this tail unconditionally. This is bad as +we avoid all online_pages() logic: these pages are not accounted, we don't +send notifications (and hv_balloon is not the only receiver of them),... +And, first of all, nobody asked as to online these pages. Solve the issue by +checking if the last previously backed page was onlined and onlining the tail +only in case it was. + +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 014256a..99afef9 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -778,7 +778,17 @@ static unsigned long handle_pg_range(unsigned long pg_start, + pgs_ol = has->ha_end_pfn - start_pfn; + if (pgs_ol > pfn_cnt) + pgs_ol = pfn_cnt; +- hv_bring_pgs_online(start_pfn, pgs_ol); ++ ++ /* ++ * Check if the corresponding memory block is already ++ * online by checking its last previously backed page. ++ * In case it is we need to bring rest (which was not ++ * backed previously) online too. ++ */ ++ if (start_pfn > has->start_pfn && ++ !PageReserved(pfn_to_page(start_pfn - 1))) ++ hv_bring_pgs_online(start_pfn, pgs_ol); ++ + has->covered_end_pfn += pgs_ol; + pfn_cnt -= pgs_ol; + } diff --git a/patches.suse/msft-hv-0791-Drivers-hv-hv_balloon-eliminate-jumps-in-piecewiese-.patch b/patches.suse/msft-hv-0791-Drivers-hv-hv_balloon-eliminate-jumps-in-piecewiese-.patch new file mode 100644 index 0000000000..a81567e713 --- /dev/null +++ b/patches.suse/msft-hv-0791-Drivers-hv-hv_balloon-eliminate-jumps-in-piecewiese-.patch @@ -0,0 +1,57 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Mar 2015 09:10:12 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: eliminate jumps in piecewiese linear floor function +Git-commit: 7fb0e1a65075a871c58cbcf8c877d1f9ae5cd83c +References: fate#317533 + +Commit 79208c57da53 ("Drivers: hv: hv_balloon: Make adjustments in computing +the floor") was inacurate as it introduced a jump in our piecewiese linear +'floor' function: + +At 2048MB we have: +Left limit: +104 + 2048/8 = 360 +Right limit: +256 + 2048/16 = 384 (so the right value is 232) + +We now have to make an adjustment at 8192 boundary: +232 + 8192/16 = 744 +512 + 8192/32 = 768 (so the right value is 488) + +Suggested-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 99afef9..4f5323c 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -976,8 +976,8 @@ static unsigned long compute_balloon_floor(void) + * 128 72 (1/2) + * 512 168 (1/4) + * 2048 360 (1/8) +- * 8192 768 (1/16) +- * 32768 1536 (1/32) ++ * 8192 744 (1/16) ++ * 32768 1512 (1/32) + */ + if (totalram_pages < MB2PAGES(128)) + min_pages = MB2PAGES(8) + (totalram_pages >> 1); +@@ -986,9 +986,9 @@ static unsigned long compute_balloon_floor(void) + else if (totalram_pages < MB2PAGES(2048)) + min_pages = MB2PAGES(104) + (totalram_pages >> 3); + else if (totalram_pages < MB2PAGES(8192)) +- min_pages = MB2PAGES(256) + (totalram_pages >> 4); ++ min_pages = MB2PAGES(232) + (totalram_pages >> 4); + else +- min_pages = MB2PAGES(512) + (totalram_pages >> 5); ++ min_pages = MB2PAGES(488) + (totalram_pages >> 5); + #undef MB2PAGES + return min_pages; + } diff --git a/patches.suse/msft-hv-0792-Drivers-hv-hv_balloon-survive-ballooning-request-wit.patch b/patches.suse/msft-hv-0792-Drivers-hv-hv_balloon-survive-ballooning-request-wit.patch new file mode 100644 index 0000000000..2d9cf584af --- /dev/null +++ b/patches.suse/msft-hv-0792-Drivers-hv-hv_balloon-survive-ballooning-request-wit.patch @@ -0,0 +1,123 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Fri, 27 Mar 2015 09:10:13 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: survive ballooning request with num_pages=0 +Git-commit: 0a1a86ac046091d7228c9f3a283dea5be96275dd +References: fate#317533 + +... and simplify alloc_balloon_pages() interface by removing redundant +alloc_error from it. + +If we happen to enter balloon_up() with balloon_wrk.num_pages = 0 we will enter +infinite 'while (!done)' loop as alloc_balloon_pages() will be always returning +0 and not setting alloc_error. We will also be sending a meaningless message to +the host on every iteration. + +The 'alloc_unit == 1 && alloc_error -> num_ballooned == 0' change and +alloc_error elimination requires a special comment. We do alloc_balloon_pages() +with 2 different alloc_unit values and there are 4 different +alloc_balloon_pages() results, let's check them all. + +alloc_unit = 512: +1) num_ballooned = 0, alloc_error = 0: we do 'alloc_unit=1' and retry pre- and + post-patch. +2) num_ballooned > 0, alloc_error = 0: we check 'num_ballooned == num_pages' + and act accordingly, pre- and post-patch. +3) num_ballooned > 0, alloc_error > 0: we report this chunk and remain within + the loop, no changes here. +4) num_ballooned = 0, alloc_error > 0: we do 'alloc_unit=1' and retry pre- and + post-patch. + +alloc_unit = 1: +1) num_ballooned = 0, alloc_error = 0: this can happen in two cases: when we + passed 'num_pages=0' to alloc_balloon_pages() or when there was no space in + bl_resp to place a single response. The second option is not possible as + bl_resp is of PAGE_SIZE size and single response 'union dm_mem_page_range' is + 8 bytes, but the first one is (in theory, I think that Hyper-V host never + places such requests). Pre-patch code loops forever, post-patch code sends + a reply with more_pages = 0 and finishes. +2) num_ballooned > 0, alloc_error = 0: we ran out of space in bl_resp, we + report partial success and remain within the loop, no changes pre- and + post-patch. +3) num_ballooned > 0, alloc_error > 0: pre-patch code finishes, post-patch code + does one more try and if there is no progress (we finish with + 'num_ballooned = 0') we finish. So we try a bit harder with this patch. +4) num_ballooned = 0, alloc_error > 0: both pre- and post-patch code enter + 'more_pages = 0' branch and finish. + +So this patch has two real effects: +1) We reply with an empty response to 'num_pages=0' request. +2) We try a bit harder on alloc_unit=1 allocations (and reply with an empty + tail reply in case we fail). + +An empty reply should be supported by host as we were able to send it even with +pre-patch code when we were not able to allocate a single page. + +Suggested-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 19 ++++++------------- + 1 file changed, 6 insertions(+), 13 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 4f5323c..74312c8 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1081,9 +1081,9 @@ static void free_balloon_pages(struct hv_dynmem_device *dm, + + + +-static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages, +- struct dm_balloon_response *bl_resp, int alloc_unit, +- bool *alloc_error) ++static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages, ++ struct dm_balloon_response *bl_resp, ++ int alloc_unit) + { + int i = 0; + struct page *pg; +@@ -1104,11 +1104,8 @@ static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages, + __GFP_NOMEMALLOC | __GFP_NOWARN, + get_order(alloc_unit << PAGE_SHIFT)); + +- if (!pg) { +- *alloc_error = true; ++ if (!pg) + return i * alloc_unit; +- } +- + + dm->num_pages_ballooned += alloc_unit; + +@@ -1140,7 +1137,6 @@ static void balloon_up(struct work_struct *dummy) + struct dm_balloon_response *bl_resp; + int alloc_unit; + int ret; +- bool alloc_error; + bool done = false; + int i; + struct sysinfo val; +@@ -1173,18 +1169,15 @@ static void balloon_up(struct work_struct *dummy) + + + num_pages -= num_ballooned; +- alloc_error = false; + num_ballooned = alloc_balloon_pages(&dm_device, num_pages, +- bl_resp, alloc_unit, +- &alloc_error); ++ bl_resp, alloc_unit); + + if (alloc_unit != 1 && num_ballooned == 0) { + alloc_unit = 1; + continue; + } + +- if ((alloc_unit == 1 && alloc_error) || +- (num_ballooned == num_pages)) { ++ if (num_ballooned == 0 || num_ballooned == num_pages) { + bl_resp->more_pages = 0; + done = true; + dm_device.state = DM_INITIALIZED; diff --git a/patches.suse/msft-hv-0793-hv_vmbus-Add-gradually-increased-delay-for-retries-i.patch b/patches.suse/msft-hv-0793-hv_vmbus-Add-gradually-increased-delay-for-retries-i.patch new file mode 100644 index 0000000000..1d01da2027 --- /dev/null +++ b/patches.suse/msft-hv-0793-hv_vmbus-Add-gradually-increased-delay-for-retries-i.patch @@ -0,0 +1,54 @@ +From: Haiyang Zhang <haiyangz@microsoft.com> +Date: Fri, 27 Mar 2015 09:10:14 -0700 +Patch-mainline: v4.1-rc1 +Subject: hv_vmbus: Add gradually increased delay for retries in vmbus_post_msg() +Git-commit: e1c0d82dab4a4605d3bd1968436f030dfed4a829 +References: fate#317533 + +Most of the retries can be done within a millisecond successfully, so we +sleep 1ms before the first retry, then gradually increase the retry +interval to 2^n with max value of 2048ms. Doing so, we will have shorter +overall delay time, because most of the cases succeed within 1-2 attempts. + +Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> +Reviewed-by: K. Y. Srinivasan <kys@microsoft.com> +Reviewed-by: Dexuan Cui <decui@microsoft.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/connection.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c +index 583d7d4..b27220a 100644 +--- a/drivers/hv/connection.c ++++ b/drivers/hv/connection.c +@@ -422,6 +422,7 @@ int vmbus_post_msg(void *buffer, size_t buflen) + union hv_connection_id conn_id; + int ret = 0; + int retries = 0; ++ u32 msec = 1; + + conn_id.asu32 = 0; + conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; +@@ -431,7 +432,7 @@ int vmbus_post_msg(void *buffer, size_t buflen) + * insufficient resources. Retry the operation a couple of + * times before giving up. + */ +- while (retries < 10) { ++ while (retries < 20) { + ret = hv_post_message(conn_id, 1, buffer, buflen); + + switch (ret) { +@@ -454,7 +455,9 @@ int vmbus_post_msg(void *buffer, size_t buflen) + } + + retries++; +- msleep(1000); ++ msleep(msec); ++ if (msec < 2048) ++ msec *= 2; + } + return ret; + } diff --git a/patches.suse/msft-hv-0794-Drivers-hv-hv_balloon-correctly-handle-val.freeram-n.patch b/patches.suse/msft-hv-0794-Drivers-hv-hv_balloon-correctly-handle-val.freeram-n.patch new file mode 100644 index 0000000000..715b4b0122 --- /dev/null +++ b/patches.suse/msft-hv-0794-Drivers-hv-hv_balloon-correctly-handle-val.freeram-n.patch @@ -0,0 +1,39 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Tue, 31 Mar 2015 11:16:40 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: correctly handle val.freeram<num_pages case +Git-commit: ba0c444153889a9b672974d85a4a57a8eeb49fe3 +References: fate#317533 + +'Drivers: hv: hv_balloon: refuse to balloon below the floor' fix does not +correctly handle the case when val.freeram < num_pages as val.freeram is +__kernel_ulong_t and the 'val.freeram - num_pages' value will be a huge +positive value instead of being negative. + +Usually host doesn't ask us to balloon more than val.freeram but in case +he have a memory hog started after we post the last pressure report we +can get into troubles. + +Suggested-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Reviewed-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 74312c8..4052ad8 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1155,7 +1155,7 @@ static void balloon_up(struct work_struct *dummy) + floor = compute_balloon_floor(); + + /* Refuse to balloon below the floor, keep the 2M granularity. */ +- if (val.freeram - num_pages < floor) { ++ if (val.freeram < num_pages || val.freeram - num_pages < floor) { + num_pages = val.freeram > floor ? (val.freeram - floor) : 0; + num_pages -= num_pages % PAGES_IN_2M; + } diff --git a/patches.suse/msft-hv-0795-Drivers-hv-hv_balloon-correctly-handle-num_pages-INT.patch b/patches.suse/msft-hv-0795-Drivers-hv-hv_balloon-correctly-handle-num_pages-INT.patch new file mode 100644 index 0000000000..36b4b6ff83 --- /dev/null +++ b/patches.suse/msft-hv-0795-Drivers-hv-hv_balloon-correctly-handle-num_pages-INT.patch @@ -0,0 +1,58 @@ +From: Vitaly Kuznetsov <vkuznets@redhat.com> +Date: Tue, 31 Mar 2015 11:16:41 -0700 +Patch-mainline: v4.1-rc1 +Subject: Drivers: hv: hv_balloon: correctly handle num_pages>INT_MAX case +Git-commit: 797f88c987b02a8de8d4fac94ec2877b92ec35a2 +References: fate#317533 + +balloon_wrk.num_pages is __u32 and it comes from host in struct dm_balloon +where it is also __u32. We, however, use 'int' in balloon_up() and in case +we happen to receive num_pages>INT_MAX request we'll end up allocating zero +pages as 'num_pages < alloc_unit' check in alloc_balloon_pages() will pass. +Change num_pages type to unsigned int. + +In real life ballooning request come with num_pages in [512, 32768] range so +this is more a future-proof/cleanup. + +Reported-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> +Reviewed-by: Laszlo Ersek <lersek@redhat.com> +Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +Acked-by: <ohering@suse.de> +--- + drivers/hv/hv_balloon.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c +index 4052ad8..cb5b7dc 100644 +--- a/drivers/hv/hv_balloon.c ++++ b/drivers/hv/hv_balloon.c +@@ -1081,11 +1081,12 @@ static void free_balloon_pages(struct hv_dynmem_device *dm, + + + +-static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages, +- struct dm_balloon_response *bl_resp, +- int alloc_unit) ++static unsigned int alloc_balloon_pages(struct hv_dynmem_device *dm, ++ unsigned int num_pages, ++ struct dm_balloon_response *bl_resp, ++ int alloc_unit) + { +- int i = 0; ++ unsigned int i = 0; + struct page *pg; + + if (num_pages < alloc_unit) +@@ -1132,8 +1133,8 @@ static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages, + + static void balloon_up(struct work_struct *dummy) + { +- int num_pages = dm_device.balloon_wrk.num_pages; +- int num_ballooned = 0; ++ unsigned int num_pages = dm_device.balloon_wrk.num_pages; ++ unsigned int num_ballooned = 0; + struct dm_balloon_response *bl_resp; + int alloc_unit; + int ret; diff --git a/patches.suse/suse-hv-module-unload.patch b/patches.suse/suse-hv-module-unload.patch new file mode 100644 index 0000000000..a43cd0efab --- /dev/null +++ b/patches.suse/suse-hv-module-unload.patch @@ -0,0 +1,52 @@ +Subject: hv: no rmmod for hv_vmbus and hv_utils +From: <ohering@suse.de> +Patch-mainline: Never + +The base kernel lacks support for proper rmmod/insmod. + +--- + drivers/hv/hv_util.c | 3 ++- + drivers/hv/vmbus_drv.c | 3 ++- + 2 files changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/hv/hv_util.c ++++ b/drivers/hv/hv_util.c +@@ -433,15 +433,16 @@ static int __init init_hyperv_utils(void + return vmbus_driver_register(&util_drv); + } + ++#if 0 + static void exit_hyperv_utils(void) + { + pr_info("De-Registered HyperV Utility Driver\n"); + + vmbus_driver_unregister(&util_drv); + } ++#endif + + module_init(init_hyperv_utils); +-module_exit(exit_hyperv_utils); + + MODULE_DESCRIPTION("Hyper-V Utilities"); + MODULE_LICENSE("GPL"); +--- a/drivers/hv/vmbus_drv.c ++++ b/drivers/hv/vmbus_drv.c +@@ -962,6 +962,7 @@ cleanup: + return ret; + } + ++#if 0 + static void __exit vmbus_exit(void) + { + int cpu; +@@ -978,9 +979,9 @@ static void __exit vmbus_exit(void) + hv_cpu_hotplug_quirk(false); + vmbus_disconnect(); + } ++#endif + + + MODULE_LICENSE("GPL"); + + subsys_initcall(hv_acpi_init); +-module_exit(vmbus_exit); diff --git a/series.conf b/series.conf index a56ca91993..46e1392a30 100644 --- a/series.conf +++ b/series.conf @@ -21828,6 +21828,58 @@ patches.suse/msft-hv-0739-hyperv-match-wait_for_completion_timeout-return-type.patch patches.suse/msft-hv-0740-hyperv-Fix-the-error-processing-in-netvsc_send.patch patches.suse/msft-hv-0741-hyperv-fix-sparse-warnings.patch + patches.suse/msft-hv-0742-hyperv-Implement-netvsc_get_channels-ethool-op.patch + patches.suse/msft-hv-0743-Drivers-hv-vmbus-prevent-cpu-offlining-on-newer-hype.patch + patches.suse/msft-hv-0744-Drivers-hv-vmbus-rename-channel-work-queues.patch + patches.suse/msft-hv-0745-Drivers-hv-vmbus-avoid-double-kfree-for-device_obj.patch + patches.suse/msft-hv-0746-Drivers-hv-vmbus-teardown-hv_vmbus_con-workqueue-and.patch + patches.suse/msft-hv-0747-drivers-hv-vmbus-Teardown-synthetic-interrupt-contro.patch + patches.suse/msft-hv-0748-Drivers-hv-vmbus-Teardown-clockevent-devices-on-modu.patch + patches.suse/msft-hv-0749-hv-hv_util-move-vmbus_open-to-a-later-place.patch + patches.suse/msft-hv-0750-hv-vmbus_post_msg-retry-the-hypercall-on-some-transi.patch + patches.suse/msft-hv-0751-hv-vmbus_open-reset-the-channel-state-on-ENOMEM.patch + patches.suse/msft-hv-0752-hv-channel-match-var-type-to-return-type-of-wait_for.patch + patches.suse/msft-hv-0753-hv-channel_mgmt-match-var-type-to-return-type-of-wai.patch + patches.suse/msft-hv-0754-hv-hv_balloon-match-var-type-to-return-type-of-wait_.patch + patches.suse/msft-hv-0755-Drivers-hv-vmbus-Fix-a-bug-in-the-error-path-in-vmbu.patch + patches.suse/msft-hv-0756-Drivers-hv-vmbus-Add-support-for-the-NetworkDirect-G.patch + patches.suse/msft-hv-0757-Drivers-hv-vmbus-Properly-handle-child-device-remove.patch + patches.suse/msft-hv-0758-Drivers-hv-vmbus-Introduce-a-function-to-remove-a-re.patch + patches.suse/msft-hv-0759-Drivers-hv-vmbus-Handle-both-rescind-and-offer-messa.patch + patches.suse/msft-hv-0760-Drivers-hv-vmbus-Remove-the-channel-from-the-channel.patch + patches.suse/msft-hv-0761-Drivers-hv-util-On-device-remove-close-the-channel-a.patch + patches.suse/msft-hv-0762-Drivers-hv-vmbus-Get-rid-of-some-unnecessary-message.patch + patches.suse/msft-hv-0763-Drivers-hv-hv_balloon-eliminate-the-trylock-path-in-.patch + patches.suse/msft-hv-0764-Drivers-hv-hv_balloon-report-offline-pages-as-being-.patch + patches.suse/msft-hv-0765-Drivers-hv-hv_balloon-refuse-to-balloon-below-the-fl.patch + patches.suse/msft-hv-0766-Drivers-hv-vmbus-Add-support-for-VMBus-panic-notifie.patch + patches.suse/msft-hv-0767-Drivers-hv-vmbus-Use-a-round-robin-algorithm-for-pic.patch + patches.suse/msft-hv-0768-Drivers-hv-vmbus-Suport-an-API-to-send-pagebuffers-w.patch + patches.suse/msft-hv-0769-Drivers-hv-vmbus-Suport-an-API-to-send-packet-with-a.patch + patches.suse/msft-hv-0770-mei-bus-can-be-static.patch + patches.suse/msft-hv-0771-hyperv-hyperv_fb-match-wait_for_completion_timeout-r.patch + patches.suse/msft-hv-0772-Drivers-hv-vmbus-Perform-device-register-in-the-per-.patch + patches.suse/msft-hv-0773-Drivers-hv-hv_balloon-keep-locks-balanced-on-add_mem.patch + patches.suse/msft-hv-0774-Drivers-hv-hv_balloon-don-t-lose-memory-when-onlinin.patch + patches.suse/msft-hv-0775-Drivers-hv-vmbus-Correcting-truncation-error-for-con.patch + patches.suse/msft-hv-0776-hv-vmbus-missing-curly-braces-in-vmbus_process_offer.patch + patches.suse/msft-hv-0778-Drivers-hv-vmbus-Fix-a-bug-in-rescind-processing-in-.patch + patches.suse/msft-hv-0779-hv-hypervvssd-call-endmntent-before-call-setmntent-a.patch + patches.suse/msft-hv-0780-Drivers-hv-vmbus-Export-the-vmbus_sendpacket_pagebuf.patch + patches.suse/msft-hv-0781-Drivers-hv-vmbus-Fix-a-siganlling-host-signalling-is.patch + patches.suse/msft-hv-0782-Drivers-hv-vmbus-Don-t-wait-after-requesting-offers.patch + patches.suse/msft-hv-0784-hv_netvsc-remove-vmbus_are_subchannels_present-in-rn.patch + patches.suse/msft-hv-0785-hv_netvsc-Cleanup-the-test-for-freeing-skb-when-we-u.patch + patches.suse/msft-hv-0787-hv-run-non-blocking-message-handlers-in-the-dispatch.patch + patches.suse/msft-hv-0788-hv-don-t-schedule-new-works-in-vmbus_onoffer-vmbus_o.patch + patches.suse/msft-hv-0789-hv-remove-the-per-channel-workqueue.patch + patches.suse/msft-hv-0790-Drivers-hv-hv_balloon-do-not-online-pages-in-offline.patch + patches.suse/msft-hv-0791-Drivers-hv-hv_balloon-eliminate-jumps-in-piecewiese-.patch + patches.suse/msft-hv-0792-Drivers-hv-hv_balloon-survive-ballooning-request-wit.patch + patches.suse/msft-hv-0793-hv_vmbus-Add-gradually-increased-delay-for-retries-i.patch + patches.suse/msft-hv-0794-Drivers-hv-hv_balloon-correctly-handle-val.freeram-n.patch + patches.suse/msft-hv-0795-Drivers-hv-hv_balloon-correctly-handle-num_pages-INT.patch + patches.suse/msft-hv-0801-scsi-storvsc-Increase-the-ring-buffer-size.patch patches.suse/msft-hv-0802-scsi-storvsc-Size-the-queue-depth-based-on-the-ringb.patch patches.suse/msft-hv-0803-scsi-storvsc-Always-send-on-the-selected-outgoing-ch.patch @@ -21847,6 +21899,7 @@ patches.suse/suse-hv-bind-hv_blkkvsc-to-hv_storvsc.patch patches.suse/suse-hv-bind-hv_mouse-to-hid-hyperv.patch patches.suse/suse-hv-HV_DRV_VERSION.patch + patches.suse/suse-hv-module-unload.patch ######################################################## |