Merge tag 'hyperv-fixes-signed-20220407' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / hv / vmbus_drv.c
index 60ee8b3..14de170 100644 (file)
@@ -77,8 +77,8 @@ static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
 
        /*
         * Hyper-V should be notified only once about a panic.  If we will be
-        * doing hyperv_report_panic_msg() later with kmsg data, don't do
-        * the notification here.
+        * doing hv_kmsg_dump() with kmsg data later, don't do the notification
+        * here.
         */
        if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
            && hyperv_report_reg()) {
@@ -100,8 +100,8 @@ static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
 
        /*
         * Hyper-V should be notified only once about a panic.  If we will be
-        * doing hyperv_report_panic_msg() later with kmsg data, don't do
-        * the notification here.
+        * doing hv_kmsg_dump() with kmsg data later, don't do the notification
+        * here.
         */
        if (hyperv_report_reg())
                hyperv_report_panic(regs, val, true);
@@ -920,6 +920,21 @@ static int vmbus_probe(struct device *child_device)
        return ret;
 }
 
+/*
+ * vmbus_dma_configure -- Configure DMA coherence for VMbus device
+ */
+static int vmbus_dma_configure(struct device *child_device)
+{
+       /*
+        * On ARM64, propagate the DMA coherence setting from the top level
+        * VMbus ACPI device to the child VMbus device being added here.
+        * On x86/x64 coherence is assumed and these calls have no effect.
+        */
+       hv_setup_dma_ops(child_device,
+               device_get_dma_attr(&hv_acpi_dev->dev) == DEV_DMA_COHERENT);
+       return 0;
+}
+
 /*
  * vmbus_remove - Remove a vmbus device
  */
@@ -1040,6 +1055,7 @@ static struct bus_type  hv_bus = {
        .remove =               vmbus_remove,
        .probe =                vmbus_probe,
        .uevent =               vmbus_uevent,
+       .dma_configure =        vmbus_dma_configure,
        .dev_groups =           vmbus_dev_groups,
        .drv_groups =           vmbus_drv_groups,
        .bus_groups =           vmbus_bus_groups,
@@ -1546,14 +1562,20 @@ static int vmbus_bus_init(void)
        if (ret)
                goto err_connect;
 
+       if (hv_is_isolation_supported())
+               sysctl_record_panic_msg = 0;
+
        /*
         * Only register if the crash MSRs are available
         */
        if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
                u64 hyperv_crash_ctl;
                /*
-                * Sysctl registration is not fatal, since by default
-                * reporting is enabled.
+                * Panic message recording (sysctl_record_panic_msg)
+                * is enabled by default in non-isolated guests and
+                * disabled by default in isolated guests; the panic
+                * message recording won't be available in isolated
+                * guests should the following registration fail.
                 */
                hv_ctl_table_hdr = register_sysctl_table(hv_root_table);
                if (!hv_ctl_table_hdr)
@@ -2097,6 +2119,10 @@ int vmbus_device_register(struct hv_device *child_device_obj)
        child_device_obj->device.parent = &hv_acpi_dev->dev;
        child_device_obj->device.release = vmbus_device_release;
 
+       child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
+       child_device_obj->device.dma_mask = &child_device_obj->dma_mask;
+       dma_set_mask(&child_device_obj->device, DMA_BIT_MASK(64));
+
        /*
         * Register with the LDM. This will kick off the driver/device
         * binding...which will eventually call vmbus_match() and vmbus_probe()
@@ -2122,9 +2148,6 @@ int vmbus_device_register(struct hv_device *child_device_obj)
        }
        hv_debug_add_dev_dir(child_device_obj);
 
-       child_device_obj->device.dma_parms = &child_device_obj->dma_parms;
-       child_device_obj->device.dma_mask = &child_device_obj->dma_mask;
-       dma_set_mask(&child_device_obj->device, DMA_BIT_MASK(64));
        return 0;
 
 err_kset_unregister:
@@ -2428,6 +2451,21 @@ static int vmbus_acpi_add(struct acpi_device *device)
 
        hv_acpi_dev = device;
 
+       /*
+        * Older versions of Hyper-V for ARM64 fail to include the _CCA
+        * method on the top level VMbus device in the DSDT. But devices
+        * are hardware coherent in all current Hyper-V use cases, so fix
+        * up the ACPI device to behave as if _CCA is present and indicates
+        * hardware coherence.
+        */
+       ACPI_COMPANION_SET(&device->dev, device);
+       if (IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED) &&
+           device_get_dma_attr(&device->dev) == DEV_DMA_NOT_SUPPORTED) {
+               pr_info("No ACPI _CCA found; assuming coherent device I/O\n");
+               device->flags.cca_seen = true;
+               device->flags.coherent_dma = true;
+       }
+
        result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
                                        vmbus_walk_resources, NULL);
 
@@ -2780,10 +2818,15 @@ static void __exit vmbus_exit(void)
        if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
                kmsg_dump_unregister(&hv_kmsg_dumper);
                unregister_die_notifier(&hyperv_die_block);
-               atomic_notifier_chain_unregister(&panic_notifier_list,
-                                                &hyperv_panic_block);
        }
 
+       /*
+        * The panic notifier is always registered, hence we should
+        * also unconditionally unregister it here as well.
+        */
+       atomic_notifier_chain_unregister(&panic_notifier_list,
+                                        &hyperv_panic_block);
+
        free_page((unsigned long)hv_panic_page);
        unregister_sysctl_table(hv_ctl_table_hdr);
        hv_ctl_table_hdr = NULL;