aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2021-06-10 17:15:48 +0530
committerViresh Kumar <viresh.kumar@linaro.org>2023-07-07 12:19:47 +0530
commit9d6d9675bb09d3b8af9e8d3b4cdb9387d28ee3bd (patch)
tree817ed05d7b5716a0ef9097573a8502cc63112721
parentca6ef754ab816b09e47aed9d7229c7332455be45 (diff)
test-irqxen/guest
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r--drivers/gpio/gpio-virtio-test.c96
-rw-r--r--drivers/gpio/gpio-virtio.c21
2 files changed, 115 insertions, 2 deletions
diff --git a/drivers/gpio/gpio-virtio-test.c b/drivers/gpio/gpio-virtio-test.c
new file mode 100644
index 000000000000..5a6db64b39ad
--- /dev/null
+++ b/drivers/gpio/gpio-virtio-test.c
@@ -0,0 +1,96 @@
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+
+static struct completion completion;
+static irqreturn_t __maybe_unused TEST_irq_handler_empty(int irq, void *pw)
+{
+ pr_info("%s: %d: %d\n", __func__, __LINE__, irq);
+ complete(&completion);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t __maybe_unused TEST_irq_handler_disable(int irq, void *pw)
+{
+ pr_info("%s: %d: %d\n", __func__, __LINE__, irq);
+ complete(&completion);
+ disable_irq(irq);
+ return IRQ_HANDLED;
+}
+
+static void __maybe_unused TEST_my_request_irq(int gpio, void *handler, int flag)
+{
+ int ret;
+
+ pr_info("%s: %d: %d\n", __func__, __LINE__, gpio);
+ ret = gpio_request_one(gpio, GPIOF_DIR_IN, "test");
+ if (ret) {
+ pr_err("failed to request IRQ GPIO: %d\n", ret);
+ return;
+ }
+
+ ret = request_irq(gpio_to_irq(gpio), handler, flag, __func__, NULL);
+ if (ret != 0)
+ pr_err("failed to request ...: %d\n", ret);
+}
+
+static void __maybe_unused TEST_my_request_irq_threaded(int gpio, void *handler, int flag)
+{
+ int ret;
+
+ pr_info("%s: %d: %d\n", __func__, __LINE__, gpio);
+ ret = gpio_request_one(gpio, GPIOF_DIR_IN, "test");
+ if (ret) {
+ pr_err("failed to request IRQ GPIO: %d\n", ret);
+ return;
+ }
+
+ ret = request_threaded_irq(gpio_to_irq(gpio), NULL, handler, flag, __func__, NULL);
+ if (ret != 0)
+ pr_err("failed to request ...: %d\n", ret);
+}
+
+struct test_configuration {
+ void (*register_irq)(int gpio, void *handler, int flag);
+ irqreturn_t (*handler)(int irq, void *pw);
+ unsigned int flags;
+};
+
+static struct test_configuration tests[] = {
+ { TEST_my_request_irq, TEST_irq_handler_empty, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING },
+ { TEST_my_request_irq, TEST_irq_handler_empty, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT},
+// { TEST_my_request_irq, TEST_irq_handler_disable, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING },
+// { TEST_my_request_irq, TEST_irq_handler_disable, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT},
+ { TEST_my_request_irq_threaded, TEST_irq_handler_empty, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT},
+ { TEST_my_request_irq_threaded, TEST_irq_handler_disable, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT},
+
+// { TEST_my_request_irq, TEST_irq_handler_empty, IRQF_TRIGGER_LOW },
+// { TEST_my_request_irq, TEST_irq_handler_empty, IRQF_TRIGGER_LOW | IRQF_ONESHOT},
+//// { TEST_my_request_irq, TEST_irq_handler_disable, IRQF_TRIGGER_LOW },
+//// { TEST_my_request_irq, TEST_irq_handler_disable, IRQF_TRIGGER_LOW | IRQF_ONESHOT},
+// { TEST_my_request_irq_threaded, TEST_irq_handler_empty, IRQF_TRIGGER_LOW | IRQF_ONESHOT},
+// { TEST_my_request_irq_threaded, TEST_irq_handler_disable, IRQF_TRIGGER_LOW | IRQF_ONESHOT},
+};
+
+static void test_gpio(int base)
+{
+ struct test_configuration *test;
+ int i;
+
+ init_completion(&completion);
+
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ test = tests + i;
+ test->register_irq(base + i, test->handler, test->flags);
+ wait_for_completion(&completion);
+ pr_info("\n\n\n");
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tests); i++) {
+ test = tests + i;
+
+ if (test->handler == TEST_irq_handler_disable)
+ enable_irq(gpio_to_irq(base + i));
+ }
+
+ disable_irq(gpio_to_irq(base));
+}
diff --git a/drivers/gpio/gpio-virtio.c b/drivers/gpio/gpio-virtio.c
index fab515091963..b80300e3d3ca 100644
--- a/drivers/gpio/gpio-virtio.c
+++ b/drivers/gpio/gpio-virtio.c
@@ -225,6 +225,7 @@ static void virtio_gpio_irq_prepare(struct virtio_gpio *vgpio, u16 gpio)
sgs[0] = &req_sg;
sgs[1] = &res_sg;
+ pr_info("%s: %d: %d\n", __func__, __LINE__, gpio);
ret = virtqueue_add_sgs(vgpio->event_vq, sgs, 1, 1, irq_line, GFP_ATOMIC);
if (ret) {
dev_err(&vgpio->vdev->dev, "failed to add request to eventq\n");
@@ -241,6 +242,7 @@ static void virtio_gpio_irq_enable(struct irq_data *d)
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
+ pr_info("%s: %d: %lu\n", __func__, __LINE__, d->hwirq);
raw_spin_lock(&vgpio->eventq_lock);
irq_line->disabled = false;
irq_line->masked = false;
@@ -257,7 +259,9 @@ static void virtio_gpio_irq_disable(struct irq_data *d)
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
+ pr_info("%s: %d: %lu\n", __func__, __LINE__, d->hwirq);
raw_spin_lock(&vgpio->eventq_lock);
+
irq_line->disabled = true;
irq_line->masked = true;
irq_line->queue_pending = false;
@@ -273,6 +277,7 @@ static void virtio_gpio_irq_mask(struct irq_data *d)
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
+ pr_info("%s: %d: %lu\n", __func__, __LINE__, d->hwirq);
raw_spin_lock(&vgpio->eventq_lock);
irq_line->masked = true;
raw_spin_unlock(&vgpio->eventq_lock);
@@ -288,7 +293,8 @@ static void virtio_gpio_irq_unmask(struct irq_data *d)
raw_spin_lock(&vgpio->eventq_lock);
irq_line->masked = false;
- pr_info("%s: %d\n", __func__, __LINE__);
+ pr_info("%s: %d: %lu\n", __func__, __LINE__, d->hwirq);
+
/* Queue the buffer unconditionally on unmask */
virtio_gpio_irq_prepare(vgpio, d->hwirq);
raw_spin_unlock(&vgpio->eventq_lock);
@@ -300,6 +306,7 @@ static int virtio_gpio_irq_set_type(struct irq_data *d, unsigned int type)
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
struct vgpio_irq_line *irq_line = &vgpio->irq_lines[d->hwirq];
+ pr_info("%s: %d: %lu\n", __func__, __LINE__, d->hwirq);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
type = VIRTIO_GPIO_IRQ_TYPE_EDGE_RISING;
@@ -334,6 +341,7 @@ static void virtio_gpio_irq_bus_lock(struct irq_data *d)
struct virtio_gpio *vgpio = gpiochip_get_data(gc);
mutex_lock(&vgpio->irq_lock);
+ pr_info("%s: %d: %lu\n", __func__, __LINE__, d->hwirq);
}
static void virtio_gpio_irq_bus_sync_unlock(struct irq_data *d)
@@ -344,7 +352,9 @@ static void virtio_gpio_irq_bus_sync_unlock(struct irq_data *d)
u8 type = irq_line->disabled ? VIRTIO_GPIO_IRQ_TYPE_NONE : irq_line->type;
unsigned long flags;
- pr_info("%s: %d\n", __func__, __LINE__);
+ pr_info("%s: %d: %lu: %d: %d\n", __func__, __LINE__, d->hwirq,
+ irq_line->update_pending, irq_line->type);
+
if (irq_line->update_pending) {
irq_line->update_pending = false;
virtio_gpio_req(vgpio, VIRTIO_GPIO_MSG_IRQ_TYPE, d->hwirq, type,
@@ -442,6 +452,8 @@ static void virtio_gpio_event_vq(struct virtqueue *vq)
ret = generic_handle_domain_irq(vgpio->gc.irq.domain, gpio);
if (ret)
dev_err(dev, "failed to handle interrupt: %d\n", ret);
+
+ pr_info("IRQ finished %s: %d: %d\n", __func__, __LINE__, gpio);
}
}
@@ -549,6 +561,8 @@ static const char **virtio_gpio_get_names(struct virtio_gpio *vgpio,
return names;
}
+#include "gpio-virtio-test.c"
+
static int virtio_gpio_probe(struct virtio_device *vdev)
{
struct virtio_gpio_config config;
@@ -636,6 +650,9 @@ static int virtio_gpio_probe(struct virtio_device *vdev)
dev_err(dev, "Failed to add virtio-gpio controller\n");
}
+ if (virtio_has_feature(vdev, VIRTIO_GPIO_F_IRQ))
+ test_gpio(vgpio->gc.base);
+
return ret;
}