Commit 5bf8db6f authored by Michael Hennerich's avatar Michael Hennerich Committed by Kleber Sacilotto de Souza

gpio: adp5588: Fix sleep-in-atomic-context bug

BugLink: https://bugs.launchpad.net/bugs/1798770

[ Upstream commit 6537886c ]

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: default avatarJia-Ju Bai <baijiaju1990@gmail.com>
Signed-off-by: default avatarMichael Hennerich <michael.hennerich@analog.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarSasha Levin <alexander.levin@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarStefan Bader <stefan.bader@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 58d13d04
...@@ -41,6 +41,8 @@ struct adp5588_gpio { ...@@ -41,6 +41,8 @@ struct adp5588_gpio {
uint8_t int_en[3]; uint8_t int_en[3];
uint8_t irq_mask[3]; uint8_t irq_mask[3];
uint8_t irq_stat[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) static int adp5588_gpio_read(struct i2c_client *client, u8 reg)
...@@ -177,12 +179,28 @@ static void adp5588_irq_bus_sync_unlock(struct irq_data *d) ...@@ -177,12 +179,28 @@ static void adp5588_irq_bus_sync_unlock(struct irq_data *d)
struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d); struct adp5588_gpio *dev = irq_data_get_irq_chip_data(d);
int i; 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]) { if (dev->int_en[i] ^ dev->irq_mask[i]) {
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, adp5588_gpio_write(dev->client, GPIO_INT_EN1 + i,
dev->int_en[i]); dev->int_en[i]);
} }
}
mutex_unlock(&dev->irq_lock); mutex_unlock(&dev->irq_lock);
} }
...@@ -225,9 +243,7 @@ static int adp5588_irq_set_type(struct irq_data *d, unsigned int type) ...@@ -225,9 +243,7 @@ static int adp5588_irq_set_type(struct irq_data *d, unsigned int type)
else else
return -EINVAL; return -EINVAL;
adp5588_gpio_direction_input(&dev->gpio_chip, gpio); dev->int_input_en[bank] |= bit;
adp5588_gpio_write(dev->client, GPIO_INT_LVL1 + bank,
dev->int_lvl[bank]);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment