critical section 中断唤醒系统流程(11)

电脑杂谈  发布时间:2018-02-14 08:19:38  来源:网络整理

static void gpio_keys_gpio_work_func(struct work_struct *work)

{

struct gpio_button_data *bdata =

container_of(work, struct gpio_button_data, work.work);

gpio_keys_gpio_report_event(bdata);

if (bdata->button->wakeup)

pm_relax(bdata->input->dev.parent);

}

static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)

{

struct gpio_button_data *bdata = dev_id;

if (bdata->button->wakeup) {

const struct gpio_keys_button *button = bdata->button;

pm_stay_awake(bdata->input->dev.parent);

}

mod_delayed_work(system_wq,

&bdata->work,

msecs_to_jiffies(bdata->software_debounce));

return IRQ_HANDLED;

}

好了,现在你放心好了,即使你是在gpio_keys_gpio_work_func()中msleep(2000),系统也会等到pm_relax()执行之后才系统才可能suspend。

3. 驱动工程师建议

看了这么多代码总是想说点东西。不管是建议还是什么。我由衷地希望驱动工程师可以写出完美没有bug并且简介的代码。因此,这里有点小建议给驱动工程师(某些特性可能需要比较新的内核版本)。

1)如果设备具有唤醒系统的功能,请在probe函数中调用device_init_wakeup()和dev_pm_set_wake_irq()(注意调用顺序,先device_init_wakeup()再dev_pm_set_wake_irq())。毕竟这样系统suspend的时候会自动帮助我们enable_irq_wake()和disable_irq_wake(),何乐而不为呢!简单就是美。如果你是i2c设备,那么可以更完美。连probe函数里面也可以不用调用了。只需要在设备的dts中添加wakeup-source属性即可。i2c core会自动帮我们完成这些操作。

2)如果你习惯在driver的suspend()中关闭中断,在resum()中打开中断,我觉你你没必要这么做,何必要这些冗余代码呢!

3)既然dts现在这么流行了,你又何必不用呢!设备dts中的interrupts属性都会指明中断触发type,那你就用嘛!怎么获取这个flag呢?irqd_get_trigger_type()可以通过dts获取irq的触发type。所以request_threaded_irq()的第四个参数irqflags可以使用irqd_get_trigger_type()获得。如果你的内核版本更新的话,还可以更简单,irqflags传入0即可,在request_threaded_irq()中会自动帮我们调用irqd_get_trigger_type()获取。当然了,我也看聪明的IC厂家提供的driver,在dts中自定义一个属性表明irqflags,在driver中获取。我只能猜测driver的编写者不知道irqd_get_trigger_type()接口吧!

4)如果中断下半部使用工作队列,请成对使用pm_stay_awake()和pm_relax()。否则,谁也无法保证系统不会再一次的睡眠。


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-77052-11.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...