power: qpnp-fg-gen3: Skip the status_change work if suspended

There is a scenario where the status change work can hold
a mutex lock for ~1.5 seconds which can race with the FG resume
callback. Avoid this condition by adding a state variable
to track the suspend/resume state and skip executing the
status change work while suspended.

CRs-Fixed: 2101514
Change-Id: Ib5300a5dfce30c4c6bcc8d8428b664c184a83fb4
Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
This commit is contained in:
Anirudh Ghayal 2017-10-18 11:36:22 +05:30
parent 11734d0451
commit fa88f5e4cb
2 changed files with 25 additions and 0 deletions

View file

@ -404,6 +404,7 @@ struct fg_chip {
struct mutex sram_rw_lock;
struct mutex charge_full_lock;
struct mutex qnovo_esr_ctrl_lock;
spinlock_t suspend_lock;
u32 batt_soc_base;
u32 batt_info_base;
u32 mem_if_base;
@ -438,6 +439,7 @@ struct fg_chip {
bool slope_limit_en;
bool use_ima_single_mode;
bool qnovo_enable;
bool suspended;
struct completion soc_update;
struct completion soc_ready;
struct delayed_work profile_load_work;

View file

@ -3776,6 +3776,14 @@ static int fg_notifier_cb(struct notifier_block *nb,
struct power_supply *psy = data;
struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
spin_lock(&chip->suspend_lock);
if (chip->suspended) {
/* Return if we are still suspended */
spin_unlock(&chip->suspend_lock);
return NOTIFY_OK;
}
spin_unlock(&chip->suspend_lock);
if (event != PSY_EVENT_PROP_CHANGED)
return NOTIFY_OK;
@ -5089,6 +5097,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
mutex_init(&chip->ttf.lock);
mutex_init(&chip->charge_full_lock);
mutex_init(&chip->qnovo_esr_ctrl_lock);
spin_lock_init(&chip->suspend_lock);
init_completion(&chip->soc_update);
init_completion(&chip->soc_ready);
INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
@ -5186,6 +5195,10 @@ static int fg_gen3_suspend(struct device *dev)
struct fg_chip *chip = dev_get_drvdata(dev);
int rc;
spin_lock(&chip->suspend_lock);
chip->suspended = true;
spin_unlock(&chip->suspend_lock);
rc = fg_esr_timer_config(chip, true);
if (rc < 0)
pr_err("Error in configuring ESR timer, rc=%d\n", rc);
@ -5209,6 +5222,16 @@ static int fg_gen3_resume(struct device *dev)
if (fg_sram_dump)
schedule_delayed_work(&chip->sram_dump_work,
msecs_to_jiffies(fg_sram_dump_period_ms));
if (!work_pending(&chip->status_change_work)) {
pm_stay_awake(chip->dev);
schedule_work(&chip->status_change_work);
}
spin_lock(&chip->suspend_lock);
chip->suspended = false;
spin_unlock(&chip->suspend_lock);
return 0;
}