2022-06-10 09:53:14

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

This is a final patchset in the series created in the framework of
my Baikal-T1 PCIe/eDMA-related work:

[1: In-progress v4] PCI: dwc: Various fixes and cleanups
Link: https://lore.kernel.org/linux-pci/[email protected]/
[2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
Link: https://lore.kernel.org/linux-pci/[email protected]/
[3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
Link: https://lore.kernel.org/linux-pci/[email protected]/
[4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
Nothing prevents them from being reviewed synchronously though.

Please note originally this series was self content, but due to Frank
being a bit faster in his work submission I had to rebase my patchset onto
his one. So now this patchset turns to be dependent on the Frank' work:

Link: https://lore.kernel.org/linux-pci/[email protected]/

So please merge Frank' series first before applying this one.

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/[email protected]/
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/[email protected]/
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.

Signed-off-by: Serge Semin <[email protected]>
Cc: Alexey Malahov <[email protected]>
Cc: Pavel Parkhomenko <[email protected]>
Cc: "Krzysztof Wilczyński" <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]

Serge Semin (24):
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: Bypass dma-ranges mapping for the local setup
dmaengine: dw-edma: Skip cleanup procedure if no private data found
PCI: dwc: Add DW eDMA engine support

drivers/dma/dw-edma/dw-edma-core.c | 216 +++++-----
drivers/dma/dw-edma/dw-edma-core.h | 10 +-
drivers/dma/dw-edma/dw-edma-pcie.c | 24 +-
drivers/dma/dw-edma/dw-edma-v0-core.c | 76 ++--
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 -
.../pci/controller/dwc/pcie-designware-ep.c | 12 +-
.../pci/controller/dwc/pcie-designware-host.c | 13 +-
drivers/pci/controller/dwc/pcie-designware.c | 186 +++++++++
drivers/pci/controller/dwc/pcie-designware.h | 20 +
include/linux/dma/edma.h | 18 +-
include/linux/dmaengine.h | 2 +-
13 files changed, 589 insertions(+), 366 deletions(-)

--
2.35.1


2022-06-10 09:57:58

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 11/24] dmaengine: dw-edma: Stop checking debugfs_create_*() return value

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 <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
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(&regs->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(&regs->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.35.1

2022-06-10 10:00:41

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 16/24] dmaengine: dw-edma: Move eDMA data pointer to DebugFS node descriptor

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 <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
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 *)&regs->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 = &regs->type.legacy.ch; \
+ __ch_regs = REGS_ADDR(dw, type.legacy.ch); \
else if (_dir == EDMA_DIR_READ) \
- __ch_regs = &regs->type.unroll.ch[_ch].rd; \
+ __ch_regs = REGS_ADDR(dw, type.unroll.ch[_ch].rd); \
else \
- __ch_regs = &regs->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 *)&regs->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, &regs->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.35.1

2022-06-10 10:02:30

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 17/24] dmaengine: dw-edma: Join Write/Read channels into a single device

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 <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
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 e9cb3056b6b7..f5124e7b50cf 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -209,6 +209,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)
{
@@ -723,8 +741,7 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
pm_runtime_put(chan->dw->chip->dev);
}

-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;
@@ -732,27 +749,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);
@@ -762,52 +767,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);
@@ -819,7 +834,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;
@@ -828,6 +843,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;
@@ -841,9 +857,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)
@@ -988,13 +1002,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;

@@ -1034,15 +1043,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
pm_runtime_disable(dev);

/* 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.35.1

2022-06-10 10:02:33

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 14/24] dmaengine: dw-edma: Rename DebugFS dentry variables to 'dent'

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 <[email protected]>
Signed-off-by: Serge Semin <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>

---

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(&regs->type.unroll.ch[i].wr, ch_dir);
+ dw_edma_debugfs_regs_ch(&regs->type.unroll.ch[i].wr, ch_dent);

lim[0][i].start = &regs->type.unroll.ch[i].wr;
lim[0][i].end = &regs->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(&regs->type.unroll.ch[i].rd, ch_dir);
+ dw_edma_debugfs_regs_ch(&regs->type.unroll.ch[i].rd, ch_dent);

lim[1][i].start = &regs->type.unroll.ch[i].rd;
lim[1][i].end = &regs->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.35.1

2022-06-10 10:03:57

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 23/24] dmaengine: dw-edma: Skip cleanup procedure if no private data found

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 <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
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 4f56149dc8d8..5736a537f4c8 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -1040,6 +1040,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.35.1

2022-06-10 10:05:45

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 04/24] dmaengine: dw-edma: Fix missing src/dst address of the interleaved xfers

The interleaved DMA transfers support was added in the commit 85e7518f42c8
("dmaengine: dw-edma: Add device_prep_interleave_dma() support"). It
seems like the support was broken from the very beginning. Depending on
the selected channel either source or destination address are left
uninitialized which was obviously wrong. I don't really know how come the
original modification was working for the commit author. Anyway let's fix
it by initializing the destination address of the eDMA burst descriptors
for the DEV_TO_MEM interleaved operations and by initializing the source
address of the eDMA burst descriptors for the MEM_TO_DEV interleaved
operations.

Fixes: 85e7518f42c8 ("dmaengine: dw-edma: Add device_prep_interleave_dma() support")
Signed-off-by: Serge Semin <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
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 04efcb16d13d..f0ef87d75ea9 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -456,6 +456,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
* and destination addresses are increased
* by the same portion (data length)
*/
+ } else if (xfer->type == EDMA_XFER_INTERLEAVED) {
+ burst->dar = dst_addr;
}
} else {
burst->dar = dst_addr;
@@ -471,6 +473,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
* and destination addresses are increased
* by the same portion (data length)
*/
+ } else if (xfer->type == EDMA_XFER_INTERLEAVED) {
+ burst->sar = src_addr;
}
}

