acpi: add utility to test for device dma coherency
Subsystems (3)
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
@@ -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
@@ -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
Quoted 32 lines · Mark Salter
ACPI 5.1 adds a
_CCAobject 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
_CCAobject and return the coherency attribute if found.Signed-off-by Mark Salter <[email protected]>--- drivers/acpi/utils.c | 26 ++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ 2 files changed, 28 insertions(+)drivers/acpi/utils.c +7
-0@@ -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.
Quoted 37 lines · Rafael J. Wysocki
Quoted 36 lines · Mark Salter
ACPI 5.1 adds a
_CCAobject 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
_CCAobject and return the coherency attribute if found.Signed-off-by Mark Salter <[email protected]>--- drivers/acpi/utils.c | 26 ++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ 2 files changed, 28 insertions(+)drivers/acpi/utils.c +11
-0@@ -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
@@ -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 ; }
Hi,
Quoted 39 lines
From: Mark Salter [mailto:[email protected]]
Sent: Wednesday, September 10, 2014 4:58 AMACPI 5.1 adds a
_CCAobject 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
_CCAobject and return the coherency attribute if found.Signed-off-by Mark Salter <[email protected]>--- drivers/acpi/utils.c | 26 ++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ 2 files changed, 28 insertions(+)drivers/acpi/utils.c +11
-0@@ -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@@ -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