Commit b6ac1280 authored by Joshua Scott's avatar Joshua Scott Committed by Linus Walleij

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: default avatarJoshua Scott <joshua.scott@alliedtelesis.co.nz>
Reviewed-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent 121dcb76
...@@ -443,12 +443,13 @@ static struct irq_chip pca953x_irq_chip = { ...@@ -443,12 +443,13 @@ static struct irq_chip pca953x_irq_chip = {
.irq_set_type = pca953x_irq_set_type, .irq_set_type = pca953x_irq_set_type,
}; };
static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) static bool pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
{ {
u8 cur_stat[MAX_BANK]; u8 cur_stat[MAX_BANK];
u8 old_stat[MAX_BANK]; u8 old_stat[MAX_BANK];
u8 pendings = 0; bool pending_seen = false;
u8 trigger[MAX_BANK], triggers = 0; bool trigger_seen = false;
u8 trigger[MAX_BANK];
int ret, i, offset = 0; int ret, i, offset = 0;
switch (chip->chip_type) { switch (chip->chip_type) {
...@@ -461,7 +462,7 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) ...@@ -461,7 +462,7 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
} }
ret = pca953x_read_regs(chip, offset, cur_stat); ret = pca953x_read_regs(chip, offset, cur_stat);
if (ret) if (ret)
return 0; return false;
/* Remove output pins from the equation */ /* Remove output pins from the equation */
for (i = 0; i < NBANK(chip); i++) for (i = 0; i < NBANK(chip); i++)
...@@ -471,11 +472,12 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) ...@@ -471,11 +472,12 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
for (i = 0; i < NBANK(chip); i++) { for (i = 0; i < NBANK(chip); i++) {
trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i]; trigger[i] = (cur_stat[i] ^ old_stat[i]) & chip->irq_mask[i];
triggers += trigger[i]; if (trigger[i])
trigger_seen = true;
} }
if (!triggers) if (!trigger_seen)
return 0; return false;
memcpy(chip->irq_stat, cur_stat, NBANK(chip)); memcpy(chip->irq_stat, cur_stat, NBANK(chip));
...@@ -483,10 +485,11 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending) ...@@ -483,10 +485,11 @@ static u8 pca953x_irq_pending(struct pca953x_chip *chip, u8 *pending)
pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) | pending[i] = (old_stat[i] & chip->irq_trig_fall[i]) |
(cur_stat[i] & chip->irq_trig_raise[i]); (cur_stat[i] & chip->irq_trig_raise[i]);
pending[i] &= trigger[i]; pending[i] &= trigger[i];
pendings += pending[i]; if (pending[i])
pending_seen = true;
} }
return pendings; return pending_seen;
} }
static irqreturn_t pca953x_irq_handler(int irq, void *devid) static irqreturn_t pca953x_irq_handler(int irq, void *devid)
......
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