diff options
author | Joshua Scott <joshua.scott@alliedtelesis.co.nz> | 2015-05-21 20:35:12 -0400 |
---|---|---|
committer | Linus Walleij <linus.walleij@linaro.org> | 2015-06-01 10:53:55 -0400 |
commit | b6ac1280b6969607c5a01e316cc4ab693490c333 (patch) | |
tree | 08f9f9f49b0014d3942d9cf34b5280aff50239ef /drivers/gpio | |
parent | 121dcb760426ca67ee90a8b2db6a75eee010f8e3 (diff) |
gpio: Prevent an integer overflow in the pca953x driver
Interrupts were missed if an 8-bit integer overflow occurred. This was
observed when bank0,pin7 and bank1,pin7 changed simultaniously.
As the 8-bit totals were only checked against zero, replace them with
booleans. Name the booleans so that their purpose is clear.
Signed-off-by: Joshua Scott <joshua.scott@alliedtelesis.co.nz>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index eed42035207d..d233eb3b8132 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c | |||
@@ -443,12 +443,13 @@ static struct irq_chip pca953x_irq_chip = { | |||
443 | .irq_set_type = pca953x_irq_set_type, | 443 | .irq_set_type = pca953x_irq_set_type, |
444 | }; | 444 | }; |
445 | 445 | ||
446 | static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) | 446 | static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) |
447 | { | 447 | { |
448 | u8 cur_stat[MAX_BANK]; | 448 | u8 cur_stat[MAX_BANK]; |
449 | u8 old_stat[MAX_BANK]; | 449 | u8 old_stat[MAX_BANK]; |
450 | u8 pendings = 0; | 450 | bool pending_seen = false; |
451 | u8 trigger[MAX_BANK], triggers = 0; | 451 | bool trigger_seen = false; |
452 | u8 trigger[MAX_BANK]; | ||
452 | int ret, i, offset = 0; | 453 | int ret, i, offset = 0; |
453 | 454 | ||
454 | switch (chip->chip_type) { | 455 | switch (chip->chip_type) { |
@@ -461,7 +462,7 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) | |||
461 | } | 462 | } |
462 | ret = pca953x_read_regs(chip, offset, cur_stat); | 463 | ret = pca953x_read_regs(chip, offset, cur_stat); |
463 | if (ret) | 464 | if (ret) |
464 | return 0; | 465 | return false; |
465 | 466 | ||
466 | /* Remove output pins from the equation */ | 467 | /* Remove output pins from the equation */ |
467 | for (i = 0; i < NBANK(chip); i++) | 468 | for (i = 0; i < NBANK(chip); i++) |
@@ -471,11 +472,12 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) | |||
471 | 472 | ||
472 | for (i = 0; i < NBANK(chip); i++) { | 473 | for (i = 0; i < NBANK(chip); i++) { |
473 | trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; | 474 | trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; |
474 | triggers += trigger[i]; | 475 | if (trigger[i]) |
476 | trigger_seen = true; | ||
475 | } | 477 | } |
476 | 478 | ||
477 | if (!triggers) | 479 | if (!trigger_seen) |
478 | return 0; | 480 | return false; |
479 | 481 | ||
480 | memcpy(chip->irq_stat, cur_stat, NBANK(chip)); | 482 | memcpy(chip->irq_stat, cur_stat, NBANK(chip)); |
481 | 483 | ||
@@ -483,10 +485,11 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) | |||
483 | pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | | 485 | pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | |
484 | (cur_stat[i] & chip->irq_trig_raise[i]); | 486 | (cur_stat[i] & chip->irq_trig_raise[i]); |
485 | pending[i] &= trigger[i]; | 487 | pending[i] &= trigger[i]; |
486 | pendings += pending[i]; | 488 | if (pending[i]) |
489 | pending_seen = true; | ||
487 | } | 490 | } |
488 | 491 | ||
489 | return pendings; | 492 | return pending_seen; |
490 | } | 493 | } |
491 | 494 | ||
492 | static irqreturn_t pca953x_irq_handler(int irq, void *devid) | 495 | static irqreturn_t pca953x_irq_handler(int irq, void *devid) |