All of lore.kernel.org
 help / color / mirror / Atom feed
From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
To: <rjw@rjwysocki.net>, <lenb@kernel.org>, <catalin.marinas@arm.com>,
	<will.deacon@arm.com>, <thomas.lendacky@amd.com>,
	<herbert@gondor.apana.org.au>, <davem@davemloft.net>
Cc: al.stone@linaro.org, arnd@arndb.de, linaro-acpi@lists.linaro.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, leo.duran@amd.com,
	hanjun.guo@linaro.org,
	Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>,
	msalter@redhat.com, grant.likely@linaro.org,
	linux-arm-kernel@lists.infradead.org,
	linux-crypto@vger.kernel.org
Subject: [V2 PATCH 1/5] ACPI / scan: Parse _CCA and setup device coherency
Date: Tue, 5 May 2015 10:12:05 -0500	[thread overview]
Message-ID: <1430838729-21572-2-git-send-email-Suravee.Suthikulpanit@amd.com> (raw)
In-Reply-To: <1430838729-21572-1-git-send-email-Suravee.Suthikulpanit@amd.com>

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>
---
NOTE:
 * Since there seem to be conflict opinions regarding how
   architecture should handle _CCA=0. So, I am proposing the
   CONFIG_ARCH_SUPPORT_CCA_ZERO, which can be specified by
   for each architecture to define behavior of the ACPI
   scanning code when _CCA=0. Let me know if this is acceptable.

 drivers/acpi/Kconfig         |  6 +++++
 drivers/acpi/acpi_platform.c |  4 ++-
 drivers/acpi/scan.c          | 62 ++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h      | 11 +++++++-
 include/linux/acpi.h         |  5 ++++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb5..dd386e9 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_MUST_HAVE_CCA
+	bool
+
+config ACPI_SUPPORT_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..a6feca4 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -108,9 +108,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
 	if (IS_ERR(pdev))
 		dev_err(&adev->dev, "platform device creation failed: %ld\n",
 			PTR_ERR(pdev));
-	else
+	else {
+		acpi_setup_device_dma(adev, &pdev->dev);
 		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..ac33b29 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,66 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
 	kfree(pnp->unique_id);
 }
 
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev)
+{
+	int coherent = acpi_dma_is_coherent(adev);
+
+	/**
+	 * Currently, we only support DMA for devices that _CCA=1
+	 * since this seems to be the case on most ACPI platforms.
+	 *
+	 * 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 enables
+	 * CONFIG_ACPI_SUPPORT_CCA_ZERO.
+	 *
+	 * For the case when _CCA is missing but platform requires it
+	 * (i.e. is_coherent=0 && cca_seen=0), we do not call
+	 * arch_setup_dma_ops() and fallback to arch-specific default
+	 * handling.
+	 */
+	if (adev->flags.cca_seen) {
+		if (!coherent && !IS_ENABLED(CONFIG_ACPI_SUPPORT_CCA_ZERO))
+			return;
+		arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+	}
+}
+
+static void acpi_init_coherency(struct acpi_device *adev)
+{
+	unsigned long long cca = 0;
+	acpi_status status;
+	struct acpi_device *parent = adev->parent;
+
+	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_MUST_HAVE_CCA)) {
+			/*
+			 * If architecture does not specify that _CCA is
+			 * required for DMA-able devices (e.g. x86),
+			 * we default to _CCA=1.
+			 */
+			cca = 1;
+		} else {
+			dev_err(&adev->dev, FW_BUG
+				"DMA is not setup due to missing _CCA.\n");
+		}
+	}
+
+	adev->flags.is_coherent = cca;
+	acpi_setup_device_dma(adev, &adev->dev);
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta)
 {
@@ -2155,6 +2216,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..b804183 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,13 @@ struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return adev && adev->flags.is_coherent;
+}
+
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev);
+
 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..d14e777 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -583,6 +583,11 @@ static inline int acpi_device_modalias(struct device *dev,
 	return -ENODEV;
 }
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return false;
+}
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */
-- 
2.1.0

WARNING: multiple messages have this Message-ID (diff)
From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
To: rjw@rjwysocki.net, lenb@kernel.org, catalin.marinas@arm.com,
	will.deacon@arm.com, thomas.lendacky@amd.com,
	herbert@gondor.apana.org.au, davem@davemloft.net
Cc: al.stone@linaro.org, arnd@arndb.de, linaro-acpi@lists.linaro.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-acpi@vger.kernel.org, leo.duran@amd.com,
	hanjun.guo@linaro.org,
	Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>,
	msalter@redhat.com, grant.likely@linaro.org,
	linux-arm-kernel@lists.infradead.org,
	linux-crypto@vger.kernel.org
Subject: [V2 PATCH 1/5] ACPI / scan: Parse _CCA and setup device coherency
Date: Tue, 5 May 2015 10:12:05 -0500	[thread overview]
Message-ID: <1430838729-21572-2-git-send-email-Suravee.Suthikulpanit@amd.com> (raw)
In-Reply-To: <1430838729-21572-1-git-send-email-Suravee.Suthikulpanit@amd.com>

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>
---
NOTE:
 * Since there seem to be conflict opinions regarding how
   architecture should handle _CCA=0. So, I am proposing the
   CONFIG_ARCH_SUPPORT_CCA_ZERO, which can be specified by
   for each architecture to define behavior of the ACPI
   scanning code when _CCA=0. Let me know if this is acceptable.

 drivers/acpi/Kconfig         |  6 +++++
 drivers/acpi/acpi_platform.c |  4 ++-
 drivers/acpi/scan.c          | 62 ++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h      | 11 +++++++-
 include/linux/acpi.h         |  5 ++++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb5..dd386e9 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_MUST_HAVE_CCA
+	bool
+
+config ACPI_SUPPORT_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..a6feca4 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -108,9 +108,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
 	if (IS_ERR(pdev))
 		dev_err(&adev->dev, "platform device creation failed: %ld\n",
 			PTR_ERR(pdev));
-	else
+	else {
+		acpi_setup_device_dma(adev, &pdev->dev);
 		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..ac33b29 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,66 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
 	kfree(pnp->unique_id);
 }
 
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev)
+{
+	int coherent = acpi_dma_is_coherent(adev);
+
+	/**
+	 * Currently, we only support DMA for devices that _CCA=1
+	 * since this seems to be the case on most ACPI platforms.
+	 *
+	 * 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 enables
+	 * CONFIG_ACPI_SUPPORT_CCA_ZERO.
+	 *
+	 * For the case when _CCA is missing but platform requires it
+	 * (i.e. is_coherent=0 && cca_seen=0), we do not call
+	 * arch_setup_dma_ops() and fallback to arch-specific default
+	 * handling.
+	 */
+	if (adev->flags.cca_seen) {
+		if (!coherent && !IS_ENABLED(CONFIG_ACPI_SUPPORT_CCA_ZERO))
+			return;
+		arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+	}
+}
+
+static void acpi_init_coherency(struct acpi_device *adev)
+{
+	unsigned long long cca = 0;
+	acpi_status status;
+	struct acpi_device *parent = adev->parent;
+
+	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_MUST_HAVE_CCA)) {
+			/*
+			 * If architecture does not specify that _CCA is
+			 * required for DMA-able devices (e.g. x86),
+			 * we default to _CCA=1.
+			 */
+			cca = 1;
+		} else {
+			dev_err(&adev->dev, FW_BUG
+				"DMA is not setup due to missing _CCA.\n");
+		}
+	}
+
+	adev->flags.is_coherent = cca;
+	acpi_setup_device_dma(adev, &adev->dev);
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta)
 {
@@ -2155,6 +2216,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..b804183 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,13 @@ struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return adev && adev->flags.is_coherent;
+}
+
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev);
+
 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..d14e777 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -583,6 +583,11 @@ static inline int acpi_device_modalias(struct device *dev,
 	return -ENODEV;
 }
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return false;
+}
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */
-- 
2.1.0

WARNING: multiple messages have this Message-ID (diff)
From: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
To: <rjw@rjwysocki.net>, <lenb@kernel.org>, <catalin.marinas@arm.com>,
	<will.deacon@arm.com>, <thomas.lendacky@amd.com>,
	<herbert@gondor.apana.org.au>, <davem@davemloft.net>
