aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorSemen Protsenko <semen.protsenko@globallogic.com>2015-01-13 08:41:44 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-01-15 12:03:49 -0500
commit09afa276d52ea5a7ff8fcd2ad9dfe204bfb18372 (patch)
tree58551a32dd3959887c5e19b7f7b7ea0d8544962a /drivers/gpio
parent479f8a5744d8141e95ef40ab364ae2d3648848ef (diff)
gpio: max732x: Fix possible deadlock
This patch was derived from next one: "gpio: fix pca953x set_type 'scheduling while atomic' bug". After adding entry that consumes max732x GPIO as interrupt line to dts file, deadlock appears somewhere in max732x probe function. Deadlock caught by lockdep (from kernel log): <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< cut here >>>>>>>>>>>>>>>>>>>>>>>>>>> [ 0.473419] ====================================================== [ 0.473419] [ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ] [ 0.473449] 3.x.xx-xxxxx-xxxxxxxx-dirty #2 Tainted: G W [ 0.473449] ------------------------------------------------------ [ 0.473449] swapper/0/1 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: [ 0.473449] (&lock->wait_lock){+.+...}, at: [<c072e350>] rt_mutex_trylock+0xc/0x74 [ 0.473480] [ 0.473480] and this task is already holding: [ 0.473510] (&chip->lock){......}, at: [<c0314514>] max732x_gpio_set_value+0x2c/0xa4 [ 0.473541] which would create a new lock dependency: [ 0.473541] (&chip->lock){......} -> (&lock->wait_lock){+.+...} ... [ 0.474273] *** DEADLOCK *** [ 0.474273] [ 0.474273] 5 locks held by swapper/0/1: [ 0.474273] #0: (&__lockdep_no_validate__){......}, at: [<c03b2328>] __driver_attach+0x48/0x98 [ 0.474304] #1: (&__lockdep_no_validate__){......}, at: [<c03b2338>] __driver_attach+0x58/0x98 [ 0.474334] #2: (&chip->irq_lock){+.+...}, at: [<c0313e3c>] max732x_irq_bus_lock+0x14/0x20 [ 0.474365] #3: (&irq_desc_lock_class){-.....}, at: [<c00a65a4>] __irq_get_desc_lock+0x48/0x88 [ 0.474365] #4: (&chip->lock){......}, at: [<c0314514>] max732x_gpio <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< cut here >>>>>>>>>>>>>>>>>>>>>>>>>>> Signed-off-by: Semen Protsenko <semen.protsenko@globallogic.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r--drivers/gpio/gpio-max732x.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/gpio/gpio-max732x.c b/drivers/gpio/gpio-max732x.c
index f8f3e8081a89..5fbab135f4a7 100644
--- a/drivers/gpio/gpio-max732x.c
+++ b/drivers/gpio/gpio-max732x.c
@@ -377,8 +377,18 @@ static void max732x_irq_bus_lock(struct irq_data *d)
377static void max732x_irq_bus_sync_unlock(struct irq_data *d) 377static void max732x_irq_bus_sync_unlock(struct irq_data *d)
378{ 378{
379 struct max732x_chip *chip = irq_data_get_irq_chip_data(d); 379 struct max732x_chip *chip = irq_data_get_irq_chip_data(d);
380 uint16_t new_irqs;
381 uint16_t level;
380 382
381 max732x_irq_update_mask(chip); 383 max732x_irq_update_mask(chip);
384
385 new_irqs = chip->irq_trig_fall | chip->irq_trig_raise;
386 while (new_irqs) {
387 level = __ffs(new_irqs);
388 max732x_gpio_direction_input(&chip->gpio_chip, level);
389 new_irqs &= ~(1 << level);
390 }
391
382 mutex_unlock(&chip->irq_lock); 392 mutex_unlock(&chip->irq_lock);
383} 393}
384 394
@@ -410,7 +420,7 @@ static int max732x_irq_set_type(struct irq_data *d, unsigned int type)
410 else 420 else
411 chip->irq_trig_raise &= ~mask; 421 chip->irq_trig_raise &= ~mask;
412 422
413 return max732x_gpio_direction_input(&chip->gpio_chip, off); 423 return 0;
414} 424}
415 425
416static struct irq_chip max732x_irq_chip = { 426static struct irq_chip max732x_irq_chip = {