struct rz_dmac *dmac = to_rz_dmac(chan->device);
struct rz_dmac_desc *desc, *_desc;
unsigned long flags;
+ int ret;
+
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dmac->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret) {
+ dev_err(dmac->dev, "RPM resume failed for channel %s, ret=%d\n!",
+ dma_chan_name(chan), ret);
+ }
spin_lock_irqsave(&channel->vc.lock, flags);
rz_lmdesc_setup(channel, channel->lmdesc.base);
- rz_dmac_disable_hw(channel);
+ /* Skip touching HW if RPM resume failed. Let the cleanup do its jobs. */
+ if (!ret)
+ rz_dmac_disable_hw(channel);
if (channel->mid_rid >= 0) {
clear_bit(channel->mid_rid, dmac->modules);
static int rz_dmac_terminate_all(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+ struct rz_dmac *dmac = to_rz_dmac(chan->device);
unsigned long flags;
LIST_HEAD(head);
+ int ret;
+
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dmac->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret) {
+ dev_err(dmac->dev, "RPM resume failed for channel %s, ret=%d\n!",
+ dma_chan_name(chan), ret);
+ }
spin_lock_irqsave(&channel->vc.lock, flags);
- rz_dmac_disable_hw(channel);
+ /* Don't return if RPM failed. Let the cleanup do its jobs. */
+ if (!ret)
+ rz_dmac_disable_hw(channel);
rz_lmdesc_setup(channel, channel->lmdesc.base);
if (channel->desc) {
spin_unlock_irqrestore(&channel->vc.lock, flags);
vchan_dma_desc_free_list(&channel->vc, &head);
- return 0;
+ return ret;
}
static void rz_dmac_issue_pending(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+ struct rz_dmac *dmac = to_rz_dmac(chan->device);
unsigned long flags;
+ int ret;
+
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dmac->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return;
spin_lock_irqsave(&channel->vc.lock, flags);
vchan_synchronize(&channel->vc);
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dmac->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return;
+
ret = read_poll_timeout(rz_dmac_ch_readl, chstat, !(chstat & CHSTAT_EN),
100, 100000, false, channel, CHSTAT, 1);
if (ret < 0)
struct rz_dmac_desc *desc = NULL;
struct virt_dma_desc *vd;
u32 crla, crtb, i;
+ int ret;
vd = vchan_find_desc(&channel->vc, cookie);
if (vd) {
return 0;
}
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
+
/*
* We need to read two registers. Make sure the hardware does not move
* to next lmdesc while reading the current lmdesc. Trying it 3 times
static int rz_dmac_device_pause(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+ struct rz_dmac *dmac = to_rz_dmac(chan->device);
+ int ret;
+
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dmac->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
guard(spinlock_irqsave)(&channel->vc.lock);
static int rz_dmac_device_resume(struct dma_chan *chan)
{
struct rz_dmac_chan *channel = to_rz_dmac_chan(chan);
+ struct rz_dmac *dmac = to_rz_dmac(chan->device);
+ int ret;
+
+ PM_RUNTIME_ACQUIRE_IF_ENABLED(dmac->dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
guard(spinlock_irqsave)(&channel->vc.lock);
return dev_err_probe(&pdev->dev, PTR_ERR(dmac->rstc),
"failed to get resets\n");
+ pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {