Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit acd30250 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'irq-core-for-linus' of...

Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  irq: Export functions to allow modular irq drivers
  genirq: Uninline and sanity check generic_handle_irq()
  genirq: Remove pointless ifdefs
  genirq: Make generic irq chip depend on CONFIG_GENERIC_IRQ_CHIP
  genirq: Add chip suspend and resume callbacks
  genirq: Implement a generic interrupt chip
  genirq: Support per-IRQ thread disabling.
  genirq: irq_desc: Document preflow_handler and affinity_hint
  genirq: Update DocBook comments
  genirq: Forgotten updates/deletions after removal of compat code
parents 6595b4a9 edf76f83
Loading
Loading
Loading
Loading
+47 −35
Original line number Diff line number Diff line
@@ -191,8 +191,8 @@
	<para>
	Whenever an interrupt triggers, the lowlevel arch code calls into
	the generic interrupt code by calling desc->handle_irq().
	This highlevel IRQ handling function only uses desc->chip primitives
	referenced by the assigned chip descriptor structure.
	This highlevel IRQ handling function only uses desc->irq_data.chip
	primitives referenced by the assigned chip descriptor structure.
	</para>
    </sect1>
    <sect1 id="Highlevel_Driver_API">
@@ -206,11 +206,11 @@
	  <listitem><para>enable_irq()</para></listitem>
	  <listitem><para>disable_irq_nosync() (SMP only)</para></listitem>
	  <listitem><para>synchronize_irq() (SMP only)</para></listitem>
	  <listitem><para>set_irq_type()</para></listitem>
	  <listitem><para>set_irq_wake()</para></listitem>
	  <listitem><para>set_irq_data()</para></listitem>
	  <listitem><para>set_irq_chip()</para></listitem>
	  <listitem><para>set_irq_chip_data()</para></listitem>
	  <listitem><para>irq_set_irq_type()</para></listitem>
	  <listitem><para>irq_set_irq_wake()</para></listitem>
	  <listitem><para>irq_set_handler_data()</para></listitem>
	  <listitem><para>irq_set_chip()</para></listitem>
	  <listitem><para>irq_set_chip_data()</para></listitem>
          </itemizedlist>
	  See the autogenerated function documentation for details.
	</para>
@@ -225,6 +225,8 @@
	  <listitem><para>handle_fasteoi_irq</para></listitem>
	  <listitem><para>handle_simple_irq</para></listitem>
	  <listitem><para>handle_percpu_irq</para></listitem>
	  <listitem><para>handle_edge_eoi_irq</para></listitem>
	  <listitem><para>handle_bad_irq</para></listitem>
	  </itemizedlist>
	  The interrupt flow handlers (either predefined or architecture
	  specific) are assigned to specific interrupts by the architecture
@@ -241,13 +243,13 @@
		<programlisting>
default_enable(struct irq_data *data)
{
	desc->chip->irq_unmask(data);
	desc->irq_data.chip->irq_unmask(data);
}

default_disable(struct irq_data *data)
{
	if (!delay_disable(data))
		desc->chip->irq_mask(data);
		desc->irq_data.chip->irq_mask(data);
}

default_ack(struct irq_data *data)
@@ -284,9 +286,9 @@ noop(struct irq_data *data))
		<para>
		The following control flow is implemented (simplified excerpt):
		<programlisting>
desc->chip->irq_mask();
handle_IRQ_event(desc->action);
desc->chip->irq_unmask();
desc->irq_data.chip->irq_mask_ack();
handle_irq_event(desc->action);
desc->irq_data.chip->irq_unmask();
		</programlisting>
		</para>
	    </sect3>
@@ -300,8 +302,8 @@ desc->chip->irq_unmask();
		<para>
		The following control flow is implemented (simplified excerpt):
		<programlisting>
handle_IRQ_event(desc->action);
desc->chip->irq_eoi();
handle_irq_event(desc->action);
desc->irq_data.chip->irq_eoi();
		</programlisting>
		</para>
	    </sect3>
@@ -315,17 +317,17 @@ desc->chip->irq_eoi();
		The following control flow is implemented (simplified excerpt):
		<programlisting>
