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>
This commit is contained in:
parent
981d4978ff
commit
d9a3e99294
|
@ -129,12 +129,25 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
|
|||
const struct shdma_ops *ops = sdev->ops;
|
||||
dev_dbg(schan->dev, "Bring up channel %d\n",
|
||||
schan->id);
|
||||
/*
|
||||
* TODO: .xfer_setup() might fail on some platforms.
|
||||
* Make it int then, on error remove chunks from the
|
||||
* queue again
|
||||
*/
|
||||
ops->setup_xfer(schan, schan->slave_id);
|
||||
|
||||
ret = ops->setup_xfer(schan, schan->slave_id);
|
||||
if (ret < 0) {
|
||||
dev_err(schan->dev, "setup_xfer failed: %d\n", ret);
|
||||
|
||||
/* Remove chunks from the queue and mark them as idle */
|
||||
list_for_each_entry_safe(chunk, c, &schan->ld_queue, node) {
|
||||
if (chunk->cookie == cookie) {
|
||||
chunk->mark = DESC_IDLE;
|
||||
list_move(&chunk->node, &schan->ld_free);
|
||||
}
|
||||
}
|
||||
|
||||
schan->pm_state = SHDMA_PM_ESTABLISHED;
|
||||
ret = pm_runtime_put(schan->dev);
|
||||
|
||||
spin_unlock_irq(&schan->chan_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (schan->pm_state == SHDMA_PM_PENDING)
|
||||
shdma_chan_xfer_ld_queue(schan);
|
||||
|
|
|
@ -300,21 +300,30 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
|
|||
return dmae_is_busy(sh_chan);
|
||||
}
|
||||
|
||||
static void sh_dmae_setup_xfer(struct shdma_chan *schan,
|
||||
int slave_id)
|
||||
static int sh_dmae_setup_xfer(struct shdma_chan *schan, int slave_id)
|
||||
{
|
||||
struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
|
||||
shdma_chan);
|
||||
|
||||
int ret = 0;
|
||||
if (slave_id >= 0) {
|
||||
const struct sh_dmae_slave_config *cfg =
|
||||
sh_chan->config;
|
||||
|
||||
dmae_set_dmars(sh_chan, cfg->mid_rid);
|
||||
dmae_set_chcr(sh_chan, cfg->chcr);
|
||||
ret = dmae_set_dmars(sh_chan, cfg->mid_rid);
|
||||
if (ret < 0)
|
||||
goto END;
|
||||
|
||||
ret = dmae_set_chcr(sh_chan, cfg->chcr);
|
||||
if (ret < 0)
|
||||
goto END;
|
||||
|
||||
} else {
|
||||
dmae_init(sh_chan);
|
||||
}
|
||||
|
||||
END:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -96,7 +96,7 @@ struct shdma_ops {
|
|||
int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
|
||||
dma_addr_t, dma_addr_t, size_t *);
|
||||
int (*set_slave)(struct shdma_chan *, int, dma_addr_t, bool);
|
||||
void (*setup_xfer)(struct shdma_chan *, int);
|
||||
int (*setup_xfer)(struct shdma_chan *, int);
|
||||
void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
|
||||
struct shdma_desc *(*embedded_desc)(void *, int);
|
||||
bool (*chan_irq)(struct shdma_chan *, int);
|
||||
|
|
Loading…
Reference in New Issue