4.6 只在root domain注册的设备中断
为了与《4.5 只在head domain注册的设备中断》更好的对比,同样以macb网口驱动为例。在Linux中,macb的驱动位于drivers/net/ethernet/cadence中。

以drivers/net/ethernet/cadence/macb_main.c为例,驱动加载后,匹配到对应的platform_device(.name = “macb”),调用macb_probe执行设备初始化。通过platform_get_irq->of_irq_get获取Linux virq,然后调用devm_request_irq向Linux中断子系统注册中断处理程序macb_interrupt。

具体调用堆栈如下,最终调用到request_threaded_irq,第一个参数是virq,第二个参数是macb_interrupt,第三个thread_fn是NULL.
macb_probe
->init(pdev)
->macb_config->init
->default_gem_config->init
->macb_init
->devm_request_irq(&pdev->dev, queue->irq, macb_interrupt, IRQF_SHARED, dev->name, queue)
->devm_request_threaded_irq(dev, irq, handler, NULL, irqflags, devname, dev_id);
->request_threaded_irq(irq, handler, thread_fn, irqflags, devname, dev_id);
当macb中断触发时,经过层层调用到底__ipipe_dispatch_irq。因为没有在head domain注册中断处理程序,必然会走到下图红框中,调用__ipipe_set_irq_pending将macb中断记录到root domain的interrupt log中。

在《3.4.1.3 IPIPE interrupt log数据结构》中,已经讨论过interrupt log的记录与回放。从interrupt log中查询出未处理的中断,进行处理,为方便描述简称interrupt log回放。核心函数就是__ipipe_next_irq,它是__ipipe_set_irq_pending的反向操作。从下图的函数调用关系可知,IPIPE总是通过调用__ipipe_sync_stage来完成interrupt log回放。
经过层层调用,
__ipipe_do_sync_pipeline->__ipipe_sync_stage->__ipipe_do_sync_stage最终会执行root domain的handler,即之前注册的__ipipe_do_IRQ!

例如,__ipipe_do_sync_pipeline->__ipipe_sync_stage->__ipipe_do_sync_stage最终会执行root domain的irqs[irq].handler,即之前注册的__ipipe_do_IRQ!
走到了__ipipe_do_IRQ之后,会回归到Linux中断子系统,调用__handle_domain_irq,顺着Linux的中断处理流程,最终回到Linux中macb对应的中断处理程序macb_interrupt!
到Linux中macb对应的中断处理程序macb_interrupt!
对比《4.5 只在head domain注册的设备中断》和《4.6 仅在root domain注册的设备中断》,同样一个硬件设备,应该只在Head domain或root domain加载一个驱动。除了设备中断不会从Xenomai流到Linux之外,还需要防止两个驱动对寄存器的操作发生冲突。参考《4.4 timer中断从Xenomai流向Linux》,timer设备是一个特例,而且打完了IPIPE Patch后,Linux本身不再直接操作timer硬件。
2012

被折叠的 条评论
为什么被折叠?



