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

dmaengine: cppi41: Fix cppi41_dma_prep_slave_sg() when idle

Yegor Yefremov <yegorslists@googlemail.com> reported that musb and ftdi
uart can fail for the first open of the uart unless connected using
a hub.

This is because the first dma call done by musb_ep_program() must wait
if cppi41 is PM runtime suspended. Otherwise musb_ep_program() continues
with other non-dma packets before the DMA transfer is started causing at
least ftdi uarts to fail to receive data.

Let's fix the issue by waking up cppi41 with PM runtime calls added to
cppi41_dma_prep_slave_sg() and return NULL if still idled. This way we
have musb_ep_program() continue with PIO until cppi41 is awake.

Fixes: fdea2d09b997 ("dmaengine: cppi41: Add basic PM runtime support")
Reported-by: Yegor Yefremov <yegorslists@googlemail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Cc: stable@vger.kernel.org # v4.9+
Link: https://lore.kernel.org/r/20191023153138.23442-1-tony@atomide.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Tony Lindgren and committed by
Vinod Koul
bacdcb66 76678193

+20 -1
+20 -1
drivers/dma/ti/cppi41.c
··· 586 586 enum dma_transfer_direction dir, unsigned long tx_flags, void *context) 587 587 { 588 588 struct cppi41_channel *c = to_cpp41_chan(chan); 589 + struct dma_async_tx_descriptor *txd = NULL; 590 + struct cppi41_dd *cdd = c->cdd; 589 591 struct cppi41_desc *d; 590 592 struct scatterlist *sg; 591 593 unsigned int i; 594 + int error; 595 + 596 + error = pm_runtime_get(cdd->ddev.dev); 597 + if (error < 0) { 598 + pm_runtime_put_noidle(cdd->ddev.dev); 599 + 600 + return NULL; 601 + } 602 + 603 + if (cdd->is_suspended) 604 + goto err_out_not_ready; 592 605 593 606 d = c->desc; 594 607 for_each_sg(sgl, sg, sg_len, i) { ··· 624 611 d++; 625 612 } 626 613 627 - return &c->txd; 614 + txd = &c->txd; 615 + 616 + err_out_not_ready: 617 + pm_runtime_mark_last_busy(cdd->ddev.dev); 618 + pm_runtime_put_autosuspend(cdd->ddev.dev); 619 + 620 + return txd; 628 621 } 629 622 630 623 static void cppi41_compute_td_desc(struct cppi41_desc *d)