qcom: battery: Fix using stale votable pointers
The code flow between battery.c and smblib.c could end up with stale references in smblib. This is when if pl_init fails for some reason after creating the votables, while smblib obtains references to them, those references become invalid. Fix this by calling pl_init early in smb2 driver's probe such that if it fails smb2 driver exits early. Also change the name of pl_(de)init() functions to more appropriate name - qcom_batt_(de)init(). Change-Id: I58f79d26e6cc8524e792a23185ff6fc8cfdffa75 Signed-off-by: Harry Yang <harryy@codeaurora.org> Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
parent
0f0e36134d
commit
3ecadbc42f
3 changed files with 69 additions and 17 deletions
|
@ -930,11 +930,17 @@ static int pl_determine_initial_status(struct pl_data *chip)
|
|||
}
|
||||
|
||||
#define DEFAULT_RESTRICTED_CURRENT_UA 1000000
|
||||
static int pl_init(void)
|
||||
int qcom_batt_init(void)
|
||||
{
|
||||
struct pl_data *chip;
|
||||
int rc = 0;
|
||||
|
||||
/* initialize just once */
|
||||
if (the_chip) {
|
||||
pr_err("was initialized earlier Failing now\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
@ -1014,7 +1020,9 @@ static int pl_init(void)
|
|||
goto unreg_notifier;
|
||||
}
|
||||
|
||||
return rc;
|
||||
the_chip = chip;
|
||||
|
||||
return 0;
|
||||
|
||||
unreg_notifier:
|
||||
power_supply_unreg_notifier(&chip->nb);
|
||||
|
@ -1031,21 +1039,23 @@ cleanup:
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void pl_deinit(void)
|
||||
void qcom_batt_deinit(void)
|
||||
{
|
||||
struct pl_data *chip = the_chip;
|
||||
|
||||
if (chip == NULL)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&chip->status_change_work);
|
||||
cancel_delayed_work_sync(&chip->pl_taper_work);
|
||||
cancel_work_sync(&chip->pl_disable_forever_work);
|
||||
|
||||
power_supply_unreg_notifier(&chip->nb);
|
||||
destroy_votable(chip->pl_awake_votable);
|
||||
destroy_votable(chip->pl_disable_votable);
|
||||
destroy_votable(chip->fv_votable);
|
||||
destroy_votable(chip->fcc_votable);
|
||||
wakeup_source_unregister(chip->pl_ws);
|
||||
the_chip = NULL;
|
||||
kfree(chip);
|
||||
}
|
||||
|
||||
module_init(pl_init);
|
||||
module_exit(pl_deinit)
|
||||
|
||||
MODULE_DESCRIPTION("");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
|
17
drivers/power/supply/qcom/battery.h
Normal file
17
drivers/power/supply/qcom/battery.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __BATTERY_H
|
||||
#define __BATTERY_H
|
||||
int qcom_batt_init(void);
|
||||
void qcom_batt_deinit(void);
|
||||
#endif /* __BATTERY_H */
|
|
@ -19,10 +19,11 @@
|
|||
#include <linux/qpnp/qpnp-revid.h>
|
||||
#include <linux/input/qpnp-power-on.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/pmic-voter.h>
|
||||
#include "smb-lib.h"
|
||||
#include "smb-reg.h"
|
||||
#include "battery.h"
|
||||
#include "storm-watch.h"
|
||||
#include <linux/pmic-voter.h>
|
||||
|
||||
#define smblib_err(chg, fmt, ...) \
|
||||
pr_err("%s: %s: " fmt, chg->name, \
|
||||
|
@ -4268,26 +4269,30 @@ static int smblib_create_votables(struct smb_charger *chg)
|
|||
int rc = 0;
|
||||
|
||||
chg->fcc_votable = find_votable("FCC");
|
||||
if (!chg->fcc_votable) {
|
||||
rc = -EPROBE_DEFER;
|
||||
if (chg->fcc_votable == NULL) {
|
||||
rc = -EINVAL;
|
||||
smblib_err(chg, "Couldn't find FCC votable rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chg->fv_votable = find_votable("FV");
|
||||
if (!chg->fv_votable) {
|
||||
rc = -EPROBE_DEFER;
|
||||
if (chg->fv_votable == NULL) {
|
||||
rc = -EINVAL;
|
||||
smblib_err(chg, "Couldn't find FV votable rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chg->usb_icl_votable = find_votable("USB_ICL");
|
||||
if (!chg->usb_icl_votable) {
|
||||
rc = -EPROBE_DEFER;
|
||||
rc = -EINVAL;
|
||||
smblib_err(chg, "Couldn't find USB_ICL votable rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chg->pl_disable_votable = find_votable("PL_DISABLE");
|
||||
if (!chg->pl_disable_votable) {
|
||||
rc = -EPROBE_DEFER;
|
||||
if (chg->pl_disable_votable == NULL) {
|
||||
rc = -EINVAL;
|
||||
smblib_err(chg, "Couldn't find votable PL_DISABLE rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
vote(chg->pl_disable_votable, PL_INDIRECT_VOTER, true, 0);
|
||||
|
@ -4471,6 +4476,14 @@ int smblib_init(struct smb_charger *chg)
|
|||
case PARALLEL_MASTER:
|
||||
chg->qnovo_fcc_ua = -EINVAL;
|
||||
chg->qnovo_fv_uv = -EINVAL;
|
||||
|
||||
rc = qcom_batt_init();
|
||||
if (rc < 0) {
|
||||
smblib_err(chg, "Couldn't init qcom_batt_init rc=%d\n",
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = smblib_create_votables(chg);
|
||||
if (rc < 0) {
|
||||
smblib_err(chg, "Couldn't create votables rc=%d\n",
|
||||
|
@ -4502,8 +4515,20 @@ int smblib_deinit(struct smb_charger *chg)
|
|||
{
|
||||
switch (chg->mode) {
|
||||
case PARALLEL_MASTER:
|
||||
cancel_work_sync(&chg->bms_update_work);
|
||||
cancel_work_sync(&chg->rdstd_cc2_detach_work);
|
||||
cancel_delayed_work_sync(&chg->hvdcp_detect_work);
|
||||
cancel_delayed_work_sync(&chg->step_soc_req_work);
|
||||
cancel_delayed_work_sync(&chg->clear_hdc_work);
|
||||
cancel_work_sync(&chg->otg_oc_work);
|
||||
cancel_work_sync(&chg->vconn_oc_work);
|
||||
cancel_delayed_work_sync(&chg->otg_ss_done_work);
|
||||
cancel_delayed_work_sync(&chg->icl_change_work);
|
||||
cancel_delayed_work_sync(&chg->pl_enable_work);
|
||||
cancel_work_sync(&chg->legacy_detection_work);
|
||||
power_supply_unreg_notifier(&chg->nb);
|
||||
smblib_destroy_votables(chg);
|
||||
qcom_batt_deinit();
|
||||
break;
|
||||
case PARALLEL_SLAVE:
|
||||
break;
|
||||
|
|
Loading…
Add table
Reference in a new issue