Hi Arnd, Mark,
On 2014-11-6 18:43, Arnd Bergmann wrote:
On Wednesday 05 November 2014 20:32:46 al.stone@linaro.org wrote:
From: Mark Salter msalter@redhat.com
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.
Signed-off-by: Mark Salter msalter@redhat.com
This should probably come before patch 26, so you can use it in that driver.
On a more general note, we also need to change the platform device creation path for ACPI to evaluate this and set the correct dma_map_ops based on it.
I rework this patch a little bit and add it to platform creation patch for ACPI, if it is ok to you, I will send it to ACPI maiilist.
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 if device is coherent.
Signed-off-by: Mark Salter msalter@redhat.com Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/acpi/utils.c | 31 +++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 2 ++ 2 files changed, 33 insertions(+)
diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 371ac12..10faba9 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -723,3 +723,34 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) return false; } EXPORT_SYMBOL(acpi_check_dsm); + +/** + * acpi_dma_is_coherent - check if device is coherent + * @handle: ACPI device handle + * + * Search a device and its parents for a _CCA method and check + * if device is coherent. + */ +bool acpi_dma_is_coherent(acpi_handle handle) +{ + unsigned long long data; + acpi_status status; + + do { + status = acpi_evaluate_integer(handle, "_CCA", NULL, &data); + if (ACPI_SUCCESS(status)) + break; + + status = acpi_get_parent(handle, &handle); + } while (ACPI_SUCCESS(status)); + + /* + * _CCA object returns 1 to indicate that a bus-master device + * supports hardware managed cache coherency + */ + if (data == 1) + return true; + + return false; +} +EXPORT_SYMBOL(acpi_dma_is_coherent); diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 7d1ce40..411a765 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -69,6 +69,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);
+bool acpi_dma_is_coherent(acpi_handle handle); + 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)
and I have another patch to use the function above:
use acpi_dma_is_coherent() when platform device is created.
Signed-off-by: Hanjun Guo hanjun.guo@linaro.org --- drivers/acpi/acpi_platform.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 24b918b..055ed15 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -105,12 +105,20 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev) pdevinfo.acpi_node.companion = adev; pdevinfo.dma_mask = DMA_BIT_MASK(32); pdev = platform_device_register_full(&pdevinfo); - if (IS_ERR(pdev)) + if (IS_ERR(pdev)) { dev_err(&adev->dev, "platform device creation failed: %ld\n", PTR_ERR(pdev)); - else + } else { + /* + * if _CCA (Cache Coherency Attribute) exist, call arch hook to setup + * dma coherent operations. + */ + if (acpi_dma_is_coherent(acpi_device_handle(adev))) + set_arch_dma_coherent_ops(&pdev->dev); + dev_dbg(&adev->dev, "created platform device %s\n", dev_name(&pdev->dev)); + }
kfree(resources); return pdev;