if (desc->status &amp; running) {
	desc->chip->irq_mask();
	desc->irq_data.chip->irq_mask_ack();
	desc->status |= pending | masked;
	return;
}
desc->chip->irq_ack();
desc->irq_data.chip->irq_ack();
desc->status |= running;
do {
	if (desc->status &amp; masked)
		desc->chip->irq_unmask();
		desc->irq_data.chip->irq_unmask();
	desc->status &amp;= ~pending;
	handle_IRQ_event(desc->action);
	handle_irq_event(desc->action);
} while (status &amp; pending);
desc->status &amp;= ~running;
		</programlisting>
@@ -344,7 +346,7 @@ desc->status &amp;= ~running;
		<para>
		The following control flow is implemented (simplified excerpt):
		<programlisting>
handle_IRQ_event(desc->action);
handle_irq_event(desc->action);
		</programlisting>
		</para>
   	    </sect3>
@@ -362,12 +364,29 @@ handle_IRQ_event(desc->action);
		<para>
		The following control flow is implemented (simplified excerpt):
		<programlisting>
handle_IRQ_event(desc->action);
if (desc->chip->irq_eoi)
        desc->chip->irq_eoi();
if (desc->irq_data.chip->irq_ack)
	desc->irq_data.chip->irq_ack();
handle_irq_event(desc->action);
if (desc->irq_data.chip->irq_eoi)
        desc->irq_data.chip->irq_eoi();
		</programlisting>
		</para>
   	    </sect3>
	    <sect3 id="EOI_Edge_IRQ_flow_handler">
	 	<title>EOI Edge IRQ flow handler</title>
		<para>
		handle_edge_eoi_irq provides an abnomination of the edge
		handler which is solely used to tame a badly wreckaged
		irq controller on powerpc/cell.
		</para>
   	    </sect3>
	    <sect3 id="BAD_IRQ_flow_handler">
	 	<title>Bad IRQ flow handler</title>
		<para>
		handle_bad_irq is used for spurious interrupts which
		have no real handler assigned..
		</para>
   	    </sect3>
	</sect2>
	<sect2 id="Quirks_and_optimizations">
	<title>Quirks and optimizations</title>
@@ -410,6 +429,7 @@ if (desc->chip->irq_eoi)
	  <listitem><para>irq_mask_ack() - Optional, recommended for performance</para></listitem>
	  <listitem><para>irq_mask()</para></listitem>
	  <listitem><para>irq_unmask()</para></listitem>
	  <listitem><para>irq_eoi() - Optional, required for eoi flow handlers</para></listitem>
	  <listitem><para>irq_retrigger() - Optional</para></listitem>
	  <listitem><para>irq_set_type() - Optional</para></listitem>
	  <listitem><para>irq_set_wake() - Optional</para></listitem>
@@ -424,32 +444,24 @@ if (desc->chip->irq_eoi)
  <chapter id="doirq">
     <title>__do_IRQ entry point</title>
     <para>
 	The original implementation __do_IRQ() is an alternative entry
	point for all types of interrupts.
	The original implementation __do_IRQ() was an alternative entry
	point for all types of interrupts. It not longer exists.
     </para>
     <para>
	This handler turned out to be not suitable for all
	interrupt hardware and was therefore reimplemented with split
	functionality for egde/level/simple/percpu interrupts. This is not
	functionality for edge/level/simple/percpu interrupts. This is not
	only a functional optimization. It also shortens code paths for
	interrupts.
      </para>
      <para>
	To make use of the split implementation, replace the call to
	__do_IRQ by a call to desc->handle_irq() and associate
        the appropriate handler function to desc->handle_irq().
	In most cases the generic handler implementations should
	be sufficient.
     </para>
  </chapter>

  <chapter id="locking">
     <title>Locking on SMP</title>
     <para>
	The locking of chip registers is up to the architecture that
	defines the chip primitives. There is a chip->lock field that can be used
	for serialization, but the generic layer does not touch it. The per-irq
	structure is protected via desc->lock, by the generic layer.
	defines the chip primitives. The per-irq structure is
	protected via desc->lock, by the generic layer.
     </para>
  </chapter>
  <chapter id="structs">
+160 −19
Original line number Diff line number Diff line
@@ -53,12 +53,13 @@ typedef void (*irq_preflow_handler_t)(struct irq_data *data);
 * Bits which can be modified via irq_set/clear/modify_status_flags()
 * IRQ_LEVEL			- Interrupt is level type. Will be also
 *				  updated in the code when the above trigger
 *				  bits are modified via set_irq_type()
 *				  bits are modified via irq_set_irq_type()
 * IRQ_PER_CPU			- Mark an interrupt PER_CPU. Will protect
 *				  it from affinity setting
 * IRQ_NOPROBE			- Interrupt cannot be probed by autoprobing
 * IRQ_NOREQUEST		- Interrupt cannot be requested via
 *				  request_irq()
 * IRQ_NOTHREAD			- Interrupt cannot be threaded
 * IRQ_NOAUTOEN			- Interrupt is not automatically enabled in
 *				  request/setup_irq()
 * IRQ_NO_BALANCING		- Interrupt cannot be balanced (affinity set)
@@ -85,6 +86,7 @@ enum {
	IRQ_NO_BALANCING	= (1 << 13),
	IRQ_MOVE_PCNTXT		= (1 << 14),
	IRQ_NESTED_THREAD	= (1 << 15),
	IRQ_NOTHREAD		= (1 << 16),
};

#define IRQF_MODIFY_MASK	\
@@ -261,23 +263,6 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
 * struct irq_chip - hardware interrupt chip descriptor
 *
 * @name:		name for /proc/interrupts
 * @startup:		deprecated, replaced by irq_startup
 * @shutdown:		deprecated, replaced by irq_shutdown
 * @enable:		deprecated, replaced by irq_enable
 * @disable:		deprecated, replaced by irq_disable
 * @ack:		deprecated, replaced by irq_ack
 * @mask:		deprecated, replaced by irq_mask
 * @mask_ack:		deprecated, replaced by irq_mask_ack
 * @unmask:		deprecated, replaced by irq_unmask
 * @eoi:		deprecated, replaced by irq_eoi
 * @end:		deprecated, will go away with __do_IRQ()
 * @set_affinity:	deprecated, replaced by irq_set_affinity
 * @retrigger:		deprecated, replaced by irq_retrigger
 * @set_type:		deprecated, replaced by irq_set_type
 * @set_wake:		deprecated, replaced by irq_wake
 * @bus_lock:		deprecated, replaced by irq_bus_lock
 * @bus_sync_unlock:	deprecated, replaced by irq_bus_sync_unlock
 *
 * @irq_startup:	start up the interrupt (defaults to ->enable if NULL)
 * @irq_shutdown:	shut down the interrupt (defaults to ->disable if NULL)
 * @irq_enable:		enable the interrupt (defaults to chip->unmask if NULL)
@@ -295,6 +280,9 @@ static inline void irqd_clr_chained_irq_inprogress(struct irq_data *d)
 * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
 * @irq_cpu_online:	configure an interrupt source for a secondary CPU
 * @irq_cpu_offline:	un-configure an interrupt source for a secondary CPU
 * @irq_suspend:	function called from core code on suspend once per chip
 * @irq_resume:		function called from core code on resume once per chip
 * @irq_pm_shutdown:	function called from core code on shutdown once per chip
 * @irq_print_chip:	optional to print special chip info in show_interrupts
 * @flags:		chip specific flags
 *
@@ -324,6 +312,10 @@ struct irq_chip {
	void		(*irq_cpu_online)(struct irq_data *data);
	void		(*irq_cpu_offline)(struct irq_data *data);

	void		(*irq_suspend)(struct irq_data *data);
	void		(*irq_resume)(struct irq_data *data);
	void		(*irq_pm_shutdown)(struct irq_data *data);

	void		(*irq_print_chip)(struct irq_data *data, struct seq_file *p);

	unsigned long	flags;
@@ -439,7 +431,7 @@ irq_set_handler(unsigned int irq, irq_flow_handler_t handle)
/*
 * Set a highlevel chained flow handler for a given IRQ.
 * (a chained handler is automatically enabled and set to
 *  IRQ_NOREQUEST and IRQ_NOPROBE)
 *  IRQ_NOREQUEST, IRQ_NOPROBE, and IRQ_NOTHREAD)
 */
static inline void
irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
@@ -469,6 +461,16 @@ static inline void irq_set_probe(unsigned int irq)
	irq_modify_status(irq, IRQ_NOPROBE, 0);
}

static inline void irq_set_nothread(unsigned int irq)
{
	irq_modify_status(irq, 0, IRQ_NOTHREAD);
}

static inline void irq_set_thread(unsigned int irq)
{
	irq_modify_status(irq, IRQ_NOTHREAD, 0);
}

static inline void irq_set_nested_thread(unsigned int irq, bool nest)
{
	if (nest)
@@ -573,6 +575,145 @@ static inline int irq_reserve_irq(unsigned int irq)
	return irq_reserve_irqs(irq, 1);
}

#ifndef irq_reg_writel
# define irq_reg_writel(val, addr)	writel(val, addr)
#endif
#ifndef irq_reg_readl
# define irq_reg_readl(addr)		readl(addr)
#endif

/**
 * struct irq_chip_regs - register offsets for struct irq_gci
 * @enable:	Enable register offset to reg_base
 * @disable:	Disable register offset to reg_base
 * @mask:	Mask register offset to reg_base
 * @ack:	Ack register offset to reg_base
 * @eoi:	Eoi register offset to reg_base
 * @type:	Type configuration register offset to reg_base
 * @polarity:	Polarity configuration register offset to reg_base
 */
struct irq_chip_regs {
	unsigned long		enable;
	unsigned long		disable;
	unsigned long		mask;
	unsigned long		ack;
	unsigned long		eoi;
	unsigned long		type;
	unsigned long		polarity;
};

/**
 * struct irq_chip_type - Generic interrupt chip instance for a flow type
 * @chip:		The real interrupt chip which provides the callbacks
 * @regs:		Register offsets for this chip
 * @handler:		Flow handler associated with this chip
 * @type:		Chip can handle these flow types
 *
 * A irq_generic_chip can have several instances of irq_chip_type when
 * it requires different functions and register offsets for different
 * flow types.
 */
struct irq_chip_type {
	struct irq_chip		chip;
	struct irq_chip_regs	regs;
	irq_flow_handler_t	handler;
	u32			type;
};

/**
 * struct irq_chip_generic - Generic irq chip data structure
 * @lock:		Lock to protect register and cache data access
 * @reg_base:		Register base address (virtual)
 * @irq_base:		Interrupt base nr for this chip
 * @irq_cnt:		Number of interrupts handled by this chip
 * @mask_cache:		Cached mask register
 * @type_cache:		Cached type register
 * @polarity_cache:	Cached polarity register
 * @wake_enabled:	Interrupt can wakeup from suspend
 * @wake_active:	Interrupt is marked as an wakeup from suspend source
 * @num_ct:		Number of available irq_chip_type instances (usually 1)
 * @private:		Private data for non generic chip callbacks
 * @list:		List head for keeping track of instances
 * @chip_types:		Array of interrupt irq_chip_types
 *
 * Note, that irq_chip_generic can have multiple irq_chip_type
 * implementations which can be associated to a particular irq line of
 * an irq_chip_generic instance. That allows to share and protect
 * state in an irq_chip_generic instance when we need to implement
 * different flow mechanisms (level/edge) for it.
 */
struct irq_chip_generic {
	raw_spinlock_t		lock;
	void __iomem		*reg_base;
	unsigned int		irq_base;
	unsigned int		irq_cnt;
	u32			mask_cache;
	u32			type_cache;
	u32			polarity_cache;
	u32			wake_enabled;
	u32			wake_active;
	unsigned int		num_ct;
	void			*private;
	struct list_head	list;
	struct irq_chip_type	chip_types[0];
};

/**
 * enum irq_gc_flags - Initialization flags for generic irq chips
 * @IRQ_GC_INIT_MASK_CACHE:	Initialize the mask_cache by reading mask reg
 * @IRQ_GC_INIT_NESTED_LOCK:	Set the lock class of the irqs to nested for
 *				irq chips which need to call irq_set_wake() on
 *				the parent irq. Usually GPIO implementations
 */
enum irq_gc_flags {
	IRQ_GC_INIT_MASK_CACHE		= 1 << 0,
	IRQ_GC_INIT_NESTED_LOCK		= 1 << 1,
};

