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:
parent
11734d0451
commit
fa88f5e4cb
2 changed files with 25 additions and 0 deletions
|
@ -404,6 +404,7 @@ struct fg_chip {
|
||||||
struct mutex sram_rw_lock;
|
struct mutex sram_rw_lock;
|
||||||
struct mutex charge_full_lock;
|
struct mutex charge_full_lock;
|
||||||
struct mutex qnovo_esr_ctrl_lock;
|
struct mutex qnovo_esr_ctrl_lock;
|
||||||
|
spinlock_t suspend_lock;
|
||||||
u32 batt_soc_base;
|
u32 batt_soc_base;
|
||||||
u32 batt_info_base;
|
u32 batt_info_base;
|
||||||
u32 mem_if_base;
|
u32 mem_if_base;
|
||||||
|
@ -438,6 +439,7 @@ struct fg_chip {
|
||||||
bool slope_limit_en;
|
bool slope_limit_en;
|
||||||
bool use_ima_single_mode;
|
bool use_ima_single_mode;
|
||||||
bool qnovo_enable;
|
bool qnovo_enable;
|
||||||
|
bool suspended;
|
||||||
struct completion soc_update;
|
struct completion soc_update;
|
||||||
struct completion soc_ready;
|
struct completion soc_ready;
|
||||||
struct delayed_work profile_load_work;
|
struct delayed_work profile_load_work;
|
||||||
|
|
|
@ -3776,6 +3776,14 @@ static int fg_notifier_cb(struct notifier_block *nb,
|
||||||
struct power_supply *psy = data;
|
struct power_supply *psy = data;
|
||||||
struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
|
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)
|
if (event != PSY_EVENT_PROP_CHANGED)
|
||||||
return NOTIFY_OK;
|
return NOTIFY_OK;
|
||||||
|
|
||||||
|
@ -5089,6 +5097,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
|
||||||
mutex_init(&chip->ttf.lock);
|
mutex_init(&chip->ttf.lock);
|
||||||
mutex_init(&chip->charge_full_lock);
|
mutex_init(&chip->charge_full_lock);
|
||||||
mutex_init(&chip->qnovo_esr_ctrl_lock);
|
mutex_init(&chip->qnovo_esr_ctrl_lock);
|
||||||
|
spin_lock_init(&chip->suspend_lock);
|
||||||
init_completion(&chip->soc_update);
|
init_completion(&chip->soc_update);
|
||||||
init_completion(&chip->soc_ready);
|
init_completion(&chip->soc_ready);
|
||||||
INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
|
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);
|
struct fg_chip *chip = dev_get_drvdata(dev);
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
spin_lock(&chip->suspend_lock);
|
||||||
|
chip->suspended = true;
|
||||||
|
spin_unlock(&chip->suspend_lock);
|
||||||
|
|
||||||
rc = fg_esr_timer_config(chip, true);
|
rc = fg_esr_timer_config(chip, true);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
pr_err("Error in configuring ESR timer, rc=%d\n", rc);
|
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)
|
if (fg_sram_dump)
|
||||||
schedule_delayed_work(&chip->sram_dump_work,
|
schedule_delayed_work(&chip->sram_dump_work,
|
||||||
msecs_to_jiffies(fg_sram_dump_period_ms));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue