________________________________
From: Greg Gallagher <[email protected]>
Sent: Monday, July 13, 2020 3:43 PM
To: Josh Karch <[email protected]>
Cc: [email protected] <[email protected]>
Subject: Re: xeno-gpio-xilinx causes gpio-xilinx's IRQ 
callback(xgpio_irqhandler) to trigger rather than gpio-core's 
"gpio_pin_interrupt"

Hi Josh,


On Mon., Jul. 13, 2020, 6:37 p.m. Josh Karch via Xenomai 
<[email protected]<mailto:[email protected]>> wrote:
Hi,

With the CAN bus issues resolved, I now have a situation where the 
xeno-gpio-xilinx driver (gpio-core.c) causes a complete system lockup when IRQs 
are enabled and a GPIO toggle triggers the IRQ event.

Here's what I know:  I instrumented the NRT driver to see how deeply entrenched 
and intertwined the real-time and non real-time drivers are:

(1) xeno-gpio-xilinx calls gpio-core which piggybacks upon the Xilinx 
"gpio-xilinx" driver.
(2)It uses the OF scan information to create /dev/rtdm/gpio@address/gpioxxx 
driver pins.

When enabling interrupts:
(1)It uses the  NRT "Xgpio-request" function to request a gpio pin and set the 
pin to an input, though for some reason it calls the set gpio as input function 
twice
(2) It then calls xgpio-toirq twice for some reason
(3) It sets the IRQ type.  Only the rising edge IRQ is supported with the 
Xilinx Driver
(4) It uses the unmask function in the non RT driver to unmask the IRQ
(5) It then sets the gpio as input again. I think this is a side effect of 
calling the IOCTL to enable IRQ and then to block file descriptors on interrupt.
(6) Once the interrupt is triggered, on occasion the Non realtime 
xgpio_irqhandler gets called rather than the gpio_pin_interrupt function.  This 
makes me think the NRT driver is not properly setting the interrupt up to work 
with the Xenomai handler.  Once the non realtime xgpio_irqhandler gets called 
the code gets stuck in an infinite loop and crashes.

Sometimes the system freezes before using the handler, other times it runs the 
handler but it's not possible to break.

The following is a transcript of a time when the nrt handler is not called.    
Otherwise you'd see a message when IRQ is triggered that the system continually 
is in a nrt IRQ handler loop.

So the question is: why is the non-rt handler being called and not the 
gpio-core rt_gpio "gpio-pin-interrupt"?


[  303.900487] requesting GPIO
[  303.903419] setting gpio 0 as input
[  303.907004] setting gpio 0 as input
[  303.910549] called xgpio to irq
[  303.913768] called xgpio to irq
[  303.916913] setting irq type 1
[  303.919990] unmasking IRQ
[  303.922600] setting gpio 0 as input
[  324.917162] rcu: INFO: rcu_sched detected stalls on CPUs/tasks:
[  324.923100] rcu:     0-...0: (1 ticks this GP) idle=66e/1/0x4000000000000000
softirq=8388/8389 fqs=2247
[  324.932321] rcu:     (detected by 3, t=5252 jiffies, g=12713, q=188)
[  324.938411] Task dump for CPU 0:
[  324.941629] xeno_gpio_teste R  running task        0   433    388 0x00000202
[  324.948682] Call trace:
[  324.951126]  __switch_to+0x94/0xf0
[  324.954522]  0xffffff8008dea658

Best,

Josh Karch

Do you have have the gic and the IRQ handlers in place for the xilinx-gpio 
xenomai driver?  The current implementation doesn't support interrupts.

Thanks

Greg


Hi Greg, so the only changes between the "gpio-core.c"  from stock Xenomai and 
the driver I'm working with is the section of code which adds dual-channel 
functionality to the Xilinx driver in "rtdm_gpiochip_scan_of."  These are the 
functions in gpio-core.  It seems there are a lot of functions in gpio-core 
dealing with interrupts.  The Xilinx stock driver provided by Xilinx has 
interrupt functions in there.  What else is missing?

Best,

Josh

static int gpio_pin_interrupt(rtdm_irq_t *irqh)
{
struct rtdm_gpio_pin *pin;
pin = rtdm_irq_get_arg(irqh, struct rtdm_gpio_pin);
pin->timestamp = rtdm_clock_read_monotonic();
rtdm_event_signal(&pin->event);
return RTDM_IRQ_HANDLED;
}
static int request_gpio_irq(unsigned int gpio, struct rtdm_gpio_pin *pin,
struct rtdm_gpio_chan *chan,
int trigger)
{
int ret, irq_trigger, irq;
if (trigger & ~GPIO_TRIGGER_MASK)
return -EINVAL;
if (!chan->requested) {
ret = gpio_request(gpio, pin->name);
if (ret) {
if (ret != -EPROBE_DEFER)
printk(XENO_ERR
"can not request GPIO%d\n", gpio);
return ret;
}
chan->requested = true;
}
ret = gpio_direction_input(gpio);
if (ret) {
printk(XENO_ERR "cannot set GPIO%d as input\n", gpio);
goto fail;
}
chan->has_direction = true;
gpio_export(gpio, true);
rtdm_event_clear(&pin->event);
/*
* Attempt to hook the interrupt associated to that pin. We
* might fail getting a valid IRQ number, in case the GPIO
* chip did not define any mapping handler (->to_irq). If so,
* just assume that either we have no IRQ indeed, or interrupt
* handling may be open coded elsewhere.
*/
irq = gpio_to_irq(gpio);
if (irq < 0)
goto done;
irq_trigger = 0;
if (trigger & GPIO_TRIGGER_EDGE_RISING)
irq_trigger |= IRQ_TYPE_EDGE_RISING;
if (trigger & GPIO_TRIGGER_EDGE_FALLING)
irq_trigger |= IRQ_TYPE_EDGE_FALLING;
if (trigger & GPIO_TRIGGER_LEVEL_HIGH)
irq_trigger |= IRQ_TYPE_LEVEL_HIGH;
if (trigger & GPIO_TRIGGER_LEVEL_LOW)
irq_trigger |= IRQ_TYPE_LEVEL_LOW;
if (irq_trigger)
irq_set_irq_type(irq, irq_trigger);
ret = rtdm_irq_request(&pin->irqh, irq, gpio_pin_interrupt,
0, pin->name, pin);
if (ret) {
printk(XENO_ERR "cannot request GPIO%d interrupt\n", gpio);
goto fail;
}
rtdm_irq_enable(&pin->irqh);
done:
chan->is_interrupt = true;
return 0;
fail:
gpio_free(gpio);
chan->requested = false;
return ret;
}













Reply via email to