/* Generic chip callback functions */
void irq_gc_noop(struct irq_data *d);
void irq_gc_mask_disable_reg(struct irq_data *d);
void irq_gc_mask_set_bit(struct irq_data *d);
void irq_gc_mask_clr_bit(struct irq_data *d);
void irq_gc_unmask_enable_reg(struct irq_data *d);
void irq_gc_ack(struct irq_data *d);
void irq_gc_mask_disable_reg_and_ack(struct irq_data *d);
void irq_gc_eoi(struct irq_data *d);
int irq_gc_set_wake(struct irq_data *d, unsigned int on);

/* Setup functions for irq_chip_generic */
struct irq_chip_generic *
irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base,
		       void __iomem *reg_base, irq_flow_handler_t handler);
void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
			    enum irq_gc_flags flags, unsigned int clr,
			    unsigned int set);
int irq_setup_alt_chip(struct irq_data *d, unsigned int type);
void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
			     unsigned int clr, unsigned int set);

static inline struct irq_chip_type *irq_data_get_chip_type(struct irq_data *d)
{
	return container_of(d->chip, struct irq_chip_type, chip);
}

#define IRQ_MSK(n) (u32)((n) < 32 ? ((1 << (n)) - 1) : UINT_MAX)

#ifdef CONFIG_SMP
static inline void irq_gc_lock(struct irq_chip_generic *gc)
{
	raw_spin_lock(&gc->lock);
}

static inline void irq_gc_unlock(struct irq_chip_generic *gc)
{
	raw_spin_unlock(&gc->lock);
}
#else
static inline void irq_gc_lock(struct irq_chip_generic *gc) { }
static inline void irq_gc_unlock(struct irq_chip_generic *gc) { }
#endif

#endif /* CONFIG_GENERIC_HARDIRQS */

#endif /* !CONFIG_S390 */
+5 −6
Original line number Diff line number Diff line
@@ -16,16 +16,18 @@ struct timer_rand_state;
 * @irq_data:		per irq and chip data passed down to chip functions
 * @timer_rand_state:	pointer to timer rand state struct
 * @kstat_irqs:		irq stats per cpu
 * @handle_irq:		highlevel irq-events handler [if NULL, __do_IRQ()]
 * @handle_irq:		highlevel irq-events handler
 * @preflow_handler:	handler called before the flow handler (currently used by sparc)
 * @action:		the irq action chain
 * @status:		status information
 * @core_internal_state__do_not_mess_with_it: core internal status information
 * @depth:		disable-depth, for nested irq_disable() calls
 * @wake_depth:		enable depth, for multiple set_irq_wake() callers
 * @wake_depth:		enable depth, for multiple irq_set_irq_wake() callers
 * @irq_count:		stats field to detect stalled irqs
 * @last_unhandled:	aging timer for unhandled count
 * @irqs_unhandled:	stats field for spurious unhandled interrupts
 * @lock:		locking for SMP
 * @affinity_hint:	hint to user space for preferred irq affinity
 * @affinity_notify:	context for notification of affinity changes
 * @pending_mask:	pending rebalanced interrupts
 * @threads_oneshot:	bitfield to handle shared oneshot threads
@@ -109,10 +111,7 @@ static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *de
	desc->handle_irq(irq, desc);
}

static inline void generic_handle_irq(unsigned int irq)
{
	generic_handle_irq_desc(irq, irq_to_desc(irq));
}
int generic_handle_irq(unsigned int irq);

/* Test to see if a driver has successfully requested an irq */
static inline int irq_has_action(unsigned int irq)
+4 −0
Original line number Diff line number Diff line
@@ -48,6 +48,10 @@ config IRQ_PREFLOW_FASTEOI
config IRQ_EDGE_EOI_HANDLER
       bool

# Generic configurable interrupt chip implementation
config GENERIC_IRQ_CHIP
       bool

# Support forced irq threading
config IRQ_FORCED_THREADING
       bool
+1 −0
Original line number Diff line number Diff line

obj-y := irqdesc.o handle.o manage.o spurious.o resend.o chip.o dummychip.o devres.o
obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
Loading