--
2.35.1

2022-06-10 10:07:29

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 06/24] dmaengine: dw-edma: Fix invalid interleaved xfers semantics

The interleaved DMA transfer support added in commit 85e7518f42c8
("dmaengine: dw-edma: Add device_prep_interleave_dma() support") seems
contradicting to what the DMA-engine defines. The next conditional
statements:
if (!xfer->xfer.il->numf)
return NULL;
if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0)
return NULL;
basically mean that numf can't be zero and frame_size must always be zero,
otherwise the transfer won't be executed. But further the transfer
execution method takes the frames size from the
dma_interleaved_template.sgl[] array for each frame. That array in
accordance with [1] is supposed to be of
dma_interleaved_template.frame_size size, which as we discovered before
the code expects to be zero. So judging by the dw_edma_device_transfer()
implementation the method implies the dma_interleaved_template.sgl[] array
being of dma_interleaved_template.numf size, which is wrong. Since the
dw_edma_device_transfer() method doesn't permit
dma_interleaved_template.frame_size being non-zero then actual multi-chunk
interleaved transfer turns to be unsupported even though the code implies
having it supported.

Let's fix that by adding a fully functioning support of the interleaved
DMA transfers. First of all dma_interleaved_template.frame_size is
supposed to be greater or equal to one thus having at least simple linear
chunked frames. Secondly we can create a walk-through all over the chunks
and frames just by initializing the number of the eDMA burst transactios
as a multiple of dma_interleaved_template.numf and
dma_interleaved_template.frame_size and getting the frame_size-modulo of
the iteration step as an index of the dma_interleaved_template.sgl[]
array. The rest of the dw_edma_device_transfer() method code can be left
unchanged.

[1] include/linux/dmaengine.h: doc struct dma_interleaved_template

Fixes: 85e7518f42c8 ("dmaengine: dw-edma: Add device_prep_interleave_dma() support")
Signed-off-by: Serge Semin <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
drivers/dma/dw-edma/dw-edma-core.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 225eab58acb7..ef49deb5a7f3 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -333,6 +333,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
struct dw_edma_chunk *chunk;
struct dw_edma_burst *burst;
struct dw_edma_desc *desc;
+ size_t fsz = 0;
u32 cnt = 0;
int i;

@@ -382,9 +383,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
if (xfer->xfer.sg.len < 1)
return NULL;
} else if (xfer->type == EDMA_XFER_INTERLEAVED) {
- if (!xfer->xfer.il->numf)
- return NULL;
- if (xfer->xfer.il->numf > 0 && xfer->xfer.il->frame_size > 0)
+ if (!xfer->xfer.il->numf || xfer->xfer.il->frame_size < 1)
return NULL;
if (!xfer->xfer.il->src_inc || !xfer->xfer.il->dst_inc)
return NULL;
@@ -414,10 +413,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
cnt = xfer->xfer.sg.len;
sg = xfer->xfer.sg.sgl;
} else if (xfer->type == EDMA_XFER_INTERLEAVED) {
- if (xfer->xfer.il->numf > 0)
- cnt = xfer->xfer.il->numf;
- else
- cnt = xfer->xfer.il->frame_size;
+ cnt = xfer->xfer.il->numf * xfer->xfer.il->frame_size;
+ fsz = xfer->xfer.il->frame_size;
}

for (i = 0; i < cnt; i++) {
@@ -439,7 +436,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
else if (xfer->type == EDMA_XFER_SCATTER_GATHER)
burst->sz = sg_dma_len(sg);
else if (xfer->type == EDMA_XFER_INTERLEAVED)
- burst->sz = xfer->xfer.il->sgl[i].size;
+ burst->sz = xfer->xfer.il->sgl[i % fsz].size;

chunk->ll_region.sz += burst->sz;
desc->alloc_sz += burst->sz;
@@ -482,10 +479,9 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)

