Skip to contentSkip to conversation

acpi: add utility to test for device dma coherency

PATCH In review Mark Salter 3 participants 4 messages Sep 9, 2014 – Sep 10, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 acpi: add utility to test for device dma coherency

ACPI 5.1 adds a _CCA object to indicate memory coherency of a bus master device. It is an integer with zero meaning non-coherent and one meaning coherent. This attribute may be inherited from a parent device. It may also be missing entirely, in which case, an architecture-specific default is assumed.

This patch adds a utility function to parse a device handle (and its parents) for a _CCA object and return the coherency attribute if found.

---
 drivers/acpi/utils.c    | 26 ++++++++++++++++++++++++++
 include/acpi/acpi_bus.h |  2 ++
 2 files changed, 28 insertions(+)
drivers/acpi/utils.c +26 -0
index 07c8c5a..aec9656 100644
@@ -698,3 +698,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
 	return false;
 }
 EXPORT_SYMBOL(acpi_check_dsm);
+
+/**
+ * acpi_check_coherency - check for memory coherency of a device
+ * @handle: ACPI device handle
+ * @val:    Pointer to returned value
+ *
+ * Search a device and its parents for a _CCA method and return
+ * its value.
+ */
+acpi_status acpi_check_coherency(acpi_handle handle, int *val)
+{
+	unsigned long long data;
+	acpi_status status;
+
+	do {
+		status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
+		if (!ACPI_FAILURE(status)) {
+			*val = data;
+			break;
+		}
+		status = acpi_get_parent(handle, &handle);
+	} while (!ACPI_FAILURE(status));
+
+	return status;
+}
+EXPORT_SYMBOL(acpi_check_coherency);
include/acpi/acpi_bus.h +2 -0
index bcfd808..b97f09d 100644
@@ -68,6 +68,8 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs);
 union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
 			int rev, int func, union acpi_object *argv4);
 
+acpi_status acpi_check_coherency(acpi_handle handle, int *val);
+
 static inline union acpi_object *
 acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
 			union acpi_object *argv4, acpi_object_type type)
Signature · 1 line
1.8.3.1
#1 lore raw
Quoted 32 lines · Mark Salter

ACPI 5.1 adds a _CCA object to indicate memory coherency of a bus master device. It is an integer with zero meaning non-coherent and one meaning coherent. This attribute may be inherited from a parent device. It may also be missing entirely, in which case, an architecture-specific default is assumed.

This patch adds a utility function to parse a device handle (and its parents) for a _CCA object and return the coherency attribute if found.

---
 drivers/acpi/utils.c    | 26 ++++++++++++++++++++++++++
 include/acpi/acpi_bus.h |  2 ++
 2 files changed, 28 insertions(+)
drivers/acpi/utils.c +7 -0
index 07c8c5a..aec9656 100644
@@ -698,3 +698,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
 	return false;
 }
 EXPORT_SYMBOL(acpi_check_dsm);
+
+/**
+ * acpi_check_coherency - check for memory coherency of a device
+ * @handle: ACPI device handle
+ * @val:    Pointer to returned value
+ *
+ * Search a device and its parents for a _CCA method and return

drivers/acpi/utils.c bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) · line 717

Quoted 10 lines
drivers/acpi/utils.c +10 -0
+ * its value.
+ */
+acpi_status acpi_check_coherency(acpi_handle handle, int *val)
+{
+	unsigned long long data;
+	acpi_status status;
+
+	do {
+		status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
+		if (!ACPI_FAILURE(status)) {

We have an ACPI_SUCCESS() macro for that.

drivers/acpi/utils.c bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) · line 723

Quoted 6 lines
drivers/acpi/utils.c +6 -0
+			*val = data;
+			break;
+		}
+		status = acpi_get_parent(handle, &handle);
+	} while (!ACPI_FAILURE(status));
+

And here.

Anyway, how do you think this routine will be used? Do you have any particular use cases in mind?

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#2 lore raw
Quoted 37 lines · Rafael J. Wysocki
Quoted 36 lines · Mark Salter

ACPI 5.1 adds a _CCA object to indicate memory coherency of a bus master device. It is an integer with zero meaning non-coherent and one meaning coherent. This attribute may be inherited from a parent device. It may also be missing entirely, in which case, an architecture-specific default is assumed.

This patch adds a utility function to parse a device handle (and its parents) for a _CCA object and return the coherency attribute if found.

---
 drivers/acpi/utils.c    | 26 ++++++++++++++++++++++++++
 include/acpi/acpi_bus.h |  2 ++
 2 files changed, 28 insertions(+)
drivers/acpi/utils.c +11 -0
index 07c8c5a..aec9656 100644
@@ -698,3 +698,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
 	return false;
 }
 EXPORT_SYMBOL(acpi_check_dsm);
+
+/**
+ * acpi_check_coherency - check for memory coherency of a device
+ * @handle: ACPI device handle
+ * @val:    Pointer to returned value
+ *
+ * Search a device and its parents for a _CCA method and return
+ * its value.
+ */
+acpi_status acpi_check_coherency(acpi_handle handle, int *val)
+{
Quoted 8 lines

drivers/acpi/utils.c bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) · line 717

Quoted 6 lines
drivers/acpi/utils.c +6 -0
+	unsigned long long data;
+	acpi_status status;
+
+	do {
+		status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
+		if (!ACPI_FAILURE(status)) {

We have an ACPI_SUCCESS() macro for that.

ah, okay

Quoted 10 lines

drivers/acpi/utils.c bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) · line 723

Quoted 7 lines
drivers/acpi/utils.c +6 -0
+			*val = data;
+			break;
+		}
+		status = acpi_get_parent(handle, &handle);
+	} while (!ACPI_FAILURE(status));
+

And here.

Quoted 3 lines

Anyway, how do you think this routine will be used? Do you have any particular use cases in mind?

An arm64 kernel defaults to non-coherent dma ops. There is a platform and amba bus notifier in arm64/mm/dma-mapping.c which looks for a device-tree dma-coherent property. If found, the device is switched to using coherent dma ops. I'm thinking of doing something similar for ACPI in that same bus notifier:

arch/arm64/mm/dma-mapping.c +16 -0
index 4164c5a..f26dd78 100644
@@ -27,6 +27,7 @@
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 #include <linux/amba/bus.h>
+#include <linux/acpi.h>
 
 #include <asm/cacheflush.h>
 
@@ -319,6 +320,21 @@ static int dma_bus_notifier(struct notifier_block *nb,
 	if (of_property_read_bool(dev->of_node, "dma-coherent"))
 		set_dma_ops(dev, &coherent_swiotlb_dma_ops);
 
+#ifdef CONFIG_ACPI
+	if (ACPI_HANDLE(dev)) {
+		acpi_status status;
+		int coherent;
+
+		/*
+		 * Kernel defaults to noncoherent ops but ACPI 5.1 spec says arm64
+		 * defaults to coherent. Set coherent ops if _CCA not found or _CCA
+		 * found and non-zero.
+		 */
+		status =  acpi_check_coherency(ACPI_HANDLE(dev), &coherent);
+		if (ACPI_FAILURE(status) || coherent)
+			set_dma_ops(dev, &coherent_swiotlb_dma_ops);
+	}
+#endif
 	return NOTIFY_OK;
 }
 
#3 lore raw
In reply to Mark Salter

Hi,

Quoted 39 lines

From: Mark Salter [mailto:[email protected]]
Sent: Wednesday, September 10, 2014 4:58 AM

ACPI 5.1 adds a _CCA object to indicate memory coherency of a bus master device. It is an integer with zero meaning non-coherent and one meaning coherent. This attribute may be inherited from a parent device. It may also be missing entirely, in which case, an architecture-specific default is assumed.

This patch adds a utility function to parse a device handle (and its parents) for a _CCA object and return the coherency attribute if found.

---
 drivers/acpi/utils.c    | 26 ++++++++++++++++++++++++++
 include/acpi/acpi_bus.h |  2 ++
 2 files changed, 28 insertions(+)
drivers/acpi/utils.c +11 -0
index 07c8c5a..aec9656 100644
@@ -698,3 +698,29 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs)
 	return false;
 }
 EXPORT_SYMBOL(acpi_check_dsm);
+
+/**
+ * acpi_check_coherency - check for memory coherency of a device
+ * @handle: ACPI device handle
+ * @val:    Pointer to returned value
+ *
+ * Search a device and its parents for a _CCA method and return
+ * its value.
+ */
+acpi_status acpi_check_coherency(acpi_handle handle, int *val)
+{

drivers/acpi/utils.c bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) · line 721

Quoted 10 lines
drivers/acpi/utils.c +10 -0
+	unsigned long long data;
+	acpi_status status;
+
+	do {
+		status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
+		if (!ACPI_FAILURE(status)) {
+			*val = data;
+			break;
+		}
+		status = acpi_get_parent(handle, &handle);

Why do you need such a loop?
In ACPI specification 5.3 ACPI Namespace, there is such a statement:
Quote: "A name is located by finding the matching name in the current namespace, and then in the parent namespace." This searching rule should have already been implemented by ACPICA.

Thanks and best regards
-Lv

Quoted 20 lines
drivers/acpi/utils.c +5 -0
+	} while (!ACPI_FAILURE(status));
+
+	return status;
+}
+EXPORT_SYMBOL(acpi_check_coherency);
include/acpi/acpi_bus.h +2 -1
index bcfd808..b97f09d 100644
@@ -68,6 +68,8 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs);
 union acpi_object *acpi_evaluate_dsm(acpi_handle handle, const u8 *uuid,
 			int rev, int func, union acpi_object *argv4);
 
+acpi_status acpi_check_coherency(acpi_handle handle, int *val);
+
 static inline union acpi_object *
 acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func,
 			union acpi_object *argv4, acpi_object_type type)
--

1.8.3.1