linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 0/3] simulated interrupts
@ 2017-08-14 14:53 Bartosz Golaszewski
  2017-08-14 14:53 ` [PATCH v4 1/3] irq/irq_sim: add a simple interrupt simulator framework Bartosz Golaszewski
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2017-08-14 14:53 UTC (permalink / raw)
  To: Linus Walleij, Thomas Gleixner, Marc Zyngier, Jonathan Corbet,
	Bamvor Jian Zhang, Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-kernel, linux-gpio, linux-doc, Bartosz Golaszewski

Some frameworks (e.g. iio, gpiolib) use irq_work to implement simulated
interrupts that can be 'fired' from process context when needed and
requested just like normal interrupts. This is useful for testing and
development purposes.

Currently this code is reimplemented by every user. This series
proposes to add a new set of functions that can be used by drivers
that want to simulate interrupts without having to duplicate any
boilerplate code.

The first patch adds a simple irq simulator framework. The second
extends it with resource management. The third uses the new
functionality in the gpio-mockup testing driver.

NOTE: The next candidate for using this API would be iio-dummy-evgen.

v1 -> v2:
- added a call to irq_work_sync in irq_sim_fini()

v2 -> v3:
- added the license header to new files
- added Acked-by's and Reviewed-by's

v3 -> v4:
- moved the .c file to kernel/irq

Bartosz Golaszewski (3):
  irq/irq_sim: add a simple interrupt simulator framework
  irq/irq_sim: add a devres variant of irq_sim_init()
  gpio: mockup: use irq_sim

 Documentation/driver-model/devres.txt |   1 +
 drivers/gpio/Kconfig                  |   2 +-
 drivers/gpio/gpio-mockup.c            |  77 ++--------------
 include/linux/irq_sim.h               |  48 ++++++++++
 kernel/irq/Kconfig                    |   5 ++
 kernel/irq/Makefile                   |   1 +
 kernel/irq/irq_sim.c                  | 164 ++++++++++++++++++++++++++++++++++
 7 files changed, 227 insertions(+), 71 deletions(-)
 create mode 100644 include/linux/irq_sim.h
 create mode 100644 kernel/irq/irq_sim.c

-- 
2.13.2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v4 1/3] irq/irq_sim: add a simple interrupt simulator framework
  2017-08-14 14:53 [PATCH v4 0/3] simulated interrupts Bartosz Golaszewski
@ 2017-08-14 14:53 ` Bartosz Golaszewski
  2017-08-16 14:46   ` [tip:irq/core] genirq/irq_sim: Add " tip-bot for Bartosz Golaszewski
  2017-08-14 14:53 ` [PATCH v4 2/3] irq/irq_sim: add a devres variant of irq_sim_init() Bartosz Golaszewski
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Bartosz Golaszewski @ 2017-08-14 14:53 UTC (permalink / raw)
  To: Linus Walleij, Thomas Gleixner, Marc Zyngier, Jonathan Corbet,
	Bamvor Jian Zhang, Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-kernel, linux-gpio, linux-doc, Bartosz Golaszewski

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 ++++++++++++++++++
 kernel/irq/Kconfig      |   5 ++
 kernel/irq/Makefile     |   1 +
 kernel/irq/irq_sim.c    | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 171 insertions(+)
 create mode 100644 include/linux/irq_sim.h
 create mode 100644 kernel/irq/irq_sim.c

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/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 27c4e774071c..1d06af787932 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -63,6 +63,11 @@ config GENERIC_IRQ_CHIP
 config IRQ_DOMAIN
 	bool
 
+# Support for simulated interrupts
+config IRQ_SIM
+	bool
+	select IRQ_WORK
+
 # Support for hierarchical irq domains
 config IRQ_DOMAIN_HIERARCHY
 	bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index e4aef7351f2b..1970cafe8f2a 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_IRQ_TIMINGS) += timings.o
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
+obj-$(CONFIG_IRQ_SIM) += irq_sim.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
new file mode 100644
index 000000000000..31a2c12a79ae
--- /dev/null
+++ b/kernel/irq/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);
-- 
2.13.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 2/3] irq/irq_sim: add a devres variant of irq_sim_init()
  2017-08-14 14:53 [PATCH v4 0/3] simulated interrupts Bartosz Golaszewski
  2017-08-14 14:53 ` [PATCH v4 1/3] irq/irq_sim: add a simple interrupt simulator framework Bartosz Golaszewski
@ 2017-08-14 14:53 ` Bartosz Golaszewski
  2017-08-16 14:46   ` [tip:irq/core] genirq/irq_sim: Add " tip-bot for Bartosz Golaszewski
  2017-08-14 14:53 ` [PATCH v4 3/3] gpio: mockup: use irq_sim Bartosz Golaszewski
  2017-08-16 14:44 ` [PATCH v4 0/3] simulated interrupts Thomas Gleixner
  3 siblings, 1 reply; 8+ messages in thread
From: Bartosz Golaszewski @ 2017-08-14 14:53 UTC (permalink / raw)
  To: Linus Walleij, Thomas Gleixner, Marc Zyngier, Jonathan Corbet,
	Bamvor Jian Zhang, Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-kernel, linux-gpio, linux-doc, Bartosz Golaszewski

Add a resource managed version of irq_sim_init(). This can be
conveniently used in device drivers.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
 Documentation/driver-model/devres.txt |  1 +
 include/linux/irq_sim.h               |  4 ++++
 kernel/irq/irq_sim.c                  | 43 +++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+)

diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 30e04f7a690d..69f08c0f23a8 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -312,6 +312,7 @@ IRQ
   devm_irq_alloc_descs_from()
   devm_irq_alloc_generic_chip()
   devm_irq_setup_generic_chip()
+  devm_irq_sim_init()
 
 LED
   devm_led_classdev_register()
diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h
index 9ee1a4f8bd94..9ad634fcc662 100644
--- a/include/linux/irq_sim.h
+++ b/include/linux/irq_sim.h
@@ -11,6 +11,7 @@
 #define _LINUX_IRQ_SIM_H
 
 #include <linux/irq_work.h>
+#include <linux/device.h>
 
 /*
  * Provides a framework for allocating simulated interrupts which can be
@@ -37,6 +38,9 @@ struct irq_sim {
 int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs);
 void irq_sim_fini(struct irq_sim *sim);
 
+int devm_irq_sim_init(struct device *dev,
+		      struct irq_sim *sim, unsigned int num_irqs);
+
 void irq_sim_fire(struct irq_sim *sim, unsigned int offset);
 
 int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset);
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
index 31a2c12a79ae..3daa10d62a27 100644
--- a/kernel/irq/irq_sim.c
+++ b/kernel/irq/irq_sim.c
@@ -92,6 +92,49 @@ void irq_sim_fini(struct irq_sim *sim)
 }
 EXPORT_SYMBOL_GPL(irq_sim_fini);
 
+struct irq_sim_devres {
+	struct irq_sim *sim;
+};
+
+static void devm_irq_sim_release(struct device *dev, void *res)
+{
+	struct irq_sim_devres *this = res;
+
+	irq_sim_fini(this->sim);
+}
+
+/**
+ * irq_sim_init - Initialize the interrupt simulator for a managed device.
+ *
+ * @dev:        Device to initialize the simulator object for.
+ * @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 devm_irq_sim_init(struct device *dev,
+		      struct irq_sim *sim, unsigned int num_irqs)
+{
+	struct irq_sim_devres *dr;
+	int rv;
+
+	dr = devres_alloc(devm_irq_sim_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	rv = irq_sim_init(sim, num_irqs);
+	if (rv) {
+		devres_free(dr);
+		return rv;
+	}
+
+	dr->sim = sim;
+	devres_add(dev, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_irq_sim_init);
+
 /**
  * irq_sim_fire - Enqueue an interrupt.
  *
-- 
2.13.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v4 3/3] gpio: mockup: use irq_sim
  2017-08-14 14:53 [PATCH v4 0/3] simulated interrupts Bartosz Golaszewski
  2017-08-14 14:53 ` [PATCH v4 1/3] irq/irq_sim: add a simple interrupt simulator framework Bartosz Golaszewski
  2017-08-14 14:53 ` [PATCH v4 2/3] irq/irq_sim: add a devres variant of irq_sim_init() Bartosz Golaszewski
@ 2017-08-14 14:53 ` Bartosz Golaszewski
  2017-08-16 14:44 ` [PATCH v4 0/3] simulated interrupts Thomas Gleixner
  3 siblings, 0 replies; 8+ messages in thread
From: Bartosz Golaszewski @ 2017-08-14 14:53 UTC (permalink / raw)
  To: Linus Walleij, Thomas Gleixner, Marc Zyngier, Jonathan Corbet,
	Bamvor Jian Zhang, Jonathan Cameron, Lars-Peter Clausen
  Cc: linux-kernel, linux-gpio, linux-doc, Bartosz Golaszewski

Shrink the driver by removing the code dealing with dummy interrupts
and replacing it with calls to the irq_sim API.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/gpio/Kconfig       |  2 +-
 drivers/gpio/gpio-mockup.c | 77 +++++-----------------------------------------
 2 files changed, 8 insertions(+), 71 deletions(-)

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 461d6fc3688b..f858faa5731a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -311,7 +311,7 @@ config GPIO_MOCKUP
 	depends on GPIOLIB && SYSFS
 	select GPIO_SYSFS
 	select GPIOLIB_IRQCHIP
-	select IRQ_WORK
+	select IRQ_SIM
 	help
 	  This enables GPIO Testing driver, which provides a way to test GPIO
 	  subsystem through sysfs(or char device) and debugfs. GPIO_SYSFS
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index a6565e128f9e..6db7163e6d98 100644
--- a/drivers/gpio/gpio-mockup.c
+++ b/drivers/gpio/gpio-mockup.c
@@ -20,7 +20,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/irq_work.h>
+#include <linux/irq_sim.h>
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 
@@ -47,18 +47,12 @@ enum {
 struct gpio_mockup_line_status {
 	int dir;
 	bool value;
-	bool irq_enabled;
-};
-
-struct gpio_mockup_irq_context {
-	struct irq_work work;
-	int irq;
 };
 
 struct gpio_mockup_chip {
 	struct gpio_chip gc;
 	struct gpio_mockup_line_status *lines;
-	struct gpio_mockup_irq_context irq_ctx;
+	struct irq_sim irqsim;
 	struct dentry *dbg_dir;
 };
 
@@ -144,65 +138,11 @@ static int gpio_mockup_name_lines(struct device *dev,
 	return 0;
 }
 
-static int gpio_mockup_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	return chip->irq_base + offset;
-}
-
-static void gpio_mockup_irqmask(struct irq_data *data)
+static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset)
 {
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
 	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
 
-	chip->lines[data->irq - gc->irq_base].irq_enabled = false;
-}
-
-static void gpio_mockup_irqunmask(struct irq_data *data)
-{
-	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
-	struct gpio_mockup_chip *chip = gpiochip_get_data(gc);
-
-	chip->lines[data->irq - gc->irq_base].irq_enabled = true;
-}
-
-static struct irq_chip gpio_mockup_irqchip = {
-	.name		= GPIO_MOCKUP_NAME,
-	.irq_mask	= gpio_mockup_irqmask,
-	.irq_unmask	= gpio_mockup_irqunmask,
-};
-
-static void gpio_mockup_handle_irq(struct irq_work *work)
-{
-	struct gpio_mockup_irq_context *irq_ctx;
-
-	irq_ctx = container_of(work, struct gpio_mockup_irq_context, work);
-	handle_simple_irq(irq_to_desc(irq_ctx->irq));
-}
-
-static int gpio_mockup_irqchip_setup(struct device *dev,
-				     struct gpio_mockup_chip *chip)
-{
-	struct gpio_chip *gc = &chip->gc;
-	int irq_base, i;
-
-	irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0);
-	if (irq_base < 0)
-		return irq_base;
-
-	gc->irq_base = irq_base;
-	gc->irqchip = &gpio_mockup_irqchip;
-
-	for (i = 0; i < gc->ngpio; i++) {
-		irq_set_chip(irq_base + i, gc->irqchip);
-		irq_set_chip_data(irq_base + i, gc);
-		irq_set_handler(irq_base + i, &handle_simple_irq);
-		irq_modify_status(irq_base + i,
-				  IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
-	}
-
-	init_irq_work(&chip->irq_ctx.work, gpio_mockup_handle_irq);
-
-	return 0;
+	return irq_sim_irqnum(&chip->irqsim, offset);
 }
 
 static ssize_t gpio_mockup_event_write(struct file *file,
@@ -228,11 +168,8 @@ static ssize_t gpio_mockup_event_write(struct file *file,
 	chip = priv->chip;
 	gc = &chip->gc;
 
-	if (chip->lines[priv->offset].irq_enabled) {
-		gpiod_set_value_cansleep(desc, val);
-		priv->chip->irq_ctx.irq = gc->irq_base + priv->offset;
-		irq_work_queue(&priv->chip->irq_ctx.work);
-	}
+	gpiod_set_value_cansleep(desc, val);
+	irq_sim_fire(&chip->irqsim, priv->offset);
 
 	return size;
 }
@@ -319,7 +256,7 @@ static int gpio_mockup_add(struct device *dev,
 			return ret;
 	}
 
-	ret = gpio_mockup_irqchip_setup(dev, chip);
+	ret = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio);
 	if (ret)
 		return ret;
 
-- 
2.13.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 0/3] simulated interrupts
  2017-08-14 14:53 [PATCH v4 0/3] simulated interrupts Bartosz Golaszewski
                   ` (2 preceding siblings ...)
  2017-08-14 14:53 ` [PATCH v4 3/3] gpio: mockup: use irq_sim Bartosz Golaszewski
@ 2017-08-16 14:44 ` Thomas Gleixner
  2017-08-20 22:11   ` Linus Walleij
  3 siblings, 1 reply; 8+ messages in thread
From: Thomas Gleixner @ 2017-08-16 14:44 UTC (permalink / raw)
  To: Bartosz Golaszewski
  Cc: Linus Walleij, Marc Zyngier, Jonathan Corbet, Bamvor Jian Zhang,
	Jonathan Cameron, Lars-Peter Clausen, linux-kernel, linux-gpio,
	linux-doc

On Mon, 14 Aug 2017, Bartosz Golaszewski wrote:

> Some frameworks (e.g. iio, gpiolib) use irq_work to implement simulated
> interrupts that can be 'fired' from process context when needed and
> requested just like normal interrupts. This is useful for testing and
> development purposes.
> 
> Currently this code is reimplemented by every user. This series
> proposes to add a new set of functions that can be used by drivers
> that want to simulate interrupts without having to duplicate any
> boilerplate code.
> 
> The first patch adds a simple irq simulator framework. The second
> extends it with resource management. The third uses the new
> functionality in the gpio-mockup testing driver.

I merged the irq part (1+2) into a separate branch, which can be consumed
by the gpio folks so the mockup driver patch can be merged as well.

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

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [tip:irq/core] genirq/irq_sim: Add a simple interrupt simulator framework
  2017-08-14 14:53 ` [PATCH v4 1/3] irq/irq_sim: add a simple interrupt simulator framework Bartosz Golaszewski
