diff mbox

[V3,1/5] ACPI / scan: Parse _CCA and setup device coherency

Message ID 1431045436-8690-2-git-send-email-Suravee.Suthikulpanit@amd.com (mailing list archive)
State Not Applicable
Delegated to: Herbert Xu
Headers show

Commit Message

Suravee Suthikulpanit May 8, 2015, 12:37 a.m. UTC
This patch implements support for ACPI _CCA object, which is introduced in
ACPIv5.1, can be used for specifying device DMA coherency attribute.

The parsing logic traverses device namespace to parse coherency
information, and stores it in acpi_device_flags. Then uses it to call
arch_setup_dma_ops() when creating each device enumerated in DSDT
during ACPI scan.

This patch also introduces acpi_dma_is_coherent(), which provides
an interface for device drivers to check the coherency information
similarly to the of_dma_is_coherent().

Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
---
 drivers/acpi/Kconfig         |  6 ++++++
 drivers/acpi/acpi_platform.c | 10 +++++++---
 drivers/acpi/scan.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h      | 32 +++++++++++++++++++++++++++++++-
 include/linux/acpi.h         | 10 ++++++++++
 5 files changed, 96 insertions(+), 4 deletions(-)

Comments

Rafael J. Wysocki May 8, 2015, 8:53 p.m. UTC | #1
On Thursday, May 07, 2015 07:37:12 PM Suravee Suthikulpanit wrote:
> This patch implements support for ACPI _CCA object, which is introduced in
> ACPIv5.1, can be used for specifying device DMA coherency attribute.
> 
> The parsing logic traverses device namespace to parse coherency
> information, and stores it in acpi_device_flags. Then uses it to call
> arch_setup_dma_ops() when creating each device enumerated in DSDT
> during ACPI scan.
> 
> This patch also introduces acpi_dma_is_coherent(), which provides
> an interface for device drivers to check the coherency information
> similarly to the of_dma_is_coherent().
> 
> Signed-off-by: Mark Salter <msalter@redhat.com>
> Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
> ---
>  drivers/acpi/Kconfig         |  6 ++++++
>  drivers/acpi/acpi_platform.c | 10 +++++++---
>  drivers/acpi/scan.c          | 42 ++++++++++++++++++++++++++++++++++++++++++
>  include/acpi/acpi_bus.h      | 32 +++++++++++++++++++++++++++++++-
>  include/linux/acpi.h         | 10 ++++++++++
>  5 files changed, 96 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> index ab2cbb5..7822149 100644
> --- a/drivers/acpi/Kconfig
> +++ b/drivers/acpi/Kconfig
> @@ -54,6 +54,12 @@ config ACPI_GENERIC_GSI
>  config ACPI_SYSTEM_POWER_STATES_SUPPORT
>  	bool
>  
> +config ACPI_CCA_REQUIRED
> +	bool
> +
> +config ARM64_SUPPORT_ACPI_CCA_ZERO

Hmm.  I guess the Arnd's idea what to simply use CONFIG_ARM64 directly instead
of adding this new option.

> +	bool
> +
>  config ACPI_SLEEP
>  	bool
>  	depends on SUSPEND || HIBERNATION
> diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
> index 4bf7559..a084ea0 100644
> --- a/drivers/acpi/acpi_platform.c
> +++ b/drivers/acpi/acpi_platform.c
> @@ -103,14 +103,18 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
>  	pdevinfo.res = resources;
>  	pdevinfo.num_res = count;
>  	pdevinfo.fwnode = acpi_fwnode_handle(adev);
> -	pdevinfo.dma_mask = DMA_BIT_MASK(32);
> +	pdevinfo.dma_mask = acpi_dma_is_supported(adev)? DMA_BIT_MASK(32): 0;

Spaces before the "?" and ":", please.

>  	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 (acpi_dma_is_supported(adev))
> +			arch_setup_dma_ops(&pdev->dev, 0, 0, NULL,
> +					   acpi_dma_is_coherent(adev));

OK, so I understand why this is needed, but ->

>  		dev_dbg(&adev->dev, "created platform device %s\n",
>  			dev_name(&pdev->dev));
> +	}
>  
>  	kfree(resources);
>  	return pdev;
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 849b699..0976dc2 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -11,6 +11,7 @@
>  #include <linux/kthread.h>
>  #include <linux/dmi.h>
>  #include <linux/nls.h>
> +#include <linux/dma-mapping.h>
>  
>  #include <asm/pgtable.h>
>  
> @@ -2137,6 +2138,46 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
>  	kfree(pnp->unique_id);
>  }
>  
> +static void acpi_init_coherency(struct acpi_device *adev)
> +{
> +	unsigned long long cca = 0;
> +	acpi_status status;
> +	struct acpi_device *parent = adev->parent;
> +	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
> +
> +	if (parent && parent->flags.cca_seen) {
> +		/*
> +		 * From ACPI spec, OSPM will ignore _CCA if an ancestor
> +		 * already saw one.
> +		 */
> +		adev->flags.cca_seen = 1;
> +		cca = acpi_dma_is_coherent(parent);
> +	} else {
> +		status = acpi_evaluate_integer(adev->handle, "_CCA",
> +					       NULL, &cca);
> +		if (ACPI_SUCCESS(status)) {
> +			adev->flags.cca_seen = 1;
> +		} else if (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED)) {
> +			/*
> +			 * If architecture does not specify that _CCA is
> +			 * required for DMA-able devices (e.g. x86),
> +			 * we default to _CCA=1.
> +			 */
> +			cca = 1;
> +		} else {
> +			acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &buffer);
> +			pr_debug("ACPI device %s is missing _CCA.\n",
> +				(char *) buffer.pointer);
> +			kfree(buffer.pointer);
> +		}
> +	}
> +
> +	adev->flags.is_coherent = cca;
> +	if (acpi_dma_is_supported(adev))
> +		arch_setup_dma_ops(&adev->dev, 0, 0, NULL,
> +				   acpi_dma_is_coherent(adev));

Why do we need this one?  adev->dev is not a device, it is an ACPI namespace
node representation.  Why do you want to set up DMA ops for it?

Would you set up DMA ops for a struct device_node?

