* [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
[not found] ` <1457404974-1800-1-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 7:38 ` Christoph Hellwig
2016-03-08 2:42 ` [PATCH v5 4/9] arm: dma-mapping: add {map, unmap}_resource for iommu ops Niklas Söderlund
` (4 subsequent siblings)
5 siblings, 2 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Niklas Söderlund,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
include/linux/dma-mapping.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..cc305d1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,38 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
}
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ unsigned long pfn = __phys_to_pfn(phys_addr);
+
+ BUG_ON(!valid_dma_direction(dir));
+
+ /* Don't allow RAM to be mapped */
+ BUG_ON(pfn_valid(pfn));
+
+ if (ops->map_resource)
+ return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+ return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->unmap_resource)
+ ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
size_t size,
enum dma_data_direction dir)
--
2.7.2
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-08 2:42 ` [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 7:38 ` Christoph Hellwig
1 sibling, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu
Cc: robin.murphy, laurent.pinchart, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch, Niklas Söderlund
Map/Unmap a device resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
include/linux/dma-mapping.h | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index e3aba4e..cc305d1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -216,6 +216,38 @@ static inline void dma_unmap_page(struct device *dev, dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
}
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ unsigned long pfn = __phys_to_pfn(phys_addr);
+
+ BUG_ON(!valid_dma_direction(dir));
+
+ /* Don't allow RAM to be mapped */
+ BUG_ON(pfn_valid(pfn));
+
+ if (ops->map_resource)
+ return ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+ return phys_addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ BUG_ON(!valid_dma_direction(dir));
+ if (ops->unmap_resource)
+ ops->unmap_resource(dev, addr, size, dir, attrs);
+
+}
+
static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
size_t size,
enum dma_data_direction dir)
--
2.7.2
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-08 2:42 ` [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource Niklas Söderlund
2016-03-08 2:42 ` Niklas Söderlund
@ 2016-03-08 7:38 ` Christoph Hellwig
2016-03-10 16:05 ` Niklas S??derlund
1 sibling, 1 reply; 54+ messages in thread
From: Christoph Hellwig @ 2016-03-08 7:38 UTC (permalink / raw)
To: Niklas S??derlund
Cc: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu, robin.murphy, laurent.pinchart, geert+renesas,
linus.walleij, dan.j.williams, arnd, linux-arch
Please add some documentation on where/how this should be used. It's
not a very obvious interface.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-08 7:38 ` Christoph Hellwig
@ 2016-03-10 16:05 ` Niklas S??derlund
2016-03-10 16:05 ` Niklas S??derlund
` (2 more replies)
0 siblings, 3 replies; 54+ messages in thread
From: Niklas S??derlund @ 2016-03-10 16:05 UTC (permalink / raw)
To: Christoph Hellwig
Cc: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu, robin.murphy, laurent.pinchart, geert+renesas,
linus.walleij, dan.j.williams, arnd, linux-arch
Hi Christoph,
On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
> Please add some documentation on where/how this should be used. It's
> not a very obvious interface.
Good idea, I have added the following to Documentation/DMA-API.txt and
folded it in to this patch. Do you feel it's adequate and do you know
anywhere else I should add documentation?
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..248556a 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
recommended that you never use these unless you really know what the
cache width is.
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+
+Maps a MMIO region so it can be accessed by the device and returns the
+DMA address of the memory. API should only be used to map device MMIO,
+mapping of RAM is not permitted.
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+
+Unmaps the IOMMU region previously mapped. All the parameters passed in
+must be identical to those passed in (and returned) by the mapping API.
+
int
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
--
Regards,
Niklas Söderlund
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-10 16:05 ` Niklas S??derlund
@ 2016-03-10 16:05 ` Niklas S??derlund
2016-03-11 6:19 ` Vinod Koul
2016-03-11 6:47 ` Dan Williams
2 siblings, 0 replies; 54+ messages in thread
From: Niklas S??derlund @ 2016-03-10 16:05 UTC (permalink / raw)
To: Christoph Hellwig
Cc: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu, robin.murphy, laurent.pinchart, geert+renesas,
linus.walleij, dan.j.williams, arnd, linux-arch
Hi Christoph,
On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
> Please add some documentation on where/how this should be used. It's
> not a very obvious interface.
Good idea, I have added the following to Documentation/DMA-API.txt and
folded it in to this patch. Do you feel it's adequate and do you know
anywhere else I should add documentation?
diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..248556a 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
recommended that you never use these unless you really know what the
cache width is.
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+
+Maps a MMIO region so it can be accessed by the device and returns the
+DMA address of the memory. API should only be used to map device MMIO,
+mapping of RAM is not permitted.
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+
+Unmaps the IOMMU region previously mapped. All the parameters passed in
+must be identical to those passed in (and returned) by the mapping API.
+
int
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
--
Regards,
Niklas Söderlund
^ permalink raw reply related [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-10 16:05 ` Niklas S??derlund
2016-03-10 16:05 ` Niklas S??derlund
@ 2016-03-11 6:19 ` Vinod Koul
2016-03-11 6:19 ` Vinod Koul
2016-03-11 6:47 ` Dan Williams
2 siblings, 1 reply; 54+ messages in thread
From: Vinod Koul @ 2016-03-11 6:19 UTC (permalink / raw)
To: Christoph Hellwig, linux-renesas-soc, linux-arm-kernel,
linux-kernel, dmaengine, iommu, robin.murphy, laurent.pinchart,
geert+renesas, linus.walleij, dan.j.williams, arnd, linux-arch
On Thu, Mar 10, 2016 at 05:05:23PM +0100, Niklas S??derlund wrote:
> Hi Christoph,
>
> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
> > Please add some documentation on where/how this should be used. It's
> > not a very obvious interface.
>
> Good idea, I have added the following to Documentation/DMA-API.txt and
> folded it in to this patch. Do you feel it's adequate and do you know
> anywhere else I should add documentation?
>
> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
> index 45ef3f2..248556a 100644
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
> recommended that you never use these unless you really know what the
> cache width is.
>
> +dma_addr_t
> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
> + enum dma_data_direction dir, struct dma_attrs *attrs)
> +
> +Maps a MMIO region so it can be accessed by the device and returns the
> +DMA address of the memory. API should only be used to map device MMIO,
> +mapping of RAM is not permitted.
> +
> +void
> +dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
> + enum dma_data_direction dir, struct dma_attrs *attrs)
Using function prototypes in documentation may not be a great idea as you
are explaining the role of this function and not arguments.
> +
> +Unmaps the IOMMU region previously mapped. All the parameters passed in
> +must be identical to those passed in (and returned) by the mapping API.
> +
> int
> dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
>
> -In some circumstances dma_map_single() and dma_map_page() will fail to create
> -a mapping. A driver can check for these errors by testing the returned
> -DMA address with dma_mapping_error(). A non-zero return value means the mapping
> -could not be created and the driver should take appropriate action (e.g.
> -reduce current DMA mapping usage or delay and try again later).
> +In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
> +will fail to create a mapping. A driver can check for these errors by testing
> +the returned DMA address with dma_mapping_error(). A non-zero return value
> +means the mapping could not be created and the driver should take appropriate
> +action (e.g. reduce current DMA mapping usage or delay and try again later).
>
> --
> Regards,
> Niklas Söderlund
--
~Vinod
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 6:19 ` Vinod Koul
@ 2016-03-11 6:19 ` Vinod Koul
0 siblings, 0 replies; 54+ messages in thread
From: Vinod Koul @ 2016-03-11 6:19 UTC (permalink / raw)
To: Christoph Hellwig, linux-renesas-soc, linux-arm-kernel,
linux-kernel, dmaengine, iommu, robin.murphy, laurent.pinchart,
geert+renesas, linus.walleij, dan.j.williams, arnd, linux-arch
On Thu, Mar 10, 2016 at 05:05:23PM +0100, Niklas S??derlund wrote:
> Hi Christoph,
>
> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
> > Please add some documentation on where/how this should be used. It's
> > not a very obvious interface.
>
> Good idea, I have added the following to Documentation/DMA-API.txt and
> folded it in to this patch. Do you feel it's adequate and do you know
> anywhere else I should add documentation?
>
> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
> index 45ef3f2..248556a 100644
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
> recommended that you never use these unless you really know what the
> cache width is.
>
> +dma_addr_t
> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
> + enum dma_data_direction dir, struct dma_attrs *attrs)
> +
> +Maps a MMIO region so it can be accessed by the device and returns the
> +DMA address of the memory. API should only be used to map device MMIO,
> +mapping of RAM is not permitted.
> +
> +void
> +dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
> + enum dma_data_direction dir, struct dma_attrs *attrs)
Using function prototypes in documentation may not be a great idea as you
are explaining the role of this function and not arguments.
> +
> +Unmaps the IOMMU region previously mapped. All the parameters passed in
> +must be identical to those passed in (and returned) by the mapping API.
> +
> int
> dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
>
> -In some circumstances dma_map_single() and dma_map_page() will fail to create
> -a mapping. A driver can check for these errors by testing the returned
> -DMA address with dma_mapping_error(). A non-zero return value means the mapping
> -could not be created and the driver should take appropriate action (e.g.
> -reduce current DMA mapping usage or delay and try again later).
> +In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
> +will fail to create a mapping. A driver can check for these errors by testing
> +the returned DMA address with dma_mapping_error(). A non-zero return value
> +means the mapping could not be created and the driver should take appropriate
> +action (e.g. reduce current DMA mapping usage or delay and try again later).
>
> --
> Regards,
> Niklas Söderlund
--
~Vinod
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-10 16:05 ` Niklas S??derlund
2016-03-10 16:05 ` Niklas S??derlund
2016-03-11 6:19 ` Vinod Koul
@ 2016-03-11 6:47 ` Dan Williams
2016-03-11 6:47 ` Dan Williams
` (2 more replies)
2 siblings, 3 replies; 54+ messages in thread
From: Dan Williams @ 2016-03-11 6:47 UTC (permalink / raw)
To: Christoph Hellwig, Vinod Koul, linux-renesas-soc,
linux-arm-kernel, linux-kernel, dmaengine, iommu, robin.murphy,
Laurent Pinchart, geert+renesas, Linus Walleij, Dan J Williams,
Arnd Bergmann, linux-arch
On Thu, Mar 10, 2016 at 8:05 AM, Niklas S??derlund
<niklas.soderlund@ragnatech.se> wrote:
> Hi Christoph,
>
> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
>> Please add some documentation on where/how this should be used. It's
>> not a very obvious interface.
>
> Good idea, I have added the following to Documentation/DMA-API.txt and
> folded it in to this patch. Do you feel it's adequate and do you know
> anywhere else I should add documentation?
>
> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
> index 45ef3f2..248556a 100644
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
> recommended that you never use these unless you really know what the
> cache width is.
>
> +dma_addr_t
> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
> + enum dma_data_direction dir, struct dma_attrs *attrs)
> +
> +Maps a MMIO region so it can be accessed by the device and returns the
> +DMA address of the memory. API should only be used to map device MMIO,
> +mapping of RAM is not permitted.
> +
I think it is confusing to use the dma_ prefix for this peer-to-peer
mmio functionality. dma_addr_t is a device's view of host memory.
Something like bus_addr_t bus_map_resource(). Doesn't this routine
also need the source device in addition to the target device? The
resource address is from the perspective of the host cpu, it may be a
different address space in the view of two devices relative to each
other.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 6:47 ` Dan Williams
@ 2016-03-11 6:47 ` Dan Williams
2016-03-11 11:15 ` Christoph Hellwig
[not found] ` <CAPcyv4gO4EZnBuVKXT8+gsMhbHJzuK7sfr0uRcjVdJP-nUUz4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2 siblings, 0 replies; 54+ messages in thread
From: Dan Williams @ 2016-03-11 6:47 UTC (permalink / raw)
To: Christoph Hellwig, Vinod Koul, linux-renesas-soc,
linux-arm-kernel, linux-kernel, dmaengine, iommu, robin.murphy,
Laurent Pinchart, geert+renesas, Linus Walleij, Dan J Williams,
Arnd Bergmann, linux-arch
On Thu, Mar 10, 2016 at 8:05 AM, Niklas S??derlund
<niklas.soderlund@ragnatech.se> wrote:
> Hi Christoph,
>
> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
>> Please add some documentation on where/how this should be used. It's
>> not a very obvious interface.
>
> Good idea, I have added the following to Documentation/DMA-API.txt and
> folded it in to this patch. Do you feel it's adequate and do you know
> anywhere else I should add documentation?
>
> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
> index 45ef3f2..248556a 100644
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
> recommended that you never use these unless you really know what the
> cache width is.
>
> +dma_addr_t
> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
> + enum dma_data_direction dir, struct dma_attrs *attrs)
> +
> +Maps a MMIO region so it can be accessed by the device and returns the
> +DMA address of the memory. API should only be used to map device MMIO,
> +mapping of RAM is not permitted.
> +
I think it is confusing to use the dma_ prefix for this peer-to-peer
mmio functionality. dma_addr_t is a device's view of host memory.
Something like bus_addr_t bus_map_resource(). Doesn't this routine
also need the source device in addition to the target device? The
resource address is from the perspective of the host cpu, it may be a
different address space in the view of two devices relative to each
other.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 6:47 ` Dan Williams
2016-03-11 6:47 ` Dan Williams
@ 2016-03-11 11:15 ` Christoph Hellwig
2016-03-11 12:58 ` Niklas Söderlund
[not found] ` <CAPcyv4gO4EZnBuVKXT8+gsMhbHJzuK7sfr0uRcjVdJP-nUUz4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2 siblings, 1 reply; 54+ messages in thread
From: Christoph Hellwig @ 2016-03-11 11:15 UTC (permalink / raw)
To: Dan Williams
Cc: Christoph Hellwig, Vinod Koul, linux-renesas-soc,
linux-arm-kernel, linux-kernel, dmaengine, iommu, robin.murphy,
Laurent Pinchart, geert+renesas, Linus Walleij, Arnd Bergmann,
linux-arch
On Thu, Mar 10, 2016 at 10:47:10PM -0800, Dan Williams wrote:
> I think it is confusing to use the dma_ prefix for this peer-to-peer
> mmio functionality. dma_addr_t is a device's view of host memory.
> Something like bus_addr_t bus_map_resource(). Doesn't this routine
> also need the source device in addition to the target device? The
> resource address is from the perspective of the host cpu, it may be a
> different address space in the view of two devices relative to each
> other.
Is it supposed to be per-mmio? It's in dma-mapping ops, and has dma
in the name, so I suspected it's for some form of peer dma. But given
that our dma APIs reuqire a struct page backing I have no idea how this
even supposed to work, and this little documentation blurb still doesn't
clear that up.
So for now I'd like to NAK this patch until the use case can be
explained clearly, and actually works.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 11:15 ` Christoph Hellwig
@ 2016-03-11 12:58 ` Niklas Söderlund
2016-03-11 12:58 ` Niklas Söderlund
2016-03-15 8:22 ` Christoph Hellwig
0 siblings, 2 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-11 12:58 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Dan Williams, Vinod Koul, linux-renesas-soc, linux-arm-kernel,
linux-kernel, dmaengine, iommu, robin.murphy, Laurent Pinchart,
geert+renesas, Linus Walleij, Arnd Bergmann, linux-arch
Hi all,
Thanks for your comments.
On 2016-03-11 03:15:22 -0800, Christoph Hellwig wrote:
> On Thu, Mar 10, 2016 at 10:47:10PM -0800, Dan Williams wrote:
> > I think it is confusing to use the dma_ prefix for this peer-to-peer
> > mmio functionality. dma_addr_t is a device's view of host memory.
> > Something like bus_addr_t bus_map_resource(). Doesn't this routine
> > also need the source device in addition to the target device? The
> > resource address is from the perspective of the host cpu, it may be a
> > different address space in the view of two devices relative to each
> > other.
>
> Is it supposed to be per-mmio? It's in dma-mapping ops, and has dma
> in the name, so I suspected it's for some form of peer dma. But given
> that our dma APIs reuqire a struct page backing I have no idea how this
> even supposed to work, and this little documentation blurb still doesn't
> clear that up.
>
> So for now I'd like to NAK this patch until the use case can be
> explained clearly, and actually works.
I can explain the use case and maybe we can figure out if this approach
is the correct one to solve it.
The problem is that I have devices behind an IOMMU which I would like to
use with DMA. Vinod recently moved forward with his and Linus Walleij
patch '[PATCH] dmaengine: use phys_addr_t for slave configuration' which
clarifies that the DMA slave address provided by a client is the
physical address. This puts the task of mapping the DMA slave address
from a phys_addr_t to a dma_addr_t on the DMA engine.
Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
the same and no special care is needed. However if you have a IOMMU you
need to map the DMA slave phys_addr_t to a dma_addr_t using something
like this. Is it not very similar to dma_map_single() where one maps
processor virtual memory (instead if MMIO) so that it can be used with
DMA slaves?
--
Regards,
Niklas Söderlund
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 12:58 ` Niklas Söderlund
@ 2016-03-11 12:58 ` Niklas Söderlund
2016-03-15 8:22 ` Christoph Hellwig
1 sibling, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-11 12:58 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Dan Williams, Vinod Koul, linux-renesas-soc, linux-arm-kernel,
linux-kernel, dmaengine, iommu, robin.murphy, Laurent Pinchart,
geert+renesas, Linus Walleij, Arnd Bergmann, linux-arch
Hi all,
Thanks for your comments.
On 2016-03-11 03:15:22 -0800, Christoph Hellwig wrote:
> On Thu, Mar 10, 2016 at 10:47:10PM -0800, Dan Williams wrote:
> > I think it is confusing to use the dma_ prefix for this peer-to-peer
> > mmio functionality. dma_addr_t is a device's view of host memory.
> > Something like bus_addr_t bus_map_resource(). Doesn't this routine
> > also need the source device in addition to the target device? The
> > resource address is from the perspective of the host cpu, it may be a
> > different address space in the view of two devices relative to each
> > other.
>
> Is it supposed to be per-mmio? It's in dma-mapping ops, and has dma
> in the name, so I suspected it's for some form of peer dma. But given
> that our dma APIs reuqire a struct page backing I have no idea how this
> even supposed to work, and this little documentation blurb still doesn't
> clear that up.
>
> So for now I'd like to NAK this patch until the use case can be
> explained clearly, and actually works.
I can explain the use case and maybe we can figure out if this approach
is the correct one to solve it.
The problem is that I have devices behind an IOMMU which I would like to
use with DMA. Vinod recently moved forward with his and Linus Walleij
patch '[PATCH] dmaengine: use phys_addr_t for slave configuration' which
clarifies that the DMA slave address provided by a client is the
physical address. This puts the task of mapping the DMA slave address
from a phys_addr_t to a dma_addr_t on the DMA engine.
Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
the same and no special care is needed. However if you have a IOMMU you
need to map the DMA slave phys_addr_t to a dma_addr_t using something
like this. Is it not very similar to dma_map_single() where one maps
processor virtual memory (instead if MMIO) so that it can be used with
DMA slaves?
--
Regards,
Niklas Söderlund
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 12:58 ` Niklas Söderlund
2016-03-11 12:58 ` Niklas Söderlund
@ 2016-03-15 8:22 ` Christoph Hellwig
[not found] ` <20160315082254.GE9136-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>
1 sibling, 1 reply; 54+ messages in thread
From: Christoph Hellwig @ 2016-03-15 8:22 UTC (permalink / raw)
To: Christoph Hellwig, Dan Williams, Vinod Koul, linux-renesas-soc,
linux-arm-kernel, linux-kernel, dmaengine, iommu, robin.murphy,
Laurent Pinchart, geert+renesas, Linus Walleij, Arnd Bergmann,
linux-arch
On Fri, Mar 11, 2016 at 01:58:46PM +0100, Niklas S?derlund wrote:
> Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
> the same and no special care is needed. However if you have a IOMMU you
> need to map the DMA slave phys_addr_t to a dma_addr_t using something
> like this. Is it not very similar to dma_map_single() where one maps
> processor virtual memory (instead if MMIO) so that it can be used with
> DMA slaves?
It's similar, but I don't think this actually works as a general case
as there are quite a few places that expect to be able to have a
struct page for a physical address. We'd at least need a very careful
audit for that case.
^ permalink raw reply [flat|nested] 54+ messages in thread
[parent not found: <CAPcyv4gO4EZnBuVKXT8+gsMhbHJzuK7sfr0uRcjVdJP-nUUz4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>]
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
[not found] ` <CAPcyv4gO4EZnBuVKXT8+gsMhbHJzuK7sfr0uRcjVdJP-nUUz4A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2016-03-11 13:46 ` Robin Murphy
2016-03-11 13:46 ` Robin Murphy
2016-03-11 17:51 ` Dan Williams
0 siblings, 2 replies; 54+ messages in thread
From: Robin Murphy @ 2016-03-11 13:46 UTC (permalink / raw)
To: Dan Williams, Christoph Hellwig, Vinod Koul,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
Laurent Pinchart, geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
Linus Walleij, Arnd Bergmann, linux-arch-u79uwXL29TY76Z2rM5mHXA
Hi Dan,
On 11/03/16 06:47, Dan Williams wrote:
> On Thu, Mar 10, 2016 at 8:05 AM, Niklas S??derlund
> <niklas.soderlund-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org> wrote:
>> Hi Christoph,
>>
>> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
>>> Please add some documentation on where/how this should be used. It's
>>> not a very obvious interface.
>>
>> Good idea, I have added the following to Documentation/DMA-API.txt and
>> folded it in to this patch. Do you feel it's adequate and do you know
>> anywhere else I should add documentation?
>>
>> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
>> index 45ef3f2..248556a 100644
>> --- a/Documentation/DMA-API.txt
>> +++ b/Documentation/DMA-API.txt
>> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
>> recommended that you never use these unless you really know what the
>> cache width is.
>>
>> +dma_addr_t
>> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
>> + enum dma_data_direction dir, struct dma_attrs *attrs)
>> +
>> +Maps a MMIO region so it can be accessed by the device and returns the
>> +DMA address of the memory. API should only be used to map device MMIO,
>> +mapping of RAM is not permitted.
>> +
>
> I think it is confusing to use the dma_ prefix for this peer-to-peer
> mmio functionality. dma_addr_t is a device's view of host memory.
> Something like bus_addr_t bus_map_resource(). Doesn't this routine
> also need the source device in addition to the target device? The
> resource address is from the perspective of the host cpu, it may be a
> different address space in the view of two devices relative to each
> other.
Hmm, the trouble with that is that when the DMA master is behind an
IOMMU, the address space as seen by the device is dynamic and whatever
we decide it to be, so there is no distinction between a "DMA" address
and a "bus" address.
In practice the dmaengine API has clearly worked for however long with
slave MMIO addresses being a dma_addr_t, and it doesn't look like anyone
objected to the change to phys_addr_t in -next either. If nothing is
using bus_addr_t anyway, what's the right thing to do? Looking up
through higher abstraction layers, we have the likes of struct
snd_dmaengine_dai_dma_data also expecting the slave address to be a
dma_addr_t, leading to things like the direct casting in
bcm2835_i2s_probe() for the non-IOMMU dma != phys != bus case that could
also be cleaned up with this proposed interface.
Robin.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 13:46 ` Robin Murphy
@ 2016-03-11 13:46 ` Robin Murphy
2016-03-11 17:51 ` Dan Williams
1 sibling, 0 replies; 54+ messages in thread
From: Robin Murphy @ 2016-03-11 13:46 UTC (permalink / raw)
To: Dan Williams, Christoph Hellwig, Vinod Koul, linux-renesas-soc,
linux-arm-kernel, linux-kernel, dmaengine, iommu,
Laurent Pinchart, geert+renesas, Linus Walleij, Arnd Bergmann,
linux-arch
Hi Dan,
On 11/03/16 06:47, Dan Williams wrote:
> On Thu, Mar 10, 2016 at 8:05 AM, Niklas S??derlund
> <niklas.soderlund@ragnatech.se> wrote:
>> Hi Christoph,
>>
>> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
>>> Please add some documentation on where/how this should be used. It's
>>> not a very obvious interface.
>>
>> Good idea, I have added the following to Documentation/DMA-API.txt and
>> folded it in to this patch. Do you feel it's adequate and do you know
>> anywhere else I should add documentation?
>>
>> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
>> index 45ef3f2..248556a 100644
>> --- a/Documentation/DMA-API.txt
>> +++ b/Documentation/DMA-API.txt
>> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial page mapping, it is
>> recommended that you never use these unless you really know what the
>> cache width is.
>>
>> +dma_addr_t
>> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
>> + enum dma_data_direction dir, struct dma_attrs *attrs)
>> +
>> +Maps a MMIO region so it can be accessed by the device and returns the
>> +DMA address of the memory. API should only be used to map device MMIO,
>> +mapping of RAM is not permitted.
>> +
>
> I think it is confusing to use the dma_ prefix for this peer-to-peer
> mmio functionality. dma_addr_t is a device's view of host memory.
> Something like bus_addr_t bus_map_resource(). Doesn't this routine
> also need the source device in addition to the target device? The
> resource address is from the perspective of the host cpu, it may be a
> different address space in the view of two devices relative to each
> other.
Hmm, the trouble with that is that when the DMA master is behind an
IOMMU, the address space as seen by the device is dynamic and whatever
we decide it to be, so there is no distinction between a "DMA" address
and a "bus" address.
In practice the dmaengine API has clearly worked for however long with
slave MMIO addresses being a dma_addr_t, and it doesn't look like anyone
objected to the change to phys_addr_t in -next either. If nothing is
using bus_addr_t anyway, what's the right thing to do? Looking up
through higher abstraction layers, we have the likes of struct
snd_dmaengine_dai_dma_data also expecting the slave address to be a
dma_addr_t, leading to things like the direct casting in
bcm2835_i2s_probe() for the non-IOMMU dma != phys != bus case that could
also be cleaned up with this proposed interface.
Robin.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource
2016-03-11 13:46 ` Robin Murphy
2016-03-11 13:46 ` Robin Murphy
@ 2016-03-11 17:51 ` Dan Williams
1 sibling, 0 replies; 54+ messages in thread
From: Dan Williams @ 2016-03-11 17:51 UTC (permalink / raw)
To: Robin Murphy
Cc: Christoph Hellwig, Vinod Koul, linux-renesas-soc,
linux-arm-kernel, linux-kernel, dmaengine, iommu,
Laurent Pinchart, geert+renesas, Linus Walleij, Arnd Bergmann,
linux-arch
On Fri, Mar 11, 2016 at 5:46 AM, Robin Murphy <robin.murphy@arm.com> wrote:
> Hi Dan,
>
>
> On 11/03/16 06:47, Dan Williams wrote:
>>
>> On Thu, Mar 10, 2016 at 8:05 AM, Niklas S??derlund
>> <niklas.soderlund@ragnatech.se> wrote:
>>>
>>> Hi Christoph,
>>>
>>> On 2016-03-07 23:38:47 -0800, Christoph Hellwig wrote:
>>>>
>>>> Please add some documentation on where/how this should be used. It's
>>>> not a very obvious interface.
>>>
>>>
>>> Good idea, I have added the following to Documentation/DMA-API.txt and
>>> folded it in to this patch. Do you feel it's adequate and do you know
>>> anywhere else I should add documentation?
>>>
>>> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
>>> index 45ef3f2..248556a 100644
>>> --- a/Documentation/DMA-API.txt
>>> +++ b/Documentation/DMA-API.txt
>>> @@ -277,14 +277,29 @@ and <size> parameters are provided to do partial
>>> page mapping, it is
>>> recommended that you never use these unless you really know what the
>>> cache width is.
>>>
>>> +dma_addr_t
>>> +dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
>>> + enum dma_data_direction dir, struct dma_attrs *attrs)
>>> +
>>> +Maps a MMIO region so it can be accessed by the device and returns the
>>> +DMA address of the memory. API should only be used to map device MMIO,
>>> +mapping of RAM is not permitted.
>>> +
>>
>>
>> I think it is confusing to use the dma_ prefix for this peer-to-peer
>> mmio functionality. dma_addr_t is a device's view of host memory.
>> Something like bus_addr_t bus_map_resource(). Doesn't this routine
>> also need the source device in addition to the target device? The
>> resource address is from the perspective of the host cpu, it may be a
>> different address space in the view of two devices relative to each
>> other.
>
>
> Hmm, the trouble with that is that when the DMA master is behind an IOMMU,
> the address space as seen by the device is dynamic and whatever we decide it
> to be, so there is no distinction between a "DMA" address and a "bus"
> address.
>
> In practice the dmaengine API has clearly worked for however long with slave
> MMIO addresses being a dma_addr_t, and it doesn't look like anyone objected
> to the change to phys_addr_t in -next either. If nothing is using bus_addr_t
> anyway, what's the right thing to do? Looking up through higher abstraction
> layers, we have the likes of struct snd_dmaengine_dai_dma_data also
> expecting the slave address to be a dma_addr_t, leading to things like the
> direct casting in bcm2835_i2s_probe() for the non-IOMMU dma != phys != bus
> case that could also be cleaned up with this proposed interface.
>
So the "bus_addr_t" reaction was prompted by the recent activity of
RDMA developers looking to re-use the devm_memremap_pages() api. That
enabling is looking at how to setup peer-to-peer PCI-E cycles for an
RDMA device to deliver data to another local device without taking a
round trip through host memory.
I understand the history of the dmaengine-slave implementation, but it
seems we're getting to point where we need a less overloaded
identifier than "dma" for the case of devices talking to each other.
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH v5 4/9] arm: dma-mapping: add {map, unmap}_resource for iommu ops
[not found] ` <1457404974-1800-1-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
2016-03-08 2:42 ` [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` [PATCH v5 4/9] arm: dma-mapping: add {map,unmap}_resource " Niklas Söderlund
2016-03-08 2:42 ` [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical Niklas Söderlund
` (3 subsequent siblings)
5 siblings, 1 reply; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Niklas Söderlund,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/mm/dma-mapping.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
__free_iova(mapping, iova, len);
}
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+ phys_addr_t phys_addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+ dma_addr_t dma_addr;
+ int ret, prot;
+ phys_addr_t addr = phys_addr & PAGE_MASK;
+ int offset = phys_addr & ~PAGE_MASK;
+ int len = PAGE_ALIGN(size + offset);
+
+ dma_addr = __alloc_iova(mapping, size);
+ if (dma_addr == DMA_ERROR_CODE)
+ return dma_addr;
+
+ prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+ ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+ if (ret < 0)
+ goto fail;
+
+ return dma_addr + offset;
+fail:
+ __free_iova(mapping, dma_addr, size);
+ return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+ dma_addr_t iova = dma_handle & PAGE_MASK;
+ int offset = dma_handle & ~PAGE_MASK;
+ int len = PAGE_ALIGN(size + offset);
+
+ if (!iova)
+ return;
+
+ iommu_unmap(mapping->domain, iova, len);
+ __free_iova(mapping, iova, len);
+}
+
static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
{
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
+ .map_resource = arm_iommu_map_resource,
+ .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask = arm_dma_set_mask,
};
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg = arm_coherent_iommu_unmap_sg,
+ .map_resource = arm_iommu_map_resource,
+ .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask = arm_dma_set_mask,
};
--
2.7.2
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 4/9] arm: dma-mapping: add {map,unmap}_resource for iommu ops
2016-03-08 2:42 ` [PATCH v5 4/9] arm: dma-mapping: add {map, unmap}_resource for iommu ops Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
0 siblings, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu
Cc: robin.murphy, laurent.pinchart, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch, Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/mm/dma-mapping.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 63 insertions(+)
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0eca381..ae2b175 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1814,6 +1814,63 @@ static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
__free_iova(mapping, iova, len);
}
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+ phys_addr_t phys_addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+ dma_addr_t dma_addr;
+ int ret, prot;
+ phys_addr_t addr = phys_addr & PAGE_MASK;
+ int offset = phys_addr & ~PAGE_MASK;
+ int len = PAGE_ALIGN(size + offset);
+
+ dma_addr = __alloc_iova(mapping, size);
+ if (dma_addr == DMA_ERROR_CODE)
+ return dma_addr;
+
+ prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+ ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+ if (ret < 0)
+ goto fail;
+
+ return dma_addr + offset;
+fail:
+ __free_iova(mapping, dma_addr, size);
+ return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+ dma_addr_t iova = dma_handle & PAGE_MASK;
+ int offset = dma_handle & ~PAGE_MASK;
+ int len = PAGE_ALIGN(size + offset);
+
+ if (!iova)
+ return;
+
+ iommu_unmap(mapping->domain, iova, len);
+ __free_iova(mapping, iova, len);
+}
+
static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
{
@@ -1858,6 +1915,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
+ .map_resource = arm_iommu_map_resource,
+ .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask = arm_dma_set_mask,
};
@@ -1873,6 +1933,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg = arm_coherent_iommu_unmap_sg,
+ .map_resource = arm_iommu_map_resource,
+ .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask = arm_dma_set_mask,
};
--
2.7.2
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical
[not found] ` <1457404974-1800-1-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
2016-03-08 2:42 ` [PATCH v5 3/9] dma-mapping: add dma_{map,unmap}_resource Niklas Söderlund
2016-03-08 2:42 ` [PATCH v5 4/9] arm: dma-mapping: add {map, unmap}_resource for iommu ops Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` Niklas Söderlund
[not found] ` <1457404974-1800-6-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
2016-03-08 2:42 ` [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration Niklas Söderlund
` (2 subsequent siblings)
5 siblings, 2 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Niklas Söderlund,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w
Slave addresses coming from a client is physical not dma. Store the
address using the correct data type. This is in preparation for hooking
up the dma-mapping API to the slave addresses.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/dma/sh/rcar-dmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..01cf82f 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -144,8 +144,8 @@ struct rcar_dmac_chan {
unsigned int src_xfer_size;
unsigned int dst_xfer_size;
- dma_addr_t src_slave_addr;
- dma_addr_t dst_slave_addr;
+ phys_addr_t src_slave_addr;
+ phys_addr_t dst_slave_addr;
int mid_rid;
spinlock_t lock;
--
2.7.2
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical
2016-03-08 2:42 ` [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
[not found] ` <1457404974-1800-6-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
1 sibling, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu
Cc: robin.murphy, laurent.pinchart, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch, Niklas Söderlund
Slave addresses coming from a client is physical not dma. Store the
address using the correct data type. This is in preparation for hooking
up the dma-mapping API to the slave addresses.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/dma/sh/rcar-dmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 7820d07..01cf82f 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -144,8 +144,8 @@ struct rcar_dmac_chan {
unsigned int src_xfer_size;
unsigned int dst_xfer_size;
- dma_addr_t src_slave_addr;
- dma_addr_t dst_slave_addr;
+ phys_addr_t src_slave_addr;
+ phys_addr_t dst_slave_addr;
int mid_rid;
spinlock_t lock;
--
2.7.2
^ permalink raw reply related [flat|nested] 54+ messages in thread
[parent not found: <1457404974-1800-6-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>]
* Re: [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical
[not found] ` <1457404974-1800-6-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
@ 2016-03-17 11:30 ` Laurent Pinchart
2016-03-17 11:30 ` Laurent Pinchart
0 siblings, 1 reply; 54+ messages in thread
From: Laurent Pinchart @ 2016-03-17 11:30 UTC (permalink / raw)
To: Niklas Söderlund
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Hi Niklas,
Thank you for the patch.
On Tuesday 08 March 2016 03:42:50 Niklas Söderlund wrote:
> Slave addresses coming from a client is physical not dma. Store the
> address using the correct data type. This is in preparation for hooking
> up the dma-mapping API to the slave addresses.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
> ---
> drivers/dma/sh/rcar-dmac.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 7820d07..01cf82f 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -144,8 +144,8 @@ struct rcar_dmac_chan {
>
> unsigned int src_xfer_size;
> unsigned int dst_xfer_size;
> - dma_addr_t src_slave_addr;
> - dma_addr_t dst_slave_addr;
> + phys_addr_t src_slave_addr;
> + phys_addr_t dst_slave_addr;
This moves the cast from phys_addr_t to dma_addr_t from the driver's DMA
engine operations to other places. I'm not sure there's much value in doing
so. I'd squash this patch with 7/9, the result will be easier to review.
> int mid_rid;
>
> spinlock_t lock;
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical
2016-03-17 11:30 ` Laurent Pinchart
@ 2016-03-17 11:30 ` Laurent Pinchart
0 siblings, 0 replies; 54+ messages in thread
From: Laurent Pinchart @ 2016-03-17 11:30 UTC (permalink / raw)
To: Niklas Söderlund
Cc: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu, robin.murphy, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch
Hi Niklas,
Thank you for the patch.
On Tuesday 08 March 2016 03:42:50 Niklas Söderlund wrote:
> Slave addresses coming from a client is physical not dma. Store the
> address using the correct data type. This is in preparation for hooking
> up the dma-mapping API to the slave addresses.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
> ---
> drivers/dma/sh/rcar-dmac.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 7820d07..01cf82f 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -144,8 +144,8 @@ struct rcar_dmac_chan {
>
> unsigned int src_xfer_size;
> unsigned int dst_xfer_size;
> - dma_addr_t src_slave_addr;
> - dma_addr_t dst_slave_addr;
> + phys_addr_t src_slave_addr;
> + phys_addr_t dst_slave_addr;
This moves the cast from phys_addr_t to dma_addr_t from the driver's DMA
engine operations to other places. I'm not sure there's much value in doing
so. I'd squash this patch with 7/9, the result will be easier to review.
> int mid_rid;
>
> spinlock_t lock;
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration
[not found] ` <1457404974-1800-1-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
` (2 preceding siblings ...)
2016-03-08 2:42 ` [PATCH v5 5/9] dmaengine: rcar-dmac: slave address are physical Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` Niklas Söderlund
[not found] ` <1457404974-1800-7-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
2016-03-08 2:42 ` [PATCH v5 7/9] dmaengine: rcar-dmac: add iommu support for slave transfers Niklas Söderlund
2016-03-08 2:42 ` [PATCH v5 8/9] ARM: dts: r8a7790: add iommus to dmac0 and dmac1 Niklas Söderlund
5 siblings, 2 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Niklas Söderlund,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/dma/sh/rcar-dmac.c | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 01cf82f..b3911fe 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
/*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+ phys_addr_t slave_addr;
+ unsigned int xfer_size;
+};
+
+/*
* struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
* @chan: base DMA channel object
* @iomem: channel I/O memory base
* @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
* @mid_rid: hardware MID/RID for the DMA client using this channel
* @lock: protects the channel CHCR register and the desc members
* @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
- unsigned int src_xfer_size;
- unsigned int dst_xfer_size;
- phys_addr_t src_slave_addr;
- phys_addr_t dst_slave_addr;
+ struct rcar_dmac_chan_slave src;
+ struct rcar_dmac_chan_slave dst;
int mid_rid;
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
| RCAR_DMACHCR_RS_DMARS;
- xfer_size = chan->src_xfer_size;
+ xfer_size = chan->src.xfer_size;
break;
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
| RCAR_DMACHCR_RS_DMARS;
- xfer_size = chan->dst_xfer_size;
+ xfer_size = chan->dst.xfer_size;
break;
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
}
dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src_slave_addr : rchan->dst_slave_addr;
+ ? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
dir, flags, false);
}
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
}
dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src_slave_addr : rchan->dst_slave_addr;
+ ? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
dir, flags, true);
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan *chan,
* We could lock this, but you shouldn't be configuring the
* channel, while using it...
*/
- rchan->src_slave_addr = cfg->src_addr;
- rchan->dst_slave_addr = cfg->dst_addr;
- rchan->src_xfer_size = cfg->src_addr_width;
- rchan->dst_xfer_size = cfg->dst_addr_width;
+ rchan->src.slave_addr = cfg->src_addr;
+ rchan->dst.slave_addr = cfg->dst_addr;
+ rchan->src.xfer_size = cfg->src_addr_width;
+ rchan->dst.xfer_size = cfg->dst_addr_width;
return 0;
}
--
2.7.2
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration
2016-03-08 2:42 ` [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
[not found] ` <1457404974-1800-7-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
1 sibling, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu
Cc: robin.murphy, laurent.pinchart, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch, Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/dma/sh/rcar-dmac.c | 38 ++++++++++++++++++++++----------------
1 file changed, 22 insertions(+), 16 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 01cf82f..b3911fe 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
/*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+ phys_addr_t slave_addr;
+ unsigned int xfer_size;
+};
+
+/*
* struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
* @chan: base DMA channel object
* @iomem: channel I/O memory base
* @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
* @mid_rid: hardware MID/RID for the DMA client using this channel
* @lock: protects the channel CHCR register and the desc members
* @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
- unsigned int src_xfer_size;
- unsigned int dst_xfer_size;
- phys_addr_t src_slave_addr;
- phys_addr_t dst_slave_addr;
+ struct rcar_dmac_chan_slave src;
+ struct rcar_dmac_chan_slave dst;
int mid_rid;
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
| RCAR_DMACHCR_RS_DMARS;
- xfer_size = chan->src_xfer_size;
+ xfer_size = chan->src.xfer_size;
break;
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
| RCAR_DMACHCR_RS_DMARS;
- xfer_size = chan->dst_xfer_size;
+ xfer_size = chan->dst.xfer_size;
break;
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
}
dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src_slave_addr : rchan->dst_slave_addr;
+ ? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
dir, flags, false);
}
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
}
dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src_slave_addr : rchan->dst_slave_addr;
+ ? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
dir, flags, true);
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan *chan,
* We could lock this, but you shouldn't be configuring the
* channel, while using it...
*/
- rchan->src_slave_addr = cfg->src_addr;
- rchan->dst_slave_addr = cfg->dst_addr;
- rchan->src_xfer_size = cfg->src_addr_width;
- rchan->dst_xfer_size = cfg->dst_addr_width;
+ rchan->src.slave_addr = cfg->src_addr;
+ rchan->dst.slave_addr = cfg->dst_addr;
+ rchan->src.xfer_size = cfg->src_addr_width;
+ rchan->dst.xfer_size = cfg->dst_addr_width;
return 0;
}
--
2.7.2
^ permalink raw reply related [flat|nested] 54+ messages in thread
[parent not found: <1457404974-1800-7-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>]
* Re: [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration
[not found] ` <1457404974-1800-7-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
@ 2016-03-17 11:28 ` Laurent Pinchart
2016-03-17 11:28 ` Laurent Pinchart
0 siblings, 1 reply; 54+ messages in thread
From: Laurent Pinchart @ 2016-03-17 11:28 UTC (permalink / raw)
To: Niklas Söderlund
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, arnd-r2nGTMty4D4,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ,
vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
Hi Niklas,
Thank you for the patch.
On Tuesday 08 March 2016 03:42:51 Niklas Söderlund wrote:
> Group slave address and transfer size in own structs for source and
> destination. This is in preparation for hooking up the dma-mapping API
> to the slave addresses.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
> ---
> drivers/dma/sh/rcar-dmac.c | 38 ++++++++++++++++++++++----------------
> 1 file changed, 22 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 01cf82f..b3911fe 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
> sizeof(struct rcar_dmac_xfer_chunk))
>
> /*
> + * struct rcar_dmac_chan_slave - Slave configuration
> + * @slave_addr: slave memory address
> + * @xfer_size: size (in bytes) of hardware transfers
> + */
> +struct rcar_dmac_chan_slave {
> + phys_addr_t slave_addr;
> + unsigned int xfer_size;
> +};
> +
> +/*
> * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
> * @chan: base DMA channel object
> * @iomem: channel I/O memory base
> * @index: index of this channel in the controller
> - * @src_xfer_size: size (in bytes) of hardware transfers on the source side
> - * @dst_xfer_size: size (in bytes) of hardware transfers on the
> destination side - * @src_slave_addr: slave source memory address
> - * @dst_slave_addr: slave destination memory address
> + * @src: slave memory address and size on the source side
> + * @dst: slave memory address and size on the destination side
> * @mid_rid: hardware MID/RID for the DMA client using this channel
> * @lock: protects the channel CHCR register and the desc members
> * @desc.free: list of free descriptors
> @@ -142,10 +150,8 @@ struct rcar_dmac_chan {
> void __iomem *iomem;
> unsigned int index;
>
> - unsigned int src_xfer_size;
> - unsigned int dst_xfer_size;
> - phys_addr_t src_slave_addr;
> - phys_addr_t dst_slave_addr;
> + struct rcar_dmac_chan_slave src;
> + struct rcar_dmac_chan_slave dst;
> int mid_rid;
>
> spinlock_t lock;
> @@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct
> rcar_dmac_chan *chan, case DMA_DEV_TO_MEM:
> chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
>
> | RCAR_DMACHCR_RS_DMARS;
>
> - xfer_size = chan->src_xfer_size;
> + xfer_size = chan->src.xfer_size;
> break;
>
> case DMA_MEM_TO_DEV:
> chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
>
> | RCAR_DMACHCR_RS_DMARS;
>
> - xfer_size = chan->dst_xfer_size;
> + xfer_size = chan->dst.xfer_size;
> break;
>
> case DMA_MEM_TO_MEM:
> @@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct
> scatterlist *sgl, }
>
> dev_addr = dir == DMA_DEV_TO_MEM
> - ? rchan->src_slave_addr : rchan->dst_slave_addr;
> + ? rchan->src.slave_addr : rchan->dst.slave_addr;
> return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
> dir, flags, false);
> }
> @@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan,
> dma_addr_t buf_addr, }
>
> dev_addr = dir == DMA_DEV_TO_MEM
> - ? rchan->src_slave_addr : rchan->dst_slave_addr;
> + ? rchan->src.slave_addr : rchan->dst.slave_addr;
> desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
> dir, flags, true);
>
> @@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan
> *chan, * We could lock this, but you shouldn't be configuring the
> * channel, while using it...
> */
> - rchan->src_slave_addr = cfg->src_addr;
> - rchan->dst_slave_addr = cfg->dst_addr;
> - rchan->src_xfer_size = cfg->src_addr_width;
> - rchan->dst_xfer_size = cfg->dst_addr_width;
> + rchan->src.slave_addr = cfg->src_addr;
> + rchan->dst.slave_addr = cfg->dst_addr;
> + rchan->src.xfer_size = cfg->src_addr_width;
> + rchan->dst.xfer_size = cfg->dst_addr_width;
>
> return 0;
> }
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration
2016-03-17 11:28 ` Laurent Pinchart
@ 2016-03-17 11:28 ` Laurent Pinchart
0 siblings, 0 replies; 54+ messages in thread
From: Laurent Pinchart @ 2016-03-17 11:28 UTC (permalink / raw)
To: Niklas Söderlund
Cc: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu, robin.murphy, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch
Hi Niklas,
Thank you for the patch.
On Tuesday 08 March 2016 03:42:51 Niklas Söderlund wrote:
> Group slave address and transfer size in own structs for source and
> destination. This is in preparation for hooking up the dma-mapping API
> to the slave addresses.
>
> Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> ---
> drivers/dma/sh/rcar-dmac.c | 38 ++++++++++++++++++++++----------------
> 1 file changed, 22 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 01cf82f..b3911fe 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
> sizeof(struct rcar_dmac_xfer_chunk))
>
> /*
> + * struct rcar_dmac_chan_slave - Slave configuration
> + * @slave_addr: slave memory address
> + * @xfer_size: size (in bytes) of hardware transfers
> + */
> +struct rcar_dmac_chan_slave {
> + phys_addr_t slave_addr;
> + unsigned int xfer_size;
> +};
> +
> +/*
> * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
> * @chan: base DMA channel object
> * @iomem: channel I/O memory base
> * @index: index of this channel in the controller
> - * @src_xfer_size: size (in bytes) of hardware transfers on the source side
> - * @dst_xfer_size: size (in bytes) of hardware transfers on the
> destination side - * @src_slave_addr: slave source memory address
> - * @dst_slave_addr: slave destination memory address
> + * @src: slave memory address and size on the source side
> + * @dst: slave memory address and size on the destination side
> * @mid_rid: hardware MID/RID for the DMA client using this channel
> * @lock: protects the channel CHCR register and the desc members
> * @desc.free: list of free descriptors
> @@ -142,10 +150,8 @@ struct rcar_dmac_chan {
> void __iomem *iomem;
> unsigned int index;
>
> - unsigned int src_xfer_size;
> - unsigned int dst_xfer_size;
> - phys_addr_t src_slave_addr;
> - phys_addr_t dst_slave_addr;
> + struct rcar_dmac_chan_slave src;
> + struct rcar_dmac_chan_slave dst;
> int mid_rid;
>
> spinlock_t lock;
> @@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct
> rcar_dmac_chan *chan, case DMA_DEV_TO_MEM:
> chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
>
> | RCAR_DMACHCR_RS_DMARS;
>
> - xfer_size = chan->src_xfer_size;
> + xfer_size = chan->src.xfer_size;
> break;
>
> case DMA_MEM_TO_DEV:
> chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
>
> | RCAR_DMACHCR_RS_DMARS;
>
> - xfer_size = chan->dst_xfer_size;
> + xfer_size = chan->dst.xfer_size;
> break;
>
> case DMA_MEM_TO_MEM:
> @@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct
> scatterlist *sgl, }
>
> dev_addr = dir == DMA_DEV_TO_MEM
> - ? rchan->src_slave_addr : rchan->dst_slave_addr;
> + ? rchan->src.slave_addr : rchan->dst.slave_addr;
> return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
> dir, flags, false);
> }
> @@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan,
> dma_addr_t buf_addr, }
>
> dev_addr = dir == DMA_DEV_TO_MEM
> - ? rchan->src_slave_addr : rchan->dst_slave_addr;
> + ? rchan->src.slave_addr : rchan->dst.slave_addr;
> desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
> dir, flags, true);
>
> @@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan
> *chan, * We could lock this, but you shouldn't be configuring the
> * channel, while using it...
> */
> - rchan->src_slave_addr = cfg->src_addr;
> - rchan->dst_slave_addr = cfg->dst_addr;
> - rchan->src_xfer_size = cfg->src_addr_width;
> - rchan->dst_xfer_size = cfg->dst_addr_width;
> + rchan->src.slave_addr = cfg->src_addr;
> + rchan->dst.slave_addr = cfg->dst_addr;
> + rchan->src.xfer_size = cfg->src_addr_width;
> + rchan->dst.xfer_size = cfg->dst_addr_width;
>
> return 0;
> }
--
Regards,
Laurent Pinchart
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH v5 7/9] dmaengine: rcar-dmac: add iommu support for slave transfers
[not found] ` <1457404974-1800-1-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
` (3 preceding siblings ...)
2016-03-08 2:42 ` [PATCH v5 6/9] dmaengine: rcar-dmac: group slave configuration Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` [PATCH v5 8/9] ARM: dts: r8a7790: add iommus to dmac0 and dmac1 Niklas Söderlund
5 siblings, 1 reply; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Niklas Söderlund,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/dma/sh/rcar-dmac.c | 82 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 74 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b3911fe..56816e3 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
};
/*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+ dma_addr_t addr;
+ enum dma_data_direction dir;
+ struct rcar_dmac_chan_slave slave;
+};
+
+/*
* struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
* @chan: base DMA channel object
* @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+ struct rcar_dmac_chan_map map;
int mid_rid;
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
DMA_MEM_TO_MEM, flags, false);
}
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+ enum dma_transfer_direction dir)
+{
+ struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+ struct rcar_dmac_chan_map *map = &rchan->map;
+ phys_addr_t dev_addr;
+ size_t dev_size;
+ enum dma_data_direction dev_dir;
+
+ if (dir == DMA_DEV_TO_MEM) {
+ dev_addr = rchan->src.slave_addr;
+ dev_size = rchan->src.xfer_size;
+ dev_dir = DMA_TO_DEVICE;
+ } else {
+ dev_addr = rchan->dst.slave_addr;
+ dev_size = rchan->dst.xfer_size;
+ dev_dir = DMA_FROM_DEVICE;
+ }
+
+ /* Reuse current map if possible. */
+ if (dev_addr == map->slave.slave_addr &&
+ dev_size == map->slave.xfer_size &&
+ dev_dir == map->dir)
+ return 0;
+
+ /* Remove old mapping if present. */
+ if (map->slave.xfer_size)
+ dma_unmap_resource(chan->device->dev, map->addr,
+ map->slave.xfer_size, map->dir, NULL);
+ map->slave.xfer_size = 0;
+
+ /* Create new slave address map. */
+ map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+ dev_dir, NULL);
+
+ if (dma_mapping_error(chan->device->dev, map->addr)) {
+ dev_err(chan->device->dev,
+ "chan%u: failed to map %zx@%pap", rchan->index,
+ dev_size, &dev_addr);
+ return -EIO;
+ }
+
+ dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+ rchan->index, dev_size, &dev_addr, &map->addr,
+ dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+ map->slave.slave_addr = dev_addr;
+ map->slave.xfer_size = dev_size;
+ map->dir = dev_dir;
+
+ return 0;
+}
+
static struct dma_async_tx_descriptor *
rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
{
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
- dma_addr_t dev_addr;
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
return NULL;
}
- dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src.slave_addr : rchan->dst.slave_addr;
- return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+ if (rcar_dmac_map_slave_addr(chan, dir))
+ return NULL;
+
+ return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
dir, flags, false);
}
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
- dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
return NULL;
}
+ if (rcar_dmac_map_slave_addr(chan, dir))
+ return NULL;
+
sg_len = buf_len / period_len;
if (sg_len > RCAR_DMAC_MAX_SG_LEN) {
dev_err(chan->device->dev,
@@ -1098,9 +1166,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
sg_dma_len(&sgl[i]) = period_len;
}
- dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src.slave_addr : rchan->dst.slave_addr;
- desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+ desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
dir, flags, true);
kfree(sgl);
--
2.7.2
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 7/9] dmaengine: rcar-dmac: add iommu support for slave transfers
2016-03-08 2:42 ` [PATCH v5 7/9] dmaengine: rcar-dmac: add iommu support for slave transfers Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
0 siblings, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu
Cc: robin.murphy, laurent.pinchart, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch, Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
---
drivers/dma/sh/rcar-dmac.c | 82 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 74 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b3911fe..56816e3 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
};
/*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+ dma_addr_t addr;
+ enum dma_data_direction dir;
+ struct rcar_dmac_chan_slave slave;
+};
+
+/*
* struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
* @chan: base DMA channel object
* @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+ struct rcar_dmac_chan_map map;
int mid_rid;
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dma_dest,
DMA_MEM_TO_MEM, flags, false);
}
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+ enum dma_transfer_direction dir)
+{
+ struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+ struct rcar_dmac_chan_map *map = &rchan->map;
+ phys_addr_t dev_addr;
+ size_t dev_size;
+ enum dma_data_direction dev_dir;
+
+ if (dir == DMA_DEV_TO_MEM) {
+ dev_addr = rchan->src.slave_addr;
+ dev_size = rchan->src.xfer_size;
+ dev_dir = DMA_TO_DEVICE;
+ } else {
+ dev_addr = rchan->dst.slave_addr;
+ dev_size = rchan->dst.xfer_size;
+ dev_dir = DMA_FROM_DEVICE;
+ }
+
+ /* Reuse current map if possible. */
+ if (dev_addr == map->slave.slave_addr &&
+ dev_size == map->slave.xfer_size &&
+ dev_dir == map->dir)
+ return 0;
+
+ /* Remove old mapping if present. */
+ if (map->slave.xfer_size)
+ dma_unmap_resource(chan->device->dev, map->addr,
+ map->slave.xfer_size, map->dir, NULL);
+ map->slave.xfer_size = 0;
+
+ /* Create new slave address map. */
+ map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+ dev_dir, NULL);
+
+ if (dma_mapping_error(chan->device->dev, map->addr)) {
+ dev_err(chan->device->dev,
+ "chan%u: failed to map %zx@%pap", rchan->index,
+ dev_size, &dev_addr);
+ return -EIO;
+ }
+
+ dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+ rchan->index, dev_size, &dev_addr, &map->addr,
+ dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+ map->slave.slave_addr = dev_addr;
+ map->slave.xfer_size = dev_size;
+ map->dir = dev_dir;
+
+ return 0;
+}
+
static struct dma_async_tx_descriptor *
rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
{
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
- dma_addr_t dev_addr;
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
return NULL;
}
- dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src.slave_addr : rchan->dst.slave_addr;
- return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+ if (rcar_dmac_map_slave_addr(chan, dir))
+ return NULL;
+
+ return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
dir, flags, false);
}
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
- dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
return NULL;
}
+ if (rcar_dmac_map_slave_addr(chan, dir))
+ return NULL;
+
sg_len = buf_len / period_len;
if (sg_len > RCAR_DMAC_MAX_SG_LEN) {
dev_err(chan->device->dev,
@@ -1098,9 +1166,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr,
sg_dma_len(&sgl[i]) = period_len;
}
- dev_addr = dir == DMA_DEV_TO_MEM
- ? rchan->src.slave_addr : rchan->dst.slave_addr;
- desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+ desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
dir, flags, true);
kfree(sgl);
--
2.7.2
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 8/9] ARM: dts: r8a7790: add iommus to dmac0 and dmac1
[not found] ` <1457404974-1800-1-git-send-email-niklas.soderlund+renesas-1zkq55x86MTxsAP9Fp7wbw@public.gmane.org>
` (4 preceding siblings ...)
2016-03-08 2:42 ` [PATCH v5 7/9] dmaengine: rcar-dmac: add iommu support for slave transfers Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
2016-03-08 2:42 ` Niklas Söderlund
5 siblings, 1 reply; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul-ral2JQCrhuEAvxtiuMwx3w,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
dmaengine-u79uwXL29TY76Z2rM5mHXA,
iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA
Cc: linux-arch-u79uwXL29TY76Z2rM5mHXA, Niklas Söderlund,
geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ, arnd-r2nGTMty4D4,
linus.walleij-QSEj5FYQhm4dnm+yROfE0A,
laurent.pinchart-ryLnwIuWjnjg/C1BVhZhaw,
dan.j.williams-ral2JQCrhuEAvxtiuMwx3w
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/r8a7790.dtsi | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 26772f7..c600daa 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <&cpg_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+ iommus = <&ipmmu_ds 0>,
+ <&ipmmu_ds 1>,
+ <&ipmmu_ds 2>,
+ <&ipmmu_ds 3>,
+ <&ipmmu_ds 4>,
+ <&ipmmu_ds 5>,
+ <&ipmmu_ds 6>,
+ <&ipmmu_ds 7>,
+ <&ipmmu_ds 8>,
+ <&ipmmu_ds 9>,
+ <&ipmmu_ds 10>,
+ <&ipmmu_ds 11>,
+ <&ipmmu_ds 12>,
+ <&ipmmu_ds 13>,
+ <&ipmmu_ds 14>;
};
dmac1: dma-controller@e6720000 {
@@ -325,6 +340,21 @@
power-domains = <&cpg_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+ iommus = <&ipmmu_ds 15>,
+ <&ipmmu_ds 16>,
+ <&ipmmu_ds 17>,
+ <&ipmmu_ds 18>,
+ <&ipmmu_ds 19>,
+ <&ipmmu_ds 20>,
+ <&ipmmu_ds 21>,
+ <&ipmmu_ds 22>,
+ <&ipmmu_ds 23>,
+ <&ipmmu_ds 24>,
+ <&ipmmu_ds 25>,
+ <&ipmmu_ds 26>,
+ <&ipmmu_ds 27>,
+ <&ipmmu_ds 28>,
+ <&ipmmu_ds 29>;
};
audma0: dma-controller@ec700000 {
--
2.7.2
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply related [flat|nested] 54+ messages in thread
* [PATCH v5 8/9] ARM: dts: r8a7790: add iommus to dmac0 and dmac1
2016-03-08 2:42 ` [PATCH v5 8/9] ARM: dts: r8a7790: add iommus to dmac0 and dmac1 Niklas Söderlund
@ 2016-03-08 2:42 ` Niklas Söderlund
0 siblings, 0 replies; 54+ messages in thread
From: Niklas Söderlund @ 2016-03-08 2:42 UTC (permalink / raw)
To: vinod.koul, linux-renesas-soc, linux-arm-kernel, linux-kernel,
dmaengine, iommu
Cc: robin.murphy, laurent.pinchart, geert+renesas, linus.walleij,
dan.j.williams, arnd, linux-arch, Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
arch/arm/boot/dts/r8a7790.dtsi | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 26772f7..c600daa 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -294,6 +294,21 @@
power-domains = <&cpg_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+ iommus = <&ipmmu_ds 0>,
+ <&ipmmu_ds 1>,
+ <&ipmmu_ds 2>,
+ <&ipmmu_ds 3>,
+ <&ipmmu_ds 4>,
+ <&ipmmu_ds 5>,
+ <&ipmmu_ds 6>,
+ <&ipmmu_ds 7>,
+ <&ipmmu_ds 8>,
+ <&ipmmu_ds 9>,
+ <&ipmmu_ds 10>,
+ <&ipmmu_ds 11>,
+ <&ipmmu_ds 12>,
+ <&ipmmu_ds 13>,
+ <&ipmmu_ds 14>;
};
dmac1: dma-controller@e6720000 {
@@ -325,6 +340,21 @@
power-domains = <&cpg_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+ iommus = <&ipmmu_ds 15>,
+ <&ipmmu_ds 16>,
+ <&ipmmu_ds 17>,
+ <&ipmmu_ds 18>,
+ <&ipmmu_ds 19>,
+ <&ipmmu_ds 20>,
+ <&ipmmu_ds 21>,
+ <&ipmmu_ds 22>,
+ <&ipmmu_ds 23>,
+ <&ipmmu_ds 24>,
+ <&ipmmu_ds 25>,
+ <&ipmmu_ds 26>,
+ <&ipmmu_ds 27>,
+ <&ipmmu_ds 28>,
+ <&ipmmu_ds 29>;
};
audma0: dma-controller@ec700000 {
--
2.7.2
^ permalink raw reply related [flat|nested] 54+ messages in thread