drivers/dma/fsldma.c | 2 +- drivers/dma/fsldma.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
On 64-bit QorIQ platforms like T4240, the CPU supports 40-bit addressing
and memory configurations > 64GiB. The fsldma driver is limiting itself
to only 64GiB in all Elo configurations.
Setup fsldma driver to make use of the full 40-bit addressing space,
specifically on the e5500 and e6500 CPUs.
Signed-off-by: Ben Collins <bcollins@kernel.org>
Cc: Zhang Wei <zw@zh-kernel.org>
Cc: Vinod Koul <vkoul@kernel.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: dmaengine@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
drivers/dma/fsldma.c | 2 +-
drivers/dma/fsldma.h | 7 +++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
index b5e7d18b97669..8c01963ad47d8 100644
--- a/drivers/dma/fsldma.c
+++ b/drivers/dma/fsldma.c
@@ -1254,7 +1254,7 @@ static int fsldma_of_probe(struct platform_device *op)
fdev->common.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
fdev->common.residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
- dma_set_mask(&(op->dev), DMA_BIT_MASK(36));
+ dma_set_mask(&(op->dev), DMA_BIT_MASK(ELO_MAX_PHYS_BITS));
platform_set_drvdata(op, fdev);
diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h
index 308bed0a560ac..1e7bd37208412 100644
--- a/drivers/dma/fsldma.h
+++ b/drivers/dma/fsldma.h
@@ -13,6 +13,13 @@
#include <linux/dmapool.h>
#include <linux/dmaengine.h>
+/* Physical addressing capability */
+#if defined(CONFIG_E6500_CPU) || defined(CONFIG_E5500_CPU)
+#define ELO_MAX_PHYS_BITS 40
+#else
+#define ELO_MAX_PHYS_BITS 36
+#endif
+
/* Define data structures needed by Freescale
* MPC8540 and MPC8349 DMA controller.
*/
--
2.49.0
--
Ben Collins
https://libjwt.io
https://github.com/benmcollins
--
3EC9 7598 1672 961A 1139 173A 5D5A 57C7 242B 22CF
On Tue, Apr 22, 2025, at 04:49, Ben Collins wrote:
> On 64-bit QorIQ platforms like T4240, the CPU supports 40-bit addressing
> and memory configurations > 64GiB. The fsldma driver is limiting itself
> to only 64GiB in all Elo configurations.
>
> Setup fsldma driver to make use of the full 40-bit addressing space,
> specifically on the e5500 and e6500 CPUs.
I don't think making the mask depend on a compile-time option is
correct, e.g. when you build a combined 32-bit kernel for e500 and
e5500, you set a different mask compared to an e500-only kernel.
The question here is whether the mask is a limitation of the
IP block or the bus it's connected to, of if there is any
limitation at all:
- The driver just writes the DMA address as a 64-bit register,
so most likely the DMA device can in fact do wider addressing,
and any limitation is either in the bus or the available
memory
- SoCs that don't set a dma-ranges property in the parent bus
are normally still capped to 32 bit DMA. I don't see those
properties, so unless there is a special hack on those chips,
you get 32 bit DMA regardless of what DMA mask the driver
requests
- If there are chips that have more than 64GB of RAM installed
but have a limitation in the way the DMA engine is wired
up to 36 bits, that should be reflected in the dma-ranges
property, not the device driver.
- If the limitation is indeed specific to the version of the
IP block, this would normally need to be detected based on
the compatible string of the DMA engine itself, not a compile
time setting.
Arnd
On Tue, Apr 22, 2025 at 08:34:55AM -0500, Arnd Bergmann wrote: > On Tue, Apr 22, 2025, at 04:49, Ben Collins wrote: > > On 64-bit QorIQ platforms like T4240, the CPU supports 40-bit addressing > > and memory configurations > 64GiB. The fsldma driver is limiting itself > > to only 64GiB in all Elo configurations. > > > > Setup fsldma driver to make use of the full 40-bit addressing space, > > specifically on the e5500 and e6500 CPUs. > ... > > - The driver just writes the DMA address as a 64-bit register, > so most likely the DMA device can in fact do wider addressing, > and any limitation is either in the bus or the available > memory > > - SoCs that don't set a dma-ranges property in the parent bus > are normally still capped to 32 bit DMA. I don't see those > properties, so unless there is a special hack on those chips, > you get 32 bit DMA regardless of what DMA mask the driver > requests I've yet to see a dma-ranges property in any of the Freescale PowerPC device trees. I'll check on this, but I think it's a seperate issue. The main thing is just to configure the dma hw correctly. > - If there are chips that have more than 64GB of RAM installed > but have a limitation in the way the DMA engine is wired > up to 36 bits, that should be reflected in the dma-ranges > property, not the device driver. > > - If the limitation is indeed specific to the version of the > IP block, this would normally need to be detected based on > the compatible string of the DMA engine itself, not a compile > time setting. So a little research shows that these 3 compatible strings in the fsldma are: fsl,elo3-dma: 40-bit fsl,eloplus-dma: 36-bit fsl,elo-dma: 32-bit I'll rework it so addressing is based on the compatible string. -- Ben Collins https://libjwt.io https://github.com/benmcollins -- 3EC9 7598 1672 961A 1139 173A 5D5A 57C7 242B 22CF
On Tue, Apr 22, 2025, at 09:12, Ben Collins wrote:
> On Tue, Apr 22, 2025 at 08:34:55AM -0500, Arnd Bergmann wrote:
>>
>> - SoCs that don't set a dma-ranges property in the parent bus
>> are normally still capped to 32 bit DMA. I don't see those
>> properties, so unless there is a special hack on those chips,
>> you get 32 bit DMA regardless of what DMA mask the driver
>> requests
>
> I've yet to see a dma-ranges property in any of the Freescale PowerPC
> device trees.
Right, but this could just mean that they end up using SWIOTLB
to bounce the high DMA pages or use an IOMMU rather than actually
translating the physical address to a dma address.
The only special case I see for freescale powerpc chips is the
PCI dma_set_mask() handler that does
static void fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
{
/*
* Fix up PCI devices that are able to DMA to the large inbound
* mapping that allows addressing any RAM address from across PCI.
*/
if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) {
dev->bus_dma_limit = 0;
dev->archdata.dma_offset = pci64_dma_offset;
}
}
but that should not apply here because this is not a PCI device.
> I'll check on this, but I think it's a seperate issue. The main thing is
> just to configure the dma hw correctly.
I think it's still important to check this before changing the
driver: if the larger mask doesn't actually have any effect now
because the DT caps the DMA at 4GB, then it might break later
when someone adds the correct dma-ranges properties.
> So a little research shows that these 3 compatible strings in
> the fsldma are:
>
> fsl,elo3-dma: 40-bit
> fsl,eloplus-dma: 36-bit
> fsl,elo-dma: 32-bit
>
> I'll rework it so addressing is based on the compatible string.
Sounds good, yes. Just to clarify: where did you find those
limits? Are you sure those are not just the maximum addressable
amounts of physical RAM on the chips that use the respective
controllers?
Arnd
On Tue, Apr 22, 2025 at 09:59:42AM -0500, Arnd Bergmann wrote:
> On Tue, Apr 22, 2025, at 09:12, Ben Collins wrote:
> > On Tue, Apr 22, 2025 at 08:34:55AM -0500, Arnd Bergmann wrote:
> >>
> >> - SoCs that don't set a dma-ranges property in the parent bus
> >> are normally still capped to 32 bit DMA. I don't see those
> >> properties, so unless there is a special hack on those chips,
> >> you get 32 bit DMA regardless of what DMA mask the driver
> >> requests
> >
> > I've yet to see a dma-ranges property in any of the Freescale PowerPC
> > device trees.
>
> Right, but this could just mean that they end up using SWIOTLB
> to bounce the high DMA pages or use an IOMMU rather than actually
> translating the physical address to a dma address.
There's a few things going on. The Local Address Window can shift
anywhere in the 64-bit address space and be as wide as the physical
address (40-bit on T4240, 36-bit on P4080). I think this is mainly for
IO to PCIe and RapidIO, though.
> The only special case I see for freescale powerpc chips is the
> PCI dma_set_mask() handler that does
>
> static void fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
> {
> /*
> * Fix up PCI devices that are able to DMA to the large inbound
> * mapping that allows addressing any RAM address from across PCI.
> */
> if (dev_is_pci(dev) && dma_mask >= pci64_dma_offset * 2 - 1) {
> dev->bus_dma_limit = 0;
> dev->archdata.dma_offset = pci64_dma_offset;
> }
> }
>
> but that should not apply here because this is not a PCI device.
Right.
> > I'll check on this, but I think it's a seperate issue. The main thing is
> > just to configure the dma hw correctly.
>
> I think it's still important to check this before changing the
> driver: if the larger mask doesn't actually have any effect now
> because the DT caps the DMA at 4GB, then it might break later
> when someone adds the correct dma-ranges properties.
I'm adding dma-ranges to my dt for testing.
> > So a little research shows that these 3 compatible strings in
> > the fsldma are:
> >
> > fsl,elo3-dma: 40-bit
> > fsl,eloplus-dma: 36-bit
> > fsl,elo-dma: 32-bit
> >
> > I'll rework it so addressing is based on the compatible string.
>
> Sounds good, yes. Just to clarify: where did you find those
> limits? Are you sure those are not just the maximum addressable
> amounts of physical RAM on the chips that use the respective
> controllers?
This is where things might be more interesting. The P4080RM and T4240RM
is where I got this information. Register "cdar" in the fsldma code. This
makes up 0x08 and 0x0c registers.
In the RM 0x08 is the extended address register. On P4080 it says this
holds the top 4 bits of the 36-bit address, and on T4240 it says the top
8 bits of the 40-bit address. So the asynx_tx physical address needs to
be masked to the 36-bit or 40-bit.
--
Ben Collins
https://libjwt.io
https://github.com/benmcollins
--
3EC9 7598 1672 961A 1139 173A 5D5A 57C7 242B 22CF
On Tue, Apr 22, 2025, at 10:56, Ben Collins wrote:
> On Tue, Apr 22, 2025 at 09:59:42AM -0500, Arnd Bergmann wrote:
>>
>> Right, but this could just mean that they end up using SWIOTLB
>> to bounce the high DMA pages or use an IOMMU rather than actually
>> translating the physical address to a dma address.
>
> There's a few things going on. The Local Address Window can shift
> anywhere in the 64-bit address space and be as wide as the physical
> address (40-bit on T4240, 36-bit on P4080). I think this is mainly for
> IO to PCIe and RapidIO, though.
There are usually two sets of registers, not sure which one the Local
Address Window refers to:
- Translation of MMIO addresses (PCI BAR and device registers) when
accessed from CPU and possibly from P2P DMA, these are represented
by the 'ranges' property in DT.
- Translation of physical memory when accessed from a DMA bus master,
represented by the 'dma-ranges' property.
The latter is what the dma-mapping API needs. This code has changed
a lot over the years, but in the current version the idea is that
the limit enforced by the driver through dma_set_mask() is independent
of the limit enforced by the platform bus based on the dma-ranges
property.
The bit that matters in the end is the intersection of both,
so dma_map_single() etc only maps a page that is addressable
by both the device and the bus.
>> > I'll check on this, but I think it's a seperate issue. The main thing is
>> > just to configure the dma hw correctly.
>>
>> I think it's still important to check this before changing the
>> driver: if the larger mask doesn't actually have any effect now
>> because the DT caps the DMA at 4GB, then it might break later
>> when someone adds the correct dma-ranges properties.
>
> I'm adding dma-ranges to my dt for testing.
Ok. The other thing you can try is to printk() the dev->bus_dma_limit
to see if it even tries to use >32bit addressing.
>> > So a little research shows that these 3 compatible strings in
>> > the fsldma are:
>> >
>> > fsl,elo3-dma: 40-bit
>> > fsl,eloplus-dma: 36-bit
>> > fsl,elo-dma: 32-bit
>> >
>> > I'll rework it so addressing is based on the compatible string.
>>
>> Sounds good, yes. Just to clarify: where did you find those
>> limits? Are you sure those are not just the maximum addressable
>> amounts of physical RAM on the chips that use the respective
>> controllers?
>
> This is where things might be more interesting. The P4080RM and T4240RM
> is where I got this information. Register "cdar" in the fsldma code. This
> makes up 0x08 and 0x0c registers.
> In the RM 0x08 is the extended address register. On P4080 it says this
> holds the top 4 bits of the 36-bit address, and on T4240 it says the top
> 8 bits of the 40-bit address. So the asynx_tx physical address needs to
> be masked to the 36-bit or 40-bit.
Ok, makes sense.
Arnd
On Tue, Apr 22, 2025 at 11:25:40AM -0500, Arnd Bergmann wrote: > On Tue, Apr 22, 2025, at 10:56, Ben Collins wrote: > > On Tue, Apr 22, 2025 at 09:59:42AM -0500, Arnd Bergmann wrote: > >> > >> Right, but this could just mean that they end up using SWIOTLB > >> to bounce the high DMA pages or use an IOMMU rather than actually > >> translating the physical address to a dma address. > > > > There's a few things going on. The Local Address Window can shift > > anywhere in the 64-bit address space and be as wide as the physical > > address (40-bit on T4240, 36-bit on P4080). I think this is mainly for > > IO to PCIe and RapidIO, though. > > There are usually two sets of registers, not sure which one the Local > Address Window refers to: > > - Translation of MMIO addresses (PCI BAR and device registers) when > accessed from CPU and possibly from P2P DMA, these are represented > by the 'ranges' property in DT. > > - Translation of physical memory when accessed from a DMA bus master, > represented by the 'dma-ranges' property. > > The latter is what the dma-mapping API needs. This code has changed > a lot over the years, but in the current version the idea is that > the limit enforced by the driver through dma_set_mask() is independent > of the limit enforced by the platform bus based on the dma-ranges > property. LAWs translate physical addresses to IOVA (PCIe/RapidIO/SoC resources) and are used for all master level translations (CPU, DMA, PCIe, DDR, RapidIO). This is at the interconnect level. I believe LAWs cover both of these cases. > >> > I'll check on this, but I think it's a seperate issue. The main thing is > >> > just to configure the dma hw correctly. > >> > >> I think it's still important to check this before changing the > >> driver: if the larger mask doesn't actually have any effect now > >> because the DT caps the DMA at 4GB, then it might break later > >> when someone adds the correct dma-ranges properties. > > > > I'm adding dma-ranges to my dt for testing. > > Ok. The other thing you can try is to printk() the dev->bus_dma_limit > to see if it even tries to use >32bit addressing. Did that. Every combination of IOMMU on/off and dma-ranges in my dt always showed bus_dma_limit as 0x0. As an aside, if you could give this a quick check, I can send the revised patch. Appreciate the feedback. https://github.com/benmcollins/linux/commit/2f2946b33294ebff2fdaae6d1eadc976147470d6 -- Ben Collins https://libjwt.io https://github.com/benmcollins -- 3EC9 7598 1672 961A 1139 173A 5D5A 57C7 242B 22CF
On Tue, Apr 22, 2025, at 23:10, Ben Collins wrote:
> On Tue, Apr 22, 2025 at 11:25:40AM -0500, Arnd Bergmann wrote:
>> On Tue, Apr 22, 2025, at 10:56, Ben Collins wrote:
>>
>> >> > I'll check on this, but I think it's a seperate issue. The main thing is
>> >> > just to configure the dma hw correctly.
>> >>
>> >> I think it's still important to check this before changing the
>> >> driver: if the larger mask doesn't actually have any effect now
>> >> because the DT caps the DMA at 4GB, then it might break later
>> >> when someone adds the correct dma-ranges properties.
>> >
>> > I'm adding dma-ranges to my dt for testing.
>>
>> Ok. The other thing you can try is to printk() the dev->bus_dma_limit
>> to see if it even tries to use >32bit addressing.
>
> Did that. Every combination of IOMMU on/off and dma-ranges in my dt always
> showed bus_dma_limit as 0x0.
Strange, either something changed since I last looked at this code,
or there is something on Freescale SoCs that avoids the
default logic.
There was originally a hack for powerpc that allowed DMA to be
done in the absence of a dma-ranges property in the bus node, but
limit it to 32-bit addressing for backwards compatibility, while
all other architectures should require either an empty dma-ranges
to allow full addressing or a specific translation if there is
a bus specific limit and/or offset.
Looking at the current code I don't see that any more, so it's
possible that now any DMA is allowed even if there is no
dma-ranges property at all.
> As an aside, if you could give this a quick check, I can send the revised
> patch. Appreciate the feedback.
>
> https://github.com/benmcollins/linux/commit/2f2946b33294ebff2fdaae6d1eadc976147470d6
This looks correct to me, but I would change two things:
- remove the debug message, which you probably left by accident
- instead of the explicit of_device_is_compatible(), change it
to use the .data field of the of_device_id table instead.
Arnd
On Wed, Apr 23, 2025 at 03:49:16PM -0500, Arnd Bergmann wrote: > On Tue, Apr 22, 2025, at 23:10, Ben Collins wrote: > > On Tue, Apr 22, 2025 at 11:25:40AM -0500, Arnd Bergmann wrote: > >> On Tue, Apr 22, 2025, at 10:56, Ben Collins wrote: > >> > >> >> > I'll check on this, but I think it's a seperate issue. The main thing is > >> >> > just to configure the dma hw correctly. > >> >> > >> >> I think it's still important to check this before changing the > >> >> driver: if the larger mask doesn't actually have any effect now > >> >> because the DT caps the DMA at 4GB, then it might break later > >> >> when someone adds the correct dma-ranges properties. > >> > > >> > I'm adding dma-ranges to my dt for testing. > >> > >> Ok. The other thing you can try is to printk() the dev->bus_dma_limit > >> to see if it even tries to use >32bit addressing. > > > > Did that. Every combination of IOMMU on/off and dma-ranges in my dt always > > showed bus_dma_limit as 0x0. > There was originally a hack for powerpc that allowed DMA to be > done in the absence of a dma-ranges property in the bus node, but > limit it to 32-bit addressing for backwards compatibility, while > all other architectures should require either an empty dma-ranges > to allow full addressing or a specific translation if there is > a bus specific limit and/or offset. > > Looking at the current code I don't see that any more, so it's > possible that now any DMA is allowed even if there is no > dma-ranges property at all. It's still there. It hardcodes zone_dma_limit to 31-bits: arch/powerpc/mm/mem.c: paging_init() I'm digging into this more. I'll check back when I have a better understanding. > > As an aside, if you could give this a quick check, I can send the revised > > patch. Appreciate the feedback. > > > > https://github.com/benmcollins/linux/commit/2f2946b33294ebff2fdaae6d1eadc976147470d6 > > This looks correct to me, but I would change two things: > > - remove the debug message, which you probably left by accident > - instead of the explicit of_device_is_compatible(), change it > to use the .data field of the of_device_id table instead. Will do. -- Ben Collins https://libjwt.io https://github.com/benmcollins -- 3EC9 7598 1672 961A 1139 173A 5D5A 57C7 242B 22CF
On Wed, Apr 23, 2025, at 22:41, Ben Collins wrote:
> On Wed, Apr 23, 2025 at 03:49:16PM -0500, Arnd Bergmann wrote:
>> Looking at the current code I don't see that any more, so it's
>> possible that now any DMA is allowed even if there is no
>> dma-ranges property at all.
>
> It's still there. It hardcodes zone_dma_limit to 31-bits:
>
> arch/powerpc/mm/mem.c: paging_init()
>
> I'm digging into this more. I'll check back when I have a better
> understanding.
zone_dma_limit is the other side of this: you need a ZONE_DMA
and/or ZONE_DMA32 memory zone that lets a driver allocate buffers
from low addresses if the DMA mask is smaller than the available
memory.
Arnd
© 2016 - 2025 Red Hat, Inc.