@ 2017-08-16 14:46   ` tip-bot for Bartosz Golaszewski
  0 siblings, 0 replies; 8+ messages in thread
From: tip-bot for Bartosz Golaszewski @ 2017-08-16 14:46 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: mingo, Jonathan.Cameron, hpa, corbet, linus.walleij, lars, brgl,
	jic23, linux-kernel, tglx, marc.zyngier, bamvor.zhangjian

Commit-ID:  b19af510e67e6ca696b8721f45c148119437307c
Gitweb:     http://git.kernel.org/tip/b19af510e67e6ca696b8721f45c148119437307c
Author:     Bartosz Golaszewski <brgl@bgdev.pl>
AuthorDate: Mon, 14 Aug 2017 16:53:16 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 16 Aug 2017 16:40:02 +0200

genirq/irq_sim: Add a simple interrupt simulator framework

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>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-doc@vger.kernel.org
Cc: linux-gpio@vger.kernel.org
Cc: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
Cc: Jonathan Cameron <jic23@kernel.org>
Link: http://lkml.kernel.org/r/20170814145318.6495-2-brgl@bgdev.pl
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/irq_sim.h |  41 ++++++++++++++++
 kernel/irq/Kconfig      |   5 ++
 kernel/irq/Makefile     |   1 +
 kernel/irq/irq_sim.c    | 121 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 168 insertions(+)

diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h
new file mode 100644
index 0000000..39ce57b
--- /dev/null
+++ b/include/linux/irq_sim.h
@@ -0,0 +1,41 @@
+#ifndef _LINUX_IRQ_SIM_H
+#define _LINUX_IRQ_SIM_H
+/*
+ * 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_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/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 27c4e77..1d06af7 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -63,6 +63,11 @@ config GENERIC_IRQ_CHIP
 config IRQ_DOMAIN
 	bool
 
+# Support for simulated interrupts
+config IRQ_SIM
+	bool
+	select IRQ_WORK
+
 # Support for hierarchical irq domains
 config IRQ_DOMAIN_HIERARCHY
 	bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index e4aef73..1970caf 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_IRQ_TIMINGS) += timings.o
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
+obj-$(CONFIG_IRQ_SIM) += irq_sim.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
new file mode 100644
index 0000000..31a2c12
--- /dev/null
+++ b/kernel/irq/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);

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [tip:irq/core] genirq/irq_sim: Add a devres variant of irq_sim_init()
  2017-08-14 14:53 ` [PATCH v4 2/3] irq/irq_sim: add a devres variant of irq_sim_init() Bartosz Golaszewski
@ 2017-08-16 14:46   ` tip-bot for Bartosz Golaszewski
  0 siblings, 0 replies; 8+ messages in thread
From: tip-bot for Bartosz Golaszewski @ 2017-08-16 14:46 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: brgl, bamvor.zhangjian, lars, marc.zyngier, hpa, linus.walleij,
	linux-kernel, corbet, jic23, Jonathan.Cameron, mingo, tglx

Commit-ID:  44e72c7ebf294043cfe276f7328b8c0e6a3e50e9
Gitweb:     http://git.kernel.org/tip/44e72c7ebf294043cfe276f7328b8c0e6a3e50e9
Author:     Bartosz Golaszewski <brgl@bgdev.pl>
AuthorDate: Mon, 14 Aug 2017 16:53:17 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Wed, 16 Aug 2017 16:40:02 +0200

genirq/irq_sim: Add a devres variant of irq_sim_init()

Add a resource managed version of irq_sim_init(). This can be
conveniently used in device drivers.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Cc: Lars-Peter Clausen <lars@metafoo.de>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: linux-doc@vger.kernel.org
Cc: linux-gpio@vger.kernel.org
Cc: Bamvor Jian Zhang <bamvor.zhangjian@linaro.org>
Cc: Jonathan Cameron <jic23@kernel.org>
Link: http://lkml.kernel.org/r/20170814145318.6495-3-brgl@bgdev.pl
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 Documentation/driver-model/devres.txt |  1 +
 include/linux/irq_sim.h               |  3 +++
 kernel/irq/irq_sim.c                  | 43 +++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 30e04f7..69f08c0 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -312,6 +312,7 @@ IRQ
   devm_irq_alloc_descs_from()
   devm_irq_alloc_generic_chip()
   devm_irq_setup_generic_chip()
+  devm_irq_sim_init()
 
 LED
   devm_led_classdev_register()
diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h
index 39ce57b..0380d89 100644
--- a/include/linux/irq_sim.h
+++ b/include/linux/irq_sim.h
@@ -10,6 +10,7 @@
  */
 
 #include <linux/irq_work.h>
+#include <linux/device.h>
 
 /*
  * Provides a framework for allocating simulated interrupts which can be
@@ -34,6 +35,8 @@ struct irq_sim {
 };
 
 int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs);
+int devm_irq_sim_init(struct device *dev, 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);
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
index 31a2c12..24caabf 100644
--- a/kernel/irq/irq_sim.c
+++ b/kernel/irq/irq_sim.c
@@ -10,6 +10,10 @@
 #include <linux/irq_sim.h>
 #include <linux/irq.h>
 
+struct irq_sim_devres {
+	struct irq_sim		*sim;
+};
+
 static void irq_sim_irqmask(struct irq_data *data)
 {
 	struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
@@ -92,6 +96,45 @@ void irq_sim_fini(struct irq_sim *sim)
 }
 EXPORT_SYMBOL_GPL(irq_sim_fini);
 
+static void devm_irq_sim_release(struct device *dev, void *res)
+{
+	struct irq_sim_devres *this = res;
+
+	irq_sim_fini(this->sim);
+}
+
+/**
+ * irq_sim_init - Initialize the interrupt simulator for a managed device.
+ *
+ * @dev:        Device to initialize the simulator object for.
+ * @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 devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
+		      unsigned int num_irqs)
+{
+	struct irq_sim_devres *dr;
+	int rv;
+
+	dr = devres_alloc(devm_irq_sim_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	rv = irq_sim_init(sim, num_irqs);
+	if (rv) {
+		devres_free(dr);
+		return rv;
+	}
+
+	dr->sim = sim;
+	devres_add(dev, dr);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(devm_irq_sim_init);
+
 /**
  * irq_sim_fire - Enqueue an interrupt.
  *

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v4 0/3] simulated interrupts
  2017-08-16 14:44 ` [PATCH v4 0/3] simulated interrupts Thomas Gleixner