Cc: <msalter@redhat.com>, <hanjun.guo@linaro.org>,
	<al.stone@linaro.org>, <grant.likely@linaro.org>, <arnd@arndb.de>,
	<leo.duran@amd.com>, <linux-arm-kernel@lists.infradead.org>,
	<linux-acpi@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<linaro-acpi@lists.linaro.org>, <netdev@vger.kernel.org>,
	<linux-crypto@vger.kernel.org>,
	"Suravee Suthikulpanit" <Suravee.Suthikulpanit@amd.com>
Subject: [V2 PATCH 1/5] ACPI / scan: Parse _CCA and setup device coherency
Date: Tue, 5 May 2015 10:12:05 -0500	[thread overview]
Message-ID: <1430838729-21572-2-git-send-email-Suravee.Suthikulpanit@amd.com> (raw)
In-Reply-To: <1430838729-21572-1-git-send-email-Suravee.Suthikulpanit@amd.com>

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>
---
NOTE:
 * Since there seem to be conflict opinions regarding how
   architecture should handle _CCA=0. So, I am proposing the
   CONFIG_ARCH_SUPPORT_CCA_ZERO, which can be specified by
   for each architecture to define behavior of the ACPI
   scanning code when _CCA=0. Let me know if this is acceptable.

 drivers/acpi/Kconfig         |  6 +++++
 drivers/acpi/acpi_platform.c |  4 ++-
 drivers/acpi/scan.c          | 62 ++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h      | 11 +++++++-
 include/linux/acpi.h         |  5 ++++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb5..dd386e9 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_MUST_HAVE_CCA
+	bool
+
+config ACPI_SUPPORT_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..a6feca4 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -108,9 +108,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
 	if (IS_ERR(pdev))
 		dev_err(&adev->dev, "platform device creation failed: %ld\n",
 			PTR_ERR(pdev));
-	else
+	else {
+		acpi_setup_device_dma(adev, &pdev->dev);
 		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..ac33b29 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,66 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
 	kfree(pnp->unique_id);
 }
 
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev)
+{
+	int coherent = acpi_dma_is_coherent(adev);
+
+	/**
+	 * Currently, we only support DMA for devices that _CCA=1
+	 * since this seems to be the case on most ACPI platforms.
+	 *
+	 * 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 enables
+	 * CONFIG_ACPI_SUPPORT_CCA_ZERO.
+	 *
+	 * For the case when _CCA is missing but platform requires it
+	 * (i.e. is_coherent=0 && cca_seen=0), we do not call
+	 * arch_setup_dma_ops() and fallback to arch-specific default
+	 * handling.
+	 */
+	if (adev->flags.cca_seen) {
+		if (!coherent && !IS_ENABLED(CONFIG_ACPI_SUPPORT_CCA_ZERO))
+			return;
+		arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+	}
+}
+
+static void acpi_init_coherency(struct acpi_device *adev)
+{
+	unsigned long long cca = 0;
+	acpi_status status;
+	struct acpi_device *parent = adev->parent;
+
+	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_MUST_HAVE_CCA)) {
+			/*
+			 * If architecture does not specify that _CCA is
+			 * required for DMA-able devices (e.g. x86),
+			 * we default to _CCA=1.
+			 */
+			cca = 1;
+		} else {
+			dev_err(&adev->dev, FW_BUG
+				"DMA is not setup due to missing _CCA.\n");
+		}
+	}
+
+	adev->flags.is_coherent = cca;
+	acpi_setup_device_dma(adev, &adev->dev);
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta)
 {
@@ -2155,6 +2216,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..b804183 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,13 @@ struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return adev && adev->flags.is_coherent;
+}
+
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev);
+
 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..d14e777 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -583,6 +583,11 @@ static inline int acpi_device_modalias(struct device *dev,
 	return -ENODEV;
 }
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return false;
+}
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */
-- 
2.1.0


WARNING: multiple messages have this Message-ID (diff)
From: Suravee.Suthikulpanit@amd.com (Suravee Suthikulpanit)
To: linux-arm-kernel@lists.infradead.org
Subject: [V2 PATCH 1/5] ACPI / scan: Parse _CCA and setup device coherency
Date: Tue, 5 May 2015 10:12:05 -0500	[thread overview]
Message-ID: <1430838729-21572-2-git-send-email-Suravee.Suthikulpanit@amd.com> (raw)
In-Reply-To: <1430838729-21572-1-git-send-email-Suravee.Suthikulpanit@amd.com>

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>
---
NOTE:
 * Since there seem to be conflict opinions regarding how
   architecture should handle _CCA=0. So, I am proposing the
   CONFIG_ARCH_SUPPORT_CCA_ZERO, which can be specified by
   for each architecture to define behavior of the ACPI
   scanning code when _CCA=0. Let me know if this is acceptable.

 drivers/acpi/Kconfig         |  6 +++++
 drivers/acpi/acpi_platform.c |  4 ++-
 drivers/acpi/scan.c          | 62 ++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h      | 11 +++++++-
 include/linux/acpi.h         |  5 ++++
 5 files changed, 86 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index ab2cbb5..dd386e9 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_MUST_HAVE_CCA
+	bool
+
+config ACPI_SUPPORT_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..a6feca4 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -108,9 +108,11 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev)
 	if (IS_ERR(pdev))
 		dev_err(&adev->dev, "platform device creation failed: %ld\n",
 			PTR_ERR(pdev));
-	else
+	else {
+		acpi_setup_device_dma(adev, &pdev->dev);
 		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..ac33b29 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,66 @@ void acpi_free_pnp_ids(struct acpi_device_pnp *pnp)
 	kfree(pnp->unique_id);
 }
 
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev)
+{
+	int coherent = acpi_dma_is_coherent(adev);
+
+	/**
+	 * Currently, we only support DMA for devices that _CCA=1
+	 * since this seems to be the case on most ACPI platforms.
+	 *
+	 * 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 enables
+	 * CONFIG_ACPI_SUPPORT_CCA_ZERO.
+	 *
+	 * For the case when _CCA is missing but platform requires it
+	 * (i.e. is_coherent=0 && cca_seen=0), we do not call
+	 * arch_setup_dma_ops() and fallback to arch-specific default
+	 * handling.
+	 */
+	if (adev->flags.cca_seen) {
+		if (!coherent && !IS_ENABLED(CONFIG_ACPI_SUPPORT_CCA_ZERO))
+			return;
+		arch_setup_dma_ops(dev, 0, 0, NULL, coherent);
+	}
+}
+
+static void acpi_init_coherency(struct acpi_device *adev)
+{
+	unsigned long long cca = 0;
+	acpi_status status;
+	struct acpi_device *parent = adev->parent;
+
+	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_MUST_HAVE_CCA)) {
+			/*
+			 * If architecture does not specify that _CCA is
+			 * required for DMA-able devices (e.g. x86),
+			 * we default to _CCA=1.
+			 */
+			cca = 1;
+		} else {
+			dev_err(&adev->dev, FW_BUG
+				"DMA is not setup due to missing _CCA.\n");
+		}
+	}
+
+	adev->flags.is_coherent = cca;
+	acpi_setup_device_dma(adev, &adev->dev);
+}
+
 void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 			     int type, unsigned long long sta)
 {
@@ -2155,6 +2216,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..b804183 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,13 @@ struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return adev && adev->flags.is_coherent;
+}
+
+void acpi_setup_device_dma(struct acpi_device *adev, struct device *dev);
+
 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..d14e777 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -583,6 +583,11 @@ static inline int acpi_device_modalias(struct device *dev,
 	return -ENODEV;
 }
 
+static inline bool acpi_dma_is_coherent(struct acpi_device *adev)
+{
+	return false;
+}
+
 #define ACPI_PTR(_ptr)	(NULL)
 
 #endif	/* !CONFIG_ACPI */
-- 
2.1.0

  reply	other threads:[~2015-05-05 15:12 UTC|newest]

