Linux Kernel threaded irq

1.How-to

request_threaded_irq()
{
action->handler = handler;
action->thread_fn = thread_fn;
->__setup_irq()
{
/*
* Create a handler thread when a thread function is supplied
* and the interrupt does not nest into another interrupt
* thread.
*/
if (new->thread_fn && !nested) {
struct task_struct *t;


t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
  new->name);

adb shell ps -P -p
可以看到创建的 irq thread:
USER     PID   PPID  VSIZE  RSS   PRIO  NICE  RTPRI SCHED  PCY  WCHAN    PC        NAME
root      57    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/102-msm_iom
root      58    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/102-msm_iom
root      59    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/102-msm_iom
root      60    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/79-msm_iomm
root      61    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/78-msm_iomm
root      62    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/78-msm_iomm
root      63    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/74-msm_iomm
root      64    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/75-msm_iomm
root      65    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/75-msm_iomm
root      66    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/273-msm_iom
root      67    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/273-msm_iom
root      68    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/273-msm_iom
root      69    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/97-msm_iomm
root      70    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/97-msm_iomm
root      71    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/97-msm_iomm
root      77    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/402-mba
root      78    2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/530-wcnss
root      134   2     0      0     -51   0     50    1     fg  c0100ac8 00000000 S irq/335-main_tt

2.什么时候执行

产生中断之后先执行中断对应的 hard handler, 之后根据hard handler中断服务程序是否返回 IRQ_WAKE_THREAD flag决定是否执行中断对应的thread_fn。
(下半部tasklet 也是在hard handler 中断服务程序中执行tasklet_schedule()触发的)
执行流程是下面这个样子的:
 

handle_irq_event_percpu()
->
trace_irq_handler_entry(irq, action);
res = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, res);
->
switch (res) {
case IRQ_WAKE_THREAD:
/*
* Catch drivers which return WAKE_THREAD but
* did not set up a thread function
*/
if (unlikely(!action->thread_fn)) {
warn_no_thread(irq, action);
break;
}


irq_wake_thread(desc, action);


->static void irq_wake_thread(struct irq_desc *desc, struct irqaction *action)
{
wake_up_process(action->thread);




->
/*
 * Interrupt handler thread
 */
static int irq_thread(void *data)
{
static const struct sched_param param = {
.sched_priority = MAX_USER_RT_PRIO/2,
};
sched_setscheduler(current, SCHED_FIFO, &param);//irq thread 优先级比ksoftirqd/N 高很多
->
ret = action->thread_fn(action->irq, action->dev_id);

 

3. 一个threaded irq 典型的例子

static irqreturn_t ads7846_hard_irq(int irq, void *handle)
{
	struct ads7846 *ts = handle;

	return get_pendown_state(ts) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
}


static irqreturn_t ads7846_irq(int irq, void *handle)
{
	struct ads7846 *ts = handle;

	/* Start with a small delay before checking pendown state */
	msleep(TS_POLL_DELAY);

	while (!ts->stopped && get_pendown_state(ts)) {

		/* pen is down, continue with the measurement */
		ads7846_read_state(ts);

		if (!ts->stopped)
			ads7846_report_state(ts);

		wait_event_timeout(ts->wait, ts->stopped,
				   msecs_to_jiffies(TS_POLL_PERIOD));
	}

	if (ts->pendown) {
		struct input_dev *input = ts->input;

		input_report_key(input, BTN_TOUCH, 0);
		input_report_abs(input, ABS_PRESSURE, 0);
		input_sync(input);

		ts->pendown = false;
		dev_vdbg(&ts->spi->dev, "UP\n");
	}

	return IRQ_HANDLED;
}


static int __devinit ads7846_probe(struct spi_device *spi)
{
err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq,
  irq_flags, spi->dev.driver->name, ts);

这个驱动既申请了 hard handler(ads7846_hard_irq) 也申请了thread_fn(ads7846_irq)。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值