Commit 4ec69c7ebc2cb8df1f33b26f4492481c452fef66
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge branch 'fixes' of git://git.infradead.org/users/vkoul/slave-dma
Pull dmaengine fixes from Vinod Koul: "We have couple of fixes for dmaengine queued up: - dma mempcy fix for dma configuration of sun6i by Maxime - pl330 fixes: First the fixing allocation for data buffers by Liviu and then Jon's fixe for fifo width and usage" * 'fixes' of git://git.infradead.org/users/vkoul/slave-dma: dmaengine: Fix allocation size for PL330 data buffer depth. dmaengine: pl330: Limit MFIFO usage for memcpy to avoid exhausting entries dmaengine: pl330: Align DMA memcpy operations to MFIFO width dmaengine: sun6i: Fix memcpy operation
Showing 2 changed files Side-by-side Diff
drivers/dma/pl330.c
... | ... | @@ -271,7 +271,7 @@ |
271 | 271 | #define DMAC_MODE_NS (1 << 0) |
272 | 272 | unsigned int mode; |
273 | 273 | unsigned int data_bus_width:10; /* In number of bits */ |
274 | - unsigned int data_buf_dep:10; | |
274 | + unsigned int data_buf_dep:11; | |
275 | 275 | unsigned int num_chan:4; |
276 | 276 | unsigned int num_peri:6; |
277 | 277 | u32 peri_ns; |
... | ... | @@ -2336,7 +2336,7 @@ |
2336 | 2336 | int burst_len; |
2337 | 2337 | |
2338 | 2338 | burst_len = pl330->pcfg.data_bus_width / 8; |
2339 | - burst_len *= pl330->pcfg.data_buf_dep; | |
2339 | + burst_len *= pl330->pcfg.data_buf_dep / pl330->pcfg.num_chan; | |
2340 | 2340 | burst_len >>= desc->rqcfg.brst_size; |
2341 | 2341 | |
2342 | 2342 | /* src/dst_burst_len can't be more than 16 */ |
2343 | 2343 | |
2344 | 2344 | |
... | ... | @@ -2459,16 +2459,25 @@ |
2459 | 2459 | /* Select max possible burst size */ |
2460 | 2460 | burst = pl330->pcfg.data_bus_width / 8; |
2461 | 2461 | |
2462 | - while (burst > 1) { | |
2463 | - if (!(len % burst)) | |
2464 | - break; | |
2462 | + /* | |
2463 | + * Make sure we use a burst size that aligns with all the memcpy | |
2464 | + * parameters because our DMA programming algorithm doesn't cope with | |
2465 | + * transfers which straddle an entry in the DMA device's MFIFO. | |
2466 | + */ | |
2467 | + while ((src | dst | len) & (burst - 1)) | |
2465 | 2468 | burst /= 2; |
2466 | - } | |
2467 | 2469 | |
2468 | 2470 | desc->rqcfg.brst_size = 0; |
2469 | 2471 | while (burst != (1 << desc->rqcfg.brst_size)) |
2470 | 2472 | desc->rqcfg.brst_size++; |
2471 | 2473 | |
2474 | + /* | |
2475 | + * If burst size is smaller than bus width then make sure we only | |
2476 | + * transfer one at a time to avoid a burst stradling an MFIFO entry. | |
2477 | + */ | |
2478 | + if (desc->rqcfg.brst_size * 8 < pl330->pcfg.data_bus_width) | |
2479 | + desc->rqcfg.brst_len = 1; | |
2480 | + | |
2472 | 2481 | desc->rqcfg.brst_len = get_burst_len(desc, len); |
2473 | 2482 | |
2474 | 2483 | desc->txd.flags = flags; |
... | ... | @@ -2732,7 +2741,7 @@ |
2732 | 2741 | |
2733 | 2742 | |
2734 | 2743 | dev_info(&adev->dev, |
2735 | - "Loaded driver for PL330 DMAC-%d\n", adev->periphid); | |
2744 | + "Loaded driver for PL330 DMAC-%x\n", adev->periphid); | |
2736 | 2745 | dev_info(&adev->dev, |
2737 | 2746 | "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", |
2738 | 2747 | pcfg->data_buf_dep, pcfg->data_bus_width / 8, pcfg->num_chan, |
drivers/dma/sun6i-dma.c
... | ... | @@ -230,30 +230,25 @@ |
230 | 230 | readl(pchan->base + DMA_CHAN_CUR_PARA)); |
231 | 231 | } |
232 | 232 | |
233 | -static inline int convert_burst(u32 maxburst, u8 *burst) | |
233 | +static inline s8 convert_burst(u32 maxburst) | |
234 | 234 | { |
235 | 235 | switch (maxburst) { |
236 | 236 | case 1: |
237 | - *burst = 0; | |
238 | - break; | |
237 | + return 0; | |
239 | 238 | case 8: |
240 | - *burst = 2; | |
241 | - break; | |
239 | + return 2; | |
242 | 240 | default: |
243 | 241 | return -EINVAL; |
244 | 242 | } |
245 | - | |
246 | - return 0; | |
247 | 243 | } |
248 | 244 | |
249 | -static inline int convert_buswidth(enum dma_slave_buswidth addr_width, u8 *width) | |
245 | +static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width) | |
250 | 246 | { |
251 | 247 | if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) || |
252 | 248 | (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES)) |
253 | 249 | return -EINVAL; |
254 | 250 | |
255 | - *width = addr_width >> 1; | |
256 | - return 0; | |
251 | + return addr_width >> 1; | |
257 | 252 | } |
258 | 253 | |
259 | 254 | static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev, |
260 | 255 | |
261 | 256 | |
262 | 257 | |
263 | 258 | |
... | ... | @@ -284,26 +279,25 @@ |
284 | 279 | struct dma_slave_config *config) |
285 | 280 | { |
286 | 281 | u8 src_width, dst_width, src_burst, dst_burst; |
287 | - int ret; | |
288 | 282 | |
289 | 283 | if (!config) |
290 | 284 | return -EINVAL; |
291 | 285 | |
292 | - ret = convert_burst(config->src_maxburst, &src_burst); | |
293 | - if (ret) | |
294 | - return ret; | |
286 | + src_burst = convert_burst(config->src_maxburst); | |
287 | + if (src_burst) | |
288 | + return src_burst; | |
295 | 289 | |
296 | - ret = convert_burst(config->dst_maxburst, &dst_burst); | |
297 | - if (ret) | |
298 | - return ret; | |
290 | + dst_burst = convert_burst(config->dst_maxburst); | |
291 | + if (dst_burst) | |
292 | + return dst_burst; | |
299 | 293 | |
300 | - ret = convert_buswidth(config->src_addr_width, &src_width); | |
301 | - if (ret) | |
302 | - return ret; | |
294 | + src_width = convert_buswidth(config->src_addr_width); | |
295 | + if (src_width) | |
296 | + return src_width; | |
303 | 297 | |
304 | - ret = convert_buswidth(config->dst_addr_width, &dst_width); | |
305 | - if (ret) | |
306 | - return ret; | |
298 | + dst_width = convert_buswidth(config->dst_addr_width); | |
299 | + if (dst_width) | |
300 | + return dst_width; | |
307 | 301 | |
308 | 302 | lli->cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) | |
309 | 303 | DMA_CHAN_CFG_SRC_WIDTH(src_width) | |
310 | 304 | |
... | ... | @@ -542,11 +536,10 @@ |
542 | 536 | { |
543 | 537 | struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(chan->device); |
544 | 538 | struct sun6i_vchan *vchan = to_sun6i_vchan(chan); |
545 | - struct dma_slave_config *sconfig = &vchan->cfg; | |
546 | 539 | struct sun6i_dma_lli *v_lli; |
547 | 540 | struct sun6i_desc *txd; |
548 | 541 | dma_addr_t p_lli; |
549 | - int ret; | |
542 | + s8 burst, width; | |
550 | 543 | |
551 | 544 | dev_dbg(chan2dev(chan), |
552 | 545 | "%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n", |
553 | 546 | |
554 | 547 | |
... | ... | @@ -565,14 +558,21 @@ |
565 | 558 | goto err_txd_free; |
566 | 559 | } |
567 | 560 | |
568 | - ret = sun6i_dma_cfg_lli(v_lli, src, dest, len, sconfig); | |
569 | - if (ret) | |
570 | - goto err_dma_free; | |
561 | + v_lli->src = src; | |
562 | + v_lli->dst = dest; | |
563 | + v_lli->len = len; | |
564 | + v_lli->para = NORMAL_WAIT; | |
571 | 565 | |
566 | + burst = convert_burst(8); | |
567 | + width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES); | |
572 | 568 | v_lli->cfg |= DMA_CHAN_CFG_SRC_DRQ(DRQ_SDRAM) | |
573 | 569 | DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) | |
574 | 570 | DMA_CHAN_CFG_DST_LINEAR_MODE | |
575 | - DMA_CHAN_CFG_SRC_LINEAR_MODE; | |
571 | + DMA_CHAN_CFG_SRC_LINEAR_MODE | | |
572 | + DMA_CHAN_CFG_SRC_BURST(burst) | | |
573 | + DMA_CHAN_CFG_SRC_WIDTH(width) | | |
574 | + DMA_CHAN_CFG_DST_BURST(burst) | | |
575 | + DMA_CHAN_CFG_DST_WIDTH(width); | |
576 | 576 | |
577 | 577 | sun6i_dma_lli_add(NULL, v_lli, p_lli, txd); |
578 | 578 | |
... | ... | @@ -580,8 +580,6 @@ |
580 | 580 | |
581 | 581 | return vchan_tx_prep(&vchan->vc, &txd->vd, flags); |
582 | 582 | |
583 | -err_dma_free: | |
584 | - dma_pool_free(sdev->pool, v_lli, p_lli); | |
585 | 583 | err_txd_free: |
586 | 584 | kfree(txd); |
587 | 585 | return NULL; |
... | ... | @@ -915,6 +913,7 @@ |
915 | 913 | sdc->slave.device_prep_dma_memcpy = sun6i_dma_prep_dma_memcpy; |
916 | 914 | sdc->slave.device_control = sun6i_dma_control; |
917 | 915 | sdc->slave.chancnt = NR_MAX_VCHANS; |
916 | + sdc->slave.copy_align = 4; | |
918 | 917 | |
919 | 918 | sdc->slave.dev = &pdev->dev; |
920 | 919 |