diff options
author | Stefan Mavrodiev <stefan@olimex.com> | 2019-06-07 15:42:25 +0300 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2019-07-02 14:11:31 +0300 |
commit | 76304994645028accc0cfe287652344b696f4470 (patch) | |
tree | 594b62dc81e1c3efa627236786a733511367655a /drivers/mfd | |
parent | 554e937ec8d75930bc711612208af27961e3dc61 (diff) | |
download | linux-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.c | 17 |
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; } |