From: nikita.yoush@cogentembedded.com (Nikita Yushchenko)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2] arm64: do not set dma masks that device connection can't handle
Date: Mon, 9 Jan 2017 10:30:02 +0300 [thread overview]
Message-ID: <1483947002-16410-1-git-send-email-nikita.yoush@cogentembedded.com> (raw)
It is possible that device is capable of 64-bit DMA addresses, and
device driver tries to set wide DMA mask, but bridge or bus used to
connect device to the system can't handle wide addresses.
With swiotlb, memory above 4G still can be used by drivers for streaming
DMA, but *dev->mask and dev->dma_coherent_mask must still keep values
that hardware handles physically.
This patch enforces that. Based on original version by
Arnd Bergmann <arnd@arndb.de>, extended with coherent mask hadnling.
Signed-off-by: Nikita Yushchenko <nikita.yoush@cogentembedded.com>
CC: Arnd Bergmann <arnd@arndb.de>
---
Changes since v1:
- fixed issues noted by Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
- save mask, not size
- remove doube empty line
arch/arm64/Kconfig | 3 +++
arch/arm64/include/asm/device.h | 1 +
arch/arm64/mm/dma-mapping.c | 51 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 55 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 1117421..afb2c08 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -216,6 +216,9 @@ config NEED_DMA_MAP_STATE
config NEED_SG_DMA_LENGTH
def_bool y
+config ARCH_HAS_DMA_SET_COHERENT_MASK
+ def_bool y
+
config SMP
def_bool y
diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h
index 243ef25..a57e7bb 100644
--- a/arch/arm64/include/asm/device.h
+++ b/arch/arm64/include/asm/device.h
@@ -22,6 +22,7 @@ struct dev_archdata {
void *iommu; /* private IOMMU data */
#endif
bool dma_coherent;
+ u64 parent_dma_mask;
};
struct pdev_archdata {
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index e040827..5ab15ce 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -352,6 +352,30 @@ static int __swiotlb_dma_supported(struct device *hwdev, u64 mask)
return 1;
}
+static int __swiotlb_set_dma_mask(struct device *dev, u64 mask)
+{
+ /* device is not DMA capable */
+ if (!dev->dma_mask)
+ return -EIO;
+
+ /* mask is below swiotlb bounce buffer, so fail */
+ if (!swiotlb_dma_supported(dev, mask))
+ return -EIO;
+
+ /*
+ * because of the swiotlb, we can return success for
+ * larger masks, but need to ensure that bounce buffers
+ * are used above parent_dma_mask, so set that as
+ * the effective mask.
+ */
+ if (mask > dev->archdata.parent_dma_mask)
+ mask = dev->archdata.parent_dma_mask;
+
+ *dev->dma_mask = mask;
+
+ return 0;
+}
+
static struct dma_map_ops swiotlb_dma_ops = {
.alloc = __dma_alloc,
.free = __dma_free,
@@ -367,8 +391,23 @@ static struct dma_map_ops swiotlb_dma_ops = {
.sync_sg_for_device = __swiotlb_sync_sg_for_device,
.dma_supported = __swiotlb_dma_supported,
.mapping_error = swiotlb_dma_mapping_error,
+ .set_dma_mask = __swiotlb_set_dma_mask,
};
+int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+ if (!dma_supported(dev, mask))
+ return -EIO;
+
+ if (get_dma_ops(dev) == &swiotlb_dma_ops &&
+ mask > dev->archdata.parent_dma_mask)
+ mask = dev->archdata.parent_dma_mask;
+
+ dev->coherent_dma_mask = mask;
+ return 0;
+}
+EXPORT_SYMBOL(dma_set_coherent_mask);
+
static int __init atomic_pool_init(void)
{
pgprot_t prot = __pgprot(PROT_NORMAL_NC);
@@ -958,6 +997,18 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
if (!dev->archdata.dma_ops)
dev->archdata.dma_ops = &swiotlb_dma_ops;
+ /*
+ * we don't yet support buses that have a non-zero mapping.
+ * Let's hope we won't need it
+ */
+ WARN_ON(dma_base != 0);
+
+ /*
+ * Whatever the parent bus can set. A device must not set
+ * a DMA mask larger than this.
+ */
+ dev->archdata.parent_dma_mask = size - 1;
+
dev->archdata.dma_coherent = coherent;
__iommu_setup_dma_ops(dev, dma_base, size, iommu);
}
--
2.1.4
next reply other threads:[~2017-01-09 7:30 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-09 7:30 Nikita Yushchenko [this message]
2017-01-10 11:51 ` [PATCH v2] arm64: do not set dma masks that device connection can't handle Will Deacon
2017-01-10 12:47 ` Nikita Yushchenko
2017-01-10 13:12 ` Arnd Bergmann
2017-01-10 13:25 ` Robin Murphy
2017-01-10 13:42 ` Arnd Bergmann
2017-01-10 14:16 ` Robin Murphy
2017-01-10 15:06 ` Arnd Bergmann
2017-01-11 12:37 ` Nikita Yushchenko
2017-01-11 16:21 ` Arnd Bergmann
2017-01-11 18:28 ` Robin Murphy
2017-01-10 14:59 ` Christoph Hellwig
2017-01-10 14:00 ` [PATCH] arm64: avoid increasing DMA masks above what hardware supports Nikita Yushchenko
2017-01-10 17:14 ` Robin Murphy
2017-01-11 7:59 ` Nikita Yushchenko
2017-01-11 11:54 ` Robin Murphy
2017-01-11 13:41 ` Nikita Yushchenko
2017-01-11 14:50 ` Robin Murphy
2017-01-11 16:03 ` Nikita Yushchenko
2017-01-11 16:50 ` Robin Murphy
2017-01-11 18:31 ` [PATCH 0/2] arm64: fix handling of DMA masks wider than bus supports Nikita Yushchenko
2017-01-11 18:31 ` [PATCH 1/2] dma-mapping: let arch know origin of dma range passed to arch_setup_dma_ops() Nikita Yushchenko
2017-01-11 21:08 ` Arnd Bergmann
2017-01-12 5:52 ` Nikita Yushchenko
2017-01-12 6:33 ` Nikita Yushchenko
2017-01-12 13:28 ` Arnd Bergmann
2017-01-12 13:39 ` Nikita Yushchenko
2017-01-12 12:16 ` Will Deacon
2017-01-12 13:25 ` Arnd Bergmann
2017-01-12 13:43 ` Robin Murphy
2017-01-13 10:40 ` kbuild test robot
2017-01-11 18:31 ` [PATCH 2/2] arm64: avoid increasing DMA masks above what hardware supports Nikita Yushchenko
2017-01-11 21:11 ` Arnd Bergmann
2017-01-12 5:53 ` Nikita Yushchenko
2017-01-13 10:16 ` kbuild test robot
2017-01-10 14:01 ` [PATCH v2] arm64: do not set dma masks that device connection can't handle Nikita Yushchenko
2017-01-10 14:57 ` Christoph Hellwig
2017-01-10 14:51 ` Christoph Hellwig
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=1483947002-16410-1-git-send-email-nikita.yoush@cogentembedded.com \
--to=nikita.yoush@cogentembedded.com \
--cc=linux-arm-kernel@lists.infradead.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).