@ 2017-08-20 22:11   ` Linus Walleij
  0 siblings, 0 replies; 8+ messages in thread
From: Linus Walleij @ 2017-08-20 22:11 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Bartosz Golaszewski, Marc Zyngier, Jonathan Corbet,
	Bamvor Jian Zhang, Jonathan Cameron, Lars-Peter Clausen,
	linux-kernel, linux-gpio, linux-doc

On Wed, Aug 16, 2017 at 4:44 PM, Thomas Gleixner <tglx@linutronix.de> wrote:

> I merged the irq part (1+2) into a separate branch, which can be consumed
> by the gpio folks so the mockup driver patch can be merged as well.
>
>    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/for-gpio

Awesome, thanks Thomas. I pulled this into the GPIO devel branch.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-08-20 22:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-14 14:53 [PATCH v4 0/3] simulated interrupts Bartosz Golaszewski
2017-08-14 14:53 ` [PATCH v4 1/3] irq/irq_sim: add a simple interrupt simulator framework Bartosz Golaszewski
2017-08-16 14:46   ` [tip:irq/core] genirq/irq_sim: Add " tip-bot for Bartosz Golaszewski
2017-08-14 14:53 ` [PATCH v4 2/3] irq/irq_sim: add a devres variant of irq_sim_init() Bartosz Golaszewski
2017-08-16 14:46   ` [tip:irq/core] genirq/irq_sim: Add " tip-bot for Bartosz Golaszewski
2017-08-14 14:53 ` [PATCH v4 3/3] gpio: mockup: use irq_sim Bartosz Golaszewski
2017-08-16 14:44 ` [PATCH v4 0/3] simulated interrupts Thomas Gleixner
2017-08-20 22:11   ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).