> +}
> +
>  void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
>  			     int type, unsigned long long sta)
>  {
> @@ -2155,6 +2196,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
>  	device->flags.visited = false;
>  	device_initialize(&device->dev);
>  	dev_set_uevent_suppress(&device->dev, true);
> +	acpi_init_coherency(device);
>  }
>  
>  void acpi_device_add_finalize(struct acpi_device *device)
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 8de4fa9..17fb630 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -208,7 +208,9 @@ struct acpi_device_flags {
>  	u32 visited:1;
>  	u32 hotplug_notify:1;
>  	u32 is_dock_station:1;
> -	u32 reserved:23;
> +	u32 is_coherent:1;
> +	u32 cca_seen:1;
> +	u32 reserved:21;
>  };
>  
>  /* File System */
> @@ -380,6 +382,34 @@ struct acpi_device {
>  	void (*remove)(struct acpi_device *);
>  };
>  
> +static inline bool acpi_dma_is_supported(struct acpi_device *adev)
> +{
> +	/**
> +	 * Currently, we mainly support _CCA=1 (i.e. is_coherent=1)
> +	 * This should be equivalent to specifyig dma-coherent for
> +	 * a device in OF.
> +	 *
> +	 * For the case when _CCA=0 (i.e. is_coherent=0 && cca_seen=1),
> +	 * we would rely on arch-specific cache maintenance for
> +	 * non-coherence DMA operations if architecture specifies
> +	 * _XXX_SUPPORT_CCA_ZERO. Otherwise, we do not support
> +	 * DMA on this device and fallback to arch-specific default
> +	 * handling.
> +	 *
> +	 * For the case when _CCA is missing (i.e. cca_seen=0) but
> +	 * platform specifies ACPI_CCA_REQUIRED, we do not support DMA,
> +	 * and fallback to arch-specific default handling.
> +	 */
> +	return adev && (adev->flags.is_coherent ||
> +			(adev->flags.cca_seen &&
> +			 IS_ENABLED(CONFIG_ARM64_SUPPORT_ACPI_CCA_ZERO)));

So what exactly would be wrong with using IS_ENABLED(CONFIG_ARM64) here?

> +}
> +
> +static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
> +{
> +	return adev && adev->flags.is_coherent;
> +}
> +
>  static inline bool is_acpi_node(struct fwnode_handle *fwnode)
>  {
>  	return fwnode && fwnode->type == FWNODE_ACPI;
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index b10c4a6..baccf3b 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -583,6 +583,16 @@ static inline int acpi_device_modalias(struct device *dev,
>  	return -ENODEV;
>  }
>  
> +static inline bool acpi_dma_is_supported(struct acpi_device *adev)
> +{
> +	return false;
> +}
> +
> +static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
> +{
> +	return false;
> +}
> +
>  #define ACPI_PTR(_ptr)	(NULL)
>  
>  #endif	/* !CONFIG_ACPI */
>
Catalin Marinas May 11, 2015, 4:16 p.m. UTC | #2
On Fri, May 08, 2015 at 10:53:59PM +0200, Rafael J. Wysocki wrote:
> On Thursday, May 07, 2015 07:37:12 PM Suravee Suthikulpanit wrote:
> > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > index ab2cbb5..7822149 100644
> > --- a/drivers/acpi/Kconfig
> > +++ b/drivers/acpi/Kconfig
> > @@ -54,6 +54,12 @@ config ACPI_GENERIC_GSI
> >  config ACPI_SYSTEM_POWER_STATES_SUPPORT
> >  	bool
> >  
> > +config ACPI_CCA_REQUIRED
> > +	bool
> > +
> > +config ARM64_SUPPORT_ACPI_CCA_ZERO
> 
> Hmm.  I guess the Arnd's idea what to simply use CONFIG_ARM64 directly instead
> of adding this new option.

I agree.

> > +static inline bool acpi_dma_is_supported(struct acpi_device *adev)
> > +{
> > +	/**
> > +	 * Currently, we mainly support _CCA=1 (i.e. is_coherent=1)
> > +	 * This should be equivalent to specifyig dma-coherent for
> > +	 * a device in OF.
> > +	 *
> > +	 * For the case when _CCA=0 (i.e. is_coherent=0 && cca_seen=1),
> > +	 * we would rely on arch-specific cache maintenance for
> > +	 * non-coherence DMA operations if architecture specifies
> > +	 * _XXX_SUPPORT_CCA_ZERO. Otherwise, we do not support
> > +	 * DMA on this device and fallback to arch-specific default
> > +	 * handling.
> > +	 *
> > +	 * For the case when _CCA is missing (i.e. cca_seen=0) but
> > +	 * platform specifies ACPI_CCA_REQUIRED, we do not support DMA,
> > +	 * and fallback to arch-specific default handling.
> > +	 */
> > +	return adev && (adev->flags.is_coherent ||
> > +			(adev->flags.cca_seen &&
> > +			 IS_ENABLED(CONFIG_ARM64_SUPPORT_ACPI_CCA_ZERO)));
> 
> So what exactly would be wrong with using IS_ENABLED(CONFIG_ARM64) here?

I'm not sure I follow why we need to check for ARM64 here at all. Can we
not just have something like:

	return adev && (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED) ||
			adev->flags.cca_seen)
Rafael J. Wysocki May 12, 2015, 1:20 a.m. UTC | #3
On Monday, May 11, 2015 05:16:27 PM Catalin Marinas wrote:
> On Fri, May 08, 2015 at 10:53:59PM +0200, Rafael J. Wysocki wrote:
> > On Thursday, May 07, 2015 07:37:12 PM Suravee Suthikulpanit wrote:
> > > diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
> > > index ab2cbb5..7822149 100644
> > > --- a/drivers/acpi/Kconfig
> > > +++ b/drivers/acpi/Kconfig
> > > @@ -54,6 +54,12 @@ config ACPI_GENERIC_GSI
> > >  config ACPI_SYSTEM_POWER_STATES_SUPPORT
> > >  	bool
> > >  
> > > +config ACPI_CCA_REQUIRED
> > > +	bool
> > > +
> > > +config ARM64_SUPPORT_ACPI_CCA_ZERO
> > 
> > Hmm.  I guess the Arnd's idea what to simply use CONFIG_ARM64 directly instead
> > of adding this new option.
> 
> I agree.
> 
> > > +static inline bool acpi_dma_is_supported(struct acpi_device *adev)
> > > +{
> > > +	/**
> > > +	 * Currently, we mainly support _CCA=1 (i.e. is_coherent=1)
> > > +	 * This should be equivalent to specifyig dma-coherent for
> > > +	 * a device in OF.
> > > +	 *
> > > +	 * For the case when _CCA=0 (i.e. is_coherent=0 && cca_seen=1),
> > > +	 * we would rely on arch-specific cache maintenance for
> > > +	 * non-coherence DMA operations if architecture specifies
> > > +	 * _XXX_SUPPORT_CCA_ZERO. Otherwise, we do not support
> > > +	 * DMA on this device and fallback to arch-specific default
> > > +	 * handling.
> > > +	 *
> > > +	 * For the case when _CCA is missing (i.e. cca_seen=0) but
> > > +	 * platform specifies ACPI_CCA_REQUIRED, we do not support DMA,
> > > +	 * and fallback to arch-specific default handling.
> > > +	 */
> > > +	return adev && (adev->flags.is_coherent ||
> > > +			(adev->flags.cca_seen &&
> > > +			 IS_ENABLED(CONFIG_ARM64_SUPPORT_ACPI_CCA_ZERO)));
> > 
> > So what exactly would be wrong with using IS_ENABLED(CONFIG_ARM64) here?
> 
> I'm not sure I follow why we need to check for ARM64 here at all. Can we
> not just have something like:
> 
> 	return adev && (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED) ||
> 			adev->flags.cca_seen)

If _CCA returns 0 on non-ARM64, DMA is not supported for this device, so
in that case the function should return 'false' while the above check will
make it return 'true'.
Suravee Suthikulpanit May 12, 2015, 3:06 p.m. UTC | #4
On 5/11/2015 8:20 PM, Rafael J. Wysocki wrote:
> On Monday, May 11, 2015 05:16:27 PM Catalin Marinas wrote:
>> On Fri, May 08, 2015 at 10:53:59PM +0200, Rafael J. Wysocki wrote:
>>> On Thursday, May 07, 2015 07:37:12 PM Suravee Suthikulpanit wrote:
>>>> diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
>>>> index ab2cbb5..7822149 100644
>>>> --- a/drivers/acpi/Kconfig
>>>> +++ b/drivers/acpi/Kconfig
>>>> @@ -54,6 +54,12 @@ config ACPI_GENERIC_GSI
>>>>   config ACPI_SYSTEM_POWER_STATES_SUPPORT
>>>>   	bool
>>>>
>>>> +config ACPI_CCA_REQUIRED
>>>> +	bool
>>>> +
>>>> +config ARM64_SUPPORT_ACPI_CCA_ZERO
>>>
>>> Hmm.  I guess the Arnd's idea what to simply use CONFIG_ARM64 directly instead
>>> of adding this new option.
>>
>> I agree.
>>
>>>> +static inline bool acpi_dma_is_supported(struct acpi_device *adev)
>>>> +{
>>>> +	/**
>>>> +	 * Currently, we mainly support _CCA=1 (i.e. is_coherent=1)
>>>> +	 * This should be equivalent to specifyig dma-coherent for
>>>> +	 * a device in OF.
>>>> +	 *
>>>> +	 * For the case when _CCA=0 (i.e. is_coherent=0 && cca_seen=1),
>>>> +	 * we would rely on arch-specific cache maintenance for
>>>> +	 * non-coherence DMA operations if architecture specifies
>>>> +	 * _XXX_SUPPORT_CCA_ZERO. Otherwise, we do not support
>>>> +	 * DMA on this device and fallback to arch-specific default
>>>> +	 * handling.
>>>> +	 *
>>>> +	 * For the case when _CCA is missing (i.e. cca_seen=0) but
>>>> +	 * platform specifies ACPI_CCA_REQUIRED, we do not support DMA,
>>>> +	 * and fallback to arch-specific default handling.
>>>> +	 */
>>>> +	return adev && (adev->flags.is_coherent ||
>>>> +			(adev->flags.cca_seen &&
>>>> +			 IS_ENABLED(CONFIG_ARM64_SUPPORT_ACPI_CCA_ZERO)));
>>>
>>> So what exactly would be wrong with using IS_ENABLED(CONFIG_ARM64) here?
>>
>> I'm not sure I follow why we need to check for ARM64 here at all. Can we
>> not just have something like:
>>
>> 	return adev && (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED) ||
>> 			adev->flags.cca_seen)
>
> If _CCA returns 0 on non-ARM64, DMA is not supported for this device, so
> in that case the function should return 'false' while the above check will
> make it return 'true'.
>

The main idea is basically to allow architecture to decide if it wants 
to specify if it wants to support _CCA=0. Currently, there are two 
approaches.
1. Do not support and disable DMA
2. Support and default to what architecture would normally do for 
non-coherent DMA.

Since, ARM64 being the only platform, which supports ACPI and would 
support _CCA=0. I can just put CONFIG_ARM64 then as Arnd and Rafael 
mentioned.

Thanks,
Suravee


--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb5..7822149 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -54,6 +54,12 @@  config ACPI_GENERIC_GSI
 config ACPI_SYSTEM_POWER_STATES_SUPPORT
 	bool
 
+config ACPI_CCA_REQUIRED
+	bool
+
+config ARM64_SUPPORT_ACPI_CCA_ZERO
+	bool
+
 config ACPI_SLEEP
 	bool
 	depends on SUSPEND || HIBERNATION
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 4bf7559..a084ea0 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -103,14 +103,18 @@  struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
 	pdevinfo.res = resources;
 	pdevinfo.num_res = count;
 	pdevinfo.fwnode = acpi_fwnode_handle(adev);
-	pdevinfo.dma_mask = DMA_BIT_MASK(32);
+	pdevinfo.dma_mask = acpi_dma_is_supported(adev)? DMA_BIT_MASK(32): 0;
 	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 (acpi_dma_is_supported(adev))
+			arch_setup_dma_ops(&pdev->dev, 0, 0, NULL,
+					   acpi_dma_is_coherent(adev));
 		dev_dbg(&adev->dev, "created platform device %s\n",
 			dev_name(&pdev->dev));
+	}
 
 	kfree(resources);
 	return pdev;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 849b699..0976dc2 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -11,6 +11,7 @@ 
 #include <linux/kthread.h>
 #include <linux/dmi.h>
 #include <linux/nls.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/pgtable.h>
 
