Skip to content

Commit

Permalink
net: ipa: use autosuspend
Browse files Browse the repository at this point in the history
Use runtime power management autosuspend.

Up until this point, we only suspended the IPA hardware for system
suspend; now we'll suspend it aggressively using runtime power
management, setting the initial autosuspend delay to half a second
of inactivity.

Replace pm_runtime_put() calls with pm_runtime_put_autosuspend(),
call pm_runtime_mark_last_busy() before each of those.  In places
where we're shutting things down, or decrementing power references
for errors, use pm_runtime_put_noidle() instead.

Finally, remove ipa_runtime_idle(), so the ->runtime_suspend
callback will occur if idle.

Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Alex Elder authored and davem330 committed Aug 22, 2021
1 parent 4af14db commit 1aac309
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 25 deletions.
15 changes: 7 additions & 8 deletions drivers/net/ipa/ipa_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
* An IPA clock reference must be held for any access to IPA hardware.
*/

#define IPA_AUTOSUSPEND_DELAY 500 /* milliseconds */

/**
* struct ipa_interconnect - IPA interconnect information
* @path: Interconnect path
Expand Down Expand Up @@ -267,11 +269,6 @@ static int ipa_runtime_resume(struct device *dev)
return 0;
}

static int ipa_runtime_idle(struct device *dev)
{
return -EAGAIN;
}

static int ipa_suspend(struct device *dev)
{
struct ipa *ipa = dev_get_drvdata(dev);
Expand Down Expand Up @@ -443,7 +440,8 @@ ipa_clock_init(struct device *dev, const struct ipa_clock_data *data)
if (ret)
goto err_kfree;

pm_runtime_dont_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, IPA_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(dev);
pm_runtime_enable(dev);

return clock;
Expand All @@ -459,9 +457,11 @@ ipa_clock_init(struct device *dev, const struct ipa_clock_data *data)
/* Inverse of ipa_clock_init() */
void ipa_clock_exit(struct ipa_clock *clock)
{
struct device *dev = clock->dev;
struct clk *clk = clock->core;

pm_runtime_disable(clock->dev);
pm_runtime_disable(dev);
pm_runtime_dont_use_autosuspend(dev);
ipa_interconnect_exit(clock);
kfree(clock);
clk_put(clk);
Expand All @@ -472,5 +472,4 @@ const struct dev_pm_ops ipa_pm_ops = {
.resume = ipa_resume,
.runtime_suspend = ipa_runtime_suspend,
.runtime_resume = ipa_runtime_resume,
.runtime_idle = ipa_runtime_idle,
};
3 changes: 2 additions & 1 deletion drivers/net/ipa/ipa_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ static irqreturn_t ipa_isr_thread(int irq, void *dev_id)
iowrite32(pending, ipa->reg_virt + offset);
}
out_power_put:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

return IRQ_HANDLED;
}
Expand Down
11 changes: 6 additions & 5 deletions drivers/net/ipa/ipa_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,14 +766,15 @@ static int ipa_probe(struct platform_device *pdev)
if (ret)
goto err_deconfig;
done:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

return 0;

