* Re: [PATCH 02/22] usb: remove the dead USB_OHCI_SH option
From: Rob Landley @ 2023-01-15 0:55 UTC (permalink / raw)
To: Greg Kroah-Hartman, Christoph Hellwig
Cc: Yoshinori Sato, Rich Felker, Arnd Bergmann, Laurent Pinchart,
Kieran Bingham, Geert Uytterhoeven, linux-kernel, linux-watchdog,
devicetree, linux-arch, dmaengine, dri-devel, linux-renesas-soc,
linux-i2c, linux-input, linux-media, linux-mmc, linux-mtd, netdev,
linux-gpio, linux-rtc, linux-spi, linux-serial, linux-usb,
linux-fbdev, alsa-devel, linux-sh
In-Reply-To: <Y8EEbCP6PRMzWP5y@kroah.com>
On 1/13/23 01:12, Greg Kroah-Hartman wrote:
> On Fri, Jan 13, 2023 at 07:23:19AM +0100, Christoph Hellwig wrote:
>> USB_OHCI_SH is a dummy option that never builds any code, remove it.
>>
>> Signed-off-by: Christoph Hellwig <hch@lst.de>
>> ---
>> drivers/usb/host/Kconfig | 11 -----------
>> 1 file changed, 11 deletions(-)
>>
>> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
>> index 8d799d23c476e1..ca5f657c092cf4 100644
>> --- a/drivers/usb/host/Kconfig
>> +++ b/drivers/usb/host/Kconfig
>> @@ -548,17 +548,6 @@ config USB_OHCI_HCD_SSB
>>
>> If unsure, say N.
>>
>> -config USB_OHCI_SH
>> - bool "OHCI support for SuperH USB controller (DEPRECATED)"
>> - depends on SUPERH || COMPILE_TEST
>> - select USB_OHCI_HCD_PLATFORM
>> - help
>> - This option is deprecated now and the driver was removed, use
>> - USB_OHCI_HCD_PLATFORM instead.
>> -
>> - Enables support for the on-chip OHCI controller on the SuperH.
>> - If you use the PCI OHCI controller, this option is not necessary.
>> -
>> config USB_OHCI_EXYNOS
>> tristate "OHCI support for Samsung S5P/Exynos SoC Series"
>> depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
>> --
>> 2.39.0
>>
>
> Do you want all of these to go through a single tree, or can they go
> through the different driver subsystem trees?
Neither please. Multiple people are objecting.
Rob
^ permalink raw reply
* Re: remove arch/sh
From: Rob Landley @ 2023-01-13 23:32 UTC (permalink / raw)
To: John Paul Adrian Glaubitz, Geert Uytterhoeven
Cc: Christoph Hellwig, Yoshinori Sato, Rich Felker, Arnd Bergmann,
Greg Kroah-Hartman, Laurent Pinchart, Kieran Bingham,
Geert Uytterhoeven, linux-kernel, linux-watchdog, devicetree,
linux-arch, dmaengine, dri-devel, linux-renesas-soc, linux-i2c,
linux-input, linux-media, linux-mmc, linux-mtd, netdev,
linux-gpio, linux-rtc, linux-spi, linux-serial, linux-usb,
linux-fbdev, alsa-devel, linux-sh
In-Reply-To: <fe09d811-e290-821d-ec8b-75936b6583c2@physik.fu-berlin.de>
On 1/13/23 13:05, John Paul Adrian Glaubitz wrote:
> Hi Rob!
>
> On 1/13/23 20:11, Rob Landley wrote:
>> There is definitely interest in this architecture. I'm aware Rich hasn't been
>> the most responsive maintainer. (I'm told he's on vacation with his family at
>> the moment, according to the text I got about this issue from the J-core
>> hardware guys in Japan.)
>
> Well, maybe we can just give it a try together ...
Jeff Dionne said he'd make himself available to answer hardware questions. (He
said he maintained some Linux ports 20 years ago, but isn't current with Linux
plumbing. Last month he was digging through the guts of vxworks, and the project
before that was some sort of BSD I think?)
I _do_ maintain Linux patches, I just generally don't bother to repost them
endlessly. Here's my "on top of 6.1" stack for example, each of which links to
at least one time it was posted to linux-kernel:
https://landley.net/toybox/downloads/binaries/mkroot/0.8.9/linux-patches/
>> The main reason we haven't converted everything to device tree is we only have
>> access to test hardware for a subset of the boards. Pruning the list of
>> supported boards and converting the rest to device tree might make sense. We can
>> always add/convert boards back later...
>
> There is a patch by Yoshinori Sato which adds device tree support to SH. Maybe we
> can revive it.
The turtle board is device tree and has been since it was merged. The
infrastructure is there, the question is converting over boards and testing
them, or deciding to prune them. Did Sato-san convert many boards? (I'm not
finding his patch via google...)
> Adrian
Rob
^ permalink raw reply
* Re: remove arch/sh
From: John Paul Adrian Glaubitz @ 2023-01-13 19:05 UTC (permalink / raw)
To: Rob Landley, Geert Uytterhoeven
Cc: Christoph Hellwig, Yoshinori Sato, Rich Felker, Arnd Bergmann,
Greg Kroah-Hartman, Laurent Pinchart, Kieran Bingham,
Geert Uytterhoeven, linux-kernel, linux-watchdog, devicetree,
linux-arch, dmaengine, dri-devel, linux-renesas-soc, linux-i2c,
linux-input, linux-media, linux-mmc, linux-mtd, netdev,
linux-gpio, linux-rtc, linux-spi, linux-serial, linux-usb,
linux-fbdev, alsa-devel, linux-sh
In-Reply-To: <6891afb6-4190-6a52-0319-745b3f138d97@landley.net>
Hi Rob!
On 1/13/23 20:11, Rob Landley wrote:
>> I actually would be willing to do it but I'm a bit hesitant as I'm not 100%
>> sure my skills are sufficient. Maybe if someone can assist me?
>
> My skills aren't sufficient and I dunno how much time I have, but I can
> certainly assist. I test sh4 regularlyish and it's in the list of architectures
> I ship binaries and tiny VM images for, just refreshed tuesday:
>
> https://landley.net/toybox/downloads/binaries/0.8.9/
> https://landley.net/toybox/downloads/binaries/mkroot/0.8.9/
>
> (The sh2eb isn't a VM, it's a physical board I have here...)
>
> There is definitely interest in this architecture. I'm aware Rich hasn't been
> the most responsive maintainer. (I'm told he's on vacation with his family at
> the moment, according to the text I got about this issue from the J-core
> hardware guys in Japan.)
Well, maybe we can just give it a try together ...
> The main reason we haven't converted everything to device tree is we only have
> access to test hardware for a subset of the boards. Pruning the list of
> supported boards and converting the rest to device tree might make sense. We can
> always add/convert boards back later...
There is a patch by Yoshinori Sato which adds device tree support to SH. Maybe we
can revive it.
Adrian
--
.''`. John Paul Adrian Glaubitz
: :' : Debian Developer
`. `' Physicist
`- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913
^ permalink raw reply
* Re: remove arch/sh
From: Rob Landley @ 2023-01-13 19:11 UTC (permalink / raw)
To: John Paul Adrian Glaubitz, Geert Uytterhoeven
Cc: Christoph Hellwig, Yoshinori Sato, Rich Felker, Arnd Bergmann,
Greg Kroah-Hartman, Laurent Pinchart, Kieran Bingham,
Geert Uytterhoeven, linux-kernel, linux-watchdog, devicetree,
linux-arch, dmaengine, dri-devel, linux-renesas-soc, linux-i2c,
linux-input, linux-media, linux-mmc, linux-mtd, netdev,
linux-gpio, linux-rtc, linux-spi, linux-serial, linux-usb,
linux-fbdev, alsa-devel, linux-sh
In-Reply-To: <142532fb-5997-bdc1-0811-a80ae33f4ba4@physik.fu-berlin.de>
On 1/13/23 02:52, John Paul Adrian Glaubitz wrote:
> Hi Geert!
>
> On 1/13/23 09:26, Geert Uytterhoeven wrote:
>> Indeed. The main issue is not the lack of people sending patches and
>> fixes, but those patches never being applied by the maintainers.
>> Perhaps someone is willing to stand up to take over maintainership?
>
> I actually would be willing to do it but I'm a bit hesitant as I'm not 100%
> sure my skills are sufficient. Maybe if someone can assist me?
My skills aren't sufficient and I dunno how much time I have, but I can
certainly assist. I test sh4 regularlyish and it's in the list of architectures
I ship binaries and tiny VM images for, just refreshed tuesday:
https://landley.net/toybox/downloads/binaries/0.8.9/
https://landley.net/toybox/downloads/binaries/mkroot/0.8.9/
(The sh2eb isn't a VM, it's a physical board I have here...)
There is definitely interest in this architecture. I'm aware Rich hasn't been
the most responsive maintainer. (I'm told he's on vacation with his family at
the moment, according to the text I got about this issue from the J-core
hardware guys in Japan.)
The main reason we haven't converted everything to device tree is we only have
access to test hardware for a subset of the boards. Pruning the list of
supported boards and converting the rest to device tree might make sense. We can
always add/convert boards back later...
Rob
^ permalink raw reply
* Re: [PATCH v9 00/27] dmaengine: dw-edma: Add RP/EP local DMA controllers support
From: Serge Semin @ 2023-01-13 18:34 UTC (permalink / raw)
To: Serge Semin, Lorenzo Pieralisi, Vinod Koul, obin Murphy,
Manivannan Sadhasivam
Cc: Gustavo Pimentel, Rob Herring, Bjorn Helgaas, Cai Huoqing,
Jingoo Han, Frank Li, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Hello folks,
On Fri, Jan 13, 2023 at 08:13:42PM +0300, Serge Semin wrote:
> This is a final patchset in the series created in the framework of
> my Baikal-T1 PCIe/eDMA-related work:
>
> [1: Done v5] PCI: dwc: Various fixes and cleanups
> Link: https://lore.kernel.org/linux-pci/20220624143428.8334-1-Sergey.Semin@baikalelectronics.ru/
> Merged: kernel 6.0-rc1
> [2: Done v4] PCI: dwc: Add hw version and dma-ranges support
> Link: https://lore.kernel.org/linux-pci/20220624143947.8991-1-Sergey.Semin@baikalelectronics.ru/
> Merged: kernel 6.0-rc1
> [3: Done v7] PCI: dwc: Add generic resources and Baikal-T1 support
> Link: https://lore.kernel.org/linux-pci/20221113191301.5526-1-Sergey.Semin@baikalelectronics.ru/
> Merged: kernel 6.2-rc1
> [4: In-review v9] dmaengine: dw-edma: Add RP/EP local DMA controllers support
> Link: ---you are looking at it---
>
> Note it is very recommended to merge the patchsets in the same order as
> they are listed in the set above in order to have them applied smoothly.
> Since the patchsets 1-3 have already been merged into the mainline kernel
> this series can be applied via any DMA-engine or PCI repos.
>
> Here is a short summary regarding this patchset. The series starts with
> fixes patches. We discovered that the dw-edma-pcie.c driver incorrectly
> initializes the LL/DT base addresses for the platforms with not matching
> CPU and PCIe memory spaces. It is fixed by using the pci_bus_address()
> method to get a correct base address. After that you can find a series of
> the interleaved xfers fixes. It turned out the interleaved transfers
> implementation didn't work quite correctly from the very beginning for
> instance missing src/dst addresses initialization, etc. In the framework
> of the next two patches we suggest to add a new platform-specific
> callback - pci_address() and use it to convert the CPU address to the PCIe
> space address. It is at least required for the DW eDMA remote End-point
> setup on the platforms with not-matching CPU/PCIe address spaces. In case
> of the DW eDMA local RP/EP setup the conversion will be done automatically
> by the outbound iATU (if no DMA-bypass flag is specified for the
> corresponding iATU window). Then we introduce a set of the patches to make
> the DebugFS part of the code supporting the multi-eDMA controllers
> platforms. It starts with several cleanup patches and is closed joining
> the Read/Write channels into a single DMA-device as they originally should
> have been. After that you can find the patches with adding the non-atomic
> io-64 methods usage, dropping DT-region descriptors allocation, replacing
> chip IDs with the device name. In addition to that in order to have the
> eDMA embedded into the DW PCIe RP/EP supported we need to bypass the
> dma-ranges-based memory ranges mapping since in case of the root port DT
> node it's applicable for the peripheral PCIe devices only. Finally at the
> series closure we introduce a generic DW eDMA controller support being
> available in the DW PCIe Root Port/Endpoint driver.
>
> Link: https://lore.kernel.org/linux-pci/20220324014836.19149-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v2:
> - Drop the patches:
> [PATCH 1/25] dmaengine: dw-edma: Drop dma_slave_config.direction field usage
> [PATCH 2/25] dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics
> since they are going to be merged in in the framework of the
> Frank's patchset.
> - Add a new patch: "dmaengine: dw-edma: Release requested IRQs on
> failure."
> - Drop __iomem qualifier from the struct dw_edma_debugfs_entry instance
> definition in the dw_edma_debugfs_u32_get() method. (@Manivannan)
> - Add a new patch: "dmaengine: dw-edma: Rename DebugFS dentry variables to
> 'dent'." (@Manivannan)
> - Slightly extend the eDMA name array size. (@Manivannan)
> - Change the specific DMA mapping comment a bit to being
> clearer. (@Manivannan)
> - Add a new patch: "PCI: dwc: Add generic iATU/eDMA CSRs space detection
> method."
> - Don't fail eDMA detection procedure if the DW eDMA driver couldn't probe
> device. That happens if the driver is disabled. (@Manivannan)
> - Add "dma" registers resource mapping procedure. (@Manivannan)
> - Move the eDMA CSRs space detection into the dw_pcie_map_detect() method.
> - Remove eDMA on the dw_pcie_ep_init() internal errors. (@Manivannan)
> - Remove eDMA in the dw_pcie_ep_exit() method.
> - Move the dw_pcie_edma_detect() method execution to the tail of the
> dw_pcie_ep_init() function.
>
> Link: https://lore.kernel.org/linux-pci/20220503225104.12108-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v3:
> - Conditionally set dchan->dev->device.dma_coherent field since it can
> be missing on some platforms. (@Manivannan)
> - Drop the patch: "PCI: dwc: Add generic iATU/eDMA CSRs space detection
> method". A similar modification has been done in another patchset.
> - Add more comprehensive and less regression prune eDMA block detection
> procedure.
> - Drop the patch: "dma-direct: take dma-ranges/offsets into account in
> resource mapping". It will be separately reviewed.
> - Remove Manivannan tb tag from the modified patches.
> - Rebase onto the kernel v5.18.
>
> Link: https://lore.kernel.org/linux-pci/20220610091459.17612-1-Sergey.Semin@baikalelectronics.ru
> Changelog v4:
> - Rabase onto the laters Frank Li series:
> Link: https://lore.kernel.org/all/20220524152159.2370739-1-Frank.Li@nxp.com/
> - Add Vinod' Ab-tag.
> - Rebase onto the kernel v5.19-rcX.
>
> Link: https://lore.kernel.org/linux-pci/20220728142841.12305-1-Sergey.Semin@baikalelectronics.ru
> Changelog v5:
> - Just resend.
> - Rebase onto the kernel v6.0-rc2.
>
> Link: https://lore.kernel.org/linux-pci/20220822185332.26149-1-Sergey.Semin@baikalelectronics.ru
> Changelog v6:
> - Fix some patchlog and in-line comments misspells. (@Bjorn)
> - Directly call *_dma_configure() method on the DW eDMA channel child
> device used for the DMA buffers mapping. (@Robin)
> - Explicitly set the DMA-mask of the child device in the channel
> allocation proecedure. (@Robin)
> - Rebase onto the kernel v6.1-rc3.
>
> Link: https://lore.kernel.org/linux-pci/20221107210438.1515-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v7:
> - Activate the mapping auto-detection procedure for IP-cores older than
> 5.40a. The viewport-based access has been removed since that
> version. (@Yoshihiro)
> - Drop the patch
> [PATCH v6 22/24] dmaengine: dw-edma: Bypass dma-ranges mapping for the local setup
> since the problem has been fixed in the commit f1ad5338a4d5 ("of: Fix
> "dma-ranges" handling for bus controllers"). (@Robin)
> - Add a new patch:
> [PATCH v7 23/25] PCI: dwc: Restore DMA-mask after MSI-data allocation
> (@Robin)
> - Add a new patch:
> [PATCH v7 24/25] PCI: bt1: Set 64-bit DMA-mask
> (@Robin)
>
> Link: https://lore.kernel.org/linux-pci/20221214235305.31744-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v8:
> - Add a new patch:
> [PATCH v8 23/26] dmaengine: dw-edma: Relax driver config settings
> (@tbot)
> - Replace the patch
> [PATCH v7 23/25] PCI: dwc: Restore DMA-mask after MSI-data allocation
> with a new one:
> [PATCH v8 24/26] PCI: dwc: Set coherent DMA-mask on MSI-address allocation
> (@Robin, @Christoph)
>
> Link: https://lore.kernel.org/linux-pci/20221219144658.26620-1-Sergey.Semin@baikalelectronics.ru/
> Changelog v9:
> - Add a new patch:
> [PATCH v9 23/27] dmaengine: dw-edma: Add mem-mapped LL-entries support
> (@tbot)
> - Rebase onto the kernel 6.2-rc3.
This is currently the latest version of the patchset. There are
several new patches (suggested by @Yoshihiro, @Robin and @tbot) and a
few updates have been introduced since the last @Vinod' and
@Manivannan' reviews. Thus I had to drop their Rb/Tb-tags from the
cover-letter and from some of the patches. Other than that the series
seems to be ready to be merged in (@Robin already blessed the
DMA-mask-related patches). Since all the preceding patchsets have
already been mainlined it can be done via any repo: DMA-engine, PCI,
etc.
-Serge(y)
>
> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
> Cc: Pavel Parkhomenko <Pavel.Parkhomenko@baikalelectronics.ru>
> Cc: "Krzysztof Wilczyński" <kw@linux.com>
> Cc: caihuoqing <caihuoqing@baidu.com>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: linux-pci@vger.kernel.org
> Cc: dmaengine@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
>
> Serge Semin (27):
> dmaengine: Fix dma_slave_config.dst_addr description
> dmaengine: dw-edma: Release requested IRQs on failure
> dmaengine: dw-edma: Convert ll/dt phys-address to PCIe bus/DMA address
> dmaengine: dw-edma: Fix missing src/dst address of the interleaved
> xfers
> dmaengine: dw-edma: Don't permit non-inc interleaved xfers
> dmaengine: dw-edma: Fix invalid interleaved xfers semantics
> dmaengine: dw-edma: Add CPU to PCIe bus address translation
> dmaengine: dw-edma: Add PCIe bus address getter to the remote EP
> glue-driver
> dmaengine: dw-edma: Drop chancnt initialization
> dmaengine: dw-edma: Fix DebugFS reg entry type
> dmaengine: dw-edma: Stop checking debugfs_create_*() return value
> dmaengine: dw-edma: Add dw_edma prefix to the DebugFS nodes descriptor
> dmaengine: dw-edma: Convert DebugFS descs to being kz-allocated
> dmaengine: dw-edma: Rename DebugFS dentry variables to 'dent'
> dmaengine: dw-edma: Simplify the DebugFS context CSRs init procedure
> dmaengine: dw-edma: Move eDMA data pointer to DebugFS node descriptor
> dmaengine: dw-edma: Join Write/Read channels into a single device
> dmaengine: dw-edma: Use DMA-engine device DebugFS subdirectory
> dmaengine: dw-edma: Use non-atomic io-64 methods
> dmaengine: dw-edma: Drop DT-region allocation
> dmaengine: dw-edma: Replace chip ID number with device name
> dmaengine: dw-edma: Skip cleanup procedure if no private data found
> dmaengine: dw-edma: Add mem-mapped LL-entries support
> dmaengine: dw-edma: Relax driver config settings
> PCI: dwc: Set coherent DMA-mask on MSI-address allocation
> PCI: bt1: Set 64-bit DMA-mask
> PCI: dwc: Add DW eDMA engine support
>
> drivers/dma/dw-edma/Kconfig | 5 +-
> drivers/dma/dw-edma/dw-edma-core.c | 196 ++++-----
> drivers/dma/dw-edma/dw-edma-core.h | 10 +-
> drivers/dma/dw-edma/dw-edma-pcie.c | 56 ++-
> drivers/dma/dw-edma/dw-edma-v0-core.c | 121 +++---
> drivers/dma/dw-edma/dw-edma-v0-core.h | 1 -
> drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 372 ++++++++----------
> drivers/dma/dw-edma/dw-edma-v0-debugfs.h | 5 -
> drivers/pci/controller/dwc/pcie-bt1.c | 4 +
> .../pci/controller/dwc/pcie-designware-ep.c | 12 +-
> .../pci/controller/dwc/pcie-designware-host.c | 24 +-
> drivers/pci/controller/dwc/pcie-designware.c | 195 +++++++++
> drivers/pci/controller/dwc/pcie-designware.h | 21 +
> include/linux/dma/edma.h | 25 +-
> include/linux/dmaengine.h | 2 +-
> 15 files changed, 652 insertions(+), 397 deletions(-)
>
> --
> 2.39.0
>
>
^ permalink raw reply
* Re: [PATCH v7 24/25] PCI: bt1: Set 64-bit DMA-mask
From: Serge Semin @ 2023-01-13 18:23 UTC (permalink / raw)
To: Robin Murphy, Lorenzo Pieralisi
Cc: Serge Semin, Gustavo Pimentel, Vinod Koul, Rob Herring,
Bjorn Helgaas, Lorenzo Pieralisi, Cai Huoqing, Jingoo Han,
Frank Li, Manivannan Sadhasivam, Krzysztof Wilczyński,
Alexey Malahov, Pavel Parkhomenko, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <8984a6ee-9066-bd2e-761f-96a8dd7875b6@arm.com>
On Fri, Jan 13, 2023 at 05:40:38PM +0000, Robin Murphy wrote:
> On 2023-01-13 12:04, Lorenzo Pieralisi wrote:
> > On Thu, Dec 15, 2022 at 02:53:04AM +0300, Serge Semin wrote:
> > > The DW PCIe RC IP-core is synthesized with the 64-bits AXI address bus.
> > > Since the device is also equipped with the eDMA engine we need to
> > > explicitly set the device DMA-mask so the DMA-engine clients would be able
> > > to allocate the data buffers from the DMA-able memory space.
> > >
> > > Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
> > >
> > > ---
> > >
> > > Changelog v7:
> > > - This is a new patch added on v7 stage of the series. (@Robin)
> > > ---
> > > drivers/pci/controller/dwc/pcie-bt1.c | 4 ++++
> > > 1 file changed, 4 insertions(+)
> >
> > Hi Robin,
> >
> > are you OK with this change ? I think that's the last (PCI) bit we
> > need to take the series.
>
> Yup, having gone and double-checked the context this seems fine too - I've
> slightly lost track of all the circles we've been round in by now, but it
> looks like the way things all end up after v8 (and now v9) should be
> uncontentious.
Yes, v9 has just been submitted with your Rb-tag preserved in the
coherent-DMA-mask modification patch (patch #25/27).
Please find the last version of the series here:
https://lore.kernel.org/linux-pci/20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru/
-Serge(y)
>
> Thanks,
> Robin.
>
> >
> > Thanks,
> > Lorenzo
> >
> > > diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c
> > > index 8b6c7d544d9a..04aa58348aa5 100644
> > > --- a/drivers/pci/controller/dwc/pcie-bt1.c
> > > +++ b/drivers/pci/controller/dwc/pcie-bt1.c
> > > @@ -583,6 +583,10 @@ static int bt1_pcie_add_port(struct bt1_pcie *btpci)
> > > struct device *dev = &btpci->pdev->dev;
> > > int ret;
> > > + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
> > > + if (ret)
> > > + return ret;
> > > +
> > > btpci->dw.version = DW_PCIE_VER_460A;
> > > btpci->dw.dev = dev;
> > > btpci->dw.ops = &bt1_pcie_ops;
> > > --
> > > 2.38.1
> > >
> > >
^ permalink raw reply
* Re: [PATCH v7 24/25] PCI: bt1: Set 64-bit DMA-mask
From: Robin Murphy @ 2023-01-13 17:40 UTC (permalink / raw)
To: Lorenzo Pieralisi, Serge Semin
Cc: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Jingoo Han, Frank Li,
Manivannan Sadhasivam, Krzysztof Wilczyński, Serge Semin,
Alexey Malahov, Pavel Parkhomenko, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <Y8FI3m0Yare5gCeM@lpieralisi>
On 2023-01-13 12:04, Lorenzo Pieralisi wrote:
> On Thu, Dec 15, 2022 at 02:53:04AM +0300, Serge Semin wrote:
>> The DW PCIe RC IP-core is synthesized with the 64-bits AXI address bus.
>> Since the device is also equipped with the eDMA engine we need to
>> explicitly set the device DMA-mask so the DMA-engine clients would be able
>> to allocate the data buffers from the DMA-able memory space.
>>
>> Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
>>
>> ---
>>
>> Changelog v7:
>> - This is a new patch added on v7 stage of the series. (@Robin)
>> ---
>> drivers/pci/controller/dwc/pcie-bt1.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>
> Hi Robin,
>
> are you OK with this change ? I think that's the last (PCI) bit we
> need to take the series.
Yup, having gone and double-checked the context this seems fine too -
I've slightly lost track of all the circles we've been round in by now,
but it looks like the way things all end up after v8 (and now v9) should
be uncontentious.
Thanks,
Robin.
>
> Thanks,
> Lorenzo
>
>> diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c
>> index 8b6c7d544d9a..04aa58348aa5 100644
>> --- a/drivers/pci/controller/dwc/pcie-bt1.c
>> +++ b/drivers/pci/controller/dwc/pcie-bt1.c
>> @@ -583,6 +583,10 @@ static int bt1_pcie_add_port(struct bt1_pcie *btpci)
>> struct device *dev = &btpci->pdev->dev;
>> int ret;
>>
>> + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
>> + if (ret)
>> + return ret;
>> +
>> btpci->dw.version = DW_PCIE_VER_460A;
>> btpci->dw.dev = dev;
>> btpci->dw.ops = &bt1_pcie_ops;
>> --
>> 2.38.1
>>
>>
^ permalink raw reply
* [PATCH v9 24/27] dmaengine: dw-edma: Relax driver config settings
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Since the DW PCIe RP/EP driver is about to be updated to register the DW
eDMA-based DMA-engine the drivers build modes must be synchronized.
Currently the DW PCIe RP/EP driver is always built as a builtin module.
Meanwhile the DW eDMA driver can be built as a loadable module. Thus in
the later case the kernel with DW PCIe controllers support will fail to be
linked due to lacking the DW eDMA probe/remove symbols. At the same time
forcibly selecting the DW eDMA driver from the DW PCIe RP/EP kconfig will
effectively eliminate the tristate type of the former driver fixing it to
just the builtin kernel module.
Seeing the DW eDMA engine isn't that often met built into the DW PCIe
Root-ports and End-points let's convert the DW eDMA driver config to being
more flexible instead of just forcibly selecting the DW eDMA kconfig. In
order to do that first the DW eDMA PCIe driver config should be converted
to being depended from the DW eDMA core config instead of selecting the
one. Second the DW eDMA probe and remove symbols should be referenced only
if they are reachable by the caller. Thus the user will be able to build
the DW eDMA core driver with any type, meanwhile the dependent code will
be either restricted to the same build type (e.g. DW eDMA PCIe driver if
DW eDMA driver is built as a loadable module) or just won't be able to use
the eDMA engine registration/de-registration functionality (e.g. DW PCIe
RP/EP driver if DW eDMA driver is built as a loadable module).
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
Changelog v8:
- This is a new patch added on v8 stage of the series in order to fix
the tbot-reported build issues. (@tbot)
---
drivers/dma/dw-edma/Kconfig | 5 ++++-
include/linux/dma/edma.h | 2 +-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/dw-edma/Kconfig b/drivers/dma/dw-edma/Kconfig
index 7ff17b2db6a1..2b6f2679508d 100644
--- a/drivers/dma/dw-edma/Kconfig
+++ b/drivers/dma/dw-edma/Kconfig
@@ -9,11 +9,14 @@ config DW_EDMA
Support the Synopsys DesignWare eDMA controller, normally
implemented on endpoints SoCs.
+if DW_EDMA
+
config DW_EDMA_PCIE
tristate "Synopsys DesignWare eDMA PCIe driver"
depends on PCI && PCI_MSI
- select DW_EDMA
help
Provides a glue-logic between the Synopsys DesignWare
eDMA controller and an endpoint PCIe device. This also serves
as a reference design to whom desires to use this IP.
+
+endif # DW_EDMA
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 08833f12b386..c062c8db472c 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -101,7 +101,7 @@ struct dw_edma_chip {
};
/* Export to the platform drivers */
-#if IS_ENABLED(CONFIG_DW_EDMA)
+#if IS_REACHABLE(CONFIG_DW_EDMA)
int dw_edma_probe(struct dw_edma_chip *chip);
int dw_edma_remove(struct dw_edma_chip *chip);
#else
--
2.39.0
^ permalink raw reply related
* [PATCH v9 27/27] PCI: dwc: Add DW eDMA engine support
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
caihuoqing, Yoshihiro Shimoda, linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Since the DW eDMA driver now supports eDMA controllers embedded into the
locally accessible DW PCIe Root Ports and Endpoints, we can use the
updated interface to register DW eDMA as DMA engine device if it's
available. In order to successfully do that the DW PCIe core driver need
to perform some preparations first. First of all it needs to find out the
eDMA controller CSRs base address, whether they are accessible over the
Port Logic or iATU unrolled space. Afterwards it can try to auto-detect
the eDMA controller availability and number of read/write channels.
If none was found the procedure will just silently halt with no error
returned. Secondly the platform is supposed to provide either combined or
per-channel IRQ signals. If no valid IRQs set is found the procedure will
also halt with no error returned so to be backward compatible with the
platforms where DW PCIe controllers have eDMA embedded but lack of the
IRQs defined for them. Finally before actually probing the eDMA device we
need to allocate LLP items buffers. After that the DW eDMA can be
registered. If registration is successful the info-message regarding the
number of detected Read/Write eDMA channels will be printed to the system
as is done for the iATU settings.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
Changelog v2:
- Don't fail eDMA detection procedure if the DW eDMA driver couldn't probe
device. That happens if the driver is disabled. (@Manivannan)
- Add "dma" registers resource mapping procedure. (@Manivannan)
- Move the eDMA CSRs space detection into the dw_pcie_map_detect() method.
- Remove eDMA on the dw_pcie_ep_init() internal errors. (@Manivannan)
- Remove eDMA in the dw_pcie_ep_exit() method.
- Move the dw_pcie_edma_detect() method execution to the tail of the
dw_pcie_ep_init() function.
Changelog v3:
- Add more comprehensive and less regression prune eDMA block detection
procedure.
- Remove Manivannan tb tag since the patch content has been changed.
Changelog v6:
- Fix some patchlog and in-line comments misspells. (@Bjorn)
Changelog v7:
- Activate the mapping auto-detection procedure for IP-cores older than
5.40a since the viewport-based access has been removed since that
version. (@Yoshihiro)
---
.../pci/controller/dwc/pcie-designware-ep.c | 12 +-
.../pci/controller/dwc/pcie-designware-host.c | 13 +-
drivers/pci/controller/dwc/pcie-designware.c | 195 ++++++++++++++++++
drivers/pci/controller/dwc/pcie-designware.h | 21 ++
4 files changed, 238 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index d06654895eba..f9182f8d552f 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -612,8 +612,11 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
{
+ struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
struct pci_epc *epc = ep->epc;
+ dw_pcie_edma_remove(pci);
+
pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
epc->mem->window.page_size);
@@ -785,6 +788,10 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
goto err_exit_epc_mem;
}
+ ret = dw_pcie_edma_detect(pci);
+ if (ret)
+ goto err_free_epc_mem;
+
if (ep->ops->get_features) {
epc_features = ep->ops->get_features(ep);
if (epc_features->core_init_notifier)
@@ -793,10 +800,13 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
ret = dw_pcie_ep_init_complete(ep);
if (ret)
- goto err_free_epc_mem;
+ goto err_remove_edma;
return 0;
+err_remove_edma:
+ dw_pcie_edma_remove(pci);
+
err_free_epc_mem:
pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem,
epc->mem->window.page_size);
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index e10608af39b4..a9e3dda36c21 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -476,14 +476,18 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
dw_pcie_iatu_detect(pci);
- ret = dw_pcie_setup_rc(pp);
+ ret = dw_pcie_edma_detect(pci);
if (ret)
goto err_free_msi;
+ ret = dw_pcie_setup_rc(pp);
+ if (ret)
+ goto err_remove_edma;
+
if (!dw_pcie_link_up(pci)) {
ret = dw_pcie_start_link(pci);
if (ret)
- goto err_free_msi;
+ goto err_remove_edma;
}
/* Ignore errors, the link may come up later */
@@ -500,6 +504,9 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
err_stop_link:
dw_pcie_stop_link(pci);
+err_remove_edma:
+ dw_pcie_edma_remove(pci);
+
err_free_msi:
if (pp->has_msi_ctrl)
dw_pcie_free_msi(pp);
@@ -521,6 +528,8 @@ void dw_pcie_host_deinit(struct dw_pcie_rp *pp)
dw_pcie_stop_link(pci);
+ dw_pcie_edma_remove(pci);
+
if (pp->has_msi_ctrl)
dw_pcie_free_msi(pp);
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 6d5d619ab2e9..53a16b8b6ac2 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -12,6 +12,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/dma/edma.h>
#include <linux/gpio/consumer.h>
#include <linux/ioport.h>
#include <linux/of.h>
@@ -142,6 +143,18 @@ int dw_pcie_get_resources(struct dw_pcie *pci)
if (!pci->atu_size)
pci->atu_size = SZ_4K;
+ /* eDMA region can be mapped to a custom base address */
+ if (!pci->edma.reg_base) {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+ if (res) {
+ pci->edma.reg_base = devm_ioremap_resource(pci->dev, res);
+ if (IS_ERR(pci->edma.reg_base))
+ return PTR_ERR(pci->edma.reg_base);
+ } else if (pci->atu_size >= 2 * DEFAULT_DBI_DMA_OFFSET) {
+ pci->edma.reg_base = pci->atu_base + DEFAULT_DBI_DMA_OFFSET;
+ }
+ }
+
/* LLDD is supposed to manually switch the clocks and resets state */
if (dw_pcie_cap_is(pci, REQ_RES)) {
ret = dw_pcie_get_clocks(pci);
@@ -782,6 +795,188 @@ void dw_pcie_iatu_detect(struct dw_pcie *pci)
pci->region_align / SZ_1K, (pci->region_limit + 1) / SZ_1G);
}
+static u32 dw_pcie_readl_dma(struct dw_pcie *pci, u32 reg)
+{
+ u32 val = 0;
+ int ret;
+
+ if (pci->ops && pci->ops->read_dbi)
+ return pci->ops->read_dbi(pci, pci->edma.reg_base, reg, 4);
+
+ ret = dw_pcie_read(pci->edma.reg_base + reg, 4, &val);
+ if (ret)
+ dev_err(pci->dev, "Read DMA address failed\n");
+
+ return val;
+}
+
+static int dw_pcie_edma_irq_vector(struct device *dev, unsigned int nr)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ char name[6];
+ int ret;
+
+ if (nr >= EDMA_MAX_WR_CH + EDMA_MAX_RD_CH)
+ return -EINVAL;
+
+ ret = platform_get_irq_byname_optional(pdev, "dma");
+ if (ret > 0)
+ return ret;
+
+ snprintf(name, sizeof(name), "dma%u", nr);
+
+ return platform_get_irq_byname_optional(pdev, name);
+}
+
+static struct dw_edma_core_ops dw_pcie_edma_ops = {
+ .irq_vector = dw_pcie_edma_irq_vector,
+};
+
+static int dw_pcie_edma_find_chip(struct dw_pcie *pci)
+{
+ u32 val;
+
+ /*
+ * Indirect eDMA CSRs access has been completely removed since v5.40a
+ * thus no space is now reserved for the eDMA channels viewport and
+ * former DMA CTRL register is no longer fixed to FFs.
+ */
+ if (dw_pcie_ver_is_ge(pci, 540A))
+ val = 0xFFFFFFFF;
+ else
+ val = dw_pcie_readl_dbi(pci, PCIE_DMA_VIEWPORT_BASE + PCIE_DMA_CTRL);
+
+ if (val == 0xFFFFFFFF && pci->edma.reg_base) {
+ pci->edma.mf = EDMA_MF_EDMA_UNROLL;
+
+ val = dw_pcie_readl_dma(pci, PCIE_DMA_CTRL);
+ } else if (val != 0xFFFFFFFF) {
+ pci->edma.mf = EDMA_MF_EDMA_LEGACY;
+
+ pci->edma.reg_base = pci->dbi_base + PCIE_DMA_VIEWPORT_BASE;
+ } else {
+ return -ENODEV;
+ }
+
+ pci->edma.dev = pci->dev;
+
+ if (!pci->edma.ops)
+ pci->edma.ops = &dw_pcie_edma_ops;
+
+ pci->edma.flags |= DW_EDMA_CHIP_LOCAL;
+
+ pci->edma.ll_wr_cnt = FIELD_GET(PCIE_DMA_NUM_WR_CHAN, val);
+ pci->edma.ll_rd_cnt = FIELD_GET(PCIE_DMA_NUM_RD_CHAN, val);
+
+ /* Sanity check the channels count if the mapping was incorrect */
+ if (!pci->edma.ll_wr_cnt || pci->edma.ll_wr_cnt > EDMA_MAX_WR_CH ||
+ !pci->edma.ll_rd_cnt || pci->edma.ll_rd_cnt > EDMA_MAX_RD_CH)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int dw_pcie_edma_irq_verify(struct dw_pcie *pci)
+{
+ struct platform_device *pdev = to_platform_device(pci->dev);
+ u16 ch_cnt = pci->edma.ll_wr_cnt + pci->edma.ll_rd_cnt;
+ char name[6];
+ int ret;
+
+ if (pci->edma.nr_irqs == 1)
+ return 0;
+ else if (pci->edma.nr_irqs > 1)
+ return pci->edma.nr_irqs != ch_cnt ? -EINVAL : 0;
+
+ ret = platform_get_irq_byname_optional(pdev, "dma");
+ if (ret > 0) {
+ pci->edma.nr_irqs = 1;
+ return 0;
+ }
+
+ for (; pci->edma.nr_irqs < ch_cnt; pci->edma.nr_irqs++) {
+ snprintf(name, sizeof(name), "dma%d", pci->edma.nr_irqs);
+
+ ret = platform_get_irq_byname_optional(pdev, name);
+ if (ret <= 0)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dw_pcie_edma_ll_alloc(struct dw_pcie *pci)
+{
+ struct dw_edma_region *ll;
+ dma_addr_t paddr;
+ int i;
+
+ for (i = 0; i < pci->edma.ll_wr_cnt; i++) {
+ ll = &pci->edma.ll_region_wr[i];
+ ll->sz = DMA_LLP_MEM_SIZE;
+ ll->vaddr.mem = dmam_alloc_coherent(pci->dev, ll->sz,
+ &paddr, GFP_KERNEL);
+ if (!ll->vaddr.mem)
+ return -ENOMEM;
+
+ ll->paddr = paddr;
+ }
+
+ for (i = 0; i < pci->edma.ll_rd_cnt; i++) {
+ ll = &pci->edma.ll_region_rd[i];
+ ll->sz = DMA_LLP_MEM_SIZE;
+ ll->vaddr.mem = dmam_alloc_coherent(pci->dev, ll->sz,
+ &paddr, GFP_KERNEL);
+ if (!ll->vaddr.mem)
+ return -ENOMEM;
+
+ ll->paddr = paddr;
+ }
+
+ return 0;
+}
+
+int dw_pcie_edma_detect(struct dw_pcie *pci)
+{
+ int ret;
+
+ /* Don't fail if no eDMA was found (for the backward compatibility) */
+ ret = dw_pcie_edma_find_chip(pci);
+ if (ret)
+ return 0;
+
+ /* Don't fail on the IRQs verification (for the backward compatibility) */
+ ret = dw_pcie_edma_irq_verify(pci);
+ if (ret) {
+ dev_err(pci->dev, "Invalid eDMA IRQs found\n");
+ return 0;
+ }
+
+ ret = dw_pcie_edma_ll_alloc(pci);
+ if (ret) {
+ dev_err(pci->dev, "Couldn't allocate LLP memory\n");
+ return ret;
+ }
+
+ /* Don't fail if the DW eDMA driver can't find the device */
+ ret = dw_edma_probe(&pci->edma);
+ if (ret && ret != -ENODEV) {
+ dev_err(pci->dev, "Couldn't register eDMA device\n");
+ return ret;
+ }
+
+ dev_info(pci->dev, "eDMA: unroll %s, %hu wr, %hu rd\n",
+ pci->edma.mf == EDMA_MF_EDMA_UNROLL ? "T" : "F",
+ pci->edma.ll_wr_cnt, pci->edma.ll_rd_cnt);
+
+ return 0;
+}
+
+void dw_pcie_edma_remove(struct dw_pcie *pci)
+{
+ dw_edma_remove(&pci->edma);
+}
+
void dw_pcie_setup(struct dw_pcie *pci)
{
u32 val;
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 393dfb931df6..79713ce075cc 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -15,6 +15,7 @@
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/dma-mapping.h>
+#include <linux/dma/edma.h>
#include <linux/gpio/consumer.h>
#include <linux/irq.h>
#include <linux/msi.h>
@@ -31,6 +32,7 @@
#define DW_PCIE_VER_480A 0x3438302a
#define DW_PCIE_VER_490A 0x3439302a
#define DW_PCIE_VER_520A 0x3532302a
+#define DW_PCIE_VER_540A 0x3534302a
#define __dw_pcie_ver_cmp(_pci, _ver, _op) \
((_pci)->version _op DW_PCIE_VER_ ## _ver)
@@ -167,6 +169,18 @@
#define PCIE_MSIX_DOORBELL 0x948
#define PCIE_MSIX_DOORBELL_PF_SHIFT 24
+/*
+ * eDMA CSRs. DW PCIe IP-core v4.70a and older had the eDMA registers accessible
+ * over the Port Logic registers space. Afterwards the unrolled mapping was
+ * introduced so eDMA and iATU could be accessed via a dedicated registers
+ * space.
+ */
+#define PCIE_DMA_VIEWPORT_BASE 0x970
+#define PCIE_DMA_UNROLL_BASE 0x80000
+#define PCIE_DMA_CTRL 0x008
+#define PCIE_DMA_NUM_WR_CHAN GENMASK(3, 0)
+#define PCIE_DMA_NUM_RD_CHAN GENMASK(19, 16)
+
#define PCIE_PL_CHK_REG_CONTROL_STATUS 0xB20
#define PCIE_PL_CHK_REG_CHK_REG_START BIT(0)
#define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS BIT(1)
@@ -215,6 +229,7 @@
* this offset, if atu_base not set.
*/
#define DEFAULT_DBI_ATU_OFFSET (0x3 << 20)
+#define DEFAULT_DBI_DMA_OFFSET PCIE_DMA_UNROLL_BASE
#define MAX_MSI_IRQS 256
#define MAX_MSI_IRQS_PER_CTRL 32
@@ -226,6 +241,9 @@
#define MAX_IATU_IN 256
#define MAX_IATU_OUT 256
+/* Default eDMA LLP memory size */
+#define DMA_LLP_MEM_SIZE PAGE_SIZE
+
struct dw_pcie;
struct dw_pcie_rp;
struct dw_pcie_ep;
@@ -369,6 +387,7 @@ struct dw_pcie {
int num_lanes;
int link_gen;
u8 n_fts[2];
+ struct dw_edma_chip edma;
struct clk_bulk_data app_clks[DW_PCIE_NUM_APP_CLKS];
struct clk_bulk_data core_clks[DW_PCIE_NUM_CORE_CLKS];
struct reset_control_bulk_data app_rsts[DW_PCIE_NUM_APP_RSTS];
@@ -408,6 +427,8 @@ int dw_pcie_prog_ep_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index);
void dw_pcie_setup(struct dw_pcie *pci);
void dw_pcie_iatu_detect(struct dw_pcie *pci);
+int dw_pcie_edma_detect(struct dw_pcie *pci);
+void dw_pcie_edma_remove(struct dw_pcie *pci);
static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
{
--
2.39.0
^ permalink raw reply related
* [PATCH v9 23/27] dmaengine: dw-edma: Add mem-mapped LL-entries support
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Currently the DW eDMA driver only supports the linked lists memory
allocated locally with respect to the remote eDMA engine setup. It means
the linked lists will be accessible by the CPU via the MMIO space only. If
eDMA is embedded into the DW PCIe Root Ports or local End-points (which
support will be added in one of the following up commits) the linked lists
are supposed to be allocated in the CPU memory. In that case the
LL-entries can be directly accessed meanwhile the former case implies
using the MMIO-accessors for that.
In order to have both cases supported by the driver the dw_edma_region
descriptor should be fixed to contain the MMIO-backed and just
memory-based virtual addresses. The linked lists initialization procedure
will use one of them depending on the eDMA device nature. If the eDMA
engine is embedded into the local DW PCIe RP/EP controllers then the list
entries will be directly accessed by referencing the corresponding
structure fields. Otherwise the MMIO accessors usage will be preserved.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
Changelog v9:
- This is a new patch added on v9 stage of the series.
---
drivers/dma/dw-edma/dw-edma-pcie.c | 32 ++++++-------
drivers/dma/dw-edma/dw-edma-v0-core.c | 69 +++++++++++++++++----------
include/linux/dma/edma.h | 5 +-
3 files changed, 64 insertions(+), 42 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 3f9dadc73854..2b40f2b44f5e 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -240,20 +240,20 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
struct dw_edma_block *ll_block = &vsec_data.ll_wr[i];
struct dw_edma_block *dt_block = &vsec_data.dt_wr[i];
- ll_region->vaddr = pcim_iomap_table(pdev)[ll_block->bar];
- if (!ll_region->vaddr)
+ ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
+ if (!ll_region->vaddr.io)
return -ENOMEM;
- ll_region->vaddr += ll_block->off;
+ ll_region->vaddr.io += ll_block->off;
ll_region->paddr = pci_bus_address(pdev, ll_block->bar);
ll_region->paddr += ll_block->off;
ll_region->sz = ll_block->sz;
- dt_region->vaddr = pcim_iomap_table(pdev)[dt_block->bar];
- if (!dt_region->vaddr)
+ dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
+ if (!dt_region->vaddr.io)
return -ENOMEM;
- dt_region->vaddr += dt_block->off;
+ dt_region->vaddr.io += dt_block->off;
dt_region->paddr = pci_bus_address(pdev, dt_block->bar);
dt_region->paddr += dt_block->off;
dt_region->sz = dt_block->sz;
@@ -265,20 +265,20 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
struct dw_edma_block *ll_block = &vsec_data.ll_rd[i];
struct dw_edma_block *dt_block = &vsec_data.dt_rd[i];
- ll_region->vaddr = pcim_iomap_table(pdev)[ll_block->bar];
- if (!ll_region->vaddr)
+ ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
+ if (!ll_region->vaddr.io)
return -ENOMEM;
- ll_region->vaddr += ll_block->off;
+ ll_region->vaddr.io += ll_block->off;
ll_region->paddr = pci_bus_address(pdev, ll_block->bar);
ll_region->paddr += ll_block->off;
ll_region->sz = ll_block->sz;
- dt_region->vaddr = pcim_iomap_table(pdev)[dt_block->bar];
- if (!dt_region->vaddr)
+ dt_region->vaddr.io = pcim_iomap_table(pdev)[dt_block->bar];
+ if (!dt_region->vaddr.io)
return -ENOMEM;
- dt_region->vaddr += dt_block->off;
+ dt_region->vaddr.io += dt_block->off;
dt_region->paddr = pci_bus_address(pdev, dt_block->bar);
dt_region->paddr += dt_block->off;
dt_region->sz = dt_block->sz;
@@ -303,24 +303,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
pci_dbg(pdev, "L. List:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
i, vsec_data.ll_wr[i].bar,
vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
- chip->ll_region_wr[i].vaddr, &chip->ll_region_wr[i].paddr);
+ chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr);
pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
i, vsec_data.dt_wr[i].bar,
vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
- chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
+ chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr);
}
for (i = 0; i < chip->ll_rd_cnt; i++) {
pci_dbg(pdev, "L. List:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
i, vsec_data.ll_rd[i].bar,
vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
- chip->ll_region_rd[i].vaddr, &chip->ll_region_rd[i].paddr);
+ chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr);
pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
i, vsec_data.dt_rd[i].bar,
vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
- chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
+ chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr);
}
pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 51a34b43434c..7df833873a19 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -159,9 +159,6 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
#define GET_CH_32(dw, dir, ch, name) \
readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name))
-#define SET_LL_32(ll, value) \
- writel(value, ll)
-
static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
u64 value, void __iomem *addr)
{
@@ -219,9 +216,6 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
#define GET_CH_64(dw, dir, ch, name) \
readq_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name))
-#define SET_LL_64(ll, value) \
- writeq(value, ll)
-
/* eDMA management callbacks */
void dw_edma_v0_core_off(struct dw_edma *dw)
{
@@ -293,17 +287,53 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
GET_RW_32(dw, dir, int_status));
}
+static void dw_edma_v0_write_ll_data(struct dw_edma_chunk *chunk, int i,
+ u32 control, u32 size, u64 sar, u64 dar)
+{
+ ptrdiff_t ofs = i * sizeof(struct dw_edma_v0_lli);
+
+ if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+ struct dw_edma_v0_lli *lli = chunk->ll_region.vaddr.mem + ofs;
+
+ lli->control = control;
+ lli->transfer_size = size;
+ lli->sar.reg = sar;
+ lli->dar.reg = dar;
+ } else {
+ struct dw_edma_v0_lli __iomem *lli = chunk->ll_region.vaddr.io + ofs;
+
+ writel(control, &lli->control);
+ writel(size, &lli->transfer_size);
+ writeq(sar, &lli->sar.reg);
+ writeq(dar, &lli->dar.reg);
+ }
+}
+
+static void dw_edma_v0_write_ll_link(struct dw_edma_chunk *chunk,
+ int i, u32 control, u64 pointer)
+{
+ ptrdiff_t ofs = i * sizeof(struct dw_edma_v0_lli);
+
+ if (chunk->chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+ struct dw_edma_v0_llp *llp = chunk->ll_region.vaddr.mem + ofs;
+
+ llp->control = control;
+ llp->llp.reg = pointer;
+ } else {
+ struct dw_edma_v0_llp __iomem *llp = chunk->ll_region.vaddr.io + ofs;
+
+ writel(control, &llp->control);
+ writeq(pointer, &llp->llp.reg);
+ }
+}
+
static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
{
struct dw_edma_burst *child;
struct dw_edma_chan *chan = chunk->chan;
- struct dw_edma_v0_lli __iomem *lli;
- struct dw_edma_v0_llp __iomem *llp;
u32 control = 0, i = 0;
int j;
- lli = chunk->ll_region.vaddr;
-
if (chunk->cb)
control = DW_EDMA_V0_CB;
@@ -315,27 +345,16 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
control |= DW_EDMA_V0_RIE;
}
- /* Channel control */
- SET_LL_32(&lli[i].control, control);
- /* Transfer size */
- SET_LL_32(&lli[i].transfer_size, child->sz);
- /* SAR */
- SET_LL_64(&lli[i].sar.reg, child->sar);
- /* DAR */
- SET_LL_64(&lli[i].dar.reg, child->dar);
-
- i++;
+
+ dw_edma_v0_write_ll_data(chunk, i++, control, child->sz,
+ child->sar, child->dar);
}
- llp = (void __iomem *)&lli[i];
control = DW_EDMA_V0_LLP | DW_EDMA_V0_TCB;
if (!chunk->cb)
control |= DW_EDMA_V0_CB;
- /* Channel control */
- SET_LL_32(&llp->control, control);
- /* Linked list */
- SET_LL_64(&llp->llp.reg, chunk->ll_region.paddr);
+ dw_edma_v0_write_ll_link(chunk, i, control, chunk->ll_region.paddr);
}
void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 9d44da4aa59d..08833f12b386 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -19,7 +19,10 @@ struct dw_edma;
struct dw_edma_region {
u64 paddr;
- void __iomem *vaddr;
+ union {
+ void *mem;
+ void __iomem *io;
+ } vaddr;
size_t sz;
};
--
2.39.0
^ permalink raw reply related
* [PATCH v9 26/27] PCI: bt1: Set 64-bit DMA-mask
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
caihuoqing, Yoshihiro Shimoda, linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
The DW PCIe RC IP-core is synthesized with the 64-bits AXI address bus.
Since the device is also equipped with the eDMA engine we need to
explicitly set the device DMA-mask so the DMA-engine clients would be able
to allocate the data buffers from the DMA-able memory space.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
---
Changelog v7:
- This is a new patch added on v7 stage of the series. (@Robin)
---
drivers/pci/controller/dwc/pcie-bt1.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/pci/controller/dwc/pcie-bt1.c b/drivers/pci/controller/dwc/pcie-bt1.c
index 3346770e6654..95a723a6fd46 100644
--- a/drivers/pci/controller/dwc/pcie-bt1.c
+++ b/drivers/pci/controller/dwc/pcie-bt1.c
@@ -583,6 +583,10 @@ static int bt1_pcie_add_port(struct bt1_pcie *btpci)
struct device *dev = &btpci->pdev->dev;
int ret;
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
+ if (ret)
+ return ret;
+
btpci->dw.version = DW_PCIE_VER_460A;
btpci->dw.dev = dev;
btpci->dw.ops = &bt1_pcie_ops;
--
2.39.0
^ permalink raw reply related
* [PATCH v9 22/27] dmaengine: dw-edma: Skip cleanup procedure if no private data found
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
DW eDMA driver private data is preserved in the passed DW eDMA chip info
structure. If either probe procedure failed or for some reason the passed
info object doesn't have private data pointer initialized we need to halt
the DMA device cleanup procedure in order to prevent possible system
crashes.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index e3671bfbe186..1906a836f0aa 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -1011,6 +1011,10 @@ int dw_edma_remove(struct dw_edma_chip *chip)
struct dw_edma *dw = chip->dw;
int i;
+ /* Skip removal if no private data found */
+ if (!dw)
+ return -ENODEV;
+
/* Disable eDMA */
dw_edma_v0_core_off(dw);
--
2.39.0
^ permalink raw reply related
* [PATCH v9 20/27] dmaengine: dw-edma: Drop DT-region allocation
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
There is no point in allocating an additional memory for the data target
regions passed then to the client drivers. Just use the already available
structures defined in the dw_edma_chip instance.
Note these regions are unused in normal circumstances since they are
specific to the case of eDMA being embedded into the DW PCIe End-point and
having it's CSRs accessible over a End-point' BAR. This case is only known
to be implemented as a part of the Synopsys PCIe EndPoint IP prototype
kit.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 21 ++++-----------------
1 file changed, 4 insertions(+), 17 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 58808bec4148..040a88cfe070 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -738,7 +738,6 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
{
struct dw_edma_chip *chip = dw->chip;
- struct dw_edma_region *dt_region;
struct device *dev = chip->dev;
struct dw_edma_chan *chan;
struct dw_edma_irq *irq;
@@ -754,12 +753,6 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
for (i = 0; i < ch_cnt; i++) {
chan = &dw->chan[i];
- dt_region = devm_kzalloc(dev, sizeof(*dt_region), GFP_KERNEL);
- if (!dt_region)
- return -ENOMEM;
-
- chan->vc.chan.private = dt_region;
-
chan->dw = dw;
if (i < dw->wr_ch_cnt) {
@@ -807,17 +800,11 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
chan->msi.data);
chan->vc.desc_free = vchan_free_desc;
- vchan_init(&chan->vc, dma);
+ chan->vc.chan.private = chan->dir == EDMA_DIR_WRITE ?
+ &dw->chip->dt_region_wr[chan->id] :
+ &dw->chip->dt_region_rd[chan->id];
- if (chan->dir == EDMA_DIR_WRITE) {
- dt_region->paddr = chip->dt_region_wr[chan->id].paddr;
- dt_region->vaddr = chip->dt_region_wr[chan->id].vaddr;
- dt_region->sz = chip->dt_region_wr[chan->id].sz;
- } else {
- dt_region->paddr = chip->dt_region_rd[chan->id].paddr;
- dt_region->vaddr = chip->dt_region_rd[chan->id].vaddr;
- dt_region->sz = chip->dt_region_rd[chan->id].sz;
- }
+ vchan_init(&chan->vc, dma);
dw_edma_v0_core_device_config(chan);
}
--
2.39.0
^ permalink raw reply related
* [PATCH v9 18/27] dmaengine: dw-edma: Use DMA-engine device DebugFS subdirectory
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Since all DW eDMA read and write channels are now installed in a framework
of a single DMA-engine device, we can freely move all the DW eDMA-specific
DebugFS nodes into a ready-to-use DMA-engine DebugFS subdirectory. It's
created during the DMA-device registration and can be found in the
dma_device.dbg_dev_root field.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 3 ---
drivers/dma/dw-edma/dw-edma-core.h | 3 ---
drivers/dma/dw-edma/dw-edma-v0-core.c | 5 -----
drivers/dma/dw-edma/dw-edma-v0-core.h | 1 -
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 16 ++++------------
drivers/dma/dw-edma/dw-edma-v0-debugfs.h | 5 -----
6 files changed, 4 insertions(+), 29 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index c3ecae4287d0..58808bec4148 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -1038,9 +1038,6 @@ int dw_edma_remove(struct dw_edma_chip *chip)
list_del(&chan->vc.chan.device_node);
}
- /* Turn debugfs off */
- dw_edma_v0_core_debugfs_off(dw);
-
return 0;
}
EXPORT_SYMBOL_GPL(dw_edma_remove);
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index b576a8fff45a..e3ad3e372b55 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -111,9 +111,6 @@ struct dw_edma {
raw_spinlock_t lock; /* Only for legacy */
struct dw_edma_chip *chip;
-#ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs;
-#endif /* CONFIG_DEBUG_FS */
};
struct dw_edma_sg {
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 77e6cfe52e0a..66f296daac5a 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -504,8 +504,3 @@ void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
{
dw_edma_v0_debugfs_on(dw);
}
-
-void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
-{
- dw_edma_v0_debugfs_off(dw);
-}
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
index 75aec6d31b21..ab96a1f48080 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.h
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
@@ -23,6 +23,5 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
/* eDMA debug fs callbacks */
void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
-void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
#endif /* _DW_EDMA_V0_CORE_H */
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index e6cf608d121b..d12c607433bf 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -268,7 +268,7 @@ static void dw_edma_debugfs_regs(struct dw_edma *dw)
struct dentry *regs_dent;
int nr_entries;
- regs_dent = debugfs_create_dir(REGISTERS_STR, dw->debugfs);
+ regs_dent = debugfs_create_dir(REGISTERS_STR, dw->dma.dbg_dev_root);
nr_entries = ARRAY_SIZE(debugfs_regs);
dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);
@@ -282,17 +282,9 @@ void dw_edma_v0_debugfs_on(struct dw_edma *dw)
if (!debugfs_initialized())
return;
- dw->debugfs = debugfs_create_dir(dw->name, NULL);
-
- debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
- debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
- debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
+ debugfs_create_u32("mf", 0444, dw->dma.dbg_dev_root, &dw->chip->mf);
+ debugfs_create_u16("wr_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->wr_ch_cnt);
+ debugfs_create_u16("rd_ch_cnt", 0444, dw->dma.dbg_dev_root, &dw->rd_ch_cnt);
dw_edma_debugfs_regs(dw);
}
-
-void dw_edma_v0_debugfs_off(struct dw_edma *dw)
-{
- debugfs_remove_recursive(dw->debugfs);
- dw->debugfs = NULL;
-}
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.h b/drivers/dma/dw-edma/dw-edma-v0-debugfs.h
index 3391b86edf5a..fb3342d97d6d 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.h
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.h
@@ -13,15 +13,10 @@
#ifdef CONFIG_DEBUG_FS
void dw_edma_v0_debugfs_on(struct dw_edma *dw);
-void dw_edma_v0_debugfs_off(struct dw_edma *dw);
#else
static inline void dw_edma_v0_debugfs_on(struct dw_edma *dw)
{
}
-
-static inline void dw_edma_v0_debugfs_off(struct dw_edma *dw)
-{
-}
#endif /* CONFIG_DEBUG_FS */
#endif /* _DW_EDMA_V0_DEBUG_FS_H */
--
2.39.0
^ permalink raw reply related
* [PATCH v9 25/27] PCI: dwc: Set coherent DMA-mask on MSI-address allocation
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
caihuoqing, Yoshihiro Shimoda, linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
The MSI target address requires to be reserved within the lowest 4GB
memory in order to support the PCIe peripherals with no 64-bit MSI TLPs
support. Since the allocation is done from the DMA-coherent memory let's
modify the allocation procedure to setting the coherent DMA-mask only and
avoiding the streaming DMA-mask modification. Thus at least the streaming
DMA operations would work with no artificial limitations. It will be
specifically useful for the eDMA-capable controllers so the corresponding
DMA-engine clients would map the DMA buffers with no need in the SWIOTLB
intervention for the buffers allocated above the 4GB memory region.
While at it let's add a brief comment about the reason of having the MSI
target address allocated from the DMA-coherent memory limited with the 4GB
upper bound.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Robin Murphy <robin.murphy@arm.com>
---
Changelog v8:
- This is a new patch added on v8 stage of the series.
(@Robin, @Christoph)
---
drivers/pci/controller/dwc/pcie-designware-host.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index 3ab6ae3712c4..e10608af39b4 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -366,7 +366,16 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
dw_chained_msi_isr, pp);
}
- ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ /*
+ * Even though the iMSI-RX Module supports 64-bit addresses some
+ * peripheral PCIe devices may lack the 64-bit messages support. In
+ * order not to miss MSI TLPs from those devices the MSI target address
+ * has to be reserved within the lowest 4GB.
+ * Note until there is a better alternative found the reservation is
+ * done by allocating from the artificially limited DMA-coherent
+ * memory.
+ */
+ ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (ret)
dev_warn(dev, "Failed to set DMA mask to 32-bit. Devices with only 32-bit MSI support may not work properly\n");
--
2.39.0
^ permalink raw reply related
* [PATCH v9 15/27] dmaengine: dw-edma: Simplify the DebugFS context CSRs init procedure
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
DW eDMA v4.70a and older have the read and write channels context CSRs
indirectly accessible. It means the CSRs like Channel Control, Xfer size,
SAR, DAR and LLP address are accessed over at a fixed MMIO address, but
their reference to the corresponding channel is determined by the Viewport
CSR. In order to have a coherent access to these registers the CSR IOs are
supposed to be protected with a spin-lock. DW eDMA v4.80a and newer
normally have unrolled Read/Write channel context registers. That is all
CSRs denoted before are directly mapped in the controller MMIO space.
Since both normal and viewport-based registers are exposed via the DebugFS
nodes, the original code author decided to implement an algorithm based on
the unrolled CSRs mapping with the viewport addresses recalculation if
it's required. The problem is that such implementation turned to be first
unscalable (supports a platform with only single eDMA available since a
base address statically preserved) and second needlessly overcomplicated
(it loops over all Rd/Wr context addresses and re-calculates the viewport
base address on each DebugFS node access). The algorithm can be greatly
simplified just by adding the channel ID and it's direction fields in the
eDMA DebugFS node descriptor. These new parameters can be used to find a
CSR offset within the corresponding channel registers space. The DW eDMA
DebugFS node getter afterwards will also use them in order to activate the
respective context CSRs viewport before reading data from the specified
register. In case of the unrolled version of the CSRs mapping there won't
be any spin-lock taken/released, no viewport activation as before this
modification.
Note this modification fixes the REGISTER() macros using an externally
defined local variable. The same problem with the rest of the macro will
be fixed in the next commit.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 84 +++++++++++-------------
1 file changed, 38 insertions(+), 46 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 7bb3363b40e4..1596eedf35c5 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -15,9 +15,27 @@
#define REGS_ADDR(name) \
((void __iomem *)®s->name)
+
+#define REGS_CH_ADDR(name, _dir, _ch) \
+ ({ \
+ struct dw_edma_v0_ch_regs __iomem *__ch_regs; \
+ \
+ if ((dw)->chip->mf == EDMA_MF_EDMA_LEGACY) \
+ __ch_regs = ®s->type.legacy.ch; \
+ else if (_dir == EDMA_DIR_READ) \
+ __ch_regs = ®s->type.unroll.ch[_ch].rd; \
+ else \
+ __ch_regs = ®s->type.unroll.ch[_ch].wr; \
+ \
+ (void __iomem *)&__ch_regs->name; \
+ })
+
#define REGISTER(name) \
{ #name, REGS_ADDR(name) }
+#define CTX_REGISTER(name, dir, ch) \
+ { #name, REGS_CH_ADDR(name, dir, ch), dir, ch }
+
#define WR_REGISTER(name) \
{ #name, REGS_ADDR(wr_##name) }
#define RD_REGISTER(name) \
@@ -41,14 +59,11 @@
static struct dw_edma *dw;
static struct dw_edma_v0_regs __iomem *regs;
-static struct {
- void __iomem *start;
- void __iomem *end;
-} lim[2][EDMA_V0_MAX_NR_CH];
-
struct dw_edma_debugfs_entry {
const char *name;
void __iomem *reg;
+ enum dw_edma_dir dir;
+ u16 ch;
};
static int dw_edma_debugfs_u32_get(void *data, u64 *val)
@@ -58,33 +73,16 @@ static int dw_edma_debugfs_u32_get(void *data, u64 *val)
if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
reg >= (void __iomem *)®s->type.legacy.ch) {
- void __iomem *ptr = ®s->type.legacy.ch;
- u32 viewport_sel = 0;
unsigned long flags;
- u16 ch;
-
- for (ch = 0; ch < dw->wr_ch_cnt; ch++)
- if (lim[0][ch].start >= reg && reg < lim[0][ch].end) {
- ptr += (reg - lim[0][ch].start);
- goto legacy_sel_wr;
- }
-
- for (ch = 0; ch < dw->rd_ch_cnt; ch++)
- if (lim[1][ch].start >= reg && reg < lim[1][ch].end) {
- ptr += (reg - lim[1][ch].start);
- goto legacy_sel_rd;
- }
-
- return 0;
-legacy_sel_rd:
- viewport_sel = BIT(31);
-legacy_sel_wr:
- viewport_sel |= FIELD_PREP(EDMA_V0_VIEWPORT_MASK, ch);
+ u32 viewport_sel;
+
+ viewport_sel = entry->dir == EDMA_DIR_READ ? BIT(31) : 0;
+ viewport_sel |= FIELD_PREP(EDMA_V0_VIEWPORT_MASK, entry->ch);
raw_spin_lock_irqsave(&dw->lock, flags);
writel(viewport_sel, ®s->type.legacy.viewport_sel);
- *val = readl(ptr);
+ *val = readl(reg);
raw_spin_unlock_irqrestore(&dw->lock, flags);
} else {
@@ -114,19 +112,19 @@ static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry ini[],
}
}
-static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
+static void dw_edma_debugfs_regs_ch(enum dw_edma_dir dir, u16 ch,
struct dentry *dent)
{
- const struct dw_edma_debugfs_entry debugfs_regs[] = {
- REGISTER(ch_control1),
- REGISTER(ch_control2),
- REGISTER(transfer_size),
- REGISTER(sar.lsb),
- REGISTER(sar.msb),
- REGISTER(dar.lsb),
- REGISTER(dar.msb),
- REGISTER(llp.lsb),
- REGISTER(llp.msb),
+ struct dw_edma_debugfs_entry debugfs_regs[] = {
+ CTX_REGISTER(ch_control1, dir, ch),
+ CTX_REGISTER(ch_control2, dir, ch),
+ CTX_REGISTER(transfer_size, dir, ch),
+ CTX_REGISTER(sar.lsb, dir, ch),
+ CTX_REGISTER(sar.msb, dir, ch),
+ CTX_REGISTER(dar.lsb, dir, ch),
+ CTX_REGISTER(dar.msb, dir, ch),
+ CTX_REGISTER(llp.lsb, dir, ch),
+ CTX_REGISTER(llp.msb, dir, ch),
};
int nr_entries;
@@ -191,10 +189,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dent)
ch_dent = debugfs_create_dir(name, regs_dent);
- dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].wr, ch_dent);
-
- lim[0][i].start = ®s->type.unroll.ch[i].wr;
- lim[0][i].end = ®s->type.unroll.ch[i].padding_1[0];
+ dw_edma_debugfs_regs_ch(EDMA_DIR_WRITE, i, ch_dent);
}
}
@@ -256,10 +251,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dent)
ch_dent = debugfs_create_dir(name, regs_dent);
- dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].rd, ch_dent);
-
- lim[1][i].start = ®s->type.unroll.ch[i].rd;
- lim[1][i].end = ®s->type.unroll.ch[i].padding_2[0];
+ dw_edma_debugfs_regs_ch(EDMA_DIR_READ, i, ch_dent);
}
}
--
2.39.0
^ permalink raw reply related
* [PATCH v9 16/27] dmaengine: dw-edma: Move eDMA data pointer to DebugFS node descriptor
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
The last thing that really stops the DebugFS part of the eDMA driver from
supporting the multi-eDMA platform in is keeping the eDMA private data
pointer in the static area of the DebugFS module. Since the DebugFS node
descriptors are now kz-allocated we can freely move that pointer to being
preserved in the descriptors. After the DebugFS initialization procedure
that pointer will be used in the DebugFS files getter to access the common
CSRs space and the context CSRs spin-lock. So the main part of this change
is connected with the DebugFS nodes descriptors initialization macros,
which aside with already defined prototypes now require to have the DW
eDMA private data pointer passed.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 242 +++++++++++------------
1 file changed, 117 insertions(+), 125 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 1596eedf35c5..e6cf608d121b 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -13,53 +13,55 @@
#include "dw-edma-v0-regs.h"
#include "dw-edma-core.h"
-#define REGS_ADDR(name) \
- ((void __iomem *)®s->name)
+#define REGS_ADDR(dw, name) \
+ ({ \
+ struct dw_edma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \
+ \
+ (void __iomem *)&__regs->name; \
+ })
-#define REGS_CH_ADDR(name, _dir, _ch) \
+#define REGS_CH_ADDR(dw, name, _dir, _ch) \
({ \
struct dw_edma_v0_ch_regs __iomem *__ch_regs; \
\
if ((dw)->chip->mf == EDMA_MF_EDMA_LEGACY) \
- __ch_regs = ®s->type.legacy.ch; \
+ __ch_regs = REGS_ADDR(dw, type.legacy.ch); \
else if (_dir == EDMA_DIR_READ) \
- __ch_regs = ®s->type.unroll.ch[_ch].rd; \
+ __ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].rd); \
else \
- __ch_regs = ®s->type.unroll.ch[_ch].wr; \
+ __ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].wr); \
\
(void __iomem *)&__ch_regs->name; \
})
-#define REGISTER(name) \
- { #name, REGS_ADDR(name) }
+#define REGISTER(dw, name) \
+ { dw, #name, REGS_ADDR(dw, name) }
-#define CTX_REGISTER(name, dir, ch) \
- { #name, REGS_CH_ADDR(name, dir, ch), dir, ch }
+#define CTX_REGISTER(dw, name, dir, ch) \
+ { dw, #name, REGS_CH_ADDR(dw, name, dir, ch), dir, ch }
-#define WR_REGISTER(name) \
- { #name, REGS_ADDR(wr_##name) }
-#define RD_REGISTER(name) \
- { #name, REGS_ADDR(rd_##name) }
+#define WR_REGISTER(dw, name) \
+ { dw, #name, REGS_ADDR(dw, wr_##name) }
+#define RD_REGISTER(dw, name) \
+ { dw, #name, REGS_ADDR(dw, rd_##name) }
-#define WR_REGISTER_LEGACY(name) \
- { #name, REGS_ADDR(type.legacy.wr_##name) }
+#define WR_REGISTER_LEGACY(dw, name) \
+ { dw, #name, REGS_ADDR(dw, type.legacy.wr_##name) }
#define RD_REGISTER_LEGACY(name) \
- { #name, REGS_ADDR(type.legacy.rd_##name) }
+ { dw, #name, REGS_ADDR(dw, type.legacy.rd_##name) }
-#define WR_REGISTER_UNROLL(name) \
- { #name, REGS_ADDR(type.unroll.wr_##name) }
-#define RD_REGISTER_UNROLL(name) \
- { #name, REGS_ADDR(type.unroll.rd_##name) }
+#define WR_REGISTER_UNROLL(dw, name) \
+ { dw, #name, REGS_ADDR(dw, type.unroll.wr_##name) }
+#define RD_REGISTER_UNROLL(dw, name) \
+ { dw, #name, REGS_ADDR(dw, type.unroll.rd_##name) }
#define WRITE_STR "write"
#define READ_STR "read"
#define CHANNEL_STR "channel"
#define REGISTERS_STR "registers"
-static struct dw_edma *dw;
-static struct dw_edma_v0_regs __iomem *regs;
-
struct dw_edma_debugfs_entry {
+ struct dw_edma *dw;
const char *name;
void __iomem *reg;
enum dw_edma_dir dir;
@@ -69,10 +71,11 @@ struct dw_edma_debugfs_entry {
static int dw_edma_debugfs_u32_get(void *data, u64 *val)
{
struct dw_edma_debugfs_entry *entry = data;
+ struct dw_edma *dw = entry->dw;
void __iomem *reg = entry->reg;
if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
- reg >= (void __iomem *)®s->type.legacy.ch) {
+ reg >= REGS_ADDR(dw, type.legacy.ch)) {
unsigned long flags;
u32 viewport_sel;
@@ -81,7 +84,7 @@ static int dw_edma_debugfs_u32_get(void *data, u64 *val)
raw_spin_lock_irqsave(&dw->lock, flags);
- writel(viewport_sel, ®s->type.legacy.viewport_sel);
+ writel(viewport_sel, REGS_ADDR(dw, type.legacy.viewport_sel));
*val = readl(reg);
raw_spin_unlock_irqrestore(&dw->lock, flags);
@@ -93,7 +96,8 @@ static int dw_edma_debugfs_u32_get(void *data, u64 *val)
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n");
-static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry ini[],
+static void dw_edma_debugfs_create_x32(struct dw_edma *dw,
+ const struct dw_edma_debugfs_entry ini[],
int nr_entries, struct dentry *dent)
{
struct dw_edma_debugfs_entry *entries;
@@ -112,62 +116,62 @@ static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry ini[],
}
}
-static void dw_edma_debugfs_regs_ch(enum dw_edma_dir dir, u16 ch,
- struct dentry *dent)
+static void dw_edma_debugfs_regs_ch(struct dw_edma *dw, enum dw_edma_dir dir,
+ u16 ch, struct dentry *dent)
{
struct dw_edma_debugfs_entry debugfs_regs[] = {
- CTX_REGISTER(ch_control1, dir, ch),
- CTX_REGISTER(ch_control2, dir, ch),
- CTX_REGISTER(transfer_size, dir, ch),
- CTX_REGISTER(sar.lsb, dir, ch),
- CTX_REGISTER(sar.msb, dir, ch),
- CTX_REGISTER(dar.lsb, dir, ch),
- CTX_REGISTER(dar.msb, dir, ch),
- CTX_REGISTER(llp.lsb, dir, ch),
- CTX_REGISTER(llp.msb, dir, ch),
+ CTX_REGISTER(dw, ch_control1, dir, ch),
+ CTX_REGISTER(dw, ch_control2, dir, ch),
+ CTX_REGISTER(dw, transfer_size, dir, ch),
+ CTX_REGISTER(dw, sar.lsb, dir, ch),
+ CTX_REGISTER(dw, sar.msb, dir, ch),
+ CTX_REGISTER(dw, dar.lsb, dir, ch),
+ CTX_REGISTER(dw, dar.msb, dir, ch),
+ CTX_REGISTER(dw, llp.lsb, dir, ch),
+ CTX_REGISTER(dw, llp.msb, dir, ch),
};
int nr_entries;
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dent);
+ dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, dent);
}
-static void dw_edma_debugfs_regs_wr(struct dentry *dent)
+static void dw_edma_debugfs_regs_wr(struct dw_edma *dw, struct dentry *dent)
{
const struct dw_edma_debugfs_entry debugfs_regs[] = {
/* eDMA global registers */
- WR_REGISTER(engine_en),
- WR_REGISTER(doorbell),
- WR_REGISTER(ch_arb_weight.lsb),
- WR_REGISTER(ch_arb_weight.msb),
+ WR_REGISTER(dw, engine_en),
+ WR_REGISTER(dw, doorbell),
+ WR_REGISTER(dw, ch_arb_weight.lsb),
+ WR_REGISTER(dw, ch_arb_weight.msb),
/* eDMA interrupts registers */
- WR_REGISTER(int_status),
- WR_REGISTER(int_mask),
- WR_REGISTER(int_clear),
- WR_REGISTER(err_status),
- WR_REGISTER(done_imwr.lsb),
- WR_REGISTER(done_imwr.msb),
- WR_REGISTER(abort_imwr.lsb),
- WR_REGISTER(abort_imwr.msb),
- WR_REGISTER(ch01_imwr_data),
- WR_REGISTER(ch23_imwr_data),
- WR_REGISTER(ch45_imwr_data),
- WR_REGISTER(ch67_imwr_data),
- WR_REGISTER(linked_list_err_en),
+ WR_REGISTER(dw, int_status),
+ WR_REGISTER(dw, int_mask),
+ WR_REGISTER(dw, int_clear),
+ WR_REGISTER(dw, err_status),
+ WR_REGISTER(dw, done_imwr.lsb),
+ WR_REGISTER(dw, done_imwr.msb),
+ WR_REGISTER(dw, abort_imwr.lsb),
+ WR_REGISTER(dw, abort_imwr.msb),
+ WR_REGISTER(dw, ch01_imwr_data),
+ WR_REGISTER(dw, ch23_imwr_data),
+ WR_REGISTER(dw, ch45_imwr_data),
+ WR_REGISTER(dw, ch67_imwr_data),
+ WR_REGISTER(dw, linked_list_err_en),
};
const struct dw_edma_debugfs_entry debugfs_unroll_regs[] = {
/* eDMA channel context grouping */
- WR_REGISTER_UNROLL(engine_chgroup),
- WR_REGISTER_UNROLL(engine_hshake_cnt.lsb),
- WR_REGISTER_UNROLL(engine_hshake_cnt.msb),
- WR_REGISTER_UNROLL(ch0_pwr_en),
- WR_REGISTER_UNROLL(ch1_pwr_en),
- WR_REGISTER_UNROLL(ch2_pwr_en),
- WR_REGISTER_UNROLL(ch3_pwr_en),
- WR_REGISTER_UNROLL(ch4_pwr_en),
- WR_REGISTER_UNROLL(ch5_pwr_en),
- WR_REGISTER_UNROLL(ch6_pwr_en),
- WR_REGISTER_UNROLL(ch7_pwr_en),
+ WR_REGISTER_UNROLL(dw, engine_chgroup),
+ WR_REGISTER_UNROLL(dw, engine_hshake_cnt.lsb),
+ WR_REGISTER_UNROLL(dw, engine_hshake_cnt.msb),
+ WR_REGISTER_UNROLL(dw, ch0_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch1_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch2_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch3_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch4_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch5_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch6_pwr_en),
+ WR_REGISTER_UNROLL(dw, ch7_pwr_en),
};
struct dentry *regs_dent, *ch_dent;
int nr_entries, i;
@@ -176,11 +180,11 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dent)
regs_dent = debugfs_create_dir(WRITE_STR, dent);
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dent);
+ dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);
if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
- dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
+ dw_edma_debugfs_create_x32(dw, debugfs_unroll_regs, nr_entries,
regs_dent);
}
@@ -189,47 +193,47 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dent)
ch_dent = debugfs_create_dir(name, regs_dent);
- dw_edma_debugfs_regs_ch(EDMA_DIR_WRITE, i, ch_dent);
+ dw_edma_debugfs_regs_ch(dw, EDMA_DIR_WRITE, i, ch_dent);
}
}
-static void dw_edma_debugfs_regs_rd(struct dentry *dent)
+static void dw_edma_debugfs_regs_rd(struct dw_edma *dw, struct dentry *dent)
{
const struct dw_edma_debugfs_entry debugfs_regs[] = {
/* eDMA global registers */
- RD_REGISTER(engine_en),
- RD_REGISTER(doorbell),
- RD_REGISTER(ch_arb_weight.lsb),
- RD_REGISTER(ch_arb_weight.msb),
+ RD_REGISTER(dw, engine_en),
+ RD_REGISTER(dw, doorbell),
+ RD_REGISTER(dw, ch_arb_weight.lsb),
+ RD_REGISTER(dw, ch_arb_weight.msb),
/* eDMA interrupts registers */
- RD_REGISTER(int_status),
- RD_REGISTER(int_mask),
- RD_REGISTER(int_clear),
- RD_REGISTER(err_status.lsb),
- RD_REGISTER(err_status.msb),
- RD_REGISTER(linked_list_err_en),
- RD_REGISTER(done_imwr.lsb),
- RD_REGISTER(done_imwr.msb),
- RD_REGISTER(abort_imwr.lsb),
- RD_REGISTER(abort_imwr.msb),
- RD_REGISTER(ch01_imwr_data),
- RD_REGISTER(ch23_imwr_data),
- RD_REGISTER(ch45_imwr_data),
- RD_REGISTER(ch67_imwr_data),
+ RD_REGISTER(dw, int_status),
+ RD_REGISTER(dw, int_mask),
+ RD_REGISTER(dw, int_clear),
+ RD_REGISTER(dw, err_status.lsb),
+ RD_REGISTER(dw, err_status.msb),
+ RD_REGISTER(dw, linked_list_err_en),
+ RD_REGISTER(dw, done_imwr.lsb),
+ RD_REGISTER(dw, done_imwr.msb),
+ RD_REGISTER(dw, abort_imwr.lsb),
+ RD_REGISTER(dw, abort_imwr.msb),
+ RD_REGISTER(dw, ch01_imwr_data),
+ RD_REGISTER(dw, ch23_imwr_data),
+ RD_REGISTER(dw, ch45_imwr_data),
+ RD_REGISTER(dw, ch67_imwr_data),
};
const struct dw_edma_debugfs_entry debugfs_unroll_regs[] = {
/* eDMA channel context grouping */
- RD_REGISTER_UNROLL(engine_chgroup),
- RD_REGISTER_UNROLL(engine_hshake_cnt.lsb),
- RD_REGISTER_UNROLL(engine_hshake_cnt.msb),
- RD_REGISTER_UNROLL(ch0_pwr_en),
- RD_REGISTER_UNROLL(ch1_pwr_en),
- RD_REGISTER_UNROLL(ch2_pwr_en),
- RD_REGISTER_UNROLL(ch3_pwr_en),
- RD_REGISTER_UNROLL(ch4_pwr_en),
- RD_REGISTER_UNROLL(ch5_pwr_en),
- RD_REGISTER_UNROLL(ch6_pwr_en),
- RD_REGISTER_UNROLL(ch7_pwr_en),
+ RD_REGISTER_UNROLL(dw, engine_chgroup),
+ RD_REGISTER_UNROLL(dw, engine_hshake_cnt.lsb),
+ RD_REGISTER_UNROLL(dw, engine_hshake_cnt.msb),
+ RD_REGISTER_UNROLL(dw, ch0_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch1_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch2_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch3_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch4_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch5_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch6_pwr_en),
+ RD_REGISTER_UNROLL(dw, ch7_pwr_en),
};
struct dentry *regs_dent, *ch_dent;
int nr_entries, i;
@@ -238,11 +242,11 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dent)
regs_dent = debugfs_create_dir(READ_STR, dent);
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dent);
+ dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);
if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
- dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
+ dw_edma_debugfs_create_x32(dw, debugfs_unroll_regs, nr_entries,
regs_dent);
}
@@ -251,15 +255,15 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dent)
ch_dent = debugfs_create_dir(name, regs_dent);
- dw_edma_debugfs_regs_ch(EDMA_DIR_READ, i, ch_dent);
+ dw_edma_debugfs_regs_ch(dw, EDMA_DIR_READ, i, ch_dent);
}
}
-static void dw_edma_debugfs_regs(void)
+static void dw_edma_debugfs_regs(struct dw_edma *dw)
{
const struct dw_edma_debugfs_entry debugfs_regs[] = {
- REGISTER(ctrl_data_arb_prior),
- REGISTER(ctrl),
+ REGISTER(dw, ctrl_data_arb_prior),
+ REGISTER(dw, ctrl),
};
struct dentry *regs_dent;
int nr_entries;
@@ -267,40 +271,28 @@ static void dw_edma_debugfs_regs(void)
regs_dent = debugfs_create_dir(REGISTERS_STR, dw->debugfs);
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dent);
+ dw_edma_debugfs_create_x32(dw, debugfs_regs, nr_entries, regs_dent);
- dw_edma_debugfs_regs_wr(regs_dent);
- dw_edma_debugfs_regs_rd(regs_dent);
+ dw_edma_debugfs_regs_wr(dw, regs_dent);
+ dw_edma_debugfs_regs_rd(dw, regs_dent);
}
-void dw_edma_v0_debugfs_on(struct dw_edma *_dw)
+void dw_edma_v0_debugfs_on(struct dw_edma *dw)
{
if (!debugfs_initialized())
return;
- dw = _dw;
- if (!dw)
- return;
-
- regs = dw->chip->reg_base;
- if (!regs)
- return;
-
dw->debugfs = debugfs_create_dir(dw->name, NULL);
debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
- dw_edma_debugfs_regs();
+ dw_edma_debugfs_regs(dw);
}
-void dw_edma_v0_debugfs_off(struct dw_edma *_dw)
+void dw_edma_v0_debugfs_off(struct dw_edma *dw)
{
- dw = _dw;
- if (!dw)
- return;
-
debugfs_remove_recursive(dw->debugfs);
dw->debugfs = NULL;
}
--
2.39.0
^ permalink raw reply related
* [PATCH v9 17/27] dmaengine: dw-edma: Join Write/Read channels into a single device
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Indeed there is no point in such split up because due to multiple reasons.
First of all eDMA read and write channels belong to one physical
controller. Splitting them up illogical. Secondly the channels
differentiating can be done by means of the filtering and the
dma_get_slave_caps() method. Finally having these channels handled
separately not only needlessly complicates the code, but also causes the
DebugFS error printed to console:
>> Debugfs: Directory '1f052000.pcie' with parent 'dmaengine' already present!
So to speak let's join the read/write channels into a single DMA device.
The client drivers will be able to choose the channel with required
capability by getting the DMA slave direction setting. It's default value
is overridden by the dw_edma_device_caps() callback in accordance with the
channel nature.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 116 +++++++++++++++--------------
drivers/dma/dw-edma/dw-edma-core.h | 5 +-
2 files changed, 61 insertions(+), 60 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index ecd3e8f7ac5d..c3ecae4287d0 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -208,6 +208,24 @@ static void dw_edma_start_transfer(struct dw_edma_chan *chan)
desc->chunks_alloc--;
}
+static void dw_edma_device_caps(struct dma_chan *dchan,
+ struct dma_slave_caps *caps)
+{
+ struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
+
+ if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+ if (chan->dir == EDMA_DIR_READ)
+ caps->directions = BIT(DMA_DEV_TO_MEM);
+ else
+ caps->directions = BIT(DMA_MEM_TO_DEV);
+ } else {
+ if (chan->dir == EDMA_DIR_WRITE)
+ caps->directions = BIT(DMA_DEV_TO_MEM);
+ else
+ caps->directions = BIT(DMA_MEM_TO_DEV);
+ }
+}
+
static int dw_edma_device_config(struct dma_chan *dchan,
struct dma_slave_config *config)
{
@@ -717,8 +735,7 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
}
}
-static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
- u32 wr_alloc, u32 rd_alloc)
+static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
{
struct dw_edma_chip *chip = dw->chip;
struct dw_edma_region *dt_region;
@@ -726,27 +743,15 @@ static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
struct dw_edma_chan *chan;
struct dw_edma_irq *irq;
struct dma_device *dma;
- u32 alloc, off_alloc;
- u32 i, j, cnt;
- int err = 0;
+ u32 i, ch_cnt;
u32 pos;
- if (write) {
- i = 0;
- cnt = dw->wr_ch_cnt;
- dma = &dw->wr_edma;
- alloc = wr_alloc;
- off_alloc = 0;
- } else {
- i = dw->wr_ch_cnt;
- cnt = dw->rd_ch_cnt;
- dma = &dw->rd_edma;
- alloc = rd_alloc;
- off_alloc = wr_alloc;
- }
+ ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt;
+ dma = &dw->dma;
INIT_LIST_HEAD(&dma->channels);
- for (j = 0; (alloc || dw->nr_irqs == 1) && j < cnt; j++, i++) {
+
+ for (i = 0; i < ch_cnt; i++) {
chan = &dw->chan[i];
dt_region = devm_kzalloc(dev, sizeof(*dt_region), GFP_KERNEL);
@@ -756,52 +761,62 @@ static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
chan->vc.chan.private = dt_region;
chan->dw = dw;
- chan->id = j;
- chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
+
+ if (i < dw->wr_ch_cnt) {
+ chan->id = i;
+ chan->dir = EDMA_DIR_WRITE;
+ } else {
+ chan->id = i - dw->wr_ch_cnt;
+ chan->dir = EDMA_DIR_READ;
+ }
+
chan->configured = false;
chan->request = EDMA_REQ_NONE;
chan->status = EDMA_ST_IDLE;
- if (write)
- chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
+ if (chan->dir == EDMA_DIR_WRITE)
+ chan->ll_max = (chip->ll_region_wr[chan->id].sz / EDMA_LL_SZ);
else
- chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
+ chan->ll_max = (chip->ll_region_rd[chan->id].sz / EDMA_LL_SZ);
chan->ll_max -= 1;
dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
- write ? "write" : "read", j, chan->ll_max);
+ chan->dir == EDMA_DIR_WRITE ? "write" : "read",
+ chan->id, chan->ll_max);
if (dw->nr_irqs == 1)
pos = 0;
+ else if (chan->dir == EDMA_DIR_WRITE)
+ pos = chan->id % wr_alloc;
else
- pos = off_alloc + (j % alloc);
+ pos = wr_alloc + chan->id % rd_alloc;
irq = &dw->irq[pos];
- if (write)
- irq->wr_mask |= BIT(j);
+ if (chan->dir == EDMA_DIR_WRITE)
+ irq->wr_mask |= BIT(chan->id);
else
- irq->rd_mask |= BIT(j);
+ irq->rd_mask |= BIT(chan->id);
irq->dw = dw;
memcpy(&chan->msi, &irq->msi, sizeof(chan->msi));
dev_vdbg(dev, "MSI:\t\tChannel %s[%u] addr=0x%.8x%.8x, data=0x%.8x\n",
- write ? "write" : "read", j,
+ chan->dir == EDMA_DIR_WRITE ? "write" : "read", chan->id,
chan->msi.address_hi, chan->msi.address_lo,
chan->msi.data);
chan->vc.desc_free = vchan_free_desc;
vchan_init(&chan->vc, dma);
- if (write) {
- dt_region->paddr = chip->dt_region_wr[j].paddr;
- dt_region->vaddr = chip->dt_region_wr[j].vaddr;
- dt_region->sz = chip->dt_region_wr[j].sz;
+ if (chan->dir == EDMA_DIR_WRITE) {
+ dt_region->paddr = chip->dt_region_wr[chan->id].paddr;
+ dt_region->vaddr = chip->dt_region_wr[chan->id].vaddr;
+ dt_region->sz = chip->dt_region_wr[chan->id].sz;
} else {
- dt_region->paddr = chip->dt_region_rd[j].paddr;
- dt_region->vaddr = chip->dt_region_rd[j].vaddr;
- dt_region->sz = chip->dt_region_rd[j].sz;
+ dt_region->paddr = chip->dt_region_rd[chan->id].paddr;
+ dt_region->vaddr = chip->dt_region_rd[chan->id].vaddr;
+ dt_region->sz = chip->dt_region_rd[chan->id].sz;
}
dw_edma_v0_core_device_config(chan);
@@ -813,7 +828,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
dma_cap_set(DMA_CYCLIC, dma->cap_mask);
dma_cap_set(DMA_PRIVATE, dma->cap_mask);
dma_cap_set(DMA_INTERLEAVE, dma->cap_mask);
- dma->directions = BIT(write ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV);
+ dma->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
dma->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
dma->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
dma->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
@@ -822,6 +837,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
dma->dev = chip->dev;
dma->device_alloc_chan_resources = dw_edma_alloc_chan_resources;
dma->device_free_chan_resources = dw_edma_free_chan_resources;
+ dma->device_caps = dw_edma_device_caps;
dma->device_config = dw_edma_device_config;
dma->device_pause = dw_edma_device_pause;
dma->device_resume = dw_edma_device_resume;
@@ -835,9 +851,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
dma_set_max_seg_size(dma->dev, U32_MAX);
/* Register DMA device */
- err = dma_async_device_register(dma);
-
- return err;
+ return dma_async_device_register(dma);
}
static inline void dw_edma_dec_irq_alloc(int *nr_irqs, u32 *alloc, u16 cnt)
@@ -982,13 +996,8 @@ int dw_edma_probe(struct dw_edma_chip *chip)
if (err)
return err;
- /* Setup write channels */
- err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
- if (err)
- goto err_irq_free;
-
- /* Setup read channels */
- err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
+ /* Setup write/read channels */
+ err = dw_edma_channel_setup(dw, wr_alloc, rd_alloc);
if (err)
goto err_irq_free;
@@ -1022,15 +1031,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
/* Deregister eDMA device */
- dma_async_device_unregister(&dw->wr_edma);
- list_for_each_entry_safe(chan, _chan, &dw->wr_edma.channels,
- vc.chan.device_node) {
- tasklet_kill(&chan->vc.task);
- list_del(&chan->vc.chan.device_node);
- }
-
- dma_async_device_unregister(&dw->rd_edma);
- list_for_each_entry_safe(chan, _chan, &dw->rd_edma.channels,
+ dma_async_device_unregister(&dw->dma);
+ list_for_each_entry_safe(chan, _chan, &dw->dma.channels,
vc.chan.device_node) {
tasklet_kill(&chan->vc.task);
list_del(&chan->vc.chan.device_node);
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index 85df2d511907..b576a8fff45a 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -98,10 +98,9 @@ struct dw_edma_irq {
struct dw_edma {
char name[20];
- struct dma_device wr_edma;
- u16 wr_ch_cnt;
+ struct dma_device dma;
- struct dma_device rd_edma;
+ u16 wr_ch_cnt;
u16 rd_ch_cnt;
struct dw_edma_irq *irq;
--
2.39.0
^ permalink raw reply related
* [PATCH v9 19/27] dmaengine: dw-edma: Use non-atomic io-64 methods
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Instead of splitting the 64-bits IOs up into two 32-bits ones it's
possible to use the already available non-atomic readq/writeq methods
implemented exactly for such cases. They are defined in the dedicated
header files io-64-nonatomic-lo-hi.h/io-64-nonatomic-hi-lo.h. So in case
if the 64-bits readq/writeq methods are unavailable on some platforms at
consideration, the corresponding drivers can have any of these headers
included and stop locally re-implementing the 64-bits IO accessors taking
into account the non-atomic nature of the included methods. Let's do that
in the DW eDMA driver too. Note by doing so we can discard the
CONFIG_64BIT config ifdefs from the code.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-v0-core.c | 55 +++++++++------------------
1 file changed, 18 insertions(+), 37 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 66f296daac5a..51a34b43434c 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -8,6 +8,8 @@
#include <linux/bitfield.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+
#include "dw-edma-core.h"
#include "dw-edma-v0-core.h"
#include "dw-edma-v0-regs.h"
@@ -53,8 +55,6 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
SET_32(dw, rd_##name, value); \
} while (0)
-#ifdef CONFIG_64BIT
-
#define SET_64(dw, name, value) \
writeq(value, &(__dw_regs(dw)->name))
@@ -80,8 +80,6 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
SET_64(dw, rd_##name, value); \
} while (0)
-#endif /* CONFIG_64BIT */
-
#define SET_COMPAT(dw, name, value) \
writel(value, &(__dw_regs(dw)->type.unroll.name))
@@ -164,14 +162,13 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
#define SET_LL_32(ll, value) \
writel(value, ll)
-#ifdef CONFIG_64BIT
-
static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
u64 value, void __iomem *addr)
{
+ unsigned long flags;
+
if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
u32 viewport_sel;
- unsigned long flags;
raw_spin_lock_irqsave(&dw->lock, flags);
@@ -181,22 +178,22 @@ static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
writel(viewport_sel,
&(__dw_regs(dw)->type.legacy.viewport_sel));
- writeq(value, addr);
+ }
+
+ writeq(value, addr);
+ if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
raw_spin_unlock_irqrestore(&dw->lock, flags);
- } else {
- writeq(value, addr);
- }
}
static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
const void __iomem *addr)
{
- u32 value;
+ unsigned long flags;
+ u64 value;
if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
u32 viewport_sel;
- unsigned long flags;
raw_spin_lock_irqsave(&dw->lock, flags);
@@ -206,12 +203,12 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
writel(viewport_sel,
&(__dw_regs(dw)->type.legacy.viewport_sel));
- value = readq(addr);
+ }
+
+ value = readq(addr);
+ if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
raw_spin_unlock_irqrestore(&dw->lock, flags);
- } else {
- value = readq(addr);
- }
return value;
}
@@ -225,8 +222,6 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
#define SET_LL_64(ll, value) \
writeq(value, ll)
-#endif /* CONFIG_64BIT */
-
/* eDMA management callbacks */
void dw_edma_v0_core_off(struct dw_edma *dw)
{
@@ -325,19 +320,10 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
/* Transfer size */
SET_LL_32(&lli[i].transfer_size, child->sz);
/* SAR */
- #ifdef CONFIG_64BIT
- SET_LL_64(&lli[i].sar.reg, child->sar);
- #else /* CONFIG_64BIT */
- SET_LL_32(&lli[i].sar.lsb, lower_32_bits(child->sar));
- SET_LL_32(&lli[i].sar.msb, upper_32_bits(child->sar));
- #endif /* CONFIG_64BIT */
+ SET_LL_64(&lli[i].sar.reg, child->sar);
/* DAR */
- #ifdef CONFIG_64BIT
- SET_LL_64(&lli[i].dar.reg, child->dar);
- #else /* CONFIG_64BIT */
- SET_LL_32(&lli[i].dar.lsb, lower_32_bits(child->dar));
- SET_LL_32(&lli[i].dar.msb, upper_32_bits(child->dar));
- #endif /* CONFIG_64BIT */
+ SET_LL_64(&lli[i].dar.reg, child->dar);
+
i++;
}
@@ -349,12 +335,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
/* Channel control */
SET_LL_32(&llp->control, control);
/* Linked list */
- #ifdef CONFIG_64BIT
- SET_LL_64(&llp->llp.reg, chunk->ll_region.paddr);
- #else /* CONFIG_64BIT */
- SET_LL_32(&llp->llp.lsb, lower_32_bits(chunk->ll_region.paddr));
- SET_LL_32(&llp->llp.msb, upper_32_bits(chunk->ll_region.paddr));
- #endif /* CONFIG_64BIT */
+ SET_LL_64(&llp->llp.reg, chunk->ll_region.paddr);
}
void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
--
2.39.0
^ permalink raw reply related
* [PATCH v9 21/27] dmaengine: dw-edma: Replace chip ID number with device name
From: Serge Semin @ 2023-01-13 17:14 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Using some abstract number as the DW eDMA chip identifier isn't really
practical. First of all there can be more than one DW eDMA controller on
the platform some of them can be detected as the PCIe end-points, some of
them can be embedded into the DW PCIe Root Port/End-point controllers.
Seeing some abstract number in for instance IRQ handlers list doesn't give
a notion regarding their reference to the particular DMA controller.
Secondly current DW eDMA chip id implementation doesn't provide the
multi-eDMA platforms support for same reason of possibly having eDMA
detected on different system buses. At the same time re-implementing
something ida-based won't give much benefits especially seeing the DW eDMA
chip ID is only used in the IRQ request procedure. So to speak in order to
preserve the code simplicity and get to have the multi-eDMA platforms
support let's just use the parental device name to create the DW eDMA
controller name.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
Changelog v2:
- Slightly extend the eDMA name array. (@Manivannan)
---
drivers/dma/dw-edma/dw-edma-core.c | 3 ++-
drivers/dma/dw-edma/dw-edma-core.h | 2 +-
drivers/dma/dw-edma/dw-edma-pcie.c | 1 -
include/linux/dma/edma.h | 1 -
4 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 040a88cfe070..e3671bfbe186 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -973,7 +973,8 @@ int dw_edma_probe(struct dw_edma_chip *chip)
if (!dw->chan)
return -ENOMEM;
- snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%d", chip->id);
+ snprintf(dw->name, sizeof(dw->name), "dw-edma-core:%s",
+ dev_name(chip->dev));
/* Disable eDMA, only to establish the ideal initial conditions */
dw_edma_v0_core_off(dw);
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index e3ad3e372b55..0ab2b6dba880 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -96,7 +96,7 @@ struct dw_edma_irq {
};
struct dw_edma {
- char name[20];
+ char name[32];
struct dma_device dma;
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index f530bacfd716..3f9dadc73854 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -222,7 +222,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
/* Data structure initialization */
chip->dev = dev;
- chip->id = pdev->devfn;
chip->mf = vsec_data.mf;
chip->nr_irqs = nr_irqs;
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 380a0a3e251f..9d44da4aa59d 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -76,7 +76,6 @@ enum dw_edma_chip_flags {
*/
struct dw_edma_chip {
struct device *dev;
- int id;
int nr_irqs;
const struct dw_edma_core_ops *ops;
u32 flags;
--
2.39.0
^ permalink raw reply related
* [PATCH v9 14/27] dmaengine: dw-edma: Rename DebugFS dentry variables to 'dent'
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Since we are about to add the eDMA channels direction support to the
debugfs module it will be confusing to have both the DebugFS directory and
the channels direction short names used in the same code. As a preparation
patch let's convert the DebugFS dentry 'dir' variables to having the
'dent' name so to prevent the confusion.
Suggested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
Changelog v2:
- This is a new patch added in v2. (@Manivannan)
---
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 46 ++++++++++++------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 78f15e4b07ac..7bb3363b40e4 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -96,7 +96,7 @@ static int dw_edma_debugfs_u32_get(void *data, u64 *val)
DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n");
static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry ini[],
- int nr_entries, struct dentry *dir)
+ int nr_entries, struct dentry *dent)
{
struct dw_edma_debugfs_entry *entries;
int i;
@@ -109,13 +109,13 @@ static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry ini[],
for (i = 0; i < nr_entries; i++) {
entries[i] = ini[i];
- debugfs_create_file_unsafe(entries[i].name, 0444, dir,
+ debugfs_create_file_unsafe(entries[i].name, 0444, dent,
&entries[i], &fops_x32);
}
}
static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
- struct dentry *dir)
+ struct dentry *dent)
{
const struct dw_edma_debugfs_entry debugfs_regs[] = {
REGISTER(ch_control1),
@@ -131,10 +131,10 @@ static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
int nr_entries;
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dir);
+ dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dent);
}
-static void dw_edma_debugfs_regs_wr(struct dentry *dir)
+static void dw_edma_debugfs_regs_wr(struct dentry *dent)
{
const struct dw_edma_debugfs_entry debugfs_regs[] = {
/* eDMA global registers */
@@ -171,34 +171,34 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
WR_REGISTER_UNROLL(ch6_pwr_en),
WR_REGISTER_UNROLL(ch7_pwr_en),
};
- struct dentry *regs_dir, *ch_dir;
+ struct dentry *regs_dent, *ch_dent;
int nr_entries, i;
char name[16];
- regs_dir = debugfs_create_dir(WRITE_STR, dir);
+ regs_dent = debugfs_create_dir(WRITE_STR, dent);
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
+ dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dent);
if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
- regs_dir);
+ regs_dent);
}
for (i = 0; i < dw->wr_ch_cnt; i++) {
snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
- ch_dir = debugfs_create_dir(name, regs_dir);
+ ch_dent = debugfs_create_dir(name, regs_dent);
- dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].wr, ch_dir);
+ dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].wr, ch_dent);
lim[0][i].start = ®s->type.unroll.ch[i].wr;
lim[0][i].end = ®s->type.unroll.ch[i].padding_1[0];
}
}
-static void dw_edma_debugfs_regs_rd(struct dentry *dir)
+static void dw_edma_debugfs_regs_rd(struct dentry *dent)
{
const struct dw_edma_debugfs_entry debugfs_regs[] = {
/* eDMA global registers */
@@ -236,27 +236,27 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
RD_REGISTER_UNROLL(ch6_pwr_en),
RD_REGISTER_UNROLL(ch7_pwr_en),
};
- struct dentry *regs_dir, *ch_dir;
+ struct dentry *regs_dent, *ch_dent;
int nr_entries, i;
char name[16];
- regs_dir = debugfs_create_dir(READ_STR, dir);
+ regs_dent = debugfs_create_dir(READ_STR, dent);
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
+ dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dent);
if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
- regs_dir);
+ regs_dent);
}
for (i = 0; i < dw->rd_ch_cnt; i++) {
snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
- ch_dir = debugfs_create_dir(name, regs_dir);
+ ch_dent = debugfs_create_dir(name, regs_dent);
- dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].rd, ch_dir);
+ dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].rd, ch_dent);
lim[1][i].start = ®s->type.unroll.ch[i].rd;
lim[1][i].end = ®s->type.unroll.ch[i].padding_2[0];
@@ -269,16 +269,16 @@ static void dw_edma_debugfs_regs(void)
REGISTER(ctrl_data_arb_prior),
REGISTER(ctrl),
};
- struct dentry *regs_dir;
+ struct dentry *regs_dent;
int nr_entries;
- regs_dir = debugfs_create_dir(REGISTERS_STR, dw->debugfs);
+ regs_dent = debugfs_create_dir(REGISTERS_STR, dw->debugfs);
nr_entries = ARRAY_SIZE(debugfs_regs);
- dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
+ dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dent);
- dw_edma_debugfs_regs_wr(regs_dir);
- dw_edma_debugfs_regs_rd(regs_dir);
+ dw_edma_debugfs_regs_wr(regs_dent);
+ dw_edma_debugfs_regs_rd(regs_dent);
}
void dw_edma_v0_debugfs_on(struct dw_edma *_dw)
--
2.39.0
^ permalink raw reply related
* [PATCH v9 05/27] dmaengine: dw-edma: Don't permit non-inc interleaved xfers
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel, Gustavo Pimentel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
DW eDMA controller always increments both source and destination
addresses. Permitting DMA interleaved transfers with no src_inc/dst_inc
flags set may lead to unexpected behaviour for the device users. Let's fix
that by terminating the interleaved transfers if at least one of the
dma_interleaved_template.{src_inc,dst_inc} flag is initialized with false
value. Note in addition to that we need to increase the source and
destination addresses accordingly after each iteration.
Fixes: 85e7518f42c8 ("dmaengine: dw-edma: Add device_prep_interleave_dma() support")
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 778d91d9fc1b..35588e14f79a 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -385,6 +385,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
return NULL;
if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0)
return NULL;
+ if (!xfer->xfer.il->src_inc || !xfer->xfer.il->dst_inc)
+ return NULL;
} else {
return NULL;
}
@@ -484,15 +486,13 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
struct dma_interleaved_template *il = xfer->xfer.il;
struct data_chunk *dc = &il->sgl[i];
- if (il->src_sgl) {
- src_addr += burst->sz;
+ src_addr += burst->sz;
+ if (il->src_sgl)
src_addr += dmaengine_get_src_icg(il, dc);
- }
- if (il->dst_sgl) {
- dst_addr += burst->sz;
+ dst_addr += burst->sz;
+ if (il->dst_sgl)
dst_addr += dmaengine_get_dst_icg(il, dc);
- }
}
}
--
2.39.0
^ permalink raw reply related
* [PATCH v9 07/27] dmaengine: dw-edma: Add CPU to PCIe bus address translation
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Starting from commit 9575632052ba ("dmaengine: make slave address
physical") the source and destination addresses of the DMA-slave device
have been converted to being defined in CPU address space. It's DMA-device
driver responsibility to properly convert them to the reachable DMA bus
spaces. In case of the DW eDMA device, the source or destination
peripheral (slave) devices reside PCIe bus space. Thus we need to perform
the PCIe Host/EP windows-based (i.e. ranges DT-property) addresses
translation otherwise the eDMA transactions won't work as expected (or can
be even harmful) in case if the CPU and PCIe address spaces don't match.
Note 1. Even though the DMA interleaved template has both source and
destination addresses declared of dma_addr_t type only CPU memory range is
supposed to be mapped in a way so to be seen by the DMA device since it's
a subject of the DMA getting towards the system side. The device part must
not be mapped since slave device resides in the PCIe bus space, which
isn't affected by IOMMUs or iATU translations. DW PCIe eDMA generates
corresponding MWr/MRd TLPs on its own.
Note 2. This functionality is mainly required for the remote eDMA setup
since the CPU address must be manually translated into the PCIe bus space
before being written to LLI.{SAR,DAR}. If eDMA is embedded into the
locally accessible DW PCIe RP/EP software-based translation isn't required
since it will be done by hardware by means of the Outbound iATU as long as
the DMA_BYPASS flag is cleared. If the later flag is set or there is no
Outbound iATU entry found to which the SAR or DAR falls in (for Read and
Write channel respectfully), there won't be any translation performed but
DMA will proceed with the corresponding source/destination address as is.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 18 +++++++++++++++++-
include/linux/dma/edma.h | 15 +++++++++++++++
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index d5c4192141ef..6c9f95a8e397 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -39,6 +39,17 @@ struct dw_edma_desc *vd2dw_edma_desc(struct virt_dma_desc *vd)
return container_of(vd, struct dw_edma_desc, vd);
}
+static inline
+u64 dw_edma_get_pci_address(struct dw_edma_chan *chan, phys_addr_t cpu_addr)
+{
+ struct dw_edma_chip *chip = chan->dw->chip;
+
+ if (chip->ops->pci_address)
+ return chip->ops->pci_address(chip->dev, cpu_addr);
+
+ return cpu_addr;
+}
+
static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
{
struct dw_edma_burst *burst;
@@ -327,11 +338,11 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan);
enum dma_transfer_direction dir = xfer->direction;
- phys_addr_t src_addr, dst_addr;
struct scatterlist *sg = NULL;
struct dw_edma_chunk *chunk;
struct dw_edma_burst *burst;
struct dw_edma_desc *desc;
+ u64 src_addr, dst_addr;
size_t fsz = 0;
u32 cnt = 0;
int i;
@@ -406,6 +417,11 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
dst_addr = chan->config.dst_addr;
}
+ if (dir == DMA_DEV_TO_MEM)
+ src_addr = dw_edma_get_pci_address(chan, (phys_addr_t)src_addr);
+ else
+ dst_addr = dw_edma_get_pci_address(chan, (phys_addr_t)dst_addr);
+
if (xfer->type == EDMA_XFER_CYCLIC) {
cnt = xfer->xfer.cyclic.cnt;
} else if (xfer->type == EDMA_XFER_SCATTER_GATHER) {
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index a864978ddd27..380a0a3e251f 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -23,8 +23,23 @@ struct dw_edma_region {
size_t sz;
};
+/**
+ * struct dw_edma_core_ops - platform-specific eDMA methods
+ * @irq_vector: Get IRQ number of the passed eDMA channel. Note the
+ * method accepts the channel id in the end-to-end
+ * numbering with the eDMA write channels being placed
+ * first in the row.
+ * @pci_address: Get PCIe bus address corresponding to the passed CPU
+ * address. Note there is no need in specifying this
+ * function if the address translation is performed by
+ * the DW PCIe RP/EP controller with the DW eDMA device in
+ * subject and DMA_BYPASS isn't set for all the outbound
+ * iATU windows. That will be done by the controller
+ * automatically.
+ */
struct dw_edma_core_ops {
int (*irq_vector)(struct device *dev, unsigned int nr);
+ u64 (*pci_address)(struct device *dev, phys_addr_t cpu_addr);
};
enum dw_edma_map_format {
--
2.39.0
^ permalink raw reply related
* [PATCH v9 13/27] dmaengine: dw-edma: Convert DebugFS descs to being kz-allocated
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
Currently all the DW eDMA DebugFS nodes descriptors are allocated on
stack, while the DW eDMA driver private data and CSR limits are statically
preserved. Such design won't work for the multi-eDMA platforms. As a
preparation to adding the multi-eDMA system setups support we need to have
each DebugFS node separately allocated and described. Afterwards we'll put
an addition info there like Read/Write channel flag, channel ID, DW eDMA
private data reference.
Note this conversion is mainly required due to having the legacy DW eDMA
controllers with indirect Read/Write channels context CSRs access. If we
didn't need to have a synchronized access to these registers the DebugFS
code of the driver would have been much simpler.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
Changelog v2:
- Drop __iomem qualifier from the struct dw_edma_debugfs_entry instance
definition in the dw_edma_debugfs_u32_get() method. (@Manivannan)
---
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 2121ffc33cf3..78f15e4b07ac 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -53,7 +53,8 @@ struct dw_edma_debugfs_entry {
static int dw_edma_debugfs_u32_get(void *data, u64 *val)
{
- void __iomem *reg = data;
+ struct dw_edma_debugfs_entry *entry = data;
+ void __iomem *reg = entry->reg;
if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
reg >= (void __iomem *)®s->type.legacy.ch) {
@@ -94,14 +95,22 @@ static int dw_edma_debugfs_u32_get(void *data, u64 *val)
}
DEFINE_DEBUGFS_ATTRIBUTE(fops_x32, dw_edma_debugfs_u32_get, NULL, "0x%08llx\n");
-static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry entries[],
+static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry ini[],
int nr_entries, struct dentry *dir)
{
+ struct dw_edma_debugfs_entry *entries;
int i;
+ entries = devm_kcalloc(dw->chip->dev, nr_entries, sizeof(*entries),
+ GFP_KERNEL);
+ if (!entries)
+ return;
+
for (i = 0; i < nr_entries; i++) {
+ entries[i] = ini[i];
+
debugfs_create_file_unsafe(entries[i].name, 0444, dir,
- entries[i].reg, &fops_x32);
+ &entries[i], &fops_x32);
}
}
--
2.39.0
^ permalink raw reply related
* [PATCH v9 11/27] dmaengine: dw-edma: Stop checking debugfs_create_*() return value
From: Serge Semin @ 2023-01-13 17:13 UTC (permalink / raw)
To: Gustavo Pimentel, Vinod Koul, Rob Herring, Bjorn Helgaas,
Lorenzo Pieralisi, Cai Huoqing, Robin Murphy, Jingoo Han,
Frank Li, Manivannan Sadhasivam
Cc: Serge Semin, Serge Semin, Alexey Malahov, Pavel Parkhomenko,
Krzysztof Wilczyński, caihuoqing, Yoshihiro Shimoda,
linux-pci, dmaengine, linux-kernel
In-Reply-To: <20230113171409.30470-1-Sergey.Semin@baikalelectronics.ru>
First of all they never return NULL. So checking their return value for
being not NULL just pointless. Secondly the DebugFS subsystem is designed
in a way to be used as simple as possible. So if one of the
debugfs_create_*() method in a hierarchy fails, the following methods will
just silently return the passed erroneous parental dentry. Finally the
code is supposed to be working no matter whether anything DebugFS-related
fails. So in order to make code simpler and DebugFS-independent let's drop
the debugfs_create_*() methods return value checking in the same way as
the most of the kernel drivers do.
Note in order to preserve some memory space we suggest to skip the DebugFS
nodes initialization if the file system in unavailable.
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 20 +++++---------------
1 file changed, 5 insertions(+), 15 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 8e61810dea4b..6e7f3ef60ca7 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -100,9 +100,8 @@ static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],
int i;
for (i = 0; i < nr_entries; i++) {
- if (!debugfs_create_file_unsafe(entries[i].name, 0444, dir,
- entries[i].reg, &fops_x32))
- break;
+ debugfs_create_file_unsafe(entries[i].name, 0444, dir,
+ entries[i].reg, &fops_x32);
}
}
@@ -168,8 +167,6 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
char name[16];
regs_dir = debugfs_create_dir(WRITE_STR, dir);
- if (!regs_dir)
- return;
nr_entries = ARRAY_SIZE(debugfs_regs);
dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
@@ -184,8 +181,6 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
ch_dir = debugfs_create_dir(name, regs_dir);
- if (!ch_dir)
- return;
dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].wr, ch_dir);
@@ -237,8 +232,6 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
char name[16];
regs_dir = debugfs_create_dir(READ_STR, dir);
- if (!regs_dir)
- return;
nr_entries = ARRAY_SIZE(debugfs_regs);
dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
@@ -253,8 +246,6 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
snprintf(name, sizeof(name), "%s:%d", CHANNEL_STR, i);
ch_dir = debugfs_create_dir(name, regs_dir);
- if (!ch_dir)
- return;
dw_edma_debugfs_regs_ch(®s->type.unroll.ch[i].rd, ch_dir);
@@ -273,8 +264,6 @@ static void dw_edma_debugfs_regs(void)
int nr_entries;
regs_dir = debugfs_create_dir(REGISTERS_STR, dw->debugfs);
- if (!regs_dir)
- return;
nr_entries = ARRAY_SIZE(debugfs_regs);
dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
@@ -285,6 +274,9 @@ static void dw_edma_debugfs_regs(void)
void dw_edma_v0_debugfs_on(struct dw_edma *_dw)
{
+ if (!debugfs_initialized())
+ return;
+
dw = _dw;
if (!dw)
return;
@@ -294,8 +286,6 @@ void dw_edma_v0_debugfs_on(struct dw_edma *_dw)
return;
dw->debugfs = debugfs_create_dir(dw->name, NULL);
- if (!dw->debugfs)
- return;
debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
--
2.39.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox