Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio/omap: optimise interrupt service routine

The OMAP GPIO interrupt service routine is checking each bit in the
GPIO interrupt status register to see which bits are set. It is not
efficient to check every bit especially if only a few bits are set.
Therefore, instead of checking every bit use the __ffs() function,
which returns the location of the first set bit, to find all the set
bits.

This optimisation was suggested-by and developed in collaboration
with Felipe Balbi.

Signed-off-by: Jon Hunter <jon-hunter@ti.com>
Reviewed-by: Felipe Balbi <balbi@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>

authored by

Jon Hunter and committed by
Linus Walleij
3513cdec 60b18b9a

+7 -7
+7 -7
drivers/gpio/gpio-omap.c
··· 689 689 { 690 690 void __iomem *isr_reg = NULL; 691 691 u32 isr; 692 - unsigned int i; 692 + unsigned int bit; 693 693 struct gpio_bank *bank; 694 694 int unmasked = 0; 695 695 struct irq_chip *chip = irq_desc_get_chip(desc); ··· 730 730 if (!isr) 731 731 break; 732 732 733 - for (i = 0; isr != 0; isr >>= 1, i++) { 734 - if (!(isr & 1)) 735 - continue; 733 + while (isr) { 734 + bit = __ffs(isr); 735 + isr &= ~(1 << bit); 736 736 737 737 /* 738 738 * Some chips can't respond to both rising and falling ··· 741 741 * to respond to the IRQ for the opposite direction. 742 742 * This will be indicated in the bank toggle_mask. 743 743 */ 744 - if (bank->toggle_mask & (1 << i)) 745 - _toggle_gpio_edge_triggering(bank, i); 744 + if (bank->toggle_mask & (1 << bit)) 745 + _toggle_gpio_edge_triggering(bank, bit); 746 746 747 - generic_handle_irq(irq_find_mapping(bank->domain, i)); 747 + generic_handle_irq(irq_find_mapping(bank->domain, bit)); 748 748 } 749 749 } 750 750 /* if bank has any level sensitive GPIO pin interrupt