diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-15 08:06:26 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-15 08:06:26 -0700 |
| commit | 6a66840a68683d9361a9b31faf3bd8104428ad29 (patch) | |
| tree | 0033c284126c9ba3445b06bdb52281f9cd864d77 | |
| parent | 9fee1f650a0a9ea6fa7c0b26244a778dd92542d5 (diff) | |
| parent | dbc393f6f009a2bf7e4a22ef2d70b53f533f20f4 (diff) | |
Merge tag 'hyperv-fixes-signed-20261015' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull Hyper-V fixes from Wei Liu:
- Typo and comment fixes (Hemanth Selam, Jiangshan Yi)
- Update maintainers list (Wei Liu, Long Li)
- Two Hyper-V PCI driver fixes (Naman Jain, Sahil Chandna)
- Small fixes for core Hyper-V code (Hardik Garg, Michael Kelley,
Waiman Long)
* tag 'hyperv-fixes-signed-20261015' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
MAINTAINERS: drop KY from Hyper-V maintainers list
PCI: hv: Warn when wait_for_response() waits indefinitely
PCI: hv: Probe vPCI buses asynchronously
MAINTAINERS: remove myself from the Hyper-V entries
mshv_vtl: Check per-CPU register page before mmap
tools/hv: fix typo "retrive" in comment
Drivers: hv: vmbus: fix typo "substract" in comment
Drivers: hv: Don't reset VMBus connection state on error/exit paths
x86/hyperv: Avoid using per-cpu output page in hv_apicid_to_vp_index()
x86/hyperv: Fix stale comments after stimer message mode removal
Drivers: hv: Avoid infinite retry loop in init_vp_index()
| -rw-r--r-- | MAINTAINERS | 3 | ||||
| -rw-r--r-- | arch/x86/hyperv/hv_init.c | 7 | ||||
| -rw-r--r-- | drivers/hv/channel.c | 2 | ||||
| -rw-r--r-- | drivers/hv/channel_mgmt.c | 12 | ||||
| -rw-r--r-- | drivers/hv/connection.c | 1 | ||||
| -rw-r--r-- | drivers/hv/mshv_vtl_main.c | 3 | ||||
| -rw-r--r-- | drivers/hv/vmbus_drv.c | 19 | ||||
| -rw-r--r-- | drivers/pci/controller/pci-hyperv.c | 49 | ||||
| -rwxr-xr-x | tools/hv/hv_get_dns_info.sh | 2 |
9 files changed, 64 insertions, 34 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index f53047aa8d3c..c39194e896be 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8170,7 +8170,6 @@ F: drivers/gpu/drm/tiny/hx8357d.c DRM DRIVER FOR HYPERV SYNTHETIC VIDEO DEVICE M: Dexuan Cui <decui@microsoft.com> -M: Long Li <longli@microsoft.com> M: Saurabh Sengar <ssengar@linux.microsoft.com> L: linux-hyperv@vger.kernel.org L: dri-devel@lists.freedesktop.org @@ -12161,11 +12160,9 @@ S: Maintained F: drivers/media/i2c/hi847.c Hyper-V/Azure CORE AND DRIVERS -M: "K. Y. Srinivasan" <kys@microsoft.com> M: Haiyang Zhang <haiyangz@microsoft.com> M: Wei Liu <wei.liu@kernel.org> M: Dexuan Cui <decui@microsoft.com> -M: Long Li <longli@microsoft.com> L: linux-hyperv@vger.kernel.org S: Supported T: git git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c index 0b4a1c0b0b16..9900a5c59fd3 100644 --- a/arch/x86/hyperv/hv_init.c +++ b/arch/x86/hyperv/hv_init.c @@ -426,7 +426,7 @@ static void __init hv_stimer_setup_percpu_clockev(void) int ret; /* - * Continue afters errors in setting up stimer clockevents + * Continue after errors in setting up stimer clockevents * as we can run with the LAPIC timer as a fallback. */ ret = hv_stimer_alloc(false); @@ -434,7 +434,7 @@ static void __init hv_stimer_setup_percpu_clockev(void) pr_warn("stimer setup failed with error %d\n", ret); /* - * Still register the LAPIC timer to allows users + * Still register the LAPIC timer to allow users * to switch to LAPIC timer via /sys, if they want to. */ if (old_setup_percpu_clockev) @@ -727,7 +727,8 @@ int hv_apicid_to_vp_index(u32 apic_id) input->partition_id = HV_PARTITION_ID_SELF; input->apic_ids[0] = apic_id; - output = *this_cpu_ptr(hyperv_pcpu_output_arg); + /* Treat input as having 2 APIC IDs so output is 64-bit aligned */ + output = (void *)input + struct_size(input, apic_ids, 2); control = HV_HYPERCALL_REP_COMP_1 | HVCALL_GET_VP_INDEX_FROM_APIC_ID; status = hv_do_hypercall(control, input, output); diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 7e4cc6f55237..a0883ddf32e2 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -79,7 +79,7 @@ static inline u32 hv_ring_gpadl_send_hvpgoffset(u32 offset) * therefore leaving a (PAGE_SIZE - HV_HYP_PAGE_SIZE) gap. * * And to calculate the effective send offset in gpadl, we need to - * substract this gap. + * subtract this gap. */ return (offset - (PAGE_SIZE - HV_HYP_PAGE_SIZE)) >> HV_HYP_PAGE_SHIFT; } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index a044fd3b3c4e..c42def04ac41 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -752,13 +752,14 @@ static void init_vp_index(struct vmbus_channel *channel) u32 i, ncpu = num_online_cpus(); cpumask_var_t available_mask; struct cpumask *allocated_mask; + const struct cpumask *node_mask; const struct cpumask *hk_mask = housekeeping_cpumask(HK_TYPE_MANAGED_IRQ); u32 target_cpu; int numa_node; if (!perf_chn || !alloc_cpumask_var(&available_mask, GFP_KERNEL) || - cpumask_empty(hk_mask)) { + !cpumask_intersects(hk_mask, cpu_online_mask)) { /* * If the channel is not a performance critical * channel, bind it to VMBUS_CONNECT_CPU. @@ -780,14 +781,19 @@ static void init_vp_index(struct vmbus_channel *channel) next_numa_node_id = 0; continue; } - if (cpumask_empty(cpumask_of_node(numa_node))) + /* + * Try next NUMA node if current NUMA node has no CPU + * or doesn't contain any housekeeping CPU. + */ + node_mask = cpumask_of_node(numa_node); + if (!cpumask_intersects(node_mask, hk_mask)) continue; break; } allocated_mask = &hv_context.hv_numa_map[numa_node]; retry: - cpumask_xor(available_mask, allocated_mask, cpumask_of_node(numa_node)); + cpumask_xor(available_mask, allocated_mask, node_mask); cpumask_and(available_mask, available_mask, hk_mask); if (cpumask_empty(available_mask)) { diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 1ab3581b096a..818667ef9c74 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -346,7 +346,6 @@ int vmbus_connect(void) cleanup: pr_err("Unable to connect to host\n"); - vmbus_connection.conn_state = DISCONNECTED; vmbus_disconnect(); kfree(msginfo); diff --git a/drivers/hv/mshv_vtl_main.c b/drivers/hv/mshv_vtl_main.c index 6e3c11c68171..d8225242c73f 100644 --- a/drivers/hv/mshv_vtl_main.c +++ b/drivers/hv/mshv_vtl_main.c @@ -819,6 +819,9 @@ static vm_fault_t mshv_vtl_fault(struct vm_fault *vmf) return VM_FAULT_NOPAGE; } + if (!page) + return VM_FAULT_SIGBUS; + get_page(page); vmf->page = page; diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 5ebdbe24b5a1..4692687cdbf3 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -2923,23 +2923,19 @@ static void hv_crash_handler(struct pt_regs *regs) static int hv_synic_suspend(void *data) { /* - * When we reach here, all the non-boot CPUs have been offlined. - * If we're in a legacy configuration where stimer Direct Mode is - * not enabled, the stimers on the non-boot CPUs have been unbound - * in hv_synic_cleanup() -> hv_stimer_legacy_cleanup() -> - * hv_stimer_cleanup() -> clockevents_unbind_device(). + * When we reach here, all the non-boot CPUs have been offlined, + * and their stimers have been cleaned up by the cpuhp teardown + * callback hv_stimer_cleanup(). * * hv_synic_suspend() only runs on CPU0 with interrupts disabled. - * Here we do not call hv_stimer_legacy_cleanup() on CPU0 because: - * 1) it's unnecessary as interrupts remain disabled between - * syscore_suspend() and syscore_resume(): see create_image() and + * The stimer on CPU0 is not explicitly cleaned up here because: + * 1) it's harmless as interrupts remain disabled between + * syscore_suspend() and syscore_resume(), so the stimer cannot + * fire during this window: see create_image() and * resume_target_kernel() * 2) the stimer on CPU0 is automatically disabled later by * syscore_suspend() -> timekeeping_suspend() -> tick_suspend() -> ... * -> clockevents_shutdown() -> ... -> hv_ce_shutdown() - * 3) a warning would be triggered if we call - * clockevents_unbind_device(), which may sleep, in an - * interrupts-disabled context. */ hv_hyp_synic_disable_regs(0); @@ -3043,7 +3039,6 @@ static void __exit vmbus_exit(void) hv_remove_kexec_handler(); hv_remove_crash_handler(); - vmbus_connection.conn_state = DISCONNECTED; hv_stimer_global_cleanup(); vmbus_disconnect(); if (vmbus_irq == -1) diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 89816a2bd7cd..85d826f8f68d 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -1040,19 +1040,38 @@ static void put_pcichild(struct hv_pci_dev *hpdev) /* * There is no good way to get notified from vmbus_onoffer_rescind(), - * so let's use polling here, since this is not a hot path. + * so let's use polling here, since this is not a hot path. If + * wait_for_response() has been polling for 2 minutes + * without either a rescind or completion, add a warning. */ +#define PCI_RESPONSE_WARN_POLL_COUNT 1200 + static int wait_for_response(struct hv_device *hdev, - struct completion *comp) + struct completion *comp, + const char *msg_type) { + u64 counter = 0; + while (true) { if (hdev->channel->rescind) { dev_warn_once(&hdev->device, "The device is gone.\n"); return -ENODEV; } - if (wait_for_completion_timeout(comp, HZ / 10)) + counter++; + + if (wait_for_completion_timeout(comp, HZ / 10)) { + if (counter > PCI_RESPONSE_WARN_POLL_COUNT) + dev_warn(&hdev->device, + "Late %s completion arrived.\n", msg_type); break; + } + + if (counter == PCI_RESPONSE_WARN_POLL_COUNT) { + dev_err(&hdev->device, + "%s stuck waiting for response, relid = %u\n", + msg_type, hdev->channel->offermsg.child_relid); + } } return 0; @@ -1518,7 +1537,8 @@ static int hv_read_config_block(struct pci_dev *pdev, void *buf, if (ret) return ret; - ret = wait_for_response(hbus->hdev, &comp_pkt.comp_pkt.host_event); + ret = wait_for_response(hbus->hdev, &comp_pkt.comp_pkt.host_event, + "PCI_READ_BLOCK"); if (ret) return ret; @@ -1607,7 +1627,8 @@ static int hv_write_config_block(struct pci_dev *pdev, void *buf, if (ret) return ret; - ret = wait_for_response(hbus->hdev, &comp_pkt.host_event); + ret = wait_for_response(hbus->hdev, &comp_pkt.host_event, + "PCI_WRITE_BLOCK"); if (ret) return ret; @@ -2624,7 +2645,8 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus, if (ret) goto error; - if (wait_for_response(hbus->hdev, &comp_pkt.host_event)) + if (wait_for_response(hbus->hdev, &comp_pkt.host_event, + "PCI_QUERY_RESOURCE_REQUIREMENTS")) goto error; hpdev->desc = *desc; @@ -3256,7 +3278,8 @@ static int hv_pci_protocol_negotiation(struct hv_device *hdev, (unsigned long)pkt, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (!ret) - ret = wait_for_response(hdev, &comp_pkt.host_event); + ret = wait_for_response(hdev, &comp_pkt.host_event, + "PCI_QUERY_PROTOCOL_VERSION"); if (ret) { dev_err(&hdev->device, @@ -3476,7 +3499,8 @@ enter_d0_retry: (unsigned long)pkt, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (!ret) - ret = wait_for_response(hdev, &comp_pkt.host_event); + ret = wait_for_response(hdev, &comp_pkt.host_event, + "PCI_BUS_D0ENTRY"); if (ret) goto exit; @@ -3553,7 +3577,8 @@ static int hv_pci_query_relations(struct hv_device *hdev) ret = vmbus_sendpacket(hdev->channel, &message, sizeof(message), 0, VM_PKT_DATA_INBAND, 0); if (!ret) - ret = wait_for_response(hdev, &comp); + ret = wait_for_response(hdev, &comp, + "PCI_QUERY_BUS_RELATIONS"); /* * In the case of fast device addition/removal, it's possible that @@ -3644,7 +3669,8 @@ static int hv_send_resources_allocated(struct hv_device *hdev) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (!ret) - ret = wait_for_response(hdev, &comp_pkt.host_event); + ret = wait_for_response(hdev, &comp_pkt.host_event, + "PCI_RESOURCE_ASSIGNED"); if (ret) break; @@ -4155,6 +4181,9 @@ static struct hv_driver hv_pci_drv = { .remove = hv_pci_remove, .suspend = hv_pci_suspend, .resume = hv_pci_resume, + .driver = { + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static void __exit exit_hv_pci_drv(void) diff --git a/tools/hv/hv_get_dns_info.sh b/tools/hv/hv_get_dns_info.sh index 268521234d4b..288821565eee 100755 --- a/tools/hv/hv_get_dns_info.sh +++ b/tools/hv/hv_get_dns_info.sh @@ -1,6 +1,6 @@ #!/bin/sh -# This example script parses /etc/resolv.conf to retrive DNS information. +# This example script parses /etc/resolv.conf to retrieve DNS information. # In the interest of keeping the KVP daemon code free of distro specific # information; the kvp daemon code invokes this external script to gather # DNS information. |