if (xfer->type == EDMA_XFER_SCATTER_GATHER) {
sg = sg_next(sg);
- } else if (xfer->type == EDMA_XFER_INTERLEAVED &&
- xfer->xfer.il->frame_size > 0) {
+ } else if (xfer->type == EDMA_XFER_INTERLEAVED) {
struct dma_interleaved_template *il = xfer->xfer.il;
- struct data_chunk *dc = &il->sgl[i];
+ struct data_chunk *dc = &il->sgl[i % fsz];

src_addr += burst->sz;
if (il->src_sgl)
--
2.35.1

2022-06-10 10:07:43

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 08/24] dmaengine: dw-edma: Add PCIe bus address getter to the remote EP glue-driver

In general the Synopsys PCIe EndPoint IP prototype kit can be attached to
a PCIe bus with any PCIe Host controller including to the one with
distinctive from CPU address space. Due to that we need to make sure that
the source and destination addresses of the DMA-slave devices are properly
converted to the PCIe bus address space, otherwise the DMA transaction
will not only work as expected, but may cause the memory corruption with
subsequent system crash. Let's do that by introducing a new
dw_edma_pcie_address() method defined in the dw-edma-pcie.c, which will
perform the denoted translation by using the pcibios_resource_to_bus()
method.

Fixes: 41aaff2a2ac0 ("dmaengine: Add Synopsys eDMA IP PCIe glue-logic")
Signed-off-by: Serge Semin <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>

---

Note this patch depends on the patch "dmaengine: dw-edma: Add CPU to PCIe
bus address translation" from this series.
---
drivers/dma/dw-edma/dw-edma-pcie.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)

diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 04c95cba1244..f530bacfd716 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -95,8 +95,23 @@ static int dw_edma_pcie_irq_vector(struct device *dev, unsigned int nr)
return pci_irq_vector(to_pci_dev(dev), nr);
}

+static u64 dw_edma_pcie_address(struct device *dev, phys_addr_t cpu_addr)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ struct pci_bus_region region;
+ struct resource res = {
+ .flags = IORESOURCE_MEM,
+ .start = cpu_addr,
+ .end = cpu_addr,
+ };
+
+ pcibios_resource_to_bus(pdev->bus, &region, &res);
+ return region.start;
+}
+
static const struct dw_edma_core_ops dw_edma_pcie_core_ops = {
.irq_vector = dw_edma_pcie_irq_vector,
+ .pci_address = dw_edma_pcie_address,
};

static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev,
--
2.35.1

2022-06-10 10:08:42

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 01/24] dmaengine: Fix dma_slave_config.dst_addr description

Most likely due to a copy-paste mistake the dst_addr member of the
dma_slave_config structure has been marked as ignored if the !source!
address belong to the memory. That is relevant to the src_addr field of
the structure while the dst_addr field as containing a destination device
address is supposed to be ignored if the destination is the CPU memory.
Let's fix the field description accordingly.

Signed-off-by: Serge Semin <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
include/linux/dmaengine.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 842d4f7ca752..f204ea16ac1c 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -395,7 +395,7 @@ enum dma_slave_buswidth {
* should be read (RX), if the source is memory this argument is
* ignored.
* @dst_addr: this is the physical address where DMA slave data
- * should be written (TX), if the source is memory this argument
+ * should be written (TX), if the destination is memory this argument
* is ignored.
* @src_addr_width: this is the width in bytes of the source (RX)
* register where DMA data shall be read. If the source
--
2.35.1

2022-06-10 10:20:51

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 12/24] dmaengine: dw-edma: Add dw_edma prefix to the DebugFS nodes descriptor

The rest of the locally defined and used methods and structures have
dw_edma prefix in their names. It's right in accordance with the kernel
coding style to follow the locally defined rule of naming. Let's add that
prefix to the debugfs_entries structure too especially seeing it's name
may be confusing as if that structure belongs to the global DebugFS space.

Signed-off-by: Serge Semin <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 6e7f3ef60ca7..2121ffc33cf3 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -46,7 +46,7 @@ static struct {
void __iomem *end;
} lim[2][EDMA_V0_MAX_NR_CH];

-struct debugfs_entries {
+struct dw_edma_debugfs_entry {
const char *name;
void __iomem *reg;
};
@@ -94,7 +94,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 debugfs_entries entries[],
+static void dw_edma_debugfs_create_x32(const struct dw_edma_debugfs_entry entries[],
int nr_entries, struct dentry *dir)
{
int i;
@@ -108,8 +108,7 @@ static void dw_edma_debugfs_create_x32(const struct debugfs_entries entries[],
static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
struct dentry *dir)
{
- int nr_entries;
- const struct debugfs_entries debugfs_regs[] = {
+ const struct dw_edma_debugfs_entry debugfs_regs[] = {
REGISTER(ch_control1),
REGISTER(ch_control2),
REGISTER(transfer_size),
@@ -120,6 +119,7 @@ static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,
REGISTER(llp.lsb),
REGISTER(llp.msb),
};
+ int nr_entries;

nr_entries = ARRAY_SIZE(debugfs_regs);
dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, dir);
@@ -127,7 +127,7 @@ static void dw_edma_debugfs_regs_ch(struct dw_edma_v0_ch_regs __iomem *regs,

static void dw_edma_debugfs_regs_wr(struct dentry *dir)
{
- const struct debugfs_entries debugfs_regs[] = {
+ const struct dw_edma_debugfs_entry debugfs_regs[] = {
/* eDMA global registers */
WR_REGISTER(engine_en),
WR_REGISTER(doorbell),
@@ -148,7 +148,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
WR_REGISTER(ch67_imwr_data),
WR_REGISTER(linked_list_err_en),
};
- const struct debugfs_entries debugfs_unroll_regs[] = {
+ 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),
@@ -191,7 +191,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)

static void dw_edma_debugfs_regs_rd(struct dentry *dir)
{
- const struct debugfs_entries debugfs_regs[] = {
+ const struct dw_edma_debugfs_entry debugfs_regs[] = {
/* eDMA global registers */
RD_REGISTER(engine_en),
RD_REGISTER(doorbell),
@@ -213,7 +213,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
RD_REGISTER(ch45_imwr_data),
RD_REGISTER(ch67_imwr_data),
};
- const struct debugfs_entries debugfs_unroll_regs[] = {
+ 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),
@@ -256,7 +256,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)

static void dw_edma_debugfs_regs(void)
{
- const struct debugfs_entries debugfs_regs[] = {
+ const struct dw_edma_debugfs_entry debugfs_regs[] = {
REGISTER(ctrl_data_arb_prior),
REGISTER(ctrl),
};
--
2.35.1

2022-06-10 10:31:33

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 24/24] PCI: dwc: Add DW eDMA engine support

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 it's 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
log in the similar way as it's done for the iATU settings.

Signed-off-by: Serge Semin <[email protected]>

---

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.
---
.../pci/controller/dwc/pcie-designware-ep.c | 12 +-
.../pci/controller/dwc/pcie-designware-host.c | 13 +-
drivers/pci/controller/dwc/pcie-designware.c | 186 ++++++++++++++++++
drivers/pci/controller/dwc/pcie-designware.h | 20 ++
4 files changed, 228 insertions(+), 3 deletions(-)

diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index dd7ec1eb7520..2a6f8382bc1b 100644
--- a/drivers/pci/controller/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -604,8 +604,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);

@@ -763,6 +766,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)
@@ -771,10 +778,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 c941ea95badf..d46d303084ec 100644
--- a/drivers/pci/controller/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -404,14 +404,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 */
@@ -428,6 +432,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);
@@ -449,6 +456,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 fd43514a00bb..e04128a22bbe 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_res(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);
@@ -785,6 +798,179 @@ 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;
+
+ 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 = dmam_alloc_coherent(pci->dev, ll->sz,
+ &paddr, GFP_KERNEL);
+ if (!ll->vaddr)
+ 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 = dmam_alloc_coherent(pci->dev, ll->sz,
+ &paddr, GFP_KERNEL);
+ if (!ll->vaddr)
+ 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 779fbf147d9b..442bba41cd8a 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>
@@ -160,6 +161,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. Afterwords 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)
@@ -176,6 +189,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
@@ -187,6 +201,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;
@@ -331,6 +348,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];
@@ -370,6 +388,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.35.1

2022-06-10 10:35:29

by Serge Semin

[permalink] [raw]
Subject: [PATCH v3 20/24] dmaengine: dw-edma: Drop DT-region allocation

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 <[email protected]>
Reviewed-by: Manivannan Sadhasivam <[email protected]>
Tested-by: Manivannan Sadhasivam <[email protected]>
---
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 7ba3b60c960c..98a94a66fb82 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -744,7 +744,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;
@@ -760,12 +759,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) {
@@ -813,17 +806,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.35.1

2022-06-10 10:44:19

by Serge Semin

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On Fri, Jun 10, 2022 at 12:14:35PM +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: In-progress v4] PCI: dwc: Various fixes and cleanups
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> Nothing prevents them from being reviewed synchronously though.
>
> Please note originally this series was self content, but due to Frank
> being a bit faster in his work submission I had to rebase my patchset onto
> his one. So now this patchset turns to be dependent on the Frank' work:
>
> Link: https://lore.kernel.org/linux-pci/[email protected]/
>
> So please merge Frank' series first before applying this one.
>
> 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/[email protected]/
> 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/[email protected]/
> 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.

@Mani, several patches have been changed. Could you have a look at the
series one more time?

-Sergey

> - Rebase onto the kernel v5.18.
>
> Signed-off-by: Serge Semin <[email protected]>
> Cc: Alexey Malahov <[email protected]>
> Cc: Pavel Parkhomenko <[email protected]>
> Cc: "Krzysztof Wilczyński" <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Cc: [email protected]
>
> Serge Semin (24):
> 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: Bypass dma-ranges mapping for the local setup
> dmaengine: dw-edma: Skip cleanup procedure if no private data found
> PCI: dwc: Add DW eDMA engine support
>
> drivers/dma/dw-edma/dw-edma-core.c | 216 +++++-----
> drivers/dma/dw-edma/dw-edma-core.h | 10 +-
> drivers/dma/dw-edma/dw-edma-pcie.c | 24 +-
> drivers/dma/dw-edma/dw-edma-v0-core.c | 76 ++--
> 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 -
> .../pci/controller/dwc/pcie-designware-ep.c | 12 +-
> .../pci/controller/dwc/pcie-designware-host.c | 13 +-
> drivers/pci/controller/dwc/pcie-designware.c | 186 +++++++++
> drivers/pci/controller/dwc/pcie-designware.h | 20 +
> include/linux/dma/edma.h | 18 +-
> include/linux/dmaengine.h | 2 +-
> 13 files changed, 589 insertions(+), 366 deletions(-)
>
> --
> 2.35.1
>

2022-07-09 08:54:28

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 24/24] PCI: dwc: Add DW eDMA engine support

On Fri, Jun 10, 2022 at 12:14:59PM +0300, Serge Semin wrote:
> 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 it's 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
> log in the similar way as it's done for the iATU settings.
>
> Signed-off-by: Serge Semin <[email protected]>

Eventhough I didn't test this patch, it looks good to me as my previous
comments were addressed.

Reviewed-by: Manivannan Sadhasivam <[email protected]>

Thanks,
Mani

>
> ---
>
> 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.
> ---
> .../pci/controller/dwc/pcie-designware-ep.c | 12 +-
> .../pci/controller/dwc/pcie-designware-host.c | 13 +-
> drivers/pci/controller/dwc/pcie-designware.c | 186 ++++++++++++++++++
> drivers/pci/controller/dwc/pcie-designware.h | 20 ++
> 4 files changed, 228 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
> index dd7ec1eb7520..2a6f8382bc1b 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-ep.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
> @@ -604,8 +604,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);
>
> @@ -763,6 +766,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)
> @@ -771,10 +778,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 c941ea95badf..d46d303084ec 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -404,14 +404,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 */
> @@ -428,6 +432,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);
> @@ -449,6 +456,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 fd43514a00bb..e04128a22bbe 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_res(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);
> @@ -785,6 +798,179 @@ 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;
> +
> + 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 = dmam_alloc_coherent(pci->dev, ll->sz,
> + &paddr, GFP_KERNEL);
> + if (!ll->vaddr)
> + 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 = dmam_alloc_coherent(pci->dev, ll->sz,
> + &paddr, GFP_KERNEL);
> + if (!ll->vaddr)
> + 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 779fbf147d9b..442bba41cd8a 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>
> @@ -160,6 +161,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. Afterwords 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)
> @@ -176,6 +189,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
> @@ -187,6 +201,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;
> @@ -331,6 +348,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];
> @@ -370,6 +388,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.35.1
>

--
மணிவண்ணன் சதாசிவம்

2022-07-11 14:54:42

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On Fri, Jun 10, 2022 at 12:21:33PM +0300, Serge Semin wrote:
> On Fri, Jun 10, 2022 at 12:14:35PM +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: In-progress v4] PCI: dwc: Various fixes and cleanups
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> > Nothing prevents them from being reviewed synchronously though.
> >
> > Please note originally this series was self content, but due to Frank
> > being a bit faster in his work submission I had to rebase my patchset onto
> > his one. So now this patchset turns to be dependent on the Frank' work:
> >
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> >
> > So please merge Frank' series first before applying this one.
> >
> > 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/[email protected]/
> > 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/[email protected]/
> > 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.
>
> @Mani, several patches have been changed. Could you have a look at the
> series one more time?
>

Reviewed all patches in this series. I believe this will still work on my
hardware once I test it. But even if it doesn't work, we can fix it in
5.20-rc's as it supposed to be. So definitely not a show stopper.

Vinod: Could you please merge this one for 5.20?

Thanks,
Mani

> -Sergey
>
> > - Rebase onto the kernel v5.18.
> >
> > Signed-off-by: Serge Semin <[email protected]>
> > Cc: Alexey Malahov <[email protected]>
> > Cc: Pavel Parkhomenko <[email protected]>
> > Cc: "Krzysztof Wilczyński" <[email protected]>
> > Cc: [email protected]
> > Cc: [email protected]
> > Cc: [email protected]
> >
> > Serge Semin (24):
> > 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: Bypass dma-ranges mapping for the local setup
> > dmaengine: dw-edma: Skip cleanup procedure if no private data found
> > PCI: dwc: Add DW eDMA engine support
> >
> > drivers/dma/dw-edma/dw-edma-core.c | 216 +++++-----
> > drivers/dma/dw-edma/dw-edma-core.h | 10 +-
> > drivers/dma/dw-edma/dw-edma-pcie.c | 24 +-
> > drivers/dma/dw-edma/dw-edma-v0-core.c | 76 ++--
> > 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 -
> > .../pci/controller/dwc/pcie-designware-ep.c | 12 +-
> > .../pci/controller/dwc/pcie-designware-host.c | 13 +-
> > drivers/pci/controller/dwc/pcie-designware.c | 186 +++++++++
> > drivers/pci/controller/dwc/pcie-designware.h | 20 +
> > include/linux/dma/edma.h | 18 +-
> > include/linux/dmaengine.h | 2 +-
> > 13 files changed, 589 insertions(+), 366 deletions(-)
> >
> > --
> > 2.35.1
> >

--
மணிவண்ணன் சதாசிவம்

2022-07-11 15:27:48

by Manivannan Sadhasivam

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On Mon, Jul 11, 2022 at 08:15:41PM +0530, Manivannan Sadhasivam wrote:
> On Fri, Jun 10, 2022 at 12:21:33PM +0300, Serge Semin wrote:
> > On Fri, Jun 10, 2022 at 12:14:35PM +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: In-progress v4] PCI: dwc: Various fixes and cleanups
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> > > Nothing prevents them from being reviewed synchronously though.
> > >
> > > Please note originally this series was self content, but due to Frank
> > > being a bit faster in his work submission I had to rebase my patchset onto
> > > his one. So now this patchset turns to be dependent on the Frank' work:
> > >
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > >
> > > So please merge Frank' series first before applying this one.
> > >
> > > 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/[email protected]/
> > > 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/[email protected]/
> > > 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.
> >
> > @Mani, several patches have been changed. Could you have a look at the
> > series one more time?
> >
>
> Reviewed all patches in this series. I believe this will still work on my
> hardware once I test it. But even if it doesn't work, we can fix it in
> 5.20-rc's as it supposed to be. So definitely not a show stopper.
>
> Vinod: Could you please merge this one for 5.20?
>

Hmm, maybe this can go through pci tree as Bjorn merged earlier edma series as
well. In that case Vinod's ack is sufficient.

But I'll leave it up to Bjorn and Vinod.

Thanks,
Mani

> Thanks,
> Mani
>
> > -Sergey
> >
> > > - Rebase onto the kernel v5.18.
> > >
> > > Signed-off-by: Serge Semin <[email protected]>
> > > Cc: Alexey Malahov <[email protected]>
> > > Cc: Pavel Parkhomenko <[email protected]>
> > > Cc: "Krzysztof Wilczyński" <[email protected]>
> > > Cc: [email protected]
> > > Cc: [email protected]
> > > Cc: [email protected]
> > >
> > > Serge Semin (24):
> > > 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: Bypass dma-ranges mapping for the local setup
> > > dmaengine: dw-edma: Skip cleanup procedure if no private data found
> > > PCI: dwc: Add DW eDMA engine support
> > >
> > > drivers/dma/dw-edma/dw-edma-core.c | 216 +++++-----
> > > drivers/dma/dw-edma/dw-edma-core.h | 10 +-
> > > drivers/dma/dw-edma/dw-edma-pcie.c | 24 +-
> > > drivers/dma/dw-edma/dw-edma-v0-core.c | 76 ++--
> > > 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 -
> > > .../pci/controller/dwc/pcie-designware-ep.c | 12 +-
> > > .../pci/controller/dwc/pcie-designware-host.c | 13 +-
> > > drivers/pci/controller/dwc/pcie-designware.c | 186 +++++++++
> > > drivers/pci/controller/dwc/pcie-designware.h | 20 +
> > > include/linux/dma/edma.h | 18 +-
> > > include/linux/dmaengine.h | 2 +-
> > > 13 files changed, 589 insertions(+), 366 deletions(-)
> > >
> > > --
> > > 2.35.1
> > >
>
> --
> மணிவண்ணன் சதாசிவம்

--
மணிவண்ணன் சதாசிவம்

2022-07-11 16:22:40

