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>
This commit is contained in:
parent
554e937ec8
commit
7630499464
|
@ -562,7 +562,6 @@ static int rk808_probe(struct i2c_client *client,
|
||||||
struct rk808 *rk808;
|
struct rk808 *rk808;
|
||||||
const struct rk808_reg_data *pre_init_reg;
|
const struct rk808_reg_data *pre_init_reg;
|
||||||
const struct mfd_cell *cells;
|
const struct mfd_cell *cells;
|
||||||
void (*pm_pwroff_fn)(void) = NULL;
|
|
||||||
int nr_pre_init_regs;
|
int nr_pre_init_regs;
|
||||||
int nr_cells;
|
int nr_cells;
|
||||||
int pm_off = 0, msb, lsb;
|
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);
|
nr_pre_init_regs = ARRAY_SIZE(rk805_pre_init_reg);
|
||||||
cells = rk805s;
|
cells = rk805s;
|
||||||
nr_cells = ARRAY_SIZE(rk805s);
|
nr_cells = ARRAY_SIZE(rk805s);
|
||||||
pm_pwroff_fn = rk805_device_shutdown;
|
rk808->pm_pwroff_fn = rk805_device_shutdown;
|
||||||
break;
|
break;
|
||||||
case RK808_ID:
|
case RK808_ID:
|
||||||
rk808->regmap_cfg = &rk808_regmap_config;
|
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);
|
nr_pre_init_regs = ARRAY_SIZE(rk808_pre_init_reg);
|
||||||
cells = rk808s;
|
cells = rk808s;
|
||||||
nr_cells = ARRAY_SIZE(rk808s);
|
nr_cells = ARRAY_SIZE(rk808s);
|
||||||
pm_pwroff_fn = rk808_device_shutdown;
|
rk808->pm_pwroff_fn = rk808_device_shutdown;
|
||||||
break;
|
break;
|
||||||
case RK818_ID:
|
case RK818_ID:
|
||||||
rk808->regmap_cfg = &rk818_regmap_config;
|
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);
|
nr_pre_init_regs = ARRAY_SIZE(rk818_pre_init_reg);
|
||||||
cells = rk818s;
|
cells = rk818s;
|
||||||
nr_cells = ARRAY_SIZE(rk818s);
|
nr_cells = ARRAY_SIZE(rk818s);
|
||||||
pm_pwroff_fn = rk818_device_shutdown;
|
rk808->pm_pwroff_fn = rk818_device_shutdown;
|
||||||
break;
|
break;
|
||||||
case RK809_ID:
|
case RK809_ID:
|
||||||
case RK817_ID:
|
case RK817_ID:
|
||||||
|
@ -692,7 +691,7 @@ static int rk808_probe(struct i2c_client *client,
|
||||||
"rockchip,system-power-controller");
|
"rockchip,system-power-controller");
|
||||||
if (pm_off && !pm_power_off) {
|
if (pm_off && !pm_power_off) {
|
||||||
rk808_i2c_client = client;
|
rk808_i2c_client = client;
|
||||||
pm_power_off = pm_pwroff_fn;
|
pm_power_off = rk808->pm_pwroff_fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -707,7 +706,13 @@ static int rk808_remove(struct i2c_client *client)
|
||||||
struct rk808 *rk808 = i2c_get_clientdata(client);
|
struct rk808 *rk808 = i2c_get_clientdata(client);
|
||||||
|
|
||||||
regmap_del_irq_chip(client->irq, rk808->irq_data);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -628,5 +628,6 @@ struct rk808 {
|
||||||
long variant;
|
long variant;
|
||||||
const struct regmap_config *regmap_cfg;
|
const struct regmap_config *regmap_cfg;
|
||||||
const struct regmap_irq_chip *regmap_irq_chip;
|
const struct regmap_irq_chip *regmap_irq_chip;
|
||||||
|
void (*pm_pwroff_fn)(void);
|
||||||
};
|
};
|
||||||
#endif /* __LINUX_REGULATOR_RK808_H */
|
#endif /* __LINUX_REGULATOR_RK808_H */
|
||||||
|
|
Loading…
Reference in New Issue