Message ID | 20170814112056.3751-2-brgl@bgdev.pl |
---|---|
State | New |
Headers | show |
On Mon, 14 Aug 2017, Bartosz Golaszewski wrote: > Implement a simple, irq_work-based framework for simulating > interrupts. Currently the API exposes routines for initializing and > deinitializing the simulator object, enqueueing the interrupts and > retrieving the allocated interrupt numbers based on the offset of the > dummy interrupt in the simulator struct. > > Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> > Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> > --- > include/linux/irq_sim.h | 44 ++++++++++++++++++ > init/Kconfig | 4 ++ > kernel/Makefile | 1 + > kernel/irq_sim.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ Please move this to kernel/irq/ ... and the config option to kernel/irq/Kconfig. Thanks, tglx -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
2017-08-14 15:06 GMT+02:00 Thomas Gleixner <tglx@linutronix.de>: > On Mon, 14 Aug 2017, Bartosz Golaszewski wrote: > >> Implement a simple, irq_work-based framework for simulating >> interrupts. Currently the API exposes routines for initializing and >> deinitializing the simulator object, enqueueing the interrupts and >> retrieving the allocated interrupt numbers based on the offset of the >> dummy interrupt in the simulator struct. >> >> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> >> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> >> --- >> include/linux/irq_sim.h | 44 ++++++++++++++++++ >> init/Kconfig | 4 ++ >> kernel/Makefile | 1 + >> kernel/irq_sim.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ > > Please move this to kernel/irq/ ... and the config option to kernel/irq/Kconfig. > > Thanks, > > tglx > > How about moving irq_work.c there too? Best regards, Bartosz Golaszewski -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 14 Aug 2017, Bartosz Golaszewski wrote: > 2017-08-14 15:06 GMT+02:00 Thomas Gleixner <tglx@linutronix.de>: > > On Mon, 14 Aug 2017, Bartosz Golaszewski wrote: > > > >> Implement a simple, irq_work-based framework for simulating > >> interrupts. Currently the API exposes routines for initializing and > >> deinitializing the simulator object, enqueueing the interrupts and > >> retrieving the allocated interrupt numbers based on the offset of the > >> dummy interrupt in the simulator struct. > >> > >> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> > >> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> > >> --- > >> include/linux/irq_sim.h | 44 ++++++++++++++++++ > >> init/Kconfig | 4 ++ > >> kernel/Makefile | 1 + > >> kernel/irq_sim.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ > > > > Please move this to kernel/irq/ ... and the config option to kernel/irq/Kconfig. > > > > Thanks, > > > > tglx > > > > > > How about moving irq_work.c there too? We could, but irq_work is not really part of the interrupt subsystem, while your interrupt simulator definitely is. Thanks, tglx -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
2017-08-14 16:48 GMT+02:00 Thomas Gleixner <tglx@linutronix.de>: > On Mon, 14 Aug 2017, Bartosz Golaszewski wrote: >> 2017-08-14 15:06 GMT+02:00 Thomas Gleixner <tglx@linutronix.de>: >> > On Mon, 14 Aug 2017, Bartosz Golaszewski wrote: >> > >> >> Implement a simple, irq_work-based framework for simulating >> >> interrupts. Currently the API exposes routines for initializing and >> >> deinitializing the simulator object, enqueueing the interrupts and >> >> retrieving the allocated interrupt numbers based on the offset of the >> >> dummy interrupt in the simulator struct. >> >> >> >> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl> >> >> Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> >> >> --- >> >> include/linux/irq_sim.h | 44 ++++++++++++++++++ >> >> init/Kconfig | 4 ++ >> >> kernel/Makefile | 1 + >> >> kernel/irq_sim.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ >> > >> > Please move this to kernel/irq/ ... and the config option to kernel/irq/Kconfig. >> > >> > Thanks, >> > >> > tglx >> > >> > >> >> How about moving irq_work.c there too? > > We could, but irq_work is not really part of the interrupt subsystem, while > your interrupt simulator definitely is. > Fair enough, let's leave it where it is. I'll send v4. Thanks, Bartosz -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h new file mode 100644 index 000000000000..9ee1a4f8bd94 --- /dev/null +++ b/include/linux/irq_sim.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef _LINUX_IRQ_SIM_H +#define _LINUX_IRQ_SIM_H + +#include <linux/irq_work.h> + +/* + * Provides a framework for allocating simulated interrupts which can be + * requested like normal irqs and enqueued from process context. + */ + +struct irq_sim_work_ctx { + struct irq_work work; + int irq; +}; + +struct irq_sim_irq_ctx { + int irqnum; + bool enabled; +}; + +struct irq_sim { + struct irq_sim_work_ctx work_ctx; + int irq_base; + unsigned int irq_count; + struct irq_sim_irq_ctx *irqs; +}; + +int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs); +void irq_sim_fini(struct irq_sim *sim); + +void irq_sim_fire(struct irq_sim *sim, unsigned int offset); + +int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset); + +#endif /* _LINUX_IRQ_SIM_H */ diff --git a/init/Kconfig b/init/Kconfig index 8514b25db21c..220456599c3f 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -23,6 +23,10 @@ config CONSTRUCTORS config IRQ_WORK bool +config IRQ_SIM + bool + select IRQ_WORK + config BUILDTIME_EXTABLE_SORT bool diff --git a/kernel/Makefile b/kernel/Makefile index 4cb8e8b23c6e..4472567c5835 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -97,6 +97,7 @@ obj-$(CONFIG_TRACE_CLOCK) += trace/ obj-$(CONFIG_RING_BUFFER) += trace/ obj-$(CONFIG_TRACEPOINTS) += trace/ obj-$(CONFIG_IRQ_WORK) += irq_work.o +obj-$(CONFIG_IRQ_SIM) += irq_sim.o obj-$(CONFIG_CPU_PM) += cpu_pm.o obj-$(CONFIG_BPF) += bpf/ diff --git a/kernel/irq_sim.c b/kernel/irq_sim.c new file mode 100644 index 000000000000..31a2c12a79ae --- /dev/null +++ b/kernel/irq_sim.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/irq_sim.h> +#include <linux/irq.h> + +static void irq_sim_irqmask(struct irq_data *data) +{ + struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data); + + irq_ctx->enabled = false; +} + +static void irq_sim_irqunmask(struct irq_data *data) +{ + struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data); + + irq_ctx->enabled = true; +} + +static struct irq_chip irq_sim_irqchip = { + .name = "irq_sim", + .irq_mask = irq_sim_irqmask, + .irq_unmask = irq_sim_irqunmask, +}; + +static void irq_sim_handle_irq(struct irq_work *work) +{ + struct irq_sim_work_ctx *work_ctx; + + work_ctx = container_of(work, struct irq_sim_work_ctx, work); + handle_simple_irq(irq_to_desc(work_ctx->irq)); +} + +/** + * irq_sim_init - Initialize the interrupt simulator: allocate a range of + * dummy interrupts. + * + * @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. + */ +int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs) +{ + int i; + + sim->irqs = kmalloc_array(num_irqs, sizeof(*sim->irqs), GFP_KERNEL); + if (!sim->irqs) + return -ENOMEM; + + sim->irq_base = irq_alloc_descs(-1, 0, num_irqs, 0); + if (sim->irq_base < 0) { + kfree(sim->irqs); + return sim->irq_base; + } + + for (i = 0; i < num_irqs; i++) { + sim->irqs[i].irqnum = sim->irq_base + i; + sim->irqs[i].enabled = false; + irq_set_chip(sim->irq_base + i, &irq_sim_irqchip); + irq_set_chip_data(sim->irq_base + i, &sim->irqs[i]); + irq_set_handler(sim->irq_base + i, &handle_simple_irq); + irq_modify_status(sim->irq_base + i, + IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); + } + + init_irq_work(&sim->work_ctx.work, irq_sim_handle_irq); + sim->irq_count = num_irqs; + + return 0; +} +EXPORT_SYMBOL_GPL(irq_sim_init); + +/** + * irq_sim_fini - Deinitialize the interrupt simulator: free the interrupt + * descriptors and allocated memory. + * + * @sim: The interrupt simulator to tear down. + */ +void irq_sim_fini(struct irq_sim *sim) +{ + irq_work_sync(&sim->work_ctx.work); + irq_free_descs(sim->irq_base, sim->irq_count); + kfree(sim->irqs); +} +EXPORT_SYMBOL_GPL(irq_sim_fini); + +/** + * irq_sim_fire - Enqueue an interrupt. + * + * @sim: The interrupt simulator object. + * @offset: Offset of the simulated interrupt which should be fired. + */ +void irq_sim_fire(struct irq_sim *sim, unsigned int offset) +{ + if (sim->irqs[offset].enabled) { + sim->work_ctx.irq = irq_sim_irqnum(sim, offset); + irq_work_queue(&sim->work_ctx.work); + } +} +EXPORT_SYMBOL_GPL(irq_sim_fire); + +/** + * irq_sim_irqnum - Get the allocated number of a dummy interrupt. + * + * @sim: The interrupt simulator object. + * @offset: Offset of the simulated interrupt for which to retrieve + * the number. + */ +int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset) +{ + return sim->irqs[offset].irqnum; +} +EXPORT_SYMBOL_GPL(irq_sim_irqnum);