]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - include/linux/irq.h
Merge tag 'v2.6.37' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / include / linux / irq.h
index c03243ad84b46b220324d499b18e0805e9fb827b..abde2527c699684f78cf029b82c740af751c26a2 100644 (file)
@@ -72,6 +72,10 @@ typedef      void (*irq_flow_handler_t)(unsigned int irq,
 #define IRQ_ONESHOT            0x08000000      /* IRQ is not unmasked after hardirq */
 #define IRQ_NESTED_THREAD      0x10000000      /* IRQ is nested into another, no own handler thread */
 
+#define IRQF_MODIFY_MASK       \
+       (IRQ_TYPE_SENSE_MASK | IRQ_NOPROBE | IRQ_NOREQUEST | \
+        IRQ_NOAUTOEN | IRQ_MOVE_PCNTXT | IRQ_LEVEL)
+
 #ifdef CONFIG_IRQ_PER_CPU
 # define CHECK_IRQ_PER_CPU(var) ((var) & IRQ_PER_CPU)
 # define IRQ_NO_BALANCING_MASK (IRQ_PER_CPU | IRQ_NO_BALANCING)
@@ -80,36 +84,77 @@ typedef     void (*irq_flow_handler_t)(unsigned int irq,
 # define IRQ_NO_BALANCING_MASK IRQ_NO_BALANCING
 #endif
 
-struct proc_dir_entry;
 struct msi_desc;
 
+/**
+ * struct irq_data - per irq and irq chip data passed down to chip functions
+ * @irq:               interrupt number
+ * @node:              node index useful for balancing
+ * @chip:              low level interrupt hardware access
+ * @handler_data:      per-IRQ data for the irq_chip methods
+ * @chip_data:         platform-specific per-chip private data for the chip
+ *                     methods, to allow shared chip implementations
+ * @msi_desc:          MSI descriptor
+ * @affinity:          IRQ affinity on SMP
+ *
+ * The fields here need to overlay the ones in irq_desc until we
+ * cleaned up the direct references and switched everything over to
+ * irq_data.
+ */
+struct irq_data {
+       unsigned int            irq;
+       unsigned int            node;
+       struct irq_chip         *chip;
+       void                    *handler_data;
+       void                    *chip_data;
+       struct msi_desc         *msi_desc;
+#ifdef CONFIG_SMP
+       cpumask_var_t           affinity;
+#endif
+};
+
 /**
  * struct irq_chip - hardware interrupt chip descriptor
  *
  * @name:              name for /proc/interrupts
- * @startup:           start up the interrupt (defaults to ->enable if NULL)
- * @shutdown:          shut down the interrupt (defaults to ->disable if NULL)
- * @enable:            enable the interrupt (defaults to chip->unmask if NULL)
- * @disable:           disable the interrupt
- * @ack:               start of a new interrupt
- * @mask:              mask an interrupt source
- * @mask_ack:          ack and mask an interrupt source
- * @unmask:            unmask an interrupt source
- * @eoi:               end of interrupt - chip level
- * @end:               end of interrupt - flow level
- * @set_affinity:      set the CPU affinity on SMP machines
- * @retrigger:         resend an IRQ to the CPU
- * @set_type:          set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
- * @set_wake:          enable/disable power-management wake-on of an IRQ
+ * @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
  *
- * @bus_lock:          function to lock access to slow bus (i2c) chips
- * @bus_sync_unlock:   function to sync and unlock slow bus (i2c) chips
+ * @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)
+ * @irq_disable:       disable the interrupt
+ * @irq_ack:           start of a new interrupt
+ * @irq_mask:          mask an interrupt source
+ * @irq_mask_ack:      ack and mask an interrupt source
+ * @irq_unmask:                unmask an interrupt source
+ * @irq_eoi:           end of interrupt
+ * @irq_set_affinity:  set the CPU affinity on SMP machines
+ * @irq_retrigger:     resend an IRQ to the CPU
+ * @irq_set_type:      set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
+ * @irq_set_wake:      enable/disable power-management wake-on of an IRQ
+ * @irq_bus_lock:      function to lock access to slow bus (i2c) chips
+ * @irq_bus_sync_unlock:function to sync and unlock slow bus (i2c) chips
  *
  * @release:           release function solely used by UML
- * @typename:          obsoleted by name, kept as migration helper
  */
 struct irq_chip {
        const char      *name;
+#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
        unsigned int    (*startup)(unsigned int irq);
        void            (*shutdown)(unsigned int irq);
        void            (*enable)(unsigned int irq);
@@ -130,154 +175,66 @@ struct irq_chip {
 
        void            (*bus_lock)(unsigned int irq);
        void            (*bus_sync_unlock)(unsigned int irq);
+#endif
+       unsigned int    (*irq_startup)(struct irq_data *data);
+       void            (*irq_shutdown)(struct irq_data *data);
+       void            (*irq_enable)(struct irq_data *data);
+       void            (*irq_disable)(struct irq_data *data);
+
+       void            (*irq_ack)(struct irq_data *data);
+       void            (*irq_mask)(struct irq_data *data);
+       void            (*irq_mask_ack)(struct irq_data *data);
+       void            (*irq_unmask)(struct irq_data *data);
+       void            (*irq_eoi)(struct irq_data *data);
+
+       int             (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
+       int             (*irq_retrigger)(struct irq_data *data);
+       int             (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
+       int             (*irq_set_wake)(struct irq_data *data, unsigned int on);
+
+       void            (*irq_bus_lock)(struct irq_data *data);
+       void            (*irq_bus_sync_unlock)(struct irq_data *data);
 
        /* Currently used only by UML, might disappear one day.*/
 #ifdef CONFIG_IRQ_RELEASE_METHOD
        void            (*release)(unsigned int irq, void *dev_id);
 #endif
-       /*
-        * For compatibility, ->typename is copied into ->name.
-        * Will disappear.
-        */
-       const char      *typename;
 };
 
-struct timer_rand_state;
-struct irq_2_iommu;
-/**
- * struct irq_desc - interrupt descriptor
- * @irq:               interrupt number for this descriptor
- * @timer_rand_state:  pointer to timer rand state struct
- * @kstat_irqs:                irq stats per cpu
- * @irq_2_iommu:       iommu with this irq
- * @handle_irq:                highlevel irq-events handler [if NULL, __do_IRQ()]
- * @chip:              low level interrupt hardware access
- * @msi_desc:          MSI descriptor
- * @handler_data:      per-IRQ data for the irq_chip methods
- * @chip_data:         platform-specific per-chip private data for the chip
- *                     methods, to allow shared chip implementations
- * @action:            the irq action chain
- * @status:            status information
- * @depth:             disable-depth, for nested irq_disable() calls
- * @wake_depth:                enable depth, for multiple 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:          IRQ affinity on SMP
- * @node:              node index useful for balancing
- * @pending_mask:      pending rebalanced interrupts
- * @threads_active:    number of irqaction threads currently running
- * @wait_for_threads:  wait queue for sync_irq to wait for threaded handlers
- * @dir:               /proc/irq/ procfs entry
- * @name:              flow handler name for /proc/interrupts output
- */
-struct irq_desc {
-       unsigned int            irq;
-       struct timer_rand_state *timer_rand_state;
-       unsigned int            *kstat_irqs;
-#ifdef CONFIG_INTR_REMAP
-       struct irq_2_iommu      *irq_2_iommu;
-#endif
-       irq_flow_handler_t      handle_irq;
-       struct irq_chip         *chip;
-       struct msi_desc         *msi_desc;
-       void                    *handler_data;
-       void                    *chip_data;
-       struct irqaction        *action;        /* IRQ action list */
-       unsigned int            status;         /* IRQ status */
-
-       unsigned int            depth;          /* nested irq disables */
-       unsigned int            wake_depth;     /* nested wake enables */
-       unsigned int            irq_count;      /* For detecting broken IRQs */
-       unsigned long           last_unhandled; /* Aging timer for unhandled count */
-       unsigned int            irqs_unhandled;
-       raw_spinlock_t          lock;
-#ifdef CONFIG_SMP
-       cpumask_var_t           affinity;
-       const struct cpumask    *affinity_hint;
-       unsigned int            node;
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_var_t           pending_mask;
-#endif
-#endif
-       atomic_t                threads_active;
-       wait_queue_head_t       wait_for_threads;
-#ifdef CONFIG_PROC_FS
-       struct proc_dir_entry   *dir;
-#endif
-       const char              *name;
-} ____cacheline_internodealigned_in_smp;
+/* This include will go away once we isolated irq_desc usage to core code */
+#include <linux/irqdesc.h>
 
-extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
-                                       struct irq_desc *desc, int node);
-extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
+/*
+ * Pick up the arch-dependent methods:
+ */
+#include <asm/hw_irq.h>
 
-#ifndef CONFIG_SPARSE_IRQ
-extern struct irq_desc irq_desc[NR_IRQS];
+#ifndef NR_IRQS_LEGACY
+# define NR_IRQS_LEGACY 0
 #endif
 
-#ifdef CONFIG_NUMA_IRQ_DESC
-extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int node);
-#else
-static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
-{
-       return desc;
-}
+#ifndef ARCH_IRQ_INIT_FLAGS
+# define ARCH_IRQ_INIT_FLAGS   0
 #endif
 
-extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
-
-/*
- * Pick up the arch-dependent methods:
- */
-#include <asm/hw_irq.h>
+#define IRQ_DEFAULT_INIT_FLAGS (IRQ_DISABLED | ARCH_IRQ_INIT_FLAGS)
 
+struct irqaction;
 extern int setup_irq(unsigned int irq, struct irqaction *new);
 extern void remove_irq(unsigned int irq, struct irqaction *act);
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 
-#ifdef CONFIG_SMP
-
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-
+#if defined(CONFIG_SMP) && defined(CONFIG_GENERIC_PENDING_IRQ)
 void move_native_irq(int irq);
 void move_masked_irq(int irq);
-
-#else /* CONFIG_GENERIC_PENDING_IRQ */
-
-static inline void move_irq(int irq)
-{
-}
-
-static inline void move_native_irq(int irq)
-{
-}
-
-static inline void move_masked_irq(int irq)
-{
-}
-
-#endif /* CONFIG_GENERIC_PENDING_IRQ */
-
-#else /* CONFIG_SMP */
-
-#define move_native_irq(x)
-#define move_masked_irq(x)
-
-#endif /* CONFIG_SMP */
+#else
+static inline void move_native_irq(int irq) { }
+static inline void move_masked_irq(int irq) { }
+#endif
 
 extern int no_irq_affinity;
 
-static inline int irq_balancing_disabled(unsigned int irq)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       return desc->status & IRQ_NO_BALANCING_MASK;
-}
-
 /* Handle irq action chains: */
 extern irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action);
 
@@ -293,42 +250,10 @@ extern void handle_percpu_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_bad_irq(unsigned int irq, struct irq_desc *desc);
 extern void handle_nested_irq(unsigned int irq);
 
-/*
- * Monolithic do_IRQ implementation.
- */
-#ifndef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-extern unsigned int __do_IRQ(unsigned int irq);
-#endif
-
-/*
- * Architectures call this to let the generic IRQ layer
- * handle an interrupt. If the descriptor is attached to an
- * irqchip-style controller then we call the ->handle_irq() handler,
- * and it calls __do_IRQ() if it's attached to an irqtype-style controller.
- */
-static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
-{
-#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
-       desc->handle_irq(irq, desc);
-#else
-       if (likely(desc->handle_irq))
-               desc->handle_irq(irq, desc);
-       else
-               __do_IRQ(irq);
-#endif
-}
-
-static inline void generic_handle_irq(unsigned int irq)
-{
-       generic_handle_irq_desc(irq, irq_to_desc(irq));
-}
-
 /* Handling of unhandled and spurious interrupts: */
 extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
                           irqreturn_t action_ret);
 
