Linus,

please pull the latest irq-urgent-for-linus git tree from:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git 
irq-urgent-for-linus

This update contains:

  - A few fixes mopping up the fallout of the big irq overhaul

  - Move the interrupt resource management logic out of the spin locked,
    irq disabled region to avoid unnecessary restrictions of the resource
    callbacks

  - Preparation for reworking the per cpu irq request function.

Thanks,

        tglx

------------------>
Daniel Lezcano (1):
      genirq: Allow to pass the IRQF_TIMER flag with percpu irq request

Geert Uytterhoeven (1):
      genirq: Force inlining of __irq_startup_managed to prevent build failure

Marc Zyngier (1):
      irqdomain: Allow ACPI device nodes to be used as irqdomain identifiers

Sebastian Ott (1):
      genirq/debugfs: Fix build for !CONFIG_IRQ_DOMAIN

Thomas Gleixner (5):
      genirq: Move bus locking into __setup_irq()
      genirq: Add mutex to irq desc to serialize request/free_irq()
      genirq: Move irq resource handling out of spinlocked region
      genirq/timings: Move free timings out of spinlocked region
      genirq/debugfs: Remove redundant NULL pointer check


 include/linux/interrupt.h | 11 ++++++++-
 include/linux/irqdesc.h   |  3 +++
 kernel/irq/chip.c         |  2 +-
 kernel/irq/internals.h    |  4 ++-
 kernel/irq/irqdesc.c      |  1 +
 kernel/irq/irqdomain.c    | 19 +++++++++++++--
 kernel/irq/manage.c       | 62 ++++++++++++++++++++++++++++++-----------------
 7 files changed, 75 insertions(+), 27 deletions(-)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 37f8e354f564..5ac6e238555e 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -152,8 +152,17 @@ request_any_context_irq(unsigned int irq, irq_handler_t 
handler,
                        unsigned long flags, const char *name, void *dev_id);
 
 extern int __must_check
+__request_percpu_irq(unsigned int irq, irq_handler_t handler,
+                    unsigned long flags, const char *devname,
+                    void __percpu *percpu_dev_id);
+
+static inline int __must_check
 request_percpu_irq(unsigned int irq, irq_handler_t handler,
-                  const char *devname, void __percpu *percpu_dev_id);
+                  const char *devname, void __percpu *percpu_dev_id)
+{
+       return __request_percpu_irq(irq, handler, 0,
+                                   devname, percpu_dev_id);
+}
 
 extern const void *free_irq(unsigned int, void *);
 extern void free_percpu_irq(unsigned int, void __percpu *);
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index d425a3a09722..3e90a094798d 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -3,6 +3,7 @@
 
 #include <linux/rcupdate.h>
 #include <linux/kobject.h>
+#include <linux/mutex.h>
 
 /*
  * Core internal functions to deal with irq descriptors
@@ -45,6 +46,7 @@ struct pt_regs;
  *                     IRQF_FORCE_RESUME set
  * @rcu:               rcu head for delayed free
  * @kobj:              kobject used to represent this struct in sysfs
+ * @request_mutex:     mutex to protect request/free before locking desc->lock
  * @dir:               /proc/irq/ procfs entry
  * @debugfs_file:      dentry for the debugfs file
  * @name:              flow handler name for /proc/interrupts output
@@ -96,6 +98,7 @@ struct irq_desc {
        struct rcu_head         rcu;
        struct kobject          kobj;
 #endif
+       struct mutex            request_mutex;
        int                     parent_irq;
        struct module           *owner;
        const char              *name;
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 2e30d925a40d..aa5497dfb29e 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -234,7 +234,7 @@ __irq_startup_managed(struct irq_desc *desc, struct cpumask 
*aff, bool force)
        return IRQ_STARTUP_MANAGED;
 }
 #else
-static int
+static __always_inline int
 __irq_startup_managed(struct irq_desc *desc, struct cpumask *aff, bool force)
 {
        return IRQ_STARTUP_NORMAL;
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 9da14d125df4..dbfba9933ed2 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -437,7 +437,9 @@ static inline void irq_remove_debugfs_entry(struct irq_desc 
*desc)
 # ifdef CONFIG_IRQ_DOMAIN
 void irq_domain_debugfs_init(struct dentry *root);
 # else
-static inline void irq_domain_debugfs_init(struct dentry *root);
+static inline void irq_domain_debugfs_init(struct dentry *root)
+{
+}
 # endif
 #else /* CONFIG_GENERIC_IRQ_DEBUGFS */
 static inline void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *d)
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 948b50e78549..906a67e58391 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -373,6 +373,7 @@ static struct irq_desc *alloc_desc(int irq, int node, 
unsigned int flags,
 
        raw_spin_lock_init(&desc->lock);
        lockdep_set_class(&desc->lock, &irq_desc_lock_class);
+       mutex_init(&desc->request_mutex);
        init_rcu_head(&desc->rcu);
 
        desc_set_defaults(irq, desc, node, affinity, owner);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 14fe862aa2e3..f1f251479aa6 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -1,5 +1,6 @@
 #define pr_fmt(fmt)  "irq: " fmt
 
+#include <linux/acpi.h>
 #include <linux/debugfs.h>
 #include <linux/hardirq.h>
 #include <linux/interrupt.h>
@@ -155,6 +156,21 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle 
*fwnode, int size,
                        domain->name = fwid->name;
                        break;
                }
