Skip to content

Commit ca7f285

Browse files
fancervinodkoul
authored andcommitted
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 <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 585d354 commit ca7f285

File tree

4 files changed

+26
-0
lines changed

4 files changed

+26
-0
lines changed

drivers/dma/dw/core.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,11 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
791791

792792
memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
793793

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+
794799
dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst);
795800
dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst);
796801

@@ -1049,6 +1054,13 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
10491054
dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
10501055
}
10511056

1057+
static void dwc_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
1058+
{
1059+
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
1060+
1061+
caps->max_burst = dwc->max_burst;
1062+
}
1063+
10521064
int do_dma_probe(struct dw_dma_chip *chip)
10531065
{
10541066
struct dw_dma *dw = chip->dw;
@@ -1189,9 +1201,12 @@ int do_dma_probe(struct dw_dma_chip *chip)
11891201
dwc->nollp =
11901202
(dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0 ||
11911203
(dwc_params >> DWC_PARAMS_HC_LLP & 0x1) == 1;
1204+
dwc->max_burst =
1205+
(0x4 << (dwc_params >> DWC_PARAMS_MSIZE & 0x7));
11921206
} else {
11931207
dwc->block_size = pdata->block_size;
11941208
dwc->nollp = !pdata->multi_block[i];
1209+
dwc->max_burst = pdata->max_burst[i] ?: DW_DMA_MAX_BURST;
11951210
}
11961211
}
11971212

@@ -1214,6 +1229,7 @@ int do_dma_probe(struct dw_dma_chip *chip)
12141229
dw->dma.device_prep_dma_memcpy = dwc_prep_dma_memcpy;
12151230
dw->dma.device_prep_slave_sg = dwc_prep_slave_sg;
12161231

1232+
dw->dma.device_caps = dwc_caps;
12171233
dw->dma.device_config = dwc_config;
12181234
dw->dma.device_pause = dwc_pause;
12191235
dw->dma.device_resume = dwc_resume;

drivers/dma/dw/of.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev)
9898
pdata->multi_block[tmp] = 1;
9999
}
100100

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+
101106
if (!of_property_read_u32(np, "snps,dma-protection-control", &tmp)) {
102107
if (tmp > CHAN_PROTCTL_MASK)
103108
return NULL;

drivers/dma/dw/regs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ struct dw_dma_regs {
126126
/* Bitfields in DWC_PARAMS */
127127
#define DWC_PARAMS_MBLK_EN 11 /* multi block transfer */
128128
#define DWC_PARAMS_HC_LLP 13 /* set LLP register to zero */
129+
#define DWC_PARAMS_MSIZE 16 /* max group transaction size */
129130

130131
/* bursts size */
131132
enum dw_dma_msize {
@@ -284,6 +285,7 @@ struct dw_dma_chan {
284285
/* hardware configuration */
285286
unsigned int block_size;
286287
bool nollp;
288+
u32 max_burst;
287289

288290
/* custom slave configuration */
289291
struct dw_dma_slave dws;

include/linux/platform_data/dma-dw.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct dw_dma_slave {
4444
* @data_width: Maximum data width supported by hardware per AHB master
4545
* (in bytes, power of 2)
4646
* @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).
4749
* @protctl: Protection control signals setting per channel.
4850
*/
4951
struct dw_dma_platform_data {
@@ -58,6 +60,7 @@ struct dw_dma_platform_data {
5860
unsigned char nr_masters;
5961
unsigned char data_width[DW_DMA_MAX_NR_MASTERS];
6062
unsigned char multi_block[DW_DMA_MAX_NR_CHANNELS];
63+
u32 max_burst[DW_DMA_MAX_NR_CHANNELS];
6164
#define CHAN_PROTCTL_PRIVILEGED BIT(0)
6265
#define CHAN_PROTCTL_BUFFERABLE BIT(1)
6366
#define CHAN_PROTCTL_CACHEABLE BIT(2)

0 commit comments

Comments
 (0)