Skip to content

Commit 3720007

Browse files
kelleymhliuw
authored andcommitted
Drivers: hv: vmbus: Propagate VMbus coherence to each VMbus device
VMbus synthetic devices are not represented in the ACPI DSDT -- only the top level VMbus device is represented. As a result, on ARM64 coherence information in the _CCA method is not specified for synthetic devices, so they default to not hardware coherent. Drivers for some of these synthetic devices have been recently updated to use the standard DMA APIs, and they are incurring extra overhead of unneeded software coherence management. Fix this by propagating coherence information from the VMbus node in ACPI to the individual synthetic devices. There's no effect on x86/x64 where devices are always hardware coherent. Signed-off-by: Michael Kelley <mikelley@microsoft.com> Acked-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/1648138492-2191-2-git-send-email-mikelley@microsoft.com Signed-off-by: Wei Liu <wei.liu@kernel.org>
1 parent 792f232 commit 3720007

3 files changed

Lines changed: 43 additions & 0 deletions

File tree

drivers/hv/hv_common.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <linux/panic_notifier.h>
2121
#include <linux/ptrace.h>
2222
#include <linux/slab.h>
23+
#include <linux/dma-map-ops.h>
2324
#include <asm/hyperv-tlfs.h>
2425
#include <asm/mshyperv.h>
2526

@@ -216,6 +217,16 @@ bool hv_query_ext_cap(u64 cap_query)
216217
}
217218
EXPORT_SYMBOL_GPL(hv_query_ext_cap);
218219

220+
void hv_setup_dma_ops(struct device *dev, bool coherent)
221+
{
222+
/*
223+
* Hyper-V does not offer a vIOMMU in the guest
224+
* VM, so pass 0/NULL for the IOMMU settings
225+
*/
226+
arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
227+
}
228+
EXPORT_SYMBOL_GPL(hv_setup_dma_ops);
229+
219230
bool hv_is_hibernation_supported(void)
220231
{
221232
return !hv_root_partition && acpi_sleep_state_supported(ACPI_STATE_S4);

drivers/hv/vmbus_drv.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,21 @@ static int vmbus_probe(struct device *child_device)
920920
return ret;
921921
}
922922

923+
/*
924+
* vmbus_dma_configure -- Configure DMA coherence for VMbus device
925+
*/
926+
static int vmbus_dma_configure(struct device *child_device)
927+
{
928+
/*
929+
* On ARM64, propagate the DMA coherence setting from the top level
930+
* VMbus ACPI device to the child VMbus device being added here.
931+
* On x86/x64 coherence is assumed and these calls have no effect.
932+
*/
933+
hv_setup_dma_ops(child_device,
934+
device_get_dma_attr(&hv_acpi_dev->dev) == DEV_DMA_COHERENT);
935+
return 0;
936+
}
937+
923938
/*
924939
* vmbus_remove - Remove a vmbus device
925940
*/
@@ -1040,6 +1055,7 @@ static struct bus_type hv_bus = {
10401055
.remove = vmbus_remove,
10411056
.probe = vmbus_probe,
10421057
.uevent = vmbus_uevent,
1058+
.dma_configure = vmbus_dma_configure,
10431059
.dev_groups = vmbus_dev_groups,
10441060
.drv_groups = vmbus_drv_groups,
10451061
.bus_groups = vmbus_bus_groups,
@@ -2435,6 +2451,21 @@ static int vmbus_acpi_add(struct acpi_device *device)
24352451

24362452
hv_acpi_dev = device;
24372453

2454+
/*
2455+
* Older versions of Hyper-V for ARM64 fail to include the _CCA
2456+
* method on the top level VMbus device in the DSDT. But devices
2457+
* are hardware coherent in all current Hyper-V use cases, so fix
2458+
* up the ACPI device to behave as if _CCA is present and indicates
2459+
* hardware coherence.
2460+
*/
2461+
ACPI_COMPANION_SET(&device->dev, device);
2462+
if (IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED) &&
2463+
device_get_dma_attr(&device->dev) == DEV_DMA_NOT_SUPPORTED) {
2464+
pr_info("No ACPI _CCA found; assuming coherent device I/O\n");
2465+
device->flags.cca_seen = true;
2466+
device->flags.coherent_dma = true;
2467+
}
2468+
24382469
result = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
24392470
vmbus_walk_resources, NULL);
24402471

include/asm-generic/mshyperv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ bool hv_isolation_type_snp(void);
269269
u64 hv_ghcb_hypercall(u64 control, void *input, void *output, u32 input_size);
270270
void hyperv_cleanup(void);
271271
bool hv_query_ext_cap(u64 cap_query);
272+
void hv_setup_dma_ops(struct device *dev, bool coherent);
272273
void *hv_map_memory(void *addr, unsigned long size);
273274
void hv_unmap_memory(void *addr);
274275
#else /* CONFIG_HYPERV */

0 commit comments

Comments
 (0)