+#ifdef CONFIG_ACPI
+       } else if (is_acpi_device_node(fwnode)) {
+               struct acpi_buffer buf = {
+                       .length = ACPI_ALLOCATE_BUFFER,
+               };
+               acpi_handle handle;
+
+               handle = acpi_device_handle(to_acpi_device_node(fwnode));
+               if (acpi_get_name(handle, ACPI_FULL_PATHNAME, &buf) == AE_OK) {
+                       domain->name = buf.pointer;
+                       domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+               }
+
+               domain->fwnode = fwnode;
+#endif
        } else if (of_node) {
                char *name;
 
@@ -1667,8 +1683,7 @@ static void debugfs_add_domain_dir(struct irq_domain *d)
 
 static void debugfs_remove_domain_dir(struct irq_domain *d)
 {
-       if (d->debugfs_file)
-               debugfs_remove(d->debugfs_file);
+       debugfs_remove(d->debugfs_file);
 }
 
 void __init irq_domain_debugfs_init(struct dentry *root)
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 5c11c1730ba5..5624b2dd6b58 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -1167,6 +1167,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, 
struct irqaction *new)
        if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)
                new->flags &= ~IRQF_ONESHOT;
 
+       mutex_lock(&desc->request_mutex);
+       if (!desc->action) {
+               ret = irq_request_resources(desc);
+               if (ret) {
+                       pr_err("Failed to request resources for %s (irq %d) on 
irqchip %s\n",
+                              new->name, irq, desc->irq_data.chip->name);
+                       goto out_mutex;
+               }
+       }
+
+       chip_bus_lock(desc);
+
        /*
         * The following block of code has to be executed atomically
         */
@@ -1267,13 +1279,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, 
struct irqaction *new)
        }
 
        if (!shared) {
-               ret = irq_request_resources(desc);
-               if (ret) {
-                       pr_err("Failed to request resources for %s (irq %d) on 
irqchip %s\n",
-                              new->name, irq, desc->irq_data.chip->name);
-                       goto out_unlock;
-               }
-
                init_waitqueue_head(&desc->wait_for_threads);
 
                /* Setup the type (level, edge polarity) if configured: */
@@ -1347,6 +1352,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, 
struct irqaction *new)
        }
 
        raw_spin_unlock_irqrestore(&desc->lock, flags);
+       chip_bus_sync_unlock(desc);
+       mutex_unlock(&desc->request_mutex);
 
        irq_setup_timings(desc, new);
 
@@ -1378,6 +1385,14 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, 
struct irqaction *new)
 out_unlock:
        raw_spin_unlock_irqrestore(&desc->lock, flags);
 