err_deconfig:
ipa_deconfig(ipa);
err_power_put:
(void)pm_runtime_put(dev);
pm_runtime_put_noidle(dev);
ipa_modem_exit(ipa);
err_table_exit:
ipa_table_exit(ipa);
Expand All @@ -797,9 +798,10 @@ static int ipa_remove(struct platform_device *pdev)
{
struct ipa *ipa = dev_get_drvdata(&pdev->dev);
struct ipa_clock *clock = ipa->clock;
struct device *dev = &pdev->dev;
int ret;

ret = pm_runtime_get_sync(&pdev->dev);
ret = pm_runtime_get_sync(dev);
if (WARN_ON(ret < 0))
goto out_power_put;

Expand All @@ -818,8 +820,7 @@ static int ipa_remove(struct platform_device *pdev)

ipa_deconfig(ipa);
out_power_put:
(void)pm_runtime_put(&pdev->dev);

pm_runtime_put_noidle(dev);
ipa_modem_exit(ipa);
ipa_table_exit(ipa);
ipa_endpoint_exit(ipa);
Expand Down
16 changes: 10 additions & 6 deletions drivers/net/ipa/ipa_modem.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,15 @@ static int ipa_open(struct net_device *netdev)

netif_start_queue(netdev);

(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

return 0;

err_disable_tx:
ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
err_power_put:
(void)pm_runtime_put(dev);
pm_runtime_put_noidle(dev);

return ret;
}
Expand All @@ -97,7 +98,8 @@ static int ipa_stop(struct net_device *netdev)
ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_RX]);
ipa_endpoint_disable_one(ipa->name_map[IPA_ENDPOINT_AP_MODEM_TX]);
out_power_put:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

return 0;
}
Expand Down Expand Up @@ -145,7 +147,7 @@ ipa_start_xmit(struct sk_buff *skb, struct net_device *netdev)
*/
ipa_power_modem_queue_stop(ipa);

(void)pm_runtime_put(dev);
pm_runtime_put_noidle(dev);

return NETDEV_TX_BUSY;
}
Expand All @@ -154,7 +156,8 @@ ipa_start_xmit(struct sk_buff *skb, struct net_device *netdev)

ret = ipa_endpoint_skb_tx(endpoint, skb);

(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);

if (ret) {
if (ret != -E2BIG)
Expand Down Expand Up @@ -398,7 +401,8 @@ static void ipa_modem_crashed(struct ipa *ipa)
dev_err(dev, "error %d zeroing modem memory regions\n", ret);

out_power_put:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);
}

static int ipa_modem_notify(struct notifier_block *nb, unsigned long action,
Expand Down
8 changes: 6 additions & 2 deletions drivers/net/ipa/ipa_smp2p.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ static irqreturn_t ipa_smp2p_modem_setup_ready_isr(int irq, void *dev_id)
WARN(ret != 0, "error %d from ipa_setup()\n", ret);

out_power_put:
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);
out_mutex_unlock:
mutex_unlock(&smp2p->mutex);

Expand Down Expand Up @@ -211,10 +212,13 @@ static void ipa_smp2p_irq_exit(struct ipa_smp2p *smp2p, u32 irq)
/* Drop the clock reference if it was taken in ipa_smp2p_notify() */
static void ipa_smp2p_clock_release(struct ipa *ipa)
{
struct device *dev = &ipa->pdev->dev;

if (!ipa->smp2p->clock_on)
return;

(void)pm_runtime_put(&ipa->pdev->dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);
ipa->smp2p->clock_on = false;
}

Expand Down
12 changes: 9 additions & 3 deletions drivers/net/ipa/ipa_uc.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ static void ipa_uc_response_hdlr(struct ipa *ipa, enum ipa_irq_id irq_id)
case IPA_UC_RESPONSE_INIT_COMPLETED:
if (ipa->uc_clocked) {
ipa->uc_loaded = true;
(void)pm_runtime_put(dev);
pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);
ipa->uc_clocked = false;
} else {
dev_warn(dev, "unexpected init_completed response\n");
Expand All @@ -179,10 +180,15 @@ void ipa_uc_config(struct ipa *ipa)
/* Inverse of ipa_uc_config() */
void ipa_uc_deconfig(struct ipa *ipa)
{
struct device *dev = &ipa->pdev->dev;

ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_1);
ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_0);
if (ipa->uc_clocked)
(void)pm_runtime_put(&ipa->pdev->dev);
if (!ipa->uc_clocked)
return;

pm_runtime_mark_last_busy(dev);
(void)pm_runtime_put_autosuspend(dev);
}

/* Take a proxy clock reference for the microcontroller */
Expand Down

0 comments on commit 1aac309

Please sign in to comment.