Welcome to the Linux Foundation Forum!

Trying to fix suspend on kernel 4.19.325 - fix kernel panic caused by while loop

IsHacker
IsHacker Posts: 1
edited 9:06AM in Kernel Development

Hi,
I have a device running kernel 4.19.325, and it keeps waking up from suspend right after entering it (and in dmesg it says "Resume cause unknown"). So, I am trying to force it to stay in suspend until it receives an IRQ (which is what should actually wake it up). I have added this inside suspend_test function in kernel/power/suspend.c:

#ifdef CONFIG_ISHSLEEP_SUSPEND
#ifndef CONFIG_PM_DEBUG
    int pm_test_level = TEST_CORE;
    if (pm_test_level == level) {
        while (true) {
            if (ishacker_system_irq_wakeup_actual_get())
                break;
        }
        return 1;
    }
#endif /* CONFIG_PM_DEBUG */
#endif /* CONFIG_ISHSLEEP_SUSPEND */

So the complete function looks like this:

static int suspend_test(int level)
{
#ifdef CONFIG_PM_DEBUG
    if (pm_test_level == level) {
        pr_info("suspend debug: Waiting for %d second(s).\n",
                pm_test_delay);
        mdelay(pm_test_delay * 1000);
        return 1;
    }
#endif /* !CONFIG_PM_DEBUG */
#ifdef CONFIG_ISHSLEEP_SUSPEND
#ifndef CONFIG_PM_DEBUG
    int pm_test_level = TEST_CORE;
    if (pm_test_level == level) {
        while (true) {
            if (ishacker_system_irq_wakeup_actual_get())
                break;
        }
        return 1;
    }
#endif /* CONFIG_PM_DEBUG */
#endif /* CONFIG_ISHSLEEP_SUSPEND */
    return 0;
}

CONFIG_ISHSLEEP_SUSPEND is enabled in the defconfig, and ishacker_system_irq_wakeup_actual_get() returns the value of bool ishacker_system_irq_wakeup_actual, which is set to true inside pm_system_irq_wakeup function in drivers/base/power/wakeup.c:

void pm_system_irq_wakeup(unsigned int irq_number)
{
    if (pm_wakeup_irq == 0) {
        struct irq_desc *desc;
        const char *name = "null";

        desc = irq_to_desc(irq_number);
        if (desc == NULL)
            name = "stray irq";
        else if (desc->action && desc->action->name)
            name = desc->action->name;

        log_irq_wakeup_reason(irq_number);
#ifdef CONFIG_ISHSLEEP_SUSPEND
        ishacker_system_irq_wakeup_actual = true;
#endif
        pr_warn("%s: %d triggered %s\n", __func__, irq_number, name);

        pm_wakeup_irq = irq_number;
        pm_system_wakeup();
    }
}

ishacker_system_irq_wakeup_actual is set to false again (using a function) in the pm_suspend function (in kernel/power/suspend.c):

pr_info("suspend entry (%s)\n", mem_sleep_labels[state]);
#ifdef CONFIG_ISHSLEEP_SUSPEND
    ishacker_system_irq_wakeup_actual_set(false);
#endif

I am using these functions because I can't export the variables through my header file without running into duplicate symbol errors during linking, and I don't want to use extern. The functions and bools are defined in drivers/base/power/wakeup.c, they are nothing special:

#ifdef CONFIG_ISHSLEEP_SUSPEND
bool ishacker_system_irq_wakeup_actual = false;

bool ishacker_system_irq_wakeup_actual_get(void) {
    return ishacker_system_irq_wakeup_actual;
}

void ishacker_system_irq_wakeup_actual_set(bool val) {
    ishacker_system_irq_wakeup_actual = val;
}
#endif

The problem is that the kernel panics and the device reboots when I put it to suspend, and when I check /sys/fs/pstore there are no console-ramoopss (which means I can't get the panic log). Also, I noticed that if I use mdelay(5000) instead of that while loop just like in CONFIG_PM_DEBUG's suspend test mode, the device DOES stay in suspend for those 5 seconds, and then it wakes up. There is no kernel panic. But during these 5 seconds, I also cannot wake it up using the power button (which sends the IRQ), and I want it to stay in suspend UNTIL it receives an IRQ, not just for a fixed number of seconds (which is why I need a while loop).

So, I want to know what exactly is causing the panic, and how to fix it. I'm fairly new to C, so please be patient and forgive me if its some stupid mistake I did with e.g the while loop (lol).

Thanks

Categories

Upcoming Training