+       chip_bus_sync_unlock(desc);
+
+       if (!desc->action)
+               irq_release_resources(desc);
+
+out_mutex:
+       mutex_unlock(&desc->request_mutex);
+
 out_thread:
        if (new->thread) {
                struct task_struct *t = new->thread;
@@ -1417,9 +1432,7 @@ int setup_irq(unsigned int irq, struct irqaction *act)
        if (retval < 0)
                return retval;
 
-       chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
-       chip_bus_sync_unlock(desc);
 
        if (retval)
                irq_chip_pm_put(&desc->irq_data);
@@ -1443,6 +1456,7 @@ static struct irqaction *__free_irq(unsigned int irq, 
void *dev_id)
        if (!desc)
                return NULL;
 
+       mutex_lock(&desc->request_mutex);
        chip_bus_lock(desc);
        raw_spin_lock_irqsave(&desc->lock, flags);
 
@@ -1475,8 +1489,6 @@ static struct irqaction *__free_irq(unsigned int irq, 
void *dev_id)
        if (!desc->action) {
                irq_settings_clr_disable_unlazy(desc);
                irq_shutdown(desc);
-               irq_release_resources(desc);
-               irq_remove_timings(desc);
        }
 
 #ifdef CONFIG_SMP
@@ -1518,6 +1530,13 @@ static struct irqaction *__free_irq(unsigned int irq, 
void *dev_id)
                }
        }
 
+       if (!desc->action) {
+               irq_release_resources(desc);
+               irq_remove_timings(desc);
+       }
+
+       mutex_unlock(&desc->request_mutex);
+
        irq_chip_pm_put(&desc->irq_data);
        module_put(desc->owner);
        kfree(action->secondary);
@@ -1674,9 +1693,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t 
handler,
                return retval;
        }
 
-       chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
-       chip_bus_sync_unlock(desc);
 
        if (retval) {
                irq_chip_pm_put(&desc->irq_data);
@@ -1924,9 +1941,7 @@ int setup_percpu_irq(unsigned int irq, struct irqaction 
*act)
        if (retval < 0)
                return retval;
 
-       chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, act);
-       chip_bus_sync_unlock(desc);
 
        if (retval)
                irq_chip_pm_put(&desc->irq_data);
@@ -1935,9 +1950,10 @@ int setup_percpu_irq(unsigned int irq, struct irqaction 
*act)
 }
 
 /**
- *     request_percpu_irq - allocate a percpu interrupt line
+ *     __request_percpu_irq - allocate a percpu interrupt line
  *     @irq: Interrupt line to allocate
  *     @handler: Function to be called when the IRQ occurs.
+ *     @flags: Interrupt type flags (IRQF_TIMER only)
  *     @devname: An ascii name for the claiming device
  *     @dev_id: A percpu cookie passed back to the handler function
  *
@@ -1950,8 +1966,9 @@ int setup_percpu_irq(unsigned int irq, struct irqaction 
*act)
  *     the handler gets called with the interrupted CPU's instance of
  *     that variable.
  */
-int request_percpu_irq(unsigned int irq, irq_handler_t handler,
-                      const char *devname, void __percpu *dev_id)
+int __request_percpu_irq(unsigned int irq, irq_handler_t handler,
+                        unsigned long flags, const char *devname,
+                        void __percpu *dev_id)
 {
        struct irqaction *action;
        struct irq_desc *desc;
@@ -1965,12 +1982,15 @@ int request_percpu_irq(unsigned int irq, irq_handler_t 
handler,
            !irq_settings_is_per_cpu_devid(desc))
                return -EINVAL;
 
+       if (flags && flags != IRQF_TIMER)
+               return -EINVAL;
+
        action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
        if (!action)
                return -ENOMEM;
 
        action->handler = handler;
-       action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND;
+       action->flags = flags | IRQF_PERCPU | IRQF_NO_SUSPEND;
        action->name = devname;
        action->percpu_dev_id = dev_id;
 
@@ -1980,9 +2000,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t 
handler,
                return retval;
        }
 
-       chip_bus_lock(desc);
        retval = __setup_irq(irq, desc, action);
-       chip_bus_sync_unlock(desc);
 
        if (retval) {
                irq_chip_pm_put(&desc->irq_data);
@@ -1991,7 +2009,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t 
handler,
 
        return retval;
 }
-EXPORT_SYMBOL_GPL(request_percpu_irq);
+EXPORT_SYMBOL_GPL(__request_percpu_irq);
 
 /**
  *     irq_get_irqchip_state - returns the irqchip state of a interrupt.

Reply via email to