Commit 2abb0c7f authored by Alex Elder's avatar Alex Elder Committed by David S. Miller

net: ipa: resume in ipa_clock_get()

Introduce ipa_runtime_suspend() and ipa_runtime_resume(), which
encapsulate the activities necessary for suspending and resuming
the IPA hardware.  Call these functions from ipa_clock_get() and
ipa_clock_put() when the first reference is taken or last one is
dropped.

When the very first clock reference is taken (for ipa_config()),
setup isn't complete yet, so (as before) only the core clock gets
enabled.

When the last clock reference is dropped (after ipa_deconfig()),
ipa_teardown() will have made the setup_complete flag false, so
there too, the core clock will be stopped without affecting GSI
or the endpoints.

Otherwise these new functions will perform the desired suspend and
resume actions once setup is complete.
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1016c6b8
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/interconnect.h> #include <linux/interconnect.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include "ipa.h" #include "ipa.h"
...@@ -230,6 +231,38 @@ static int ipa_clock_disable(struct ipa *ipa) ...@@ -230,6 +231,38 @@ static int ipa_clock_disable(struct ipa *ipa)
return ipa_interconnect_disable(ipa); return ipa_interconnect_disable(ipa);
} }
static int ipa_runtime_suspend(struct device *dev)
{
struct ipa *ipa = dev_get_drvdata(dev);
/* Endpoints aren't usable until setup is complete */
if (ipa->setup_complete) {
__clear_bit(IPA_POWER_FLAG_RESUMED, ipa->clock->flags);
ipa_endpoint_suspend(ipa);
gsi_suspend(&ipa->gsi);
}
return ipa_clock_disable(ipa);
}
static int ipa_runtime_resume(struct device *dev)
{
struct ipa *ipa = dev_get_drvdata(dev);
int ret;
ret = ipa_clock_enable(ipa);
if (WARN_ON(ret < 0))
return ret;
/* Endpoints aren't usable until setup is complete */
if (ipa->setup_complete) {
gsi_resume(&ipa->gsi);
ipa_endpoint_resume(ipa);
}
return 0;
}
/* Get an IPA clock reference, but only if the reference count is /* Get an IPA clock reference, but only if the reference count is
* already non-zero. Returns true if the additional reference was * already non-zero. Returns true if the additional reference was
* added successfully, or false otherwise. * added successfully, or false otherwise.
...@@ -265,7 +298,7 @@ int ipa_clock_get(struct ipa *ipa) ...@@ -265,7 +298,7 @@ int ipa_clock_get(struct ipa *ipa)
goto out_mutex_unlock; goto out_mutex_unlock;
} }
ret = ipa_clock_enable(ipa); ret = ipa_runtime_resume(&ipa->pdev->dev);
refcount_set(&clock->count, 1); refcount_set(&clock->count, 1);
...@@ -287,7 +320,7 @@ int ipa_clock_put(struct ipa *ipa) ...@@ -287,7 +320,7 @@ int ipa_clock_put(struct ipa *ipa)
if (!refcount_dec_and_mutex_lock(&clock->count, &clock->mutex)) if (!refcount_dec_and_mutex_lock(&clock->count, &clock->mutex))
return 0; return 0;
ret = ipa_clock_disable(ipa); ret = ipa_runtime_suspend(&ipa->pdev->dev);
mutex_unlock(&clock->mutex); mutex_unlock(&clock->mutex);
...@@ -405,16 +438,7 @@ void ipa_clock_exit(struct ipa_clock *clock) ...@@ -405,16 +438,7 @@ void ipa_clock_exit(struct ipa_clock *clock)
*/ */
static int ipa_suspend(struct device *dev) static int ipa_suspend(struct device *dev)
{ {
struct ipa *ipa = dev_get_drvdata(dev); return ipa_runtime_suspend(dev);
/* Endpoints aren't usable until setup is complete */
if (ipa->setup_complete) {
__clear_bit(IPA_POWER_FLAG_RESUMED, ipa->clock->flags);
ipa_endpoint_suspend(ipa);
gsi_suspend(&ipa->gsi);
}
return ipa_clock_disable(ipa);
} }
/** /**
...@@ -429,20 +453,7 @@ static int ipa_suspend(struct device *dev) ...@@ -429,20 +453,7 @@ static int ipa_suspend(struct device *dev)
*/ */
static int ipa_resume(struct device *dev) static int ipa_resume(struct device *dev)
{ {
struct ipa *ipa = dev_get_drvdata(dev); return ipa_runtime_resume(dev);
int ret;
ret = ipa_clock_enable(ipa);
if (WARN_ON(ret < 0))
return ret;
/* Endpoints aren't usable until setup is complete */
if (ipa->setup_complete) {
gsi_resume(&ipa->gsi);
ipa_endpoint_resume(ipa);
}
return 0;
} }
const struct dev_pm_ops ipa_pm_ops = { const struct dev_pm_ops ipa_pm_ops = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment