Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: dw: Introduce max burst length hw config

IP core of the DW DMA controller may be synthesized with different
max burst length of the transfers per each channel. According to Synopsis
having the fixed maximum burst transactions length may provide some
performance gain. At the same time setting up the source and destination
multi size exceeding the max burst length limitation may cause a serious
problems. In our case the DMA transaction just hangs up. In order to fix
this lets introduce the max burst length platform config of the DW DMA
controller device and don't let the DMA channels configuration code
exceed the burst length hardware limitation.

Note the maximum burst length parameter can be detected either in runtime
from the DWC parameter registers or from the dedicated DT property.
Depending on the IP core configuration the maximum value can vary from
channel to channel so by overriding the channel slave max_burst capability
we make sure a DMA consumer will get the channel-specific max burst
length.

Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20200723005848.31907-10-Sergey.Semin@baikalelectronics.ru
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Serge Semin and committed by
Vinod Koul
ca7f2851 585d3545

+26
+16
drivers/dma/dw/core.c
··· 791 791 792 792 memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); 793 793 794 + dwc->dma_sconfig.src_maxburst = 795 + clamp(dwc->dma_sconfig.src_maxburst, 0U, dwc->max_burst); 796 + dwc->dma_sconfig.dst_maxburst = 797 + clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst); 798 + 794 799 dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst); 795 800 dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst); 796 801 ··· 1054 1049 dev_vdbg(chan2dev(chan), "%s: done\n", __func__); 1055 1050 } 1056 1051 1052 + static void dwc_caps(struct dma_chan *chan, struct dma_slave_caps *caps) 1053 + { 1054 + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 1055 + 1056 + caps->max_burst = dwc->max_burst; 1057 + } 1058 + 1057 1059 int do_dma_probe(struct dw_dma_chip *chip) 1058 1060 { 1059 1061 struct dw_dma *dw = chip->dw; ··· 1201 1189 dwc->nollp = 1202 1190 (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0 || 1203 1191 (dwc_params >> DWC_PARAMS_HC_LLP & 0x1) == 1; 1192 + dwc->max_burst = 1193 + (0x4 << (dwc_params >> DWC_PARAMS_MSIZE & 0x7)); 1204 1194 } else { 1205 1195 dwc->block_size = pdata->block_size; 1206 1196 dwc->nollp = !pdata->multi_block[i]; 1197 + dwc->max_burst = pdata->max_burst[i] ?: DW_DMA_MAX_BURST; 1207 1198 } 1208 1199 } 1209 1200 ··· 1229 1214 dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy; 1230 1215 dw->dma.device_prep_slave_sg = dwc_prep_slave_sg; 1231 1216 1217 + dw->dma.device_caps = dwc_caps; 1232 1218 dw->dma.device_config = dwc_config; 1233 1219 dw->dma.device_pause = dwc_pause; 1234 1220 dw->dma.device_resume = dwc_resume;
+5
drivers/dma/dw/of.c
··· 98 98 pdata->multi_block[tmp] = 1; 99 99 } 100 100 101 + if (of_property_read_u32_array(np, "snps,max-burst-len", pdata->max_burst, 102 + nr_channels)) { 103 + memset32(pdata->max_burst, DW_DMA_MAX_BURST, nr_channels); 104 + } 105 + 101 106 if (!of_property_read_u32(np, "snps,dma-protection-control", &tmp)) { 102 107 if (tmp > CHAN_PROTCTL_MASK) 103 108 return NULL;
+2
drivers/dma/dw/regs.h
··· 126 126 /* Bitfields in DWC_PARAMS */ 127 127 #define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */ 128 128 #define DWC_PARAMS_HC_LLP 13 /* set LLP register to zero */ 129 + #define DWC_PARAMS_MSIZE 16 /* max group transaction size */ 129 130 130 131 /* bursts size */ 131 132 enum dw_dma_msize { ··· 285 284 /* hardware configuration */ 286 285 unsigned int block_size; 287 286 bool nollp; 287 + u32 max_burst; 288 288 289 289 /* custom slave configuration */ 290 290 struct dw_dma_slave dws;
+3
include/linux/platform_data/dma-dw.h
··· 44 44 * @data_width: Maximum data width supported by hardware per AHB master 45 45 * (in bytes, power of 2) 46 46 * @multi_block: Multi block transfers supported by hardware per channel. 47 + * @max_burst: Maximum value of burst transaction size supported by hardware 48 + * per channel (in units of CTL.SRC_TR_WIDTH/CTL.DST_TR_WIDTH). 47 49 * @protctl: Protection control signals setting per channel. 48 50 */ 49 51 struct dw_dma_platform_data { ··· 60 58 unsigned char nr_masters; 61 59 unsigned char data_width[DW_DMA_MAX_NR_MASTERS]; 62 60 unsigned char multi_block[DW_DMA_MAX_NR_CHANNELS]; 61 + u32 max_burst[DW_DMA_MAX_NR_CHANNELS]; 63 62 #define CHAN_PROTCTL_PRIVILEGED BIT(0) 64 63 #define CHAN_PROTCTL_BUFFERABLE BIT(1) 65 64 #define CHAN_PROTCTL_CACHEABLE BIT(2)