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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'dmaengine-fix-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine

Pull dmaengine fixes from Vinod Koul:

- TI driver fix to set EOP for cyclic BCDMA transfers

- sh rz-dmac driver fix for handling config with zero address

* tag 'dmaengine-fix-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine:
dmaengine: ti: k3-udma: Set EOP for all TRs in cyclic BCDMA transfer
dmaengine: sh: rz-dmac: handle configs where one address is zero

+61 -26
+14 -11
drivers/dma/sh/rz-dmac.c
··· 601 601 struct rz_dmac_chan *channel = to_rz_dmac_chan(chan); 602 602 u32 val; 603 603 604 - channel->src_per_address = config->src_addr; 605 604 channel->dst_per_address = config->dst_addr; 606 - 607 - val = rz_dmac_ds_to_val_mapping(config->dst_addr_width); 608 - if (val == CHCFG_DS_INVALID) 609 - return -EINVAL; 610 - 611 605 channel->chcfg &= ~CHCFG_FILL_DDS_MASK; 612 - channel->chcfg |= FIELD_PREP(CHCFG_FILL_DDS_MASK, val); 606 + if (channel->dst_per_address) { 607 + val = rz_dmac_ds_to_val_mapping(config->dst_addr_width); 608 + if (val == CHCFG_DS_INVALID) 609 + return -EINVAL; 613 610 614 - val = rz_dmac_ds_to_val_mapping(config->src_addr_width); 615 - if (val == CHCFG_DS_INVALID) 616 - return -EINVAL; 611 + channel->chcfg |= FIELD_PREP(CHCFG_FILL_DDS_MASK, val); 612 + } 617 613 614 + channel->src_per_address = config->src_addr; 618 615 channel->chcfg &= ~CHCFG_FILL_SDS_MASK; 619 - channel->chcfg |= FIELD_PREP(CHCFG_FILL_SDS_MASK, val); 616 + if (channel->src_per_address) { 617 + val = rz_dmac_ds_to_val_mapping(config->src_addr_width); 618 + if (val == CHCFG_DS_INVALID) 619 + return -EINVAL; 620 + 621 + channel->chcfg |= FIELD_PREP(CHCFG_FILL_SDS_MASK, val); 622 + } 620 623 621 624 return 0; 622 625 }
+47 -15
drivers/dma/ti/k3-udma.c
··· 3185 3185 3186 3186 d->static_tr.elcnt = elcnt; 3187 3187 3188 - /* 3189 - * PDMA must to close the packet when the channel is in packet mode. 3190 - * For TR mode when the channel is not cyclic we also need PDMA to close 3191 - * the packet otherwise the transfer will stall because PDMA holds on 3192 - * the data it has received from the peripheral. 3193 - */ 3194 3188 if (uc->config.pkt_mode || !uc->cyclic) { 3189 + /* 3190 + * PDMA must close the packet when the channel is in packet mode. 3191 + * For TR mode when the channel is not cyclic we also need PDMA 3192 + * to close the packet otherwise the transfer will stall because 3193 + * PDMA holds on the data it has received from the peripheral. 3194 + */ 3195 3195 unsigned int div = dev_width * elcnt; 3196 3196 3197 3197 if (uc->cyclic) 3198 3198 d->static_tr.bstcnt = d->residue / d->sglen / div; 3199 3199 else 3200 3200 d->static_tr.bstcnt = d->residue / div; 3201 + } else if (uc->ud->match_data->type == DMA_TYPE_BCDMA && 3202 + uc->config.dir == DMA_DEV_TO_MEM && 3203 + uc->cyclic) { 3204 + /* 3205 + * For cyclic mode with BCDMA we have to set EOP in each TR to 3206 + * prevent short packet errors seen on channel teardown. So the 3207 + * PDMA must close the packet after every TR transfer by setting 3208 + * burst count equal to the number of bytes transferred. 3209 + */ 3210 + struct cppi5_tr_type1_t *tr_req = d->hwdesc[0].tr_req_base; 3201 3211 3202 - if (uc->config.dir == DMA_DEV_TO_MEM && 3203 - d->static_tr.bstcnt > uc->ud->match_data->statictr_z_mask) 3204 - return -EINVAL; 3212 + d->static_tr.bstcnt = 3213 + (tr_req->icnt0 * tr_req->icnt1) / dev_width; 3205 3214 } else { 3206 3215 d->static_tr.bstcnt = 0; 3207 3216 } 3217 + 3218 + if (uc->config.dir == DMA_DEV_TO_MEM && 3219 + d->static_tr.bstcnt > uc->ud->match_data->statictr_z_mask) 3220 + return -EINVAL; 3208 3221 3209 3222 return 0; 3210 3223 } ··· 3463 3450 /* static TR for remote PDMA */ 3464 3451 if (udma_configure_statictr(uc, d, dev_width, burst)) { 3465 3452 dev_err(uc->ud->dev, 3466 - "%s: StaticTR Z is limited to maximum 4095 (%u)\n", 3467 - __func__, d->static_tr.bstcnt); 3453 + "%s: StaticTR Z is limited to maximum %u (%u)\n", 3454 + __func__, uc->ud->match_data->statictr_z_mask, 3455 + d->static_tr.bstcnt); 3468 3456 3469 3457 udma_free_hwdesc(uc, d); 3470 3458 kfree(d); ··· 3490 3476 u16 tr0_cnt0, tr0_cnt1, tr1_cnt0; 3491 3477 unsigned int i; 3492 3478 int num_tr; 3479 + u32 period_csf = 0; 3493 3480 3494 3481 num_tr = udma_get_tr_counters(period_len, __ffs(buf_addr), &tr0_cnt0, 3495 3482 &tr0_cnt1, &tr1_cnt0); ··· 3512 3497 else 3513 3498 period_addr = buf_addr | 3514 3499 ((u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT); 3500 + 3501 + /* 3502 + * For BCDMA <-> PDMA transfers, the EOP flag needs to be set on the 3503 + * last TR of a descriptor, to mark the packet as complete. 3504 + * This is required for getting the teardown completion message in case 3505 + * of TX, and to avoid short-packet error in case of RX. 3506 + * 3507 + * As we are in cyclic mode, we do not know which period might be the 3508 + * last one, so set the flag for each period. 3509 + */ 3510 + if (uc->config.ep_type == PSIL_EP_PDMA_XY && 3511 + uc->ud->match_data->type == DMA_TYPE_BCDMA) { 3512 + period_csf = CPPI5_TR_CSF_EOP; 3513 + } 3515 3514 3516 3515 for (i = 0; i < periods; i++) { 3517 3516 int tr_idx = i * num_tr; ··· 3554 3525 } 3555 3526 3556 3527 if (!(flags & DMA_PREP_INTERRUPT)) 3557 - cppi5_tr_csf_set(&tr_req[tr_idx].flags, 3558 - CPPI5_TR_CSF_SUPR_EVT); 3528 + period_csf |= CPPI5_TR_CSF_SUPR_EVT; 3529 + 3530 + if (period_csf) 3531 + cppi5_tr_csf_set(&tr_req[tr_idx].flags, period_csf); 3559 3532 3560 3533 period_addr += period_len; 3561 3534 } ··· 3686 3655 /* static TR for remote PDMA */ 3687 3656 if (udma_configure_statictr(uc, d, dev_width, burst)) { 3688 3657 dev_err(uc->ud->dev, 3689 - "%s: StaticTR Z is limited to maximum 4095 (%u)\n", 3690 - __func__, d->static_tr.bstcnt); 3658 + "%s: StaticTR Z is limited to maximum %u (%u)\n", 3659 + __func__, uc->ud->match_data->statictr_z_mask, 3660 + d->static_tr.bstcnt); 3691 3661 3692 3662 udma_free_hwdesc(uc, d); 3693 3663 kfree(d);