Thread overview: 72+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-05 15:12 [V2 PATCH 0/5] Introduce ACPI _CCA support and device_dma_is_coherent API Suravee Suthikulpanit
2015-05-05 15:12 ` Suravee Suthikulpanit
2015-05-05 15:12 ` Suravee Suthikulpanit
2015-05-05 15:12 ` Suravee Suthikulpanit
2015-05-05 15:12 ` Suravee Suthikulpanit [this message]
2015-05-05 15:12   ` [V2 PATCH 1/5] ACPI / scan: Parse _CCA and setup device coherency Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 20:36   ` Rafael J. Wysocki
2015-05-05 20:36     ` Rafael J. Wysocki
2015-05-06  4:15     ` Suravee Suthikulpanit
2015-05-06  4:15       ` Suravee Suthikulpanit
2015-05-06  4:15       ` Suravee Suthikulpanit
2015-05-06 22:21       ` Rafael J. Wysocki
2015-05-06 22:21         ` Rafael J. Wysocki
2015-05-06 22:16         ` Suravee Suthikulanit
2015-05-06 22:16           ` Suravee Suthikulanit
2015-05-06 22:16           ` Suravee Suthikulanit
2015-05-07  9:07           ` [Linaro-acpi] " Arnd Bergmann
2015-05-07  9:07             ` Arnd Bergmann
2015-05-07 20:18             ` Rafael J. Wysocki
2015-05-07 20:18               ` Rafael J. Wysocki
2015-05-06  3:13   ` Hanjun Guo
2015-05-06  3:13     ` Hanjun Guo
2015-05-06  4:17     ` Suravee Suthikulpanit
2015-05-06  4:17       ` Suravee Suthikulpanit
2015-05-06  4:17       ` Suravee Suthikulpanit
2015-05-05 15:12 ` [V2 PATCH 2/5] arm64 : Introduce support for ACPI _CCA object Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:44   ` Arnd Bergmann
2015-05-05 15:44     ` Arnd Bergmann
2015-05-05 15:44     ` Arnd Bergmann
2015-05-05 16:09     ` Suravee Suthikulanit
2015-05-05 16:09       ` Suravee Suthikulanit
2015-05-05 16:09       ` Suravee Suthikulanit
2015-05-05 16:09       ` Suravee Suthikulanit
2015-05-05 16:12       ` [Linaro-acpi] " Arnd Bergmann
2015-05-05 16:12         ` Arnd Bergmann
2015-05-05 16:13         ` Suravee Suthikulanit
2015-05-05 16:13           ` Suravee Suthikulanit
2015-05-05 16:13           ` Suravee Suthikulanit
2015-05-05 16:24           ` Tom Lendacky
2015-05-05 16:24             ` Tom Lendacky
2015-05-05 16:24             ` Tom Lendacky
2015-05-05 18:02             ` Arnd Bergmann
2015-05-05 18:02               ` Arnd Bergmann
2015-05-06 10:08   ` Robin Murphy
2015-05-06 10:08     ` Robin Murphy
2015-05-06 10:08     ` Robin Murphy
2015-05-06 14:34     ` Suravee Suthikulanit
2015-05-06 14:34       ` Suravee Suthikulanit
2015-05-06 14:34       ` Suravee Suthikulanit
2015-05-05 15:12 ` [V2 PATCH 3/5] device property: Introduces device_dma_is_coherent() Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-06 23:52   ` Suravee Suthikulanit
2015-05-06 23:52     ` Suravee Suthikulanit
2015-05-06 23:52     ` Suravee Suthikulanit
2015-05-06 23:58     ` Rafael J. Wysocki
2015-05-06 23:58       ` Rafael J. Wysocki
2015-05-06 23:58       ` Rafael J. Wysocki
2015-05-05 15:12 ` [V2 PATCH 4/5] crypto: ccp - Unify coherency checking logic with device_dma_is_coherent() Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12 ` [V2 PATCH 5/5] amd-xgbe: " Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit
2015-05-05 15:12   ` Suravee Suthikulpanit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1430838729-21572-2-git-send-email-Suravee.Suthikulpanit@amd.com \
    --to=suravee.suthikulpanit@amd.com \
    --cc=al.stone@linaro.org \
    --cc=arnd@arndb.de \
    --cc=catalin.marinas@arm.com \
    --cc=davem@davemloft.net \
    --cc=grant.likely@linaro.org \
    --cc=hanjun.guo@linaro.org \
    --cc=herbert@gondor.apana.org.au \
    --cc=lenb@kernel.org \
    --cc=leo.duran@amd.com \
    --cc=linaro-acpi@lists.linaro.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=msalter@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=rjw@rjwysocki.net \
    --cc=thomas.lendacky@amd.com \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.