From: Vaibhav Hiremath Date: Wed, 3 Aug 2016 11:45:38 +0000 (+0530) Subject: greybus: arche-platform: Reset SVC & APB only if turned off by SUSPEND_PREPARE X-Git-Tag: v4.9-rc1~119^2~378^2~21^2~75 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=8ef0b5383110977d81746cd0b09c3877d51c3a67;p=karo-tx-linux.git greybus: arche-platform: Reset SVC & APB only if turned off by SUSPEND_PREPARE There is possible race condition in arche platform driver for maintaining of ->state field, when shared with timesync driver. Assume device booted fine, all connected modules have been enumerated correctly. As part of suspend-resume operation we have pm_notifier callback, where we turn off SVC & APB and coldboot on resume. In the process of resume, all modules gets enumerated again, and timesync driver does come into picture everytime. So when timesync driver requests arche-platform to change the state to TIMESYNC and in the middle of sync operation, if suspend gets triggered, then execution lands into arche-platform->pm_notifier callback, leading to race condition in the driver, where it checks for (state != ACTIVE) in PM_SUSPEND_PREPARE and returns, but in PM_POST_SUSPEND it just simply coldboots SVC & APB, which would inbalance all resources (including IRQ). So we need a add check in PM_POST_SUSPEND, to make sure that, we only coldboot devices if they are in to off state, i.e. if (state != OFF) then return. Testing Done: Done regressive suspend/resume testing on EVT2 platform. Note that, I some time hit issue. Signed-off-by: Vaibhav Hiremath Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c index cbe8bdcabceb..adec1fdcb5bb 100644 --- a/drivers/staging/greybus/arche-platform.c +++ b/drivers/staging/greybus/arche-platform.c @@ -548,6 +548,9 @@ static int arche_platform_pm_notifier(struct notifier_block *notifier, arche_platform_poweroff_seq(arche_pdata); break; case PM_POST_SUSPEND: + if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF) + break; + arche_platform_wd_irq_en(arche_pdata); arche_platform_coldboot_seq(arche_pdata); break;