Skip to content

Commit d9a3e99

Browse files
Thomas Andreattavinodkoul
authored andcommitted
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>
1 parent 981d497 commit d9a3e99

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

drivers/dma/sh/shdma-base.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,25 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
129129
const struct shdma_ops *ops = sdev->ops;
130130
dev_dbg(schan->dev, "Bring up channel %d\n",
131131
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+
}
138151

139152
if (schan->pm_state == SHDMA_PM_PENDING)
140153
shdma_chan_xfer_ld_queue(schan);

drivers/dma/sh/shdmac.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,21 +300,30 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
300300
return dmae_is_busy(sh_chan);
301301
}
302302

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)
305304
{
306305
struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
307306
shdma_chan);
308307

308+
int ret = 0;
309309
if (slave_id >= 0) {
310310
const struct sh_dmae_slave_config *cfg =
311311
sh_chan->config;
312312

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+
315321
} else {
316322
dmae_init(sh_chan);
317323
}
324+
325+
END:
326+
return ret;
318327
}
319328

320329
/*

include/linux/shdma-base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ struct shdma_ops {
9696
int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
9797
dma_addr_t, dma_addr_t, size_t *);
9898
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);
100100
void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
101101
struct shdma_desc *(*embedded_desc)(void *, int);
102102
bool (*chan_irq)(struct shdma_chan *, int);

0 commit comments

Comments
 (0)