summaryrefslogtreecommitdiff
path: root/drivers/mfd
diff options
context:
space:
mode:
authorStefan Mavrodiev <stefan@olimex.com>2019-06-07 15:42:25 +0300
committerLee Jones <lee.jones@linaro.org>2019-07-02 14:11:31 +0300
commit76304994645028accc0cfe287652344b696f4470 (patch)
tree594b62dc81e1c3efa627236786a733511367655a /drivers/mfd
parent554e937ec8d75930bc711612208af27961e3dc61 (diff)
downloadlinux-76304994645028accc0cfe287652344b696f4470.tar.xz
mfd: rk808: Check pm_power_off pointer
The function pointer pm_power_off may point to function from other module (PSCI for example). If rk808 is removed, pm_power_off is overwritten to NULL and the system cannot be powered off. This patch checks if pm_power_off points to a module function. Signed-off-by: Stefan Mavrodiev <stefan@olimex.com> Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/rk808.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/drivers/mfd/rk808.c b/drivers/mfd/rk808.c
index 6ee1c461a3bb..e234720fee02 100644
--- a/drivers/mfd/rk808.c
+++ b/drivers/mfd/rk808.c
@@ -562,7 +562,6 @@ static int rk808_probe(struct i2c_client *client,
struct rk808 *rk808;
const struct rk808_reg_data *pre_init_reg;
const struct mfd_cell *cells;
- void (*pm_pwroff_fn)(void) = NULL;
int nr_pre_init_regs;
int nr_cells;
int pm_off = 0, msb, lsb;
@@ -609,7 +608,7 @@ static int rk808_probe(struct i2c_client *client,
nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
cells = rk805s;
nr_cells = ARRAY_SIZE(rk805s);
- pm_pwroff_fn = rk805_device_shutdown;
+ rk808->pm_pwroff_fn = rk805_device_shutdown;
break;
case RK808_ID:
rk808->regmap_cfg = &rk808_regmap_config;
@@ -618,7 +617,7 @@ static int rk808_probe(struct i2c_client *client,
nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
cells = rk808s;
nr_cells = ARRAY_SIZE(rk808s);
- pm_pwroff_fn = rk808_device_shutdown;
+ rk808->pm_pwroff_fn = rk808_device_shutdown;
break;
case RK818_ID:
rk808->regmap_cfg = &rk818_regmap_config;
@@ -627,7 +626,7 @@ static int rk808_probe(struct i2c_client *client,
nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
cells = rk818s;
nr_cells = ARRAY_SIZE(rk818s);
- pm_pwroff_fn = rk818_device_shutdown;
+ rk808->pm_pwroff_fn = rk818_device_shutdown;
break;
case RK809_ID:
case RK817_ID:
@@ -692,7 +691,7 @@ static int rk808_probe(struct i2c_client *client,
"rockchip,system-power-controller");
if (pm_off && !pm_power_off) {
rk808_i2c_client = client;
- pm_power_off = pm_pwroff_fn;
+ pm_power_off = rk808->pm_pwroff_fn;
}
return 0;
@@ -707,7 +706,13 @@ static int rk808_remove(struct i2c_client *client)
struct rk808 *rk808 = i2c_get_clientdata(client);
regmap_del_irq_chip(client->irq, rk808->irq_data);
- pm_power_off = NULL;
+
+ /**
+ * pm_power_off may points to a function from another module.
+ * Check if the pointer is set by us and only then overwrite it.
+ */
+ if (rk808->pm_pwroff_fn && pm_power_off == rk808->pm_pwroff_fn)
+ pm_power_off = NULL;
return 0;
}