Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'hyperv-next-signed-20221009' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux

Pull hyperv updates from Wei Liu:

- Remove unnecessary delay while probing for VMBus (Stanislav
Kinsburskiy)

- Optimize vmbus_on_event (Saurabh Sengar)

- Fix a race in Hyper-V DRM driver (Saurabh Sengar)

- Miscellaneous clean-up patches from various people

* tag 'hyperv-next-signed-20221009' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux:
x86/hyperv: Replace kmap() with kmap_local_page()
drm/hyperv: Add ratelimit on error message
hyperv: simplify and rename generate_guest_id
Drivers: hv: vmbus: Split memcpy of flex-array
scsi: storvsc: remove an extraneous "to" in a comment
Drivers: hv: vmbus: Don't wait for the ACPI device upon initialization
Drivers: hv: vmbus: Use PCI_VENDOR_ID_MICROSOFT for better discoverability
Drivers: hv: vmbus: Fix kernel-doc
drm/hyperv: Don't overwrite dirt_needed value set by host
Drivers: hv: vmbus: Optimize vmbus_on_event

+40 -45
+1 -1
arch/arm64/hyperv/mshyperv.c
··· 38 38 return 0; 39 39 40 40 /* Setup the guest ID */ 41 - guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0); 41 + guest_id = hv_generate_guest_id(LINUX_VERSION_CODE); 42 42 hv_set_vpreg(HV_REGISTER_GUEST_OSID, guest_id); 43 43 44 44 /* Get the features and hints from Hyper-V */
+3 -3
arch/x86/hyperv/hv_init.c
··· 426 426 * 1. Register the guest ID 427 427 * 2. Enable the hypercall and register the hypercall page 428 428 */ 429 - guest_id = generate_guest_id(0, LINUX_VERSION_CODE, 0); 429 + guest_id = hv_generate_guest_id(LINUX_VERSION_CODE); 430 430 wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id); 431 431 432 432 /* Hyper-V requires to write guest os id via ghcb in SNP IVM. */ ··· 459 459 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); 460 460 461 461 pg = vmalloc_to_page(hv_hypercall_pg); 462 - dst = kmap(pg); 462 + dst = kmap_local_page(pg); 463 463 src = memremap(hypercall_msr.guest_physical_address << PAGE_SHIFT, PAGE_SIZE, 464 464 MEMREMAP_WB); 465 465 BUG_ON(!(src && dst)); 466 466 memcpy(dst, src, HV_HYP_PAGE_SIZE); 467 467 memunmap(src); 468 - kunmap(pg); 468 + kunmap_local(dst); 469 469 } else { 470 470 hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg); 471 471 wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
-2
drivers/gpu/drm/hyperv/hyperv_drm_drv.c
··· 142 142 if (ret) 143 143 drm_warn(dev, "Failed to update vram location.\n"); 144 144 145 - hv->dirt_needed = true; 146 - 147 145 ret = hyperv_mode_config_init(hv); 148 146 if (ret) 149 147 goto err_free_mmio;
+1 -1
drivers/gpu/drm/hyperv/hyperv_drm_proto.c
··· 208 208 VM_PKT_DATA_INBAND, 0); 209 209 210 210 if (ret) 211 - drm_err(&hv->dev, "Unable to send packet via vmbus\n"); 211 + drm_err_ratelimited(&hv->dev, "Unable to send packet via vmbus; error %d\n", ret); 212 212 213 213 return ret; 214 214 }
+14 -19
drivers/hv/connection.c
··· 431 431 void vmbus_on_event(unsigned long data) 432 432 { 433 433 struct vmbus_channel *channel = (void *) data; 434 - unsigned long time_limit = jiffies + 2; 434 + void (*callback_fn)(void *context); 435 435 436 436 trace_vmbus_on_event(channel); 437 437 438 438 hv_debug_delay_test(channel, INTERRUPT_DELAY); 439 - do { 440 - void (*callback_fn)(void *); 441 439 442 - /* A channel once created is persistent even when 443 - * there is no driver handling the device. An 444 - * unloading driver sets the onchannel_callback to NULL. 445 - */ 446 - callback_fn = READ_ONCE(channel->onchannel_callback); 447 - if (unlikely(callback_fn == NULL)) 448 - return; 440 + /* A channel once created is persistent even when 441 + * there is no driver handling the device. An 442 + * unloading driver sets the onchannel_callback to NULL. 443 + */ 444 + callback_fn = READ_ONCE(channel->onchannel_callback); 445 + if (unlikely(!callback_fn)) 446 + return; 449 447 450 - (*callback_fn)(channel->channel_callback_context); 448 + (*callback_fn)(channel->channel_callback_context); 451 449 452 - if (channel->callback_mode != HV_CALL_BATCHED) 453 - return; 450 + if (channel->callback_mode != HV_CALL_BATCHED) 451 + return; 454 452 455 - if (likely(hv_end_read(&channel->inbound) == 0)) 456 - return; 453 + if (likely(hv_end_read(&channel->inbound) == 0)) 454 + return; 457 455 458 - hv_begin_read(&channel->inbound); 459 - } while (likely(time_before(jiffies, time_limit))); 460 - 461 - /* The time limit (2 jiffies) has been reached */ 456 + hv_begin_read(&channel->inbound); 462 457 tasklet_schedule(&channel->callback_event); 463 458 } 464 459
+8 -12
drivers/hv/vmbus_drv.c
··· 46 46 47 47 static struct acpi_device *hv_acpi_dev; 48 48 49 - static struct completion probe_event; 50 - 51 49 static int hyperv_cpuhp_online; 52 50 53 51 static void *hv_panic_page; ··· 1130 1132 return; 1131 1133 1132 1134 INIT_WORK(&ctx->work, vmbus_onmessage_work); 1133 - memcpy(&ctx->msg, &msg_copy, sizeof(msg->header) + payload_size); 1135 + ctx->msg.header = msg_copy.header; 1136 + memcpy(&ctx->msg.payload, msg_copy.u.payload, payload_size); 1134 1137 1135 1138 /* 1136 1139 * The host can generate a rescind message while we ··· 1572 1573 } 1573 1574 1574 1575 /** 1575 - * __vmbus_child_driver_register() - Register a vmbus's driver 1576 + * __vmbus_driver_register() - Register a vmbus's driver 1576 1577 * @hv_driver: Pointer to driver structure you want to register 1577 1578 * @owner: owner module of the drv 1578 1579 * @mod_name: module name string ··· 2051 2052 child_device_obj->channel = channel; 2052 2053 guid_copy(&child_device_obj->dev_type, type); 2053 2054 guid_copy(&child_device_obj->dev_instance, instance); 2054 - child_device_obj->vendor_id = 0x1414; /* MSFT vendor ID */ 2055 + child_device_obj->vendor_id = PCI_VENDOR_ID_MICROSOFT; 2055 2056 2056 2057 return child_device_obj; 2057 2058 } ··· 2467 2468 ret_val = 0; 2468 2469 2469 2470 acpi_walk_err: 2470 - complete(&probe_event); 2471 2471 if (ret_val) 2472 2472 vmbus_acpi_remove(device); 2473 2473 return ret_val; ··· 2645 2647 .remove = vmbus_acpi_remove, 2646 2648 }, 2647 2649 .drv.pm = &vmbus_bus_pm, 2650 + .drv.probe_type = PROBE_FORCE_SYNCHRONOUS, 2648 2651 }; 2649 2652 2650 2653 static void hv_kexec_handler(void) ··· 2718 2719 2719 2720 static int __init hv_acpi_init(void) 2720 2721 { 2721 - int ret, t; 2722 + int ret; 2722 2723 2723 2724 if (!hv_is_hyperv_initialized()) 2724 2725 return -ENODEV; 2725 2726 2726 2727 if (hv_root_partition) 2727 2728 return 0; 2728 - 2729 - init_completion(&probe_event); 2730 2729 2731 2730 /* 2732 2731 * Get ACPI resources first. ··· 2734 2737 if (ret) 2735 2738 return ret; 2736 2739 2737 - t = wait_for_completion_timeout(&probe_event, 5*HZ); 2738 - if (t == 0) { 2739 - ret = -ETIMEDOUT; 2740 + if (!hv_acpi_dev) { 2741 + ret = -ENODEV; 2740 2742 goto cleanup; 2741 2743 } 2742 2744
+10 -1
drivers/scsi/storvsc_drv.c
··· 60 60 #define VMSTOR_PROTO_VERSION_WIN8_1 VMSTOR_PROTO_VERSION(6, 0) 61 61 #define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2) 62 62 63 + /* channel callback timeout in ms */ 64 + #define CALLBACK_TIMEOUT 2 65 + 63 66 /* Packet structure describing virtual storage requests. */ 64 67 enum vstor_packet_operation { 65 68 VSTOR_OPERATION_COMPLETE_IO = 1, ··· 1207 1204 struct hv_device *device; 1208 1205 struct storvsc_device *stor_device; 1209 1206 struct Scsi_Host *shost; 1207 + unsigned long time_limit = jiffies + msecs_to_jiffies(CALLBACK_TIMEOUT); 1210 1208 1211 1209 if (channel->primary_channel != NULL) 1212 1210 device = channel->primary_channel->device_obj; ··· 1227 1223 u64 rqst_id = desc->trans_id; 1228 1224 u32 minlen = rqst_id ? sizeof(struct vstor_packet) : 1229 1225 sizeof(enum vstor_packet_operation); 1226 + 1227 + if (unlikely(time_after(jiffies, time_limit))) { 1228 + hv_pkt_iter_close(channel); 1229 + return; 1230 + } 1230 1231 1231 1232 if (pktlen < minlen) { 1232 1233 dev_err(&device->device, ··· 2068 2059 err_out2: 2069 2060 /* 2070 2061 * Once we have connected with the host, we would need to 2071 - * to invoke storvsc_dev_remove() to rollback this state and 2062 + * invoke storvsc_dev_remove() to rollback this state and 2072 2063 * this call also frees up the stor_device; hence the jump around 2073 2064 * err_out1 label. 2074 2065 */
+3 -6
include/asm-generic/mshyperv.h
··· 105 105 } 106 106 107 107 /* Generate the guest OS identifier as described in the Hyper-V TLFS */ 108 - static inline __u64 generate_guest_id(__u64 d_info1, __u64 kernel_version, 109 - __u64 d_info2) 108 + static inline u64 hv_generate_guest_id(u64 kernel_version) 110 109 { 111 - __u64 guest_id = 0; 110 + u64 guest_id; 112 111 113 - guest_id = (((__u64)HV_LINUX_VENDOR_ID) << 48); 114 - guest_id |= (d_info1 << 48); 112 + guest_id = (((u64)HV_LINUX_VENDOR_ID) << 48); 115 113 guest_id |= (kernel_version << 16); 116 - guest_id |= d_info2; 117 114 118 115 return guest_id; 119 116 }