forked from luck/tmp_suning_uos_patched
gpio: adp5588: Fix sleep-in-atomic-context bug
This fixes: [BUG] gpio: gpio-adp5588: A possible sleep-in-atomic-context bug in adp5588_gpio_write() [BUG] gpio: gpio-adp5588: A possible sleep-in-atomic-context bug in adp5588_gpio_direction_input() Reported-by: Jia-Ju Bai <baijiaju1990@gmail.com> Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
This commit is contained in:
parent
5b394b2ddf
commit
6537886cdc
|
@ -41,6 +41,8 @@ struct adp5588_gpio {
|
|||
uint8_t int_en[3];
|
||||
uint8_t irq_mask[3];
|
||||
uint8_t irq_stat[3];
|
||||
uint8_t int_input_en[3];
|
||||
uint8_t int_lvl_cached[3];
|
||||
};
|
||||
|
||||
static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
|
||||
|
@ -173,12 +175,28 @@ static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
|
|||
struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++)
|
||||
for (i = 0; i <= ADP5588_BANK(ADP5588_MAXGPIO); i++) {
|
||||
if (dev->int_input_en[i]) {
|
||||
mutex_lock(&dev->lock);
|
||||
dev->dir[i] &= ~dev->int_input_en[i];
|
||||
dev->int_input_en[i] = 0;
|
||||
adp5588_gpio_write(dev->client, GPIO_DIR1 + i,
|
||||
dev->dir[i]);
|
||||
mutex_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
if (dev->int_lvl_cached[i] != dev->int_lvl[i]) {
|
||||
dev->int_lvl_cached[i] = dev->int_lvl[i];
|
||||
adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + i,
|
||||
dev->int_lvl[i]);
|
||||
}
|
||||
|
||||
if (dev->int_en[i] ^ dev->irq_mask[i]) {
|
||||
dev->int_en[i] = dev->irq_mask[i];
|
||||
adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
|
||||
dev->int_en[i]);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dev->irq_lock);
|
||||
}
|
||||
|
@ -221,9 +239,7 @@ static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
|
|||
else
|
||||
return -EINVAL;
|
||||
|
||||
adp5588_gpio_direction_input(&dev->gpio_chip, gpio);
|
||||
adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
|
||||
dev->int_lvl[bank]);
|
||||
dev->int_input_en[bank] |= bit;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user