Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: "The usual pile of boring changes: - Consolidate tasklet functions to share code instead of duplicating it - The first step for making the low level entry handler management on multi-platform kernels generic - A new sysfs file which allows to retrieve the wakeup state of interrupts. - Ensure that the interrupt thread follows the effective affinity and not the programmed affinity to avoid cross core wakeups. - Two new interrupt controller drivers (Microsemi Ocelot and Qualcomm PDC) - Fix the wakeup path clock handling for Reneasas interrupt chips. - Rework the boot time register reset for ARM GIC-V2/3 - Better suspend/resume support for ARM GIV-V3/ITS - Add missing locking to the ARM GIC set_type() callback - Small fixes for the irq simulator code - SPDX identifiers for the irq core code and removal of boiler plate - Small cleanups all over the place" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (37 commits) openrisc: Set CONFIG_MULTI_IRQ_HANDLER arm64: Set CONFIG_MULTI_IRQ_HANDLER genirq: Make GENERIC_IRQ_MULTI_HANDLER depend on !MULTI_IRQ_HANDLER irqchip/gic: Take lock when updating irq type irqchip/gic: Update supports_deactivate static key to modern api irqchip/gic-v3: Ensure GICR_CTLR.EnableLPI=0 is observed before enabling irqchip: Add a driver for the Microsemi Ocelot controller dt-bindings: interrupt-controller: Add binding for the Microsemi Ocelot interrupt controller irqchip/gic-v3: Probe for SCR_EL3 being clear before resetting AP0Rn irqchip/gic-v3: Don't try to reset AP0Rn irqchip/gic-v3: Do not check trigger configuration of partitionned LPIs genirq: Remove license boilerplate/references genirq: Add missing SPDX identifiers genirq/matrix: Cleanup SPDX identifier genirq: Cleanup top of file comments genirq: Pass desc to __irq_free instead of irq number irqchip/gic-v3: Loudly complain about the use of IRQ_TYPE_NONE irqchip/gic: Loudly complain about the use of IRQ_TYPE_NONE RISC-V: Move to the new GENERIC_IRQ_MULTI_HANDLER handler genirq: Add CONFIG_GENERIC_IRQ_MULTI_HANDLER ...
This commit is contained in:
@@ -132,3 +132,9 @@ config GENERIC_IRQ_DEBUGFS
|
||||
If you don't know what to do here, say N.
|
||||
|
||||
endmenu
|
||||
|
||||
config GENERIC_IRQ_MULTI_HANDLER
|
||||
depends on !MULTI_IRQ_HANDLER
|
||||
bool
|
||||
help
|
||||
Allow to specify the low level IRQ handler at run time.
|
||||
|
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/autoprobe.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
|
||||
*
|
||||
* This file contains the interrupt probing code and driver APIs.
|
||||
|
@@ -1,13 +1,11 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/chip.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
|
||||
* Copyright (C) 2005-2006, Thomas Gleixner, Russell King
|
||||
*
|
||||
* This file contains the core interrupt handling code, for irq-chip
|
||||
* based architectures.
|
||||
*
|
||||
* Detailed information is available in Documentation/core-api/genericirq.rst
|
||||
* This file contains the core interrupt handling code, for irq-chip based
|
||||
* architectures. Detailed information is available in
|
||||
* Documentation/core-api/genericirq.rst
|
||||
*/
|
||||
|
||||
#include <linux/irq.h>
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Generic cpu hotunplug interrupt migration code copied from the
|
||||
* arch/arm implementation
|
||||
|
@@ -1,8 +1,6 @@
|
||||
/*
|
||||
* Copyright 2017 Thomas Gleixner <tglx@linutronix.de>
|
||||
*
|
||||
* This file is licensed under the GPL V2.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright 2017 Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/module.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
|
||||
* Copyright (C) 2005-2006, Thomas Gleixner, Russell King
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Library implementing the most common irq chip callback functions
|
||||
*
|
||||
|
@@ -1,12 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/handle.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
|
||||
* Copyright (C) 2005-2006, Thomas Gleixner, Russell King
|
||||
*
|
||||
* This file contains the core interrupt handling code.
|
||||
*
|
||||
* Detailed information is available in Documentation/core-api/genericirq.rst
|
||||
* This file contains the core interrupt handling code. Detailed
|
||||
* information is available in Documentation/core-api/genericirq.rst
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -20,6 +18,10 @@
|
||||
|
||||
#include "internals.h"
|
||||
|
||||
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
|
||||
void (*handle_arch_irq)(struct pt_regs *) __ro_after_init;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* handle_bad_irq - handle spurious and unhandled irqs
|
||||
* @desc: description of the interrupt
|
||||
@@ -207,3 +209,14 @@ irqreturn_t handle_irq_event(struct irq_desc *desc)
|
||||
irqd_clear(&desc->irq_data, IRQD_IRQ_INPROGRESS);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
|
||||
int __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
|
||||
{
|
||||
if (handle_arch_irq)
|
||||
return -EBUSY;
|
||||
|
||||
handle_arch_irq = handle_irq;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/ipi.c
|
||||
*
|
||||
* Copyright (C) 2015 Imagination Technologies Ltd
|
||||
* Author: Qais Yousef <qais.yousef@imgtec.com>
|
||||
*
|
||||
|
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
|
||||
*
|
||||
@@ -7,6 +8,7 @@
|
||||
* option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/irq_sim.h>
|
||||
#include <linux/irq.h>
|
||||
|
||||
@@ -49,7 +51,8 @@ static void irq_sim_handle_irq(struct irq_work *work)
|
||||
* @sim: The interrupt simulator object to initialize.
|
||||
* @num_irqs: Number of interrupts to allocate
|
||||
*
|
||||
* Returns 0 on success and a negative error number on failure.
|
||||
* On success: return the base of the allocated interrupt range.
|
||||
* On failure: a negative errno.
|
||||
*/
|
||||
int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)
|
||||
{
|
||||
@@ -78,7 +81,7 @@ int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)
|
||||
init_irq_work(&sim->work_ctx.work, irq_sim_handle_irq);
|
||||
sim->irq_count = num_irqs;
|
||||
|
||||
return 0;
|
||||
return sim->irq_base;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_sim_init);
|
||||
|
||||
@@ -110,7 +113,8 @@ static void devm_irq_sim_release(struct device *dev, void *res)
|
||||
* @sim: The interrupt simulator object to initialize.
|
||||
* @num_irqs: Number of interrupts to allocate
|
||||
*
|
||||
* Returns 0 on success and a negative error number on failure.
|
||||
* On success: return the base of the allocated interrupt range.
|
||||
* On failure: a negative errno.
|
||||
*/
|
||||
int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
|
||||
unsigned int num_irqs)
|
||||
@@ -123,7 +127,7 @@ int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
|
||||
return -ENOMEM;
|
||||
|
||||
rv = irq_sim_init(sim, num_irqs);
|
||||
if (rv) {
|
||||
if (rv < 0) {
|
||||
devres_free(dr);
|
||||
return rv;
|
||||
}
|
||||
@@ -131,7 +135,7 @@ int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
|
||||
dr->sim = sim;
|
||||
devres_add(dev, dr);
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_irq_sim_init);
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
|
||||
* Copyright (C) 2005-2006, Thomas Gleixner, Russell King
|
||||
*
|
||||
* This file contains the interrupt descriptor management code
|
||||
*
|
||||
* Detailed information is available in Documentation/core-api/genericirq.rst
|
||||
* This file contains the interrupt descriptor management code. Detailed
|
||||
* information is available in Documentation/core-api/genericirq.rst
|
||||
*
|
||||
*/
|
||||
#include <linux/irq.h>
|
||||
@@ -210,6 +210,22 @@ static ssize_t type_show(struct kobject *kobj,
|
||||
}
|
||||
IRQ_ATTR_RO(type);
|
||||
|
||||
static ssize_t wakeup_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct irq_desc *desc = container_of(kobj, struct irq_desc, kobj);
|
||||
ssize_t ret = 0;
|
||||
|
||||
raw_spin_lock_irq(&desc->lock);
|
||||
ret = sprintf(buf, "%s\n",
|
||||
irqd_is_wakeup_set(&desc->irq_data) ? "enabled" : "disabled");
|
||||
raw_spin_unlock_irq(&desc->lock);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
IRQ_ATTR_RO(wakeup);
|
||||
|
||||
static ssize_t name_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -253,6 +269,7 @@ static struct attribute *irq_attrs[] = {
|
||||
&chip_name_attr.attr,
|
||||
&hwirq_attr.attr,
|
||||
&type_attr.attr,
|
||||
&wakeup_attr.attr,
|
||||
&name_attr.attr,
|
||||
&actions_attr.attr,
|
||||
NULL
|
||||
|
@@ -1,3 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
#define pr_fmt(fmt) "irq: " fmt
|
||||
|
||||
#include <linux/acpi.h>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/manage.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
|
||||
* Copyright (C) 2005-2006 Thomas Gleixner
|
||||
*
|
||||
@@ -855,10 +854,14 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
|
||||
* This code is triggered unconditionally. Check the affinity
|
||||
* mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
|
||||
*/
|
||||
if (cpumask_available(desc->irq_common_data.affinity))
|
||||
cpumask_copy(mask, desc->irq_common_data.affinity);
|
||||
else
|
||||
if (cpumask_available(desc->irq_common_data.affinity)) {
|
||||
const struct cpumask *m;
|
||||
|
||||
m = irq_data_get_effective_affinity_mask(&desc->irq_data);
|
||||
cpumask_copy(mask, m);
|
||||
} else {
|
||||
valid = false;
|
||||
}
|
||||
raw_spin_unlock_irq(&desc->lock);
|
||||
|
||||
if (valid)
|
||||
@@ -1519,9 +1522,9 @@ EXPORT_SYMBOL_GPL(setup_irq);
|
||||
* Internal function to unregister an irqaction - used to free
|
||||
* regular and special interrupts that are part of the architecture.
|
||||
*/
|
||||
static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
|
||||
static struct irqaction *__free_irq(struct irq_desc *desc, void *dev_id)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
unsigned irq = desc->irq_data.irq;
|
||||
struct irqaction *action, **action_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -1651,7 +1654,7 @@ void remove_irq(unsigned int irq, struct irqaction *act)
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))
|
||||
__free_irq(irq, act->dev_id);
|
||||
__free_irq(desc, act->dev_id);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(remove_irq);
|
||||
|
||||
@@ -1685,7 +1688,7 @@ const void *free_irq(unsigned int irq, void *dev_id)
|
||||
desc->affinity_notify = NULL;
|
||||
#endif
|
||||
|
||||
action = __free_irq(irq, dev_id);
|
||||
action = __free_irq(desc, dev_id);
|
||||
|
||||
if (!action)
|
||||
return NULL;
|
||||
|
@@ -1,8 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Thomas Gleixner <tglx@linutronix.de>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2017 Thomas Gleixner <tglx@linutronix.de>
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/bitmap.h>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/msi.c
|
||||
*
|
||||
* Copyright (C) 2014 Intel Corp.
|
||||
* Author: Jiang Liu <jiang.liu@linux.intel.com>
|
||||
*
|
||||
|
@@ -1,6 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/pm.c
|
||||
*
|
||||
* Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
|
||||
*
|
||||
* This file contains power management functions related to interrupts.
|
||||
|
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/proc.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
|
||||
*
|
||||
* This file contains the /proc/irq/ handling code.
|
||||
|
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/resend.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar
|
||||
* Copyright (C) 2005-2006, Thomas Gleixner
|
||||
*
|
||||
|
@@ -1,7 +1,5 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* linux/kernel/irq/spurious.c
|
||||
*
|
||||
* Copyright (C) 1992, 1998-2004 Linus Torvalds, Ingo Molnar
|
||||
*
|
||||
* This file contains spurious interrupt handling.
|
||||
|
@@ -1,13 +1,6 @@
|
||||
/*
|
||||
* linux/kernel/irq/timings.c
|
||||
*
|
||||
* Copyright (C) 2016, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
// Copyright (C) 2016, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/slab.h>
|
||||
|
@@ -460,40 +460,46 @@ struct tasklet_head {
|
||||
static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec);
|
||||
static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec);
|
||||
|
||||
void __tasklet_schedule(struct tasklet_struct *t)
|
||||
static void __tasklet_schedule_common(struct tasklet_struct *t,
|
||||
struct tasklet_head __percpu *headp,
|
||||
unsigned int softirq_nr)
|
||||
{
|
||||
struct tasklet_head *head;
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
head = this_cpu_ptr(headp);
|
||||
t->next = NULL;
|
||||
*__this_cpu_read(tasklet_vec.tail) = t;
|
||||
__this_cpu_write(tasklet_vec.tail, &(t->next));
|
||||
raise_softirq_irqoff(TASKLET_SOFTIRQ);
|
||||
*head->tail = t;
|
||||
head->tail = &(t->next);
|
||||
raise_softirq_irqoff(softirq_nr);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
void __tasklet_schedule(struct tasklet_struct *t)
|
||||
{
|
||||
__tasklet_schedule_common(t, &tasklet_vec,
|
||||
TASKLET_SOFTIRQ);
|
||||
}
|
||||
EXPORT_SYMBOL(__tasklet_schedule);
|
||||
|
||||
void __tasklet_hi_schedule(struct tasklet_struct *t)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
t->next = NULL;
|
||||
*__this_cpu_read(tasklet_hi_vec.tail) = t;
|
||||
__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
|
||||
raise_softirq_irqoff(HI_SOFTIRQ);
|
||||
local_irq_restore(flags);
|
||||
__tasklet_schedule_common(t, &tasklet_hi_vec,
|
||||
HI_SOFTIRQ);
|
||||
}
|
||||
EXPORT_SYMBOL(__tasklet_hi_schedule);
|
||||
|
||||
static __latent_entropy void tasklet_action(struct softirq_action *a)
|
||||
static void tasklet_action_common(struct softirq_action *a,
|
||||
struct tasklet_head *tl_head,
|
||||
unsigned int softirq_nr)
|
||||
{
|
||||
struct tasklet_struct *list;
|
||||
|
||||
local_irq_disable();
|
||||
list = __this_cpu_read(tasklet_vec.head);
|
||||
__this_cpu_write(tasklet_vec.head, NULL);
|
||||
__this_cpu_write(tasklet_vec.tail, this_cpu_ptr(&tasklet_vec.head));
|
||||
list = tl_head->head;
|
||||
tl_head->head = NULL;
|
||||
tl_head->tail = &tl_head->head;
|
||||
local_irq_enable();
|
||||
|
||||
while (list) {
|
||||
@@ -515,47 +521,21 @@ static __latent_entropy void tasklet_action(struct softirq_action *a)
|
||||
|
||||
local_irq_disable();
|
||||
t->next = NULL;
|
||||
*__this_cpu_read(tasklet_vec.tail) = t;
|
||||
__this_cpu_write(tasklet_vec.tail, &(t->next));
|
||||
__raise_softirq_irqoff(TASKLET_SOFTIRQ);
|
||||
*tl_head->tail = t;
|
||||
tl_head->tail = &t->next;
|
||||
__raise_softirq_irqoff(softirq_nr);
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static __latent_entropy void tasklet_action(struct softirq_action *a)
|
||||
{
|
||||
tasklet_action_common(a, this_cpu_ptr(&tasklet_vec), TASKLET_SOFTIRQ);
|
||||
}
|
||||
|
||||
static __latent_entropy void tasklet_hi_action(struct softirq_action *a)
|
||||
{
|
||||
struct tasklet_struct *list;
|
||||
|
||||
local_irq_disable();
|
||||
list = __this_cpu_read(tasklet_hi_vec.head);
|
||||
__this_cpu_write(tasklet_hi_vec.head, NULL);
|
||||
__this_cpu_write(tasklet_hi_vec.tail, this_cpu_ptr(&tasklet_hi_vec.head));
|
||||
local_irq_enable();
|
||||
|
||||
while (list) {
|
||||
struct tasklet_struct *t = list;
|
||||
|
||||
list = list->next;
|
||||
|
||||
if (tasklet_trylock(t)) {
|
||||
if (!atomic_read(&t->count)) {
|
||||
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
|
||||
&t->state))
|
||||
BUG();
|
||||
t->func(t->data);
|
||||
tasklet_unlock(t);
|
||||
continue;
|
||||
}
|
||||
tasklet_unlock(t);
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
t->next = NULL;
|
||||
*__this_cpu_read(tasklet_hi_vec.tail) = t;
|
||||
__this_cpu_write(tasklet_hi_vec.tail, &(t->next));
|
||||
__raise_softirq_irqoff(HI_SOFTIRQ);
|
||||
local_irq_enable();
|
||||
}
|
||||
tasklet_action_common(a, this_cpu_ptr(&tasklet_hi_vec), HI_SOFTIRQ);
|
||||
}
|
||||
|
||||
void tasklet_init(struct tasklet_struct *t,
|
||||
|
Reference in New Issue
Block a user