aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio
diff options
context:
space:
mode:
authorJoshua Scott <joshua.scott@alliedtelesis.co.nz>2015-05-21 20:35:12 -0400
committerLinus Walleij <linus.walleij@linaro.org>2015-06-01 10:53:55 -0400
commitb6ac1280b6969607c5a01e316cc4ab693490c333 (patch)
tree08f9f9f49b0014d3942d9cf34b5280aff50239ef /drivers/gpio
parent121dcb760426ca67ee90a8b2db6a75eee010f8e3 (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.c21
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
446static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) 446static 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
492static irqreturn_t pca953x_irq_handler(int irq, void *devid) 495static irqreturn_t pca953x_irq_handler(int irq, void *devid)