Messages in this thread Patch in this message | | | Date | Tue, 11 Jul 2017 12:52:17 +0200 (CEST) | From | Thomas Gleixner <> | Subject | Re: [GIT pull] irq updates for 4.13 |
| |
Sebastian,
On Tue, 11 Jul 2017, Thomas Gleixner wrote: > On Tue, 11 Jul 2017, Sebastian Reichel wrote: > So this crashes in do_raw_spin_unlock_irqrestore() !?! I just have to > wonder how the raw_spin_lock() succeeded. That does not make any sense.
can you please apply the patch below on top of 4.12? It's a backport isolating the resource request changes.
Thanks,
tglx
8<---------------------- --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1198,6 +1198,18 @@ static int 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 */ @@ -1298,13 +1310,6 @@ static int } 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_mask; - } - init_waitqueue_head(&desc->wait_for_threads); /* Setup the type (level, edge polarity) if configured: */ @@ -1312,10 +1317,8 @@ static int ret = __irq_set_trigger(desc, new->flags & IRQF_TRIGGER_MASK); - if (ret) { - irq_release_resources(desc); + if (ret) goto out_mask; - } } desc->istate &= ~(IRQS_AUTODETECT | IRQS_SPURIOUS_DISABLED | \ @@ -1373,6 +1376,8 @@ static int } raw_spin_unlock_irqrestore(&desc->lock, flags); + chip_bus_sync_unlock(desc); + mutex_unlock(&desc->request_mutex); /* * Strictly no need to wake it up, but hung_task complains @@ -1402,6 +1407,13 @@ static int out_mask: 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); + free_cpumask_var(mask); out_thread: @@ -1443,9 +1455,7 @@ int setup_irq(unsigned int irq, struct i 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); @@ -1469,6 +1479,7 @@ static struct irqaction *__free_irq(unsi if (!desc) return NULL; + mutex_lock(&desc->request_mutex); chip_bus_lock(desc); raw_spin_lock_irqsave(&desc->lock, flags); @@ -1501,7 +1512,6 @@ static struct irqaction *__free_irq(unsi if (!desc->action) { irq_settings_clr_disable_unlazy(desc); irq_shutdown(desc); - irq_release_resources(desc); } #ifdef CONFIG_SMP @@ -1543,6 +1553,11 @@ static struct irqaction *__free_irq(unsi } } + if (!desc->action) + irq_release_resources(desc); + + mutex_unlock(&desc->request_mutex); + irq_chip_pm_put(&desc->irq_data); module_put(desc->owner); kfree(action->secondary); @@ -1699,9 +1714,7 @@ int request_threaded_irq(unsigned int ir 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); @@ -1949,9 +1962,7 @@ int setup_percpu_irq(unsigned int irq, s 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); @@ -2005,9 +2016,7 @@ int request_percpu_irq(unsigned int irq, 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); --- 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 * @name: flow handler name for /proc/interrupts output */ @@ -92,6 +94,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; --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c @@ -359,6 +359,7 @@ static struct irq_desc *alloc_desc(int i 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);
| |