4

I am implementing an interrupt handling module using thread irq. I am facing this error:

1983.150961] Shut down eMMC app module init.
[ 1983.151115] genirq: Flags mismatch irq 49. 00000004 (eMMC_power_shutdown_irq_
handler) vs. 00000004 (xuartps)
fio@uz3cg-dgw:~$ (edited) 

I am choosing a Flag is #define IRQF_TRIGGER_HIGH 0x00000004 and assign to IRQ number 49 in this case.

Here is my code:

static int __init shutdownemmc_module_init(void)
{
    printk("Shut down eMMC app module init. ");
    if (request_threaded_irq( IRQ_NO,                       //IRQ number
                            (void *) emmc_irq_handler,      //IRQ handler (Top half)
                            emmc_interrupt_thread_fn,       //IRQ Thread handler (Bottom half).When the handler function returns IRQ_WAKE_THREAD
                            IRQF_TRIGGER_HIGH,                    //Handler will be called in raising edge
                            "eMMC_power_shutdown_irq_handler",    //used to identify the device name using this IRQ
                            (void *)(emmc_irq_handler)))    //device id for shared IRQ
    {
        pr_err("Cannot register IRQ ");
        pr_err(" EIO %d , EINVAL %d\n", EIO, EINVAL);
        return 0;
    }
    pr_info("Interrupt handler...Done!!!\n");
    return 0;
}

Could somebody explain what is Flags mismatch irq issue and how I can fix this problem? Thank you, Anh

Anh Hoang
  • 117
  • 4
  • 10

1 Answers1

3

It is because "xuartps" has already requested the IRQ number and did not request it to be shared.

Extracts from __setup_irq() in "kernel/irq/manage.c":

        /*
         * If nobody did set the configuration before, inherit
         * the one provided by the requester.
         */
        if (irqd_trigger_type_was_set(&desc->irq_data)) {
            oldtype = irqd_get_trigger_type(&desc->irq_data);
        } else {
            oldtype = new->flags & IRQF_TRIGGER_MASK;
            irqd_set_trigger_type(&desc->irq_data, oldtype);
        }

        if (!((old->flags & new->flags) & IRQF_SHARED) ||
            (oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
            ((old->flags ^ new->flags) & IRQF_ONESHOT))
            goto mismatch;

In the above, old is the existing handler set up by "xuartps". new is the new handler being set up by your code. In order for the IRQ to be shared, one of the conditions above is that both the old and the new handlers need to request the IRQ with the IRQF_SHARED flag. However, drivers should only set IRQF_SHARED if the underlying interrupt is supposed to be shareable; for example: all PCI interrupts are shareable and drivers for PCI devices should request interrupts with IRQF_SHARED set.

mismatch:
    if (!(new->flags & IRQF_PROBE_SHARED)) {
        pr_err("Flags mismatch irq %d. %08x (%s) vs. %08x (%s)\n",
               irq, new->flags, new->name, old->flags, old->name);
#ifdef CONFIG_DEBUG_SHIRQ
        dump_stack();
#endif
    }
    ret = -EBUSY;

The above is where the "Flags mismatch" message is printed to the kernel log.

If you were not expecting the IRQ to be already requested, check that you are requesting the correct IRQ.

Ian Abbott
  • 15,083
  • 19
  • 33