summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2015-12-22 16:58:02 +0100
committerSebastian Andrzej Siewior <bigeasy@linutronix.de>2015-12-22 16:58:02 +0100
commit1ccda4237a810cc0ef5c801ed1fd512543c70785 (patch)
tree50c0e9206604a7efb0773766f0e1712f70a1609a
parent16abccd3189b44fa3a2de507d3fe03e14f9b5e43 (diff)
download4.12-rt-patches-1ccda4237a810cc0ef5c801ed1fd512543c70785.tar.gz
[ANNOUNCE] 4.1.15-rt17
Dear RT folks! I'm pleased to announce the v4.1.15-rt17 patch set. Changes since v4.1.15-rt16: Axel Lin (1): gpio: omap: Fix missing raw locks conversion Grygorii Strashko (15): gpio: omap: fix omap_gpio_free to not clean up irq configuration gpio: omap: fix error handling in omap_gpio_irq_type gpio: omap: rework omap_x_irq_shutdown to touch only irqs specific registers gpio: omap: rework omap_gpio_request to touch only gpio specific registers gpio: omap: rework omap_gpio_irq_startup to handle current pin state properly gpio: omap: add missed spin_unlock_irqrestore in omap_gpio_irq_type gpio: omap: prevent module from being unloaded while in use gpio: omap: remove wrong irq_domain_remove usage in probe gpio: omap: switch to use platform_get_irq gpio: omap: fix omap2_set_gpio_debounce gpio: omap: protect regs access in omap_gpio_irq_handler gpio: omap: fix clk_prepare/unprepare usage gpio: omap: fix static checker warning gpio: omap: move pm runtime in irq_chip.irq_bus_lock/sync_unlock gpio: omap: convert to use generic irq handler Russ Dill (1): ARM: OMAP2: Drop the concept of certain power domains not being able to lose context. Sebastian Andrzej Siewior (4): Revert "x86: Do not disable preemption in int3 on 32bit" Revert "gpio: omap: use raw locks for locking" gpio: omap: use raw locks for locking v4.1.15-rt17 Tony Lindgren (3): gpio: omap: Allow building as a loadable module gpio: omap: Fix gpiochip_add() handling for deferred probe gpio: omap: Fix GPIO numbering for deferred probe Yang Shi (1): x86/signal: delay calling signals on 32bit bmouring@ni.com (1): rtmutex: Use chainwalking control enum Known issues: - bcache stays disabled - CPU hotplug is not better than before - The netlink_release() OOPS, reported by Clark, is still on the list, but unsolved due to lack of information - Christoph Mathys reported a stall in cgroup locking code while using Linux containers. The delta patch against 4.1.15-rt17 is appended below and can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.1/incr/patch-4.1.15-rt16-rt17.patch.xz You can get this release via the git tree at: git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v4.1.15-rt17 The RT patch against 4.1.15 can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.1/patch-4.1.15-rt17.patch.xz The split quilt queue is available at: https://cdn.kernel.org/pub/linux/kernel/projects/rt/4.1/patches-4.1.15-rt17.tar.xz Sebastian diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c index 7a577145b68b..689a1af47c80 100644 --- a/arch/arm/mach-omap2/gpio.c +++ b/arch/arm/mach-omap2/gpio.c @@ -130,7 +130,6 @@ static int __init omap2_gpio_dev_init(struct omap_hwmod *oh, void *unused) } pwrdm = omap_hwmod_get_pwrdm(oh); - pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm); pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata)); kfree(pdata); diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c index 78af6d8cf2e2..ef4227ffa3b6 100644 --- a/arch/arm/mach-omap2/powerdomain.c +++ b/arch/arm/mach-omap2/powerdomain.c @@ -1166,43 +1166,3 @@ int pwrdm_get_context_loss_count(struct powerdomain *pwrdm) return count; } -/** - * pwrdm_can_ever_lose_context - can this powerdomain ever lose context? - * @pwrdm: struct powerdomain * - * - * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain - * can lose either memory or logic context or if @pwrdm is invalid, or - * returns 0 otherwise. This function is not concerned with how the - * powerdomain registers are programmed (i.e., to go off or not); it's - * concerned with whether it's ever possible for this powerdomain to - * go off while some other part of the chip is active. This function - * assumes that every powerdomain can go to either ON or INACTIVE. - */ -bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm) -{ - int i; - - if (!pwrdm) { - pr_debug("powerdomain: %s: invalid powerdomain pointer\n", - __func__); - return 1; - } - - if (pwrdm->pwrsts & PWRSTS_OFF) - return 1; - - if (pwrdm->pwrsts & PWRSTS_RET) { - if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF) - return 1; - - for (i = 0; i < pwrdm->banks; i++) - if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF) - return 1; - } - - for (i = 0; i < pwrdm->banks; i++) - if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF) - return 1; - - return 0; -} diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h index 28a796ce07d7..5e0c033a21db 100644 --- a/arch/arm/mach-omap2/powerdomain.h +++ b/arch/arm/mach-omap2/powerdomain.h @@ -244,7 +244,6 @@ int pwrdm_state_switch(struct powerdomain *pwrdm); int pwrdm_pre_transition(struct powerdomain *pwrdm); int pwrdm_post_transition(struct powerdomain *pwrdm); int pwrdm_get_context_loss_count(struct powerdomain *pwrdm); -bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm); extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state); diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h index b1b08a28c72a..0e7bfe98e1d1 100644 --- a/arch/x86/include/asm/signal.h +++ b/arch/x86/include/asm/signal.h @@ -32,7 +32,7 @@ typedef struct { * TIF_NOTIFY_RESUME and set up the signal to be sent on exit of the * trap. */ -#if defined(CONFIG_PREEMPT_RT_FULL) && defined(CONFIG_X86_64) +#if defined(CONFIG_PREEMPT_RT_FULL) #define ARCH_RT_DELAYS_SIGNAL_SEND #endif diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ebae118938ef..324ab5247687 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -88,21 +88,9 @@ static inline void conditional_sti(struct pt_regs *regs) local_irq_enable(); } -static inline void conditional_sti_ist(struct pt_regs *regs) +static inline void preempt_conditional_sti(struct pt_regs *regs) { -#ifdef CONFIG_X86_64 - /* - * X86_64 uses a per CPU stack on the IST for certain traps - * like int3. The task can not be preempted when using one - * of these stacks, thus preemption must be disabled, otherwise - * the stack can be corrupted if the task is scheduled out, - * and another task comes in and uses this stack. - * - * On x86_32 the task keeps its own stack and it is OK if the - * task schedules out. - */ preempt_count_inc(); -#endif if (regs->flags & X86_EFLAGS_IF) local_irq_enable(); } @@ -113,13 +101,11 @@ static inline void conditional_cli(struct pt_regs *regs) local_irq_disable(); } -static inline void conditional_cli_ist(struct pt_regs *regs) +static inline void preempt_conditional_cli(struct pt_regs *regs) { if (regs->flags & X86_EFLAGS_IF) local_irq_disable(); -#ifdef CONFIG_X86_64 preempt_count_dec(); -#endif } enum ctx_state ist_enter(struct pt_regs *regs) @@ -550,9 +536,9 @@ dotraplinkage void notrace do_int3(struct pt_regs *regs, long error_code) * as we may switch to the interrupt stack. */ debug_stack_usage_inc(); - conditional_sti_ist(regs); + preempt_conditional_sti(regs); do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL); - conditional_cli_ist(regs); + preempt_conditional_cli(regs); debug_stack_usage_dec(); exit: ist_exit(regs, prev_state); @@ -682,12 +668,12 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) debug_stack_usage_inc(); /* It's safe to allow irq's after DR6 has been saved */ - conditional_sti_ist(regs); + preempt_conditional_sti(regs); if (v8086_mode(regs)) { handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, X86_TRAP_DB); - conditional_cli_ist(regs); + preempt_conditional_cli(regs); debug_stack_usage_dec(); goto exit; } @@ -707,7 +693,7 @@ dotraplinkage void do_debug(struct pt_regs *regs, long error_code) si_code = get_si_code(tsk->thread.debugreg6); if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp) send_sigtrap(tsk, regs, error_code, si_code); - conditional_cli_ist(regs); + preempt_conditional_cli(regs); debug_stack_usage_dec(); exit: diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index caefe806db5e..ff7df95de3bf 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -308,7 +308,7 @@ config GPIO_OCTEON family of SOCs. config GPIO_OMAP - bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS + tristate "TI OMAP GPIO support" if ARCH_OMAP2PLUS || COMPILE_TEST default y if ARCH_OMAP depends on ARM select GENERIC_IRQ_CHIP diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index a0ace2758e2e..4916fd726dce 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -29,6 +29,7 @@ #include <linux/platform_data/gpio-omap.h> #define OFF_MODE 1 +#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF static LIST_HEAD(omap_gpio_list); @@ -50,7 +51,7 @@ struct gpio_regs { struct gpio_bank { struct list_head node; void __iomem *base; - u16 irq; + int irq; u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; struct gpio_regs context; @@ -58,6 +59,7 @@ struct gpio_bank { u32 level_mask; u32 toggle_mask; raw_spinlock_t lock; + raw_spinlock_t wa_lock; struct gpio_chip chip; struct clk *dbck; u32 mod_usage; @@ -67,7 +69,7 @@ struct gpio_bank { struct device *dev; bool is_mpuio; bool dbck_flag; - bool loses_context; + bool context_valid; int stride; u32 width; @@ -175,7 +177,7 @@ static inline void omap_gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set static inline void omap_gpio_dbck_enable(struct gpio_bank *bank) { if (bank->dbck_enable_mask && !bank->dbck_enabled) { - clk_prepare_enable(bank->dbck); + clk_enable(bank->dbck); bank->dbck_enabled = true; writel_relaxed(bank->dbck_enable_mask, @@ -193,7 +195,7 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) */ writel_relaxed(0, bank->base + bank->regs->debounce_en); - clk_disable_unprepare(bank->dbck); + clk_disable(bank->dbck); bank->dbck_enabled = false; } } @@ -204,8 +206,9 @@ static inline void omap_gpio_dbck_disable(struct gpio_bank *bank) * @offset: the gpio number on this @bank * @debounce: debounce time to use * - * OMAP's debounce time is in 31us steps so we need - * to convert and round up to the closest unit. + * OMAP's debounce time is in 31us steps + * <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31 + * so we need to convert and round up to the closest unit. */ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, unsigned debounce) @@ -213,34 +216,33 @@ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset, void __iomem *reg; u32 val; u32 l; + bool enable = !!debounce; if (!bank->dbck_flag) return; - if (debounce < 32) - debounce = 0x01; - else if (debounce > 7936) - debounce = 0xff; - else - debounce = (debounce / 0x1f) - 1; + if (enable) { + debounce = DIV_ROUND_UP(debounce, 31) - 1; + debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK; + } l = BIT(offset); - clk_prepare_enable(bank->dbck); + clk_enable(bank->dbck); reg = bank->base + bank->regs->debounce; writel_relaxed(debounce, reg); reg = bank->base + bank->regs->debounce_en; val = readl_relaxed(reg); - if (debounce) + if (enable) val |= l; else val &= ~l; bank->dbck_enable_mask = val; writel_relaxed(val, reg); - clk_disable_unprepare(bank->dbck); + clk_disable(bank->dbck); /* * Enable debounce clock per module. * This call is mandatory because in omap_gpio_request() when @@ -285,7 +287,7 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset) bank->context.debounce = 0; writel_relaxed(bank->context.debounce, bank->base + bank->regs->debounce); - clk_disable_unprepare(bank->dbck); + clk_disable(bank->dbck); bank->dbck_enabled = false; } } @@ -488,9 +490,6 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) unsigned long flags; unsigned offset = d->hwirq; - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->dev); - if (type & ~IRQ_TYPE_SENSE_MASK) return -EINVAL; @@ -500,10 +499,15 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) raw_spin_lock_irqsave(&bank->lock, flags); retval = omap_set_gpio_triggering(bank, offset, type); + if (retval) { + raw_spin_unlock_irqrestore(&bank->lock, flags); + goto error; + } omap_gpio_init_irq(bank, offset); if (!omap_gpio_is_input(bank, offset)) { raw_spin_unlock_irqrestore(&bank->lock, flags); - return -EINVAL; + retval = -EINVAL; + goto error; } raw_spin_unlock_irqrestore(&bank->lock, flags); @@ -512,6 +516,9 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) __irq_set_handler_locked(d->irq, handle_edge_irq); + return 0; + +error: return retval; } @@ -638,22 +645,18 @@ static int omap_set_gpio_wakeup(struct gpio_bank *bank, unsigned offset, return 0; } -static void omap_reset_gpio(struct gpio_bank *bank, unsigned offset) -{ - omap_set_gpio_direction(bank, offset, 1); - omap_set_gpio_irqenable(bank, offset, 0); - omap_clear_gpio_irqstatus(bank, offset); - omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); - omap_clear_gpio_debounce(bank, offset); -} - /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable) { struct gpio_bank *bank = omap_irq_data_get_bank(d); unsigned offset = d->hwirq; + int ret; - return omap_set_gpio_wakeup(bank, offset, enable); + ret = omap_set_gpio_wakeup(bank, offset, enable); + if (!ret) + ret = irq_set_irq_wake(bank->irq, enable); + + return ret; } static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) @@ -669,14 +672,7 @@ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset) pm_runtime_get_sync(bank->dev); raw_spin_lock_irqsave(&bank->lock, flags); - /* Set trigger to none. You need to enable the desired trigger with - * request_irq() or set_irq_type(). Only do this if the IRQ line has - * not already been requested. - */ - if (!LINE_USED(bank->irq_usage, offset)) { - omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); - omap_enable_gpio_module(bank, offset); - } + omap_enable_gpio_module(bank, offset); bank->mod_usage |= BIT(offset); raw_spin_unlock_irqrestore(&bank->lock, flags); @@ -690,8 +686,11 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) raw_spin_lock_irqsave(&bank->lock, flags); bank->mod_usage &= ~(BIT(offset)); + if (!LINE_USED(bank->irq_usage, offset)) { + omap_set_gpio_direction(bank, offset, 1); + omap_clear_gpio_debounce(bank, offset); + } omap_disable_gpio_module(bank, offset); - omap_reset_gpio(bank, offset); raw_spin_unlock_irqrestore(&bank->lock, flags); /* @@ -711,29 +710,27 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) * line's interrupt handler has been run, we may miss some nested * interrupts. */ -static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) +static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) { void __iomem *isr_reg = NULL; u32 isr; unsigned int bit; - struct gpio_bank *bank; - int unmasked = 0; - struct irq_chip *irqchip = irq_desc_get_chip(desc); - struct gpio_chip *chip = irq_get_handler_data(irq); + struct gpio_bank *bank = gpiobank; + unsigned long wa_lock_flags; + unsigned long lock_flags; - chained_irq_enter(irqchip, desc); - - bank = container_of(chip, struct gpio_bank, chip); isr_reg = bank->base + bank->regs->irqstatus; - pm_runtime_get_sync(bank->dev); - if (WARN_ON(!isr_reg)) goto exit; + pm_runtime_get_sync(bank->dev); + while (1) { u32 isr_saved, level_mask = 0; u32 enabled; + raw_spin_lock_irqsave(&bank->lock, lock_flags); + enabled = omap_get_gpio_irqbank_mask(bank); isr_saved = isr = readl_relaxed(isr_reg) & enabled; @@ -747,12 +744,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask); omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask); - /* if there is only edge sensitive GPIO pin interrupts - configured, we could unmask GPIO bank interrupt immediately */ - if (!level_mask && !unmasked) { - unmasked = 1; - chained_irq_exit(irqchip, desc); - } + raw_spin_unlock_irqrestore(&bank->lock, lock_flags); if (!isr) break; @@ -761,6 +753,7 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) bit = __ffs(isr); isr &= ~(BIT(bit)); + raw_spin_lock_irqsave(&bank->lock, lock_flags); /* * Some chips can't respond to both rising and falling * at the same time. If this irq was requested with @@ -771,18 +764,20 @@ static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (bank->toggle_mask & (BIT(bit))) omap_toggle_gpio_edge_triggering(bank, bit); + raw_spin_unlock_irqrestore(&bank->lock, lock_flags); + + raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags); + generic_handle_irq(irq_find_mapping(bank->chip.irqdomain, bit)); + + raw_spin_unlock_irqrestore(&bank->wa_lock, + wa_lock_flags); } } - /* if bank has any level sensitive GPIO pin interrupt - configured, we must unmask the bank interrupt only after - handler(s) are executed in order to avoid spurious bank - interrupt */ exit: - if (!unmasked) - chained_irq_exit(irqchip, desc); pm_runtime_put(bank->dev); + return IRQ_HANDLED; } static unsigned int omap_gpio_irq_startup(struct irq_data *d) @@ -791,15 +786,22 @@ static unsigned int omap_gpio_irq_startup(struct irq_data *d) unsigned long flags; unsigned offset = d->hwirq; - if (!BANK_USED(bank)) - pm_runtime_get_sync(bank->dev); - raw_spin_lock_irqsave(&bank->lock, flags); - omap_gpio_init_irq(bank, offset); + + if (!LINE_USED(bank->mod_usage, offset)) + omap_set_gpio_direction(bank, offset, 1); + else if (!omap_gpio_is_input(bank, offset)) + goto err; + omap_enable_gpio_module(bank, offset); + bank->irq_usage |= BIT(offset); + raw_spin_unlock_irqrestore(&bank->lock, flags); omap_gpio_unmask_irq(d); return 0; +err: + raw_spin_unlock_irqrestore(&bank->lock, flags); + return -EINVAL; } static void omap_gpio_irq_shutdown(struct irq_data *d) @@ -810,9 +812,26 @@ static void omap_gpio_irq_shutdown(struct irq_data *d) raw_spin_lock_irqsave(&bank->lock, flags); bank->irq_usage &= ~(BIT(offset)); + omap_set_gpio_irqenable(bank, offset, 0); + omap_clear_gpio_irqstatus(bank, offset); + omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE); + if (!LINE_USED(bank->mod_usage, offset)) + omap_clear_gpio_debounce(bank, offset); omap_disable_gpio_module(bank, offset); - omap_reset_gpio(bank, offset); raw_spin_unlock_irqrestore(&bank->lock, flags); +} + +static void omap_gpio_irq_bus_lock(struct irq_data *data) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(data); + + if (!BANK_USED(bank)) + pm_runtime_get_sync(bank->dev); +} + +static void gpio_irq_bus_sync_unlock(struct irq_data *data) +{ + struct gpio_bank *bank = omap_irq_data_get_bank(data); /* * If this is the last IRQ to be freed in the bank, @@ -1048,10 +1067,6 @@ static void omap_gpio_mod_init(struct gpio_bank *bank) /* Initialize interface clk ungated, module enabled */ if (bank->regs->ctrl) writel_relaxed(0, base + bank->regs->ctrl); - - bank->dbck = clk_get(bank->dev, "dbclk"); - if (IS_ERR(bank->dbck)) - dev_err(bank->dev, "Could not get gpio dbck\n"); } static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) @@ -1080,7 +1095,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) } else { bank->chip.label = "gpio"; bank->chip.base = gpio; - gpio += bank->width; } bank->chip.ngpio = bank->width; @@ -1090,6 +1104,9 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) return ret; } + if (!bank->is_mpuio) + gpio += bank->width; + #ifdef CONFIG_ARCH_OMAP1 /* * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop @@ -1112,7 +1129,7 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) } ret = gpiochip_irqchip_add(&bank->chip, irqc, - irq_base, omap_gpio_irq_handler, + irq_base, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { @@ -1121,10 +1138,14 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc) return -ENODEV; } - gpiochip_set_chained_irqchip(&bank->chip, irqc, - bank->irq, omap_gpio_irq_handler); + gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL); - return 0; + ret = devm_request_irq(bank->dev, bank->irq, omap_gpio_irq_handler, + 0, dev_name(bank->dev), bank); + if (ret) + gpiochip_remove(&bank->chip); + + return ret; } static const struct of_device_id omap_gpio_match[]; @@ -1163,17 +1184,23 @@ static int omap_gpio_probe(struct platform_device *pdev) irqc->irq_unmask = omap_gpio_unmask_irq, irqc->irq_set_type = omap_gpio_irq_type, irqc->irq_set_wake = omap_gpio_wake_enable, + irqc->irq_bus_lock = omap_gpio_irq_bus_lock, + irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock, irqc->name = dev_name(&pdev->dev); - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (unlikely(!res)) { - dev_err(dev, "Invalid IRQ resource\n"); - return -ENODEV; + bank->irq = platform_get_irq(pdev, 0); + if (bank->irq <= 0) { + if (!bank->irq) + bank->irq = -ENXIO; + if (bank->irq != -EPROBE_DEFER) + dev_err(dev, + "can't get irq resource ret=%d\n", bank->irq); + return bank->irq; } - bank->irq = res->start; bank->dev = dev; bank->chip.dev = dev; + bank->chip.owner = THIS_MODULE; bank->dbck_flag = pdata->dbck_flag; bank->stride = pdata->bank_stride; bank->width = pdata->bank_width; @@ -1183,15 +1210,9 @@ static int omap_gpio_probe(struct platform_device *pdev) #ifdef CONFIG_OF_GPIO bank->chip.of_node = of_node_get(node); #endif - if (node) { - if (!of_property_read_bool(node, "ti,gpio-always-on")) - bank->loses_context = true; - } else { - bank->loses_context = pdata->loses_context; - - if (bank->loses_context) - bank->get_context_loss_count = - pdata->get_context_loss_count; + if (!node) { + bank->get_context_loss_count = + pdata->get_context_loss_count; } if (bank->regs->set_dataout && bank->regs->clr_dataout) @@ -1200,15 +1221,26 @@ static int omap_gpio_probe(struct platform_device *pdev) bank->set_dataout = omap_set_gpio_dataout_mask; raw_spin_lock_init(&bank->lock); + raw_spin_lock_init(&bank->wa_lock); /* Static mapping, never released */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); bank->base = devm_ioremap_resource(dev, res); if (IS_ERR(bank->base)) { - irq_domain_remove(bank->chip.irqdomain); return PTR_ERR(bank->base); } + if (bank->dbck_flag) { + bank->dbck = devm_clk_get(bank->dev, "dbclk"); + if (IS_ERR(bank->dbck)) { + dev_err(bank->dev, + "Could not get gpio dbck. Disable debounce\n"); + bank->dbck_flag = false; + } else { + clk_prepare(bank->dbck); + } + } + platform_set_drvdata(pdev, bank); pm_runtime_enable(bank->dev); @@ -1221,8 +1253,11 @@ static int omap_gpio_probe(struct platform_device *pdev) omap_gpio_mod_init(bank); ret = omap_gpio_chip_init(bank, irqc); - if (ret) + if (ret) { + pm_runtime_put_sync(bank->dev); + pm_runtime_disable(bank->dev); return ret; + } omap_gpio_show_rev(bank); @@ -1233,6 +1268,19 @@ static int omap_gpio_probe(struct platform_device *pdev) return 0; } +static int omap_gpio_remove(struct platform_device *pdev) +{ + struct gpio_bank *bank = platform_get_drvdata(pdev); + + list_del(&bank->node); + gpiochip_remove(&bank->chip); + pm_runtime_disable(bank->dev); + if (bank->dbck_flag) + clk_unprepare(bank->dbck); + + return 0; +} + #ifdef CONFIG_ARCH_OMAP2PLUS #if defined(CONFIG_PM) @@ -1321,7 +1369,7 @@ static int omap_gpio_runtime_resume(struct device *dev) * been initialised and so initialise it now. Also initialise * the context loss count. */ - if (bank->loses_context && !bank->context_valid) { + if (!bank->context_valid) { omap_gpio_init_context(bank); if (bank->get_context_loss_count) @@ -1342,17 +1390,15 @@ static int omap_gpio_runtime_resume(struct device *dev) writel_relaxed(bank->context.risingdetect, bank->base + bank->regs->risingdetect); - if (bank->loses_context) { - if (!bank->get_context_loss_count) { + if (!bank->get_context_loss_count) { + omap_gpio_restore_context(bank); + } else { + c = bank->get_context_loss_count(bank->dev); + if (c != bank->context_loss_count) { omap_gpio_restore_context(bank); } else { - c = bank->get_context_loss_count(bank->dev); - if (c != bank->context_loss_count) { - omap_gpio_restore_context(bank); - } else { - raw_spin_unlock_irqrestore(&bank->lock, flags); - return 0; - } + raw_spin_unlock_irqrestore(&bank->lock, flags); + return 0; } } @@ -1418,12 +1464,13 @@ static int omap_gpio_runtime_resume(struct device *dev) } #endif /* CONFIG_PM */ +#if IS_BUILTIN(CONFIG_GPIO_OMAP) void omap2_gpio_prepare_for_idle(int pwr_mode) { struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - if (!BANK_USED(bank) || !bank->loses_context) + if (!BANK_USED(bank)) continue; bank->power_mode = pwr_mode; @@ -1437,12 +1484,13 @@ void omap2_gpio_resume_after_idle(void) struct gpio_bank *bank; list_for_each_entry(bank, &omap_gpio_list, node) { - if (!BANK_USED(bank) || !bank->loses_context) + if (!BANK_USED(bank)) continue; pm_runtime_get_sync(bank->dev); } } +#endif #if defined(CONFIG_PM) static void omap_gpio_init_context(struct gpio_bank *p) @@ -1598,6 +1646,7 @@ MODULE_DEVICE_TABLE(of, omap_gpio_match); static struct platform_driver omap_gpio_driver = { .probe = omap_gpio_probe, + .remove = omap_gpio_remove, .driver = { .name = "omap_gpio", .pm = &gpio_pm_ops, @@ -1615,3 +1664,13 @@ static int __init omap_gpio_drv_reg(void) return platform_driver_register(&omap_gpio_driver); } postcore_initcall(omap_gpio_drv_reg); + +static void __exit omap_gpio_exit(void) +{ + platform_driver_unregister(&omap_gpio_driver); +} +module_exit(omap_gpio_exit); + +MODULE_DESCRIPTION("omap gpio driver"); +MODULE_ALIAS("platform:gpio-omap"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/platform_data/gpio-omap.h b/include/linux/platform_data/gpio-omap.h index 5d50b25a73d7..ff43e01b8ca9 100644 --- a/include/linux/platform_data/gpio-omap.h +++ b/include/linux/platform_data/gpio-omap.h @@ -198,7 +198,6 @@ struct omap_gpio_platform_data { int bank_width; /* GPIO bank width */ int bank_stride; /* Only needed for omap1 MPUIO */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ - bool loses_context; /* whether the bank would ever lose context */ bool is_mpuio; /* whether the bank is of type MPUIO */ u32 non_wakeup_gpios; @@ -208,9 +207,17 @@ struct omap_gpio_platform_data { int (*get_context_loss_count)(struct device *dev); }; +#if IS_BUILTIN(CONFIG_GPIO_OMAP) extern void omap2_gpio_prepare_for_idle(int off_mode); extern void omap2_gpio_resume_after_idle(void); -extern void omap_set_gpio_debounce(int gpio, int enable); -extern void omap_set_gpio_debounce_time(int gpio, int enable); +#else +static inline void omap2_gpio_prepare_for_idle(int off_mode) +{ +} + +static inline void omap2_gpio_resume_after_idle(void) +{ +} +#endif #endif diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c index 20267595df07..e0b0d9b419b5 100644 --- a/kernel/locking/rtmutex.c +++ b/kernel/locking/rtmutex.c @@ -1008,7 +1008,7 @@ static void noinline __sched rt_spin_lock_slowlock(struct rt_mutex *lock) __set_current_state_no_track(TASK_UNINTERRUPTIBLE); pi_unlock(&self->pi_lock); - ret = task_blocks_on_rt_mutex(lock, &waiter, self, 0); + ret = task_blocks_on_rt_mutex(lock, &waiter, self, RT_MUTEX_MIN_CHAINWALK); BUG_ON(ret); for (;;) { diff --git a/localversion-rt b/localversion-rt index 1199ebade17b..1e584b47c987 100644 --- a/localversion-rt +++ b/localversion-rt @@ -1 +1 @@ --rt16 +-rt17 Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-rw-r--r--patches/0001-gpio-omap-Allow-building-as-a-loadable-module.patch130
-rw-r--r--patches/0002-gpio-omap-fix-omap_gpio_free-to-not-clean-up-irq-con.patch45
-rw-r--r--patches/0003-gpio-omap-fix-error-handling-in-omap_gpio_irq_type.patch66
-rw-r--r--patches/0004-gpio-omap-rework-omap_x_irq_shutdown-to-touch-only-i.patch62
-rw-r--r--patches/0005-gpio-omap-rework-omap_gpio_request-to-touch-only-gpi.patch44
-rw-r--r--patches/0006-gpio-omap-rework-omap_gpio_irq_startup-to-handle-cur.patch52
-rw-r--r--patches/0007-gpio-omap-add-missed-spin_unlock_irqrestore-in-omap_.patch37
-rw-r--r--patches/0008-gpio-omap-prevent-module-from-being-unloaded-while-i.patch32
-rw-r--r--patches/0009-ARM-OMAP2-Drop-the-concept-of-certain-power-domains-.patch177
-rw-r--r--patches/0010-gpio-omap-use-raw-locks-for-locking.patch (renamed from patches/gpio-omap-use-raw-locks-for-locking.patch)112
-rw-r--r--patches/0011-gpio-omap-Fix-missing-raw-locks-conversion.patch29
-rw-r--r--patches/0012-gpio-omap-remove-wrong-irq_domain_remove-usage-in-pr.patch27
-rw-r--r--patches/0013-gpio-omap-switch-to-use-platform_get_irq.patch42
-rw-r--r--patches/0014-gpio-omap-fix-omap2_set_gpio_debounce.patch95
-rw-r--r--patches/0015-gpio-omap-protect-regs-access-in-omap_gpio_irq_handl.patch63
-rw-r--r--patches/0016-gpio-omap-fix-clk_prepare-unprepare-usage.patch120
-rw-r--r--patches/0017-gpio-omap-Fix-gpiochip_add-handling-for-deferred-pro.patch44
-rw-r--r--patches/0018-gpio-omap-Fix-GPIO-numbering-for-deferred-probe.patch43
-rw-r--r--patches/0019-gpio-omap-fix-static-checker-warning.patch47
-rw-r--r--patches/0020-gpio-omap-move-pm-runtime-in-irq_chip.irq_bus_lock-s.patch133
-rw-r--r--patches/0021-gpio-omap-convert-to-use-generic-irq-handler.patch184
-rw-r--r--patches/KVM-lapic-mark-LAPIC-timer-handler-as-irqsafe.patch10
-rw-r--r--patches/KVM-use-simple-waitqueue-for-vcpu-wq.patch6
-rw-r--r--patches/Revert-x86-Do-not-disable-preemption-in-int3-on-32bi.patch90
-rw-r--r--patches/irqwork-Move-irq-safe-work-to-irq-context.patch18
-rw-r--r--patches/localversion.patch4
-rw-r--r--patches/rtmutex-Use-chainwalking-control-enum.patch28
-rw-r--r--patches/series25
-rw-r--r--patches/x86-signal-delay-calling-signals-on-32bit.patch42
29 files changed, 1739 insertions, 68 deletions
diff --git a/patches/0001-gpio-omap-Allow-building-as-a-loadable-module.patch b/patches/0001-gpio-omap-Allow-building-as-a-loadable-module.patch
new file mode 100644
index 00000000000000..63fae94bf1c2ad
--- /dev/null
+++ b/patches/0001-gpio-omap-Allow-building-as-a-loadable-module.patch
@@ -0,0 +1,130 @@
+From ed28ad9cd730334b1df1de8268c2fef20766cb59 Mon Sep 17 00:00:00 2001
+From: Tony Lindgren <tony@atomide.com>
+Date: Mon, 13 Jul 2015 17:04:15 +0300
+Subject: [PATCH 01/21] gpio: omap: Allow building as a loadable module
+
+commit cac089f9026e9ddb3481daf08f0fc4e5949fa1af upstream
+
+We currently get all kinds of errors building the omap gpio driver
+as a module starting with:
+
+undefined reference to `omap2_gpio_resume_after_idle'
+undefined reference to `omap2_gpio_prepare_for_idle'
+...
+
+Let's fix the issue by adding inline functions to the header.
+Note that we can now also remove the two unused functions for
+omap_set_gpio_debounce and omap_set_gpio_debounce_time.
+
+Then doing rmmod on the module produces further warnings
+because of missing exit related functions. Let's add those.
+
+And finally, we can make the Kconfig entry just a tristate
+option that's selected for omaps.
+
+Cc: Javier Martinez Canillas <javier@dowhile0.org>
+Cc: Kevin Hilman <khilman@deeprootsystems.com>
+Cc: Nishanth Menon <nm@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Reviewed-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Reviewed-by: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/Kconfig | 2 +-
+ drivers/gpio/gpio-omap.c | 24 ++++++++++++++++++++++++
+ include/linux/platform_data/gpio-omap.h | 12 ++++++++++--
+ 3 files changed, 35 insertions(+), 3 deletions(-)
+
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -308,7 +308,7 @@ config GPIO_OCTEON
+ family of SOCs.
+
+ config GPIO_OMAP
+- bool "TI OMAP GPIO support" if COMPILE_TEST && !ARCH_OMAP2PLUS
++ tristate "TI OMAP GPIO support" if ARCH_OMAP2PLUS || COMPILE_TEST
+ default y if ARCH_OMAP
+ depends on ARM
+ select GENERIC_IRQ_CHIP
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1233,6 +1233,17 @@ static int omap_gpio_probe(struct platfo
+ return 0;
+ }
+
++static int omap_gpio_remove(struct platform_device *pdev)
++{
++ struct gpio_bank *bank = platform_get_drvdata(pdev);
++
++ list_del(&bank->node);
++ gpiochip_remove(&bank->chip);
++ pm_runtime_disable(bank->dev);
++
++ return 0;
++}
++
+ #ifdef CONFIG_ARCH_OMAP2PLUS
+
+ #if defined(CONFIG_PM)
+@@ -1418,6 +1429,7 @@ static int omap_gpio_runtime_resume(stru
+ }
+ #endif /* CONFIG_PM */
+
++#if IS_BUILTIN(CONFIG_GPIO_OMAP)
+ void omap2_gpio_prepare_for_idle(int pwr_mode)
+ {
+ struct gpio_bank *bank;
+@@ -1443,6 +1455,7 @@ void omap2_gpio_resume_after_idle(void)
+ pm_runtime_get_sync(bank->dev);
+ }
+ }
++#endif
+
+ #if defined(CONFIG_PM)
+ static void omap_gpio_init_context(struct gpio_bank *p)
+@@ -1598,6 +1611,7 @@ MODULE_DEVICE_TABLE(of, omap_gpio_match)
+
+ static struct platform_driver omap_gpio_driver = {
+ .probe = omap_gpio_probe,
++ .remove = omap_gpio_remove,
+ .driver = {
+ .name = "omap_gpio",
+ .pm = &gpio_pm_ops,
+@@ -1615,3 +1629,13 @@ static int __init omap_gpio_drv_reg(void
+ return platform_driver_register(&omap_gpio_driver);
+ }
+ postcore_initcall(omap_gpio_drv_reg);
++
++static void __exit omap_gpio_exit(void)
++{
++ platform_driver_unregister(&omap_gpio_driver);
++}
++module_exit(omap_gpio_exit);
++
++MODULE_DESCRIPTION("omap gpio driver");
++MODULE_ALIAS("platform:gpio-omap");
++MODULE_LICENSE("GPL v2");
+--- a/include/linux/platform_data/gpio-omap.h
++++ b/include/linux/platform_data/gpio-omap.h
+@@ -208,9 +208,17 @@ struct omap_gpio_platform_data {
+ int (*get_context_loss_count)(struct device *dev);
+ };
+
++#if IS_BUILTIN(CONFIG_GPIO_OMAP)
+ extern void omap2_gpio_prepare_for_idle(int off_mode);
+ extern void omap2_gpio_resume_after_idle(void);
+-extern void omap_set_gpio_debounce(int gpio, int enable);
+-extern void omap_set_gpio_debounce_time(int gpio, int enable);
++#else
++static inline void omap2_gpio_prepare_for_idle(int off_mode)
++{
++}
++
++static inline void omap2_gpio_resume_after_idle(void)
++{
++}
++#endif
+
+ #endif
diff --git a/patches/0002-gpio-omap-fix-omap_gpio_free-to-not-clean-up-irq-con.patch b/patches/0002-gpio-omap-fix-omap_gpio_free-to-not-clean-up-irq-con.patch
new file mode 100644
index 00000000000000..ba63133bd910f0
--- /dev/null
+++ b/patches/0002-gpio-omap-fix-omap_gpio_free-to-not-clean-up-irq-con.patch
@@ -0,0 +1,45 @@
+From 463bb14e6fc957a7d5ec9434afed29430debbbfb Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@linaro.org>
+Date: Mon, 13 Jul 2015 17:08:08 +0300
+Subject: [PATCH 02/21] gpio: omap: fix omap_gpio_free to not clean up irq
+ configuration
+
+commit 5f982c70a7c3382d3532ac6d13fdea48ab38b934 upstream
+
+This patch fixes following issue:
+- GPIOn is used as IRQ by some dev, for example PCF8575.INT -> gpio6.11
+- PCFx driver knows nothing about type of IRQ line (GPIO or not)
+ so it doesn't request gpio and just do request_irq()
+- If gpio6.11 will be exported through the sysfs and then un-xeported
+then IRQs from PCFx will not be received any more, because
+IRQ configuration for gpio6.11 will be cleaned up unconditionally
+in omap_gpio_free.
+
+Fix this by removing all GPIO IRQ specific code from omap_gpio_free()
+and also do GPIO clean up (change direction to 'in' and disable debounce)
+only if corresponding GPIO is not used as IRQ too.
+GPIO IRQ will be properly cleaned up by GPIO irqchip code.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -690,8 +690,11 @@ static void omap_gpio_free(struct gpio_c
+
+ spin_lock_irqsave(&bank->lock, flags);
+ bank->mod_usage &= ~(BIT(offset));
++ if (!LINE_USED(bank->irq_usage, offset)) {
++ omap_set_gpio_direction(bank, offset, 1);
++ omap_clear_gpio_debounce(bank, offset);
++ }
+ omap_disable_gpio_module(bank, offset);
+- omap_reset_gpio(bank, offset);
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ /*
diff --git a/patches/0003-gpio-omap-fix-error-handling-in-omap_gpio_irq_type.patch b/patches/0003-gpio-omap-fix-error-handling-in-omap_gpio_irq_type.patch
new file mode 100644
index 00000000000000..b10843843d7747
--- /dev/null
+++ b/patches/0003-gpio-omap-fix-error-handling-in-omap_gpio_irq_type.patch
@@ -0,0 +1,66 @@
+From 290b539f02c79ede61502447d77579f15f6a4984 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@linaro.org>
+Date: Mon, 13 Jul 2015 17:08:09 +0300
+Subject: [PATCH 03/21] gpio: omap: fix error handling in omap_gpio_irq_type
+
+commit 1562e4618ded89b07d145d6985f469fe8be04830 upstream
+
+The GPIO bank will be kept powered in case if input parameters
+are invalid or error occurred in omap_gpio_irq_type.
+
+Hence, fix it by ensuring that GPIO bank will be unpowered
+in case of errors and add additional check of value returned
+from omap_set_gpio_triggering().
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -488,9 +488,6 @@ static int omap_gpio_irq_type(struct irq
+ unsigned long flags;
+ unsigned offset = d->hwirq;
+
+- if (!BANK_USED(bank))
+- pm_runtime_get_sync(bank->dev);
+-
+ if (type & ~IRQ_TYPE_SENSE_MASK)
+ return -EINVAL;
+
+@@ -498,12 +495,18 @@ static int omap_gpio_irq_type(struct irq
+ (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
+ return -EINVAL;
+
++ if (!BANK_USED(bank))
++ pm_runtime_get_sync(bank->dev);
++
+ spin_lock_irqsave(&bank->lock, flags);
+ retval = omap_set_gpio_triggering(bank, offset, type);
++ if (retval)
++ goto error;
+ omap_gpio_init_irq(bank, offset);
+ if (!omap_gpio_is_input(bank, offset)) {
+ spin_unlock_irqrestore(&bank->lock, flags);
+- return -EINVAL;
++ retval = -EINVAL;
++ goto error;
+ }
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+@@ -512,6 +515,11 @@ static int omap_gpio_irq_type(struct irq
+ else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ __irq_set_handler_locked(d->irq, handle_edge_irq);
+
++ return 0;
++
++error:
++ if (!BANK_USED(bank))
++ pm_runtime_put(bank->dev);
+ return retval;
+ }
+
diff --git a/patches/0004-gpio-omap-rework-omap_x_irq_shutdown-to-touch-only-i.patch b/patches/0004-gpio-omap-rework-omap_x_irq_shutdown-to-touch-only-i.patch
new file mode 100644
index 00000000000000..d148a40423ea3d
--- /dev/null
+++ b/patches/0004-gpio-omap-rework-omap_x_irq_shutdown-to-touch-only-i.patch
@@ -0,0 +1,62 @@
+From 05c248c1091e714b6c2b4c8885ebfc3000352303 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@linaro.org>
+Date: Mon, 13 Jul 2015 17:08:10 +0300
+Subject: [PATCH 04/21] gpio: omap: rework omap_x_irq_shutdown to touch only
+ irqs specific registers
+
+commit 6e96c1b5e54889cd11ce29723a5c38ba284c1d91 upstream
+
+The GPIO Chip and GPIO IRQ Chip functionality are essentially orthogonal,
+so GPIO IRQ Chip implementation shouldn't touch GPIO specific
+registers and vise versa.
+
+Hence, rework omap_gpio_irq_shutdown and try to touch only irqs specific
+registers:
+- don't configure GPIO as input (it, actually, should be already configured
+ as input).
+- don't clear debounce configuration if GPIO is still used as GPIO.
+ We need to take in to account here commit c9c55d921115
+ ("gpio/omap: fix off-mode bug: clear debounce settings on free/reset").
+
+Also remove omap_reset_gpio() function as it is not used any more.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -646,15 +646,6 @@ static int omap_set_gpio_wakeup(struct g
+ return 0;
+ }
+
+-static void omap_reset_gpio(struct gpio_bank *bank, unsigned offset)
+-{
+- omap_set_gpio_direction(bank, offset, 1);
+- omap_set_gpio_irqenable(bank, offset, 0);
+- omap_clear_gpio_irqstatus(bank, offset);
+- omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+- omap_clear_gpio_debounce(bank, offset);
+-}
+-
+ /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
+ static int omap_gpio_wake_enable(struct irq_data *d, unsigned int enable)
+ {
+@@ -821,8 +812,12 @@ static void omap_gpio_irq_shutdown(struc
+
+ spin_lock_irqsave(&bank->lock, flags);
+ bank->irq_usage &= ~(BIT(offset));
++ omap_set_gpio_irqenable(bank, offset, 0);
++ omap_clear_gpio_irqstatus(bank, offset);
++ omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
++ if (!LINE_USED(bank->mod_usage, offset))
++ omap_clear_gpio_debounce(bank, offset);
+ omap_disable_gpio_module(bank, offset);
+- omap_reset_gpio(bank, offset);
+ spin_unlock_irqrestore(&bank->lock, flags);
+
+ /*
diff --git a/patches/0005-gpio-omap-rework-omap_gpio_request-to-touch-only-gpi.patch b/patches/0005-gpio-omap-rework-omap_gpio_request-to-touch-only-gpi.patch
new file mode 100644
index 00000000000000..263e701928bdb3
--- /dev/null
+++ b/patches/0005-gpio-omap-rework-omap_gpio_request-to-touch-only-gpi.patch
@@ -0,0 +1,44 @@
+From 17782f9dede8027dc6a26270b2cfec389fe39374 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@linaro.org>
+Date: Mon, 13 Jul 2015 17:08:11 +0300
+Subject: [PATCH 05/21] gpio: omap: rework omap_gpio_request to touch only gpio
+ specific registers
+
+commit c3518172129a60a1f3071e61a8a4ffc50c7b2a68 upstream
+
+The GPIO Chip and GPIO IRQ Chip functionality are essentially orthogonal,
+so GPIO Chip implementation shouldn't touch GPIO IRQ specific registers
+and vise versa.
+
+Hence, rework omap_gpio_request:
+- don't reset GPIO IRQ triggering type to IRQ_TYPE_NONE, because
+ GPIO irqchip should be responsible for that;
+- call directly omap_enable_gpio_module as all needed checks are already
+ present inside it.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -668,14 +668,7 @@ static int omap_gpio_request(struct gpio
+ pm_runtime_get_sync(bank->dev);
+
+ spin_lock_irqsave(&bank->lock, flags);
+- /* Set trigger to none. You need to enable the desired trigger with
+- * request_irq() or set_irq_type(). Only do this if the IRQ line has
+- * not already been requested.
+- */
+- if (!LINE_USED(bank->irq_usage, offset)) {
+- omap_set_gpio_triggering(bank, offset, IRQ_TYPE_NONE);
+- omap_enable_gpio_module(bank, offset);
+- }
++ omap_enable_gpio_module(bank, offset);
+ bank->mod_usage |= BIT(offset);
+ spin_unlock_irqrestore(&bank->lock, flags);
+
diff --git a/patches/0006-gpio-omap-rework-omap_gpio_irq_startup-to-handle-cur.patch b/patches/0006-gpio-omap-rework-omap_gpio_irq_startup-to-handle-cur.patch
new file mode 100644
index 00000000000000..5180d8781157d4
--- /dev/null
+++ b/patches/0006-gpio-omap-rework-omap_gpio_irq_startup-to-handle-cur.patch
@@ -0,0 +1,52 @@
+From 37652e77696d14c5f8b0130441651418e263822d Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@linaro.org>
+Date: Mon, 13 Jul 2015 17:08:12 +0300
+Subject: [PATCH 06/21] gpio: omap: rework omap_gpio_irq_startup to handle
+ current pin state properly
+
+commit 121dcb760426ca67ee90a8b2db6a75eee010f8e3 upstream
+
+The omap_gpio_irq_startup() can be called at time when:
+- corresponding GPIO has been requested already and in this case
+it has to be configured as input already. If not - return with -EINVAL
+and do not try to re-configure it as it could be unsafe.
+- corresponding GPIO is free: reconfigure GPIO as input.
+
+In addition, call omap_enable_gpio_module directly as all needed
+checks are already present inside it.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -790,11 +790,23 @@ static unsigned int omap_gpio_irq_startu
+ pm_runtime_get_sync(bank->dev);
+
+ spin_lock_irqsave(&bank->lock, flags);
+- omap_gpio_init_irq(bank, offset);
++
++ if (!LINE_USED(bank->mod_usage, offset))
++ omap_set_gpio_direction(bank, offset, 1);
++ else if (!omap_gpio_is_input(bank, offset))
++ goto err;
++ omap_enable_gpio_module(bank, offset);
++ bank->irq_usage |= BIT(offset);
++
+ spin_unlock_irqrestore(&bank->lock, flags);
+ omap_gpio_unmask_irq(d);
+
+ return 0;
++err:
++ spin_unlock_irqrestore(&bank->lock, flags);
++ if (!BANK_USED(bank))
++ pm_runtime_put(bank->dev);
++ return -EINVAL;
+ }
+
+ static void omap_gpio_irq_shutdown(struct irq_data *d)
diff --git a/patches/0007-gpio-omap-add-missed-spin_unlock_irqrestore-in-omap_.patch b/patches/0007-gpio-omap-add-missed-spin_unlock_irqrestore-in-omap_.patch
new file mode 100644
index 00000000000000..e014a2f9185783
--- /dev/null
+++ b/patches/0007-gpio-omap-add-missed-spin_unlock_irqrestore-in-omap_.patch
@@ -0,0 +1,37 @@
+From e63638dc9dbb27e4d18dd1101cbe2c153253e343 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@linaro.org>
+Date: Mon, 13 Jul 2015 17:08:13 +0300
+Subject: [PATCH 07/21] gpio: omap: add missed spin_unlock_irqrestore in
+ omap_gpio_irq_type
+
+Add missed spin_unlock_irqrestore in omap_gpio_irq_type when
+omap_set_gpio_triggering() is failed.
+
+It fixes static checker warning:
+
+ drivers/gpio/gpio-omap.c:523 omap_gpio_irq_type()
+ warn: inconsistent returns 'spin_lock:&bank->lock'.
+
+This fixes commit:
+1562e4618ded ('gpio: omap: fix error handling in omap_gpio_irq_type')
+
+Reported-by: Javier Martinez Canillas <javier@dowhile0.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -500,8 +500,10 @@ static int omap_gpio_irq_type(struct irq
+
+ spin_lock_irqsave(&bank->lock, flags);
+ retval = omap_set_gpio_triggering(bank, offset, type);
+- if (retval)
++ if (retval) {
++ spin_unlock_irqrestore(&bank->lock, flags);
+ goto error;
++ }
+ omap_gpio_init_irq(bank, offset);
+ if (!omap_gpio_is_input(bank, offset)) {
+ spin_unlock_irqrestore(&bank->lock, flags);
diff --git a/patches/0008-gpio-omap-prevent-module-from-being-unloaded-while-i.patch b/patches/0008-gpio-omap-prevent-module-from-being-unloaded-while-i.patch
new file mode 100644
index 00000000000000..e20698e51eb1ee
--- /dev/null
+++ b/patches/0008-gpio-omap-prevent-module-from-being-unloaded-while-i.patch
@@ -0,0 +1,32 @@
+From 1e7405ae2fa7c7fefb2bc8dbb8365f99755c74ad Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 13 Jul 2015 17:08:14 +0300
+Subject: [PATCH 08/21] gpio: omap: prevent module from being unloaded while in
+ use
+
+OMAP GPIO driver allowed to be built as loadable module, but it
+doesn't set owner field in GPIO chip structure. As result,
+module_get/put() API is not working and it's possible to unload
+OMAP driver while in use:
+
+ omap_gpio 48051000.gpio: REMOVING GPIOCHIP WITH GPIOS STILL REQUESTED
+
+Hence, add missing configuration.
+
+Cc: Tony Lindgren <tony@atomide.com>
+Fixes: cac089f9026e ('gpio: omap: Allow building as a loadable module')
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1187,6 +1187,7 @@ static int omap_gpio_probe(struct platfo
+ bank->irq = res->start;
+ bank->dev = dev;
+ bank->chip.dev = dev;
++ bank->chip.owner = THIS_MODULE;
+ bank->dbck_flag = pdata->dbck_flag;
+ bank->stride = pdata->bank_stride;
+ bank->width = pdata->bank_width;
diff --git a/patches/0009-ARM-OMAP2-Drop-the-concept-of-certain-power-domains-.patch b/patches/0009-ARM-OMAP2-Drop-the-concept-of-certain-power-domains-.patch
new file mode 100644
index 00000000000000..77e1ccb57a472a
--- /dev/null
+++ b/patches/0009-ARM-OMAP2-Drop-the-concept-of-certain-power-domains-.patch
@@ -0,0 +1,177 @@
+From 70f4293bd36740fd730ab25abe39281d1b312365 Mon Sep 17 00:00:00 2001
+From: Russ Dill <Russ.Dill@ti.com>
+Date: Wed, 5 Aug 2015 15:30:44 +0530
+Subject: [PATCH 09/21] ARM: OMAP2: Drop the concept of certain power domains
+ not being able to lose context.
+
+It isn't much of a win, and with hibernation, everything loses context.
+
+Signed-off-by: Russ Dill <Russ.Dill@ti.com>
+[j-keerthy@ti.com] ported to 4.1
+Signed-off-by: Keerthy <j-keerthy@ti.com>
+---
+ arch/arm/mach-omap2/gpio.c | 1
+ arch/arm/mach-omap2/powerdomain.c | 40 --------------------------------
+ arch/arm/mach-omap2/powerdomain.h | 1
+ drivers/gpio/gpio-omap.c | 36 +++++++++++-----------------
+ include/linux/platform_data/gpio-omap.h | 1
+ 5 files changed, 14 insertions(+), 65 deletions(-)
+
+--- a/arch/arm/mach-omap2/gpio.c
++++ b/arch/arm/mach-omap2/gpio.c
+@@ -130,7 +130,6 @@ static int __init omap2_gpio_dev_init(st
+ }
+
+ pwrdm = omap_hwmod_get_pwrdm(oh);
+- pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
+
+ pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata));
+ kfree(pdata);
+--- a/arch/arm/mach-omap2/powerdomain.c
++++ b/arch/arm/mach-omap2/powerdomain.c
+@@ -1166,43 +1166,3 @@ int pwrdm_get_context_loss_count(struct
+ return count;
+ }
+
+-/**
+- * pwrdm_can_ever_lose_context - can this powerdomain ever lose context?
+- * @pwrdm: struct powerdomain *
+- *
+- * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain
+- * can lose either memory or logic context or if @pwrdm is invalid, or
+- * returns 0 otherwise. This function is not concerned with how the
+- * powerdomain registers are programmed (i.e., to go off or not); it's
+- * concerned with whether it's ever possible for this powerdomain to
+- * go off while some other part of the chip is active. This function
+- * assumes that every powerdomain can go to either ON or INACTIVE.
+- */
+-bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
+-{
+- int i;
+-
+- if (!pwrdm) {
+- pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
+- __func__);
+- return 1;
+- }
+-
+- if (pwrdm->pwrsts & PWRSTS_OFF)
+- return 1;
+-
+- if (pwrdm->pwrsts & PWRSTS_RET) {
+- if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF)
+- return 1;
+-
+- for (i = 0; i < pwrdm->banks; i++)
+- if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF)
+- return 1;
+- }
+-
+- for (i = 0; i < pwrdm->banks; i++)
+- if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF)
+- return 1;
+-
+- return 0;
+-}
+--- a/arch/arm/mach-omap2/powerdomain.h
++++ b/arch/arm/mach-omap2/powerdomain.h
+@@ -244,7 +244,6 @@ int pwrdm_state_switch(struct powerdomai
+ int pwrdm_pre_transition(struct powerdomain *pwrdm);
+ int pwrdm_post_transition(struct powerdomain *pwrdm);
+ int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+-bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
+
+ extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -67,7 +67,7 @@ struct gpio_bank {
+ struct device *dev;
+ bool is_mpuio;
+ bool dbck_flag;
+- bool loses_context;
++
+ bool context_valid;
+ int stride;
+ u32 width;
+@@ -1197,15 +1197,9 @@ static int omap_gpio_probe(struct platfo
+ #ifdef CONFIG_OF_GPIO
+ bank->chip.of_node = of_node_get(node);
+ #endif
+- if (node) {
+- if (!of_property_read_bool(node, "ti,gpio-always-on"))
+- bank->loses_context = true;
+- } else {
+- bank->loses_context = pdata->loses_context;
+-
+- if (bank->loses_context)
+- bank->get_context_loss_count =
+- pdata->get_context_loss_count;
++ if (!node) {
++ bank->get_context_loss_count =
++ pdata->get_context_loss_count;
+ }
+
+ if (bank->regs->set_dataout && bank->regs->clr_dataout)
+@@ -1346,7 +1340,7 @@ static int omap_gpio_runtime_resume(stru
+ * been initialised and so initialise it now. Also initialise
+ * the context loss count.
+ */
+- if (bank->loses_context && !bank->context_valid) {
++ if (!bank->context_valid) {
+ omap_gpio_init_context(bank);
+
+ if (bank->get_context_loss_count)
+@@ -1367,17 +1361,15 @@ static int omap_gpio_runtime_resume(stru
+ writel_relaxed(bank->context.risingdetect,
+ bank->base + bank->regs->risingdetect);
+
+- if (bank->loses_context) {
+- if (!bank->get_context_loss_count) {
++ if (!bank->get_context_loss_count) {
++ omap_gpio_restore_context(bank);
++ } else {
++ c = bank->get_context_loss_count(bank->dev);
++ if (c != bank->context_loss_count) {
+ omap_gpio_restore_context(bank);
+ } else {
+- c = bank->get_context_loss_count(bank->dev);
+- if (c != bank->context_loss_count) {
+- omap_gpio_restore_context(bank);
+- } else {
+- spin_unlock_irqrestore(&bank->lock, flags);
+- return 0;
+- }
++ spin_unlock_irqrestore(&bank->lock, flags);
++ return 0;
+ }
+ }
+
+@@ -1449,7 +1441,7 @@ void omap2_gpio_prepare_for_idle(int pwr
+ struct gpio_bank *bank;
+
+ list_for_each_entry(bank, &omap_gpio_list, node) {
+- if (!BANK_USED(bank) || !bank->loses_context)
++ if (!BANK_USED(bank))
+ continue;
+
+ bank->power_mode = pwr_mode;
+@@ -1463,7 +1455,7 @@ void omap2_gpio_resume_after_idle(void)
+ struct gpio_bank *bank;
+
+ list_for_each_entry(bank, &omap_gpio_list, node) {
+- if (!BANK_USED(bank) || !bank->loses_context)
++ if (!BANK_USED(bank))
+ continue;
+
+ pm_runtime_get_sync(bank->dev);
+--- a/include/linux/platform_data/gpio-omap.h
++++ b/include/linux/platform_data/gpio-omap.h
+@@ -198,7 +198,6 @@ struct omap_gpio_platform_data {
+ int bank_width; /* GPIO bank width */
+ int bank_stride; /* Only needed for omap1 MPUIO */
+ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
+- bool loses_context; /* whether the bank would ever lose context */
+ bool is_mpuio; /* whether the bank is of type MPUIO */
+ u32 non_wakeup_gpios;
+
diff --git a/patches/gpio-omap-use-raw-locks-for-locking.patch b/patches/0010-gpio-omap-use-raw-locks-for-locking.patch
index 48947fe69c8317..85a082b1de33a1 100644
--- a/patches/gpio-omap-use-raw-locks-for-locking.patch
+++ b/patches/0010-gpio-omap-use-raw-locks-for-locking.patch
@@ -1,6 +1,7 @@
+From 8b568939eb4098e3cf10ec0b49f3b082a332667d Mon Sep 17 00:00:00 2001
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Thu, 12 Feb 2015 16:01:13 +0100
-Subject: gpio: omap: use raw locks for locking
+Date: Mon, 31 Aug 2015 18:52:19 +0300
+Subject: [PATCH 10/21] gpio: omap: use raw locks for locking
This patch converts gpio_bank.lock from a spin_lock into a
raw_spin_lock. The call path is to access this lock is always under a
@@ -27,10 +28,13 @@ is not and this is not limited to -RT:
The number of users of gpiod_set_debounce() / gpio_set_debounce()
looks low but still this is not good.
+Acked-by: Javier Martinez Canillas <javier@dowhile0.org>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
- drivers/gpio/gpio-omap.c | 78 +++++++++++++++++++++++------------------------
- 1 file changed, 39 insertions(+), 39 deletions(-)
+ drivers/gpio/gpio-omap.c | 80 +++++++++++++++++++++++------------------------
+ 1 file changed, 40 insertions(+), 40 deletions(-)
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -43,25 +47,30 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct gpio_chip chip;
struct clk *dbck;
u32 mod_usage;
-@@ -498,14 +498,14 @@ static int omap_gpio_irq_type(struct irq
- (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
- return -EINVAL;
+@@ -498,7 +498,7 @@ static int omap_gpio_irq_type(struct irq
+ if (!BANK_USED(bank))
+ pm_runtime_get_sync(bank->dev);
- spin_lock_irqsave(&bank->lock, flags);
+ raw_spin_lock_irqsave(&bank->lock, flags);
retval = omap_set_gpio_triggering(bank, offset, type);
+ if (retval) {
+ spin_unlock_irqrestore(&bank->lock, flags);
+@@ -506,11 +506,11 @@ static int omap_gpio_irq_type(struct irq
+ }
omap_gpio_init_irq(bank, offset);
if (!omap_gpio_is_input(bank, offset)) {
- spin_unlock_irqrestore(&bank->lock, flags);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
- return -EINVAL;
+ retval = -EINVAL;
+ goto error;
}
- spin_unlock_irqrestore(&bank->lock, flags);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
__irq_set_handler_locked(d->irq, handle_level_irq);
-@@ -626,14 +626,14 @@ static int omap_set_gpio_wakeup(struct g
+@@ -636,14 +636,14 @@ static int omap_set_gpio_wakeup(struct g
return -EINVAL;
}
@@ -78,65 +87,79 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -668,7 +668,7 @@ static int omap_gpio_request(struct gpio
+@@ -669,10 +669,10 @@ static int omap_gpio_request(struct gpio
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);
- spin_lock_irqsave(&bank->lock, flags);
+ raw_spin_lock_irqsave(&bank->lock, flags);
- /* Set trigger to none. You need to enable the desired trigger with
- * request_irq() or set_irq_type(). Only do this if the IRQ line has
- * not already been requested.
-@@ -678,7 +678,7 @@ static int omap_gpio_request(struct gpio
- omap_enable_gpio_module(bank, offset);
- }
+ omap_enable_gpio_module(bank, offset);
bank->mod_usage |= BIT(offset);
- spin_unlock_irqrestore(&bank->lock, flags);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
return 0;
}
-@@ -688,11 +688,11 @@ static void omap_gpio_free(struct gpio_c
+@@ -682,14 +682,14 @@ static void omap_gpio_free(struct gpio_c
struct gpio_bank *bank = container_of(chip, struct gpio_bank, chip);
unsigned long flags;
- spin_lock_irqsave(&bank->lock, flags);
+ raw_spin_lock_irqsave(&bank->lock, flags);
bank->mod_usage &= ~(BIT(offset));
+ if (!LINE_USED(bank->irq_usage, offset)) {
+ omap_set_gpio_direction(bank, offset, 1);
+ omap_clear_gpio_debounce(bank, offset);
+ }
omap_disable_gpio_module(bank, offset);
- omap_reset_gpio(bank, offset);
- spin_unlock_irqrestore(&bank->lock, flags);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
/*
* If this is the last gpio to be freed in the bank,
-@@ -794,9 +794,9 @@ static unsigned int omap_gpio_irq_startu
+@@ -791,7 +791,7 @@ static unsigned int omap_gpio_irq_startu
if (!BANK_USED(bank))
pm_runtime_get_sync(bank->dev);
- spin_lock_irqsave(&bank->lock, flags);
+ raw_spin_lock_irqsave(&bank->lock, flags);
- omap_gpio_init_irq(bank, offset);
+
+ if (!LINE_USED(bank->mod_usage, offset))
+ omap_set_gpio_direction(bank, offset, 1);
+@@ -800,12 +800,12 @@ static unsigned int omap_gpio_irq_startu
+ omap_enable_gpio_module(bank, offset);
+ bank->irq_usage |= BIT(offset);
+
- spin_unlock_irqrestore(&bank->lock, flags);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
omap_gpio_unmask_irq(d);
return 0;
-@@ -808,11 +808,11 @@ static void omap_gpio_irq_shutdown(struc
+ err:
+- spin_unlock_irqrestore(&bank->lock, flags);
++ raw_spin_unlock_irqrestore(&bank->lock, flags);
+ if (!BANK_USED(bank))
+ pm_runtime_put(bank->dev);
+ return -EINVAL;
+@@ -817,7 +817,7 @@ static void omap_gpio_irq_shutdown(struc
unsigned long flags;
unsigned offset = d->hwirq;
- spin_lock_irqsave(&bank->lock, flags);
+ raw_spin_lock_irqsave(&bank->lock, flags);
bank->irq_usage &= ~(BIT(offset));
+ omap_set_gpio_irqenable(bank, offset, 0);
+ omap_clear_gpio_irqstatus(bank, offset);
+@@ -825,7 +825,7 @@ static void omap_gpio_irq_shutdown(struc
+ if (!LINE_USED(bank->mod_usage, offset))
+ omap_clear_gpio_debounce(bank, offset);
omap_disable_gpio_module(bank, offset);
- omap_reset_gpio(bank, offset);
- spin_unlock_irqrestore(&bank->lock, flags);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
/*
* If this is the last IRQ to be freed in the bank,
-@@ -836,10 +836,10 @@ static void omap_gpio_mask_irq(struct ir
+@@ -849,10 +849,10 @@ static void omap_gpio_mask_irq(struct ir
unsigned offset = d->hwirq;
unsigned long flags;
@@ -149,7 +172,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
static void omap_gpio_unmask_irq(struct irq_data *d)
-@@ -849,7 +849,7 @@ static void omap_gpio_unmask_irq(struct
+@@ -862,7 +862,7 @@ static void omap_gpio_unmask_irq(struct
u32 trigger = irqd_get_trigger_type(d);
unsigned long flags;
@@ -158,7 +181,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (trigger)
omap_set_gpio_triggering(bank, offset, trigger);
-@@ -861,7 +861,7 @@ static void omap_gpio_unmask_irq(struct
+@@ -874,7 +874,7 @@ static void omap_gpio_unmask_irq(struct
}
omap_set_gpio_irqenable(bank, offset, 1);
@@ -167,7 +190,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/*---------------------------------------------------------------------*/
-@@ -874,9 +874,9 @@ static int omap_mpuio_suspend_noirq(stru
+@@ -887,9 +887,9 @@ static int omap_mpuio_suspend_noirq(stru
OMAP_MPUIO_GPIO_MASKIT / bank->stride;
unsigned long flags;
@@ -179,7 +202,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -889,9 +889,9 @@ static int omap_mpuio_resume_noirq(struc
+@@ -902,9 +902,9 @@ static int omap_mpuio_resume_noirq(struc
OMAP_MPUIO_GPIO_MASKIT / bank->stride;
unsigned long flags;
@@ -191,7 +214,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -937,9 +937,9 @@ static int omap_gpio_get_direction(struc
+@@ -950,9 +950,9 @@ static int omap_gpio_get_direction(struc
bank = container_of(chip, struct gpio_bank, chip);
reg = bank->base + bank->regs->direction;
@@ -203,7 +226,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return dir;
}
-@@ -949,9 +949,9 @@ static int omap_gpio_input(struct gpio_c
+@@ -962,9 +962,9 @@ static int omap_gpio_input(struct gpio_c
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
@@ -215,7 +238,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -973,10 +973,10 @@ static int omap_gpio_output(struct gpio_
+@@ -986,10 +986,10 @@ static int omap_gpio_output(struct gpio_
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
@@ -228,7 +251,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -988,9 +988,9 @@ static int omap_gpio_debounce(struct gpi
+@@ -1001,9 +1001,9 @@ static int omap_gpio_debounce(struct gpi
bank = container_of(chip, struct gpio_bank, chip);
@@ -240,7 +263,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -1001,9 +1001,9 @@ static void omap_gpio_set(struct gpio_ch
+@@ -1014,9 +1014,9 @@ static void omap_gpio_set(struct gpio_ch
unsigned long flags;
bank = container_of(chip, struct gpio_bank, chip);
@@ -252,7 +275,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
/*---------------------------------------------------------------------*/
-@@ -1199,7 +1199,7 @@ static int omap_gpio_probe(struct platfo
+@@ -1207,7 +1207,7 @@ static int omap_gpio_probe(struct platfo
else
bank->set_dataout = omap_set_gpio_dataout_mask;
@@ -261,7 +284,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* Static mapping, never released */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-@@ -1246,7 +1246,7 @@ static int omap_gpio_runtime_suspend(str
+@@ -1265,7 +1265,7 @@ static int omap_gpio_runtime_suspend(str
unsigned long flags;
u32 wake_low, wake_hi;
@@ -270,7 +293,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Only edges can generate a wakeup event to the PRCM.
-@@ -1299,7 +1299,7 @@ static int omap_gpio_runtime_suspend(str
+@@ -1318,7 +1318,7 @@ static int omap_gpio_runtime_suspend(str
bank->get_context_loss_count(bank->dev);
omap_gpio_dbck_disable(bank);
@@ -279,7 +302,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -1314,7 +1314,7 @@ static int omap_gpio_runtime_resume(stru
+@@ -1333,7 +1333,7 @@ static int omap_gpio_runtime_resume(stru
unsigned long flags;
int c;
@@ -288,14 +311,13 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* On the first resume during the probe, the context has not
-@@ -1350,14 +1350,14 @@ static int omap_gpio_runtime_resume(stru
- if (c != bank->context_loss_count) {
- omap_gpio_restore_context(bank);
- } else {
-- spin_unlock_irqrestore(&bank->lock, flags);
-+ raw_spin_unlock_irqrestore(&bank->lock, flags);
- return 0;
- }
+@@ -1368,13 +1368,13 @@ static int omap_gpio_runtime_resume(stru
+ if (c != bank->context_loss_count) {
+ omap_gpio_restore_context(bank);
+ } else {
+- spin_unlock_irqrestore(&bank->lock, flags);
++ raw_spin_unlock_irqrestore(&bank->lock, flags);
+ return 0;
}
}
@@ -305,7 +327,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -1412,7 +1412,7 @@ static int omap_gpio_runtime_resume(stru
+@@ -1429,7 +1429,7 @@ static int omap_gpio_runtime_resume(stru
}
bank->workaround_enabled = false;
diff --git a/patches/0011-gpio-omap-Fix-missing-raw-locks-conversion.patch b/patches/0011-gpio-omap-Fix-missing-raw-locks-conversion.patch
new file mode 100644
index 00000000000000..738ab126a6977a
--- /dev/null
+++ b/patches/0011-gpio-omap-Fix-missing-raw-locks-conversion.patch
@@ -0,0 +1,29 @@
+From 27934f278560ff4a800439cd01a102a65e622801 Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@ingics.com>
+Date: Mon, 31 Aug 2015 18:52:20 +0300
+Subject: [PATCH 11/21] gpio: omap: Fix missing raw locks conversion
+
+Fix below build warning:
+ CC drivers/gpio/gpio-omap.o
+drivers/gpio/gpio-omap.c: In function 'omap_gpio_irq_type':
+drivers/gpio/gpio-omap.c:504:3: warning: passing argument 1 of 'spin_unlock_irqrestore' from incompatible pointer type [enabled by default]
+include/linux/spinlock.h:360:29: note: expected 'struct spinlock_t *' but argument is of type 'struct raw_spinlock_t *'
+
+Fixes: commit 4dbada2be460 ("gpio: omap: use raw locks for locking")
+Signed-off-by: Axel Lin <axel.lin@ingics.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -501,7 +501,7 @@ static int omap_gpio_irq_type(struct irq
+ raw_spin_lock_irqsave(&bank->lock, flags);
+ retval = omap_set_gpio_triggering(bank, offset, type);
+ if (retval) {
+- spin_unlock_irqrestore(&bank->lock, flags);
++ raw_spin_unlock_irqrestore(&bank->lock, flags);
+ goto error;
+ }
+ omap_gpio_init_irq(bank, offset);
diff --git a/patches/0012-gpio-omap-remove-wrong-irq_domain_remove-usage-in-pr.patch b/patches/0012-gpio-omap-remove-wrong-irq_domain_remove-usage-in-pr.patch
new file mode 100644
index 00000000000000..0635c1fdd81887
--- /dev/null
+++ b/patches/0012-gpio-omap-remove-wrong-irq_domain_remove-usage-in-pr.patch
@@ -0,0 +1,27 @@
+From b461fa3a9d07736eb2f8405899e8b85ee962b9c8 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 31 Aug 2015 18:52:21 +0300
+Subject: [PATCH 12/21] gpio: omap: remove wrong irq_domain_remove usage in
+ probe
+
+The bank->chip.irqdomain is uninitialized at the moment when
+irq_domain_remove() is called, so remove this call.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1213,7 +1213,6 @@ static int omap_gpio_probe(struct platfo
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ bank->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(bank->base)) {
+- irq_domain_remove(bank->chip.irqdomain);
+ return PTR_ERR(bank->base);
+ }
+
diff --git a/patches/0013-gpio-omap-switch-to-use-platform_get_irq.patch b/patches/0013-gpio-omap-switch-to-use-platform_get_irq.patch
new file mode 100644
index 00000000000000..81d9cf32dd05ec
--- /dev/null
+++ b/patches/0013-gpio-omap-switch-to-use-platform_get_irq.patch
@@ -0,0 +1,42 @@
+From 65677de608ceb2c9d0f72d4fc0375d18c68b021a Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 31 Aug 2015 18:52:22 +0300
+Subject: [PATCH 13/21] gpio: omap: switch to use platform_get_irq
+
+Switch OMAP GPIO driver to use platform_get_irq(), because
+it is not recommened to use platform_get_resource(pdev, IORESOURCE_IRQ, ..)
+for requesting IRQ resources any more, as they can be not ready yet
+in case of DT-boot.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1178,13 +1178,16 @@ static int omap_gpio_probe(struct platfo
+ irqc->irq_set_wake = omap_gpio_wake_enable,
+ irqc->name = dev_name(&pdev->dev);
+
+- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+- if (unlikely(!res)) {
+- dev_err(dev, "Invalid IRQ resource\n");
+- return -ENODEV;
++ bank->irq = platform_get_irq(pdev, 0);
++ if (bank->irq <= 0) {
++ if (!bank->irq)
++ bank->irq = -ENXIO;
++ if (bank->irq != -EPROBE_DEFER)
++ dev_err(dev,
++ "can't get irq resource ret=%d\n", bank->irq);
++ return bank->irq;
+ }
+
+- bank->irq = res->start;
+ bank->dev = dev;
+ bank->chip.dev = dev;
+ bank->chip.owner = THIS_MODULE;
diff --git a/patches/0014-gpio-omap-fix-omap2_set_gpio_debounce.patch b/patches/0014-gpio-omap-fix-omap2_set_gpio_debounce.patch
new file mode 100644
index 00000000000000..c21c73f5463b0a
--- /dev/null
+++ b/patches/0014-gpio-omap-fix-omap2_set_gpio_debounce.patch
@@ -0,0 +1,95 @@
+From e02e1a208b803111ba52cc321a419378e9ed63bd Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 31 Aug 2015 18:52:23 +0300
+Subject: [PATCH 14/21] gpio: omap: fix omap2_set_gpio_debounce
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+According to TRMs:
+
+Required input line stable =
+ (the value of the GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) × 31,
+where the value of the GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME bit field
+is from 0 to 255.
+
+But now omap2_set_gpio_debounce() will calculate debounce time and
+behave incorrectly in the following cases:
+1) requested debounce time is !0 and <32
+ calculated DEBOUNCETIME = 0x1 == 62 us;
+ expected value of DEBOUNCETIME = 0x0 == 31us
+2) requested debounce time is 0
+ calculated DEBOUNCETIME = 0x1 == 62 us;
+ expected: disable debounce and DEBOUNCETIME = 0x0
+3) requested debounce time is >32 and <63
+ calculated DEBOUNCETIME = 0x0 and debounce will be disabled;
+ expected: enable debounce and DEBOUNCETIME = 0x1 == 62 us
+
+Hence, rework omap2_set_gpio_debounce() to fix above cases:
+1) introduce local variable "enable" and use it to identify
+when debounce need to be enabled or disabled. Disable debounce
+if requested debounce time is 0.
+2) use below formula for debounce time calculation:
+ debounce = (DIV_ROUND_UP(debounce, 31) - 1) & 0xFF;
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -29,6 +29,7 @@
+ #include <linux/platform_data/gpio-omap.h>
+
+ #define OFF_MODE 1
++#define OMAP4_GPIO_DEBOUNCINGTIME_MASK 0xFF
+
+ static LIST_HEAD(omap_gpio_list);
+
+@@ -204,8 +205,9 @@ static inline void omap_gpio_dbck_disabl
+ * @offset: the gpio number on this @bank
+ * @debounce: debounce time to use
+ *
+- * OMAP's debounce time is in 31us steps so we need
+- * to convert and round up to the closest unit.
++ * OMAP's debounce time is in 31us steps
++ * <debounce time> = (GPIO_DEBOUNCINGTIME[7:0].DEBOUNCETIME + 1) x 31
++ * so we need to convert and round up to the closest unit.
+ */
+ static void omap2_set_gpio_debounce(struct gpio_bank *bank, unsigned offset,
+ unsigned debounce)
+@@ -213,16 +215,15 @@ static void omap2_set_gpio_debounce(stru
+ void __iomem *reg;
+ u32 val;
+ u32 l;
++ bool enable = !!debounce;
+
+ if (!bank->dbck_flag)
+ return;
+
+- if (debounce < 32)
+- debounce = 0x01;
+- else if (debounce > 7936)
+- debounce = 0xff;
+- else
+- debounce = (debounce / 0x1f) - 1;
++ if (enable) {
++ debounce = DIV_ROUND_UP(debounce, 31) - 1;
++ debounce &= OMAP4_GPIO_DEBOUNCINGTIME_MASK;
++ }
+
+ l = BIT(offset);
+
+@@ -233,7 +234,7 @@ static void omap2_set_gpio_debounce(stru
+ reg = bank->base + bank->regs->debounce_en;
+ val = readl_relaxed(reg);
+
+- if (debounce)
++ if (enable)
+ val |= l;
+ else
+ val &= ~l;
diff --git a/patches/0015-gpio-omap-protect-regs-access-in-omap_gpio_irq_handl.patch b/patches/0015-gpio-omap-protect-regs-access-in-omap_gpio_irq_handl.patch
new file mode 100644
index 00000000000000..010e99a7530656
--- /dev/null
+++ b/patches/0015-gpio-omap-protect-regs-access-in-omap_gpio_irq_handl.patch
@@ -0,0 +1,63 @@
+From ec29016aefaf6649096224bc9031a303cb21df47 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 31 Aug 2015 18:52:24 +0300
+Subject: [PATCH 15/21] gpio: omap: protect regs access in
+ omap_gpio_irq_handler
+
+The access to HW registers has to be be protected in
+omap_gpio_irq_handler(), as it may race with code executed on
+another CPUs.
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -718,6 +718,7 @@ static void omap_gpio_irq_handler(unsign
+ int unmasked = 0;
+ struct irq_chip *irqchip = irq_desc_get_chip(desc);
+ struct gpio_chip *chip = irq_get_handler_data(irq);
++ unsigned long lock_flags;
+
+ chained_irq_enter(irqchip, desc);
+
+@@ -732,6 +733,8 @@ static void omap_gpio_irq_handler(unsign
+ u32 isr_saved, level_mask = 0;
+ u32 enabled;
+
++ raw_spin_lock_irqsave(&bank->lock, lock_flags);
++
+ enabled = omap_get_gpio_irqbank_mask(bank);
+ isr_saved = isr = readl_relaxed(isr_reg) & enabled;
+
+@@ -745,6 +748,8 @@ static void omap_gpio_irq_handler(unsign
+ omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask);
+ omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask);
+
++ raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
++
+ /* if there is only edge sensitive GPIO pin interrupts
+ configured, we could unmask GPIO bank interrupt immediately */
+ if (!level_mask && !unmasked) {
+@@ -759,6 +764,7 @@ static void omap_gpio_irq_handler(unsign
+ bit = __ffs(isr);
+ isr &= ~(BIT(bit));
+
++ raw_spin_lock_irqsave(&bank->lock, lock_flags);
+ /*
+ * Some chips can't respond to both rising and falling
+ * at the same time. If this irq was requested with
+@@ -769,6 +775,8 @@ static void omap_gpio_irq_handler(unsign
+ if (bank->toggle_mask & (BIT(bit)))
+ omap_toggle_gpio_edge_triggering(bank, bit);
+
++ raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
++
+ generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
+ bit));
+ }
diff --git a/patches/0016-gpio-omap-fix-clk_prepare-unprepare-usage.patch b/patches/0016-gpio-omap-fix-clk_prepare-unprepare-usage.patch
new file mode 100644
index 00000000000000..b7f81f2bb53279
--- /dev/null
+++ b/patches/0016-gpio-omap-fix-clk_prepare-unprepare-usage.patch
@@ -0,0 +1,120 @@
+From 72f110f4546f9fff10bdeeb13f075c6263abe8ff Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 31 Aug 2015 18:52:25 +0300
+Subject: [PATCH 16/21] gpio: omap: fix clk_prepare/unprepare usage
+
+As per CCF documentation (clk.txt) the clk_prepare/unprepare APIs
+are not allowed in atomic context. But now OMAP GPIO driver
+uses them while applying debounce settings and as part
+of PM runtime irqsafe operations:
+
+- omap_gpio_debounce() is holding the lock with IRQs off.
+ + omap2_set_gpio_debounce()
+ + clk_prepare_enable()
+ + clk_prepare() this one might sleep.
+
+- pm_runtime_get_sync() is holding the lock with IRQs off
+ + omap_gpio_runtime_suspend()
+ + raw_spin_lock_irqsave()
+ + omap_gpio_dbck_disable()
+ + clk_disable_unprepare()
+
+Hence, fix it by moeving dbclk prepare/unprepare in OMAP GPIO
+omap_gpio_probe/omap_gpio_remove. Also, while here, ensure that
+debounce functionality is disabled if clk_get() failed,
+because otherwise kernel will carsh in omap2_set_gpio_debounce().
+
+Reported-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+---
+ drivers/gpio/gpio-omap.c | 27 ++++++++++++++++++---------
+ 1 file changed, 18 insertions(+), 9 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -176,7 +176,7 @@ static inline void omap_gpio_rmw(void __
+ static inline void omap_gpio_dbck_enable(struct gpio_bank *bank)
+ {
+ if (bank->dbck_enable_mask && !bank->dbck_enabled) {
+- clk_prepare_enable(bank->dbck);
++ clk_enable(bank->dbck);
+ bank->dbck_enabled = true;
+
+ writel_relaxed(bank->dbck_enable_mask,
+@@ -194,7 +194,7 @@ static inline void omap_gpio_dbck_disabl
+ */
+ writel_relaxed(0, bank->base + bank->regs->debounce_en);
+
+- clk_disable_unprepare(bank->dbck);
++ clk_disable(bank->dbck);
+ bank->dbck_enabled = false;
+ }
+ }
+@@ -227,7 +227,7 @@ static void omap2_set_gpio_debounce(stru
+
+ l = BIT(offset);
+
+- clk_prepare_enable(bank->dbck);
++ clk_enable(bank->dbck);
+ reg = bank->base + bank->regs->debounce;
+ writel_relaxed(debounce, reg);
+
+@@ -241,7 +241,7 @@ static void omap2_set_gpio_debounce(stru
+ bank->dbck_enable_mask = val;
+
+ writel_relaxed(val, reg);
+- clk_disable_unprepare(bank->dbck);
++ clk_disable(bank->dbck);
+ /*
+ * Enable debounce clock per module.
+ * This call is mandatory because in omap_gpio_request() when
+@@ -286,7 +286,7 @@ static void omap_clear_gpio_debounce(str
+ bank->context.debounce = 0;
+ writel_relaxed(bank->context.debounce, bank->base +
+ bank->regs->debounce);
+- clk_disable_unprepare(bank->dbck);
++ clk_disable(bank->dbck);
+ bank->dbck_enabled = false;
+ }
+ }
+@@ -1070,10 +1070,6 @@ static void omap_gpio_mod_init(struct gp
+ /* Initialize interface clk ungated, module enabled */
+ if (bank->regs->ctrl)
+ writel_relaxed(0, base + bank->regs->ctrl);
+-
+- bank->dbck = clk_get(bank->dev, "dbclk");
+- if (IS_ERR(bank->dbck))
+- dev_err(bank->dev, "Could not get gpio dbck\n");
+ }
+
+ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
+@@ -1228,6 +1224,17 @@ static int omap_gpio_probe(struct platfo
+ return PTR_ERR(bank->base);
+ }
+
++ if (bank->dbck_flag) {
++ bank->dbck = devm_clk_get(bank->dev, "dbclk");
++ if (IS_ERR(bank->dbck)) {
++ dev_err(bank->dev,
++ "Could not get gpio dbck. Disable debounce\n");
++ bank->dbck_flag = false;
++ } else {
++ clk_prepare(bank->dbck);
++ }
++ }
++
+ platform_set_drvdata(pdev, bank);
+
+ pm_runtime_enable(bank->dev);
+@@ -1259,6 +1266,8 @@ static int omap_gpio_remove(struct platf
+ list_del(&bank->node);
+ gpiochip_remove(&bank->chip);
+ pm_runtime_disable(bank->dev);
++ if (bank->dbck_flag)
++ clk_unprepare(bank->dbck);
+
+ return 0;
+ }
diff --git a/patches/0017-gpio-omap-Fix-gpiochip_add-handling-for-deferred-pro.patch b/patches/0017-gpio-omap-Fix-gpiochip_add-handling-for-deferred-pro.patch
new file mode 100644
index 00000000000000..b83f8ce541eaba
--- /dev/null
+++ b/patches/0017-gpio-omap-Fix-gpiochip_add-handling-for-deferred-pro.patch
@@ -0,0 +1,44 @@
+From f8ed3ff1efe8be27483c48d06974f8026dd673dd Mon Sep 17 00:00:00 2001
+From: Tony Lindgren <tony@atomide.com>
+Date: Mon, 28 Sep 2015 18:36:12 -0500
+Subject: [PATCH 17/21] gpio: omap: Fix gpiochip_add() handling for deferred
+ probe
+
+commit 5e606abef57a89b3ca25f5d97a953c6cdad7cbac upstream.
+
+Currently we gpio-omap breaks if gpiochip_add() returns -EPROBE_DEFER:
+
+[ 0.570000] gpiochip_add: GPIOs 0..31 (gpio) failed to register
+[ 0.570000] omap_gpio 48310000.gpio: Could not register gpio chip -517
+...
+[ 3.670000] omap_gpio 48310000.gpio: Unbalanced pm_runtime_enable!
+
+Let's fix the issue by adding the missing pm_runtime_put() on error.
+
+Cc: Grygorii Strashko <grygorii.strashko@ti.com>
+Cc: Javier Martinez Canillas <javier@dowhile0.org>
+Cc: Kevin Hilman <khilman@deeprootsystems.com>
+Cc: Santosh Shilimkar <ssantosh@kernel.org>
+Acked-by: Santosh Shilimkar <ssantosh@kernel.org>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1247,8 +1247,11 @@ static int omap_gpio_probe(struct platfo
+ omap_gpio_mod_init(bank);
+
+ ret = omap_gpio_chip_init(bank, irqc);
+- if (ret)
++ if (ret) {
++ pm_runtime_put_sync(bank->dev);
++ pm_runtime_disable(bank->dev);
+ return ret;
++ }
+
+ omap_gpio_show_rev(bank);
+
diff --git a/patches/0018-gpio-omap-Fix-GPIO-numbering-for-deferred-probe.patch b/patches/0018-gpio-omap-Fix-GPIO-numbering-for-deferred-probe.patch
new file mode 100644
index 00000000000000..ec56c6279c8512
--- /dev/null
+++ b/patches/0018-gpio-omap-Fix-GPIO-numbering-for-deferred-probe.patch
@@ -0,0 +1,43 @@
+From 1cda618ade93f4439e17e8159182b035e9c189c9 Mon Sep 17 00:00:00 2001
+From: Tony Lindgren <tony@atomide.com>
+Date: Mon, 28 Sep 2015 18:36:13 -0500
+Subject: [PATCH 18/21] gpio: omap: Fix GPIO numbering for deferred probe
+
+commit 46d4f7c25e1bb59b1663878b843a7ec06eaf5806 upstream.
+
+If gpio-omap probe fails with -EPROBE_DEFER, the GPIO numbering
+keeps increasing. Only increase the gpio count if gpiochip_add()
+was successful as otherwise the numbers will increase for each
+probe attempt.
+
+Cc: Javier Martinez Canillas <javier@dowhile0.org>
+Cc: Kevin Hilman <khilman@deeprootsystems.com>
+Cc: Santosh Shilimkar <ssantosh@kernel.org>
+Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -1098,7 +1098,6 @@ static int omap_gpio_chip_init(struct gp
+ } else {
+ bank->chip.label = "gpio";
+ bank->chip.base = gpio;
+- gpio += bank->width;
+ }
+ bank->chip.ngpio = bank->width;
+
+@@ -1108,6 +1107,9 @@ static int omap_gpio_chip_init(struct gp
+ return ret;
+ }
+
++ if (!bank->is_mpuio)
++ gpio += bank->width;
++
+ #ifdef CONFIG_ARCH_OMAP1
+ /*
+ * REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
diff --git a/patches/0019-gpio-omap-fix-static-checker-warning.patch b/patches/0019-gpio-omap-fix-static-checker-warning.patch
new file mode 100644
index 00000000000000..9d6993921f809c
--- /dev/null
+++ b/patches/0019-gpio-omap-fix-static-checker-warning.patch
@@ -0,0 +1,47 @@
+From 58ac52221b71c6a7e067ebe2f13e595cb99e17b6 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 28 Sep 2015 18:36:14 -0500
+Subject: [PATCH 19/21] gpio: omap: fix static checker warning
+
+This patch fixes below static checker warning by changing
+type of irq field in struct gpio_bank from u16 to int.
+
+drivers/gpio/gpio-omap.c:1191 omap_gpio_probe()
+ warn: assigning (-6) to unsigned variable 'bank->irq'
+
+drivers/gpio/gpio-omap.c
+ 1188 bank->irq = platform_get_irq(pdev, 0);
+ 1189 if (bank->irq <= 0) {
+
+bank->irq is u16.
+
+ 1190 if (!bank->irq)
+ 1191 bank->irq = -ENXIO;
+
+Does not work.
+
+ 1192 if (bank->irq != -EPROBE_DEFER)
+
+Does not work.
+
+ 1193 dev_err(dev,
+ 1194 "can't get irq resource ret=%d\n", bank->irq);
+ 1195 return bank->irq;
+ 1196 }
+
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -51,7 +51,7 @@ struct gpio_regs {
+ struct gpio_bank {
+ struct list_head node;
+ void __iomem *base;
+- u16 irq;
++ int irq;
+ u32 non_wakeup_gpios;
+ u32 enabled_non_wakeup_gpios;
+ struct gpio_regs context;
diff --git a/patches/0020-gpio-omap-move-pm-runtime-in-irq_chip.irq_bus_lock-s.patch b/patches/0020-gpio-omap-move-pm-runtime-in-irq_chip.irq_bus_lock-s.patch
new file mode 100644
index 00000000000000..b11be591c1f0e1
--- /dev/null
+++ b/patches/0020-gpio-omap-move-pm-runtime-in-irq_chip.irq_bus_lock-s.patch
@@ -0,0 +1,133 @@
+From c82f51eada9730a1b1c07c75a036a1a893964e49 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 28 Sep 2015 18:36:15 -0500
+Subject: [PATCH 20/21] gpio: omap: move pm runtime in
+ irq_chip.irq_bus_lock/sync_unlock
+
+The PM runtime API can't be used in atomic contex on -RT even if
+it's configured as irqsafe. As result, below error report can
+be seen when PM runtime API called from IRQ chip's callbacks
+irq_startup/irq_shutdown/irq_set_type, because they are
+protected by RAW spinlock:
+
+BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917
+in_atomic(): 1, irqs_disabled(): 128, pid: 96, name: insmod
+3 locks held by insmod/96:
+ #0: (&dev->mutex){......}, at: [<c04752c8>] __driver_attach+0x54/0xa0
+ #1: (&dev->mutex){......}, at: [<c04752d4>] __driver_attach+0x60/0xa0
+ #2: (class){......}, at: [<c00a408c>] __irq_get_desc_lock+0x60/0xa4
+irq event stamp: 1834
+hardirqs last enabled at (1833): [<c06ab2a4>] _raw_spin_unlock_irqrestore+0x88/0x90
+hardirqs last disabled at (1834): [<c06ab068>] _raw_spin_lock_irqsave+0x2c/0x64
+softirqs last enabled at (0): [<c003d220>] copy_process.part.52+0x410/0x19d8
+softirqs last disabled at (0): [< (null)>] (null)
+Preemption disabled at:[< (null)>] (null)
+
+CPU: 1 PID: 96 Comm: insmod Tainted: G W O 4.1.3-rt3-00618-g57e2387-dirty #184
+Hardware name: Generic DRA74X (Flattened Device Tree)
+[<c00190f4>] (unwind_backtrace) from [<c0014734>] (show_stack+0x20/0x24)
+[<c0014734>] (show_stack) from [<c06a62ec>] (dump_stack+0x88/0xdc)
+[<c06a62ec>] (dump_stack) from [<c006ca44>] (___might_sleep+0x198/0x2a8)
+[<c006ca44>] (___might_sleep) from [<c06ab6d4>] (rt_spin_lock+0x30/0x70)
+[<c06ab6d4>] (rt_spin_lock) from [<c04815ac>] (__pm_runtime_resume+0x68/0xa4)
+[<c04815ac>] (__pm_runtime_resume) from [<c04123f4>] (omap_gpio_irq_type+0x188/0x1d8)
+[<c04123f4>] (omap_gpio_irq_type) from [<c00a64e4>] (__irq_set_trigger+0x68/0x130)
+[<c00a64e4>] (__irq_set_trigger) from [<c00a7bc4>] (irq_set_irq_type+0x44/0x6c)
+[<c00a7bc4>] (irq_set_irq_type) from [<c00abbf8>] (irq_create_of_mapping+0x120/0x174)
+[<c00abbf8>] (irq_create_of_mapping) from [<c0577b74>] (of_irq_get+0x48/0x58)
+[<c0577b74>] (of_irq_get) from [<c0540a14>] (i2c_device_probe+0x54/0x15c)
+[<c0540a14>] (i2c_device_probe) from [<c04750dc>] (driver_probe_device+0x184/0x2c8)
+[<c04750dc>] (driver_probe_device) from [<c0475310>] (__driver_attach+0x9c/0xa0)
+[<c0475310>] (__driver_attach) from [<c0473238>] (bus_for_each_dev+0x7c/0xb0)
+[<c0473238>] (bus_for_each_dev) from [<c0474af4>] (driver_attach+0x28/0x30)
+[<c0474af4>] (driver_attach) from [<c0474760>] (bus_add_driver+0x154/0x200)
+[<c0474760>] (bus_add_driver) from [<c0476348>] (driver_register+0x88/0x108)
+[<c0476348>] (driver_register) from [<c0541600>] (i2c_register_driver+0x3c/0x90)
+[<c0541600>] (i2c_register_driver) from [<bf003018>] (pcf857x_init+0x18/0x24 [gpio_pcf857x])
+[<bf003018>] (pcf857x_init [gpio_pcf857x]) from [<c000998c>] (do_one_initcall+0x128/0x1e8)
+[<c000998c>] (do_one_initcall) from [<c06a4220>] (do_init_module+0x6c/0x1bc)
+[<c06a4220>] (do_init_module) from [<c00dd0c8>] (load_module+0x18e8/0x21c4)
+[<c00dd0c8>] (load_module) from [<c00ddaa0>] (SyS_init_module+0xfc/0x158)
+[<c00ddaa0>] (SyS_init_module) from [<c000ff40>] (ret_fast_syscall+0x0/0x54)
+
+The IRQ chip interface defines only two callbacks which are executed in
+non-atomic contex - irq_bus_lock/irq_bus_sync_unlock, so lets move
+PM runtime calls there.
+
+Cc: <linux-rt-users@vger.kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Tested-by: Austin Schuh <austin@peloton-tech.com>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -496,9 +496,6 @@ static int omap_gpio_irq_type(struct irq
+ (type & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH)))
+ return -EINVAL;
+
+- if (!BANK_USED(bank))
+- pm_runtime_get_sync(bank->dev);
+-
+ raw_spin_lock_irqsave(&bank->lock, flags);
+ retval = omap_set_gpio_triggering(bank, offset, type);
+ if (retval) {
+@@ -521,8 +518,6 @@ static int omap_gpio_irq_type(struct irq
+ return 0;
+
+ error:
+- if (!BANK_USED(bank))
+- pm_runtime_put(bank->dev);
+ return retval;
+ }
+
+@@ -797,9 +792,6 @@ static unsigned int omap_gpio_irq_startu
+ unsigned long flags;
+ unsigned offset = d->hwirq;
+
+- if (!BANK_USED(bank))
+- pm_runtime_get_sync(bank->dev);
+-
+ raw_spin_lock_irqsave(&bank->lock, flags);
+
+ if (!LINE_USED(bank->mod_usage, offset))
+@@ -815,8 +807,6 @@ static unsigned int omap_gpio_irq_startu
+ return 0;
+ err:
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
+- if (!BANK_USED(bank))
+- pm_runtime_put(bank->dev);
+ return -EINVAL;
+ }
+
+@@ -835,6 +825,19 @@ static void omap_gpio_irq_shutdown(struc
+ omap_clear_gpio_debounce(bank, offset);
+ omap_disable_gpio_module(bank, offset);
+ raw_spin_unlock_irqrestore(&bank->lock, flags);
++}
++
++static void omap_gpio_irq_bus_lock(struct irq_data *data)
++{
++ struct gpio_bank *bank = omap_irq_data_get_bank(data);
++
++ if (!BANK_USED(bank))
++ pm_runtime_get_sync(bank->dev);
++}
++
++static void gpio_irq_bus_sync_unlock(struct irq_data *data)
++{
++ struct gpio_bank *bank = omap_irq_data_get_bank(data);
+
+ /*
+ * If this is the last IRQ to be freed in the bank,
+@@ -1183,6 +1186,8 @@ static int omap_gpio_probe(struct platfo
+ irqc->irq_unmask = omap_gpio_unmask_irq,
+ irqc->irq_set_type = omap_gpio_irq_type,
+ irqc->irq_set_wake = omap_gpio_wake_enable,
++ irqc->irq_bus_lock = omap_gpio_irq_bus_lock,
++ irqc->irq_bus_sync_unlock = gpio_irq_bus_sync_unlock,
+ irqc->name = dev_name(&pdev->dev);
+
+ bank->irq = platform_get_irq(pdev, 0);
diff --git a/patches/0021-gpio-omap-convert-to-use-generic-irq-handler.patch b/patches/0021-gpio-omap-convert-to-use-generic-irq-handler.patch
new file mode 100644
index 00000000000000..c30e6fbc6440e2
--- /dev/null
+++ b/patches/0021-gpio-omap-convert-to-use-generic-irq-handler.patch
@@ -0,0 +1,184 @@
+From a53b71a3646765698f8280c1889412575ea1d7f5 Mon Sep 17 00:00:00 2001
+From: Grygorii Strashko <grygorii.strashko@ti.com>
+Date: Mon, 28 Sep 2015 18:36:16 -0500
+Subject: [PATCH 21/21] gpio: omap: convert to use generic irq handler
+
+This patch converts TI OMAP GPIO driver to use generic irq handler
+instead of chained IRQ handler. This way OMAP GPIO driver will be
+compatible with RT kernel where it will be forced thread IRQ handler
+while in non-RT kernel it still will be executed in HW IRQ context.
+As part of this change the IRQ wakeup configuration is applied to
+GPIO Bank IRQ as it now will be under control of IRQ PM Core during
+suspend.
+
+There are also additional benefits:
+ - on-RT kernel there will be no complains any more about PM runtime usage
+ in atomic context "BUG: sleeping function called from invalid context";
+ - GPIO bank IRQs will appear in /proc/interrupts and its usage statistic
+ will be visible;
+ - GPIO bank IRQs could be configured through IRQ proc_fs interface and,
+ as result, could be a part of IRQ balancing process if needed;
+ - GPIO bank IRQs will be under control of IRQ PM Core during
+ suspend to RAM.
+
+Disadvantage:
+ - additional runtime overhed as call chain till
+ omap_gpio_irq_handler() will be longer now
+ - necessity to use wa_lock in omap_gpio_irq_handler() to W/A warning
+ in handle_irq_event_percpu()
+ WARNING: CPU: 1 PID: 35 at kernel/irq/handle.c:149 handle_irq_event_percpu+0x51c/0x638()
+
+This patch doesn't fully follows recommendations provided by Sebastian
+Andrzej Siewior [1], because It's required to go through and check all
+GPIO IRQ pin states as fast as possible and pass control to handle_level_irq
+or handle_edge_irq. handle_level_irq or handle_edge_irq will perform actions
+specific for IRQ triggering type and wakeup corresponding registered
+threaded IRQ handler (at least it's expected to be threaded).
+IRQs can be lost if handle_nested_irq() will be used, because excecution
+time of some pin specific GPIO IRQ handler can be very significant and
+require accessing ext. devices (I2C).
+
+Idea of such kind reworking was also discussed in [2].
+
+[1] http://www.spinics.net/lists/linux-omap/msg120665.html
+[2] http://www.spinics.net/lists/linux-omap/msg119516.html
+
+Cc: <linux-rt-users@vger.kernel.org>
+Tested-by: Tony Lindgren <tony@atomide.com>
+Tested-by: Austin Schuh <austin@peloton-tech.com>
+Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
+---
+ drivers/gpio/gpio-omap.c | 55 +++++++++++++++++++++++------------------------
+ 1 file changed, 27 insertions(+), 28 deletions(-)
+
+--- a/drivers/gpio/gpio-omap.c
++++ b/drivers/gpio/gpio-omap.c
+@@ -59,6 +59,7 @@ struct gpio_bank {
+ u32 level_mask;
+ u32 toggle_mask;
+ raw_spinlock_t lock;
++ raw_spinlock_t wa_lock;
+ struct gpio_chip chip;
+ struct clk *dbck;
+ u32 mod_usage;
+@@ -649,8 +650,13 @@ static int omap_gpio_wake_enable(struct
+ {
+ struct gpio_bank *bank = omap_irq_data_get_bank(d);
+ unsigned offset = d->hwirq;
++ int ret;
++
++ ret = omap_set_gpio_wakeup(bank, offset, enable);
++ if (!ret)
++ ret = irq_set_irq_wake(bank->irq, enable);
+
+- return omap_set_gpio_wakeup(bank, offset, enable);
++ return ret;
+ }
+
+ static int omap_gpio_request(struct gpio_chip *chip, unsigned offset)
+@@ -704,26 +710,21 @@ static void omap_gpio_free(struct gpio_c
+ * line's interrupt handler has been run, we may miss some nested
+ * interrupts.
+ */
+-static void omap_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
++static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank)
+ {
+ void __iomem *isr_reg = NULL;
+ u32 isr;
+ unsigned int bit;
+- struct gpio_bank *bank;
+- int unmasked = 0;
+- struct irq_chip *irqchip = irq_desc_get_chip(desc);
+- struct gpio_chip *chip = irq_get_handler_data(irq);
++ struct gpio_bank *bank = gpiobank;
++ unsigned long wa_lock_flags;
+ unsigned long lock_flags;
+
+- chained_irq_enter(irqchip, desc);
+-
+- bank = container_of(chip, struct gpio_bank, chip);
+ isr_reg = bank->base + bank->regs->irqstatus;
+- pm_runtime_get_sync(bank->dev);
+-
+ if (WARN_ON(!isr_reg))
+ goto exit;
+
++ pm_runtime_get_sync(bank->dev);
++
+ while (1) {
+ u32 isr_saved, level_mask = 0;
+ u32 enabled;
+@@ -745,13 +746,6 @@ static void omap_gpio_irq_handler(unsign
+
+ raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
+- /* if there is only edge sensitive GPIO pin interrupts
+- configured, we could unmask GPIO bank interrupt immediately */
+- if (!level_mask && !unmasked) {
+- unmasked = 1;
+- chained_irq_exit(irqchip, desc);
+- }
+-
+ if (!isr)
+ break;
+
+@@ -772,18 +766,18 @@ static void omap_gpio_irq_handler(unsign
+
+ raw_spin_unlock_irqrestore(&bank->lock, lock_flags);
+
++ raw_spin_lock_irqsave(&bank->wa_lock, wa_lock_flags);
++
+ generic_handle_irq(irq_find_mapping(bank->chip.irqdomain,
+ bit));
++
++ raw_spin_unlock_irqrestore(&bank->wa_lock,
++ wa_lock_flags);
+ }
+ }
+- /* if bank has any level sensitive GPIO pin interrupt
+- configured, we must unmask the bank interrupt only after
+- handler(s) are executed in order to avoid spurious bank
+- interrupt */
+ exit:
+- if (!unmasked)
+- chained_irq_exit(irqchip, desc);
+ pm_runtime_put(bank->dev);
++ return IRQ_HANDLED;
+ }
+
+ static unsigned int omap_gpio_irq_startup(struct irq_data *d)
+@@ -1135,7 +1129,7 @@ static int omap_gpio_chip_init(struct gp
+ }
+
+ ret = gpiochip_irqchip_add(&bank->chip, irqc,
+- irq_base, omap_gpio_irq_handler,
++ irq_base, handle_bad_irq,
+ IRQ_TYPE_NONE);
+
+ if (ret) {
+@@ -1144,10 +1138,14 @@ static int omap_gpio_chip_init(struct gp
+ return -ENODEV;
+ }
+
+- gpiochip_set_chained_irqchip(&bank->chip, irqc,
+- bank->irq, omap_gpio_irq_handler);
++ gpiochip_set_chained_irqchip(&bank->chip, irqc, bank->irq, NULL);
+
+- return 0;
++ ret = devm_request_irq(bank->dev, bank->irq, omap_gpio_irq_handler,
++ 0, dev_name(bank->dev), bank);
++ if (ret)
++ gpiochip_remove(&bank->chip);
++
++ return ret;
+ }
+
+ static const struct of_device_id omap_gpio_match[];
+@@ -1223,6 +1221,7 @@ static int omap_gpio_probe(struct platfo
+ bank->set_dataout = omap_set_gpio_dataout_mask;
+
+ raw_spin_lock_init(&bank->lock);
++ raw_spin_lock_init(&bank->wa_lock);
+
+ /* Static mapping, never released */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/patches/KVM-lapic-mark-LAPIC-timer-handler-as-irqsafe.patch b/patches/KVM-lapic-mark-LAPIC-timer-handler-as-irqsafe.patch
index 875dc538bc9a0a..7440ee2bf35472 100644
--- a/patches/KVM-lapic-mark-LAPIC-timer-handler-as-irqsafe.patch
+++ b/patches/KVM-lapic-mark-LAPIC-timer-handler-as-irqsafe.patch
@@ -18,7 +18,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
-@@ -1167,8 +1167,36 @@ void wait_lapic_expire(struct kvm_vcpu *
+@@ -1169,8 +1169,36 @@ void wait_lapic_expire(struct kvm_vcpu *
__delay(tsc_deadline - guest_tsc);
}
@@ -55,7 +55,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
ktime_t now;
atomic_set(&apic->lapic_timer.pending, 0);
-@@ -1199,9 +1227,11 @@ static void start_apic_timer(struct kvm_
+@@ -1201,9 +1229,11 @@ static void start_apic_timer(struct kvm_
}
}
@@ -68,7 +68,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
apic_debug("%s: bus cycle is %" PRId64 "ns, now 0x%016"
PRIx64 ", "
-@@ -1233,8 +1263,10 @@ static void start_apic_timer(struct kvm_
+@@ -1235,8 +1265,10 @@ static void start_apic_timer(struct kvm_
do_div(ns, this_tsc_khz);
expire = ktime_add_ns(now, ns);
expire = ktime_sub_ns(expire, lapic_timer_advance_ns);
@@ -80,7 +80,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
} else
apic_timer_expired(apic);
-@@ -1707,6 +1739,7 @@ int kvm_create_lapic(struct kvm_vcpu *vc
+@@ -1709,6 +1741,7 @@ int kvm_create_lapic(struct kvm_vcpu *vc
hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
HRTIMER_MODE_ABS);
apic->lapic_timer.timer.function = apic_timer_fn;
@@ -88,7 +88,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* APIC is created enabled. This will prevent kvm_lapic_set_base from
-@@ -1834,7 +1867,8 @@ void __kvm_migrate_apic_timer(struct kvm
+@@ -1836,7 +1869,8 @@ void __kvm_migrate_apic_timer(struct kvm
timer = &vcpu->arch.apic->lapic_timer.timer;
if (hrtimer_cancel(timer))
diff --git a/patches/KVM-use-simple-waitqueue-for-vcpu-wq.patch b/patches/KVM-use-simple-waitqueue-for-vcpu-wq.patch
index 9ec1315628bcef..16160641401fa5 100644
--- a/patches/KVM-use-simple-waitqueue-for-vcpu-wq.patch
+++ b/patches/KVM-use-simple-waitqueue-for-vcpu-wq.patch
@@ -224,7 +224,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
-@@ -1104,7 +1104,7 @@ static void apic_update_lvtt(struct kvm_
+@@ -1106,7 +1106,7 @@ static void apic_update_lvtt(struct kvm_
static void apic_timer_expired(struct kvm_lapic *apic)
{
struct kvm_vcpu *vcpu = apic->vcpu;
@@ -233,7 +233,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct kvm_timer *ktimer = &apic->lapic_timer;
if (atomic_read(&apic->lapic_timer.pending))
-@@ -1113,8 +1113,8 @@ static void apic_timer_expired(struct kv
+@@ -1115,8 +1115,8 @@ static void apic_timer_expired(struct kv
atomic_inc(&apic->lapic_timer.pending);
kvm_set_pending_timer(vcpu);
@@ -255,7 +255,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct pid *pid;
int sigset_active;
sigset_t sigset;
-@@ -690,7 +690,7 @@ static inline bool kvm_arch_has_noncoher
+@@ -701,7 +701,7 @@ static inline bool kvm_arch_has_noncoher
}
#endif
diff --git a/patches/Revert-x86-Do-not-disable-preemption-in-int3-on-32bi.patch b/patches/Revert-x86-Do-not-disable-preemption-in-int3-on-32bi.patch
new file mode 100644
index 00000000000000..a6cbd45a0c0eed
--- /dev/null
+++ b/patches/Revert-x86-Do-not-disable-preemption-in-int3-on-32bi.patch
@@ -0,0 +1,90 @@
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Tue, 22 Dec 2015 12:17:39 +0100
+Subject: Revert "x86: Do not disable preemption in int3 on 32bit"
+
+Since commit 959274753857 ("x86, traps: Track entry into and exit from
+IST context") we always disable preemption. Which means the original
+patch is no longer usefull.
+The patch mentioned is part of v4.0-rc1+
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/x86/kernel/traps.c | 28 +++++++---------------------
+ 1 file changed, 7 insertions(+), 21 deletions(-)
+
+--- a/arch/x86/kernel/traps.c
++++ b/arch/x86/kernel/traps.c
+@@ -88,21 +88,9 @@ static inline void conditional_sti(struc
+ local_irq_enable();
+ }
+
+-static inline void conditional_sti_ist(struct pt_regs *regs)
++static inline void preempt_conditional_sti(struct pt_regs *regs)
+ {
+-#ifdef CONFIG_X86_64
+- /*
+- * X86_64 uses a per CPU stack on the IST for certain traps
+- * like int3. The task can not be preempted when using one
+- * of these stacks, thus preemption must be disabled, otherwise
+- * the stack can be corrupted if the task is scheduled out,
+- * and another task comes in and uses this stack.
+- *
+- * On x86_32 the task keeps its own stack and it is OK if the
+- * task schedules out.
+- */
+ preempt_count_inc();
+-#endif
+ if (regs->flags & X86_EFLAGS_IF)
+ local_irq_enable();
+ }
+@@ -113,13 +101,11 @@ static inline void conditional_cli(struc
+ local_irq_disable();
+ }
+
+-static inline void conditional_cli_ist(struct pt_regs *regs)
++static inline void preempt_conditional_cli(struct pt_regs *regs)
+ {
+ if (regs->flags & X86_EFLAGS_IF)
+ local_irq_disable();
+-#ifdef CONFIG_X86_64
+ preempt_count_dec();
+-#endif
+ }
+
+ enum ctx_state ist_enter(struct pt_regs *regs)
+@@ -550,9 +536,9 @@ dotraplinkage void notrace do_int3(struc
+ * as we may switch to the interrupt stack.
+ */
+ debug_stack_usage_inc();
+- conditional_sti_ist(regs);
++ preempt_conditional_sti(regs);
+ do_trap(X86_TRAP_BP, SIGTRAP, "int3", regs, error_code, NULL);
+- conditional_cli_ist(regs);
++ preempt_conditional_cli(regs);
+ debug_stack_usage_dec();
+ exit:
+ ist_exit(regs, prev_state);
+@@ -682,12 +668,12 @@ dotraplinkage void do_debug(struct pt_re
+ debug_stack_usage_inc();
+
+ /* It's safe to allow irq's after DR6 has been saved */
+- conditional_sti_ist(regs);
++ preempt_conditional_sti(regs);
+
+ if (v8086_mode(regs)) {
+ handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code,
+ X86_TRAP_DB);
+- conditional_cli_ist(regs);
++ preempt_conditional_cli(regs);
+ debug_stack_usage_dec();
+ goto exit;
+ }
+@@ -707,7 +693,7 @@ dotraplinkage void do_debug(struct pt_re
+ si_code = get_si_code(tsk->thread.debugreg6);
+ if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS) || user_icebp)
+ send_sigtrap(tsk, regs, error_code, si_code);
+- conditional_cli_ist(regs);
++ preempt_conditional_cli(regs);
+ debug_stack_usage_dec();
+
+ exit:
diff --git a/patches/irqwork-Move-irq-safe-work-to-irq-context.patch b/patches/irqwork-Move-irq-safe-work-to-irq-context.patch
index 99c5a41041c6a9..57a542ac3562de 100644
--- a/patches/irqwork-Move-irq-safe-work-to-irq-context.patch
+++ b/patches/irqwork-Move-irq-safe-work-to-irq-context.patch
@@ -20,10 +20,8 @@ Cc: stable-rt@vger.kernel.org
kernel/time/timer.c | 6 ++----
3 files changed, 17 insertions(+), 4 deletions(-)
-Index: linux-rt-devel/include/linux/irq_work.h
-===================================================================
---- linux-rt-devel.orig/include/linux/irq_work.h
-+++ linux-rt-devel/include/linux/irq_work.h
+--- a/include/linux/irq_work.h
++++ b/include/linux/irq_work.h
@@ -52,4 +52,10 @@ static inline bool irq_work_needs_cpu(vo
static inline void irq_work_run(void) { }
#endif
@@ -35,10 +33,8 @@ Index: linux-rt-devel/include/linux/irq_work.h
+#endif
+
#endif /* _LINUX_IRQ_WORK_H */
-Index: linux-rt-devel/kernel/irq_work.c
-===================================================================
---- linux-rt-devel.orig/kernel/irq_work.c
-+++ linux-rt-devel/kernel/irq_work.c
+--- a/kernel/irq_work.c
++++ b/kernel/irq_work.c
@@ -200,8 +200,17 @@ void irq_work_tick(void)
if (!llist_empty(raised) && !arch_irq_work_has_interrupt())
@@ -57,10 +53,8 @@ Index: linux-rt-devel/kernel/irq_work.c
/*
* Synchronize against the irq_work @entry, ensures the entry is not
-Index: linux-rt-devel/kernel/time/timer.c
-===================================================================
---- linux-rt-devel.orig/kernel/time/timer.c
-+++ linux-rt-devel/kernel/time/timer.c
+--- a/kernel/time/timer.c
++++ b/kernel/time/timer.c
@@ -1455,7 +1455,7 @@ void update_process_times(int user_tick)
scheduler_tick();
run_local_timers();
diff --git a/patches/localversion.patch b/patches/localversion.patch
index dee63a20fa3bba..a3b81e783166e2 100644
--- a/patches/localversion.patch
+++ b/patches/localversion.patch
@@ -1,4 +1,4 @@
-Subject: v4.1.15-rt16
+Subject: v4.1.15-rt17
From: Thomas Gleixner <tglx@linutronix.de>
Date: Fri, 08 Jul 2011 20:25:16 +0200
@@ -10,4 +10,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- /dev/null
+++ b/localversion-rt
@@ -0,0 +1 @@
-+-rt16
++-rt17
diff --git a/patches/rtmutex-Use-chainwalking-control-enum.patch b/patches/rtmutex-Use-chainwalking-control-enum.patch
new file mode 100644
index 00000000000000..2ecfc54b064aba
--- /dev/null
+++ b/patches/rtmutex-Use-chainwalking-control-enum.patch
@@ -0,0 +1,28 @@
+From 13f032043086194982ac91c68124adae545f5627 Mon Sep 17 00:00:00 2001
+From: "bmouring@ni.com" <bmouring@ni.com>
+Date: Tue, 15 Dec 2015 17:07:30 -0600
+Subject: [PATCH] rtmutex: Use chainwalking control enum
+
+In 8930ed80 (rtmutex: Cleanup deadlock detector debug logic),
+chainwalking control enums were introduced to limit the deadlock
+detection logic. One of the calls to task_blocks_on_rt_mutex was
+missed when converting to use the enums.
+
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Brad Mouring <brad.mouring@ni.com>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/locking/rtmutex.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/kernel/locking/rtmutex.c
++++ b/kernel/locking/rtmutex.c
+@@ -1007,7 +1007,7 @@ static void noinline __sched rt_spin_lo
+ __set_current_state_no_track(TASK_UNINTERRUPTIBLE);
+ pi_unlock(&self->pi_lock);
+
+- ret = task_blocks_on_rt_mutex(lock, &waiter, self, 0);
++ ret = task_blocks_on_rt_mutex(lock, &waiter, self, RT_MUTEX_MIN_CHAINWALK);
+ BUG_ON(ret);
+
+ for (;;) {
diff --git a/patches/series b/patches/series
index c9cf63a135c1a4..f90b2efe106988 100644
--- a/patches/series
+++ b/patches/series
@@ -89,7 +89,27 @@ kernel-SRCU-provide-a-static-initializer.patch
############################################################
# Stuff which should go upstream ASAP
############################################################
-gpio-omap-use-raw-locks-for-locking.patch
+0001-gpio-omap-Allow-building-as-a-loadable-module.patch
+0002-gpio-omap-fix-omap_gpio_free-to-not-clean-up-irq-con.patch
+0003-gpio-omap-fix-error-handling-in-omap_gpio_irq_type.patch
+0004-gpio-omap-rework-omap_x_irq_shutdown-to-touch-only-i.patch
+0005-gpio-omap-rework-omap_gpio_request-to-touch-only-gpi.patch
+0006-gpio-omap-rework-omap_gpio_irq_startup-to-handle-cur.patch
+0007-gpio-omap-add-missed-spin_unlock_irqrestore-in-omap_.patch
+0008-gpio-omap-prevent-module-from-being-unloaded-while-i.patch
+0009-ARM-OMAP2-Drop-the-concept-of-certain-power-domains-.patch
+0010-gpio-omap-use-raw-locks-for-locking.patch
+0011-gpio-omap-Fix-missing-raw-locks-conversion.patch
+0012-gpio-omap-remove-wrong-irq_domain_remove-usage-in-pr.patch
+0013-gpio-omap-switch-to-use-platform_get_irq.patch
+0014-gpio-omap-fix-omap2_set_gpio_debounce.patch
+0015-gpio-omap-protect-regs-access-in-omap_gpio_irq_handl.patch
+0016-gpio-omap-fix-clk_prepare-unprepare-usage.patch
+0017-gpio-omap-Fix-gpiochip_add-handling-for-deferred-pro.patch
+0018-gpio-omap-Fix-GPIO-numbering-for-deferred-probe.patch
+0019-gpio-omap-fix-static-checker-warning.patch
+0020-gpio-omap-move-pm-runtime-in-irq_chip.irq_bus_lock-s.patch
+0021-gpio-omap-convert-to-use-generic-irq-handler.patch
# SCHED BLOCK/WQ
block-shorten-interrupt-disabled-regions.patch
@@ -141,6 +161,7 @@ net-sched-dev_deactivate_many-use-msleep-1-instead-o.patch
# X86
x86-io-apic-migra-no-unmask.patch
fix-rt-int3-x86_32-3.2-rt.patch
+Revert-x86-Do-not-disable-preemption-in-int3-on-32bi.patch
# RCU
@@ -210,6 +231,7 @@ mm-workingset-do-not-protect-workingset_shadow_nodes.patch
# Sigh
signal-fix-up-rcu-wreckage.patch
oleg-signal-rt-fix.patch
+x86-signal-delay-calling-signals-on-32bit.patch
# ANNOTATE BUG/WARNON
net-wireless-warn-nort.patch
@@ -337,6 +359,7 @@ rtmutex-lock-killable.patch
spinlock-types-separate-raw.patch
rtmutex-avoid-include-hell.patch
rt-add-rt-locks.patch
+rtmutex-Use-chainwalking-control-enum.patch
rtmutex-add-a-first-shot-of-ww_mutex.patch
ptrace-fix-ptrace-vs-tasklist_lock-race.patch
diff --git a/patches/x86-signal-delay-calling-signals-on-32bit.patch b/patches/x86-signal-delay-calling-signals-on-32bit.patch
new file mode 100644
index 00000000000000..bd37c47fc92b90
--- /dev/null
+++ b/patches/x86-signal-delay-calling-signals-on-32bit.patch
@@ -0,0 +1,42 @@
+From: Yang Shi <yang.shi@linaro.org>
+Date: Thu, 10 Dec 2015 10:58:51 -0800
+Subject: x86/signal: delay calling signals on 32bit
+
+When running some ptrace single step tests on x86-32 machine, the below problem
+is triggered:
+
+BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:917
+in_atomic(): 1, irqs_disabled(): 0, pid: 1041, name: dummy2
+Preemption disabled at:[<c100326f>] do_debug+0x1f/0x1a0
+
+CPU: 10 PID: 1041 Comm: dummy2 Tainted: G W 4.1.13-rt13 #1
+Call Trace:
+ [<c1aa8306>] dump_stack+0x46/0x5c
+ [<c1080517>] ___might_sleep+0x137/0x220
+ [<c1ab0eff>] rt_spin_lock+0x1f/0x80
+ [<c1064b5a>] do_force_sig_info+0x2a/0xc0
+ [<c106567d>] force_sig_info+0xd/0x10
+ [<c1010cff>] send_sigtrap+0x6f/0x80
+ [<c10033b1>] do_debug+0x161/0x1a0
+ [<c1ab2921>] debug_stack_correct+0x2e/0x35
+
+This happens since 959274753857 ("x86, traps: Track entry into and exit
+from IST context") which was merged in v4.1-rc1.
+
+Signed-off-by: Yang Shi <yang.shi@linaro.org>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ arch/x86/include/asm/signal.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/x86/include/asm/signal.h
++++ b/arch/x86/include/asm/signal.h
+@@ -32,7 +32,7 @@ typedef struct {
+ * TIF_NOTIFY_RESUME and set up the signal to be sent on exit of the
+ * trap.
+ */
+-#if defined(CONFIG_PREEMPT_RT_FULL) && defined(CONFIG_X86_64)
++#if defined(CONFIG_PREEMPT_RT_FULL)
+ #define ARCH_RT_DELAYS_SIGNAL_SEND
+ #endif
+