dmaengine: dw-edma: HDMA support
Subsystems (3)
cover dmaengine: dw-edma: HDMA support
This patch series adds the HDMA support, as long the IP design has set the compatible register map parameter, which allows compatibility at some degree for the existing Synopsys DesignWare eDMA driver that is already available on the Kernel.
The HDMA "Hyper-DMA" IP is an enhancement of the eDMA "embedded-DMA" IP.
This new improvement comes with a PCI DVSEC that allows to the driver recognize and switch behavior if it's an eDMA or an HDMA, becoming retrocompatible, in the absence of this DVSEC, the driver will assume that is an eDMA IP.
It also adds the interleaved support, since it will be similar to the current scatter-gather implementation.
As well fixes/improves some abnormal behaviors not detected before, such as:
- crash on loading/unloading driver
- memory space definition for the data area and for the linked list space
- scatter-gather address calculation on 32 bits platforms
- minor comment and variable reordering
Gustavo Pimentel (15):
dmaengine: dw-edma: Add writeq() and readq() for 64 bits architectures
dmaengine: dw-edma: Fix comments offset characters' alignment
dmaengine: dw-edma: Add support for the HDMA feature
PCI: Add pci_find_vsec_capability() to find a specific VSEC
dmaengine: dw-edma: Add PCIe VSEC data retrieval support
dmaengine: dw-edma: Add device_prep_interleave_dma() support
dmaengine: dw-edma: Improve number of channels check
dmaengine: dw-edma: Reorder variables to keep consistency
dmaengine: dw-edma: Improve the linked list and data blocks definition
dmaengine: dw-edma: Change linked list and data blocks offset and
sizes
dmaengine: dw-edma: Move struct dentry variable from static definition
into dw_edma struct
dmaengine: dw-edma: Fix crash on loading/unloading driver
dmaengine: dw-edma: Change DMA abreviation from lower into upper case
dmaengine: dw-edma: Revert fix scatter-gather address calculation
dmaengine: dw-edma: Add pcim_iomap_table return checker
drivers/dma/dw-edma/dw-edma-core.c | 178 +++++++++++------- drivers/dma/dw-edma/dw-edma-core.h | 37 ++-- drivers/dma/dw-edma/dw-edma-pcie.c | 275 +++++++++++++++++++++------- drivers/dma/dw-edma/dw-edma-v0-core.c | 300 ++++++++++++++++++++++++------- drivers/dma/dw-edma/dw-edma-v0-core.h | 2 +- drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 77 ++++---- drivers/dma/dw-edma/dw-edma-v0-debugfs.h | 4 +- drivers/dma/dw-edma/dw-edma-v0-regs.h | 291 +++++++++++++++++++----------- drivers/pci/pci.c | 29 +++ include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 5 + 11 files changed, 844 insertions(+), 355 deletions(-)
Signature · 1 line
2.7.4
PATCH 1/15 dmaengine: dw-edma: Add writeq() and readq() for 64 bits architectures
Add writeq() and readq() for 64 bits architures support.
Supporting these two functions will allow the write or the read of eDMA 64 bits registers at once instead of having two consecutive operations.
Also, this improvement will allow the PCI optimization transaction messages, which will generate a 64 bits message instead of two messages of 32 bits.
--- drivers/dma/dw-edma/dw-edma-v0-core.c | 254 +++++++++++++++++++++++-------- drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 48 +++--- drivers/dma/dw-edma/dw-edma-v0-regs.h | 149 +++++++++++++----- 3 files changed, 326 insertions(+), 125 deletions(-)
drivers/dma/dw-edma/dw-edma-v0-core.c +190 -64
@@ -28,29 +28,69 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)return dw->rg_region.vaddr; } -#define SET (dw, name, value) \ +#define SET_32 (dw, name, value) \ writel(value, &(__dw_regs(dw)->name)) -#define GET (dw, name) \ +#define GET_32 (dw, name) \ readl(&(__dw_regs(dw)->name)) -#define SET_RW (dw, dir, name, value) \ +#define SET_RW_32 (dw, dir, name, value) \ do { \ if ((dir) == EDMA_DIR_WRITE) \ - SET(dw, wr_##name, value); \ + SET_32(dw, wr_##name, value); \ else \ - SET(dw, rd_##name, value); \ + SET_32(dw, rd_##name, value); \ } while (0) -#define GET_RW (dw, dir, name) \ +#define GET_RW_32 (dw, dir, name) \ ((dir) == EDMA_DIR_WRITE \ - ? GET(dw, wr_##name) \ - : GET(dw, rd_##name)) + ? GET_32(dw, wr_##name) \ + : GET_32(dw, rd_##name)) -#define SET_BOTH (dw, name, value) \ +#define SET_BOTH_32 (dw, name, value) \ do { \ - SET(dw, wr_##name, value); \ - SET(dw, rd_##name, value); \ + SET_32(dw, wr_##name, value); \ + SET_32(dw, rd_##name, value); \ + } while (0) + +#ifdef CONFIG_64BIT + +#define SET_64 (dw, name, value) \ + writeq(value, &(__dw_regs(dw)->name)) + +#define GET_64 (dw, name) \ + readq(&(__dw_regs(dw)->name)) + +#define SET_RW_64 (dw, dir, name, value) \ + do { \ + if ((dir) == EDMA_DIR_WRITE) \ + SET_64(dw, wr_##name, value); \ + else \ + SET_64(dw, rd_##name, value); \ + } while (0) + +#define GET_RW_64 (dw, dir, name) \ + ((dir) == EDMA_DIR_WRITE \ + ? GET_64(dw, wr_##name) \ + : GET_64(dw, rd_##name)) + +#define SET_BOTH_64 (dw, name, value) \ + do { \ + SET_64(dw, wr_##name, value); \ + SET_64(dw, rd_##name, value); \ + } while (0) + +#endif /* CONFIG_64BIT */ + +#define SET_COMPAT (dw, name, value) \ + writel(value, &(__dw_regs(dw)->type.unroll.name)) + +#define SET_RW_COMPAT (dw, dir, name, value) \ + do { \ + if ((dir) == EDMA_DIR_WRITE) \ + SET_COMPAT(dw, wr_##name, value); \ + else \ + SET_COMPAT(dw, rd_##name, value); \ } while (0) static inline struct dw_edma_v0_ch_regs __iomem *
@@ -115,21 +155,86 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,return value; } -#define SET_CH (dw, dir, ch, name, value) \ +#define SET_CH_32 (dw, dir, ch, name, value) \ writel_ch(dw, dir, ch, value, &(__dw_ch_regs(dw, dir, ch)->name)) -#define GET_CH (dw, dir, ch, name) \ +#define GET_CH_32 (dw, dir, ch, name) \ readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name)) -#define SET_LL (ll, value) \ +#define SET_LL_32 (ll, value) \ writel(value, ll) +#ifdef CONFIG_64BIT + +static inline void writeq_ch (struct dw_edma *dw,enum dw_edma_dir dir,u16 ch, +u64 value,void __iomem *addr) +{ +if (dw->mf ==EDMA_MF_EDMA_LEGACY ) { +u32 viewport_sel; +unsigned long flags; + +raw_spin_lock_irqsave (&dw->lock, flags); + + viewport_sel =FIELD_PREP (EDMA_V0_VIEWPORT_MASK , ch); +if (dir ==EDMA_DIR_READ ) + viewport_sel |=BIT (31 ); + +writel (viewport_sel, + &(__dw_regs (dw)->type.legacy.viewport_sel)); +writeq (value, addr); + +raw_spin_unlock_irqrestore (&dw->lock, flags); + }else { +writeq (value, addr); + } +} + +static inline u64 readq_ch (struct dw_edma *dw,enum dw_edma_dir dir,u16 ch, +const void __iomem *addr) +{ +u32 value; + +if (dw->mf ==EDMA_MF_EDMA_LEGACY ) { +u32 viewport_sel; +unsigned long flags; + +raw_spin_lock_irqsave (&dw->lock, flags); + + viewport_sel =FIELD_PREP (EDMA_V0_VIEWPORT_MASK , ch); +if (dir ==EDMA_DIR_READ ) + viewport_sel |=BIT (31 ); + +writel (viewport_sel, + &(__dw_regs (dw)->type.legacy.viewport_sel)); + value =readq (addr); + +raw_spin_unlock_irqrestore (&dw->lock, flags); + }else { + value =readq (addr); + } + +return value; +} + +#define SET_CH_64 (dw, dir, ch, name, value) \ + writeq_ch(dw, dir, ch, value, &(__dw_ch_regs(dw, dir, ch)->name)) + +#define GET_CH_64 (dw, dir, ch, name) \ + readq_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name)) + +#define SET_LL_64 (ll, value) \ + writeq(value, ll) + +#endif /* CONFIG_64BIT */ +/* eDMA management callbacks */ void dw_edma_v0_core_off (struct dw_edma *dw) { -SET_BOTH (dw, int_mask,EDMA_V0_DONE_INT_MASK |EDMA_V0_ABORT_INT_MASK ); -SET_BOTH (dw, int_clear,EDMA_V0_DONE_INT_MASK |EDMA_V0_ABORT_INT_MASK ); -SET_BOTH (dw, engine_en,0 ); +SET_BOTH_32 (dw, int_mask, +EDMA_V0_DONE_INT_MASK |EDMA_V0_ABORT_INT_MASK ); +SET_BOTH_32 (dw, int_clear, +EDMA_V0_DONE_INT_MASK |EDMA_V0_ABORT_INT_MASK ); +SET_BOTH_32 (dw, engine_en,0 ); }u16 dw_edma_v0_core_ch_count (struct dw_edma *dw,enum dw_edma_dir dir)
@@ -137,9 +242,11 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)u32 num_ch;if (dir ==EDMA_DIR_WRITE ) - num_ch =FIELD_GET (EDMA_V0_WRITE_CH_COUNT_MASK ,GET (dw, ctrl)); + num_ch =FIELD_GET (EDMA_V0_WRITE_CH_COUNT_MASK , +GET_32 (dw, ctrl));else - num_ch =FIELD_GET (EDMA_V0_READ_CH_COUNT_MASK ,GET (dw, ctrl)); + num_ch =FIELD_GET (EDMA_V0_READ_CH_COUNT_MASK , +GET_32 (dw, ctrl));if (num_ch >EDMA_V0_MAX_NR_CH ) num_ch =EDMA_V0_MAX_NR_CH ;
@@ -153,7 +260,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)u32 tmp; tmp =FIELD_GET (EDMA_V0_CH_STATUS_MASK , -GET_CH (dw, chan->dir, chan->id, ch_control1)); +GET_CH_32 (dw, chan->dir, chan->id, ch_control1));if (tmp ==1 )return DMA_IN_PROGRESS ;
@@ -167,26 +274,28 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan) {struct dw_edma *dw = chan->chip->dw; -SET_RW (dw, chan->dir, int_clear, -FIELD_PREP (EDMA_V0_DONE_INT_MASK ,BIT (chan->id))); +SET_RW_32 (dw, chan->dir, int_clear, +FIELD_PREP (EDMA_V0_DONE_INT_MASK ,BIT (chan->id))); }void dw_edma_v0_core_clear_abort_int (struct dw_edma_chan *chan) {struct dw_edma *dw = chan->chip->dw; -SET_RW (dw, chan->dir, int_clear, -FIELD_PREP (EDMA_V0_ABORT_INT_MASK ,BIT (chan->id))); +SET_RW_32 (dw, chan->dir, int_clear, +FIELD_PREP (EDMA_V0_ABORT_INT_MASK ,BIT (chan->id))); }u32 dw_edma_v0_core_status_done_int (struct dw_edma *dw,enum dw_edma_dir dir) { -return FIELD_GET (EDMA_V0_DONE_INT_MASK ,GET_RW (dw, dir, int_status)); +return FIELD_GET (EDMA_V0_DONE_INT_MASK , +GET_RW_32 (dw, dir, int_status)); }u32 dw_edma_v0_core_status_abort_int (struct dw_edma *dw,enum dw_edma_dir dir) { -return FIELD_GET (EDMA_V0_ABORT_INT_MASK ,GET_RW (dw, dir, int_status)); +return FIELD_GET (EDMA_V0_ABORT_INT_MASK , +GET_RW_32 (dw, dir, int_status)); }static void dw_edma_v0_core_write_chunk (struct dw_edma_chunk *chunk)
@@ -209,15 +318,23 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) control |= (DW_EDMA_V0_LIE |DW_EDMA_V0_RIE );/* Channel control */ -SET_LL (&lli[i].control, control); +SET_LL_32 (&lli[i].control, control);/* Transfer size */ -SET_LL (&lli[i].transfer_size, child->sz); -/* SAR - low, high */ -SET_LL (&lli[i].sar_low,lower_32_bits (child->sar)); -SET_LL (&lli[i].sar_high,upper_32_bits (child->sar)); -/* DAR - low, high */ -SET_LL (&lli[i].dar_low,lower_32_bits (child->dar)); -SET_LL (&lli[i].dar_high,upper_32_bits (child->dar)); +SET_LL_32 (&lli[i].transfer_size, child->sz); +/* SAR */ +#ifdef CONFIG_64BIT +SET_LL_64 (&lli[i].sar.reg, child->sar); +#else /* CONFIG_64BIT */ +SET_LL_32 (&lli[i].sar.lsb,lower_32_bits (child->sar)); +SET_LL_32 (&lli[i].sar.msb,upper_32_bits (child->sar)); +#endif /* CONFIG_64BIT */ +/* DAR */ +#ifdef CONFIG_64BIT +SET_LL_64 (&lli[i].dar.reg, child->dar); +#else /* CONFIG_64BIT */ +SET_LL_32 (&lli[i].dar.lsb,lower_32_bits (child->dar)); +SET_LL_32 (&lli[i].dar.msb,upper_32_bits (child->dar)); +#endif /* CONFIG_64BIT */ i++; }
@@ -227,10 +344,14 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk) control |=DW_EDMA_V0_CB ;/* Channel control */ -SET_LL (&llp->control, control); -/* Linked list - low, high */ -SET_LL (&llp->llp_low,lower_32_bits (chunk->ll_region.paddr)); -SET_LL (&llp->llp_high,upper_32_bits (chunk->ll_region.paddr)); +SET_LL_32 (&llp->control, control); +/* Linked list */ +#ifdef CONFIG_64BIT +SET_LL_64 (&llp->llp.reg, chunk->ll_region.paddr); +#else /* CONFIG_64BIT */ +SET_LL_32 (&llp->llp.lsb,lower_32_bits (chunk->ll_region.paddr)); +SET_LL_32 (&llp->llp.msb,upper_32_bits (chunk->ll_region.paddr)); +#endif /* CONFIG_64BIT */ }void dw_edma_v0_core_start (struct dw_edma_chunk *chunk,bool first)
@@ -243,28 +364,33 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)if (first) {/* Enable engine */ -SET_RW (dw, chan->dir, engine_en,BIT (0 )); +SET_RW_32 (dw, chan->dir, engine_en,BIT (0 ));/* Interrupt unmask - done, abort */ - tmp =GET_RW (dw, chan->dir, int_mask); + tmp =GET_RW_32 (dw, chan->dir, int_mask); tmp &= ~FIELD_PREP (EDMA_V0_DONE_INT_MASK ,BIT (chan->id)); tmp &= ~FIELD_PREP (EDMA_V0_ABORT_INT_MASK ,BIT (chan->id)); -SET_RW (dw, chan->dir, int_mask, tmp); +SET_RW_32 (dw, chan->dir, int_mask, tmp);/* Linked list error */ - tmp =GET_RW (dw, chan->dir, linked_list_err_en); + tmp =GET_RW_32 (dw, chan->dir, linked_list_err_en); tmp |=FIELD_PREP (EDMA_V0_LINKED_LIST_ERR_MASK ,BIT (chan->id)); -SET_RW (dw, chan->dir, linked_list_err_en, tmp); +SET_RW_32 (dw, chan->dir, linked_list_err_en, tmp);/* Channel control */ -SET_CH (dw, chan->dir, chan->id, ch_control1, - (DW_EDMA_V0_CCS |DW_EDMA_V0_LLE )); -/* Linked list - low, high */ -SET_CH (dw, chan->dir, chan->id, llp_low, -lower_32_bits (chunk->ll_region.paddr)); -SET_CH (dw, chan->dir, chan->id, llp_high, -upper_32_bits (chunk->ll_region.paddr)); +SET_CH_32 (dw, chan->dir, chan->id, ch_control1, + (DW_EDMA_V0_CCS |DW_EDMA_V0_LLE )); +/* Linked list */ +#ifdef CONFIG_64BIT +SET_CH_64 (dw, chan->dir, chan->id, llp.reg, + chunk->ll_region.paddr); +#else /* CONFIG_64BIT */ +SET_CH_32 (dw, chan->dir, chan->id, llp.lsb, +lower_32_bits (chunk->ll_region.paddr)); +SET_CH_32 (dw, chan->dir, chan->id, llp.msb, +upper_32_bits (chunk->ll_region.paddr)); +#endif /* CONFIG_64BIT */ }/* Doorbell */ -SET_RW (dw, chan->dir, doorbell, -FIELD_PREP (EDMA_V0_DOORBELL_CH_MASK , chan->id)); +SET_RW_32 (dw, chan->dir, doorbell, +FIELD_PREP (EDMA_V0_DOORBELL_CH_MASK , chan->id)); }int dw_edma_v0_core_device_config (struct dw_edma_chan *chan)
@@ -273,31 +399,31 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)u32 tmp =0 ;/* MSI done addr - low, high */ -SET_RW (dw, chan->dir, done_imwr_low, chan->msi.address_lo); -SET_RW (dw, chan->dir, done_imwr_high, chan->msi.address_hi); +SET_RW_32 (dw, chan->dir, done_imwr.lsb, chan->msi.address_lo); +SET_RW_32 (dw, chan->dir, done_imwr.msb, chan->msi.address_hi);/* MSI abort addr - low, high */ -SET_RW (dw, chan->dir, abort_imwr_low, chan->msi.address_lo); -SET_RW (dw, chan->dir, abort_imwr_high, chan->msi.address_hi); +SET_RW_32 (dw, chan->dir, abort_imwr.lsb, chan->msi.address_lo); +SET_RW_32 (dw, chan->dir, abort_imwr.msb, chan->msi.address_hi);/* MSI data - low, high */ switch (chan->id) {case 0 :case 1 : - tmp =GET_RW (dw, chan->dir, ch01_imwr_data); + tmp =GET_RW_32 (dw, chan->dir, ch01_imwr_data);break ;case 2 :case 3 : - tmp =GET_RW (dw, chan->dir, ch23_imwr_data); + tmp =GET_RW_32 (dw, chan->dir, ch23_imwr_data);break ;case 4 :case 5 : - tmp =GET_RW (dw, chan->dir, ch45_imwr_data); + tmp =GET_RW_32 (dw, chan->dir, ch45_imwr_data);break ;case 6 :case 7 : - tmp =GET_RW (dw, chan->dir, ch67_imwr_data); + tmp =GET_RW_32 (dw, chan->dir, ch67_imwr_data);break ; }
@@ -316,22 +442,22 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)switch (chan->id) {case 0 :case 1 : -SET_RW (dw, chan->dir, ch01_imwr_data, tmp); +SET_RW_32 (dw, chan->dir, ch01_imwr_data, tmp);break ;case 2 :case 3 : -SET_RW (dw, chan->dir, ch23_imwr_data, tmp); +SET_RW_32 (dw, chan->dir, ch23_imwr_data, tmp);break ;case 4 :case 5 : -SET_RW (dw, chan->dir, ch45_imwr_data, tmp); +SET_RW_32 (dw, chan->dir, ch45_imwr_data, tmp);break ;case 6 :case 7 : -SET_RW (dw, chan->dir, ch67_imwr_data, tmp); +SET_RW_32 (dw, chan->dir, ch67_imwr_data, tmp);break ; }
drivers/dma/dw-edma/dw-edma-v0-debugfs.c +24 -24
88 lines not on this page · raw message
drivers/dma/dw-edma/dw-edma-v0-regs.h +112 -37
215 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 2/15 dmaengine: dw-edma: Fix comments offset characters' alignment
In reply to Gustavo PimentelFix comments offset characters' alignment to follow the same structure of similar comments.
--- drivers/dma/dw-edma/dw-edma-v0-regs.h | 214 +++++++++++++++++----------------- 1 file changed, 107 insertions(+), 107 deletions(-)
drivers/dma/dw-edma/dw-edma-v0-regs.h +107 -107
@@ -25,177 +25,177 @@#define EDMA_V0_CH_EVEN_MSI_DATA_MASK GENMASK(15, 0)struct dw_edma_v0_ch_regs { -u32 ch_control1;/* 0x000 */ -u32 ch_control2;/* 0x004 */ -u32 transfer_size;/* 0x008 */ +u32 ch_control1;/* 0x0000 */ +u32 ch_control2;/* 0x0004 */ +u32 transfer_size;/* 0x0008 */ union { -u64 reg;/* 0x00c..0x010 */ +u64 reg;/* 0x000c..0x0010 */ struct { -u32 lsb;/* 0x00c */ -u32 msb;/* 0x010 */ +u32 lsb;/* 0x000c */ +u32 msb;/* 0x0010 */ }; } sar;union { -u64 reg;/* 0x014..0x018 */ +u64 reg;/* 0x0014..0x0018 */ struct { -u32 lsb;/* 0x014 */ -u32 msb;/* 0x018 */ +u32 lsb;/* 0x0014 */ +u32 msb;/* 0x0018 */ }; } dar;union { -u64 reg;/* 0x01c..0x020 */ +u64 reg;/* 0x001c..0x0020 */ struct { -u32 lsb;/* 0x01c */ -u32 msb;/* 0x020 */ +u32 lsb;/* 0x001c */ +u32 msb;/* 0x0020 */ }; } llp; } __packed;struct dw_edma_v0_ch { -struct dw_edma_v0_ch_regs wr;/* 0x200 */ -u32 padding_1[55 ];/* [0x224..0x2fc] */ -struct dw_edma_v0_ch_regs rd;/* 0x300 */ -u32 padding_2[55 ];/* [0x324..0x3fc] */ +struct dw_edma_v0_ch_regs wr;/* 0x0200 */ +u32 padding_1[55 ];/* 0x0224..0x02fc */ +struct dw_edma_v0_ch_regs rd;/* 0x0300 */ +u32 padding_2[55 ];/* 0x0324..0x03fc */ } __packed;struct dw_edma_v0_unroll { -u32 padding_1;/* 0x0f8 */ -u32 wr_engine_chgroup;/* 0x100 */ -u32 rd_engine_chgroup;/* 0x104 */ +u32 padding_1;/* 0x00f8 */ +u32 wr_engine_chgroup;/* 0x0100 */ +u32 rd_engine_chgroup;/* 0x0104 */ union { -u64 reg;/* 0x108..0x10c */ +u64 reg;/* 0x0108..0x010c */ struct { -u32 lsb;/* 0x108 */ -u32 msb;/* 0x10c */ +u32 lsb;/* 0x0108 */ +u32 msb;/* 0x010c */ }; } wr_engine_hshake_cnt; -u32 padding_2[2 ];/* [0x110..0x114] */ +u32 padding_2[2 ];/* 0x0110..0x0114 */ union { -u64 reg;/* 0x120..0x124 */ +u64 reg;/* 0x0120..0x0124 */ struct { -u32 lsb;/* 0x120 */ -u32 msb;/* 0x124 */ +u32 lsb;/* 0x0120 */ +u32 msb;/* 0x0124 */ }; } rd_engine_hshake_cnt; -u32 padding_3[2 ];/* [0x120..0x124] */ -u32 wr_ch0_pwr_en;/* 0x128 */ -u32 wr_ch1_pwr_en;/* 0x12c */ -u32 wr_ch2_pwr_en;/* 0x130 */ -u32 wr_ch3_pwr_en;/* 0x134 */ -u32 wr_ch4_pwr_en;/* 0x138 */ -u32 wr_ch5_pwr_en;/* 0x13c */ -u32 wr_ch6_pwr_en;/* 0x140 */ -u32 wr_ch7_pwr_en;/* 0x144 */ -u32 padding_4[8 ];/* [0x148..0x164] */ -u32 rd_ch0_pwr_en;/* 0x168 */ -u32 rd_ch1_pwr_en;/* 0x16c */ -u32 rd_ch2_pwr_en;/* 0x170 */ -u32 rd_ch3_pwr_en;/* 0x174 */ -u32 rd_ch4_pwr_en;/* 0x178 */ -u32 rd_ch5_pwr_en;/* 0x18c */ -u32 rd_ch6_pwr_en;/* 0x180 */ -u32 rd_ch7_pwr_en;/* 0x184 */ -u32 padding_5[30 ];/* [0x188..0x1fc] */ -struct dw_edma_v0_ch ch[EDMA_V0_MAX_NR_CH ];/* [0x200..0x1120] */ +u32 padding_3[2 ];/* 0x0120..0x0124 */ +u32 wr_ch0_pwr_en;/* 0x0128 */ +u32 wr_ch1_pwr_en;/* 0x012c */ +u32 wr_ch2_pwr_en;/* 0x0130 */ +u32 wr_ch3_pwr_en;/* 0x0134 */ +u32 wr_ch4_pwr_en;/* 0x0138 */ +u32 wr_ch5_pwr_en;/* 0x013c */ +u32 wr_ch6_pwr_en;/* 0x0140 */ +u32 wr_ch7_pwr_en;/* 0x0144 */ +u32 padding_4[8 ];/* 0x0148..0x0164 */ +u32 rd_ch0_pwr_en;/* 0x0168 */ +u32 rd_ch1_pwr_en;/* 0x016c */ +u32 rd_ch2_pwr_en;/* 0x0170 */ +u32 rd_ch3_pwr_en;/* 0x0174 */ +u32 rd_ch4_pwr_en;/* 0x0178 */ +u32 rd_ch5_pwr_en;/* 0x018c */ +u32 rd_ch6_pwr_en;/* 0x0180 */ +u32 rd_ch7_pwr_en;/* 0x0184 */ +u32 padding_5[30 ];/* 0x0188..0x01fc */ +struct dw_edma_v0_ch ch[EDMA_V0_MAX_NR_CH ];/* 0x0200..0x1120 */ } __packed;struct dw_edma_v0_legacy { -u32 viewport_sel;/* 0x0f8 */ -struct dw_edma_v0_ch_regs ch;/* [0x100..0x120] */ +u32 viewport_sel;/* 0x00f8 */ +struct dw_edma_v0_ch_regs ch;/* 0x0100..0x0120 */ } __packed;struct dw_edma_v0_regs {/* eDMA global registers */ -u32 ctrl_data_arb_prior;/* 0x000 */ -u32 padding_1;/* 0x004 */ -u32 ctrl;/* 0x008 */ -u32 wr_engine_en;/* 0x00c */ -u32 wr_doorbell;/* 0x010 */ -u32 padding_2;/* 0x014 */ +u32 ctrl_data_arb_prior;/* 0x0000 */ +u32 padding_1;/* 0x0004 */ +u32 ctrl;/* 0x0008 */ +u32 wr_engine_en;/* 0x000c */ +u32 wr_doorbell;/* 0x0010 */ +u32 padding_2;/* 0x0014 */ union { -u64 reg;/* 0x018..0x01c */ +u64 reg;/* 0x0018..0x001c */ struct { -u32 lsb;/* 0x018 */ -u32 msb;/* 0x01c */ +u32 lsb;/* 0x0018 */ +u32 msb;/* 0x001c */ }; } wr_ch_arb_weight; -u32 padding_3[3 ];/* [0x020..0x028] */ -u32 rd_engine_en;/* 0x02c */ -u32 rd_doorbell;/* 0x030 */ -u32 padding_4;/* 0x034 */ +u32 padding_3[3 ];/* 0x0020..0x0028 */ +u32 rd_engine_en;/* 0x002c */ +u32 rd_doorbell;/* 0x0030 */ +u32 padding_4;/* 0x0034 */ union { -u64 reg;/* 0x038..0x03c */ +u64 reg;/* 0x0038..0x003c */ struct { -u32 lsb;/* 0x038 */ -u32 msb;/* 0x03c */ +u32 lsb;/* 0x0038 */ +u32 msb;/* 0x003c */ }; } rd_ch_arb_weight; -u32 padding_5[3 ];/* [0x040..0x048] */ +u32 padding_5[3 ];/* 0x0040..0x0048 */ /* eDMA interrupts registers */ -u32 wr_int_status;/* 0x04c */ -u32 padding_6;/* 0x050 */ -u32 wr_int_mask;/* 0x054 */ -u32 wr_int_clear;/* 0x058 */ -u32 wr_err_status;/* 0x05c */ +u32 wr_int_status;/* 0x004c */ +u32 padding_6;/* 0x0050 */ +u32 wr_int_mask;/* 0x0054 */ +u32 wr_int_clear;/* 0x0058 */ +u32 wr_err_status;/* 0x005c */ union { -u64 reg;/* 0x060..0x064 */ +u64 reg;/* 0x0060..0x0064 */ struct { -u32 lsb;/* 0x060 */ -u32 msb;/* 0x064 */ +u32 lsb;/* 0x0060 */ +u32 msb;/* 0x0064 */ }; } wr_done_imwr;union { -u64 reg;/* 0x068..0x06c */ +u64 reg;/* 0x0068..0x006c */ struct { -u32 lsb;/* 0x068 */ -u32 msb;/* 0x06c */ +u32 lsb;/* 0x0068 */ +u32 msb;/* 0x006c */ }; } wr_abort_imwr; -u32 wr_ch01_imwr_data;/* 0x070 */ -u32 wr_ch23_imwr_data;/* 0x074 */ -u32 wr_ch45_imwr_data;/* 0x078 */ -u32 wr_ch67_imwr_data;/* 0x07c */ -u32 padding_7[4 ];/* [0x080..0x08c] */ -u32 wr_linked_list_err_en;/* 0x090 */ -u32 padding_8[3 ];/* [0x094..0x09c] */ -u32 rd_int_status;/* 0x0a0 */ -u32 padding_9;/* 0x0a4 */ -u32 rd_int_mask;/* 0x0a8 */ -u32 rd_int_clear;/* 0x0ac */ -u32 padding_10;/* 0x0b0 */ +u32 wr_ch01_imwr_data;/* 0x0070 */ +u32 wr_ch23_imwr_data;/* 0x0074 */ +u32 wr_ch45_imwr_data;/* 0x0078 */ +u32 wr_ch67_imwr_data;/* 0x007c */ +u32 padding_7[4 ];/* 0x0080..0x008c */ +u32 wr_linked_list_err_en;/* 0x0090 */ +u32 padding_8[3 ];/* 0x0094..0x009c */ +u32 rd_int_status;/* 0x00a0 */ +u32 padding_9;/* 0x00a4 */ +u32 rd_int_mask;/* 0x00a8 */ +u32 rd_int_clear;/* 0x00ac */ +u32 padding_10;/* 0x00b0 */ union { -u64 reg;/* 0x0b4..0x0b8 */ +u64 reg;/* 0x00b4..0x00b8 */ struct { -u32 lsb;/* 0x0b4 */ -u32 msb;/* 0x0b8 */ +u32 lsb;/* 0x00b4 */ +u32 msb;/* 0x00b8 */ }; } rd_err_status; -u32 padding_11[2 ];/* [0x0bc..0x0c0] */ -u32 rd_linked_list_err_en;/* 0x0c4 */ -u32 padding_12;/* 0x0c8 */ +u32 padding_11[2 ];/* 0x00bc..0x00c0 */ +u32 rd_linked_list_err_en;/* 0x00c4 */ +u32 padding_12;/* 0x00c8 */ union { -u64 reg;/* 0x0cc..0x0d0 */ +u64 reg;/* 0x00cc..0x00d0 */ struct { -u32 lsb;/* 0x0cc */ -u32 msb;/* 0x0d0 */ +u32 lsb;/* 0x00cc */ +u32 msb;/* 0x00d0 */ }; } rd_done_imwr;union { -u64 reg;/* 0x0d4..0x0d8 */ +u64 reg;/* 0x00d4..0x00d8 */ struct { -u32 lsb;/* 0x0d4 */ -u32 msb;/* 0x0d8 */ +u32 lsb;/* 0x00d4 */ +u32 msb;/* 0x00d8 */ }; } rd_abort_imwr; -u32 rd_ch01_imwr_data;/* 0x0dc */ -u32 rd_ch23_imwr_data;/* 0x0e0 */ -u32 rd_ch45_imwr_data;/* 0x0e4 */ -u32 rd_ch67_imwr_data;/* 0x0e8 */ -u32 padding_13[4 ];/* [0x0ec..0x0f8] */ +u32 rd_ch01_imwr_data;/* 0x00dc */ +u32 rd_ch23_imwr_data;/* 0x00e0 */ +u32 rd_ch45_imwr_data;/* 0x00e4 */ +u32 rd_ch67_imwr_data;/* 0x00e8 */ +u32 padding_13[4 ];/* 0x00ec..0x00f8 */ /* eDMA channel context grouping */ union dw_edma_v0_type { -struct dw_edma_v0_legacy legacy;/* [0x0f8..0x120] */ -struct dw_edma_v0_unroll unroll;/* [0x0f8..0x1120] */ +struct dw_edma_v0_legacy legacy;/* 0x00f8..0x0120 */ +struct dw_edma_v0_unroll unroll;/* 0x00f8..0x1120 */ } type; } __packed;
Signature · 1 line
2.7.4
PATCH 3/15 dmaengine: dw-edma: Add support for the HDMA feature
In reply to Gustavo PimentelAdd support for the HDMA feature.
This new feature enables the current eDMA IP to use a deeper prefetch of the linked list, which reduces the algorithm execution latency observed when loading the elements of the list, causing more stable and higher data transfer.
--- drivers/dma/dw-edma/dw-edma-core.h | 10 ++++---- drivers/dma/dw-edma/dw-edma-pcie.c | 23 ++++++++--------- drivers/dma/dw-edma/dw-edma-v0-core.c | 42 +++++++++++++++++++++++++++++--- drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 9 +++---- 4 files changed, 60 insertions(+), 24 deletions(-)
drivers/dma/dw-edma/dw-edma-core.h +5 -5
@@ -21,9 +21,10 @@ enum dw_edma_dir {EDMA_DIR_READ }; -enum dw_edma_mode { -EDMA_MODE_LEGACY =0 , -EDMA_MODE_UNROLL +enum dw_edma_map_format { +EDMA_MF_EDMA_LEGACY =0x0 , +EDMA_MF_EDMA_UNROLL =0x1 , +EDMA_MF_HDMA_COMPAT =0x5 };enum dw_edma_request {
@@ -123,8 +124,7 @@ struct dw_edma {struct dw_edma_irq *irq;int nr_irqs; -u32 version; -enum dw_edma_mode mode; +enum dw_edma_map_format mf;struct dw_edma_chan *chan;const struct dw_edma_core_ops *ops;
drivers/dma/dw-edma/dw-edma-pcie.c +12 -11
@@ -30,8 +30,7 @@ struct dw_edma_pcie_data {off_t dt_off;size_t dt_sz;/* Other */ -u32 version; -enum dw_edma_mode mode; +enum dw_edma_map_format mf;u8 irqs; };
@@ -49,8 +48,7 @@ static const struct dw_edma_pcie_data snps_edda_data = { .dt_off = 0x00800000, /* 8 Mbytes */ .dt_sz = 0x03800000, /* 56 Mbytes */ /* Other */ - .version = 0, - .mode = EDMA_MODE_UNROLL, + .mf = EDMA_MF_EDMA_UNROLL, .irqs = 1, };
@@ -69,8 +67,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,const struct dw_edma_pcie_data *pdata = (void *)pid->driver_data;struct device *dev = &pdev->dev;struct dw_edma_chip *chip; -int err, nr_irqs;struct dw_edma *dw; +int err, nr_irqs;/* Enable PCI device */ err =pcim_enable_device (pdev);
@@ -157,16 +155,19 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, dw->dt_region.paddr += pdata->dt_off; dw->dt_region.sz = pdata->dt_sz; - dw->version = pdata->version; - dw->mode = pdata->mode; + dw->mf = pdata->mf; dw->nr_irqs = nr_irqs; dw->ops = &dw_edma_pcie_core_ops;/* Debug info */ -pci_dbg (pdev,"Version:\t%u\n" , dw->version); - -pci_dbg (pdev,"Mode:\t%s\n" , - dw->mode ==EDMA_MODE_LEGACY ?"Legacy" :"Unroll" ); +if (dw->mf ==EDMA_MF_EDMA_LEGACY ) +pci_dbg (pdev,"Version:\teDMA Port Logic (0x%x)\n" , dw->mf); +else if (dw->mf ==EDMA_MF_EDMA_UNROLL ) +pci_dbg (pdev,"Version:\teDMA Unroll (0x%x)\n" , dw->mf); +else if (dw->mf ==EDMA_MF_HDMA_COMPAT ) +pci_dbg (pdev,"Version:\tHDMA Compatible (0x%x)\n" , dw->mf); +else +pci_dbg (pdev,"Version:\tUnknown (0x%x)\n" , dw->mf); pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n", pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
drivers/dma/dw-edma/dw-edma-v0-core.c +39 -3
66 lines not on this page · raw message
drivers/dma/dw-edma/dw-edma-v0-debugfs.c +4 -5
@@ -55,7 +55,7 @@ struct debugfs_entries {static int dw_edma_debugfs_u32_get (void *data,u64 *val) {void __iomem *reg = (void __force __iomem *)data; -if (dw->mode ==EDMA_MODE_LEGACY && +if (dw->mf ==EDMA_MF_EDMA_LEGACY && reg >= (void __iomem *)®s->type.legacy.ch) {void __iomem *ptr = ®s->type.legacy.ch;u32 viewport_sel =0 ;
@@ -174,7 +174,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir) nr_entries =ARRAY_SIZE (debugfs_regs);dw_edma_debugfs_create_x32 (debugfs_regs, nr_entries, regs_dir); -if (dw->mode ==EDMA_MODE_UNROLL ) { +if (dw->mf ==EDMA_MF_HDMA_COMPAT ) { nr_entries =ARRAY_SIZE (debugfs_unroll_regs);dw_edma_debugfs_create_x32 (debugfs_unroll_regs, nr_entries, regs_dir);
@@ -243,7 +243,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir) nr_entries =ARRAY_SIZE (debugfs_regs);dw_edma_debugfs_create_x32 (debugfs_regs, nr_entries, regs_dir); -if (dw->mode ==EDMA_MODE_UNROLL ) { +if (dw->mf ==EDMA_MF_HDMA_COMPAT ) { nr_entries =ARRAY_SIZE (debugfs_unroll_regs);dw_edma_debugfs_create_x32 (debugfs_unroll_regs, nr_entries, regs_dir);
@@ -297,8 +297,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)if (!base_dir)return ; -debugfs_create_u32 ("version" ,0444 , base_dir, &dw->version); -debugfs_create_u32 ("mode" ,0444 , base_dir, &dw->mode); +debugfs_create_u32 ("mf" ,0444 , base_dir, &dw->mf);debugfs_create_u16 ("wr_ch_cnt" ,0444 , base_dir, &dw->wr_ch_cnt);debugfs_create_u16 ("rd_ch_cnt" ,0444 , base_dir, &dw->rd_ch_cnt);
Signature · 1 line
2.7.4
PATCH 4/15 PCI: Add pci_find_vsec_capability() to find a specific VSEC
In reply to Gustavo PimentelAdd pci_find_vsec_capability() that crawls through the device config space searching in all Vendor-Specific Extended Capabilities for a particular capability ID.
Vendor-Specific Extended Capability (VSEC) is a PCIe capability (acts like a wrapper) specified by PCI-SIG that allows the vendor to create their own and specific capability in the device config space.
--- drivers/pci/pci.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 5 +++++ 3 files changed, 35 insertions(+)
drivers/pci/pci.c +29 -0
@@ -623,6 +623,35 @@ u64 pci_get_dsn(struct pci_dev *dev) }EXPORT_SYMBOL_GPL (pci_get_dsn); +/** +* pci_find_vsec_capability - Find a vendor-specific extended capability +* @dev: PCI device to query +* @cap: vendor-specific capability id code +* +* Returns the address of the vendor-specific structure that matches the +* requested capability id code within the device's PCI configuration space +* or 0 if it does not find a match. +*/ +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id) +{ +u32 header; +int vsec; + + vsec =pci_find_ext_capability (dev,PCI_EXT_CAP_ID_VNDR ); +while (vsec) { +if (pci_read_config_dword (dev, vsec +0x4 , + &header) ==PCIBIOS_SUCCESSFUL && +PCI_VSEC_CAP_ID (header) == vsec_cap_id) +break ; + + vsec =pci_find_next_ext_capability (dev, vsec, +PCI_EXT_CAP_ID_VNDR ); + } + +return vsec; +} +EXPORT_SYMBOL_GPL (pci_find_vsec_capability); +static int __pci_find_next_ht_cap (struct pci_dev *dev,int pos,int ht_cap) {int rc, ttl =PCI_FIND_CAP_TTL ;
include/linux/pci.h +1 -0
@@ -1067,6 +1067,7 @@ int pci_find_capability(struct pci_dev *dev, int cap);int pci_find_next_capability (struct pci_dev *dev,u8 pos,int cap);int pci_find_ext_capability (struct pci_dev *dev,int cap);int pci_find_next_ext_capability (struct pci_dev *dev,int pos,int cap); +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id);int pci_find_ht_capability (struct pci_dev *dev,int ht_cap);int pci_find_next_ht_capability (struct pci_dev *dev,int pos,int ht_cap);struct pci_bus *pci_find_next_bus (const struct pci_bus *from);
include/uapi/linux/pci_regs.h +5 -0
@@ -730,6 +730,11 @@#define PCI_EXT_CAP_DSN_SIZEOF 12#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 +/* Vendor-Specific Extended Capabilities */ +#define PCI_VSEC_CAP_ID (header) (header & 0x0000ffff) +#define PCI_VSEC_CAP_REV (header) ((header >> 16) & 0xf) +#define PCI_VSEC_CAP_LEN (header) ((header >> 20) & 0xffc) +/* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4/* Uncorrectable Error Status */ #define PCI_ERR_UNC_UND 0x00000001/* Undefined */
Signature · 1 line
2.7.4
Re: [PATCH 04/15] PCI: Add pci_find_vsec_capability() to find a specific VSEC
[+cc Vinod, Dan, dmaengine]
Quoted 9 lines · Gustavo Pimentel
Add
pci_find_vsec_capability()that crawls through the device config space searching in all Vendor-Specific Extended Capabilities for a particular capability ID.Vendor-Specific Extended Capability (VSEC) is a PCIe capability (acts like a wrapper) specified by PCI-SIG that allows the vendor to create their own and specific capability in the device config space.
Signed-off-by Gustavo Pimentel <[email protected]>
If you fix the below, feel free to add my
Otherwise, I can take it myself. But that will be an ordering issue in the merge window if you merge the rest of the series via another tree.
Quoted 11 lines
--- drivers/pci/pci.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 5 +++++ 3 files changed, 35 insertions(+)drivers/pci/pci.c +0
-0
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 629
Quoted 7 lines
drivers/pci/pci.c +4
-0@@ -623,6 +623,35 @@ u64 pci_get_dsn(struct pci_dev *dev) }EXPORT_SYMBOL_GPL (pci_get_dsn); +/** +* pci_find_vsec_capability - Find a vendor-specific extended capability +* @dev: PCI device to query +* @cap: vendor-specific capability id code
s/id/ID/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 632
Quoted 3 lines
drivers/pci/pci.c +3
-0+* +* Returns the address of the vendor-specific structure that matches the +* requested capability id code within the device's PCI configuration space
s/id/ID/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 638
Quoted 6 lines
drivers/pci/pci.c +6
-0+* or 0 if it does not find a match. +*/ +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id) +{ +u32 header; +int vsec;
int vsec;
u32 header;
since that's the order they're used.
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 642
Quoted 4 lines
drivers/pci/pci.c +4
-0+ + vsec =pci_find_ext_capability (dev,PCI_EXT_CAP_ID_VNDR ); +while (vsec) { + if (pci_read_config_dword(dev, vsec + 0x4,
s/0x4/PCI_VSEC_HDR/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 645
Quoted 3 lines
drivers/pci/pci.c +3
-0+ &header) == PCIBIOS_SUCCESSFUL && + PCI_VSEC_CAP_ID(header) == vsec_cap_id) +break ;
return vsec;
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 651
Quoted 6 lines
drivers/pci/pci.c +6
-0+ + vsec =pci_find_next_ext_capability (dev, vsec, +PCI_EXT_CAP_ID_VNDR ); + } + +return vsec;
return 0;
Quoted 23 lines
drivers/pci/pci.c +3
-0+} +EXPORT_SYMBOL_GPL (pci_find_vsec_capability); +static int __pci_find_next_ht_cap (struct pci_dev *dev,int pos,int ht_cap) {int rc, ttl =PCI_FIND_CAP_TTL ;include/linux/pci.h +1
-0@@ -1067,6 +1067,7 @@ int pci_find_capability(struct pci_dev *dev, int cap);int pci_find_next_capability (struct pci_dev *dev,u8 pos,int cap);int pci_find_ext_capability (struct pci_dev *dev,int cap);int pci_find_next_ext_capability (struct pci_dev *dev,int pos,int cap); +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id);int pci_find_ht_capability (struct pci_dev *dev,int ht_cap);int pci_find_next_ht_capability (struct pci_dev *dev,int pos,int ht_cap);struct pci_bus *pci_find_next_bus (const struct pci_bus *from);include/uapi/linux/pci_regs.h +0
-0
include/uapi/linux/pci_regs.h line 736
Quoted 7 lines
include/uapi/linux/pci_regs.h +4
-0@@ -730,6 +730,11 @@#define PCI_EXT_CAP_DSN_SIZEOF 12#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 +/* Vendor-Specific Extended Capabilities */ +#define PCI_VSEC_CAP_ID (header) (header & 0x0000ffff) +#define PCI_VSEC_CAP_REV (header) ((header >> 16) & 0xf) +#define PCI_VSEC_CAP_LEN (header) ((header >> 20) & 0xffc)
Please put these next to the existing PCI_VSEC_HDR.
Why does PCI_VSEC_CAP_LEN mask with 0xffc instead of 0xfff? I don't see anything in the spec about VSEC Length having to be a multiple of 4 (PCIe r5.0, sec 7.9.5.2).
But you don't use this anyway, so I'd just drop it (and PCI_VSEC_CAP_REV) altogether.
Quoted 6 lines
include/uapi/linux/pci_regs.h +0
-0/* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4/* Uncorrectable Error Status */ #define PCI_ERR_UNC_UND 0x00000001/* Undefined */ Signature · 1 line
2.7.4
Re: [PATCH 04/15] PCI: Add pci_find_vsec_capability() to find a specific VSEC
[ add Ben ]
Quoted 14 lines · Bjorn Helgaas
[+cc Vinod, Dan, dmaengine]
Quoted 9 lines · Gustavo Pimentel
Add
pci_find_vsec_capability()that crawls through the device config space searching in all Vendor-Specific Extended Capabilities for a particular capability ID.Vendor-Specific Extended Capability (VSEC) is a PCIe capability (acts like a wrapper) specified by PCI-SIG that allows the vendor to create their own and specific capability in the device config space.
Signed-off-by Gustavo Pimentel <[email protected]>
Quoted 7 lines
If you fix the below, feel free to add my
Acked-by Bjorn Helgaas <[email protected]>Otherwise, I can take it myself. But that will be an ordering issue in the merge window if you merge the rest of the series via another tree.
I wonder if this warrants and if you'd be willing to stand up a stable branch for just this commit for concerned parties to integrate, because CXL development should adopt it as well.
Quoted 108 lines
Quoted 12 lines
--- drivers/pci/pci.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 5 +++++ 3 files changed, 35 insertions(+)drivers/pci/pci.c +0
-0drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 629
Quoted 7 lines
drivers/pci/pci.c +4
-0@@ -623,6 +623,35 @@ u64 pci_get_dsn(struct pci_dev *dev) }EXPORT_SYMBOL_GPL (pci_get_dsn); +/** +* pci_find_vsec_capability - Find a vendor-specific extended capability +* @dev: PCI device to query +* @cap: vendor-specific capability id code s/id/ID/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 632
Quoted 3 lines
drivers/pci/pci.c +3
-0+* +* Returns the address of the vendor-specific structure that matches the +* requested capability id code within the device's PCI configuration space s/id/ID/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 638
Quoted 6 lines
drivers/pci/pci.c +6
-0+* or 0 if it does not find a match. +*/ +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id) +{ +u32 header; +int vsec;int vsec;
u32 header;since that's the order they're used.
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 642
Quoted 4 lines
drivers/pci/pci.c +4
-0+ + vsec =pci_find_ext_capability (dev,PCI_EXT_CAP_ID_VNDR ); +while (vsec) { + if (pci_read_config_dword(dev, vsec + 0x4,s/0x4/PCI_VSEC_HDR/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 645
Quoted 3 lines
drivers/pci/pci.c +3
-0+ &header) == PCIBIOS_SUCCESSFUL && + PCI_VSEC_CAP_ID(header) == vsec_cap_id) +break ;return vsec;
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 651
Quoted 6 lines
drivers/pci/pci.c +6
-0+ + vsec =pci_find_next_ext_capability (dev, vsec, +PCI_EXT_CAP_ID_VNDR ); + } + +return vsec;return 0;
Quoted 23 lines
drivers/pci/pci.c +3
-0+} +EXPORT_SYMBOL_GPL (pci_find_vsec_capability); +static int __pci_find_next_ht_cap (struct pci_dev *dev,int pos,int ht_cap) {int rc, ttl =PCI_FIND_CAP_TTL ;include/linux/pci.h +1
-0@@ -1067,6 +1067,7 @@ int pci_find_capability(struct pci_dev *dev, int cap);int pci_find_next_capability (struct pci_dev *dev,u8 pos,int cap);int pci_find_ext_capability (struct pci_dev *dev,int cap);int pci_find_next_ext_capability (struct pci_dev *dev,int pos,int cap); +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id);int pci_find_ht_capability (struct pci_dev *dev,int ht_cap);int pci_find_next_ht_capability (struct pci_dev *dev,int pos,int ht_cap);struct pci_bus *pci_find_next_bus (const struct pci_bus *from);include/uapi/linux/pci_regs.h +0
-0include/uapi/linux/pci_regs.h line 736
Quoted 7 lines
include/uapi/linux/pci_regs.h +4
-0@@ -730,6 +730,11 @@#define PCI_EXT_CAP_DSN_SIZEOF 12#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 +/* Vendor-Specific Extended Capabilities */ +#define PCI_VSEC_CAP_ID (header) (header & 0x0000ffff) +#define PCI_VSEC_CAP_REV (header) ((header >> 16) & 0xf) +#define PCI_VSEC_CAP_LEN (header) ((header >> 20) & 0xffc)Please put these next to the existing
PCI_VSEC_HDR.Why does
PCI_VSEC_CAP_LENmask with0xffcinstead of0xfff? I don't see anything in the spec about VSEC Length having to be a multiple of 4 (PCIe r5.0, sec 7.9.5.2).But you don't use this anyway, so I'd just drop it (and
PCI_VSEC_CAP_REV) altogether.Quoted 6 lines
include/uapi/linux/pci_regs.h +0
-1/* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4/* Uncorrectable Error Status */ #define PCI_ERR_UNC_UND 0x00000001/* Undefined */ --2.7.4
Re: [PATCH 04/15] PCI: Add pci_find_vsec_capability() to find a specific VSEC
Quoted 21 lines · Dan Williams
[ add Ben ]
Quoted 18 lines · Bjorn Helgaas
[+cc Vinod, Dan, dmaengine]
Quoted 9 lines · Gustavo Pimentel
Add
pci_find_vsec_capability()that crawls through the device config space searching in all Vendor-Specific Extended Capabilities for a particular capability ID.Vendor-Specific Extended Capability (VSEC) is a PCIe capability (acts like a wrapper) specified by PCI-SIG that allows the vendor to create their own and specific capability in the device config space.
Signed-off-by Gustavo Pimentel <[email protected]>If you fix the below, feel free to add my
Acked-by Bjorn Helgaas <[email protected]>
Quoted 8 lines
Quoted 3 lines
Otherwise, I can take it myself. But that will be an ordering issue in the merge window if you merge the rest of the series via another tree.
I wonder if this warrants and if you'd be willing to stand up a stable branch for just this commit for concerned parties to integrate, because CXL development should adopt it as well.
Yeah, can we add DVSEC too please?
Quoted 108 lines
Quoted 108 lines
Quoted 12 lines
--- drivers/pci/pci.c | 29 +++++++++++++++++++++++++++++ include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 5 +++++ 3 files changed, 35 insertions(+)drivers/pci/pci.c +0
-0drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 629
Quoted 7 lines
drivers/pci/pci.c +4
-0@@ -623,6 +623,35 @@ u64 pci_get_dsn(struct pci_dev *dev) }EXPORT_SYMBOL_GPL (pci_get_dsn); +/** +* pci_find_vsec_capability - Find a vendor-specific extended capability +* @dev: PCI device to query +* @cap: vendor-specific capability id code s/id/ID/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 632
Quoted 3 lines
drivers/pci/pci.c +3
-0+* +* Returns the address of the vendor-specific structure that matches the +* requested capability id code within the device's PCI configuration space s/id/ID/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 638
Quoted 6 lines
drivers/pci/pci.c +6
-0+* or 0 if it does not find a match. +*/ +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id) +{ +u32 header; +int vsec;int vsec;
u32 header;since that's the order they're used.
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 642
Quoted 4 lines
drivers/pci/pci.c +4
-0+ + vsec =pci_find_ext_capability (dev,PCI_EXT_CAP_ID_VNDR ); +while (vsec) { + if (pci_read_config_dword(dev, vsec + 0x4,s/0x4/PCI_VSEC_HDR/
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 645
Quoted 3 lines
drivers/pci/pci.c +3
-0+ &header) == PCIBIOS_SUCCESSFUL && + PCI_VSEC_CAP_ID(header) == vsec_cap_id) +break ;return vsec;
drivers/pci/pci.c u64 pci_get_dsn(struct pci_dev *dev) · line 651
Quoted 6 lines
drivers/pci/pci.c +6
-0+ + vsec =pci_find_next_ext_capability (dev, vsec, +PCI_EXT_CAP_ID_VNDR ); + } + +return vsec;return 0;
Quoted 23 lines
drivers/pci/pci.c +3
-0+} +EXPORT_SYMBOL_GPL (pci_find_vsec_capability); +static int __pci_find_next_ht_cap (struct pci_dev *dev,int pos,int ht_cap) {int rc, ttl =PCI_FIND_CAP_TTL ;include/linux/pci.h +1
-0@@ -1067,6 +1067,7 @@ int pci_find_capability(struct pci_dev *dev, int cap);int pci_find_next_capability (struct pci_dev *dev,u8 pos,int cap);int pci_find_ext_capability (struct pci_dev *dev,int cap);int pci_find_next_ext_capability (struct pci_dev *dev,int pos,int cap); +int pci_find_vsec_capability (struct pci_dev *dev,int vsec_cap_id);int pci_find_ht_capability (struct pci_dev *dev,int ht_cap);int pci_find_next_ht_capability (struct pci_dev *dev,int pos,int ht_cap);struct pci_bus *pci_find_next_bus (const struct pci_bus *from);include/uapi/linux/pci_regs.h +0
-0include/uapi/linux/pci_regs.h line 736
Quoted 7 lines
include/uapi/linux/pci_regs.h +4
-0@@ -730,6 +730,11 @@#define PCI_EXT_CAP_DSN_SIZEOF 12#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 +/* Vendor-Specific Extended Capabilities */ +#define PCI_VSEC_CAP_ID (header) (header & 0x0000ffff) +#define PCI_VSEC_CAP_REV (header) ((header >> 16) & 0xf) +#define PCI_VSEC_CAP_LEN (header) ((header >> 20) & 0xffc)Please put these next to the existing
PCI_VSEC_HDR.Why does
PCI_VSEC_CAP_LENmask with0xffcinstead of0xfff? I don't see anything in the spec about VSEC Length having to be a multiple of 4 (PCIe r5.0, sec 7.9.5.2).But you don't use this anyway, so I'd just drop it (and
PCI_VSEC_CAP_REV) altogether.Quoted 6 lines
include/uapi/linux/pci_regs.h +0
-1/* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4/* Uncorrectable Error Status */ #define PCI_ERR_UNC_UND 0x00000001/* Undefined */ --2.7.4
RE: [PATCH 04/15] PCI: Add pci_find_vsec_capability() to find a specific VSEC
In reply to Bjorn HelgaasOn Mon, Feb 1, 2021 at 22:39:20, Bjorn Helgaas <[email protected]> wrote:
Hi Bjorn,
Quoted 6 lines
Quoted 4 lines
+/**
+ *pci_find_vsec_capability- Find a vendor-specific extended capability
+ * @dev: PCI device to query
+ * @cap: vendor-specific capability id codes/id/ID/
I will do it for all the requested changes.
Quoted 7 lines
include/uapi/linux/pci_regs.h line 736
Quoted 5 lines
include/uapi/linux/pci_regs.h +4
-0+/* Vendor-Specific Extended Capabilities */ +#define PCI_VSEC_CAP_ID (header) (header & 0x0000ffff) +#define PCI_VSEC_CAP_REV (header) ((header >> 16) & 0xf) +#define PCI_VSEC_CAP_LEN (header) ((header >> 20) & 0xffc)Please put these next to the existing
PCI_VSEC_HDR.
I will move it next to HDR. The 0xffc was a typo, thanks for noticing it. About the PCI_VSEC_CAP_REV and PCI_VSEC_CAP_LEN macros, I will be using on dw_edma_pcie_get_vsec_dma_data() from dw-edma-pcie.c has a validation of the right DVSEC.
I will send a version 2 with those fixes.
-Gustavo
PATCH 5/15 dmaengine: dw-edma: Add PCIe VSEC data retrieval support
In reply to Gustavo PimentelThe latest eDMA IP development implements a Vendor-Specific Extended Capability that contains the eDMA BAR, offset, map format, and the number of read/write channels available.
--- drivers/dma/dw-edma/dw-edma-core.c | 20 ++++--- drivers/dma/dw-edma/dw-edma-pcie.c | 114 ++++++++++++++++++++++++++++--------- 2 files changed, 99 insertions(+), 35 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +12 -8
@@ -863,15 +863,19 @@ int dw_edma_probe(struct dw_edma_chip *chip)raw_spin_lock_init (&dw->lock); -/* Find out how many write channels are supported by hardware */ - dw->wr_ch_cnt =dw_edma_v0_core_ch_count (dw,EDMA_DIR_WRITE ); -if (!dw->wr_ch_cnt) -return -EINVAL ; +if (!dw->wr_ch_cnt) { +/* Find out how many write channels are supported by hardware */ + dw->wr_ch_cnt =dw_edma_v0_core_ch_count (dw,EDMA_DIR_WRITE ); +if (!dw->wr_ch_cnt) +return -EINVAL ; + } -/* Find out how many read channels are supported by hardware */ - dw->rd_ch_cnt =dw_edma_v0_core_ch_count (dw,EDMA_DIR_READ ); -if (!dw->rd_ch_cnt) -return -EINVAL ; +if (!dw->rd_ch_cnt) { +/* Find out how many read channels are supported by hardware */ + dw->rd_ch_cnt =dw_edma_v0_core_ch_count (dw,EDMA_DIR_READ ); +if (!dw->rd_ch_cnt) +return -EINVAL ; + }dev_vdbg (dev,"Channels:\twrite=%d, read=%d\n" , dw->wr_ch_cnt, dw->rd_ch_cnt);
drivers/dma/dw-edma/dw-edma-pcie.c +87 -27
177 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 6/15 dmaengine: dw-edma: Add device_prep_interleave_dma() support
In reply to Gustavo PimentelAdd device_prep_interleave_dma() support to Synopsys DMA driver.
This feature implements a similar data transfer mechanism to the scatter-gather implementation.
--- drivers/dma/dw-edma/dw-edma-core.c | 85 ++++++++++++++++++++++++++++++-------- drivers/dma/dw-edma/dw-edma-core.h | 13 ++++-- 2 files changed, 78 insertions(+), 20 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +68 -17
@@ -329,7 +329,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)struct dw_edma_chunk *chunk;struct dw_edma_burst *burst;struct dw_edma_desc *desc; -u32 cnt; +u32 cnt =0 ;int i;if (!chan->configured)
@@ -352,12 +352,19 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)return NULL ; } -if (xfer->cyclic) { +if (xfer->type ==EDMA_XFER_CYCLIC ) {if (!xfer->xfer.cyclic.len || !xfer->xfer.cyclic.cnt)return NULL ; - }else { + }else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) {if (xfer->xfer.sg.len <1 )return NULL ; + }else if (xfer->type ==EDMA_XFER_INTERLEAVED ) { +if (!xfer->xfer.il->numf) +return NULL ; +if (xfer->xfer.il->numf >0 && xfer->xfer.il->frame_size >0 ) +return NULL ; + }else { +return NULL ; } desc =dw_edma_alloc_desc (chan);
@@ -368,18 +375,28 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)if (unlikely (!chunk)) goto err_alloc; - src_addr = chan->config.src_addr; - dst_addr = chan->config.dst_addr; +if (xfer->type ==EDMA_XFER_INTERLEAVED ) { + src_addr = xfer->xfer.il->src_start; + dst_addr = xfer->xfer.il->dst_start; + }else { + src_addr = chan->config.src_addr; + dst_addr = chan->config.dst_addr; + } -if (xfer->cyclic) { +if (xfer->type ==EDMA_XFER_CYCLIC ) { cnt = xfer->xfer.cyclic.cnt; - }else { + }else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { cnt = xfer->xfer.sg.len; sg = xfer->xfer.sg.sgl; + }else if (xfer->type ==EDMA_XFER_INTERLEAVED ) { +if (xfer->xfer.il->numf >0 ) + cnt = xfer->xfer.il->numf; +else + cnt = xfer->xfer.il->frame_size; }for (i =0 ; i < cnt; i++) { -if (!xfer->cyclic && !sg) +if (xfer->type ==EDMA_XFER_SCATTER_GATHER && !sg)break ;if (chunk->bursts_alloc == chan->ll_max) {
@@ -392,19 +409,21 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)if (unlikely (!burst)) goto err_alloc; -if (xfer->cyclic) +if (xfer->type ==EDMA_XFER_CYCLIC ) burst->sz = xfer->xfer.cyclic.len; -else +else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) burst->sz =sg_dma_len (sg); +else if (xfer->type ==EDMA_XFER_INTERLEAVED ) + burst->sz = xfer->xfer.il->sgl[i].size; chunk->ll_region.sz += burst->sz; desc->alloc_sz += burst->sz;if (chan->dir ==EDMA_DIR_WRITE ) { burst->sar = src_addr; -if (xfer->cyclic) { +if (xfer->type ==EDMA_XFER_CYCLIC ) { burst->dar = xfer->xfer.cyclic.paddr; - }else { + }else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { burst->dar = dst_addr;/* Unlike the typical assumption by other * drivers/IPs the peripheral memory isn't
@@ -416,9 +435,9 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) } }else { burst->dar = dst_addr; -if (xfer->cyclic) { +if (xfer->type ==EDMA_XFER_CYCLIC ) { burst->sar = xfer->xfer.cyclic.paddr; - }else { + }else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { burst->sar = src_addr;/* Unlike the typical assumption by other * drivers/IPs the peripheral memory isn't
@@ -430,10 +449,24 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) } } -if (!xfer->cyclic) { +if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { src_addr +=sg_dma_len (sg); dst_addr +=sg_dma_len (sg); sg =sg_next (sg); + }else if (xfer->type ==EDMA_XFER_INTERLEAVED && + xfer->xfer.il->frame_size >0 ) { +struct dma_interleaved_template *il = xfer->xfer.il; +struct data_chunk *dc = &il->sgl[i]; + +if (il->src_sgl) { + src_addr += burst->sz; + src_addr +=dmaengine_get_src_icg (il, dc); + } + +if (il->dst_sgl) { + dst_addr += burst->sz; + dst_addr +=dmaengine_get_dst_icg (il, dc); + } } }
@@ -459,7 +492,7 @@ dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, xfer.xfer.sg.sgl = sgl; xfer.xfer.sg.len = len; xfer.flags = flags; - xfer.cyclic = false; + xfer.type =EDMA_XFER_SCATTER_GATHER ;return dw_edma_device_transfer (&xfer); }
@@ -478,7 +511,23 @@ dw_edma_device_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t paddr, xfer.xfer.cyclic.len = len; xfer.xfer.cyclic.cnt = count; xfer.flags = flags; - xfer.cyclic = true; + xfer.type =EDMA_XFER_CYCLIC ; + +return dw_edma_device_transfer (&xfer); +} + +static struct dma_async_tx_descriptor * +dw_edma_device_prep_interleaved_dma (struct dma_chan *dchan, +struct dma_interleaved_template *ilt, +unsigned long flags) +{ +struct dw_edma_transfer xfer; + + xfer.dchan = dchan; + xfer.direction = ilt->dir; + xfer.xfer.il = ilt; + xfer.flags = flags; + xfer.type =EDMA_XFER_INTERLEAVED ;return dw_edma_device_transfer (&xfer); }
@@ -738,6 +787,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,dma_cap_set (DMA_SLAVE , dma->cap_mask);dma_cap_set (DMA_CYCLIC , dma->cap_mask);dma_cap_set (DMA_PRIVATE , dma->cap_mask); +dma_cap_set (DMA_INTERLEAVE , dma->cap_mask); dma->directions =BIT (write ?DMA_DEV_TO_MEM :DMA_MEM_TO_DEV ); dma->src_addr_widths =BIT (DMA_SLAVE_BUSWIDTH_4_BYTES ); dma->dst_addr_widths =BIT (DMA_SLAVE_BUSWIDTH_4_BYTES );
@@ -756,6 +806,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write, dma->device_tx_status = dw_edma_device_tx_status; dma->device_prep_slave_sg = dw_edma_device_prep_slave_sg; dma->device_prep_dma_cyclic = dw_edma_device_prep_dma_cyclic; + dma->device_prep_interleaved_dma = dw_edma_device_prep_interleaved_dma;dma_set_max_seg_size (dma->dev,U32_MAX );
drivers/dma/dw-edma/dw-edma-core.h +10 -3
@@ -39,6 +39,12 @@ enum dw_edma_status { EDMA_ST_BUSY }; +enum dw_edma_xfer_type { +EDMA_XFER_SCATTER_GATHER =0 , +EDMA_XFER_CYCLIC , +EDMA_XFER_INTERLEAVED +}; +struct dw_edma_chan ;struct dw_edma_chunk ;
@@ -146,12 +152,13 @@ struct dw_edma_cyclic {struct dw_edma_transfer {struct dma_chan *dchan;union dw_edma_xfer { -struct dw_edma_sg sg; -struct dw_edma_cyclic cyclic; +struct dw_edma_sg sg; +struct dw_edma_cyclic cyclic; +struct dma_interleaved_template *il; } xfer;enum dma_transfer_direction direction;unsigned long flags; -bool cyclic; +enum dw_edma_xfer_type type; }; static inline
Signature · 1 line
2.7.4
PATCH 7/15 dmaengine: dw-edma: Improve number of channels check
In reply to Gustavo PimentelIt was added some extra checks to ensure that the driver doesn't try to use more DMA channels than actually are available in hardware.
--- drivers/dma/dw-edma/dw-edma-core.c | 21 +++++++++------------ drivers/dma/dw-edma/dw-edma-core.h | 2 ++ 2 files changed, 11 insertions(+), 12 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +9 -12
@@ -914,19 +914,16 @@ int dw_edma_probe(struct dw_edma_chip *chip)raw_spin_lock_init (&dw->lock); -if (!dw->wr_ch_cnt) { -/* Find out how many write channels are supported by hardware */ - dw->wr_ch_cnt =dw_edma_v0_core_ch_count (dw,EDMA_DIR_WRITE ); -if (!dw->wr_ch_cnt) -return -EINVAL ; - } + dw->wr_ch_cnt =min_t (u16, dw->wr_ch_cnt, +dw_edma_v0_core_ch_count (dw,EDMA_DIR_WRITE )); + dw->wr_ch_cnt =min_t (u16, dw->wr_ch_cnt,EDMA_MAX_WR_CH ); -if (!dw->rd_ch_cnt) { -/* Find out how many read channels are supported by hardware */ - dw->rd_ch_cnt =dw_edma_v0_core_ch_count (dw,EDMA_DIR_READ ); -if (!dw->rd_ch_cnt) -return -EINVAL ; - } + dw->rd_ch_cnt =min_t (u16, dw->rd_ch_cnt, +dw_edma_v0_core_ch_count (dw,EDMA_DIR_READ )); + dw->rd_ch_cnt =min_t (u16, dw->rd_ch_cnt,EDMA_MAX_RD_CH ); + +if (!dw->wr_ch_cnt && !dw->rd_ch_cnt) +return -EINVAL ;dev_vdbg (dev,"Channels:\twrite=%d, read=%d\n" , dw->wr_ch_cnt, dw->rd_ch_cnt);
drivers/dma/dw-edma/dw-edma-core.h +2 -0
@@ -15,6 +15,8 @@#include "../virt-dma.h" #define EDMA_LL_SZ 24 +#define EDMA_MAX_WR_CH 8 +#define EDMA_MAX_RD_CH 8enum dw_edma_dir {EDMA_DIR_WRITE =0 ,
Signature · 1 line
2.7.4
PATCH 8/15 dmaengine: dw-edma: Reorder variables to keep consistency
In reply to Gustavo PimentelIn the driver code structure, I tried to keep the code style consistency by writing the write channels instructions first, and then follow by the read channels instructions, mimicking the hardware implementation.
However, this code style failed in some cases. This patch fixes that and no functional changes are expected.
--- drivers/dma/dw-edma/dw-edma-pcie.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/dma/dw-edma/dw-edma-pcie.c +5 -5
@@ -20,8 +20,8 @@#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_RD_CH GENMASK(25, 16)#define DW_PCIE_VSEC_DMA_WR_CH GENMASK(9, 0) +#define DW_PCIE_VSEC_DMA_RD_CH GENMASK(25, 16)struct dw_edma_pcie_data {/* eDMA registers location */
@@ -39,8 +39,8 @@ struct dw_edma_pcie_data {/* Other */ enum dw_edma_map_format mf;u8 irqs; -u16 rd_ch_cnt;u16 wr_ch_cnt; +u16 rd_ch_cnt; };static const struct dw_edma_pcie_data snps_edda_data = {
@@ -59,8 +59,8 @@ static const struct dw_edma_pcie_data snps_edda_data = {/* Other */ .mf = EDMA_MF_EDMA_UNROLL, .irqs = 1, - .rd_ch_cnt = 0, .wr_ch_cnt = 0, + .rd_ch_cnt = 0, };static int dw_edma_pcie_irq_vector (struct device *dev,unsigned int nr)
@@ -99,8 +99,8 @@ static void dw_edma_pcie_get_vsec_dma_data(struct pci_dev *pdev, pdata->rg_bar =FIELD_GET (DW_PCIE_VSEC_DMA_BAR , val);pci_read_config_dword (pdev, vsec +0xc , &val); - pdata->rd_ch_cnt =FIELD_GET (DW_PCIE_VSEC_DMA_RD_CH , val); pdata->wr_ch_cnt =FIELD_GET (DW_PCIE_VSEC_DMA_WR_CH , val); + pdata->rd_ch_cnt =FIELD_GET (DW_PCIE_VSEC_DMA_RD_CH , val);pci_read_config_dword (pdev, vsec +0x14 , &val); off = val;
@@ -216,8 +216,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, dw->mf = vsec_data.mf; dw->nr_irqs = nr_irqs; dw->ops = &dw_edma_pcie_core_ops; - dw->rd_ch_cnt = vsec_data.rd_ch_cnt; dw->wr_ch_cnt = vsec_data.wr_ch_cnt; + dw->rd_ch_cnt = vsec_data.rd_ch_cnt;/* Debug info */ if (dw->mf ==EDMA_MF_EDMA_LEGACY )
Signature · 1 line
2.7.4
PATCH 9/15 dmaengine: dw-edma: Improve the linked list and data blocks definition
In reply to Gustavo PimentelIn the previous implementation the driver assumes that only existed 2 memory spaces that would be equal distributed amount the write/read channels.
This might not be the case on some other implementations, therefore this patches changes this requirement so that each write/read channel has their own linked list and data space well defined, which allows different sizes and locations.
--- drivers/dma/dw-edma/dw-edma-core.c | 51 +++++----- drivers/dma/dw-edma/dw-edma-core.h | 9 +- drivers/dma/dw-edma/dw-edma-pcie.c | 185 ++++++++++++++++++++++++++----------- 3 files changed, 160 insertions(+), 85 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +24 -27
@@ -81,8 +81,13 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)* - Even chunks originate CB equal to 1 */ chunk->cb = !(desc->chunks_alloc %2 ); - chunk->ll_region.paddr = dw->ll_region.paddr + chan->ll_off; - chunk->ll_region.vaddr = dw->ll_region.vaddr + chan->ll_off; +if (chan->dir ==EDMA_DIR_WRITE ) { + chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr; + chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr; + }else { + chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr; + chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr; + }if (desc->chunk) {/* Create and add new element into the linked list */
@@ -691,24 +696,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,struct device *dev = chip->dev;struct dw_edma *dw = chip->dw;struct dw_edma_chan *chan; -size_t ll_chunk, dt_chunk;struct dw_edma_irq *irq;struct dma_device *dma; -u32 i, j, cnt, ch_cnt;u32 alloc, off_alloc; +u32 i, j, cnt;int err =0 ;u32 pos; - ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt; - ll_chunk = dw->ll_region.sz; - dt_chunk = dw->dt_region.sz; - -/* Calculate linked list chunk for each channel */ - ll_chunk /=roundup_pow_of_two (ch_cnt); - -/* Calculate linked list chunk for each channel */ - dt_chunk /=roundup_pow_of_two (ch_cnt); -if (write) { i =0 ; cnt = dw->wr_ch_cnt;
@@ -740,14 +734,14 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write, chan->request =EDMA_REQ_NONE ; chan->status =EDMA_ST_IDLE ; - chan->ll_off = (ll_chunk * i); - chan->ll_max = (ll_chunk /EDMA_LL_SZ ) -1 ; - - chan->dt_off = (dt_chunk * i); +if (write) + chan->ll_max = (dw->ll_region_wr[j].sz /EDMA_LL_SZ ); +else + chan->ll_max = (dw->ll_region_rd[j].sz /EDMA_LL_SZ ); + chan->ll_max -=1 ; -dev_vdbg (dev,"L. List:\tChannel %s[%u] off=0x%.8lx, max_cnt=%u\n" , - write ?"write" :"read" , j, - chan->ll_off, chan->ll_max); +dev_vdbg (dev,"L. List:\tChannel %s[%u] max_cnt=%u\n" , + write ?"write" :"read" , j, chan->ll_max);if (dw->nr_irqs ==1 ) pos =0 ;
@@ -772,12 +766,15 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write, chan->vc.desc_free = vchan_free_desc;vchan_init (&chan->vc, dma); - dt_region->paddr = dw->dt_region.paddr + chan->dt_off; - dt_region->vaddr = dw->dt_region.vaddr + chan->dt_off; - dt_region->sz = dt_chunk; - -dev_vdbg (dev,"Data:\tChannel %s[%u] off=0x%.8lx\n" , - write ?"write" :"read" , j, chan->dt_off); +if (write) { + dt_region->paddr = dw->dt_region_wr[j].paddr; + dt_region->vaddr = dw->dt_region_wr[j].vaddr; + dt_region->sz = dw->dt_region_wr[j].sz; + }else { + dt_region->paddr = dw->dt_region_rd[j].paddr; + dt_region->vaddr = dw->dt_region_rd[j].vaddr; + dt_region->sz = dw->dt_region_rd[j].sz; + }dw_edma_v0_core_device_config (chan); }
drivers/dma/dw-edma/dw-edma-core.h +4 -5
@@ -91,11 +91,8 @@ struct dw_edma_chan {int id;enum dw_edma_dir dir; -off_t ll_off;u32 ll_max; -off_t dt_off; -struct msi_msg msi;enum dw_edma_request request;
@@ -126,8 +123,10 @@ struct dw_edma {u16 rd_ch_cnt;struct dw_edma_region rg_region;/* Registers */ -struct dw_edma_region ll_region;/* Linked list */ -struct dw_edma_region dt_region;/* Data */ +struct dw_edma_region ll_region_wr[EDMA_MAX_WR_CH ]; +struct dw_edma_region ll_region_rd[EDMA_MAX_RD_CH ]; +struct dw_edma_region dt_region_wr[EDMA_MAX_WR_CH ]; +struct dw_edma_region dt_region_rd[EDMA_MAX_RD_CH ];struct dw_edma_irq *irq;int nr_irqs;
drivers/dma/dw-edma/dw-edma-pcie.c +132 -53
253 lines not on this page · raw message
Signature · 1 line
2.7.4
PATCH 10/15 dmaengine: dw-edma: Change linked list and data blocks offset and sizes
In reply to Gustavo PimentelChanges the linked list and data blocks offset and sizes to follow the recommendation given by the hardware team for the IPK solution.
Although the previous data blocks offset and sizes are still valid and functional, using them that might present some issues related to the IPK solution, since this solution is based on FPGA and might be subjected to timmings constrains.
--- drivers/dma/dw-edma/dw-edma-pcie.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/dma/dw-edma/dw-edma-pcie.c +16 -16
@@ -59,29 +59,29 @@ static const struct dw_edma_pcie_data snps_edda_data = { .rg.sz = 0x00002000, /* 8 Kbytes */ /* eDMA memory linked list location */ .ll_wr = { -/* Channel 0 - BAR 2, offset 0 Mbytes, size 2 Mbytes */ -DW_BLOCK (BAR_2 ,0x00000000 ,0x00200000 ) - /* Channel 1 - BAR 2, offset 2 Mbytes, size 2 Mbytes */ -DW_BLOCK (BAR_2 ,0x00200000 ,0x00200000 ) +/* Channel 0 - BAR 2, offset 0 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00000000 ,0x00000800 ) + /* Channel 1 - BAR 2, offset 2 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00200000 ,0x00000800 ) }, .ll_rd = { -/* Channel 0 - BAR 2, offset 4 Mbytes, size 2 Mbytes */ -DW_BLOCK (BAR_2 ,0x00400000 ,0x00200000 ) - /* Channel 1 - BAR 2, offset 6 Mbytes, size 2 Mbytes */ -DW_BLOCK (BAR_2 ,0x00600000 ,0x00200000 ) +/* Channel 0 - BAR 2, offset 4 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00400000 ,0x00000800 ) + /* Channel 1 - BAR 2, offset 6 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00600000 ,0x00000800 ) },/* eDMA memory data location */ .dt_wr = { -/* Channel 0 - BAR 2, offset 8 Mbytes, size 14 Mbytes */ -DW_BLOCK (BAR_2 ,0x00800000 ,0x00e00000 ) - /* Channel 1 - BAR 2, offset 22 Mbytes, size 14 Mbytes */ -DW_BLOCK (BAR_2 ,0x01600000 ,0x00e00000 ) +/* Channel 0 - BAR 2, offset 8 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00800000 ,0x00000800 ) + /* Channel 1 - BAR 2, offset 9 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00900000 ,0x00000800 ) }, .dt_rd = { -/* Channel 0 - BAR 2, offset 36 Mbytes, size 14 Mbytes */ -DW_BLOCK (BAR_2 ,0x02400000 ,0x00e00000 ) - /* Channel 1 - BAR 2, offset 50 Mbytes, size 14 Mbytes */ -DW_BLOCK (BAR_2 ,0x03200000 ,0x00e00000 ) +/* Channel 0 - BAR 2, offset 10 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00a00000 ,0x00000800 ) + /* Channel 1 - BAR 2, offset 11 Mbytes, size 2 Kbytes */ +DW_BLOCK (BAR_2 ,0x00b00000 ,0x00000800 ) },/* Other */ .mf = EDMA_MF_EDMA_UNROLL,
Signature · 1 line
2.7.4
PATCH 11/15 dmaengine: dw-edma: Move struct dentry variable from static definition into dw_edma struct
In reply to Gustavo PimentelMove struct dentry variable from static definition (dw-edma-v0-debugfs.c) into dw_edma struct (dw-edma-core.h)
Also the variable was renamed from base_dir to debugfs.
--- drivers/dma/dw-edma/dw-edma-core.c | 2 +- drivers/dma/dw-edma/dw-edma-core.h | 3 +++ drivers/dma/dw-edma/dw-edma-v0-core.c | 4 ++-- drivers/dma/dw-edma/dw-edma-v0-core.h | 2 +- drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 22 +++++++++++++--------- drivers/dma/dw-edma/dw-edma-v0-debugfs.h | 4 ++-- 6 files changed, 22 insertions(+), 15 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +1 -1
@@ -1003,7 +1003,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)dma_async_device_unregister (&dw->rd_edma);/* Turn debugfs off */ -dw_edma_v0_core_debugfs_off (); +dw_edma_v0_core_debugfs_off (chip);return 0 ; }
drivers/dma/dw-edma/dw-edma-core.h +3 -0
@@ -137,6 +137,9 @@ struct dw_edma {const struct dw_edma_core_ops *ops;raw_spinlock_t lock;/* Only for legacy */ +#ifdef CONFIG_DEBUG_FS +struct dentry *debugfs; +#endif /* CONFIG_DEBUG_FS */ };struct dw_edma_sg {
drivers/dma/dw-edma/dw-edma-v0-core.c +2 -2
@@ -506,7 +506,7 @@ void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)dw_edma_v0_debugfs_on (chip); } -void dw_edma_v0_core_debugfs_off (void ) +void dw_edma_v0_core_debugfs_off (struct dw_edma_chip *chip) { -dw_edma_v0_debugfs_off (); +dw_edma_v0_debugfs_off (chip); }
drivers/dma/dw-edma/dw-edma-v0-core.h +1 -1
@@ -23,6 +23,6 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);int dw_edma_v0_core_device_config (struct dw_edma_chan *chan);/* eDMA debug fs callbacks */ void dw_edma_v0_core_debugfs_on (struct dw_edma_chip *chip); -void dw_edma_v0_core_debugfs_off (void ); +void dw_edma_v0_core_debugfs_off (struct dw_edma_chip *chip);#endif /* _DW_EDMA_V0_CORE_H */
drivers/dma/dw-edma/dw-edma-v0-debugfs.c +13 -9
@@ -38,7 +38,6 @@#define CHANNEL_STR "channel"#define REGISTERS_STR "registers" -static struct dentry *base_dir;static struct dw_edma *dw;static struct dw_edma_v0_regs __iomem *regs;
@@ -272,7 +271,7 @@ static void dw_edma_debugfs_regs(void)struct dentry *regs_dir;int nr_entries; - regs_dir =debugfs_create_dir (REGISTERS_STR , base_dir); + regs_dir =debugfs_create_dir (REGISTERS_STR , dw->debugfs);if (!regs_dir)return ;
@@ -293,18 +292,23 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)if (!regs)return ; - base_dir =debugfs_create_dir (dw->name,NULL ); -if (!base_dir) + dw->debugfs =debugfs_create_dir (dw->name,NULL ); +if (!dw->debugfs)return ; -debugfs_create_u32 ("mf" ,0444 , base_dir, &dw->mf); -debugfs_create_u16 ("wr_ch_cnt" ,0444 , base_dir, &dw->wr_ch_cnt); -debugfs_create_u16 ("rd_ch_cnt" ,0444 , base_dir, &dw->rd_ch_cnt); +debugfs_create_u32 ("mf" ,0444 , dw->debugfs, &dw->mf); +debugfs_create_u16 ("wr_ch_cnt" ,0444 , dw->debugfs, &dw->wr_ch_cnt); +debugfs_create_u16 ("rd_ch_cnt" ,0444 , dw->debugfs, &dw->rd_ch_cnt);dw_edma_debugfs_regs (); } -void dw_edma_v0_debugfs_off (void ) +void dw_edma_v0_debugfs_off (struct dw_edma_chip *chip) { -debugfs_remove_recursive (base_dir); + dw = chip->dw; +if (!dw) +return ; + +debugfs_remove_recursive (dw->debugfs); + dw->debugfs =NULL ; }
drivers/dma/dw-edma/dw-edma-v0-debugfs.h +2 -2
@@ -13,13 +13,13 @@#ifdef CONFIG_DEBUG_FS void dw_edma_v0_debugfs_on (struct dw_edma_chip *chip); -void dw_edma_v0_debugfs_off (void ); +void dw_edma_v0_debugfs_off (struct dw_edma_chip *chip);#else static inline void dw_edma_v0_debugfs_on (struct dw_edma_chip *chip) { } -static inline void dw_edma_v0_debugfs_off (void ) +static inline void dw_edma_v0_debugfs_off (struct dw_edma_chip *chip) { }#endif /* CONFIG_DEBUG_FS */
Signature · 1 line
2.7.4
PATCH 12/15 dmaengine: dw-edma: Fix crash on loading/unloading driver
In reply to Gustavo PimentelWhen the driver is compiled as a module and loaded if we try to unload it, the Kernel shows a crash log. This Kernel crash is due to the dma_async_device_unregister() call done after deleting the channels, this patch fixes this issue.
--- drivers/dma/dw-edma/dw-edma-core.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +5 -6
@@ -986,22 +986,21 @@ int dw_edma_remove(struct dw_edma_chip *chip)/* Power management */ pm_runtime_disable (dev); +/* Deregister eDMA device */ +dma_async_device_unregister (&dw->wr_edma);list_for_each_entry_safe (chan, _chan, &dw->wr_edma.channels, vc.chan.device_node) { -list_del (&chan->vc.chan.device_node);tasklet_kill (&chan->vc.task); +list_del (&chan->vc.chan.device_node); } +dma_async_device_unregister (&dw->rd_edma);list_for_each_entry_safe (chan, _chan, &dw->rd_edma.channels, vc.chan.device_node) { -list_del (&chan->vc.chan.device_node);tasklet_kill (&chan->vc.task); +list_del (&chan->vc.chan.device_node); } -/* Deregister eDMA device */ -dma_async_device_unregister (&dw->wr_edma); -dma_async_device_unregister (&dw->rd_edma); -/* Turn debugfs off */ dw_edma_v0_core_debugfs_off (chip);
Signature · 1 line
2.7.4
PATCH 13/15 dmaengine: dw-edma: Change DMA abreviation from lower into upper case
In reply to Gustavo PimentelTo keep code consistent, some comments with dma keyword written in lower case are now in upper case.
--- drivers/dma/dw-edma/dw-edma-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +3 -3
@@ -341,15 +341,15 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)return NULL ;switch (chan->config.direction) { -case DMA_DEV_TO_MEM :/* local dma */ +case DMA_DEV_TO_MEM :/* local DMA */ if (dir ==DMA_DEV_TO_MEM && chan->dir ==EDMA_DIR_READ )break ;return NULL ; -case DMA_MEM_TO_DEV :/* local dma */ +case DMA_MEM_TO_DEV :/* local DMA */ if (dir ==DMA_MEM_TO_DEV && chan->dir ==EDMA_DIR_WRITE )break ;return NULL ; -default :/* remote dma */ +default :/* remote DMA */ if (dir ==DMA_MEM_TO_DEV && chan->dir ==EDMA_DIR_READ )break ;if (dir ==DMA_DEV_TO_MEM && chan->dir ==EDMA_DIR_WRITE )
Signature · 1 line
2.7.4
PATCH 14/15 dmaengine: dw-edma: Revert fix scatter-gather address calculation
In reply to Gustavo PimentelReverting the applied patch because it caused a regression on ARC700 platform (32 bits).
--- drivers/dma/dw-edma/dw-edma-core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/dma/dw-edma/dw-edma-core.c +4 -4
@@ -429,7 +429,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)if (xfer->type ==EDMA_XFER_CYCLIC ) { burst->dar = xfer->xfer.cyclic.paddr; }else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { - burst->dar = dst_addr; + src_addr +=sg_dma_len (sg); + burst->dar =sg_dma_address (sg);/* Unlike the typical assumption by other * drivers/IPs the peripheral memory isn't * a FIFO memory, in this case, it's a
@@ -443,7 +444,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)if (xfer->type ==EDMA_XFER_CYCLIC ) { burst->sar = xfer->xfer.cyclic.paddr; }else if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { - burst->sar = src_addr; + dst_addr +=sg_dma_len (sg); + burst->sar =sg_dma_address (sg);/* Unlike the typical assumption by other * drivers/IPs the peripheral memory isn't * a FIFO memory, in this case, it's a
@@ -455,8 +457,6 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer) }if (xfer->type ==EDMA_XFER_SCATTER_GATHER ) { - src_addr +=sg_dma_len (sg); - dst_addr +=sg_dma_len (sg); sg =sg_next (sg); }else if (xfer->type ==EDMA_XFER_INTERLEAVED && xfer->xfer.il->frame_size >0 ) {
Signature · 1 line
2.7.4
PATCH 15/15 dmaengine: dw-edma: Add pcim_iomap_table return checker
In reply to Gustavo PimentelDetected by CoverityScan CID 16555 ("Dereference null return")
--- drivers/dma/dw-edma/dw-edma-pcie.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/dma/dw-edma/dw-edma-pcie.c +15 -0
@@ -238,6 +238,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, dw->rd_ch_cnt = vsec_data.rd_ch_cnt; dw->rg_region.vaddr =pcim_iomap_table (pdev)[vsec_data.rg.bar]; +if (!dw->rg_region.vaddr) +return -ENOMEM ; + dw->rg_region.vaddr += vsec_data.rg.off; dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start; dw->rg_region.paddr += vsec_data.rg.off;
@@ -250,12 +253,18 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,struct dw_edma_block *dt_block = &vsec_data.dt_wr[i]; ll_region->vaddr =pcim_iomap_table (pdev)[ll_block->bar]; +if (!ll_region->vaddr) +return -ENOMEM ; + ll_region->vaddr += ll_block->off; ll_region->paddr = pdev->resource[ll_block->bar].start; ll_region->paddr += ll_block->off; ll_region->sz = ll_block->sz; dt_region->vaddr =pcim_iomap_table (pdev)[dt_block->bar]; +if (!dt_region->vaddr) +return -ENOMEM ; + dt_region->vaddr += dt_block->off; dt_region->paddr = pdev->resource[dt_block->bar].start; dt_region->paddr += dt_block->off;
@@ -269,12 +278,18 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,struct dw_edma_block *dt_block = &vsec_data.dt_rd[i]; ll_region->vaddr =pcim_iomap_table (pdev)[ll_block->bar]; +if (!ll_region->vaddr) +return -ENOMEM ; + ll_region->vaddr += ll_block->off; ll_region->paddr = pdev->resource[ll_block->bar].start; ll_region->paddr += ll_block->off; ll_region->sz = ll_block->sz; dt_region->vaddr =pcim_iomap_table (pdev)[dt_block->bar]; +if (!dt_region->vaddr) +return -ENOMEM ; + dt_region->vaddr += dt_block->off; dt_region->paddr = pdev->resource[dt_block->bar].start; dt_region->paddr += dt_block->off;
Signature · 1 line
2.7.4
Vinod Koul
maintainerQuoted 28 lines · Gustavo Pimentel
This patch series adds the HDMA support, as long the IP design has set the compatible register map parameter, which allows compatibility at some degree for the existing Synopsys DesignWare eDMA driver that is already available on the Kernel.
The HDMA "Hyper-DMA" IP is an enhancement of the eDMA "embedded-DMA" IP.
This new improvement comes with a PCI DVSEC that allows to the driver recognize and switch behavior if it's an eDMA or an HDMA, becoming retrocompatible, in the absence of this DVSEC, the driver will assume that is an eDMA IP.
It also adds the interleaved support, since it will be similar to the current scatter-gather implementation.
As well fixes/improves some abnormal behaviors not detected before, such as:
- crash on loading/unloading driver
- memory space definition for the data area and for the linked list space
- scatter-gather address calculation on 32 bits platforms
- minor comment and variable reorderingCc Vinod Koul <[email protected]>Cc Dan Williams <[email protected]>Cc Bjorn Helgaas <[email protected]>
Quoted 5 lines
Gustavo Pimentel (15):
dmaengine: dw-edma: Addwriteq()andreadq()for 64 bits architectures
dmaengine: dw-edma: Fix comments offset characters' alignment
dmaengine: dw-edma: Add support for the HDMA feature
PCI: Addpci_find_vsec_capability()to find a specific VSEC
Had this been picked up.. I see we have dependency on pci patch for this series..
Quoted 29 lines
dmaengine: dw-edma: Add PCIe VSEC data retrieval support
dmaengine: dw-edma: Adddevice_prep_interleave_dma()support
dmaengine: dw-edma: Improve number of channels check
dmaengine: dw-edma: Reorder variables to keep consistency
dmaengine: dw-edma: Improve the linked list and data blocks definition
dmaengine: dw-edma: Change linked list and data blocks offset and
sizes
dmaengine: dw-edma: Move struct dentry variable from static definition
intodw_edmastruct
dmaengine: dw-edma: Fix crash on loading/unloading driver
dmaengine: dw-edma: Change DMA abreviation from lower into upper case
dmaengine: dw-edma: Revert fix scatter-gather address calculation
dmaengine: dw-edma: Addpcim_iomap_tablereturn checkerdrivers/dma/dw-edma/dw-edma-core.c | 178 +++++++++++------- drivers/dma/dw-edma/dw-edma-core.h | 37 ++-- drivers/dma/dw-edma/dw-edma-pcie.c | 275 +++++++++++++++++++++------- drivers/dma/dw-edma/dw-edma-v0-core.c | 300 ++++++++++++++++++++++++------- drivers/dma/dw-edma/dw-edma-v0-core.h | 2 +- drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 77 ++++---- drivers/dma/dw-edma/dw-edma-v0-debugfs.h | 4 +- drivers/dma/dw-edma/dw-edma-v0-regs.h | 291 +++++++++++++++++++----------- drivers/pci/pci.c | 29 +++ include/linux/pci.h | 1 + include/uapi/linux/pci_regs.h | 5 + 11 files changed, 844 insertions(+), 355 deletions(-)Signature · 1 line
2.7.4
Signature · 1 line
~Vinod