diff options
author | Grygorii Strashko <grygorii.strashko@ti.com> | 2013-12-18 05:07:51 -0500 |
---|---|---|
committer | Sekhar Nori <nsekhar@ti.com> | 2013-12-25 13:32:12 -0500 |
commit | 6075a8b2b6c32ddcb99b85189ae41ab2903e560f (patch) | |
tree | 76b301c58257041ed0b7444965a6c5a26c5792fc /drivers/gpio | |
parent | 0d978eb7349941139241a99acf05de6dd49b78d1 (diff) |
gpio: davinci: don't create irq_domain in case of unbanked irqs
The system may crash if:
- there are more than 1 banks
- unbanked irqs are enabled
- someone will call gpio_to_irq() for GPIO from bank2 or above
Hence, fix it by not creating irq_domain if unbanked irqs are enabled
and correct gpio_to_irq_banked() to handle this properly.
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Alexandre Courbot <gnurou@gmail.com>
Cc: Sekhar Nori <nsekhar@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Lad, Prabhakar <prabhakar.csengg@gmail.com>
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-davinci.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c index 5d163c0d0a74..7629b4f12b7f 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c | |||
@@ -351,7 +351,10 @@ static int gpio_to_irq_banked(struct gpio_chip *chip, unsigned offset) | |||
351 | { | 351 | { |
352 | struct davinci_gpio_controller *d = chip2controller(chip); | 352 | struct davinci_gpio_controller *d = chip2controller(chip); |
353 | 353 | ||
354 | return irq_create_mapping(d->irq_domain, d->chip.base + offset); | 354 | if (d->irq_domain) |
355 | return irq_create_mapping(d->irq_domain, d->chip.base + offset); | ||
356 | else | ||
357 | return -ENXIO; | ||
355 | } | 358 | } |
356 | 359 | ||
357 | static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) | 360 | static int gpio_to_irq_unbanked(struct gpio_chip *chip, unsigned offset) |
@@ -429,7 +432,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) | |||
429 | struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); | 432 | struct davinci_gpio_controller *chips = platform_get_drvdata(pdev); |
430 | struct davinci_gpio_platform_data *pdata = dev->platform_data; | 433 | struct davinci_gpio_platform_data *pdata = dev->platform_data; |
431 | struct davinci_gpio_regs __iomem *g; | 434 | struct davinci_gpio_regs __iomem *g; |
432 | struct irq_domain *irq_domain; | 435 | struct irq_domain *irq_domain = NULL; |
433 | 436 | ||
434 | ngpio = pdata->ngpio; | 437 | ngpio = pdata->ngpio; |
435 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | 438 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
@@ -453,18 +456,20 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) | |||
453 | } | 456 | } |
454 | clk_prepare_enable(clk); | 457 | clk_prepare_enable(clk); |
455 | 458 | ||
456 | irq = irq_alloc_descs(-1, 0, ngpio, 0); | 459 | if (!pdata->gpio_unbanked) { |
457 | if (irq < 0) { | 460 | irq = irq_alloc_descs(-1, 0, ngpio, 0); |
458 | dev_err(dev, "Couldn't allocate IRQ numbers\n"); | 461 | if (irq < 0) { |
459 | return irq; | 462 | dev_err(dev, "Couldn't allocate IRQ numbers\n"); |
460 | } | 463 | return irq; |
464 | } | ||
461 | 465 | ||
462 | irq_domain = irq_domain_add_legacy(NULL, ngpio, irq, 0, | 466 | irq_domain = irq_domain_add_legacy(NULL, ngpio, irq, 0, |
463 | &davinci_gpio_irq_ops, | 467 | &davinci_gpio_irq_ops, |
464 | chips); | 468 | chips); |
465 | if (!irq_domain) { | 469 | if (!irq_domain) { |
466 | dev_err(dev, "Couldn't register an IRQ domain\n"); | 470 | dev_err(dev, "Couldn't register an IRQ domain\n"); |
467 | return -ENODEV; | 471 | return -ENODEV; |
472 | } | ||
468 | } | 473 | } |
469 | 474 | ||
470 | /* | 475 | /* |
@@ -475,8 +480,7 @@ static int davinci_gpio_irq_setup(struct platform_device *pdev) | |||
475 | */ | 480 | */ |
476 | for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { | 481 | for (gpio = 0, bank = 0; gpio < ngpio; bank++, gpio += 32) { |
477 | chips[bank].chip.to_irq = gpio_to_irq_banked; | 482 | chips[bank].chip.to_irq = gpio_to_irq_banked; |
478 | if (!pdata->gpio_unbanked) | 483 | chips[bank].irq_domain = irq_domain; |
479 | chips[bank].irq_domain = irq_domain; | ||
480 | } | 484 | } |
481 | 485 | ||
482 | /* | 486 | /* |