-/* Resending of interrupts :*/
-void check_irq_resend(struct irq_desc *desc, unsigned int irq);
 
 /* Enable/disable irq debugging output: */
 extern int noirqdebug_setup(char *str);
@@ -351,16 +276,6 @@ extern void
 __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
                  const char *name);
 
-/* caller has locked the irq_desc and both params are valid */
-static inline void __set_irq_handler_unlocked(int irq,
-                                             irq_flow_handler_t handler)
-{
-       struct irq_desc *desc;
-
-       desc = irq_to_desc(irq);
-       desc->handle_irq = handler;
-}
-
 /*
  * Set a highlevel flow handler for a given IRQ:
  */
@@ -384,141 +299,126 @@ set_irq_chained_handler(unsigned int irq,
 
 extern void set_irq_nested_thread(unsigned int irq, int nest);
 
-extern void set_irq_noprobe(unsigned int irq);
-extern void set_irq_probe(unsigned int irq);
+void irq_modify_status(unsigned int irq, unsigned long clr, unsigned long set);
+
+static inline void irq_set_status_flags(unsigned int irq, unsigned long set)
+{
+       irq_modify_status(irq, 0, set);
+}
+
+static inline void irq_clear_status_flags(unsigned int irq, unsigned long clr)
+{
+       irq_modify_status(irq, clr, 0);
+}
+
+static inline void set_irq_noprobe(unsigned int irq)
+{
+       irq_modify_status(irq, 0, IRQ_NOPROBE);
+}
+
+static inline void set_irq_probe(unsigned int irq)
+{
+       irq_modify_status(irq, IRQ_NOPROBE, 0);
+}
 
 /* Handle dynamic irq creation and destruction */
 extern unsigned int create_irq_nr(unsigned int irq_want, int node);
 extern int create_irq(void);
 extern void destroy_irq(unsigned int irq);
 
-/* Test to see if a driver has successfully requested an irq */
-static inline int irq_has_action(unsigned int irq)
+/*
+ * Dynamic irq helper functions. Obsolete. Use irq_alloc_desc* and
+ * irq_free_desc instead.
+ */
+extern void dynamic_irq_cleanup(unsigned int irq);
+static inline void dynamic_irq_init(unsigned int irq)
 {
-       struct irq_desc *desc = irq_to_desc(irq);
-       return desc->action != NULL;
+       dynamic_irq_cleanup(irq);
 }
 
-/* Dynamic irq helper functions */
-extern void dynamic_irq_init(unsigned int irq);
-void dynamic_irq_init_keep_chip_data(unsigned int irq);
-extern void dynamic_irq_cleanup(unsigned int irq);
-void dynamic_irq_cleanup_keep_chip_data(unsigned int irq);
-
 /* Set/get chip/data for an IRQ: */
 extern int set_irq_chip(unsigned int irq, struct irq_chip *chip);
 extern int set_irq_data(unsigned int irq, void *data);
 extern int set_irq_chip_data(unsigned int irq, void *data);
 extern int set_irq_type(unsigned int irq, unsigned int type);
 extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
+extern struct irq_data *irq_get_irq_data(unsigned int irq);
 
-#define get_irq_chip(irq)      (irq_to_desc(irq)->chip)
-#define get_irq_chip_data(irq) (irq_to_desc(irq)->chip_data)
-#define get_irq_data(irq)      (irq_to_desc(irq)->handler_data)
-#define get_irq_msi(irq)       (irq_to_desc(irq)->msi_desc)
-
-#define get_irq_desc_chip(desc)                ((desc)->chip)
-#define get_irq_desc_chip_data(desc)   ((desc)->chip_data)
-#define get_irq_desc_data(desc)                ((desc)->handler_data)
-#define get_irq_desc_msi(desc)         ((desc)->msi_desc)
-
-#endif /* CONFIG_GENERIC_HARDIRQS */
-
-#endif /* !CONFIG_S390 */
-
-#ifdef CONFIG_SMP
-/**
- * alloc_desc_masks - allocate cpumasks for irq_desc
- * @desc:      pointer to irq_desc struct
- * @node:      node which will be handling the cpumasks
- * @boot:      true if need bootmem
- *
- * Allocates affinity and pending_mask cpumask if required.
- * Returns true if successful (or not required).
- */
-static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
-                                                       bool boot)
+static inline struct irq_chip *get_irq_chip(unsigned int irq)
 {
-       gfp_t gfp = GFP_ATOMIC;
-
-       if (boot)
-               gfp = GFP_NOWAIT;
-
-#ifdef CONFIG_CPUMASK_OFFSTACK
-       if (!alloc_cpumask_var_node(&desc->affinity, gfp, node))
-               return false;
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->chip : NULL;
+}
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       if (!alloc_cpumask_var_node(&desc->pending_mask, gfp, node)) {
-               free_cpumask_var(desc->affinity);
-               return false;
-       }
-#endif
-#endif
-       return true;
+static inline struct irq_chip *irq_data_get_irq_chip(struct irq_data *d)
+{
+       return d->chip;
 }
 
-static inline void init_desc_masks(struct irq_desc *desc)
+static inline void *get_irq_chip_data(unsigned int irq)
 {
-       cpumask_setall(desc->affinity);
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_clear(desc->pending_mask);
-#endif
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->chip_data : NULL;
 }
 
-/**
- * init_copy_desc_masks - copy cpumasks for irq_desc
- * @old_desc:  pointer to old irq_desc struct
- * @new_desc:  pointer to new irq_desc struct
- *
- * Insures affinity and pending_masks are copied to new irq_desc.
- * If !CONFIG_CPUMASKS_OFFSTACK the cpumasks are embedded in the
- * irq_desc struct so the copy is redundant.
- */
+static inline void *irq_data_get_irq_chip_data(struct irq_data *d)
+{
+       return d->chip_data;
+}
 
-static inline void init_copy_desc_masks(struct irq_desc *old_desc,
-                                       struct irq_desc *new_desc)
+static inline void *get_irq_data(unsigned int irq)
 {
-#ifdef CONFIG_CPUMASK_OFFSTACK
-       cpumask_copy(new_desc->affinity, old_desc->affinity);
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->handler_data : NULL;
+}
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       cpumask_copy(new_desc->pending_mask, old_desc->pending_mask);
-#endif
-#endif
+static inline void *irq_data_get_irq_data(struct irq_data *d)
+{
+       return d->handler_data;
 }
 
