"Godbille, Clement via Xenomai" <xenomai@xenomai.org> writes:

> Dear support team members,
>
> I successfully installed the EVL core (v5.10.59) on a Raspberry pi 4 with a 
> 64 bits OS, along the EVL library. EVL tests ran smoothly and I was able to 
> use its timers and witness improvements in my application for clocks and 
> cyclic time.
>
> I am now trying to turn an existing driver (amba UART pl011) into an OOB 
> capable driver for the same application. In the open method associated with 
> this driver,  I called the evl_open_file, evl_init_wait and 
> evl_init_poll_head methods to initialize my oob-related structure following 
> what is done in the GPIO OOB capable driver provided by EVL.
>
> For  now I am just trying to add to its interruption the IRQF_OOB flag. It 
> seems that my interruption actually becomes out-of-band compatible as the 
> "oob" flag appears when I look into the /proc/interrupts file.
>
> However I don't know what I am missing in my driver initialization, for as 
> soon as the driver must handle an interrupt the OS blocks indefinitely. It 
> also blocks when I remove all code in the IRQ handler with return 
> IRQ_HANDLED, but not when I return IRQ_NONE. In that case the kernel returns 
> the message "out-of-band irq: stuck or unexpected", which is an expected 
> behaviour.
>
> I didn't change much in the original driver so far, I didn't even create 
> oob_read, oob_write or oob_ioctl methods yet, as I suppose those steps come 
> afterwards. I only created an oob_poll method which would deal with events 
> received in my interruption.
>
> I am asking you if it seems to you that I am not correctly using EVL. I must 
> also admit that this is my very first experience with kernel development so I 
> may also make inappropriate changes to my driver unrelated to EVL.
>

If you tell the interrupt pipeline to deliver the interrupt to the oob
stage to an empty handler, it won't run any code acknowledging the event
device-wise, which usually ends up badly as one would expect. If the
original in-band code is executed by such handler over the oob stage,
things will go south as well.

Once the pipeline is enabled in the kernel, you may consider that any
device IRQ is a NMI in disguise, and we cannot run common services over
NMI context because the event might preempt almost anywhere, regardless
of locks and irq-free sections. There is a way to prevent this locally,
but this is the idea.

irq_post_inband(<irq>) [1] can be used to mark some <irq> as pending in
the in-band log, so that the attached handler in called from the in-band
stage at some point later.

e.g. say that the following handler is attached to some irq, which your
code requests with IRQF_OOB set:

static irqreturn_t irq_handler(int irq, void *data)
{
        if (running_oob()) { /* called first from the oob stage because of 
IRQF_OOB */
             irq_post_inband(irq); /* now, schedule a call from in-band */
        } else {
           /* getting there as a result of earlier irq_post_inband() */
        }
}

In a nutshell, all IRQs which are not marked IRQF_OOB get posted to the
in-band stage and always run from there. This context is synchronized
with the rest of the common kernel activities, so it is ok to call the
in-band kernel infrastructure for handling the event.

IRQs which bear the IRQF_OOB flag are first delivered over the oob stage
to the very same handler, not serialized with these common
activities. Next, that handler might decide to propagate this event to
the lower stage (using irq_post_inband()) if need be.

This is usually not wanted, with the device-related handling performed
on the oob stage directly, typically using some service from the EVL
kernel API. This said, in some device-specific cases like dealing with
multiple DMAs channels with different latency requirements, one may have
to deal with events selectively either from the in-band or oob context,
depending on their actual source [2].

bottom-line: the code which is currently used by the PL011 driver to
deal with interrupts cannot be traversed from the oob context "as
is". Accessing the hw from either stages is ok, but calling the common
in-band services is not. A typical example is the code path framed by
CONFIG_RAW_PRINTK in the amba driver you mentioned, which is part of the
Dovetail code. That code is fine to run over oob or in-band context
indifferently, because it serializes appropriately for this, and makes
sure not to tread on unsafe paths.

A good starting point is reading [3][4] if you did not already.

[1] https://evlproject.org/dovetail/pipeline/pipeline_inject/
[2] https://evlproject.org/core/oob-drivers/dma/
[3] https://evlproject.org/dovetail/pipeline/
[4] https://evlproject.org/dovetail/porting/irqflow/

-- 
Philippe.

Reply via email to