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.

dmaengine: sh: setup_xref error handling

This patch modifies the type of setup_xref from void to int and handles
errors since the function can fail.

`setup_xref` now returns the (eventual) error from
`dmae_set_dmars`|`dmae_set_chcr`, while `shdma_tx_submit` handles the
result, removing the chunks from the queue and marking PM as idle in
case of an error.

Signed-off-by: Thomas Andreatta <thomas.andreatta2000@gmail.com>
Link: https://lore.kernel.org/r/20250827152442.90962-1-thomas.andreatta2000@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Thomas Andreatta and committed by
Vinod Koul
d9a3e992 981d4978

+33 -11
+19 -6
drivers/dma/sh/shdma-base.c
··· 129 129 const struct shdma_ops *ops = sdev->ops; 130 130 dev_dbg(schan->dev, "Bring up channel %d\n", 131 131 schan->id); 132 - /* 133 - * TODO: .xfer_setup() might fail on some platforms. 134 - * Make it int then, on error remove chunks from the 135 - * queue again 136 - */ 137 - ops->setup_xfer(schan, schan->slave_id); 132 + 133 + ret = ops->setup_xfer(schan, schan->slave_id); 134 + if (ret < 0) { 135 + dev_err(schan->dev, "setup_xfer failed: %d\n", ret); 136 + 137 + /* Remove chunks from the queue and mark them as idle */ 138 + list_for_each_entry_safe(chunk, c, &schan->ld_queue, node) { 139 + if (chunk->cookie == cookie) { 140 + chunk->mark = DESC_IDLE; 141 + list_move(&chunk->node, &schan->ld_free); 142 + } 143 + } 144 + 145 + schan->pm_state = SHDMA_PM_ESTABLISHED; 146 + ret = pm_runtime_put(schan->dev); 147 + 148 + spin_unlock_irq(&schan->chan_lock); 149 + return ret; 150 + } 138 151 139 152 if (schan->pm_state == SHDMA_PM_PENDING) 140 153 shdma_chan_xfer_ld_queue(schan);
+13 -4
drivers/dma/sh/shdmac.c
··· 300 300 return dmae_is_busy(sh_chan); 301 301 } 302 302 303 - static void sh_dmae_setup_xfer(struct shdma_chan *schan, 304 - int slave_id) 303 + static int sh_dmae_setup_xfer(struct shdma_chan *schan, int slave_id) 305 304 { 306 305 struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan, 307 306 shdma_chan); 308 307 308 + int ret = 0; 309 309 if (slave_id >= 0) { 310 310 const struct sh_dmae_slave_config *cfg = 311 311 sh_chan->config; 312 312 313 - dmae_set_dmars(sh_chan, cfg->mid_rid); 314 - dmae_set_chcr(sh_chan, cfg->chcr); 313 + ret = dmae_set_dmars(sh_chan, cfg->mid_rid); 314 + if (ret < 0) 315 + goto END; 316 + 317 + ret = dmae_set_chcr(sh_chan, cfg->chcr); 318 + if (ret < 0) 319 + goto END; 320 + 315 321 } else { 316 322 dmae_init(sh_chan); 317 323 } 324 + 325 + END: 326 + return ret; 318 327 } 319 328 320 329 /*
+1 -1
include/linux/shdma-base.h
··· 96 96 int (*desc_setup)(struct shdma_chan *, struct shdma_desc *, 97 97 dma_addr_t, dma_addr_t, size_t *); 98 98 int (*set_slave)(struct shdma_chan *, int, dma_addr_t, bool); 99 - void (*setup_xfer)(struct shdma_chan *, int); 99 + int (*setup_xfer)(struct shdma_chan *, int); 100 100 void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); 101 101 struct shdma_desc *(*embedded_desc)(void *, int); 102 102 bool (*chan_irq)(struct shdma_chan *, int);