irq/core changes for v3.11
Subsystems (14)
Linus,
Please pull the latest irq-core-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq-core-for-linus
HEAD: d2e08473f2488d53a71c2f53455f934ec6c44c53 softirq: Use _RET_IP_
The main changes:
- generic-irqchip driver additions, cleanups and fixes
- 3 new irqchip drivers: ARMv7-M NVIC, TB10x and Marvell Orion SoCs
- irq_get_trigger_type() simplification and cross-arch cleanup
- various cleanups, simplifications
- documentation updates
Thanks,
Ingo
------------------>
Andreas Fenkart (1):
genirq: Add kerneldoc for irq_disable.
Ben Hutchings (1):
genirq: Fix can_request_irq() for IRQs without an action
Christian Ruppert (1):
irqchip: Add TB10x interrupt controller driver
Davidlohr Bueso (1):
softirq: Use _RET_IP_
Fabio Estevam (1):
genirq: generic-chip: Export some irq_gc_ functions
Gerlando Falauto (3):
genirq: Generic chip: Remove the local cur_regs() function
genirq: Generic chip: Add support for per chip type mask cache
genirq: Generic chip: Handle separate mask registers
Grant Likely (1):
genirq: irqchip: Add mask to block out invalid irqs
Ivo Sieben (1):
genirq: Set irq thread to RT priority on creation
James Hogan (1):
genirq: Irqchip: document gcflags arg of irq_alloc_domain_generic_chips
Javier Martinez Canillas (7):
genirq: Add irq_get_trigger_type() to get IRQ flags
gpio: mvebu: Use irq_get_trigger_type() to get IRQ flags
mfd: twl4030-irq: Use irq_get_trigger_type() to get IRQ flags
mfd: stmpe: use irq_get_trigger_type() to get IRQ flags
arm: orion: Use irq_get_trigger_type() to get IRQ flags
MIPS: octeon: Use irq_get_trigger_type() to get IRQ flags
irqdomain: Use irq_get_trigger_type() to get IRQ flags
Sachin Kamat (1):
irqchip: exynos-combiner: Staticize combiner_init
Sebastian Hesselbarth (1):
irqchip: Add support for Marvell Orion SoCs
Thomas Gleixner (5):
genirq: Generic chip: Cache per irq bit mask
genirq: irqchip: Add a mask calculation function
genirq: Generic chip: Split out code into separate functions
genirq: Generic chip: Add linear irq domain support
genirq: Add the generic chip to the genirq docbook
Uwe Kleine-König (1):
irqchip: Add support for ARMv7-M NVIC
Documentation/DocBook/genericirq.tmpl | 13 + .../interrupt-controller/abilis,tb10x-ictl.txt | 38 +++ .../interrupt-controller/marvell,orion-intc.txt | 48 ++++ arch/arm/plat-orion/gpio.c | 2 +- arch/mips/cavium-octeon/octeon-irq.c | 2 +- drivers/gpio/gpio-mvebu.c | 2 +- drivers/irqchip/Kconfig | 15 + drivers/irqchip/Makefile | 3 + drivers/irqchip/exynos-combiner.c | 8 +- drivers/irqchip/irq-nvic.c | 117 ++++++++ drivers/irqchip/irq-orion.c | 192 +++++++++++++ drivers/irqchip/irq-tb10x.c | 195 +++++++++++++ drivers/mfd/stmpe.c | 3 +- drivers/mfd/twl4030-irq.c | 5 +- include/linux/irq.h | 53 +++- include/linux/irqdomain.h | 12 + kernel/irq/chip.c | 13 + kernel/irq/generic-chip.c | 314 ++++++++++++++++++--- kernel/irq/irqdomain.c | 8 +- kernel/irq/manage.c | 17 +- kernel/softirq.c | 10 +- 21 files changed, 988 insertions(+), 82 deletions(-) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/abilis,tb10x-ictl.txt create mode 100644 Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt create mode 100644 drivers/irqchip/irq-nvic.c create mode 100644 drivers/irqchip/irq-orion.c create mode 100644 drivers/irqchip/irq-tb10x.c
Documentation/DocBook/genericirq.tmpl +13 -0
@@ -464,6 +464,19 @@ if (desc->irq_data.chip->irq_eoi) protected via desc->lock, by the generic layer. </para> </chapter> + + <chapter id="genericchip"> + <title>Generic interrupt chip</title> + <para> + To avoid copies of identical implementations of irq chips the + core provides a configurable generic interrupt chip + implementation. Developers should check carefuly whether the + generic chip fits their needs before implementing the same + functionality slightly different themself. + </para> +!Ekernel/irq/generic-chip.c + </chapter> + <chapter id="structs"> <title>Structures</title> <para>
Documentation/devicetree/bindings/interrupt-controller/abilis,tb10x-ictl.txt new file +38 -0
@@ -0,0 +1,38 @@ +TB10x Top Level Interrupt Controller +==================================== + +The Abilis TB10x SOC contains a custom interrupt controller. It performs +one-to-one mapping of external interrupt sources to CPU interrupts and +provides support for reconfigurable trigger modes. + +Required properties +------------------- + +- compatible: Should be "abilis,tb10x-ictl" +- reg: specifies physical base address and size of register range. +- interrupt-congroller: Identifies the node as an interrupt controller. +- #interrupt cells: Specifies the number of cells used to encode an interrupt + source connected to this controller. The value shall be 2. +- interrupt-parent: Specifies the parent interrupt controller. +- interrupts: Specifies the list of interrupt lines which are handled by + the interrupt controller in the parent controller's notation. Interrupts + are mapped one-to-one to parent interrupts. + +Example +------- + +intc: interrupt-controller { /* Parent interrupt controller */ + interrupt-controller; + #interrupt-cells = <1>; /* For example below */ + /* ... */ +}; + +tb10x_ictl: pic@2000 { /* TB10x interrupt controller */ + compatible = "abilis,tb10x-ictl"; + reg = <0x2000 0x20>; + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + 20 21 22 23 24 25 26 27 28 29 30 31>; +};
Documentation/devicetree/bindings/interrupt-controller/marvell,orion-intc.txt new file +48 -0
48 lines not on this page · raw message
arch/arm/plat-orion/gpio.c +1 -1
@@ -426,7 +426,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)if (!(cause & (1 << i)))continue ; - type =irqd_get_trigger_type (irq_get_irq_data (irq)); + type =irq_get_trigger_type (irq);if ((type &IRQ_TYPE_SENSE_MASK ) ==IRQ_TYPE_EDGE_BOTH ) {/* Swap polarity (race with GPIO line) */ u32 polarity;
arch/mips/cavium-octeon/octeon-irq.c +1 -1
@@ -607,7 +607,7 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data)static void octeon_irq_handle_gpio (unsigned int irq,struct irq_desc *desc) { -if (irqd_get_trigger_type (irq_desc_get_irq_data (desc)) &IRQ_TYPE_EDGE_BOTH ) +if (irq_get_trigger_type (irq) &IRQ_TYPE_EDGE_BOTH )handle_edge_irq (irq, desc);else handle_level_irq (irq, desc);
drivers/gpio/gpio-mvebu.c +1 -1
@@ -457,7 +457,7 @@ static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)if (!(cause & (1 << i)))continue ; - type =irqd_get_trigger_type (irq_get_irq_data (irq)); + type =irq_get_trigger_type (irq);if ((type &IRQ_TYPE_SENSE_MASK ) ==IRQ_TYPE_EDGE_BOTH ) {/* Swap polarity (race with GPIO line) */ u32 polarity;
drivers/irqchip/Kconfig +15 -0
@@ -10,6 +10,11 @@ config ARM_GIC config GIC_NON_BANKED bool +config ARM_NVIC + bool + select IRQ_DOMAIN + select GENERIC_IRQ_CHIP + config ARM_VIC bool select IRQ_DOMAIN
@@ -25,6 +30,11 @@ config ARM_VIC_NR The maximum number of VICs available in the system, for power management. +config ORION_IRQCHIP + bool + select IRQ_DOMAIN + select MULTI_IRQ_HANDLER + config RENESAS_INTC_IRQPIN bool select IRQ_DOMAIN
@@ -33,6 +43,11 @@ config RENESAS_IRQC bool select IRQ_DOMAIN +config TB10X_IRQC + bool + select IRQ_DOMAIN + select GENERIC_IRQ_CHIP + config VERSATILE_FPGA_IRQ bool select IRQ_DOMAIN
drivers/irqchip/Makefile +3 -0
@@ -7,12 +7,15 @@ obj-$(CONFIG_ARCH_MXS) += irq-mxs.o obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o obj-$(CONFIG_METAG) += irq-metag-ext.o obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o +obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o +obj-$(CONFIG_ARM_NVIC) += irq-nvic.o obj-$(CONFIG_ARM_VIC) += irq-vic.o obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o +obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
drivers/irqchip/exynos-combiner.c +4 -4
@@ -204,10 +204,10 @@ static unsigned int combiner_lookup_irq(int group)return 0 ; } -void __init combiner_init (void __iomem *combiner_base, -struct device_node *np, -unsigned int max_nr, -int irq_base) +static void __init combiner_init (void __iomem *combiner_base, +struct device_node *np, +unsigned int max_nr, +int irq_base) {int i, irq;unsigned int nr_irq;
drivers/irqchip/irq-nvic.c new file +117 -0
117 lines not on this page · raw message
drivers/irqchip/irq-orion.c new file +192 -0
192 lines not on this page · raw message
drivers/irqchip/irq-tb10x.c new file +195 -0
195 lines not on this page · raw message
drivers/mfd/stmpe.c +1 -2
@@ -1208,8 +1208,7 @@ int stmpe_probe(struct stmpe_client_info *ci, int partnum) } stmpe->variant = stmpe_noirq_variant_info[stmpe->partnum]; }else if (pdata->irq_trigger ==IRQF_TRIGGER_NONE ) { - pdata->irq_trigger = -irqd_get_trigger_type (irq_get_irq_data (stmpe->irq)); + pdata->irq_trigger =irq_get_trigger_type (stmpe->irq); } ret =stmpe_chip_init (stmpe);
drivers/mfd/twl4030-irq.c +1 -4
@@ -537,16 +537,13 @@ static void twl4030_sih_bus_sync_unlock(struct irq_data *data)/* Modify only the bits we know must change */ while (edge_change) {int i =fls (edge_change) -1 ; -struct irq_data *idata;int byte = i >>2 ;int off = (i &0x3 ) *2 ;unsigned int type; - idata =irq_get_irq_data (i + agent->irq_base); - bytes[byte] &= ~(0x03 << off); - type =irqd_get_trigger_type (idata); + type =irq_get_trigger_type (i + agent->irq_base);if (type &IRQ_TYPE_EDGE_RISING ) bytes[byte] |=BIT (off +1 );if (type &IRQ_TYPE_EDGE_FALLING )
include/linux/irq.h +52 -1
129 lines not on this page · raw message
include/linux/irqdomain.h +12 -0
@@ -66,6 +66,10 @@ struct irq_domain_ops { unsigned long *out_hwirq, unsigned int *out_type); }; +extern struct irq_domain_ops irq_generic_chip_ops; + +struct irq_domain_chip_generic ; +/** * struct irq_domain - Hardware interrupt number translation object * @link: Element in global irq_domain list.
@@ -109,8 +113,16 @@ struct irq_domain {/* Optional device node pointer */ struct device_node *of_node; +/* Optional pointer to generic interrupt chips */ +struct irq_domain_chip_generic *gc; }; +#define IRQ_DOMAIN_MAP_LEGACY 0/* driver allocated fixed range of irqs. +* ie. legacy 8259, gets irqs 1..15 */ +#define IRQ_DOMAIN_MAP_NOMAP 1/* no fast reverse mapping */ +#define IRQ_DOMAIN_MAP_LINEAR 2/* linear map of interrupts */ +#define IRQ_DOMAIN_MAP_TREE 3/* radix tree */ +#ifdef CONFIG_IRQ_DOMAIN struct irq_domain *irq_domain_add_simple(struct device_node *of_node, unsigned int size,
kernel/irq/chip.c +13 -0
@@ -213,6 +213,19 @@ void irq_enable(struct irq_desc *desc)irq_state_clr_masked (desc); } +/** +* irq_disable - Mark interupt disabled +* @desc: irq descriptor which should be disabled +* +* If the chip does not implement the irq_disable callback, we +* use a lazy disable approach. That means we mark the interrupt +* disabled, but leave the hardware unmasked. That's an +* optimization because we avoid the hardware access for the +* common case where no interrupt happens after we marked it +* disabled. If an interrupt happens, then the interrupt flow +* handler masks the line at the hardware level and marks it +* pending. +*/ void irq_disable (struct irq_desc *desc) {irq_state_set_disabled (desc);
kernel/irq/generic-chip.c +267 -47
484 lines not on this page · raw message
kernel/irq/irqdomain.c +1 -7
@@ -16,12 +16,6 @@#include <linux/smp.h> #include <linux/fs.h> -#define IRQ_DOMAIN_MAP_LEGACY 0/* driver allocated fixed range of irqs. -* ie. legacy 8259, gets irqs 1..15 */ -#define IRQ_DOMAIN_MAP_NOMAP 1/* no fast reverse mapping */ -#define IRQ_DOMAIN_MAP_LINEAR 2/* linear map of interrupts */ -#define IRQ_DOMAIN_MAP_TREE 3/* radix tree */ -static LIST_HEAD (irq_domain_list);static DEFINE_MUTEX (irq_domain_mutex);
@@ -693,7 +687,7 @@ unsigned int irq_create_of_mapping(struct device_node *controller,/* Set type if specified and different than the current one */ if (type !=IRQ_TYPE_NONE && - type != (irqd_get_trigger_type (irq_get_irq_data (virq)))) + type !=irq_get_trigger_type (virq))irq_set_irq_type (virq, type);return virq; }
kernel/irq/manage.c +9 -8
@@ -555,9 +555,9 @@ int can_request_irq(unsigned int irq, unsigned long irqflags)return 0 ;if (irq_settings_can_request (desc)) { -if (desc->action) -if (irqflags & desc->action->flags &IRQF_SHARED ) - canrequest =1 ; +if (!desc->action || + irqflags & desc->action->flags &IRQF_SHARED ) + canrequest =1 ; }irq_put_desc_unlock (desc, flags);return canrequest;
@@ -840,9 +840,6 @@ static void irq_thread_dtor(struct callback_head *unused)static int irq_thread (void *data) {struct callback_head on_exit_work; -static const struct sched_param param = { - .sched_priority =MAX_USER_RT_PRIO /2 , - };struct irqaction *action = data;struct irq_desc *desc =irq_to_desc (action->irq); irqreturn_t (*handler_fn)(struct irq_desc *desc,
@@ -854,8 +851,6 @@ static int irq_thread(void *data)else handler_fn = irq_thread_fn; -sched_setscheduler (current,SCHED_FIFO , ¶m); -init_task_work (&on_exit_work, irq_thread_dtor);task_work_add (current, &on_exit_work, false);
@@ -950,6 +945,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)*/ if (new->thread_fn && !nested) {struct task_struct *t; +static const struct sched_param param = { + .sched_priority =MAX_USER_RT_PRIO /2 , + }; t =kthread_create (irq_thread, new,"irq/%d-%s" , irq, new->name);
@@ -957,6 +955,9 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) ret =PTR_ERR (t); goto out_mput; } + +sched_setscheduler (t,SCHED_FIFO , ¶m); +/* * We keep the reference to the task struct even if * the thread dies to avoid that the interrupt code
kernel/softirq.c +4 -6
@@ -127,8 +127,7 @@ static inline void __local_bh_disable(unsigned long ip, unsigned int cnt)void local_bh_disable (void ) { -__local_bh_disable ((unsigned long )__builtin_return_address (0 ), -SOFTIRQ_DISABLE_OFFSET ); +__local_bh_disable (_RET_IP_,SOFTIRQ_DISABLE_OFFSET ); }EXPORT_SYMBOL (local_bh_disable);
@@ -139,7 +138,7 @@ static void __local_bh_enable(unsigned int cnt)WARN_ON_ONCE (!irqs_disabled ());if (softirq_count () == cnt) -trace_softirqs_on ((unsigned long )__builtin_return_address (0 )); +trace_softirqs_on (_RET_IP_);sub_preempt_count (cnt); }
@@ -184,7 +183,7 @@ static inline void _local_bh_enable_ip(unsigned long ip)void local_bh_enable (void ) { -_local_bh_enable_ip ((unsigned long )__builtin_return_address (0 )); +_local_bh_enable_ip (_RET_IP_); }EXPORT_SYMBOL (local_bh_enable);
@@ -223,8 +222,7 @@ asmlinkage void __do_softirq(void) pending =local_softirq_pending ();account_irq_enter_time (current); -__local_bh_disable ((unsigned long )__builtin_return_address (0 ), -SOFTIRQ_OFFSET ); +__local_bh_disable (_RET_IP_,SOFTIRQ_OFFSET );lockdep_softirq_enter (); cpu =smp_processor_id ();