by Serge Semin

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On Mon, Jul 11, 2022 at 08:19:03PM +0530, Manivannan Sadhasivam wrote:
> On Mon, Jul 11, 2022 at 08:15:41PM +0530, Manivannan Sadhasivam wrote:
> > On Fri, Jun 10, 2022 at 12:21:33PM +0300, Serge Semin wrote:
> > > On Fri, Jun 10, 2022 at 12:14:35PM +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: In-progress v4] PCI: dwc: Various fixes and cleanups
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > > [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > > [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > > [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> > > > Nothing prevents them from being reviewed synchronously though.
> > > >
> > > > Please note originally this series was self content, but due to Frank
> > > > being a bit faster in his work submission I had to rebase my patchset onto
> > > > his one. So now this patchset turns to be dependent on the Frank' work:
> > > >
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > >
> > > > So please merge Frank' series first before applying this one.
> > > >
> > > > 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/[email protected]/
> > > > 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/[email protected]/
> > > > 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.
> > >
> > > @Mani, several patches have been changed. Could you have a look at the
> > > series one more time?
> > >
> >

> > Reviewed all patches in this series. I believe this will still work on my
> > hardware once I test it. But even if it doesn't work, we can fix it in
> > 5.20-rc's as it supposed to be. So definitely not a show stopper.

Hi Mani. Thanks for review. I'll make sure your tag will persist in
the patch logs.

> >

> > Vinod: Could you please merge this one for 5.20?
> >
>
> Hmm, maybe this can go through pci tree as Bjorn merged earlier edma series as
> well. In that case Vinod's ack is sufficient.

As I said in the cover letter this series depends on the three more
patchsets:
[1: Done v4] PCI: dwc: Various fixes and cleanups
Link: https://lore.kernel.org/linux-pci/[email protected]/
Link: https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/log/?h=pci/ctrl/dwc-fixes
[2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
Link: https://lore.kernel.org/linux-pci/[email protected]/
[3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
Link: https://lore.kernel.org/linux-pci/[email protected]/

So at the very least they must be merged in first before this series
gets into the kernel. #1 is already in Bjorn' repo. #2 is still on
review, but no comments have been sent in v3. So it can be merged in
as is. I desperately need Rob' feedback on my questions in order to
re-submit #3. But it's not that easy to achieve at this moment first
due to him being on vacation then him being very busy with other
patches review.( So until series #3' review is done, this patchset
will have to stay in limbo. Anyway I hope we'll settle all the issues
with Rob soon.

-Sergey

>
> But I'll leave it up to Bjorn and Vinod.
>
> Thanks,
> Mani
>
> > Thanks,
> > Mani
> >
> > > -Sergey
> > >
> > > > - Rebase onto the kernel v5.18.
> > > >
> > > > Signed-off-by: Serge Semin <[email protected]>
> > > > Cc: Alexey Malahov <[email protected]>
> > > > Cc: Pavel Parkhomenko <[email protected]>
> > > > Cc: "Krzysztof Wilczyński" <[email protected]>
> > > > Cc: [email protected]
> > > > Cc: [email protected]
> > > > Cc: [email protected]
> > > >
> > > > Serge Semin (24):
> > > > 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: Bypass dma-ranges mapping for the local setup
> > > > dmaengine: dw-edma: Skip cleanup procedure if no private data found
> > > > PCI: dwc: Add DW eDMA engine support
> > > >
> > > > drivers/dma/dw-edma/dw-edma-core.c | 216 +++++-----
> > > > drivers/dma/dw-edma/dw-edma-core.h | 10 +-
> > > > drivers/dma/dw-edma/dw-edma-pcie.c | 24 +-
> > > > drivers/dma/dw-edma/dw-edma-v0-core.c | 76 ++--
> > > > 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 -
> > > > .../pci/controller/dwc/pcie-designware-ep.c | 12 +-
> > > > .../pci/controller/dwc/pcie-designware-host.c | 13 +-
> > > > drivers/pci/controller/dwc/pcie-designware.c | 186 +++++++++
> > > > drivers/pci/controller/dwc/pcie-designware.h | 20 +
> > > > include/linux/dma/edma.h | 18 +-
> > > > include/linux/dmaengine.h | 2 +-
> > > > 13 files changed, 589 insertions(+), 366 deletions(-)
> > > >
> > > > --
> > > > 2.35.1
> > > >
> >
> > --
> > மணிவண்ணன் சதாசிவம்
>
> --
> மணிவண்ணன் சதாசிவம்

2022-07-21 12:55:35

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On 10-06-22, 12:14, Serge Semin wrote:
> This is a final patchset in the series created in the framework of
> my Baikal-T1 PCIe/eDMA-related work:
>
> [1: In-progress v4] PCI: dwc: Various fixes and cleanups
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> Nothing prevents them from being reviewed synchronously though.
>
> Please note originally this series was self content, but due to Frank
> being a bit faster in his work submission I had to rebase my patchset onto
> his one. So now this patchset turns to be dependent on the Frank' work:
>
> Link: https://lore.kernel.org/linux-pci/[email protected]/
>
> So please merge Frank' series first before applying this one.
>
> 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.

Acked-By: Vinod Koul <[email protected]>

--
~Vinod

2022-07-28 12:11:20

by Serge Semin

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On Thu, Jul 21, 2022 at 05:46:10PM +0530, Vinod Koul wrote:
> On 10-06-22, 12:14, Serge Semin wrote:
> > This is a final patchset in the series created in the framework of
> > my Baikal-T1 PCIe/eDMA-related work:
> >
> > [1: In-progress v4] PCI: dwc: Various fixes and cleanups
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> > Nothing prevents them from being reviewed synchronously though.
> >
> > Please note originally this series was self content, but due to Frank
> > being a bit faster in his work submission I had to rebase my patchset onto
> > his one. So now this patchset turns to be dependent on the Frank' work:
> >
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> >
> > So please merge Frank' series first before applying this one.
> >
> > 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.
>

> Acked-By: Vinod Koul <[email protected]>

Thanks, Vinod! The series will be merged in after the patchset
[PATCH vX 00/17] PCI: dwc: Add generic resources and Baikal-T1 support
Link: https://lore.kernel.org/linux-pci/[email protected]/
is done with Rob' review (I failed to reach him with a few issues
lately). I'll add your ab-tag to this one on the next patchset re-spin
(rebase will be likely needed).

-Sergey

>
> --
> ~Vinod

2022-07-28 13:25:27

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On 28-07-22, 14:33, Serge Semin wrote:
> On Thu, Jul 21, 2022 at 05:46:10PM +0530, Vinod Koul wrote:
> > On 10-06-22, 12:14, Serge Semin wrote:
> > > This is a final patchset in the series created in the framework of
> > > my Baikal-T1 PCIe/eDMA-related work:
> > >
> > > [1: In-progress v4] PCI: dwc: Various fixes and cleanups
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> > > Nothing prevents them from being reviewed synchronously though.
> > >
> > > Please note originally this series was self content, but due to Frank
> > > being a bit faster in his work submission I had to rebase my patchset onto
> > > his one. So now this patchset turns to be dependent on the Frank' work:
> > >
> > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > >
> > > So please merge Frank' series first before applying this one.
> > >
> > > 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.
> >
>
> > Acked-By: Vinod Koul <[email protected]>
>
> Thanks, Vinod! The series will be merged in after the patchset
> [PATCH vX 00/17] PCI: dwc: Add generic resources and Baikal-T1 support
> Link: https://lore.kernel.org/linux-pci/[email protected]/
> is done with Rob' review (I failed to reach him with a few issues
> lately). I'll add your ab-tag to this one on the next patchset re-spin
> (rebase will be likely needed).

You can cc Krzysztof (cced him0, maybe he can help with review of DT
parts

thanks
--
~Vinod

2022-07-28 14:30:30

by Serge Semin

[permalink] [raw]
Subject: Re: [PATCH v3 00/24] dmaengine: dw-edma: Add RP/EP local DMA controllers support

On Thu, Jul 28, 2022 at 06:18:30PM +0530, Vinod Koul wrote:
> On 28-07-22, 14:33, Serge Semin wrote:
> > On Thu, Jul 21, 2022 at 05:46:10PM +0530, Vinod Koul wrote:
> > > On 10-06-22, 12:14, Serge Semin wrote:
> > > > This is a final patchset in the series created in the framework of
> > > > my Baikal-T1 PCIe/eDMA-related work:
> > > >
> > > > [1: In-progress v4] PCI: dwc: Various fixes and cleanups
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > > [2: In-progress v3] PCI: dwc: Add hw version and dma-ranges support
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > > [3: In-progress v3] PCI: dwc: Add generic resources and Baikal-T1 support
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > > [4: In-progress v3] dmaengine: dw-edma: Add RP/EP local DMA 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.
> > > > Nothing prevents them from being reviewed synchronously though.
> > > >
> > > > Please note originally this series was self content, but due to Frank
> > > > being a bit faster in his work submission I had to rebase my patchset onto
> > > > his one. So now this patchset turns to be dependent on the Frank' work:
> > > >
> > > > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > > >
> > > > So please merge Frank' series first before applying this one.
> > > >
> > > > 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.
> > >
> >
> > > Acked-By: Vinod Koul <[email protected]>
> >
> > Thanks, Vinod! The series will be merged in after the patchset
> > [PATCH vX 00/17] PCI: dwc: Add generic resources and Baikal-T1 support
> > Link: https://lore.kernel.org/linux-pci/[email protected]/
> > is done with Rob' review (I failed to reach him with a few issues
> > lately). I'll add your ab-tag to this one on the next patchset re-spin
> > (rebase will be likely needed).
>

> You can cc Krzysztof (cced him0, maybe he can help with review of DT
> parts

Thanks for the suggestion. I'll Cc him in the next series re-spin.

-Sergey

>
> thanks
> --
> ~Vinod