Add AMD MDB Endpoint and non-LL mode Support
Subsystems (3)
v4 cover Add AMD MDB Endpoint and non-LL mode Support
This series of patch support the following:
- AMD MDB Endpoint Support, as part of this patch following are added:
o AMD supported device ID and vendor ID (Xilinx)
o AMD MDB specific driver data
o AMD specific VSEC capabilities to retrieve the base of phys address of MDB side DDR
o Logic to assign the offsets to LL and data blocks if more number of channels are enabled than configured in the given pci_data struct.
- Addition of non-LL mode
o The IP supported non-LL mode functions
o Flexibility to choose non-LL mode via dma_slave_config param peripheral_config, by the client
o Allow IP utilization if LL mode is not available
Devendra K Verma (2):
dmaengine: dw-edma: Add AMD MDB Endpoint Support
dmaengine: dw-edma: Add non-LL mode
Devendra K Verma (2):
dmaengine: dw-edma: Add AMD MDB Endpoint Support
dmaengine: dw-edma: Add non-LL mode
drivers/dma/dw-edma/dw-edma-core.c | 38 ++++++-- drivers/dma/dw-edma/dw-edma-core.h | 1 + drivers/dma/dw-edma/dw-edma-pcie.c | 160 ++++++++++++++++++++++++++++++++-- drivers/dma/dw-edma/dw-hdma-v0-core.c | 62 ++++++++++++- include/linux/dma/edma.h | 1 + 5 files changed, 248 insertions(+), 14 deletions(-)
Signature · 1 line
1.8.3.1
PATCH RESEND v4 1/2 dmaengine: dw-edma: Add AMD MDB Endpoint Support
AMD MDB PCIe endpoint support. For AMD specific support added the following
- AMD supported PCIe Device IDs and Vendor ID (Xilinx).
- AMD MDB specific driver data
- AMD MDB specific VSEC capability to retrieve the device DDR base address.
---
Changes in v4:
Configured 8 read and 8 write channels for Xilinx vendor Added checks to validate vendor ID for vendor specific vsec id.
Added Xilinx specific vendor id for vsec specific to Xilinx Added the LL and data region offsets, size as input params to function dw_edma_set_chan_region_offset().
Moved the LL and data region offsets assignment to function for Xilinx specific case.
Corrected comments.
Changes in v3:
Corrected a typo when assigning AMD (Xilinx) vsec id macro and condition check.
Changes in v2:
Reverted the devmem_phys_off type to u64. Renamed the function appropriately to suit the functionality for setting the LL & data region offsets.
Changes in v1:
Removed the pci device id from pci_ids.h file.
Added the vendor id macro as per the suggested method. Changed the type of the newly added devmem_phys_off variable. Added to logic to assign offsets for LL and data region blocks in case more number of channels are enabled than given in amd_mdb_data struct.
--- drivers/dma/dw-edma/dw-edma-pcie.c | 130 ++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-)
drivers/dma/dw-edma/dw-edma-pcie.c +128 -2
@@ -17,12 +17,23 @@#include "dw-edma-core.h" +/* Synopsys */ #define DW_PCIE_VSEC_DMA_ID 0x6#define DW_PCIE_VSEC_DMA_BAR GENMASK(10, 8)#define DW_PCIE_VSEC_DMA_MAP GENMASK(2, 0)#define DW_PCIE_VSEC_DMA_WR_CH GENMASK(9, 0)#define DW_PCIE_VSEC_DMA_RD_CH GENMASK(25, 16) +/* AMD MDB (Xilinx) specific defines */ +#define DW_PCIE_XILINX_MDB_VSEC_DMA_ID 0x6 +#define DW_PCIE_XILINX_MDB_VSEC_ID 0x20 +#define PCI_DEVICE_ID_AMD_MDB_B054 0xb054 +#define DW_PCIE_AMD_MDB_INVALID_ADDR (~0ULL) +#define DW_PCIE_XILINX_LL_OFF_GAP 0x200000 +#define DW_PCIE_XILINX_LL_SIZE 0x800 +#define DW_PCIE_XILINX_DT_OFF_GAP 0x100000 +#define DW_PCIE_XILINX_DT_SIZE 0x800 +#define DW_BLOCK (a, b, c) \ { \ .bar = a, \
@@ -50,6 +61,7 @@ struct dw_edma_pcie_data {u8 irqs;u16 wr_ch_cnt;u16 rd_ch_cnt; +u64 devmem_phys_off; };static const struct dw_edma_pcie_data snps_edda_data = {
@@ -90,6 +102,64 @@ struct dw_edma_pcie_data { .rd_ch_cnt = 2, }; +static const struct dw_edma_pcie_data amd_mdb_data = { +/* MDB registers location */ + .rg.bar =BAR_0 , + .rg.off =0x00001000 ,/* 4 Kbytes */ + .rg.sz =0x00002000 ,/* 8 Kbytes */ + +/* Other */ + .mf =EDMA_MF_HDMA_NATIVE , + .irqs =1 , + .wr_ch_cnt =8 , + .rd_ch_cnt =8 , +}; + +static void dw_edma_set_chan_region_offset (struct dw_edma_pcie_data *pdata, +enum pci_barno bar,off_t start_off, +off_t ll_off_gap,size_t ll_size, +off_t dt_off_gap,size_t dt_size) +{ +u16 i; +off_t off; +u16 wr_ch = pdata->wr_ch_cnt; +u16 rd_ch = pdata->rd_ch_cnt; + + off = start_off; + +/* Write channel LL region */ +for (i =0 ; i < wr_ch; i++) { + pdata->ll_wr[i].bar = bar; + pdata->ll_wr[i].off = off; + pdata->ll_wr[i].sz = ll_size; + off += ll_off_gap; + } + +/* Read channel LL region */ +for (i =0 ; i < rd_ch; i++) { + pdata->ll_rd[i].bar = bar; + pdata->ll_rd[i].off = off; + pdata->ll_rd[i].sz = ll_size; + off += ll_off_gap; + } + +/* Write channel data region */ +for (i =0 ; i < wr_ch; i++) { + pdata->dt_wr[i].bar = bar; + pdata->dt_wr[i].off = off; + pdata->dt_wr[i].sz = dt_size; + off += dt_off_gap; + } + +/* Read channel data region */ +for (i =0 ; i < rd_ch; i++) { + pdata->dt_rd[i].bar = bar; + pdata->dt_rd[i].off = off; + pdata->dt_rd[i].sz = dt_size; + off += dt_off_gap; + } +} +static int dw_edma_pcie_irq_vector (struct device *dev,unsigned int nr) {return pci_irq_vector (to_pci_dev (dev), nr);
@@ -120,9 +190,24 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev,u32 val, map;u16 vsec;u64 off; +int cap; - vsec =pci_find_vsec_capability (pdev,PCI_VENDOR_ID_SYNOPSYS , -DW_PCIE_VSEC_DMA_ID ); +/* +* Synopsys and AMD (Xilinx) use the same VSEC ID for the purpose +* of map, channel counts, etc. +*/ +switch (pdev->vendor) { +case PCI_VENDOR_ID_SYNOPSYS : + cap =DW_PCIE_VSEC_DMA_ID ; +break ; +case PCI_VENDOR_ID_XILINX : + cap =DW_PCIE_XILINX_MDB_VSEC_DMA_ID ; +break ; +default : +return ; + } + + vsec =pci_find_vsec_capability (pdev, pdev->vendor, cap);if (!vsec)return ;
@@ -155,6 +240,24 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, off <<=32 ; off |= val; pdata->rg.off = off; + +/* Xilinx specific VSEC capability */ + vsec =pci_find_vsec_capability (pdev,PCI_VENDOR_ID_XILINX , +DW_PCIE_XILINX_MDB_VSEC_ID ); +if (!vsec) +return ; + +pci_read_config_dword (pdev, vsec +PCI_VNDR_HEADER , &val); +if (PCI_VNDR_HEADER_ID (val) !=0x20 || +PCI_VNDR_HEADER_REV (val) !=0x1 ) +return ; + +pci_read_config_dword (pdev, vsec +0xc , &val); + off = val; +pci_read_config_dword (pdev, vsec +0x8 , &val); + off <<=32 ; + off |= val; + pdata->devmem_phys_off = off; } static int dw_edma_pcie_probe(struct pci_dev *pdev,
@@ -179,6 +282,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, }memcpy (vsec_data, pdata,sizeof (struct dw_edma_pcie_data )); + vsec_data->devmem_phys_off =DW_PCIE_AMD_MDB_INVALID_ADDR ;/* * Tries to find if exists a PCIe Vendor-Specific Extended Capability
@@ -186,6 +290,26 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,*/ dw_edma_pcie_get_vsec_dma_data (pdev, vsec_data); +if (pdev->vendor ==PCI_VENDOR_ID_XILINX ) { +/* +* There is no valid address found for the LL memory +* space on the device side. +*/ +if (vsec_data->devmem_phys_off ==DW_PCIE_AMD_MDB_INVALID_ADDR ) +return -EINVAL ; + +/* +* Configure the channel LL and data blocks if number of +* channels enabled in VSEC capability are more than the +* channels configured in amd_mdb_data. +*/ +dw_edma_set_chan_region_offset (vsec_data,BAR_2 ,0 , +DW_PCIE_XILINX_LL_OFF_GAP , +DW_PCIE_XILINX_LL_SIZE , +DW_PCIE_XILINX_DT_OFF_GAP , +DW_PCIE_XILINX_DT_SIZE ); + } +/* Mapping PCI BAR regions */ mask =BIT (vsec_data->rg.bar);for (i =0 ; i < vsec_data->wr_ch_cnt; i++) {
@@ -367,6 +491,8 @@ static void dw_edma_pcie_remove(struct pci_dev *pdev)static const struct pci_device_id dw_edma_pcie_id_table[] = { {PCI_DEVICE_DATA (SYNOPSYS ,EDDA , &snps_edda_data) }, + {PCI_VDEVICE (XILINX ,PCI_DEVICE_ID_AMD_MDB_B054 ), + (kernel_ulong_t)&amd_mdb_data }, { } };MODULE_DEVICE_TABLE (pci, dw_edma_pcie_id_table);
Signature · 1 line
1.8.3.1
Manivannan Sadhasivam
maintainerRe: [PATCH RESEND v4 1/2] dmaengine: dw-edma: Add AMD MDB Endpoint Support
Quoted 92 lines · Devendra K Verma
AMD MDB PCIe endpoint support. For AMD specific support added the following
- AMD supported PCIe Device IDs and Vendor ID (Xilinx).
- AMD MDB specific driver data
- AMD MDB specific VSEC capability to retrieve the device DDR base address.Signed-off-by Devendra K Verma <[email protected]>---
Changes in v4:
Configured 8 read and 8 write channels for Xilinx vendor Added checks to validate vendor ID for vendor specific vsec id.
Added Xilinx specific vendor id for vsec specific to Xilinx Added the LL and data region offsets, size as input params to functiondw_edma_set_chan_region_offset().
Moved the LL and data region offsets assignment to function for Xilinx specific case.
Corrected comments.Changes in v3:
Corrected a typo when assigning AMD (Xilinx) vsec id macro and condition check.Changes in v2:
Reverted thedevmem_phys_offtype to u64. Renamed the function appropriately to suit the functionality for setting the LL & data region offsets.Changes in v1:
Removed the pci device id frompci_ids.hfile.
Added the vendor id macro as per the suggested method. Changed the type of the newly addeddevmem_phys_offvariable. Added to logic to assign offsets for LL and data region blocks in case more number of channels are enabled than given inamd_mdb_datastruct.--- drivers/dma/dw-edma/dw-edma-pcie.c | 130 ++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-)drivers/dma/dw-edma/dw-edma-pcie.c +24
-0@@ -17,12 +17,23 @@#include "dw-edma-core.h" +/* Synopsys */ #define DW_PCIE_VSEC_DMA_ID 0x6#define DW_PCIE_VSEC_DMA_BAR GENMASK(10, 8)#define DW_PCIE_VSEC_DMA_MAP GENMASK(2, 0)#define DW_PCIE_VSEC_DMA_WR_CH GENMASK(9, 0)#define DW_PCIE_VSEC_DMA_RD_CH GENMASK(25, 16) +/* AMD MDB (Xilinx) specific defines */ +#define DW_PCIE_XILINX_MDB_VSEC_DMA_ID 0x6 +#define DW_PCIE_XILINX_MDB_VSEC_ID 0x20 +#define PCI_DEVICE_ID_AMD_MDB_B054 0xb054 +#define DW_PCIE_AMD_MDB_INVALID_ADDR (~0ULL) +#define DW_PCIE_XILINX_LL_OFF_GAP 0x200000 +#define DW_PCIE_XILINX_LL_SIZE 0x800 +#define DW_PCIE_XILINX_DT_OFF_GAP 0x100000 +#define DW_PCIE_XILINX_DT_SIZE 0x800 +#define DW_BLOCK (a, b, c) \ { \ .bar = a, \@@ -50,6 +61,7 @@ struct dw_edma_pcie_data {u8 irqs;u16 wr_ch_cnt;u16 rd_ch_cnt; +u64 devmem_phys_off; };static const struct dw_edma_pcie_data snps_edda_data = {@@ -90,6 +102,64 @@ struct dw_edma_pcie_data { .rd_ch_cnt = 2, }; +static const struct dw_edma_pcie_data amd_mdb_data = { +/* MDB registers location */ + .rg.bar =BAR_0 , + .rg.off =0x00001000 ,/* 4 Kbytes */ + .rg.sz =0x00002000 ,/* 8 Kbytes */ + +/* Other */ + .mf =EDMA_MF_HDMA_NATIVE , + .irqs =1 , + .wr_ch_cnt =8 , + .rd_ch_cnt =8 , +};
drivers/dma/dw-edma/dw-edma-pcie.c struct dw_edma_pcie_data { · line 126
Quoted 10 lines
drivers/dma/dw-edma/dw-edma-pcie.c +10
-0+ +static void dw_edma_set_chan_region_offset (struct dw_edma_pcie_data *pdata, +enum pci_barno bar,off_t start_off, +off_t ll_off_gap,size_t ll_size, +off_t dt_off_gap,size_t dt_size) +{ +u16 i; +off_t off; +u16 wr_ch = pdata->wr_ch_cnt; +u16 rd_ch = pdata->rd_ch_cnt;
Reverse Xmas order please.
Quoted 70 lines
drivers/dma/dw-edma/dw-edma-pcie.c +53
-2+ + off = start_off; + +/* Write channel LL region */ +for (i =0 ; i < wr_ch; i++) { + pdata->ll_wr[i].bar = bar; + pdata->ll_wr[i].off = off; + pdata->ll_wr[i].sz = ll_size; + off += ll_off_gap; + } + +/* Read channel LL region */ +for (i =0 ; i < rd_ch; i++) { + pdata->ll_rd[i].bar = bar; + pdata->ll_rd[i].off = off; + pdata->ll_rd[i].sz = ll_size; + off += ll_off_gap; + } + +/* Write channel data region */ +for (i =0 ; i < wr_ch; i++) { + pdata->dt_wr[i].bar = bar; + pdata->dt_wr[i].off = off; + pdata->dt_wr[i].sz = dt_size; + off += dt_off_gap; + } + +/* Read channel data region */ +for (i =0 ; i < rd_ch; i++) { + pdata->dt_rd[i].bar = bar; + pdata->dt_rd[i].off = off; + pdata->dt_rd[i].sz = dt_size; + off += dt_off_gap; + } +} +static int dw_edma_pcie_irq_vector (struct device *dev,unsigned int nr) {return pci_irq_vector (to_pci_dev (dev), nr);@@ -120,9 +190,24 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev,u32 val, map;u16 vsec;u64 off; +int cap; - vsec =pci_find_vsec_capability (pdev,PCI_VENDOR_ID_SYNOPSYS , -DW_PCIE_VSEC_DMA_ID ); +/* +* Synopsys and AMD (Xilinx) use the same VSEC ID for the purpose +* of map, channel counts, etc. +*/ +switch (pdev->vendor) { +case PCI_VENDOR_ID_SYNOPSYS : + cap =DW_PCIE_VSEC_DMA_ID ; +break ; +case PCI_VENDOR_ID_XILINX : + cap =DW_PCIE_XILINX_MDB_VSEC_DMA_ID ; +break ; +default : +return ; + } + + vsec =pci_find_vsec_capability (pdev, pdev->vendor, cap);if (!vsec)return ;@@ -155,6 +240,24 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, off <<=32 ; off |= val; pdata->rg.off = off;
drivers/dma/dw-edma/dw-edma-pcie.c static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, · line 252
Quoted 10 lines
drivers/dma/dw-edma/dw-edma-pcie.c +10
-0+ +/* Xilinx specific VSEC capability */ + vsec =pci_find_vsec_capability (pdev,PCI_VENDOR_ID_XILINX , +DW_PCIE_XILINX_MDB_VSEC_ID ); +if (!vsec) +return ; + +pci_read_config_dword (pdev, vsec +PCI_VNDR_HEADER , &val); +if (PCI_VNDR_HEADER_ID (val) !=0x20 || +PCI_VNDR_HEADER_REV (val) !=0x1 )
Can you have definitions for these header and rev IDs?
drivers/dma/dw-edma/dw-edma-pcie.c static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, · line 257
Quoted 5 lines
drivers/dma/dw-edma/dw-edma-pcie.c +5
-0+return ; + +pci_read_config_dword (pdev, vsec +0xc , &val); + off = val; +pci_read_config_dword (pdev, vsec +0x8 , &val);
Same of these offsets as well.
Quoted 15 lines
drivers/dma/dw-edma/dw-edma-pcie.c +4
-0+ off <<=32 ; + off |= val; + pdata->devmem_phys_off = off; } static int dw_edma_pcie_probe(struct pci_dev *pdev,@@ -179,6 +282,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, }memcpy (vsec_data, pdata,sizeof (struct dw_edma_pcie_data )); + vsec_data->devmem_phys_off =DW_PCIE_AMD_MDB_INVALID_ADDR ;/* * Tries to find if exists a PCIe Vendor-Specific Extended Capability
drivers/dma/dw-edma/dw-edma-pcie.c static int dw_edma_pcie_probe(struct pci_dev *pdev, · line 299
Quoted 10 lines
drivers/dma/dw-edma/dw-edma-pcie.c +7
-0@@ -186,6 +290,26 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,*/ dw_edma_pcie_get_vsec_dma_data (pdev, vsec_data); +if (pdev->vendor ==PCI_VENDOR_ID_XILINX ) { +/* +* There is no valid address found for the LL memory +* space on the device side. +*/ +if (vsec_data->devmem_phys_off ==DW_PCIE_AMD_MDB_INVALID_ADDR ) +return -EINVAL ;
-ENOMEM
- Mani
Signature · 1 line
மணிவண்ணன் சதாசிவம்
RE: [PATCH RESEND v4 1/2] dmaengine: dw-edma: Add AMD MDB Endpoint Support
[AMD Official Use Only - AMD Internal Distribution Only]
Hi
Thank you Manivannan for reviewing the patch.
Please check my response inline.
Regards,
Devendra
Quoted 119 lines
-----Original Message-----
From: Manivannan Sadhasivam <[email protected]>
Sent: Monday, October 27, 2025 6:17 PM
To: Verma, Devendra <[email protected]>
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Simek, Michal <[email protected]>
Subject: Re: [PATCH RESEND v4 1/2] dmaengine: dw-edma: Add AMD MDB Endpoint SupportCaution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
Quoted 84 lines · Devendra K Verma
AMD MDB PCIe endpoint support. For AMD specific support added the following
- AMD supported PCIe Device IDs and Vendor ID (Xilinx).
- AMD MDB specific driver data
- AMD MDB specific VSEC capability to retrieve the device DDR base address.Signed-off-by Devendra K Verma <[email protected]>---
Changes in v4:
Configured 8 read and 8 write channels for Xilinx vendor Added checks to validate vendor ID for vendor specific vsec id.
Added Xilinx specific vendor id for vsec specific to Xilinx Added the LL and data region offsets, size as input params to functiondw_edma_set_chan_region_offset().
Moved the LL and data region offsets assignment to function for Xilinx specific case.
Corrected comments.Changes in v3:
Corrected a typo when assigning AMD (Xilinx) vsec id macro and condition check.Changes in v2:
Reverted thedevmem_phys_offtype to u64.
Renamed the function appropriately to suit the functionality for setting the LL & data region offsets.Changes in v1:
Removed the pci device id frompci_ids.hfile.
Added the vendor id macro as per the suggested method. Changed the type of the newly addeddevmem_phys_offvariable. Added to logic to assign offsets for LL and data region blocks in case more number of channels are enabled than given inamd_mdb_datastruct.--- drivers/dma/dw-edma/dw-edma-pcie.c | 130 ++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-)drivers/dma/dw-edma/dw-edma-pcie.c +17
-0@@ -17,12 +17,23 @@#include "dw-edma-core.h" +/* Synopsys */ #define DW_PCIE_VSEC_DMA_ID 0x6#define DW_PCIE_VSEC_DMA_BAR GENMASK(10, 8)#define DW_PCIE_VSEC_DMA_MAP GENMASK(2, 0)#define DW_PCIE_VSEC_DMA_WR_CH GENMASK(9, 0)#define DW_PCIE_VSEC_DMA_RD_CH GENMASK(25, 16) +/* AMD MDB (Xilinx) specific defines */ +#define DW_PCIE_XILINX_MDB_VSEC_DMA_ID 0x6 +#define DW_PCIE_XILINX_MDB_VSEC_ID 0x20 +#define PCI_DEVICE_ID_AMD_MDB_B054 0xb054 +#define DW_PCIE_AMD_MDB_INVALID_ADDR (~0ULL) +#define DW_PCIE_XILINX_LL_OFF_GAP 0x200000 +#define DW_PCIE_XILINX_LL_SIZE 0x800 +#define DW_PCIE_XILINX_DT_OFF_GAP 0x100000 +#define DW_PCIE_XILINX_DT_SIZE 0x800 +#define DW_BLOCK (a, b, c) \ { \ .bar = a, \@@ -50,6 +61,7 @@ struct dw_edma_pcie_data {u8 irqs;u16 wr_ch_cnt;u16 rd_ch_cnt; +u64 devmem_phys_off; }; static const struct dw_edma_pcie_data snps_edda_data = { @@ -90,6 +102,64 @@ struct dw_edma_pcie_data { .rd_ch_cnt =2 , }; +static const struct dw_edma_pcie_data amd_mdb_data = { + /* MDB registers location */ + .rg.bar = BAR_0, + .rg.off = 0x00001000, /* 4 Kbytes */drivers/dma/dw-edma/dw-edma-pcie.c struct dw_edma_pcie_data {
Quoted 10 lines
drivers/dma/dw-edma/dw-edma-pcie.c +10
-0+ .rg.sz = 0x00002000, /* 8 Kbytes */ + +/* Other */ + .mf = EDMA_MF_HDMA_NATIVE, + .irqs = 1, + .wr_ch_cnt = 8, + .rd_ch_cnt = 8, +}; + +static void dw_edma_set_chan_region_offset(struct dw_edma_pcie_data*pdata,
drivers/dma/dw-edma/dw-edma-pcie.c struct dw_edma_pcie_data { · line 126
Quoted 8 lines
drivers/dma/dw-edma/dw-edma-pcie.c +8
-0+ enum pci_barno bar, off_t start_off, + off_t ll_off_gap, size_t ll_size, + off_t dt_off_gap, size_t +dt_size) { + u16 i; +off_t off; +u16 wr_ch = pdata->wr_ch_cnt; +u16 rd_ch = pdata->rd_ch_cnt;
Quoted 2 lines
Reverse Xmas order please.
Accepted and corrected the order.
Quoted 68 lines
drivers/dma/dw-edma/dw-edma-pcie.c static void
Quoted 67 lines
drivers/dma/dw-edma/dw-edma-pcie.c +36
-0+ + off = start_off; + +/* Write channel LL region */ +for (i =0 ; i < wr_ch; i++) { + pdata->ll_wr[i].bar = bar; + pdata->ll_wr[i].off = off; + pdata->ll_wr[i].sz = ll_size; + off += ll_off_gap; + } + +/* Read channel LL region */ +for (i =0 ; i < rd_ch; i++) { + pdata->ll_rd[i].bar = bar; + pdata->ll_rd[i].off = off; + pdata->ll_rd[i].sz = ll_size; + off += ll_off_gap; + } + +/* Write channel data region */ +for (i =0 ; i < wr_ch; i++) { + pdata->dt_wr[i].bar = bar; + pdata->dt_wr[i].off = off; + pdata->dt_wr[i].sz = dt_size; + off += dt_off_gap; + } + +/* Read channel data region */ +for (i =0 ; i < rd_ch; i++) { + pdata->dt_rd[i].bar = bar; + pdata->dt_rd[i].off = off; + pdata->dt_rd[i].sz = dt_size; + off += dt_off_gap; + } +} + static int dw_edma_pcie_irq_vector(struct device *dev, unsigned intnr) { return pci_irq_vector(to_pci_dev(dev), nr); @@ -120,9 +190,24 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, u32 val, map; u16 vsec; u64 off;drivers/dma/dw-edma/dw-edma-pcie.c +17
-2+int cap; - vsec =pci_find_vsec_capability (pdev,PCI_VENDOR_ID_SYNOPSYS , -DW_PCIE_VSEC_DMA_ID ); +/* +* Synopsys and AMD (Xilinx) use the same VSEC ID for the purpose +* of map, channel counts, etc. +*/ +switch (pdev->vendor) { +case PCI_VENDOR_ID_SYNOPSYS : + cap =DW_PCIE_VSEC_DMA_ID ; +break ; +case PCI_VENDOR_ID_XILINX : + cap =DW_PCIE_XILINX_MDB_VSEC_DMA_ID ; +break ; +default : +return ; + } + + vsec =pci_find_vsec_capability (pdev, pdev->vendor, cap);if (!vsec)return ;@@ -155,6 +240,24 @@ static voiddw_edma_pcie_get_vsec_dma_data(struct
pci_dev*pdev,
Quoted 15 lines
drivers/dma/dw-edma/dw-edma-pcie.c static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, · line 252
Quoted 13 lines
drivers/dma/dw-edma/dw-edma-pcie.c +10
-0off <<=32 ; off |= val; pdata->rg.off = off; + +/* Xilinx specific VSEC capability */ + vsec =pci_find_vsec_capability (pdev,PCI_VENDOR_ID_XILINX , +DW_PCIE_XILINX_MDB_VSEC_ID ); +if (!vsec) +return ; + +pci_read_config_dword (pdev, vsec +PCI_VNDR_HEADER , &val); +if (PCI_VNDR_HEADER_ID (val) !=0x20 || +PCI_VNDR_HEADER_REV (val) !=0x1 )Can you have definitions for these header and rev IDs?
Yes, definitions are provided.
Quoted 9 lines
drivers/dma/dw-edma/dw-edma-pcie.c static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, · line 257
Quoted 6 lines
drivers/dma/dw-edma/dw-edma-pcie.c +5
-0+return ; + +pci_read_config_dword (pdev, vsec +0xc , &val); + off = val; +pci_read_config_dword (pdev, vsec +0x8 , &val);Same of these offsets as well.
Yes, definitions are provided for the offsets.
Quoted 25 lines
Quoted 7 lines
drivers/dma/dw-edma/dw-edma-pcie.c +3
-0+ off <<=32 ; + off |= val; + pdata->devmem_phys_off = off; } static int dw_edma_pcie_probe(struct pci_dev *pdev, @@ -179,6 +282,7@@ static int dw_edma_pcie_probe(struct
pci_dev*pdev,Quoted 8 lines
} memcpy(vsec_data, pdata, sizeof(struct dw_edma_pcie_data));+
vsec_data->devmem_phys_off=DW_PCIE_AMD_MDB_INVALID_ADDR;/*
* Tries to find if exists a PCIe Vendor-Specific Extended
Capability @@ -186,6 +290,26 @@ static int dw_edma_pcie_probe(struct
pci_dev*pdev,drivers/dma/dw-edma/dw-edma-pcie.c static int dw_edma_pcie_probe(struct pci_dev *pdev,
Quoted 9 lines
*/ dw_edma_pcie_get_vsec_dma_data(pdev, vsec_data);drivers/dma/dw-edma/dw-edma-pcie.c +6
-0+if (pdev->vendor ==PCI_VENDOR_ID_XILINX ) { +/* +* There is no valid address found for the LL memory +* space on the device side. +*/ + if (vsec_data->devmem_phys_off ==
Quoted 5 lines
DW_PCIE_AMD_MDB_INVALID_ADDR)Quoted 1 line
+ return
-EINVAL;
-ENOMEM
Corrected, the return is -ENOMEM.
Please check the latest revision v5.
Quoted 4 lines
- Mani
--
மணிவண்ணன் சதாசிவம்
PATCH RESEND v4 2/2 dmaengine: dw-edma: Add non-LL mode
In reply to Devendra K VermaAMD MDB IP supports Linked List (LL) mode as well as non-LL mode. The current code does not have the mechanisms to enable the DMA transactions using the non-LL mode. The following two cases are added with this patch:
- When a valid physical base address is not configured via the Xilinx VSEC capability then the IP can still be used in non-LL mode. The default mode for all the DMA transactions and for all the DMA channels then is non-LL mode.
- When a valid physical base address is configured but the client wants to use the non-LL mode for DMA transactions then also the flexibility is provided via the peripheral_config struct member of dma_slave_config. In this case the channels can be individually configured in non-LL mode. This use case is desirable for single DMA transfer of a chunk, this saves the effort of preparing the Link List.
---
Changes in v4
No change
Changes in v3
No change
Changes in v2
Reverted the function return type to u64 for
dw_edma_get_phys_addr().
Changes in v1
Changed the function return type for dw_edma_get_phys_addr(). Corrected the typo raised in review.
--- drivers/dma/dw-edma/dw-edma-core.c | 38 ++++++++++++++++++--- drivers/dma/dw-edma/dw-edma-core.h | 1 + drivers/dma/dw-edma/dw-edma-pcie.c | 44 +++++++++++++++++-------- drivers/dma/dw-edma/dw-hdma-v0-core.c | 62 ++++++++++++++++++++++++++++++++++- include/linux/dma/edma.h | 1 + 5 files changed, 127 insertions(+), 19 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +33 -5
@@ -223,8 +223,28 @@ static int dw_edma_device_config(struct dma_chan *dchan, struct dma_slave_config *config) {struct dw_edma_chan *chan =dchan2dw_edma_chan (dchan); +int nollp =0 ; + +if (WARN_ON (config->peripheral_config && + config->peripheral_size !=sizeof (int ))) +return -EINVAL ;memcpy (&chan->config, config,sizeof (*config)); + +/* +* When there is no valid LLP base address available +* then the default DMA ops will use the non-LL mode. +* Cases where LL mode is enabled and client wants +* to use the non-LL mode then also client can do +* so via providing the peripheral_config param. +*/ +if (config->peripheral_config) + nollp = *(int *)config->peripheral_config; + + chan->nollp = false; +if (chan->dw->chip->nollp || (!chan->dw->chip->nollp && nollp)) + chan->nollp = true; + chan->configured = true;return 0 ;
@@ -353,7 +373,7 @@ static void dw_edma_device_issue_pending(struct dma_chan *dchan)struct dw_edma_chan *chan =dchan2dw_edma_chan (xfer->dchan);enum dma_transfer_direction dir = xfer->direction;struct scatterlist *sg =NULL ; -struct dw_edma_chunk *chunk; +struct dw_edma_chunk *chunk =NULL ;struct dw_edma_burst *burst;struct dw_edma_desc *desc;u64 src_addr, dst_addr;
@@ -419,9 +439,11 @@ static void dw_edma_device_issue_pending(struct dma_chan *dchan)if (unlikely (!desc)) goto err_alloc; - chunk =dw_edma_alloc_chunk (desc); -if (unlikely (!chunk)) - goto err_alloc; +if (!chan->nollp) { + chunk =dw_edma_alloc_chunk (desc); +if (unlikely (!chunk)) + goto err_alloc; + }if (xfer->type ==EDMA_XFER_INTERLEAVED ) { src_addr = xfer->xfer.il->src_start;
@@ -450,7 +472,13 @@ static void dw_edma_device_issue_pending(struct dma_chan *dchan)if (xfer->type ==EDMA_XFER_SCATTER_GATHER && !sg)break ; -if (chunk->bursts_alloc == chan->ll_max) { +/* +* For non-LL mode, only a single burst can be handled +* in a single chunk unlike LL mode where multiple bursts +* can be configured in a single chunk. +*/ +if ((chunk && chunk->bursts_alloc == chan->ll_max) || + chan->nollp) { chunk =dw_edma_alloc_chunk (desc);if (unlikely (!chunk)) goto err_alloc;
drivers/dma/dw-edma/dw-edma-core.h +1 -0
@@ -86,6 +86,7 @@ struct dw_edma_chan {u8 configured;struct dma_slave_config config; +bool nollp; };struct dw_edma_irq {
drivers/dma/dw-edma/dw-edma-pcie.c +31 -13
110 lines not on this page · raw message
drivers/dma/dw-edma/dw-hdma-v0-core.c +61 -1
74 lines not on this page · raw message
include/linux/dma/edma.h +1 -0
@@ -99,6 +99,7 @@ struct dw_edma_chip {enum dw_edma_map_format mf;struct dw_edma *dw; +bool nollp; };/* Export to the platform drivers */
Signature · 1 line
1.8.3.1
Manivannan Sadhasivam
maintainerRe: [PATCH RESEND v4 2/2] dmaengine: dw-edma: Add non-LL mode
Quoted 1 line · Devendra K Verma
AMD MDB IP supports Linked List (LL) mode as well as non-LL mode.
Isn't the patch adding non-LL mode for all platforms, not just for AMD?
Quoted 43 lines
The current code does not have the mechanisms to enable the DMA transactions using the non-LL mode. The following two cases are added with this patch:
- When a valid physical base address is not configured via the Xilinx VSEC capability then the IP can still be used in non-LL mode. The default mode for all the DMA transactions and for all the DMA channels then is non-LL mode.
- When a valid physical base address is configured but the client wants to use the non-LL mode for DMA transactions then also the flexibility is provided via theperipheral_configstruct member ofdma_slave_config. In this case the channels can be individually configured in non-LL mode. This use case is desirable for single DMA transfer of a chunk, this saves the effort of preparing the Link List.Signed-off-by Devendra K Verma <[email protected]>---
Changes in v4
No changeChanges in v3
No changeChanges in v2
Reverted the function return type to u64 for
dw_edma_get_phys_addr().Changes in v1
Changed the function return type fordw_edma_get_phys_addr(). Corrected the typo raised in review.--- drivers/dma/dw-edma/dw-edma-core.c | 38 ++++++++++++++++++--- drivers/dma/dw-edma/dw-edma-core.h | 1 + drivers/dma/dw-edma/dw-edma-pcie.c | 44 +++++++++++++++++-------- drivers/dma/dw-edma/dw-hdma-v0-core.c | 62 ++++++++++++++++++++++++++++++++++- include/linux/dma/edma.h | 1 + 5 files changed, 127 insertions(+), 19 deletions(-)drivers/dma/dw-edma/dw-edma-core.c +0
-0
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct dma_chan *dchan, · line 226
Quoted 4 lines
drivers/dma/dw-edma/dw-edma-core.c +1
-0@@ -223,8 +223,28 @@ static int dw_edma_device_config(struct dma_chan *dchan, struct dma_slave_config *config) {struct dw_edma_chan *chan =dchan2dw_edma_chan (dchan); +int nollp =0 ;
s/nollp/non_ll
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct dma_chan *dchan, · line 229
Quoted 3 lines
drivers/dma/dw-edma/dw-edma-core.c +3
-0+ +if (WARN_ON (config->peripheral_config && + config->peripheral_size !=sizeof (int )))
Use proper dev_err(), not WARN_ON.
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct dma_chan *dchan, · line 239
Quoted 10 lines
drivers/dma/dw-edma/dw-edma-core.c +8
-0+return -EINVAL ;memcpy (&chan->config, config,sizeof (*config)); + +/* +* When there is no valid LLP base address available +* then the default DMA ops will use the non-LL mode. +* Cases where LL mode is enabled and client wants +* to use the non-LL mode then also client can do +* so via providing the peripheral_config param.
Make use of 80 columns for comments throughout this patch.
Rest LGTM!
- Mani
Signature · 1 line
மணிவண்ணன் சதாசிவம்
RE: [PATCH RESEND v4 2/2] dmaengine: dw-edma: Add non-LL mode
[AMD Official Use Only - AMD Internal Distribution Only]
Thank you Manivannan for reviewing the patches!
Please check my response inline.
Regards,
Devendra
Quoted 9 lines
-----Original Message-----
From: Manivannan Sadhasivam <[email protected]>
Sent: Monday, October 27, 2025 6:45 PM
To: Verma, Devendra <[email protected]>
Cc: [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Simek, Michal <[email protected]>
Subject: Re: [PATCH RESEND v4 2/2] dmaengine: dw-edma: Add non-LL mode
Quoted 9 lines
Caution: This message originated from an External Source. Use proper caution when opening attachments, clicking links, or responding.
Quoted 1 line · Devendra K Verma
AMD MDB IP supports Linked List (LL) mode as well as non-LL mode.
Isn't the patch adding non-LL mode for all platforms, not just for AMD?
A specific case where LL mode is enabled, which is the default mode, in this case all the IPs can support the non-LL mode provided it shall be configured via the config param peripheral_config by the client. The default case where non-LL mode is enabled for all the IPs is NOT supported by all the IPs.
Quoted 46 lines
Quoted 27 lines
The current code does not have the mechanisms to enable the DMA transactions using the non-LL mode. The following two cases are added with this patch:
- When a valid physical base address is not configured via the Xilinx VSEC capability then the IP can still be used in non-LL mode. The default mode for all the DMA transactions and for all the DMA channels then is non-LL mode.
- When a valid physical base address is configured but the client wants to use the non-LL mode for DMA transactions then also the flexibility is provided via theperipheral_configstruct member ofdma_slave_config. In this case the channels can be individually configured in non-LL mode. This use case is desirable for single DMA transfer of a chunk, this saves the effort of preparing the Link List.Signed-off-by Devendra K Verma <[email protected]>---
Changes in v4
No changeChanges in v3
No changeChanges in v2
Reverted the function return type to u64 for
dw_edma_get_phys_addr().Quoted 8 lines
Changes in v1
Changed the function return type fordw_edma_get_phys_addr(). Corrected the typo raised in review.--- drivers/dma/dw-edma/dw-edma-core.c | 38 ++++++++++++++++++--- drivers/dma/dw-edma/dw-edma-core.h | 1 + drivers/dma/dw-edma/dw-edma-pcie.c | 44 +++++++++++++++++-------- drivers/dma/dw-edma/dw-hdma-v0-core.c | 62++++++++++++++++++++++++++++++++++-
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct
Quoted 9 lines
include/linux/dma/edma.h | 1 + 5 files changed, 127 insertions(+), 19 deletions(-)drivers/dma/dw-edma/dw-edma-core.c +0
-0@@ -223,8 +223,28 @@ static int dw_edma_device_config(struct
dma_chan*dchan,
Quoted 6 lines
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct dma_chan *dchan, · line 226
Quoted 3 lines
drivers/dma/dw-edma/dw-edma-core.c +1
-0struct dma_slave_config *config) {struct dw_edma_chan *chan =dchan2dw_edma_chan (dchan); +int nollp =0 ;s/nollp/non_ll
Suggestion accepted. Thanks!
Quoted 6 lines
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct dma_chan *dchan, · line 229
Quoted 3 lines
drivers/dma/dw-edma/dw-edma-core.c +3
-0+ +if (WARN_ON (config->peripheral_config && + config->peripheral_size !=sizeof (int )))Use proper
dev_err(), notWARN_ON.
Suggestion accepted, dev_err() replaces WARN_ON() in latest drop. Thanks!
Quoted 11 lines
drivers/dma/dw-edma/dw-edma-core.c static int dw_edma_device_config(struct dma_chan *dchan, · line 239
Quoted 10 lines
drivers/dma/dw-edma/dw-edma-core.c +8
-0+return -EINVAL ;memcpy (&chan->config, config,sizeof (*config)); + +/* +* When there is no valid LLP base address available +* then the default DMA ops will use the non-LL mode. +* Cases where LL mode is enabled and client wants +* to use the non-LL mode then also client can do +* so via providing the peripheral_config param.
Quoted 2 lines
Make use of 80 columns for comments throughout this patch.
Comments follow the 80-column guideline. Thanks!
Quoted 6 lines
Rest LGTM!
- Mani
--
மணிவண்ணன் சதாசிவம்