如何从IRQ范围内的非单片内核模块进行软重启?

mou*_*oul 2 linux kernel reboot irq linux-kernel

我需要重新启动处理内核中的IRQ.

我想调用/sbin/reboot二进制文件,但由于IRQ范围,我有限制.

代码如下:

#define MY_IRQ_ID       42

void __init             rebootmodule_init(void) {
    request_any_context_irq(MY_IRQ_ID, rebootmodule_irq_handler, IRQF_TRIGGER_FALLING, "irq-name", NULL);
}

irqreturn_t             rebootmodule_irq_handler(int irq, void *dev_id) {
    my_reboot();
    return IRQ_HANDLED;
}

void                    my_reboot(void) {
    int                 ret;
    char                *argv[2], *envp[4];

    argv[0] = "/sbin/reboot";
    argv[1] = NULL;
    envp[0] = "HOME=/";
    envp[1] = "PWD=/";
    envp[2] = "PATH=/sbin";
    envp[3] = NULL;
    ret = call_usermodehelper(argv[0], argv, envp, 0);
    printk(KERN_INFO "trying to reboot (ret = %d)", ret);
}
Run Code Online (Sandbox Code Playgroud)

我可以看到printk(...)IRQ被触发的时间,但是我有一些错误,即使我替换/sbin/reboot/bin/rm /tmp/its-not-working.

我测试了其他办法可以做到像重启mvBoardReset(),machine_halt(),arm_pm_restart(),pm_power_off(),kill(1, SIGTSTP),reboot(),handle_sysrq('b'),我总是说我没有IRQ范围之外的错误.

我真的很想打电话/sbin/reboot,因为它确实可以清除软复位.

感谢您的时间.

pra*_*oid 5

只是一个想法:你可以启动内核线程kthread_run(),让它睡眠wait_event(),在IRQ处理程序中唤醒它,在内核线程中wake_up()执行你的东西(运行/sbin/reboot或任何你想要的).像这样的东西(完全未经测试):

#define MY_IRQ_ID 42

static DECLARE_WAIT_QUEUE_HEAD(wq);
static volatile int showtime = 0;

void my_reboot(void) {
    int ret;
    char *argv[2], *envp[4];

    argv[0] = "/sbin/reboot";
    argv[1] = NULL;
    envp[0] = "HOME=/";
    envp[1] = "PWD=/";
    envp[2] = "PATH=/sbin";
    envp[3] = NULL;
    ret = call_usermodehelper(argv[0], argv, envp, 0);
    printk(KERN_INFO "trying to reboot (ret = %d)", ret);
}

static int my_thread(void *arg) {
    wait_event(&wq, showtime);
    my_reboot();
    return 0;
}

irqreturn_t rebootmodule_irq_handler(int irq, void *dev_id) {
    showtime = 1;
    wake_up(&wq);
    return IRQ_HANDLED;
}

void __init rebootmodule_init(void) {
    kthread_run(my_thread, NULL, "my_module");
    request_any_context_irq(MY_IRQ_ID, rebootmodule_irq_handler, IRQF_TRIGGER_FALLING, "irq-name", NULL);
}
Run Code Online (Sandbox Code Playgroud)

不要忘记在内核线程被发送到睡眠之前__exit中断时处理模块和情况.