diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2021-06-10 17:15:48 +0530 |
---|---|---|
committer | Viresh Kumar <viresh.kumar@linaro.org> | 2023-07-07 12:19:47 +0530 |
commit | 9d6d9675bb09d3b8af9e8d3b4cdb9387d28ee3bd (patch) | |
tree | 817ed05d7b5716a0ef9097573a8502cc63112721 | |
parent | ca6ef754ab816b09e47aed9d7229c7332455be45 (diff) |
test-irqxen/guest
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
-rw-r--r-- | drivers/gpio/gpio-virtio-test.c | 96 | ||||
-rw-r--r-- | drivers/gpio/gpio-virtio.c | 21 |
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; } |