From: Sanjay R Mehta <[email protected]>
This patch series add support for AMD PTDMA controller which
performs high bandwidth memory-to-memory and IO copy operation,
performs DMA transfer through queue based descriptor management.
AMD Processor has multiple ptdma device instances with each controller
having single queue. The driver also adds support for for multiple PTDMA
instances, each device will get an unique identifier and uniquely
named resources.
v10:
- modified ISR to return IR_HANDLED only in non-error condition.
- removed unnecessary prints, variables and made some cosmetic changes.
- removed pt_ordinal atomic variable and instead using dev_name()
for device name.
- removed the cmdlist dependency and instead using vc.desc_issued list.
- freeing the desc and list which was missing in the pt_terminate_all()
funtion.
- Added comment for marking PTDMA as DMA_PRIVATE.
- removed unused pt_debugfs_lock from debufs code.
- keeping same file permision for all the debug directoris.
v9:
- Modified the help message in Kconfig as per Randy's comment.
- reverted the split of code for "pt_handle_active_desc" as there
was driver hang being observerd after few iterations.
v8:
- splitted the code into different functions, one to find active desc
and second to complete and invoke callback.
- used FIELD_PREP & FIELD_GET instead of union struct bitfields.
- modified all style fixes as per the comments.
v7:
- Fixed module warnings reported ( by kernel test robot <[email protected]> ).
v6:
- Removed debug artifacts and made the suggested cosmetic changes.
- implemented and used to_pt_chan and to_pt_desc inline functions.
- Removed src and dst address check as framework does this.
- Removed devm_kcalloc() usage and used devm_kzalloc() api.
- Using framework debugfs directory to store dma info.
v5:
- modified code to submit next tranction in ISR itself and removed the tasklet.
- implemented .device_synchronize API.
- converted debugfs code by using DEFINE_SHOW_ATTRIBUTE()
- using dbg_dev_root for debugfs root directory.
- removed dma_status from pt_dma_chan
- removed module parameter cmd_queue_lenght.
- removed global device list for multiple devics.
- removed code related to dynamic adding/deleting to device list
- removed pt_add_device and pt_del_device functions
v4:
- modified DMA channel and descriptor management using virt-dma layer
instead of list based management.
- return only status of the cookie from pt_tx_status
- copyright year changed from 2019 to 2020
- removed dummy code for suspend & resume
- used bitmask and genmask
v3:
- Fixed the sparse warnings.
v2:
- Added controller description in cover letter
- Removed "default m" from Kconfig
- Replaced low_address() and high_address() functions with kernel
API's lower_32_bits & upper_32_bits().
- Removed the BH handler function pt_core_irq_bh() and instead
handling transaction in irq handler itself.
- Moved presetting of command queue registers into new function
"init_cmdq_regs()"
- Removed the kernel thread dependency to submit transaction.
- Increased the hardware command queue size to 32 and adding it
as a module parameter.
- Removed backlog command queue handling mechanism.
- Removed software command queue handling and instead submitting
transaction command directly to
hardware command queue.
- Added tasklet structure variable in "struct pt_device".
This is used to invoke pt_do_cmd_complete() upon receiving interrupt
for command completion.
- pt_core_perform_passthru() function parameters are modified and it is
now used to submit command directly to hardware from dmaengine framew
- Removed below structures, enums, macros and functions, as these value
constants. Making command submission simple,
- Removed "union pt_function" and several macros like PT_VERSION,
PT_BYTESWAP, PT_CMD_* etc..
- enum pt_passthru_bitwise, enum pt_passthru_byteswap, enum pt_memty
struct pt_dma_info, struct pt_data, struct pt_mem, struct pt_passt
struct pt_op,
Links of the review comments for v10:
1. https://lkml.org/lkml/2021/6/8/976
2. https://lkml.org/lkml/2021/6/16/7
3. https://lkml.org/lkml/2021/6/16/65
4. https://lkml.org/lkml/2021/6/16/192
5. https://lkml.org/lkml/2021/6/16/273
6. https://lkml.org/lkml/2021/6/8/1698
7. https://lkml.org/lkml/2021/6/16/8
8. https://lkml.org/lkml/2021/6/9/808
Links of the review comments for v7:
1. https://lkml.org/lkml/2020/11/18/351
2. https://lkml.org/lkml/2020/11/18/384
Links of the review comments for v5:
1. https://lkml.org/lkml/2020/7/3/154
2. https://lkml.org/lkml/2020/8/25/431
3. https://lkml.org/lkml/2020/7/3/177
4. https://lkml.org/lkml/2020/7/3/186
Links of the review comments for v5:
1. https://lkml.org/lkml/2020/5/4/42
2. https://lkml.org/lkml/2020/5/4/45
3. https://lkml.org/lkml/2020/5/4/38
4. https://lkml.org/lkml/2020/5/26/70
Links of the review comments for v4:
1. https://lkml.org/lkml/2020/1/24/12
2. https://lkml.org/lkml/2020/1/24/17
Links of the review comments for v2:
1https://lkml.org/lkml/2019/12/27/630
2. https://lkml.org/lkml/2020/1/3/23
3. https://lkml.org/lkml/2020/1/3/314
4. https://lkml.org/lkml/2020/1/10/100
Links of the review comments for v1:
1. https://lkml.org/lkml/2019/9/24/490
2. https://lkml.org/lkml/2019/9/24/399
3. https://lkml.org/lkml/2019/9/24/862
4. https://lkml.org/lkml/2019/9/24/122
Sanjay R Mehta (3):
dmaengine: ptdma: Initial driver for the AMD PTDMA
dmaengine: ptdma: register PTDMA controller as a DMA resource
dmaengine: ptdma: Add debugfs entries for PTDMA
MAINTAINERS | 6 +
drivers/dma/Kconfig | 2 +
drivers/dma/Makefile | 1 +
drivers/dma/ptdma/Kconfig | 13 ++
drivers/dma/ptdma/Makefile | 10 +
drivers/dma/ptdma/ptdma-debugfs.c | 110 ++++++++++
drivers/dma/ptdma/ptdma-dev.c | 327 ++++++++++++++++++++++++++++++
drivers/dma/ptdma/ptdma-dmaengine.c | 389 ++++++++++++++++++++++++++++++++++++
drivers/dma/ptdma/ptdma-pci.c | 245 +++++++++++++++++++++++
drivers/dma/ptdma/ptdma.h | 334 +++++++++++++++++++++++++++++++
10 files changed, 1437 insertions(+)
create mode 100644 drivers/dma/ptdma/Kconfig
create mode 100644 drivers/dma/ptdma/Makefile
create mode 100644 drivers/dma/ptdma/ptdma-debugfs.c
create mode 100644 drivers/dma/ptdma/ptdma-dev.c
create mode 100644 drivers/dma/ptdma/ptdma-dmaengine.c
create mode 100644 drivers/dma/ptdma/ptdma-pci.c
create mode 100644 drivers/dma/ptdma/ptdma.h
--
2.7.4
From: Sanjay R Mehta <[email protected]>
Add support for AMD PTDMA controller. It performs high-bandwidth
memory to memory and IO copy operation. Device commands are managed
via a circular queue of 'descriptors', each of which specifies source
and destination addresses for copying a single buffer of data.
Signed-off-by: Sanjay R Mehta <[email protected]>
---
MAINTAINERS | 6 +
drivers/dma/Kconfig | 2 +
drivers/dma/Makefile | 1 +
drivers/dma/ptdma/Kconfig | 11 ++
drivers/dma/ptdma/Makefile | 10 ++
drivers/dma/ptdma/ptdma-dev.c | 290 ++++++++++++++++++++++++++++++++++++++++
drivers/dma/ptdma/ptdma-pci.c | 245 ++++++++++++++++++++++++++++++++++
drivers/dma/ptdma/ptdma.h | 302 ++++++++++++++++++++++++++++++++++++++++++
8 files changed, 867 insertions(+)
create mode 100644 drivers/dma/ptdma/Kconfig
create mode 100644 drivers/dma/ptdma/Makefile
create mode 100644 drivers/dma/ptdma/ptdma-dev.c
create mode 100644 drivers/dma/ptdma/ptdma-pci.c
create mode 100644 drivers/dma/ptdma/ptdma.h
diff --git a/MAINTAINERS b/MAINTAINERS
index bd7aff0c..2c897fa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -957,6 +957,12 @@ S: Supported
T: git git://people.freedesktop.org/~agd5f/linux
F: drivers/gpu/drm/amd/pm/powerplay/
++AMD PTDMA DRIVER
++M: Sanjay R Mehta <[email protected]>
++L: [email protected]
++S: Maintained
++F: drivers/dma/ptdma/
+
AMD SEATTLE DEVICE TREE SUPPORT
M: Brijesh Singh <[email protected]>
M: Suravee Suthikulpanit <[email protected]>
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 6ab9d9a..7900f1a 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -714,6 +714,8 @@ source "drivers/dma/bestcomm/Kconfig"
source "drivers/dma/mediatek/Kconfig"
+source "drivers/dma/ptdma/Kconfig"
+
source "drivers/dma/qcom/Kconfig"
source "drivers/dma/dw/Kconfig"
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index aa69094..bf9ffc2 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
obj-$(CONFIG_ALTERA_MSGDMA) += altera-msgdma.o
obj-$(CONFIG_AMBA_PL08X) += amba-pl08x.o
obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
+obj-$(CONFIG_AMD_PTDMA) += ptdma/
obj-$(CONFIG_AT_HDMAC) += at_hdmac.o
obj-$(CONFIG_AT_XDMAC) += at_xdmac.o
obj-$(CONFIG_AXI_DMAC) += dma-axi-dmac.o
diff --git a/drivers/dma/ptdma/Kconfig b/drivers/dma/ptdma/Kconfig
new file mode 100644
index 0000000..e6b8ca1
--- /dev/null
+++ b/drivers/dma/ptdma/Kconfig
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config AMD_PTDMA
+ tristate "AMD PassThru DMA Engine"
+ depends on X86_64 && PCI
+ help
+ Enable support for the AMD PTDMA controller. This controller
+ provides DMA capabilities to perform high bandwidth memory to
+ memory and IO copy operations. It performs DMA transfer through
+ queue-based descriptor management. This DMA controller is intended
+ to be used with AMD Non-Transparent Bridge devices and not for
+ general purpose peripheral DMA.
diff --git a/drivers/dma/ptdma/Makefile b/drivers/dma/ptdma/Makefile
new file mode 100644
index 0000000..320fa82
--- /dev/null
+++ b/drivers/dma/ptdma/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# AMD Passthru DMA driver
+#
+
+obj-$(CONFIG_AMD_PTDMA) += ptdma.o
+
+ptdma-objs := ptdma-dev.o
+
+ptdma-$(CONFIG_PCI) += ptdma-pci.o
diff --git a/drivers/dma/ptdma/ptdma-dev.c b/drivers/dma/ptdma/ptdma-dev.c
new file mode 100644
index 0000000..4f9ae0b
--- /dev/null
+++ b/drivers/dma/ptdma/ptdma-dev.c
@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD Passthru DMA device driver
+ * -- Based on the CCP driver
+ *
+ * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
+ *
+ * Author: Sanjay R Mehta <[email protected]>
+ * Author: Gary R Hook <[email protected]>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dma-mapping.h>
+#include <linux/debugfs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+
+#include "ptdma.h"
+
+/* Human-readable error strings */
+static char *pt_error_codes[] = {
+ "",
+ "ERR 01: ILLEGAL_ENGINE",
+ "ERR 03: ILLEGAL_FUNCTION_TYPE",
+ "ERR 04: ILLEGAL_FUNCTION_MODE",
+ "ERR 06: ILLEGAL_FUNCTION_SIZE",
+ "ERR 08: ILLEGAL_FUNCTION_RSVD",
+ "ERR 09: ILLEGAL_BUFFER_LENGTH",
+ "ERR 10: VLSB_FAULT",
+ "ERR 11: ILLEGAL_MEM_ADDR",
+ "ERR 12: ILLEGAL_MEM_SEL",
+ "ERR 13: ILLEGAL_CONTEXT_ID",
+ "ERR 15: 0xF Reserved",
+ "ERR 18: CMD_TIMEOUT",
+ "ERR 19: IDMA0_AXI_SLVERR",
+ "ERR 20: IDMA0_AXI_DECERR",
+ "ERR 21: 0x15 Reserved",
+ "ERR 22: IDMA1_AXI_SLAVE_FAULT",
+ "ERR 23: IDMA1_AIXI_DECERR",
+ "ERR 24: 0x18 Reserved",
+ "ERR 27: 0x1B Reserved",
+ "ERR 38: ODMA0_AXI_SLVERR",
+ "ERR 39: ODMA0_AXI_DECERR",
+ "ERR 40: 0x28 Reserved",
+ "ERR 41: ODMA1_AXI_SLVERR",
+ "ERR 42: ODMA1_AXI_DECERR",
+ "ERR 43: LSB_PARITY_ERR",
+};
+
+static void pt_log_error(struct pt_device *d, int e)
+{
+ dev_err(d->dev, "PTDMA error: %s (0x%x)\n", pt_error_codes[e], e);
+}
+
+void pt_start_queue(struct pt_cmd_queue *cmd_q)
+{
+ /* Turn on the run bit */
+ iowrite32(cmd_q->qcontrol | CMD_Q_RUN, cmd_q->reg_control);
+}
+
+void pt_stop_queue(struct pt_cmd_queue *cmd_q)
+{
+ /* Turn off the run bit */
+ iowrite32(cmd_q->qcontrol & ~CMD_Q_RUN, cmd_q->reg_control);
+}
+
+static int pt_core_execute_cmd(struct ptdma_desc *desc, struct pt_cmd_queue *cmd_q)
+{
+ bool soc = FIELD_GET(DWORD0_SOC, desc->dw0);
+ u8 *q_desc = (u8 *)&cmd_q->qbase[cmd_q->qidx];
+ u32 tail;
+
+ if (soc) {
+ desc->dw0 |= FIELD_PREP(DWORD0_IOC, desc->dw0);
+ desc->dw0 &= ~DWORD0_SOC;
+ }
+ mutex_lock(&cmd_q->q_mutex);
+
+ /* Copy 32-byte command descriptor to hw queue. */
+ memcpy(q_desc, desc, 32);
+ cmd_q->qidx = (cmd_q->qidx + 1) % CMD_Q_LEN;
+
+ /* The data used by this command must be flushed to memory */
+ wmb();
+
+ /* Write the new tail address back to the queue register */
+ tail = lower_32_bits(cmd_q->qdma_tail + cmd_q->qidx * Q_DESC_SIZE);
+ iowrite32(tail, cmd_q->reg_tail_lo);
+
+ /* Turn the queue back on using our cached control register */
+ pt_start_queue(cmd_q);
+ mutex_unlock(&cmd_q->q_mutex);
+
+ return 0;
+}
+
+int pt_core_perform_passthru(struct pt_cmd_queue *cmd_q,
+ struct pt_passthru_engine *pt_engine)
+{
+ struct ptdma_desc desc;
+
+ cmd_q->cmd_error = 0;
+ memset(&desc, 0, sizeof(desc));
+ desc.dw0 = CMD_DESC_DW0_VAL;
+ desc.length = pt_engine->src_len;
+ desc.src_lo = lower_32_bits(pt_engine->src_dma);
+ desc.dw3.src_hi = upper_32_bits(pt_engine->src_dma);
+ desc.dst_lo = lower_32_bits(pt_engine->dst_dma);
+ desc.dw5.dst_hi = upper_32_bits(pt_engine->dst_dma);
+
+ return pt_core_execute_cmd(&desc, cmd_q);
+}
+
+static inline void pt_core_disable_queue_interrupts(struct pt_device *pt)
+{
+ iowrite32(0, pt->cmd_q.reg_int_enable);
+}
+
+static inline void pt_core_enable_queue_interrupts(struct pt_device *pt)
+{
+ iowrite32(SUPPORTED_INTERRUPTS, pt->cmd_q.reg_int_enable);
+}
+
+static irqreturn_t pt_core_irq_handler(int irq, void *data)
+{
+ struct pt_device *pt = data;
+ struct pt_cmd_queue *cmd_q = &pt->cmd_q;
+ u32 status;
+ bool err = true;
+
+ pt_core_disable_queue_interrupts(pt);
+
+ status = ioread32(cmd_q->reg_interrupt_status);
+ if (status) {
+ cmd_q->int_status = status;
+ cmd_q->q_status = ioread32(cmd_q->reg_status);
+ cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
+
+ /* On error, only save the first error value */
+ if ((status & INT_ERROR) && !cmd_q->cmd_error) {
+ cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
+ err = false;
+ }
+
+ /* Acknowledge the interrupt */
+ iowrite32(status, cmd_q->reg_interrupt_status);
+ }
+
+ pt_core_enable_queue_interrupts(pt);
+
+ return err ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void pt_init_cmdq_regs(struct pt_cmd_queue *cmd_q)
+{
+ void __iomem *io_regs = cmd_q->reg_control;
+
+ cmd_q->reg_tail_lo = io_regs + CMD_Q_TAIL_LO_BASE;
+ cmd_q->reg_head_lo = io_regs + CMD_Q_HEAD_LO_BASE;
+ cmd_q->reg_status = io_regs + CMD_Q_STATUS_BASE;
+ cmd_q->reg_int_enable = io_regs + CMD_Q_INT_ENABLE_BASE;
+ cmd_q->reg_int_status = io_regs + CMD_Q_INT_STATUS_BASE;
+ cmd_q->reg_dma_status = io_regs + CMD_Q_DMA_STATUS_BASE;
+ cmd_q->reg_dma_read_status = io_regs + CMD_Q_DMA_READ_STATUS_BASE;
+ cmd_q->reg_dma_write_status = io_regs + CMD_Q_DMA_WRITE_STATUS_BASE;
+ cmd_q->reg_interrupt_status = io_regs + CMD_Q_INTERRUPT_STATUS_BASE;
+}
+
+int pt_core_init(struct pt_device *pt)
+{
+ char dma_pool_name[MAX_DMAPOOL_NAME_LEN];
+ struct pt_cmd_queue *cmd_q = &pt->cmd_q;
+ u32 dma_addr_lo, dma_addr_hi;
+ struct device *dev = pt->dev;
+ struct dma_pool *dma_pool;
+ int ret;
+
+ /* Allocate a dma pool for the queue */
+ snprintf(dma_pool_name, sizeof(dma_pool_name), "%s_q", pt->name);
+
+ dma_pool = dma_pool_create(dma_pool_name, dev,
+ PT_DMAPOOL_MAX_SIZE,
+ PT_DMAPOOL_ALIGN, 0);
+ if (!dma_pool)
+ return -ENOMEM;
+
+ /* ptdma core initialisation */
+ iowrite32(CMD_CONFIG_VHB_EN, pt->io_regs + CMD_CONFIG_OFFSET);
+ iowrite32(CMD_QUEUE_PRIO, pt->io_regs + CMD_QUEUE_PRIO_OFFSET);
+ iowrite32(CMD_TIMEOUT_DISABLE, pt->io_regs + CMD_TIMEOUT_OFFSET);
+ iowrite32(CMD_CLK_GATE_CONFIG, pt->io_regs + CMD_CLK_GATE_CTL_OFFSET);
+ iowrite32(CMD_CONFIG_REQID, pt->io_regs + CMD_REQID_CONFIG_OFFSET);
+
+ cmd_q->pt = pt;
+ cmd_q->dma_pool = dma_pool;
+ mutex_init(&cmd_q->q_mutex);
+
+ /* Page alignment satisfies our needs for N <= 128 */
+ cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
+ cmd_q->qbase = dma_alloc_coherent(dev, cmd_q->qsize,
+ &cmd_q->qbase_dma,
+ GFP_KERNEL);
+ if (!cmd_q->qbase) {
+ dev_err(dev, "unable to allocate command queue\n");
+ ret = -ENOMEM;
+ goto e_dma_alloc;
+ }
+
+ cmd_q->qidx = 0;
+
+ /* Preset some register values */
+ cmd_q->reg_control = pt->io_regs + CMD_Q_STATUS_INCR;
+ pt_init_cmdq_regs(cmd_q);
+
+ /* Turn off the queues and disable interrupts until ready */
+ pt_core_disable_queue_interrupts(pt);
+
+ cmd_q->qcontrol = 0; /* Start with nothing */
+ iowrite32(cmd_q->qcontrol, cmd_q->reg_control);
+
+ ioread32(cmd_q->reg_int_status);
+ ioread32(cmd_q->reg_status);
+
+ /* Clear the interrupt status */
+ iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status);
+
+ /* Request an irq */
+ ret = request_irq(pt->pt_irq, pt_core_irq_handler, 0, pt->name, pt);
+ if (ret)
+ goto e_pool;
+
+ /* Update the device registers with queue information. */
+ cmd_q->qcontrol &= ~CMD_Q_SIZE;
+ cmd_q->qcontrol |= FIELD_PREP(CMD_Q_SIZE, QUEUE_SIZE_VAL);
+
+ cmd_q->qdma_tail = cmd_q->qbase_dma;
+ dma_addr_lo = lower_32_bits(cmd_q->qdma_tail);
+ iowrite32((u32)dma_addr_lo, cmd_q->reg_tail_lo);
+ iowrite32((u32)dma_addr_lo, cmd_q->reg_head_lo);
+
+ dma_addr_hi = upper_32_bits(cmd_q->qdma_tail);
+ cmd_q->qcontrol |= (dma_addr_hi << 16);
+ iowrite32(cmd_q->qcontrol, cmd_q->reg_control);
+
+ pt_core_enable_queue_interrupts(pt);
+
+ return 0;
+
+e_dma_alloc:
+ dma_free_coherent(dev, cmd_q->qsize, cmd_q->qbase, cmd_q->qbase_dma);
+
+e_pool:
+ dev_err(dev, "unable to allocate an IRQ\n");
+ dma_pool_destroy(pt->cmd_q.dma_pool);
+
+ return ret;
+}
+
+void pt_core_destroy(struct pt_device *pt)
+{
+ struct device *dev = pt->dev;
+ struct pt_cmd_queue *cmd_q = &pt->cmd_q;
+ struct pt_cmd *cmd;
+
+ /* Disable and clear interrupts */
+ pt_core_disable_queue_interrupts(pt);
+
+ /* Turn off the run bit */
+ pt_stop_queue(cmd_q);
+
+ /* Clear the interrupt status */
+ iowrite32(SUPPORTED_INTERRUPTS, cmd_q->reg_interrupt_status);
+ ioread32(cmd_q->reg_int_status);
+ ioread32(cmd_q->reg_status);
+
+ free_irq(pt->pt_irq, pt);
+
+ dma_free_coherent(dev, cmd_q->qsize, cmd_q->qbase,
+ cmd_q->qbase_dma);
+
+ /* Flush the cmd queue */
+ while (!list_empty(&pt->cmd)) {
+ /* Invoke the callback directly with an error code */
+ cmd = list_first_entry(&pt->cmd, struct pt_cmd, entry);
+ list_del(&cmd->entry);
+ cmd->pt_cmd_callback(cmd->data, -ENODEV);
+ }
+}
diff --git a/drivers/dma/ptdma/ptdma-pci.c b/drivers/dma/ptdma/ptdma-pci.c
new file mode 100644
index 0000000..ec75ec2
--- /dev/null
+++ b/drivers/dma/ptdma/ptdma-pci.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD Passthru DMA device driver
+ * -- Based on the CCP driver
+ *
+ * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
+ *
+ * Author: Sanjay R Mehta <[email protected]>
+ * Author: Tom Lendacky <[email protected]>
+ * Author: Gary R Hook <[email protected]>
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/pci_ids.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include "ptdma.h"
+
+struct pt_msix {
+ int msix_count;
+ struct msix_entry msix_entry;
+};
+
+/*
+ * pt_alloc_struct - allocate and initialize the pt_device struct
+ *
+ * @dev: device struct of the PTDMA
+ */
+static struct pt_device *pt_alloc_struct(struct device *dev)
+{
+ struct pt_device *pt;
+
+ pt = devm_kzalloc(dev, sizeof(*pt), GFP_KERNEL);
+
+ if (!pt)
+ return NULL;
+ pt->dev = dev;
+
+ INIT_LIST_HEAD(&pt->cmd);
+
+ snprintf(pt->name, MAX_PT_NAME_LEN, "pt-%s", dev_name(dev));
+
+ return pt;
+}
+
+static int pt_get_msix_irqs(struct pt_device *pt)
+{
+ struct pt_msix *pt_msix = pt->pt_msix;
+ struct device *dev = pt->dev;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int ret;
+
+ pt_msix->msix_entry.entry = 0;
+
+ ret = pci_enable_msix_range(pdev, &pt_msix->msix_entry, 1, 1);
+ if (ret < 0)
+ return ret;
+
+ pt_msix->msix_count = ret;
+
+ pt->pt_irq = pt_msix->msix_entry.vector;
+
+ return 0;
+}
+
+static int pt_get_msi_irq(struct pt_device *pt)
+{
+ struct device *dev = pt->dev;
+ struct pci_dev *pdev = to_pci_dev(dev);
+ int ret;
+
+ ret = pci_enable_msi(pdev);
+ if (ret)
+ return ret;
+
+ pt->pt_irq = pdev->irq;
+
+ return 0;
+}
+
+static int pt_get_irqs(struct pt_device *pt)
+{
+ struct device *dev = pt->dev;
+ int ret;
+
+ ret = pt_get_msix_irqs(pt);
+ if (!ret)
+ return 0;
+
+ /* Couldn't get MSI-X vectors, try MSI */
+ dev_err(dev, "could not enable MSI-X (%d), trying MSI\n", ret);
+ ret = pt_get_msi_irq(pt);
+ if (!ret)
+ return 0;
+
+ /* Couldn't get MSI interrupt */
+ dev_err(dev, "could not enable MSI (%d)\n", ret);
+
+ return ret;
+}
+
+static void pt_free_irqs(struct pt_device *pt)
+{
+ struct pt_msix *pt_msix = pt->pt_msix;
+ struct device *dev = pt->dev;
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if (pt_msix->msix_count)
+ pci_disable_msix(pdev);
+ else if (pt->pt_irq)
+ pci_disable_msi(pdev);
+
+ pt->pt_irq = 0;
+}
+
+static int pt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct pt_device *pt;
+ struct pt_msix *pt_msix;
+ struct device *dev = &pdev->dev;
+ void __iomem * const *iomap_table;
+ int bar_mask;
+ int ret = -ENOMEM;
+
+ pt = pt_alloc_struct(dev);
+ if (!pt)
+ goto e_err;
+
+ pt_msix = devm_kzalloc(dev, sizeof(*pt_msix), GFP_KERNEL);
+ if (!pt_msix)
+ goto e_err;
+
+ pt->pt_msix = pt_msix;
+ pt->dev_vdata = (struct pt_dev_vdata *)id->driver_data;
+ if (!pt->dev_vdata) {
+ ret = -ENODEV;
+ dev_err(dev, "missing driver data\n");
+ goto e_err;
+ }
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
+ goto e_err;
+ }
+
+ bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
+ ret = pcim_iomap_regions(pdev, bar_mask, "ptdma");
+ if (ret) {
+ dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
+ goto e_err;
+ }
+
+ iomap_table = pcim_iomap_table(pdev);
+ if (!iomap_table) {
+ dev_err(dev, "pcim_iomap_table failed\n");
+ ret = -ENOMEM;
+ goto e_err;
+ }
+
+ pt->io_regs = iomap_table[pt->dev_vdata->bar];
+ if (!pt->io_regs) {
+ dev_err(dev, "ioremap failed\n");
+ ret = -ENOMEM;
+ goto e_err;
+ }
+
+ ret = pt_get_irqs(pt);
+ if (ret)
+ goto e_err;
+
+ pci_set_master(pdev);
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
+ if (ret) {
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+ if (ret) {
+ dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
+ ret);
+ goto e_err;
+ }
+ }
+
+ dev_set_drvdata(dev, pt);
+
+ if (pt->dev_vdata)
+ ret = pt_core_init(pt);
+
+ if (ret)
+ goto e_err;
+
+ return 0;
+
+e_err:
+ dev_err(dev, "initialization failed\n");
+
+ return ret;
+}
+
+static void pt_pci_remove(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pt_device *pt = dev_get_drvdata(dev);
+
+ if (!pt)
+ return;
+
+ if (pt->dev_vdata)
+ pt_core_destroy(pt);
+
+ pt_free_irqs(pt);
+}
+
+static const struct pt_dev_vdata dev_vdata[] = {
+ {
+ .bar = 2,
+ },
+};
+
+static const struct pci_device_id pt_pci_table[] = {
+ { PCI_VDEVICE(AMD, 0x1498), (kernel_ulong_t)&dev_vdata[0] },
+ /* Last entry must be zero */
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, pt_pci_table);
+
+static struct pci_driver pt_pci_driver = {
+ .name = "ptdma",
+ .id_table = pt_pci_table,
+ .probe = pt_pci_probe,
+ .remove = pt_pci_remove,
+};
+
+module_pci_driver(pt_pci_driver);
+
+MODULE_AUTHOR("Sanjay R Mehta <[email protected]>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("AMD PassThru DMA driver");
diff --git a/drivers/dma/ptdma/ptdma.h b/drivers/dma/ptdma/ptdma.h
new file mode 100644
index 0000000..f8082c9
--- /dev/null
+++ b/drivers/dma/ptdma/ptdma.h
@@ -0,0 +1,302 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AMD Passthru DMA device driver
+ * -- Based on the CCP driver
+ *
+ * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
+ *
+ * Author: Sanjay R Mehta <[email protected]>
+ * Author: Tom Lendacky <[email protected]>
+ * Author: Gary R Hook <[email protected]>
+ */
+
+#ifndef __PT_DEV_H__
+#define __PT_DEV_H__
+
+#include <linux/device.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/dmapool.h>
+
+#define MAX_PT_NAME_LEN 16
+#define MAX_DMAPOOL_NAME_LEN 32
+
+#define MAX_HW_QUEUES 1
+#define MAX_CMD_QLEN 100
+
+#define PT_ENGINE_PASSTHRU 5
+#define PT_OFFSET 0x0
+
+/* Register Mappings */
+#define IRQ_MASK_REG 0x040
+#define IRQ_STATUS_REG 0x200
+
+#define CMD_Q_ERROR(__qs) ((__qs) & 0x0000003f)
+
+#define CMD_QUEUE_PRIO_OFFSET 0x00
+#define CMD_REQID_CONFIG_OFFSET 0x04
+#define CMD_TIMEOUT_OFFSET 0x08
+#define CMD_PT_VERSION 0x10
+
+#define CMD_Q_CONTROL_BASE 0x0000
+#define CMD_Q_TAIL_LO_BASE 0x0004
+#define CMD_Q_HEAD_LO_BASE 0x0008
+#define CMD_Q_INT_ENABLE_BASE 0x000C
+#define CMD_Q_INTERRUPT_STATUS_BASE 0x0010
+
+#define CMD_Q_STATUS_BASE 0x0100
+#define CMD_Q_INT_STATUS_BASE 0x0104
+#define CMD_Q_DMA_STATUS_BASE 0x0108
+#define CMD_Q_DMA_READ_STATUS_BASE 0x010C
+#define CMD_Q_DMA_WRITE_STATUS_BASE 0x0110
+#define CMD_Q_ABORT_BASE 0x0114
+#define CMD_Q_AX_CACHE_BASE 0x0118
+
+#define CMD_CONFIG_OFFSET 0x1120
+#define CMD_CLK_GATE_CTL_OFFSET 0x6004
+
+#define CMD_DESC_DW0_VAL 0x500012
+
+/* Address offset for virtual queue registers */
+#define CMD_Q_STATUS_INCR 0x1000
+
+/* Bit masks */
+#define CMD_CONFIG_REQID 0
+#define CMD_TIMEOUT_DISABLE 0
+#define CMD_CLK_DYN_GATING_DIS 0
+#define CMD_CLK_SW_GATE_MODE 0
+#define CMD_CLK_GATE_CTL 0
+#define CMD_QUEUE_PRIO GENMASK(2, 1)
+#define CMD_CONFIG_VHB_EN BIT(0)
+#define CMD_CLK_DYN_GATING_EN BIT(0)
+#define CMD_CLK_HW_GATE_MODE BIT(0)
+#define CMD_CLK_GATE_ON_DELAY BIT(12)
+#define CMD_CLK_GATE_OFF_DELAY BIT(12)
+
+#define CMD_CLK_GATE_CONFIG (CMD_CLK_GATE_CTL | \
+ CMD_CLK_HW_GATE_MODE | \
+ CMD_CLK_GATE_ON_DELAY | \
+ CMD_CLK_DYN_GATING_EN | \
+ CMD_CLK_GATE_OFF_DELAY)
+
+#define CMD_Q_LEN 32
+#define CMD_Q_RUN BIT(0)
+#define CMD_Q_HALT BIT(1)
+#define CMD_Q_MEM_LOCATION BIT(2)
+#define CMD_Q_SIZE_MASK GENMASK(4, 0)
+#define CMD_Q_SIZE GENMASK(7, 3)
+#define CMD_Q_SHIFT GENMASK(1, 0)
+#define QUEUE_SIZE_VAL ((ffs(CMD_Q_LEN) - 2) & \
+ CMD_Q_SIZE_MASK)
+#define Q_PTR_MASK (2 << (QUEUE_SIZE_VAL + 5) - 1)
+#define Q_DESC_SIZE sizeof(struct ptdma_desc)
+#define Q_SIZE(n) (CMD_Q_LEN * (n))
+
+#define INT_COMPLETION BIT(0)
+#define INT_ERROR BIT(1)
+#define INT_QUEUE_STOPPED BIT(2)
+#define INT_EMPTY_QUEUE BIT(3)
+#define SUPPORTED_INTERRUPTS (INT_COMPLETION | INT_ERROR)
+
+/****** Local Storage Block ******/
+#define LSB_START 0
+#define LSB_END 127
+#define LSB_COUNT (LSB_END - LSB_START + 1)
+
+#define PT_DMAPOOL_MAX_SIZE 64
+#define PT_DMAPOOL_ALIGN BIT(5)
+
+#define PT_PASSTHRU_BLOCKSIZE 512
+
+struct pt_device;
+
+struct pt_tasklet_data {
+ struct completion completion;
+ struct pt_cmd *cmd;
+};
+
+/*
+ * struct pt_passthru_engine - pass-through operation
+ * without performing DMA mapping
+ * @mask: mask to be applied to data
+ * @mask_len: length in bytes of mask
+ * @src_dma: data to be used for this operation
+ * @dst_dma: data produced by this operation
+ * @src_len: length in bytes of data used for this operation
+ *
+ * Variables required to be set when calling pt_enqueue_cmd():
+ * - bit_mod, byte_swap, src, dst, src_len
+ * - mask, mask_len if bit_mod is not PT_PASSTHRU_BITWISE_NOOP
+ */
+struct pt_passthru_engine {
+ dma_addr_t mask;
+ u32 mask_len; /* In bytes */
+
+ dma_addr_t src_dma, dst_dma;
+ u64 src_len; /* In bytes */
+};
+
+/*
+ * struct pt_cmd - PTDMA operation request
+ * @entry: list element
+ * @work: work element used for callbacks
+ * @pt: PT device to be run on
+ * @ret: operation return code
+ * @flags: cmd processing flags
+ * @engine: PTDMA operation to perform (passthru)
+ * @engine_error: PT engine return code
+ * @passthru: engine specific structures, refer to specific engine struct below
+ * @callback: operation completion callback function
+ * @data: parameter value to be supplied to the callback function
+ *
+ * Variables required to be set when calling pt_enqueue_cmd():
+ * - engine, callback
+ * - See the operation structures below for what is required for each
+ * operation.
+ */
+struct pt_cmd {
+ struct list_head entry;
+ struct work_struct work;
+ struct pt_device *pt;
+ int ret;
+ u32 engine;
+ u32 engine_error;
+ struct pt_passthru_engine passthru;
+ /* Completion callback support */
+ void (*pt_cmd_callback)(void *data, int err);
+ void *data;
+};
+
+struct pt_cmd_queue {
+ struct pt_device *pt;
+
+ /* Queue dma pool */
+ struct dma_pool *dma_pool;
+
+ /* Queue base address (not neccessarily aligned)*/
+ struct ptdma_desc *qbase;
+
+ /* Aligned queue start address (per requirement) */
+ struct mutex q_mutex ____cacheline_aligned;
+ unsigned int qidx;
+
+ unsigned int qsize;
+ dma_addr_t qbase_dma;
+ dma_addr_t qdma_tail;
+
+ unsigned int active;
+ unsigned int suspended;
+
+ /* Register addresses for queue */
+ void __iomem *reg_control;
+ void __iomem *reg_tail_lo;
+ void __iomem *reg_head_lo;
+ void __iomem *reg_int_enable;
+ void __iomem *reg_interrupt_status;
+ void __iomem *reg_status;
+ void __iomem *reg_int_status;
+ void __iomem *reg_dma_status;
+ void __iomem *reg_dma_read_status;
+ void __iomem *reg_dma_write_status;
+ u32 qcontrol; /* Cached control register */
+
+ /* Status values from job */
+ u32 int_status;
+ u32 q_status;
+ u32 q_int_status;
+ u32 cmd_error;
+} ____cacheline_aligned;
+
+struct pt_device {
+ struct list_head entry;
+
+ unsigned int ord;
+ char name[MAX_PT_NAME_LEN];
+
+ struct device *dev;
+
+ /* Bus specific device information */
+ struct pt_msix *pt_msix;
+
+ struct pt_dev_vdata *dev_vdata;
+
+ unsigned int pt_irq;
+
+ /* I/O area used for device communication */
+ void __iomem *io_regs;
+
+ spinlock_t cmd_lock ____cacheline_aligned;
+ unsigned int cmd_count;
+ struct list_head cmd;
+
+ /*
+ * The command queue. This represent the queue available on the
+ * PTDMA that are available for processing cmds
+ */
+ struct pt_cmd_queue cmd_q;
+
+ wait_queue_head_t lsb_queue;
+
+ struct pt_tasklet_data tdata;
+};
+
+/*
+ * descriptor for PTDMA commands
+ * 8 32-bit words:
+ * word 0: function; engine; control bits
+ * word 1: length of source data
+ * word 2: low 32 bits of source pointer
+ * word 3: upper 16 bits of source pointer; source memory type
+ * word 4: low 32 bits of destination pointer
+ * word 5: upper 16 bits of destination pointer; destination memory type
+ * word 6: reserved 32 bits
+ * word 7: reserved 32 bits
+ */
+
+#define DWORD0_SOC BIT(0)
+#define DWORD0_IOC BIT(1)
+
+struct dword3 {
+ unsigned int src_hi:16;
+ unsigned int src_mem:2;
+ unsigned int lsb_cxt_id:8;
+ unsigned int rsvd1:5;
+ unsigned int fixed:1;
+};
+
+struct dword5 {
+ unsigned int dst_hi:16;
+ unsigned int dst_mem:2;
+ unsigned int rsvd1:13;
+ unsigned int fixed:1;
+};
+
+struct ptdma_desc {
+ u32 dw0;
+ u32 length;
+ u32 src_lo;
+ struct dword3 dw3;
+ u32 dst_lo;
+ struct dword5 dw5;
+ __le32 rsvd1;
+ __le32 rsvd2;
+};
+
+/* Structure to hold PT device data */
+struct pt_dev_vdata {
+ const unsigned int bar;
+};
+
+int pt_core_init(struct pt_device *pt);
+void pt_core_destroy(struct pt_device *pt);
+
+int pt_core_perform_passthru(struct pt_cmd_queue *cmd_q,
+ struct pt_passthru_engine *pt_engine);
+
+void pt_start_queue(struct pt_cmd_queue *cmd_q);
+void pt_stop_queue(struct pt_cmd_queue *cmd_q);
+
+#endif
--
2.7.4
From: Sanjay R Mehta <[email protected]>
Register ptdma queue to Linux dmaengine framework as general-purpose
DMA channels.
Signed-off-by: Sanjay R Mehta <[email protected]>
---
drivers/dma/ptdma/Kconfig | 2 +
drivers/dma/ptdma/Makefile | 2 +-
drivers/dma/ptdma/ptdma-dev.c | 32 +++
drivers/dma/ptdma/ptdma-dmaengine.c | 389 ++++++++++++++++++++++++++++++++++++
drivers/dma/ptdma/ptdma.h | 26 +++
5 files changed, 450 insertions(+), 1 deletion(-)
create mode 100644 drivers/dma/ptdma/ptdma-dmaengine.c
diff --git a/drivers/dma/ptdma/Kconfig b/drivers/dma/ptdma/Kconfig
index e6b8ca1..b430edd 100644
--- a/drivers/dma/ptdma/Kconfig
+++ b/drivers/dma/ptdma/Kconfig
@@ -2,6 +2,8 @@
config AMD_PTDMA
tristate "AMD PassThru DMA Engine"
depends on X86_64 && PCI
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
help
Enable support for the AMD PTDMA controller. This controller
provides DMA capabilities to perform high bandwidth memory to
diff --git a/drivers/dma/ptdma/Makefile b/drivers/dma/ptdma/Makefile
index 320fa82..a528cb0 100644
--- a/drivers/dma/ptdma/Makefile
+++ b/drivers/dma/ptdma/Makefile
@@ -5,6 +5,6 @@
obj-$(CONFIG_AMD_PTDMA) += ptdma.o
-ptdma-objs := ptdma-dev.o
+ptdma-objs := ptdma-dev.o ptdma-dmaengine.o
ptdma-$(CONFIG_PCI) += ptdma-pci.o
diff --git a/drivers/dma/ptdma/ptdma-dev.c b/drivers/dma/ptdma/ptdma-dev.c
index 4f9ae0b..c1323ed 100644
--- a/drivers/dma/ptdma/ptdma-dev.c
+++ b/drivers/dma/ptdma/ptdma-dev.c
@@ -123,6 +123,26 @@ static inline void pt_core_enable_queue_interrupts(struct pt_device *pt)
iowrite32(SUPPORTED_INTERRUPTS, pt->cmd_q.reg_int_enable);
}
+static void pt_do_cmd_complete(unsigned long data)
+{
+ struct pt_tasklet_data *tdata = (struct pt_tasklet_data *)data;
+ struct pt_cmd *cmd = tdata->cmd;
+ struct pt_cmd_queue *cmd_q = &cmd->pt->cmd_q;
+ u32 tail;
+
+ if (cmd_q->cmd_error) {
+ /*
+ * Log the error and flush the queue by
+ * moving the head pointer
+ */
+ tail = lower_32_bits(cmd_q->qdma_tail + cmd_q->qidx * Q_DESC_SIZE);
+ pt_log_error(cmd_q->pt, cmd_q->cmd_error);
+ iowrite32(tail, cmd_q->reg_head_lo);
+ }
+
+ cmd->pt_cmd_callback(cmd->data, cmd->ret);
+}
+
static irqreturn_t pt_core_irq_handler(int irq, void *data)
{
struct pt_device *pt = data;
@@ -149,6 +169,7 @@ static irqreturn_t pt_core_irq_handler(int irq, void *data)
}
pt_core_enable_queue_interrupts(pt);
+ pt_do_cmd_complete((ulong)&pt->tdata);
return err ? IRQ_HANDLED : IRQ_NONE;
}
@@ -246,8 +267,16 @@ int pt_core_init(struct pt_device *pt)
pt_core_enable_queue_interrupts(pt);
+ /* Register the DMA engine support */
+ ret = pt_dmaengine_register(pt);
+ if (ret)
+ goto e_dmaengine;
+
return 0;
+e_dmaengine:
+ free_irq(pt->pt_irq, pt);
+
e_dma_alloc:
dma_free_coherent(dev, cmd_q->qsize, cmd_q->qbase, cmd_q->qbase_dma);
@@ -264,6 +293,9 @@ void pt_core_destroy(struct pt_device *pt)
struct pt_cmd_queue *cmd_q = &pt->cmd_q;
struct pt_cmd *cmd;
+ /* Unregister the DMA engine */
+ pt_dmaengine_unregister(pt);
+
/* Disable and clear interrupts */
pt_core_disable_queue_interrupts(pt);
diff --git a/drivers/dma/ptdma/ptdma-dmaengine.c b/drivers/dma/ptdma/ptdma-dmaengine.c
new file mode 100644
index 0000000..45392a3
--- /dev/null
+++ b/drivers/dma/ptdma/ptdma-dmaengine.c
@@ -0,0 +1,389 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD Passthrough DMA device driver
+ * -- Based on the CCP driver
+ *
+ * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
+ *
+ * Author: Sanjay R Mehta <[email protected]>
+ * Author: Gary R Hook <[email protected]>
+ */
+
+#include "ptdma.h"
+#include "../dmaengine.h"
+#include "../virt-dma.h"
+
+static inline struct pt_dma_chan *to_pt_chan(struct dma_chan *dma_chan)
+{
+ return container_of(dma_chan, struct pt_dma_chan, vc.chan);
+}
+
+static inline struct pt_dma_desc *to_pt_desc(struct virt_dma_desc *vd)
+{
+ return container_of(vd, struct pt_dma_desc, vd);
+}
+
+static void pt_free_chan_resources(struct dma_chan *dma_chan)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+
+ vchan_free_chan_resources(&chan->vc);
+}
+
+static void pt_synchronize(struct dma_chan *dma_chan)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+
+ vchan_synchronize(&chan->vc);
+}
+
+static void pt_do_cleanup(struct virt_dma_desc *vd)
+{
+ struct pt_dma_desc *desc = to_pt_desc(vd);
+ struct pt_device *pt = desc->pt;
+
+ kmem_cache_free(pt->dma_desc_cache, desc);
+}
+
+static int pt_dma_start_desc(struct pt_dma_desc *desc)
+{
+ struct pt_passthru_engine *pt_engine;
+ struct pt_device *pt;
+ struct pt_cmd *pt_cmd;
+ struct pt_cmd_queue *cmd_q;
+
+ desc->issued_to_hw = 1;
+
+ pt_cmd = &desc->pt_cmd;
+ pt = pt_cmd->pt;
+ cmd_q = &pt->cmd_q;
+ pt_engine = &pt_cmd->passthru;
+
+ pt->tdata.cmd = pt_cmd;
+
+ /* Execute the command */
+ pt_cmd->ret = pt_core_perform_passthru(cmd_q, pt_engine);
+
+ return 0;
+}
+
+static struct pt_dma_desc *pt_next_dma_desc(struct pt_dma_chan *chan)
+{
+ /* Get the next DMA descriptor on the active list */
+ struct virt_dma_desc *vd = vchan_next_desc(&chan->vc);
+
+ return vd ? to_pt_desc(vd) : NULL;
+}
+
+static struct pt_dma_desc *pt_handle_active_desc(struct pt_dma_chan *chan,
+ struct pt_dma_desc *desc)
+{
+ struct dma_async_tx_descriptor *tx_desc;
+ struct virt_dma_desc *vd;
+ unsigned long flags;
+
+ /* Loop over descriptors until one is found with commands */
+ do {
+ if (desc) {
+ if (!desc->issued_to_hw) {
+ /* No errors, keep going */
+ if (desc->status != DMA_ERROR)
+ return desc;
+ }
+
+ tx_desc = &desc->vd.tx;
+ vd = &desc->vd;
+ } else {
+ tx_desc = NULL;
+ }
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ if (desc) {
+ if (desc->status != DMA_ERROR)
+ desc->status = DMA_COMPLETE;
+
+ dma_cookie_complete(tx_desc);
+ dma_descriptor_unmap(tx_desc);
+ list_del(&desc->vd.node);
+ }
+
+ desc = pt_next_dma_desc(chan);
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ if (tx_desc) {
+ dmaengine_desc_get_callback_invoke(tx_desc, NULL);
+ dma_run_dependencies(tx_desc);
+ vchan_vdesc_fini(vd);
+ }
+ } while (desc);
+
+ return NULL;
+}
+
+static void pt_cmd_callback(void *data, int err)
+{
+ struct pt_dma_desc *desc = data;
+ struct dma_chan *dma_chan;
+ struct pt_dma_chan *chan;
+ int ret;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ dma_chan = desc->vd.tx.chan;
+ chan = to_pt_chan(dma_chan);
+
+ if (err)
+ desc->status = DMA_ERROR;
+
+ while (true) {
+ /* Check for DMA descriptor completion */
+ desc = pt_handle_active_desc(chan, desc);
+
+ /* Don't submit cmd if no descriptor or DMA is paused */
+ if (!desc)
+ break;
+
+ ret = pt_dma_start_desc(desc);
+ if (!ret)
+ break;
+
+ desc->status = DMA_ERROR;
+ }
+}
+
+static struct pt_dma_desc *pt_alloc_dma_desc(struct pt_dma_chan *chan,
+ unsigned long flags)
+{
+ struct pt_dma_desc *desc;
+
+ desc = kmem_cache_zalloc(chan->pt->dma_desc_cache, GFP_NOWAIT);
+ if (!desc)
+ return NULL;
+
+ vchan_tx_prep(&chan->vc, &desc->vd, flags);
+
+ desc->pt = chan->pt;
+ desc->issued_to_hw = 0;
+ desc->status = DMA_IN_PROGRESS;
+
+ return desc;
+}
+
+static struct pt_dma_desc *pt_create_desc(struct dma_chan *dma_chan,
+ dma_addr_t dst,
+ dma_addr_t src,
+ unsigned int len,
+ unsigned long flags)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+ struct pt_passthru_engine *pt_engine;
+ struct pt_dma_desc *desc;
+ struct pt_cmd *pt_cmd;
+
+ desc = pt_alloc_dma_desc(chan, flags);
+ if (!desc)
+ return NULL;
+
+ pt_cmd = &desc->pt_cmd;
+ pt_cmd->pt = chan->pt;
+ pt_engine = &pt_cmd->passthru;
+ pt_cmd->engine = PT_ENGINE_PASSTHRU;
+ pt_engine->src_dma = src;
+ pt_engine->dst_dma = dst;
+ pt_engine->src_len = len;
+ pt_cmd->pt_cmd_callback = pt_cmd_callback;
+ pt_cmd->data = desc;
+
+ desc->len = len;
+
+ return desc;
+}
+
+static struct dma_async_tx_descriptor *
+pt_prep_dma_memcpy(struct dma_chan *dma_chan, dma_addr_t dst,
+ dma_addr_t src, size_t len, unsigned long flags)
+{
+ struct pt_dma_desc *desc;
+
+ desc = pt_create_desc(dma_chan, dst, src, len, flags);
+ if (!desc)
+ return NULL;
+
+ return &desc->vd.tx;
+}
+
+static struct dma_async_tx_descriptor *
+pt_prep_dma_interrupt(struct dma_chan *dma_chan, unsigned long flags)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+ struct pt_dma_desc *desc;
+
+ desc = pt_alloc_dma_desc(chan, flags);
+ if (!desc)
+ return NULL;
+
+ return &desc->vd.tx;
+}
+
+static void pt_issue_pending(struct dma_chan *dma_chan)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+ struct pt_dma_desc *desc;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+
+ vchan_issue_pending(&chan->vc);
+
+ desc = pt_next_dma_desc(chan);
+
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ /* If there was nothing active, start processing */
+ if (desc)
+ pt_cmd_callback(desc, 0);
+}
+
+static int pt_pause(struct dma_chan *dma_chan)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+ pt_stop_queue(&chan->pt->cmd_q);
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ return 0;
+}
+
+static int pt_resume(struct dma_chan *dma_chan)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+ struct pt_dma_desc *desc = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+ pt_start_queue(&chan->pt->cmd_q);
+ desc = pt_next_dma_desc(chan);
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ /* If there was something active, re-start */
+ if (desc)
+ pt_cmd_callback(desc, 0);
+
+ return 0;
+}
+
+static int pt_terminate_all(struct dma_chan *dma_chan)
+{
+ struct pt_dma_chan *chan = to_pt_chan(dma_chan);
+ unsigned long flags;
+ LIST_HEAD(head);
+
+ spin_lock_irqsave(&chan->vc.lock, flags);
+ vchan_get_all_descriptors(&chan->vc, &head);
+ spin_unlock_irqrestore(&chan->vc.lock, flags);
+
+ vchan_dma_desc_free_list(&chan->vc, &head);
+ vchan_free_chan_resources(&chan->vc);
+
+ return 0;
+}
+
+int pt_dmaengine_register(struct pt_device *pt)
+{
+ struct pt_dma_chan *chan;
+ struct dma_device *dma_dev = &pt->dma_dev;
+ char *cmd_cache_name;
+ char *desc_cache_name;
+ int ret;
+
+ pt->pt_dma_chan = devm_kzalloc(pt->dev, sizeof(*pt->pt_dma_chan),
+ GFP_KERNEL);
+ if (!pt->pt_dma_chan)
+ return -ENOMEM;
+
+ cmd_cache_name = devm_kasprintf(pt->dev, GFP_KERNEL,
+ "%s-dmaengine-cmd-cache",
+ pt->name);
+ if (!cmd_cache_name)
+ return -ENOMEM;
+
+ desc_cache_name = devm_kasprintf(pt->dev, GFP_KERNEL,
+ "%s-dmaengine-desc-cache",
+ pt->name);
+ if (!desc_cache_name) {
+ ret = -ENOMEM;
+ goto err_cache;
+ }
+
+ pt->dma_desc_cache = kmem_cache_create(desc_cache_name,
+ sizeof(struct pt_dma_desc), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!pt->dma_desc_cache) {
+ ret = -ENOMEM;
+ goto err_cache;
+ }
+
+ dma_dev->dev = pt->dev;
+ dma_dev->src_addr_widths = DMA_SLAVE_BUSWIDTH_64_BYTES;
+ dma_dev->dst_addr_widths = DMA_SLAVE_BUSWIDTH_64_BYTES;
+ dma_dev->directions = DMA_MEM_TO_MEM;
+ dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
+ dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+ dma_cap_set(DMA_INTERRUPT, dma_dev->cap_mask);
+
+ /*
+ * PTDMA is intended to be used with the AMD NTB devices, hence
+ * marking it as DMA_PRIVATE.
+ */
+ dma_cap_set(DMA_PRIVATE, dma_dev->cap_mask);
+
+ INIT_LIST_HEAD(&dma_dev->channels);
+
+ chan = pt->pt_dma_chan;
+ chan->pt = pt;
+
+ /* Set base and prep routines */
+ dma_dev->device_free_chan_resources = pt_free_chan_resources;
+ dma_dev->device_prep_dma_memcpy = pt_prep_dma_memcpy;
+ dma_dev->device_prep_dma_interrupt = pt_prep_dma_interrupt;
+ dma_dev->device_issue_pending = pt_issue_pending;
+ dma_dev->device_tx_status = dma_cookie_status;
+ dma_dev->device_pause = pt_pause;
+ dma_dev->device_resume = pt_resume;
+ dma_dev->device_terminate_all = pt_terminate_all;
+ dma_dev->device_synchronize = pt_synchronize;
+
+ chan->vc.desc_free = pt_do_cleanup;
+ vchan_init(&chan->vc, dma_dev);
+
+ dma_set_mask_and_coherent(pt->dev, DMA_BIT_MASK(64));
+
+ ret = dma_async_device_register(dma_dev);
+ if (ret)
+ goto err_reg;
+
+ return 0;
+
+err_reg:
+ kmem_cache_destroy(pt->dma_desc_cache);
+
+err_cache:
+ kmem_cache_destroy(pt->dma_cmd_cache);
+
+ return ret;
+}
+
+void pt_dmaengine_unregister(struct pt_device *pt)
+{
+ struct dma_device *dma_dev = &pt->dma_dev;
+
+ dma_async_device_unregister(dma_dev);
+
+ kmem_cache_destroy(pt->dma_desc_cache);
+ kmem_cache_destroy(pt->dma_cmd_cache);
+}
diff --git a/drivers/dma/ptdma/ptdma.h b/drivers/dma/ptdma/ptdma.h
index f8082c9..9627585 100644
--- a/drivers/dma/ptdma/ptdma.h
+++ b/drivers/dma/ptdma/ptdma.h
@@ -14,6 +14,7 @@
#define __PT_DEV_H__
#include <linux/device.h>
+#include <linux/dmaengine.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
@@ -21,6 +22,8 @@
#include <linux/wait.h>
#include <linux/dmapool.h>
+#include "../virt-dma.h"
+
#define MAX_PT_NAME_LEN 16
#define MAX_DMAPOOL_NAME_LEN 32
@@ -170,6 +173,20 @@ struct pt_cmd {
void *data;
};
+struct pt_dma_desc {
+ struct virt_dma_desc vd;
+ struct pt_device *pt;
+ enum dma_status status;
+ size_t len;
+ bool issued_to_hw;
+ struct pt_cmd pt_cmd;
+};
+
+struct pt_dma_chan {
+ struct virt_dma_chan vc;
+ struct pt_device *pt;
+};
+
struct pt_cmd_queue {
struct pt_device *pt;
@@ -238,6 +255,12 @@ struct pt_device {
*/
struct pt_cmd_queue cmd_q;
+ /* Support for the DMA Engine capabilities */
+ struct dma_device dma_dev;
+ struct pt_dma_chan *pt_dma_chan;
+ struct kmem_cache *dma_cmd_cache;
+ struct kmem_cache *dma_desc_cache;
+
wait_queue_head_t lsb_queue;
struct pt_tasklet_data tdata;
@@ -290,6 +313,9 @@ struct pt_dev_vdata {
const unsigned int bar;
};
+int pt_dmaengine_register(struct pt_device *pt);
+void pt_dmaengine_unregister(struct pt_device *pt);
+
int pt_core_init(struct pt_device *pt);
void pt_core_destroy(struct pt_device *pt);
--
2.7.4
From: Sanjay R Mehta <[email protected]>
Expose data about the configuration and operation of the
PTDMA through debugfs entries: device name, capabilities,
configuration, statistics.
Signed-off-by: Sanjay R Mehta <[email protected]>
---
drivers/dma/ptdma/Makefile | 2 +-
drivers/dma/ptdma/ptdma-debugfs.c | 110 ++++++++++++++++++++++++++++++++++++++
drivers/dma/ptdma/ptdma-dev.c | 5 ++
drivers/dma/ptdma/ptdma.h | 6 +++
4 files changed, 122 insertions(+), 1 deletion(-)
create mode 100644 drivers/dma/ptdma/ptdma-debugfs.c
diff --git a/drivers/dma/ptdma/Makefile b/drivers/dma/ptdma/Makefile
index a528cb0..ce54102 100644
--- a/drivers/dma/ptdma/Makefile
+++ b/drivers/dma/ptdma/Makefile
@@ -5,6 +5,6 @@
obj-$(CONFIG_AMD_PTDMA) += ptdma.o
-ptdma-objs := ptdma-dev.o ptdma-dmaengine.o
+ptdma-objs := ptdma-dev.o ptdma-dmaengine.o ptdma-debugfs.o
ptdma-$(CONFIG_PCI) += ptdma-pci.o
diff --git a/drivers/dma/ptdma/ptdma-debugfs.c b/drivers/dma/ptdma/ptdma-debugfs.c
new file mode 100644
index 0000000..57d81c3
--- /dev/null
+++ b/drivers/dma/ptdma/ptdma-debugfs.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD Passthrough DMA device driver
+ * -- Based on the CCP driver
+ *
+ * Copyright (C) 2016,2021 Advanced Micro Devices, Inc.
+ *
+ * Author: Sanjay R Mehta <[email protected]>
+ * Author: Gary R Hook <[email protected]>
+ */
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "ptdma.h"
+
+/* DebugFS helpers */
+#define MAX_NAME_LEN 20
+#define RI_VERSION_NUM 0x0000003F
+
+#define RI_NUM_VQM 0x00078000
+#define RI_NVQM_SHIFT 15
+
+static int pt_debugfs_info_show(struct seq_file *s, void *p)
+{
+ struct pt_device *pt = s->private;
+ unsigned int regval;
+
+ seq_printf(s, "Device name: %s\n", pt->name);
+ seq_printf(s, " # Queues: %d\n", 1);
+ seq_printf(s, " # Cmds: %d\n", pt->cmd_count);
+
+ regval = ioread32(pt->io_regs + CMD_PT_VERSION);
+
+ seq_printf(s, " Version: %d\n", regval & RI_VERSION_NUM);
+ seq_puts(s, " Engines:");
+ seq_puts(s, "\n");
+ seq_printf(s, " Queues: %d\n", (regval & RI_NUM_VQM) >> RI_NVQM_SHIFT);
+
+ return 0;
+}
+
+/*
+ * Return a formatted buffer containing the current
+ * statistics of queue for PTDMA
+ */
+static int pt_debugfs_stats_show(struct seq_file *s, void *p)
+{
+ struct pt_device *pt = s->private;
+
+ seq_printf(s, "Total Interrupts Handled: %ld\n", pt->total_interrupts);
+
+ return 0;
+}
+
+static int pt_debugfs_queue_show(struct seq_file *s, void *p)
+{
+ struct pt_cmd_queue *cmd_q = s->private;
+ unsigned int regval;
+
+ if (!cmd_q)
+ return 0;
+
+ seq_printf(s, " Pass-Thru: %ld\n", cmd_q->total_pt_ops);
+
+ regval = ioread32(cmd_q->reg_int_enable);
+
+ seq_puts(s, " Enabled Interrupts:");
+ if (regval & INT_EMPTY_QUEUE)
+ seq_puts(s, " EMPTY");
+ if (regval & INT_QUEUE_STOPPED)
+ seq_puts(s, " STOPPED");
+ if (regval & INT_ERROR)
+ seq_puts(s, " ERROR");
+ if (regval & INT_COMPLETION)
+ seq_puts(s, " COMPLETION");
+ seq_puts(s, "\n");
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(pt_debugfs_info);
+DEFINE_SHOW_ATTRIBUTE(pt_debugfs_queue);
+DEFINE_SHOW_ATTRIBUTE(pt_debugfs_stats);
+
+void ptdma_debugfs_setup(struct pt_device *pt)
+{
+ struct pt_cmd_queue *cmd_q;
+ char name[MAX_NAME_LEN + 1];
+ struct dentry *debugfs_q_instance;
+
+ if (!debugfs_initialized())
+ return;
+
+ debugfs_create_file("info", 0400, pt->dma_dev.dbg_dev_root, pt,
+ &pt_debugfs_info_fops);
+
+ debugfs_create_file("stats", 0400, pt->dma_dev.dbg_dev_root, pt,
+ &pt_debugfs_stats_fops);
+
+ cmd_q = &pt->cmd_q;
+
+ snprintf(name, MAX_NAME_LEN - 1, "q");
+
+ debugfs_q_instance =
+ debugfs_create_dir(name, pt->dma_dev.dbg_dev_root);
+
+ debugfs_create_file("stats", 0400, debugfs_q_instance, cmd_q,
+ &pt_debugfs_queue_fops);
+}
diff --git a/drivers/dma/ptdma/ptdma-dev.c b/drivers/dma/ptdma/ptdma-dev.c
index c1323ed..4429de0 100644
--- a/drivers/dma/ptdma/ptdma-dev.c
+++ b/drivers/dma/ptdma/ptdma-dev.c
@@ -102,6 +102,7 @@ int pt_core_perform_passthru(struct pt_cmd_queue *cmd_q,
struct ptdma_desc desc;
cmd_q->cmd_error = 0;
+ cmd_q->total_pt_ops++;
memset(&desc, 0, sizeof(desc));
desc.dw0 = CMD_DESC_DW0_VAL;
desc.length = pt_engine->src_len;
@@ -151,6 +152,7 @@ static irqreturn_t pt_core_irq_handler(int irq, void *data)
bool err = true;
pt_core_disable_queue_interrupts(pt);
+ pt->total_interrupts++;
status = ioread32(cmd_q->reg_interrupt_status);
if (status) {
@@ -272,6 +274,9 @@ int pt_core_init(struct pt_device *pt)
if (ret)
goto e_dmaengine;
+ /* Set up debugfs entries */
+ ptdma_debugfs_setup(pt);
+
return 0;
e_dmaengine:
diff --git a/drivers/dma/ptdma/ptdma.h b/drivers/dma/ptdma/ptdma.h
index 9627585..a5cd65f 100644
--- a/drivers/dma/ptdma/ptdma.h
+++ b/drivers/dma/ptdma/ptdma.h
@@ -225,6 +225,8 @@ struct pt_cmd_queue {
u32 q_status;
u32 q_int_status;
u32 cmd_error;
+ /* Queue Statistics */
+ unsigned long total_pt_ops;
} ____cacheline_aligned;
struct pt_device {
@@ -263,6 +265,9 @@ struct pt_device {
wait_queue_head_t lsb_queue;
+ /* Device Statistics */
+ unsigned long total_interrupts;
+
struct pt_tasklet_data tdata;
};
@@ -316,6 +321,7 @@ struct pt_dev_vdata {
int pt_dmaengine_register(struct pt_device *pt);
void pt_dmaengine_unregister(struct pt_device *pt);
+void ptdma_debugfs_setup(struct pt_device *pt);
int pt_core_init(struct pt_device *pt);
void pt_core_destroy(struct pt_device *pt);
--
2.7.4
On 6/20/2021 10:11 PM, Sanjay R Mehta wrote:
> From: Sanjay R Mehta <[email protected]>
>
> This patch series add support for AMD PTDMA controller which
> performs high bandwidth memory-to-memory and IO copy operation,
> performs DMA transfer through queue based descriptor management.
>
> AMD Processor has multiple ptdma device instances with each controller
> having single queue. The driver also adds support for for multiple PTDMA
> instances, each device will get an unique identifier and uniquely
> named resources.
>
> v10:
> - modified ISR to return IR_HANDLED only in non-error condition.
> - removed unnecessary prints, variables and made some cosmetic changes.
> - removed pt_ordinal atomic variable and instead using dev_name()
> for device name.
> - removed the cmdlist dependency and instead using vc.desc_issued list.
> - freeing the desc and list which was missing in the pt_terminate_all()
> funtion.
> - Added comment for marking PTDMA as DMA_PRIVATE.
> - removed unused pt_debugfs_lock from debufs code.
> - keeping same file permision for all the debug directoris.
>
> v9:
> - Modified the help message in Kconfig as per Randy's comment.
> - reverted the split of code for "pt_handle_active_desc" as there
> was driver hang being observerd after few iterations.
>
> v8:
> - splitted the code into different functions, one to find active desc
> and second to complete and invoke callback.
> - used FIELD_PREP & FIELD_GET instead of union struct bitfields.
> - modified all style fixes as per the comments.
>
> v7:
> - Fixed module warnings reported ( by kernel test robot <[email protected]> ).
>
> v6:
> - Removed debug artifacts and made the suggested cosmetic changes.
> - implemented and used to_pt_chan and to_pt_desc inline functions.
> - Removed src and dst address check as framework does this.
> - Removed devm_kcalloc() usage and used devm_kzalloc() api.
> - Using framework debugfs directory to store dma info.
>
> v5:
> - modified code to submit next tranction in ISR itself and removed the tasklet.
> - implemented .device_synchronize API.
> - converted debugfs code by using DEFINE_SHOW_ATTRIBUTE()
> - using dbg_dev_root for debugfs root directory.
> - removed dma_status from pt_dma_chan
> - removed module parameter cmd_queue_lenght.
> - removed global device list for multiple devics.
> - removed code related to dynamic adding/deleting to device list
> - removed pt_add_device and pt_del_device functions
>
> v4:
> - modified DMA channel and descriptor management using virt-dma layer
> instead of list based management.
> - return only status of the cookie from pt_tx_status
> - copyright year changed from 2019 to 2020
> - removed dummy code for suspend & resume
> - used bitmask and genmask
>
> v3:
> - Fixed the sparse warnings.
>
> v2:
> - Added controller description in cover letter
> - Removed "default m" from Kconfig
> - Replaced low_address() and high_address() functions with kernel
> API's lower_32_bits & upper_32_bits().
> - Removed the BH handler function pt_core_irq_bh() and instead
> handling transaction in irq handler itself.
> - Moved presetting of command queue registers into new function
> "init_cmdq_regs()"
> - Removed the kernel thread dependency to submit transaction.
> - Increased the hardware command queue size to 32 and adding it
> as a module parameter.
> - Removed backlog command queue handling mechanism.
> - Removed software command queue handling and instead submitting
> transaction command directly to
> hardware command queue.
> - Added tasklet structure variable in "struct pt_device".
> This is used to invoke pt_do_cmd_complete() upon receiving interrupt
> for command completion.
> - pt_core_perform_passthru() function parameters are modified and it is
> now used to submit command directly to hardware from dmaengine framew
> - Removed below structures, enums, macros and functions, as these value
> constants. Making command submission simple,
> - Removed "union pt_function" and several macros like PT_VERSION,
> PT_BYTESWAP, PT_CMD_* etc..
> - enum pt_passthru_bitwise, enum pt_passthru_byteswap, enum pt_memty
> struct pt_dma_info, struct pt_data, struct pt_mem, struct pt_passt
> struct pt_op,
>
> Links of the review comments for v10:
> 1. https://lkml.org/lkml/2021/6/8/976
> 2. https://lkml.org/lkml/2021/6/16/7
> 3. https://lkml.org/lkml/2021/6/16/65
> 4. https://lkml.org/lkml/2021/6/16/192
> 5. https://lkml.org/lkml/2021/6/16/273
> 6. https://lkml.org/lkml/2021/6/8/1698
> 7. https://lkml.org/lkml/2021/6/16/8
> 8. https://lkml.org/lkml/2021/6/9/808
>
> Links of the review comments for v7:
> 1. https://lkml.org/lkml/2020/11/18/351
> 2. https://lkml.org/lkml/2020/11/18/384
>
> Links of the review comments for v5:
> 1. https://lkml.org/lkml/2020/7/3/154
> 2. https://lkml.org/lkml/2020/8/25/431
> 3. https://lkml.org/lkml/2020/7/3/177
> 4. https://lkml.org/lkml/2020/7/3/186
>
> Links of the review comments for v5:
> 1. https://lkml.org/lkml/2020/5/4/42
> 2. https://lkml.org/lkml/2020/5/4/45
> 3. https://lkml.org/lkml/2020/5/4/38
> 4. https://lkml.org/lkml/2020/5/26/70
>
> Links of the review comments for v4:
> 1. https://lkml.org/lkml/2020/1/24/12
> 2. https://lkml.org/lkml/2020/1/24/17
>
> Links of the review comments for v2:
> 1https://lkml.org/lkml/2019/12/27/630
> 2. https://lkml.org/lkml/2020/1/3/23
> 3. https://lkml.org/lkml/2020/1/3/314
> 4. https://lkml.org/lkml/2020/1/10/100
>
> Links of the review comments for v1:
> 1. https://lkml.org/lkml/2019/9/24/490
> 2. https://lkml.org/lkml/2019/9/24/399
> 3. https://lkml.org/lkml/2019/9/24/862
> 4. https://lkml.org/lkml/2019/9/24/122
>
> Sanjay R Mehta (3):
> dmaengine: ptdma: Initial driver for the AMD PTDMA
> dmaengine: ptdma: register PTDMA controller as a DMA resource
> dmaengine: ptdma: Add debugfs entries for PTDMA
>
> MAINTAINERS | 6 +
> drivers/dma/Kconfig | 2 +
> drivers/dma/Makefile | 1 +
> drivers/dma/ptdma/Kconfig | 13 ++
> drivers/dma/ptdma/Makefile | 10 +
> drivers/dma/ptdma/ptdma-debugfs.c | 110 ++++++++++
> drivers/dma/ptdma/ptdma-dev.c | 327 ++++++++++++++++++++++++++++++
> drivers/dma/ptdma/ptdma-dmaengine.c | 389 ++++++++++++++++++++++++++++++++++++
> drivers/dma/ptdma/ptdma-pci.c | 245 +++++++++++++++++++++++
> drivers/dma/ptdma/ptdma.h | 334 +++++++++++++++++++++++++++++++
> 10 files changed, 1437 insertions(+)
> create mode 100644 drivers/dma/ptdma/Kconfig
> create mode 100644 drivers/dma/ptdma/Makefile
> create mode 100644 drivers/dma/ptdma/ptdma-debugfs.c
> create mode 100644 drivers/dma/ptdma/ptdma-dev.c
> create mode 100644 drivers/dma/ptdma/ptdma-dmaengine.c
> create mode 100644 drivers/dma/ptdma/ptdma-pci.c
> create mode 100644 drivers/dma/ptdma/ptdma.h
Hi Vinod, Greg,
I had re-sent this patch series as per your advice a month ago with all
the review feedback's addressed.
Need your guidance and feedback to get this code reviewed and up-streamed.
Thanks & Regards,
Sanjay Mehta
>
On 22-07-21, 19:27, Sanjay R Mehta wrote:
>
>
> On 6/20/2021 10:11 PM, Sanjay R Mehta wrote:
> > From: Sanjay R Mehta <[email protected]>
> >
> > This patch series add support for AMD PTDMA controller which
> > performs high bandwidth memory-to-memory and IO copy operation,
> > performs DMA transfer through queue based descriptor management.
> >
> > AMD Processor has multiple ptdma device instances with each controller
> > having single queue. The driver also adds support for for multiple PTDMA
> > instances, each device will get an unique identifier and uniquely
> > named resources.
> >
> > v10:
> > - modified ISR to return IR_HANDLED only in non-error condition.
> > - removed unnecessary prints, variables and made some cosmetic changes.
> > - removed pt_ordinal atomic variable and instead using dev_name()
> > for device name.
> > - removed the cmdlist dependency and instead using vc.desc_issued list.
> > - freeing the desc and list which was missing in the pt_terminate_all()
> > funtion.
> > - Added comment for marking PTDMA as DMA_PRIVATE.
> > - removed unused pt_debugfs_lock from debufs code.
> > - keeping same file permision for all the debug directoris.
> >
> > v9:
> > - Modified the help message in Kconfig as per Randy's comment.
> > - reverted the split of code for "pt_handle_active_desc" as there
> > was driver hang being observerd after few iterations.
> >
> > v8:
> > - splitted the code into different functions, one to find active desc
> > and second to complete and invoke callback.
> > - used FIELD_PREP & FIELD_GET instead of union struct bitfields.
> > - modified all style fixes as per the comments.
> >
> > v7:
> > - Fixed module warnings reported ( by kernel test robot <[email protected]> ).
> >
> > v6:
> > - Removed debug artifacts and made the suggested cosmetic changes.
> > - implemented and used to_pt_chan and to_pt_desc inline functions.
> > - Removed src and dst address check as framework does this.
> > - Removed devm_kcalloc() usage and used devm_kzalloc() api.
> > - Using framework debugfs directory to store dma info.
> >
> > v5:
> > - modified code to submit next tranction in ISR itself and removed the tasklet.
> > - implemented .device_synchronize API.
> > - converted debugfs code by using DEFINE_SHOW_ATTRIBUTE()
> > - using dbg_dev_root for debugfs root directory.
> > - removed dma_status from pt_dma_chan
> > - removed module parameter cmd_queue_lenght.
> > - removed global device list for multiple devics.
> > - removed code related to dynamic adding/deleting to device list
> > - removed pt_add_device and pt_del_device functions
> >
> > v4:
> > - modified DMA channel and descriptor management using virt-dma layer
> > instead of list based management.
> > - return only status of the cookie from pt_tx_status
> > - copyright year changed from 2019 to 2020
> > - removed dummy code for suspend & resume
> > - used bitmask and genmask
> >
> > v3:
> > - Fixed the sparse warnings.
> >
> > v2:
> > - Added controller description in cover letter
> > - Removed "default m" from Kconfig
> > - Replaced low_address() and high_address() functions with kernel
> > API's lower_32_bits & upper_32_bits().
> > - Removed the BH handler function pt_core_irq_bh() and instead
> > handling transaction in irq handler itself.
> > - Moved presetting of command queue registers into new function
> > "init_cmdq_regs()"
> > - Removed the kernel thread dependency to submit transaction.
> > - Increased the hardware command queue size to 32 and adding it
> > as a module parameter.
> > - Removed backlog command queue handling mechanism.
> > - Removed software command queue handling and instead submitting
> > transaction command directly to
> > hardware command queue.
> > - Added tasklet structure variable in "struct pt_device".
> > This is used to invoke pt_do_cmd_complete() upon receiving interrupt
> > for command completion.
> > - pt_core_perform_passthru() function parameters are modified and it is
> > now used to submit command directly to hardware from dmaengine framew
> > - Removed below structures, enums, macros and functions, as these value
> > constants. Making command submission simple,
> > - Removed "union pt_function" and several macros like PT_VERSION,
> > PT_BYTESWAP, PT_CMD_* etc..
> > - enum pt_passthru_bitwise, enum pt_passthru_byteswap, enum pt_memty
> > struct pt_dma_info, struct pt_data, struct pt_mem, struct pt_passt
> > struct pt_op,
> >
> > Links of the review comments for v10:
> > 1. https://lkml.org/lkml/2021/6/8/976
> > 2. https://lkml.org/lkml/2021/6/16/7
> > 3. https://lkml.org/lkml/2021/6/16/65
> > 4. https://lkml.org/lkml/2021/6/16/192
> > 5. https://lkml.org/lkml/2021/6/16/273
> > 6. https://lkml.org/lkml/2021/6/8/1698
> > 7. https://lkml.org/lkml/2021/6/16/8
> > 8. https://lkml.org/lkml/2021/6/9/808
> >
> > Links of the review comments for v7:
> > 1. https://lkml.org/lkml/2020/11/18/351
> > 2. https://lkml.org/lkml/2020/11/18/384
> >
> > Links of the review comments for v5:
> > 1. https://lkml.org/lkml/2020/7/3/154
> > 2. https://lkml.org/lkml/2020/8/25/431
> > 3. https://lkml.org/lkml/2020/7/3/177
> > 4. https://lkml.org/lkml/2020/7/3/186
> >
> > Links of the review comments for v5:
> > 1. https://lkml.org/lkml/2020/5/4/42
> > 2. https://lkml.org/lkml/2020/5/4/45
> > 3. https://lkml.org/lkml/2020/5/4/38
> > 4. https://lkml.org/lkml/2020/5/26/70
> >
> > Links of the review comments for v4:
> > 1. https://lkml.org/lkml/2020/1/24/12
> > 2. https://lkml.org/lkml/2020/1/24/17
> >
> > Links of the review comments for v2:
> > 1https://lkml.org/lkml/2019/12/27/630
> > 2. https://lkml.org/lkml/2020/1/3/23
> > 3. https://lkml.org/lkml/2020/1/3/314
> > 4. https://lkml.org/lkml/2020/1/10/100
> >
> > Links of the review comments for v1:
> > 1. https://lkml.org/lkml/2019/9/24/490
> > 2. https://lkml.org/lkml/2019/9/24/399
> > 3. https://lkml.org/lkml/2019/9/24/862
> > 4. https://lkml.org/lkml/2019/9/24/122
> >
> > Sanjay R Mehta (3):
> > dmaengine: ptdma: Initial driver for the AMD PTDMA
> > dmaengine: ptdma: register PTDMA controller as a DMA resource
> > dmaengine: ptdma: Add debugfs entries for PTDMA
> >
> > MAINTAINERS | 6 +
> > drivers/dma/Kconfig | 2 +
> > drivers/dma/Makefile | 1 +
> > drivers/dma/ptdma/Kconfig | 13 ++
> > drivers/dma/ptdma/Makefile | 10 +
> > drivers/dma/ptdma/ptdma-debugfs.c | 110 ++++++++++
> > drivers/dma/ptdma/ptdma-dev.c | 327 ++++++++++++++++++++++++++++++
> > drivers/dma/ptdma/ptdma-dmaengine.c | 389 ++++++++++++++++++++++++++++++++++++
> > drivers/dma/ptdma/ptdma-pci.c | 245 +++++++++++++++++++++++
> > drivers/dma/ptdma/ptdma.h | 334 +++++++++++++++++++++++++++++++
> > 10 files changed, 1437 insertions(+)
> > create mode 100644 drivers/dma/ptdma/Kconfig
> > create mode 100644 drivers/dma/ptdma/Makefile
> > create mode 100644 drivers/dma/ptdma/ptdma-debugfs.c
> > create mode 100644 drivers/dma/ptdma/ptdma-dev.c
> > create mode 100644 drivers/dma/ptdma/ptdma-dmaengine.c
> > create mode 100644 drivers/dma/ptdma/ptdma-pci.c
> > create mode 100644 drivers/dma/ptdma/ptdma.h
>
> Hi Vinod, Greg,
>
>
> I had re-sent this patch series as per your advice a month ago with all
> the review feedback's addressed.
>
> Need your guidance and feedback to get this code reviewed and up-streamed.
This was sent during the merge window... and right now this is in my
review queue and will be addressed shortly.
--
~Vinod
On Thu, Jul 22, 2021 at 07:27:51PM +0530, Sanjay R Mehta wrote:
>
>
> On 6/20/2021 10:11 PM, Sanjay R Mehta wrote:
> > From: Sanjay R Mehta <[email protected]>
> >
> > This patch series add support for AMD PTDMA controller which
> > performs high bandwidth memory-to-memory and IO copy operation,
> > performs DMA transfer through queue based descriptor management.
> >
> > AMD Processor has multiple ptdma device instances with each controller
> > having single queue. The driver also adds support for for multiple PTDMA
> > instances, each device will get an unique identifier and uniquely
> > named resources.
> >
> > v10:
> > - modified ISR to return IR_HANDLED only in non-error condition.
> > - removed unnecessary prints, variables and made some cosmetic changes.
> > - removed pt_ordinal atomic variable and instead using dev_name()
> > for device name.
> > - removed the cmdlist dependency and instead using vc.desc_issued list.
> > - freeing the desc and list which was missing in the pt_terminate_all()
> > funtion.
> > - Added comment for marking PTDMA as DMA_PRIVATE.
> > - removed unused pt_debugfs_lock from debufs code.
> > - keeping same file permision for all the debug directoris.
> >
> > v9:
> > - Modified the help message in Kconfig as per Randy's comment.
> > - reverted the split of code for "pt_handle_active_desc" as there
> > was driver hang being observerd after few iterations.
> >
> > v8:
> > - splitted the code into different functions, one to find active desc
> > and second to complete and invoke callback.
> > - used FIELD_PREP & FIELD_GET instead of union struct bitfields.
> > - modified all style fixes as per the comments.
> >
> > v7:
> > - Fixed module warnings reported ( by kernel test robot <[email protected]> ).
> >
> > v6:
> > - Removed debug artifacts and made the suggested cosmetic changes.
> > - implemented and used to_pt_chan and to_pt_desc inline functions.
> > - Removed src and dst address check as framework does this.
> > - Removed devm_kcalloc() usage and used devm_kzalloc() api.
> > - Using framework debugfs directory to store dma info.
> >
> > v5:
> > - modified code to submit next tranction in ISR itself and removed the tasklet.
> > - implemented .device_synchronize API.
> > - converted debugfs code by using DEFINE_SHOW_ATTRIBUTE()
> > - using dbg_dev_root for debugfs root directory.
> > - removed dma_status from pt_dma_chan
> > - removed module parameter cmd_queue_lenght.
> > - removed global device list for multiple devics.
> > - removed code related to dynamic adding/deleting to device list
> > - removed pt_add_device and pt_del_device functions
> >
> > v4:
> > - modified DMA channel and descriptor management using virt-dma layer
> > instead of list based management.
> > - return only status of the cookie from pt_tx_status
> > - copyright year changed from 2019 to 2020
> > - removed dummy code for suspend & resume
> > - used bitmask and genmask
> >
> > v3:
> > - Fixed the sparse warnings.
> >
> > v2:
> > - Added controller description in cover letter
> > - Removed "default m" from Kconfig
> > - Replaced low_address() and high_address() functions with kernel
> > API's lower_32_bits & upper_32_bits().
> > - Removed the BH handler function pt_core_irq_bh() and instead
> > handling transaction in irq handler itself.
> > - Moved presetting of command queue registers into new function
> > "init_cmdq_regs()"
> > - Removed the kernel thread dependency to submit transaction.
> > - Increased the hardware command queue size to 32 and adding it
> > as a module parameter.
> > - Removed backlog command queue handling mechanism.
> > - Removed software command queue handling and instead submitting
> > transaction command directly to
> > hardware command queue.
> > - Added tasklet structure variable in "struct pt_device".
> > This is used to invoke pt_do_cmd_complete() upon receiving interrupt
> > for command completion.
> > - pt_core_perform_passthru() function parameters are modified and it is
> > now used to submit command directly to hardware from dmaengine framew
> > - Removed below structures, enums, macros and functions, as these value
> > constants. Making command submission simple,
> > - Removed "union pt_function" and several macros like PT_VERSION,
> > PT_BYTESWAP, PT_CMD_* etc..
> > - enum pt_passthru_bitwise, enum pt_passthru_byteswap, enum pt_memty
> > struct pt_dma_info, struct pt_data, struct pt_mem, struct pt_passt
> > struct pt_op,
> >
> > Links of the review comments for v10:
> > 1. https://lkml.org/lkml/2021/6/8/976
> > 2. https://lkml.org/lkml/2021/6/16/7
> > 3. https://lkml.org/lkml/2021/6/16/65
> > 4. https://lkml.org/lkml/2021/6/16/192
> > 5. https://lkml.org/lkml/2021/6/16/273
> > 6. https://lkml.org/lkml/2021/6/8/1698
> > 7. https://lkml.org/lkml/2021/6/16/8
> > 8. https://lkml.org/lkml/2021/6/9/808
> >
> > Links of the review comments for v7:
> > 1. https://lkml.org/lkml/2020/11/18/351
> > 2. https://lkml.org/lkml/2020/11/18/384
> >
> > Links of the review comments for v5:
> > 1. https://lkml.org/lkml/2020/7/3/154
> > 2. https://lkml.org/lkml/2020/8/25/431
> > 3. https://lkml.org/lkml/2020/7/3/177
> > 4. https://lkml.org/lkml/2020/7/3/186
> >
> > Links of the review comments for v5:
> > 1. https://lkml.org/lkml/2020/5/4/42
> > 2. https://lkml.org/lkml/2020/5/4/45
> > 3. https://lkml.org/lkml/2020/5/4/38
> > 4. https://lkml.org/lkml/2020/5/26/70
> >
> > Links of the review comments for v4:
> > 1. https://lkml.org/lkml/2020/1/24/12
> > 2. https://lkml.org/lkml/2020/1/24/17
> >
> > Links of the review comments for v2:
> > 1https://lkml.org/lkml/2019/12/27/630
> > 2. https://lkml.org/lkml/2020/1/3/23
> > 3. https://lkml.org/lkml/2020/1/3/314
> > 4. https://lkml.org/lkml/2020/1/10/100
> >
> > Links of the review comments for v1:
> > 1. https://lkml.org/lkml/2019/9/24/490
> > 2. https://lkml.org/lkml/2019/9/24/399
> > 3. https://lkml.org/lkml/2019/9/24/862
> > 4. https://lkml.org/lkml/2019/9/24/122
> >
> > Sanjay R Mehta (3):
> > dmaengine: ptdma: Initial driver for the AMD PTDMA
> > dmaengine: ptdma: register PTDMA controller as a DMA resource
> > dmaengine: ptdma: Add debugfs entries for PTDMA
> >
> > MAINTAINERS | 6 +
> > drivers/dma/Kconfig | 2 +
> > drivers/dma/Makefile | 1 +
> > drivers/dma/ptdma/Kconfig | 13 ++
> > drivers/dma/ptdma/Makefile | 10 +
> > drivers/dma/ptdma/ptdma-debugfs.c | 110 ++++++++++
> > drivers/dma/ptdma/ptdma-dev.c | 327 ++++++++++++++++++++++++++++++
> > drivers/dma/ptdma/ptdma-dmaengine.c | 389 ++++++++++++++++++++++++++++++++++++
> > drivers/dma/ptdma/ptdma-pci.c | 245 +++++++++++++++++++++++
> > drivers/dma/ptdma/ptdma.h | 334 +++++++++++++++++++++++++++++++
> > 10 files changed, 1437 insertions(+)
> > create mode 100644 drivers/dma/ptdma/Kconfig
> > create mode 100644 drivers/dma/ptdma/Makefile
> > create mode 100644 drivers/dma/ptdma/ptdma-debugfs.c
> > create mode 100644 drivers/dma/ptdma/ptdma-dev.c
> > create mode 100644 drivers/dma/ptdma/ptdma-dmaengine.c
> > create mode 100644 drivers/dma/ptdma/ptdma-pci.c
> > create mode 100644 drivers/dma/ptdma/ptdma.h
>
> Hi Vinod, Greg,
>
>
> I had re-sent this patch series as per your advice a month ago with all
> the review feedback's addressed.
>
> Need your guidance and feedback to get this code reviewed and up-streamed.
That is up to the drivers/dma/ maintainer, which is Vinod, not me :)
thanks,
greg k-h
On 7/22/2021 7:40 PM, Vinod Koul wrote:
> [CAUTION: External Email]
>
> On 22-07-21, 19:27, Sanjay R Mehta wrote:
>>
>>
>> On 6/20/2021 10:11 PM, Sanjay R Mehta wrote:
>>> From: Sanjay R Mehta <[email protected]>
>>>
>>> This patch series add support for AMD PTDMA controller which
>>> performs high bandwidth memory-to-memory and IO copy operation,
>>> performs DMA transfer through queue based descriptor management.
>>>
>>> AMD Processor has multiple ptdma device instances with each controller
>>> having single queue. The driver also adds support for for multiple PTDMA
>>> instances, each device will get an unique identifier and uniquely
>>> named resources.
>>>
>>> v10:
>>> - modified ISR to return IR_HANDLED only in non-error condition.
>>> - removed unnecessary prints, variables and made some cosmetic changes.
>>> - removed pt_ordinal atomic variable and instead using dev_name()
>>> for device name.
>>> - removed the cmdlist dependency and instead using vc.desc_issued list.
>>> - freeing the desc and list which was missing in the pt_terminate_all()
>>> funtion.
>>> - Added comment for marking PTDMA as DMA_PRIVATE.
>>> - removed unused pt_debugfs_lock from debufs code.
>>> - keeping same file permision for all the debug directoris.
>>>
>>> v9:
>>> - Modified the help message in Kconfig as per Randy's comment.
>>> - reverted the split of code for "pt_handle_active_desc" as there
>>> was driver hang being observerd after few iterations.
>>>
>>> v8:
>>> - splitted the code into different functions, one to find active desc
>>> and second to complete and invoke callback.
>>> - used FIELD_PREP & FIELD_GET instead of union struct bitfields.
>>> - modified all style fixes as per the comments.
>>>
>>> v7:
>>> - Fixed module warnings reported ( by kernel test robot <[email protected]> ).
>>>
>>> v6:
>>> - Removed debug artifacts and made the suggested cosmetic changes.
>>> - implemented and used to_pt_chan and to_pt_desc inline functions.
>>> - Removed src and dst address check as framework does this.
>>> - Removed devm_kcalloc() usage and used devm_kzalloc() api.
>>> - Using framework debugfs directory to store dma info.
>>>
>>> v5:
>>> - modified code to submit next tranction in ISR itself and removed the tasklet.
>>> - implemented .device_synchronize API.
>>> - converted debugfs code by using DEFINE_SHOW_ATTRIBUTE()
>>> - using dbg_dev_root for debugfs root directory.
>>> - removed dma_status from pt_dma_chan
>>> - removed module parameter cmd_queue_lenght.
>>> - removed global device list for multiple devics.
>>> - removed code related to dynamic adding/deleting to device list
>>> - removed pt_add_device and pt_del_device functions
>>>
>>> v4:
>>> - modified DMA channel and descriptor management using virt-dma layer
>>> instead of list based management.
>>> - return only status of the cookie from pt_tx_status
>>> - copyright year changed from 2019 to 2020
>>> - removed dummy code for suspend & resume
>>> - used bitmask and genmask
>>>
>>> v3:
>>> - Fixed the sparse warnings.
>>>
>>> v2:
>>> - Added controller description in cover letter
>>> - Removed "default m" from Kconfig
>>> - Replaced low_address() and high_address() functions with kernel
>>> API's lower_32_bits & upper_32_bits().
>>> - Removed the BH handler function pt_core_irq_bh() and instead
>>> handling transaction in irq handler itself.
>>> - Moved presetting of command queue registers into new function
>>> "init_cmdq_regs()"
>>> - Removed the kernel thread dependency to submit transaction.
>>> - Increased the hardware command queue size to 32 and adding it
>>> as a module parameter.
>>> - Removed backlog command queue handling mechanism.
>>> - Removed software command queue handling and instead submitting
>>> transaction command directly to
>>> hardware command queue.
>>> - Added tasklet structure variable in "struct pt_device".
>>> This is used to invoke pt_do_cmd_complete() upon receiving interrupt
>>> for command completion.
>>> - pt_core_perform_passthru() function parameters are modified and it is
>>> now used to submit command directly to hardware from dmaengine framew
>>> - Removed below structures, enums, macros and functions, as these value
>>> constants. Making command submission simple,
>>> - Removed "union pt_function" and several macros like PT_VERSION,
>>> PT_BYTESWAP, PT_CMD_* etc..
>>> - enum pt_passthru_bitwise, enum pt_passthru_byteswap, enum pt_memty
>>> struct pt_dma_info, struct pt_data, struct pt_mem, struct pt_passt
>>> struct pt_op,
>>>
>>> Links of the review comments for v10:
>>> 1. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F8%2F976&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082849269%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=WeGA5LwGm9mnQ594VpBPAbUGZXkLZ4oup1T77fJoitc%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F16%2F7&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=z3iiY0cfRUgtA5cP2lJqwmCxICyCN4FjsRI1u4aLPVU%3D&reserved=0
>>> 3. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F16%2F65&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=TABmc6i98zw%2BpjIq0hxawCL2L%2BiQe9uJvRtajCFsR6E%3D&reserved=0
>>> 4. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F16%2F192&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=vnmjIVQfPdTaoSIAyQiA%2FjyKWY6YXnmIOuvpn3QCj%2BI%3D&reserved=0
>>> 5. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F16%2F273&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=ZtH5A19dQYiHMHQS6rVenSj2Jo7%2B9pNjC8%2B24FK5zNI%3D&reserved=0
>>> 6. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F8%2F1698&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=%2BrlAck2STVZ82dnW6MeJaSvelS7FK5sKUEdh8ftMrvc%3D&reserved=0
>>> 7. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F16%2F8&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=5EP0t9eYgx0tWUu1W8eR7MhvzGtLhJm1%2FYMvJksr5jU%3D&reserved=0
>>> 8. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2021%2F6%2F9%2F808&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=WzeuQCeW2q%2FU8rEZybHezhBnYH9yG0Z7PV5dH4KeK28%3D&reserved=0
>>>
>>> Links of the review comments for v7:
>>> 1. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F11%2F18%2F351&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=0uFWTom212inntZl3C2jmQ0EYVRG8hXlDKDkMdxToAA%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F11%2F18%2F384&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=agZRP0WYYpWO4c1AoVSmbi0%2BPv%2FHYIsmknPkDUqwcuU%3D&reserved=0
>>>
>>> Links of the review comments for v5:
>>> 1. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F7%2F3%2F154&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=rhXLYx8qk6Uwt7hYiUv8zZFz%2BAekntk5x7%2BF7yrDi%2Fg%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F8%2F25%2F431&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=qeIQAK%2FtcrsJjJLftPVp1h2jAewJxcUOFWYiCsBFgC8%3D&reserved=0
>>> 3. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F7%2F3%2F177&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=DM3NiBmaXQRbe7dw4vyDwaWtkGB9IMDBkM9ieSzJ%2BlM%3D&reserved=0
>>> 4. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F7%2F3%2F186&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=BU8wRPlcKJXRSVbNO9o2a4WzPIRCBj%2BHVqK9XWWBUog%3D&reserved=0
>>>
>>> Links of the review comments for v5:
>>> 1. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F5%2F4%2F42&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=%2FLzrpW49oJQvOojpJcnyEPH6886BfeBdbPnAv8Gzyxk%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F5%2F4%2F45&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=fNCM6mogdUJtziiyTS5VeaigZcOdTRovTiAgLN7eNlo%3D&reserved=0
>>> 3. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F5%2F4%2F38&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082859237%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=uZnxL%2FzXr8D6wgZffIZQpEiXtQfJTlAWtJ5X5k%2Bxm1c%3D&reserved=0
>>> 4. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F5%2F26%2F70&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=bTNsPcdGciOdNnj7%2FFCOBHc%2FevZBQAqhyJZAkHt1iLI%3D&reserved=0
>>>
>>> Links of the review comments for v4:
>>> 1. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F1%2F24%2F12&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=Tox6tf88tSPVA%2Fq5y6ssuNlskxK3cgBpynJTtHEpPOw%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F1%2F24%2F17&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=cWe5KvRLulu55PlsxwoQwJAZFbgoV0H8mLVqCe5eePw%3D&reserved=0
>>>
>>> Links of the review comments for v2:
>>> 1https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2019%2F12%2F27%2F630&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=lSo%2BPMBxKI5nB%2FWXscbJBUvaCn7n7TfbozKhPhhDviU%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F1%2F3%2F23&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=e371CMeEbKW1K2%2Fn%2BukG0DU5U9x2LsbmgFrRrva25CM%3D&reserved=0
>>> 3. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F1%2F3%2F314&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=IJ2xiQSIH1jfDxDKuLg9F4bjJJGgxXJq5jHBNWeSAV8%3D&reserved=0
>>> 4. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2020%2F1%2F10%2F100&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=mDUnVUEREIpoUeYUeACYMQSzAon4t9652Uj4PQCrwPQ%3D&reserved=0
>>>
>>> Links of the review comments for v1:
>>> 1. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2019%2F9%2F24%2F490&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=MvwpsDwevzgU8Qn3zc29u8hjhFBZIAFZJy7lSYcegnQ%3D&reserved=0
>>> 2. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2019%2F9%2F24%2F399&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=6v6SMJY%2BY6RfGty9QxG72fsQ%2BV7NfJm%2B8Dh3cVIx%2BtQ%3D&reserved=0
>>> 3. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2019%2F9%2F24%2F862&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=7cY3MBVmXSQ40wVpdVWDDYqTV3Z%2FzCB0j%2ByNeiIO3FA%3D&reserved=0
>>> 4. https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flkml.org%2Flkml%2F2019%2F9%2F24%2F122&data=04%7C01%7CSanju.Mehta%40amd.com%7C775e5c3c08a24a2a7dc608d94d1a67e3%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637625598082869186%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=IoLPSuBMdz8T8Qyyknb2%2FJzzV8o62BqzkrQ6kirzOIM%3D&reserved=0
>>>
>>> Sanjay R Mehta (3):
>>> dmaengine: ptdma: Initial driver for the AMD PTDMA
>>> dmaengine: ptdma: register PTDMA controller as a DMA resource
>>> dmaengine: ptdma: Add debugfs entries for PTDMA
>>>
>>> MAINTAINERS | 6 +
>>> drivers/dma/Kconfig | 2 +
>>> drivers/dma/Makefile | 1 +
>>> drivers/dma/ptdma/Kconfig | 13 ++
>>> drivers/dma/ptdma/Makefile | 10 +
>>> drivers/dma/ptdma/ptdma-debugfs.c | 110 ++++++++++
>>> drivers/dma/ptdma/ptdma-dev.c | 327 ++++++++++++++++++++++++++++++
>>> drivers/dma/ptdma/ptdma-dmaengine.c | 389 ++++++++++++++++++++++++++++++++++++
>>> drivers/dma/ptdma/ptdma-pci.c | 245 +++++++++++++++++++++++
>>> drivers/dma/ptdma/ptdma.h | 334 +++++++++++++++++++++++++++++++
>>> 10 files changed, 1437 insertions(+)
>>> create mode 100644 drivers/dma/ptdma/Kconfig
>>> create mode 100644 drivers/dma/ptdma/Makefile
>>> create mode 100644 drivers/dma/ptdma/ptdma-debugfs.c
>>> create mode 100644 drivers/dma/ptdma/ptdma-dev.c
>>> create mode 100644 drivers/dma/ptdma/ptdma-dmaengine.c
>>> create mode 100644 drivers/dma/ptdma/ptdma-pci.c
>>> create mode 100644 drivers/dma/ptdma/ptdma.h
>>
>> Hi Vinod, Greg,
>>
>>
>> I had re-sent this patch series as per your advice a month ago with all
>> the review feedback's addressed.
>>
>> Need your guidance and feedback to get this code reviewed and up-streamed.
>
> This was sent during the merge window... and right now this is in my
> review queue and will be addressed shortly.
>
Ok sure. Thank you!
> --
> ~Vinod
>
On 20-06-21, 11:41, Sanjay R Mehta wrote:
> +static irqreturn_t pt_core_irq_handler(int irq, void *data)
> +{
> + struct pt_device *pt = data;
> + struct pt_cmd_queue *cmd_q = &pt->cmd_q;
> + u32 status;
> + bool err = true;
> +
> + pt_core_disable_queue_interrupts(pt);
> +
> + status = ioread32(cmd_q->reg_interrupt_status);
> + if (status) {
> + cmd_q->int_status = status;
> + cmd_q->q_status = ioread32(cmd_q->reg_status);
> + cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
> +
> + /* On error, only save the first error value */
> + if ((status & INT_ERROR) && !cmd_q->cmd_error) {
> + cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
> + err = false;
> + }
> +
> + /* Acknowledge the interrupt */
> + iowrite32(status, cmd_q->reg_interrupt_status);
> + }
> +
> + pt_core_enable_queue_interrupts(pt);
> +
> + return err ? IRQ_HANDLED : IRQ_NONE;
On err you should not return IRQ_NONE. IRQ_NONE means "interrupt was not
from this device or was not handled"
Error is handled here!
> +static struct pt_device *pt_alloc_struct(struct device *dev)
> +{
> + struct pt_device *pt;
> +
> + pt = devm_kzalloc(dev, sizeof(*pt), GFP_KERNEL);
> +
> + if (!pt)
> + return NULL;
> + pt->dev = dev;
> +
> + INIT_LIST_HEAD(&pt->cmd);
> +
> + snprintf(pt->name, MAX_PT_NAME_LEN, "pt-%s", dev_name(dev));
what is this name used for? Why not use dev_name everywhere?
> +static int pt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> +{
> + struct pt_device *pt;
> + struct pt_msix *pt_msix;
> + struct device *dev = &pdev->dev;
> + void __iomem * const *iomap_table;
> + int bar_mask;
> + int ret = -ENOMEM;
> +
> + pt = pt_alloc_struct(dev);
> + if (!pt)
> + goto e_err;
> +
> + pt_msix = devm_kzalloc(dev, sizeof(*pt_msix), GFP_KERNEL);
> + if (!pt_msix)
> + goto e_err;
> +
> + pt->pt_msix = pt_msix;
> + pt->dev_vdata = (struct pt_dev_vdata *)id->driver_data;
> + if (!pt->dev_vdata) {
> + ret = -ENODEV;
> + dev_err(dev, "missing driver data\n");
> + goto e_err;
> + }
> +
> + ret = pcim_enable_device(pdev);
> + if (ret) {
> + dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
> + goto e_err;
> + }
> +
> + bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
> + ret = pcim_iomap_regions(pdev, bar_mask, "ptdma");
> + if (ret) {
> + dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
> + goto e_err;
> + }
> +
> + iomap_table = pcim_iomap_table(pdev);
> + if (!iomap_table) {
> + dev_err(dev, "pcim_iomap_table failed\n");
> + ret = -ENOMEM;
> + goto e_err;
> + }
> +
> + pt->io_regs = iomap_table[pt->dev_vdata->bar];
> + if (!pt->io_regs) {
> + dev_err(dev, "ioremap failed\n");
> + ret = -ENOMEM;
> + goto e_err;
> + }
> +
> + ret = pt_get_irqs(pt);
> + if (ret)
> + goto e_err;
> +
> + pci_set_master(pdev);
> +
> + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
> + if (ret) {
> + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
> + if (ret) {
> + dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
> + ret);
> + goto e_err;
> + }
> + }
> +
> + dev_set_drvdata(dev, pt);
> +
> + if (pt->dev_vdata)
> + ret = pt_core_init(pt);
> +
> + if (ret)
> + goto e_err;
> +
> + return 0;
> +
> +e_err:
> + dev_err(dev, "initialization failed\n");
log the err code, that is very useful!
> + /* Register addresses for queue */
> + void __iomem *reg_control;
> + void __iomem *reg_tail_lo;
> + void __iomem *reg_head_lo;
> + void __iomem *reg_int_enable;
> + void __iomem *reg_interrupt_status;
> + void __iomem *reg_status;
> + void __iomem *reg_int_status;
> + void __iomem *reg_dma_status;
> + void __iomem *reg_dma_read_status;
> + void __iomem *reg_dma_write_status;
this looks like pointer to registers, wont it make sense to keep base
ptr and use offset to read..?
Looking at pt_init_cmdq_regs(), i think that seems to be the case. Why
waste so much memory by having so many pointers?
> + u32 qcontrol; /* Cached control register */
> +
> + /* Status values from job */
> + u32 int_status;
> + u32 q_status;
> + u32 q_int_status;
> + u32 cmd_error;
> +} ____cacheline_aligned;
> +
> +struct pt_device {
> + struct list_head entry;
> +
> + unsigned int ord;
Unused?
--
~Vinod
On 20-06-21, 11:41, Sanjay R Mehta wrote:
> From: Sanjay R Mehta <[email protected]>
>
> Register ptdma queue to Linux dmaengine framework as general-purpose
> DMA channels.
Mostly looks good, one question below:
> +static struct pt_dma_desc *pt_alloc_dma_desc(struct pt_dma_chan *chan,
> + unsigned long flags)
> +{
> + struct pt_dma_desc *desc;
> +
> + desc = kmem_cache_zalloc(chan->pt->dma_desc_cache, GFP_NOWAIT);
> + if (!desc)
> + return NULL;
> +
> + vchan_tx_prep(&chan->vc, &desc->vd, flags);
> +
> + desc->pt = chan->pt;
> + desc->issued_to_hw = 0;
> + desc->status = DMA_IN_PROGRESS;
where is this descriptor freed?
--
~Vinod
On 7/28/2021 11:25 AM, Vinod Koul wrote:
> [CAUTION: External Email]
>
Thanks Vinod for the feedback.
> On 20-06-21, 11:41, Sanjay R Mehta wrote:
>
>> +static irqreturn_t pt_core_irq_handler(int irq, void *data)
>> +{
>> + struct pt_device *pt = data;
>> + struct pt_cmd_queue *cmd_q = &pt->cmd_q;
>> + u32 status;
>> + bool err = true;
>> +
>> + pt_core_disable_queue_interrupts(pt);
>> +
>> + status = ioread32(cmd_q->reg_interrupt_status);
>> + if (status) {
>> + cmd_q->int_status = status;
>> + cmd_q->q_status = ioread32(cmd_q->reg_status);
>> + cmd_q->q_int_status = ioread32(cmd_q->reg_int_status);
>> +
>> + /* On error, only save the first error value */
>> + if ((status & INT_ERROR) && !cmd_q->cmd_error) {
>> + cmd_q->cmd_error = CMD_Q_ERROR(cmd_q->q_status);
>> + err = false;
>> + }
>> +
>> + /* Acknowledge the interrupt */
>> + iowrite32(status, cmd_q->reg_interrupt_status);
>> + }
>> +
>> + pt_core_enable_queue_interrupts(pt);
>> +
>> + return err ? IRQ_HANDLED : IRQ_NONE;
>
> On err you should not return IRQ_NONE. IRQ_NONE means "interrupt was not
> from this device or was not handled"
>
> Error is handled here!
>
Got it. Sure, will change it.
>> +static struct pt_device *pt_alloc_struct(struct device *dev)
>> +{
>> + struct pt_device *pt;
>> +
>> + pt = devm_kzalloc(dev, sizeof(*pt), GFP_KERNEL);
>> +
>> + if (!pt)
>> + return NULL;
>> + pt->dev = dev;
>> +
>> + INIT_LIST_HEAD(&pt->cmd);
>> +
>> + snprintf(pt->name, MAX_PT_NAME_LEN, "pt-%s", dev_name(dev));
>
> what is this name used for? Why not use dev_name everywhere?
>
Sure, will change it to dev_name.
>> +static int pt_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>> +{
>> + struct pt_device *pt;
>> + struct pt_msix *pt_msix;
>> + struct device *dev = &pdev->dev;
>> + void __iomem * const *iomap_table;
>> + int bar_mask;
>> + int ret = -ENOMEM;
>> +
>> + pt = pt_alloc_struct(dev);
>> + if (!pt)
>> + goto e_err;
>> +
>> + pt_msix = devm_kzalloc(dev, sizeof(*pt_msix), GFP_KERNEL);
>> + if (!pt_msix)
>> + goto e_err;
>> +
>> + pt->pt_msix = pt_msix;
>> + pt->dev_vdata = (struct pt_dev_vdata *)id->driver_data;
>> + if (!pt->dev_vdata) {
>> + ret = -ENODEV;
>> + dev_err(dev, "missing driver data\n");
>> + goto e_err;
>> + }
>> +
>> + ret = pcim_enable_device(pdev);
>> + if (ret) {
>> + dev_err(dev, "pcim_enable_device failed (%d)\n", ret);
>> + goto e_err;
>> + }
>> +
>> + bar_mask = pci_select_bars(pdev, IORESOURCE_MEM);
>> + ret = pcim_iomap_regions(pdev, bar_mask, "ptdma");
>> + if (ret) {
>> + dev_err(dev, "pcim_iomap_regions failed (%d)\n", ret);
>> + goto e_err;
>> + }
>> +
>> + iomap_table = pcim_iomap_table(pdev);
>> + if (!iomap_table) {
>> + dev_err(dev, "pcim_iomap_table failed\n");
>> + ret = -ENOMEM;
>> + goto e_err;
>> + }
>> +
>> + pt->io_regs = iomap_table[pt->dev_vdata->bar];
>> + if (!pt->io_regs) {
>> + dev_err(dev, "ioremap failed\n");
>> + ret = -ENOMEM;
>> + goto e_err;
>> + }
>> +
>> + ret = pt_get_irqs(pt);
>> + if (ret)
>> + goto e_err;
>> +
>> + pci_set_master(pdev);
>> +
>> + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48));
>> + if (ret) {
>> + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
>> + if (ret) {
>> + dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n",
>> + ret);
>> + goto e_err;
>> + }
>> + }
>> +
>> + dev_set_drvdata(dev, pt);
>> +
>> + if (pt->dev_vdata)
>> + ret = pt_core_init(pt);
>> +
>> + if (ret)
>> + goto e_err;
>> +
>> + return 0;
>> +
>> +e_err:
>> + dev_err(dev, "initialization failed\n");
>
> log the err code, that is very useful!
>
>> + /* Register addresses for queue */
>> + void __iomem *reg_control;
>> + void __iomem *reg_tail_lo;
>> + void __iomem *reg_head_lo;
>> + void __iomem *reg_int_enable;
>> + void __iomem *reg_interrupt_status;
>> + void __iomem *reg_status;
>> + void __iomem *reg_int_status;
>> + void __iomem *reg_dma_status;
>> + void __iomem *reg_dma_read_status;
>> + void __iomem *reg_dma_write_status;
>
> this looks like pointer to registers, wont it make sense to keep base
> ptr and use offset to read..?
>
> Looking at pt_init_cmdq_regs(), i think that seems to be the case. Why
> waste so much memory by having so many pointers?
>
Yes, you are right. I will make this changes.
>
>> + u32 qcontrol; /* Cached control register */
>> +
>> + /* Status values from job */
>> + u32 int_status;
>> + u32 q_status;
>> + u32 q_int_status;
>> + u32 cmd_error;
>> +} ____cacheline_aligned;
>> +
>> +struct pt_device {
>> + struct list_head entry;
>> +
>> + unsigned int ord;
>
> Unused?
>
Sure. Will remove it.
> --
> ~Vinod
>
On 7/28/2021 11:45 AM, Vinod Koul wrote:
> [CAUTION: External Email]
>
> On 20-06-21, 11:41, Sanjay R Mehta wrote:
>> From: Sanjay R Mehta <[email protected]>
>>
>> Register ptdma queue to Linux dmaengine framework as general-purpose
>> DMA channels.
>
> Mostly looks good, one question below:
>
>> +static struct pt_dma_desc *pt_alloc_dma_desc(struct pt_dma_chan *chan,
>> + unsigned long flags)
>> +{
>> + struct pt_dma_desc *desc;
>> +
>> + desc = kmem_cache_zalloc(chan->pt->dma_desc_cache, GFP_NOWAIT);
>> + if (!desc)
>> + return NULL;
>> +
>> + vchan_tx_prep(&chan->vc, &desc->vd, flags);
>> +
>> + desc->pt = chan->pt;
>> + desc->issued_to_hw = 0;
>> + desc->status = DMA_IN_PROGRESS;
>
> where is this descriptor freed?
>
This descriptor is freed in the pt_do_cleanup() function.
pt_do_cleanup() is set as a callback routine for "chan->vc.desc_free" in
the init code.
- Sanjay.
> --
> ~Vinod
>