[RESEND RFC PATCH 0/2] Expose the PIO_ISR register on SAMA5D3

Linus Walleij linus.walleij at linaro.org
Tue Dec 22 00:44:29 PST 2015


On Fri, Dec 18, 2015 at 12:19 AM, Peter Rosin <peda at axentia.se> wrote:

> This all makes sense. The reason is that I'm not familiar with
> the kernel APIs. I have to wrap my head around how to set up
> work to be performed later, etc etc.

FWIW a random work to be performed later is a delayed work.
It can be queued on a global workqueue or you can create your
own workqueue. This is the latter way, it's even simpler if you
just use NULL as workqueue, it will then end up on the big
system workqueue. The workqueue in turn uses deferrable timers,
and these can also be used directly.

#include <linux/workqueue.h>

struct foo {
   struct workqueue_struct *foo_wq;
   struct delayed_work delayed_foo_work;
   ....
};

static void foo_work_cb(struct work_struct *work)
{
        struct foo *foo = container_of(work, struct foo, delayed_foo_work.work);

        ... do the work ...
};

main {
   INIT_DEFERRABLE_WORK(&foo->delayed_foo_work, foo_work_cb);
   queue_delayed_work(foo->foo_wq, &foo->delayed_foo_work, 6*HZ);
}

6*HZ means wait for 6 seconds as the delay is given in ticks (jiffies)
and the system does HZ ticks per second.

>> > I have realized that I could work with one-shot-interrupts. Then the
>> > urgency to disable interrupts go away, as only one interrupt would
>> > be served. That was not my immediate solution though, as I have been
>> > using isr type registers in this way several times before.
>>
>> That sounds like the right solution. With ONESHOT a threaded IRQ
>> will have its line masked until you return from the ISR thread. Would this
>> work for your usecase?
>
> The ISR thread would need to be able to disable further interrupts
> before it returned, is that possible without deadlock? If so, it's
> a good fit.

Yes that is what the ONESHOT flag means. So like this:

ret = request_threaded_irq(irqnum, NULL, foo_irq_handler,
                                   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                   "foo", foo);

To register a threaded oneshot IRQ that will run on a falling edge,
as a thread, until completed, masking its own interrupt line, but
no others.

The threaded handler can msleep(), mdelay()/udelay() etc since it
is a thread. usleep_range(a, b) is the best as the system can idle
while that happens, and can plan for a good wakeup point.

Yours,
Linus Walleij



More information about the linux-arm-kernel mailing list