All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
To: linux-acpi@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org,
	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
	Will Deacon <will.deacon@arm.com>,
	Hanjun Guo <hanjun.guo@linaro.org>,
	Robin Murphy <robin.murphy@arm.com>,
	"Rafael J. Wysocki" <rjw@rjwysocki.net>,
	Robert Moore <robert.moore@intel.com>, Feng Kan <fkan@apm.com>,
	Jon Masters <jcm@redhat.com>, Zhang Rui <rui.zhang@intel.com>,
	Nate Watterson <nwatters@codeaurora.org>
Subject: [PATCH v3 4/5] ACPI: Make acpi_dma_configure() DMA regions aware
Date: Thu,  3 Aug 2017 13:32:38 +0100	[thread overview]
Message-ID: <20170803123239.11359-5-lorenzo.pieralisi@arm.com> (raw)
In-Reply-To: <20170803123239.11359-1-lorenzo.pieralisi@arm.com>

Current ACPI DMA configuration set-up device DMA capabilities through
kernel defaults that do not take into account platform specific DMA
configurations reported by firmware.

By leveraging the ACPI acpi_dev_get_dma_resources() API, add code
in acpi_dma_configure() to retrieve the DMA regions to correctly
set-up PCI devices DMA parameters.

Rework the ACPI IORT kernel API to make sure they can accommodate
the DMA set-up required by firmware. By making PCI devices DMA set-up
ACPI IORT specific, the kernel is shielded from unwanted regressions
that could be triggered by parsing DMA resources on arches that were
previously ignoring them (ie x86/ia64), leaving kernel behaviour
unchanged on those arches.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/arm64/iort.c | 37 +++++++++++++++++++++++++++++++++++--
 include/linux/acpi_iort.h |  5 +++--
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index a3215ee..606af87 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -681,12 +681,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
 }
 
 /**
- * iort_set_dma_mask - Set-up dma mask for a device.
+ * iort_dma_setup() - Set-up device DMA parameters.
  *
  * @dev: device to configure
+ * @dma_addr: device DMA address result pointer
+ * @size: DMA range size result pointer
  */
-void iort_set_dma_mask(struct device *dev)
+void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
 {
+	u64 mask, dmaaddr = 0, size = 0, offset = 0;
+	int ret, msb;
+
 	/*
 	 * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
 	 * setup the correct supported mask.
@@ -700,6 +705,34 @@ void iort_set_dma_mask(struct device *dev)
 	 */
 	if (!dev->dma_mask)
 		dev->dma_mask = &dev->coherent_dma_mask;
+
+	size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
+
+	if (dev_is_pci(dev)) {
+		ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
+		if (!ret) {
+			msb = fls64(dmaaddr + size - 1);
+			/*
+			 * Round-up to the power-of-two mask or set
+			 * the mask to the whole 64-bit address space
+			 * in case the DMA region covers the full
+			 * memory window.
+			 */
+			mask = msb == 64 ? U64_MAX : (1ULL << msb) - 1;
+			/*
+			 * Limit coherent and dma mask based on size
+			 * retrieved from firmware.
+			 */
+			dev->coherent_dma_mask = mask;
+			*dev->dma_mask = mask;
+		}
+	}
+
+	*dma_addr = dmaaddr;
+	*dma_size = size;
+
+	dev->dma_pfn_offset = PFN_DOWN(offset);
+	dev_dbg(dev, "dma_pfn_offset(%#08llx)\n", offset);
 }
 
 /**
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 8379d40..8d3f0bf 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -36,7 +36,7 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
-void iort_set_dma_mask(struct device *dev);
+void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
 const struct iommu_ops *iort_iommu_configure(struct device *dev);
 #else
 static inline void acpi_iort_init(void) { }
@@ -47,7 +47,8 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
 { return NULL; }
 static inline void acpi_configure_pmsi_domain(struct device *dev) { }
 /* IOMMU interface */
-static inline void iort_set_dma_mask(struct device *dev) { }
+static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
+				  u64 *size) { }
 static inline
 const struct iommu_ops *iort_iommu_configure(struct device *dev)
 { return NULL; }
-- 
2.10.0

WARNING: multiple messages have this Message-ID (diff)
From: lorenzo.pieralisi@arm.com (Lorenzo Pieralisi)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 4/5] ACPI: Make acpi_dma_configure() DMA regions aware
Date: Thu,  3 Aug 2017 13:32:38 +0100	[thread overview]
Message-ID: <20170803123239.11359-5-lorenzo.pieralisi@arm.com> (raw)
In-Reply-To: <20170803123239.11359-1-lorenzo.pieralisi@arm.com>

Current ACPI DMA configuration set-up device DMA capabilities through
kernel defaults that do not take into account platform specific DMA
configurations reported by firmware.

By leveraging the ACPI acpi_dev_get_dma_resources() API, add code
in acpi_dma_configure() to retrieve the DMA regions to correctly
set-up PCI devices DMA parameters.

Rework the ACPI IORT kernel API to make sure they can accommodate
the DMA set-up required by firmware. By making PCI devices DMA set-up
ACPI IORT specific, the kernel is shielded from unwanted regressions
that could be triggered by parsing DMA resources on arches that were
previously ignoring them (ie x86/ia64), leaving kernel behaviour
unchanged on those arches.

Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Hanjun Guo <hanjun.guo@linaro.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
---
 drivers/acpi/arm64/iort.c | 37 +++++++++++++++++++++++++++++++++++--
 include/linux/acpi_iort.h |  5 +++--
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index a3215ee..606af87 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -681,12 +681,17 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
 }
 
 /**
- * iort_set_dma_mask - Set-up dma mask for a device.
+ * iort_dma_setup() - Set-up device DMA parameters.
  *
  * @dev: device to configure
+ * @dma_addr: device DMA address result pointer
+ * @size: DMA range size result pointer
  */
-void iort_set_dma_mask(struct device *dev)
+void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *dma_size)
 {
+	u64 mask, dmaaddr = 0, size = 0, offset = 0;
+	int ret, msb;
+
 	/*
 	 * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
 	 * setup the correct supported mask.
@@ -700,6 +705,34 @@ void iort_set_dma_mask(struct device *dev)
 	 */
 	if (!dev->dma_mask)
 		dev->dma_mask = &dev->coherent_dma_mask;
+
+	size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
+
+	if (dev_is_pci(dev)) {
+		ret = acpi_dma_get_range(dev, &dmaaddr, &offset, &size);
+		if (!ret) {
+			msb = fls64(dmaaddr + size - 1);
+			/*
+			 * Round-up to the power-of-two mask or set
+			 * the mask to the whole 64-bit address space
+			 * in case the DMA region covers the full
+			 * memory window.
+			 */
+			mask = msb == 64 ? U64_MAX : (1ULL << msb) - 1;
+			/*
+			 * Limit coherent and dma mask based on size
+			 * retrieved from firmware.
+			 */
+			dev->coherent_dma_mask = mask;
+			*dev->dma_mask = mask;
+		}
+	}
+
+	*dma_addr = dmaaddr;
+	*dma_size = size;
+
+	dev->dma_pfn_offset = PFN_DOWN(offset);
+	dev_dbg(dev, "dma_pfn_offset(%#08llx)\n", offset);
 }
 
 /**
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 8379d40..8d3f0bf 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -36,7 +36,7 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id);
 void acpi_configure_pmsi_domain(struct device *dev);
 int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id);
 /* IOMMU interface */
-void iort_set_dma_mask(struct device *dev);
+void iort_dma_setup(struct device *dev, u64 *dma_addr, u64 *size);
 const struct iommu_ops *iort_iommu_configure(struct device *dev);
 #else
 static inline void acpi_iort_init(void) { }
@@ -47,7 +47,8 @@ static inline struct irq_domain *iort_get_device_domain(struct device *dev,
 { return NULL; }
 static inline void acpi_configure_pmsi_domain(struct device *dev) { }
 /* IOMMU interface */
-static inline void iort_set_dma_mask(struct device *dev) { }
+static inline void iort_dma_setup(struct device *dev, u64 *dma_addr,
+				  u64 *size) { }
 static inline
 const struct iommu_ops *iort_iommu_configure(struct device *dev)
 { return NULL; }
-- 
2.10.0

  parent reply	other threads:[~2017-08-03 12:32 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-03 12:32 [PATCH v3 0/5] ACPI: DMA ranges management Lorenzo Pieralisi
2017-08-03 12:32 ` Lorenzo Pieralisi
2017-08-03 12:32 ` [PATCH v3 1/5] ACPICA: resource_mgr: Allow _DMA method in walk resources Lorenzo Pieralisi
2017-08-03 12:32   ` Lorenzo Pieralisi
2017-08-03 12:32 ` [PATCH v3 2/5] ACPI: Make acpi_dev_get_resources() method agnostic Lorenzo Pieralisi
2017-08-03 12:32   ` Lorenzo Pieralisi
2017-08-03 12:32 ` [PATCH v3 3/5] ACPI: Introduce DMA ranges parsing Lorenzo Pieralisi
2017-08-03 12:32   ` Lorenzo Pieralisi
2017-08-06  5:12   ` kbuild test robot
2017-08-06  5:12     ` kbuild test robot
2017-08-06  5:12     ` kbuild test robot
2017-08-06  9:42     ` Lorenzo Pieralisi
2017-08-06  9:42       ` Lorenzo Pieralisi
2017-08-06 11:21       ` Rafael J. Wysocki
2017-08-06 11:21         ` Rafael J. Wysocki
2017-08-06 11:21         ` Rafael J. Wysocki
2017-08-03 12:32 ` Lorenzo Pieralisi [this message]
2017-08-03 12:32   ` [PATCH v3 4/5] ACPI: Make acpi_dma_configure() DMA regions aware Lorenzo Pieralisi
2017-08-03 12:32 ` [PATCH v3 5/5] ACPI/IORT: Add IORT named component memory address limits Lorenzo Pieralisi
2017-08-03 12:32   ` Lorenzo Pieralisi
2017-08-03 13:25 ` [PATCH v3 0/5] ACPI: DMA ranges management Hanjun Guo
2017-08-03 13:25   ` Hanjun Guo
2017-08-03 13:25   ` Hanjun Guo
2017-08-03 15:16 ` Will Deacon
2017-08-03 15:16   ` Will Deacon
2017-08-03 15:45 ` Nate Watterson
2017-08-03 15:45   ` Nate Watterson
2017-08-03 17:21   ` Robin Murphy
2017-08-03 17:21     ` Robin Murphy
2017-08-09 21:14 ` Jeremy Linton
2017-08-09 21:14   ` Jeremy Linton
2017-08-11  8:52   ` Lorenzo Pieralisi
2017-08-11  8:52     ` Lorenzo Pieralisi
2017-08-14 18:41 ` Feng Kan
2017-08-14 18:41   ` Feng Kan
2017-08-14 18:41   ` Feng Kan
2017-11-30  7:28 ` Feng Kan
2017-11-30  7:28   ` Feng Kan
2017-11-30  7:28   ` Feng Kan
2017-12-01  0:43   ` Feng Kan
2017-12-01  0:43     ` Feng Kan
2017-12-01  0:43     ` Feng Kan
2017-12-01 10:39     ` Lorenzo Pieralisi
2017-12-01 10:39       ` Lorenzo Pieralisi
2017-12-01 10:39       ` Lorenzo Pieralisi

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=20170803123239.11359-5-lorenzo.pieralisi@arm.com \
    --to=lorenzo.pieralisi@arm.com \
    --cc=fkan@apm.com \
    --cc=hanjun.guo@linaro.org \
    --cc=jcm@redhat.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nwatters@codeaurora.org \
    --cc=rjw@rjwysocki.net \
    --cc=robert.moore@intel.com \
    --cc=robin.murphy@arm.com \
    --cc=rui.zhang@intel.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.