-static inline void free_desc_masks(struct irq_desc *old_desc,
-                                  struct irq_desc *new_desc)
+static inline struct msi_desc *get_irq_msi(unsigned int irq)
 {
-       free_cpumask_var(old_desc->affinity);
+       struct irq_data *d = irq_get_irq_data(irq);
+       return d ? d->msi_desc : NULL;
+}
 
-#ifdef CONFIG_GENERIC_PENDING_IRQ
-       free_cpumask_var(old_desc->pending_mask);
-#endif
+static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
+{
+       return d->msi_desc;
 }
 
-#else /* !CONFIG_SMP */
+int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
+void irq_free_descs(unsigned int irq, unsigned int cnt);
+int irq_reserve_irqs(unsigned int from, unsigned int cnt);
+
+static inline int irq_alloc_desc(int node)
+{
+       return irq_alloc_descs(-1, 0, 1, node);
+}
 
-static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
-                                                               bool boot)
+static inline int irq_alloc_desc_at(unsigned int at, int node)
 {
-       return true;
+       return irq_alloc_descs(at, at, 1, node);
 }
 
-static inline void init_desc_masks(struct irq_desc *desc)
+static inline int irq_alloc_desc_from(unsigned int from, int node)
 {
+       return irq_alloc_descs(-1, from, 1, node);
 }
 
-static inline void init_copy_desc_masks(struct irq_desc *old_desc,
-                                       struct irq_desc *new_desc)
+static inline void irq_free_desc(unsigned int irq)
 {
+       irq_free_descs(irq, 1);
 }
 
-static inline void free_desc_masks(struct irq_desc *old_desc,
-                                  struct irq_desc *new_desc)
+static inline int irq_reserve_irq(unsigned int irq)
 {
+       return irq_reserve_irqs(irq, 1);
 }
-#endif /* CONFIG_SMP */
+
+#endif /* CONFIG_GENERIC_HARDIRQS */
+
+#endif /* !CONFIG_S390 */
 
 #endif /* _LINUX_IRQ_H */