Message ID | 20200415095953.v3.2.I8550512081c89ec7a545018a7d2d9418a27c1a7a@changeid (mailing list archive) |
---|---|
State | Accepted |
Commit | 91160150aba03d0c173b3f5c859a795cc701bb8d |
Headers | show |
Series | [v3,1/2] soc: qcom: rpmh-rsc: Factor "tcs_reg_addr" and "tcs_cmd_addr" calculation | expand |
Hi Doug, During suspend-resume with this change on sc7180 using latest linux-next, below warning was reported. WARNING: CPU: 0 PID: 5324 at kernel/time/timekeeping.c:754 ktime_get+0x94/0x9c ktime_get+0x94/0x9c write_tcs_reg_sync+0x4c/0x130 tcs_invalidate+0x64/0xa4 rpmh_rsc_invalidate+0x20/0x38 rpmh_flush+0x58/0x1ec rpmh_rsc_cpu_pm_callback+0xe4/0x144 notifier_call_chain+0x58/0x90 __atomic_notifier_call_chain+0x48/ cpu_pm_notify+0x40/0x6c cpu_pm_enter+0x34/0x7c cpu_pm_suspend+0x10/0x20 syscore_suspend+0x128/0x2a4 suspend_devices_and_enter+0x5e0/0x8a0 This seems to be because timekeeping is already suspend by this time. Thanks, Maulik On 4/15/2020 10:30 PM, Douglas Anderson wrote: > If our data still isn't there after 1 second, shout and give up. > > Reported-by: Joe Perches <joe@perches.com> > Signed-off-by: Douglas Anderson <dianders@chromium.org> > Reviewed-by: Stephen Boyd <swboyd@chromium.org> > --- > > Changes in v3: > - The register should be hex. > > Changes in v2: > - Patch ("Timeout after 1 second") new for v2. > > drivers/soc/qcom/rpmh-rsc.c | 12 +++++++----- > 1 file changed, 7 insertions(+), 5 deletions(-) > > diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c > index ce39d8399312..e09d1ada0cd2 100644 > --- a/drivers/soc/qcom/rpmh-rsc.c > +++ b/drivers/soc/qcom/rpmh-rsc.c > @@ -10,6 +10,7 @@ > #include <linux/delay.h> > #include <linux/interrupt.h> > #include <linux/io.h> > +#include <linux/iopoll.h> > #include <linux/kernel.h> > #include <linux/list.h> > #include <linux/module.h> > @@ -175,12 +176,13 @@ static void write_tcs_reg(const struct rsc_drv *drv, int reg, int tcs_id, > static void write_tcs_reg_sync(const struct rsc_drv *drv, int reg, int tcs_id, > u32 data) > { > + u32 new_data; > + > writel(data, tcs_reg_addr(drv, reg, tcs_id)); > - for (;;) { > - if (data == readl(tcs_reg_addr(drv, reg, tcs_id))) > - break; > - udelay(1); > - } > + if (readl_poll_timeout_atomic(tcs_reg_addr(drv, reg, tcs_id), new_data, > + new_data == data, 1, USEC_PER_SEC)) > + pr_err("%s: error writing %#x to %d:%#x\n", drv->name, > + data, tcs_id, reg); > } > > /**
Hi, On Thu, May 28, 2020 at 4:44 AM Maulik Shah <mkshah@codeaurora.org> wrote: > > Hi Doug, > > During suspend-resume with this change on sc7180 using latest > linux-next, below warning was reported. > > WARNING: CPU: 0 PID: 5324 at kernel/time/timekeeping.c:754 > ktime_get+0x94/0x9c > ktime_get+0x94/0x9c > write_tcs_reg_sync+0x4c/0x130 > tcs_invalidate+0x64/0xa4 > rpmh_rsc_invalidate+0x20/0x38 > rpmh_flush+0x58/0x1ec > rpmh_rsc_cpu_pm_callback+0xe4/0x144 > notifier_call_chain+0x58/0x90 > __atomic_notifier_call_chain+0x48/ > cpu_pm_notify+0x40/0x6c > cpu_pm_enter+0x34/0x7c > cpu_pm_suspend+0x10/0x20 > syscore_suspend+0x128/0x2a4 > suspend_devices_and_enter+0x5e0/0x8a0 > > This seems to be because timekeeping is already suspend by this time. Thanks for the report. I posted: https://lore.kernel.org/r/20200528074530.1.Ib86e5b406fe7d16575ae1bb276d650faa144b63c@changeid I think there are still a bunch of not-yet-landed patches needed for suspend-resume so I only confirmed that the code still works OK for the idle case. Hopefully you can confirm s2r is good, though I'd believe it should be exactly the same. I'm 99% sure that udelay() still works fine even when timekeeping is suspended. -Doug
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index ce39d8399312..e09d1ada0cd2 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -10,6 +10,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> @@ -175,12 +176,13 @@ static void write_tcs_reg(const struct rsc_drv *drv, int reg, int tcs_id, static void write_tcs_reg_sync(const struct rsc_drv *drv, int reg, int tcs_id, u32 data) { + u32 new_data; + writel(data, tcs_reg_addr(drv, reg, tcs_id)); - for (;;) { - if (data == readl(tcs_reg_addr(drv, reg, tcs_id))) - break; - udelay(1); - } + if (readl_poll_timeout_atomic(tcs_reg_addr(drv, reg, tcs_id), new_data, + new_data == data, 1, USEC_PER_SEC)) + pr_err("%s: error writing %#x to %d:%#x\n", drv->name, + data, tcs_id, reg); } /**