@@ -2137,6 +2138,46 @@  void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
 	kfree(pnp->unique_id);
 }
 
+static void acpi_init_coherency(struct acpi_device *adev)
+{
+	unsigned long long cca = 0;
+	acpi_status status;
+	struct acpi_device *parent = adev->parent;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	if (parent && parent->flags.cca_seen) {
+		/*
+		 * From ACPI spec, OSPM will ignore _CCA if an ancestor
+		 * already saw one.
+		 */
+		adev->flags.cca_seen = 1;
+		cca = acpi_dma_is_coherent(parent);
+	} else {
+		status = acpi_evaluate_integer(adev->handle, "_CCA",
+					       NULL, &cca);
+		if (ACPI_SUCCESS(status)) {
+			adev->flags.cca_seen = 1;
+		} else if (!IS_ENABLED(CONFIG_ACPI_CCA_REQUIRED)) {
+			/*
+			 * If architecture does not specify that _CCA is
+			 * required for DMA-able devices (e.g. x86),
+			 * we default to _CCA=1.
+			 */
+			cca = 1;
+		} else {
+			acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &buffer);
+			pr_debug("ACPI device %s is missing _CCA.\n",
+				(char *) buffer.pointer);
+			kfree(buffer.pointer);
+		}
+	}
+
+	adev->flags.is_coherent = cca;
+	if (acpi_dma_is_supported(adev))
+		arch_setup_dma_ops(&adev->dev, 0, 0, NULL,
+				   acpi_dma_is_coherent(adev));
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta)
 {
@@ -2155,6 +2196,7 @@  void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 	device->flags.visited = false;
 	device_initialize(&device->dev);
 	dev_set_uevent_suppress(&device->dev, true);
+	acpi_init_coherency(device);
 }
 
 void acpi_device_add_finalize(struct acpi_device *device)
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 8de4fa9..17fb630 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -208,7 +208,9 @@  struct acpi_device_flags {
 	u32 visited:1;
 	u32 hotplug_notify:1;
 	u32 is_dock_station:1;
-	u32 reserved:23;
+	u32 is_coherent:1;
+	u32 cca_seen:1;
+	u32 reserved:21;
 };
 
 /* File System */
@@ -380,6 +382,34 @@  struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool acpi_dma_is_supported(struct acpi_device *adev)
+{
+	/**
+	 * Currently, we mainly support _CCA=1 (i.e. is_coherent=1)
+	 * This should be equivalent to specifyig dma-coherent for
+	 * a device in OF.
+	 *
+	 * For the case when _CCA=0 (i.e. is_coherent=0 && cca_seen=1),
+	 * we would rely on arch-specific cache maintenance for
+	 * non-coherence DMA operations if architecture specifies
+	 * _XXX_SUPPORT_CCA_ZERO. Otherwise, we do not support
+	 * DMA on this device and fallback to arch-specific default
+	 * handling.
+	 *
+	 * For the case when _CCA is missing (i.e. cca_seen=0) but
+	 * platform specifies ACPI_CCA_REQUIRED, we do not support DMA,
+	 * and fallback to arch-specific default handling.
+	 */
+	return adev && (adev->flags.is_coherent ||
+			(adev->flags.cca_seen &&
+			 IS_ENABLED(CONFIG_ARM64_SUPPORT_ACPI_CCA_ZERO)));
+}
+
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return adev && adev->flags.is_coherent;
+}
+
 static inline bool is_acpi_node(struct fwnode_handle *fwnode)
 {
 	return fwnode && fwnode->type == FWNODE_ACPI;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index b10c4a6..baccf3b 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -583,6 +583,16 @@  static inline int acpi_device_modalias(struct device *dev,
 	return -ENODEV;
 }
 
+static inline bool acpi_dma_is_supported(struct acpi_device *adev)
+{
+	return false;
+}
+
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return false;
+}
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */