{
gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4, sizeof(u32));
gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4, sizeof(u32));
if (gic == &gic_data[0])
cpu_pm_register_notifier(&gic_notifier_block);
}
这段代码前面主要是分配两个per cpu的内存。这些内存在系统进入sleep状态的时候保存PPI的寄存器状态信息,在resume的时候,写回寄存器。对于root GIC,需要注册一个和电源管理的事件通知callback函数。不得不吐槽一下gic_notifier_block和gic_notifier这两个符号的命名,看不出来和电源管理有任何关系。更优雅的名字应该包括pm这样的符号,以便让其他工程师看到名字就立刻知道是和电源管理相关的。
四、GIC callback函数分析
1、irq domain相关callback函数分析
irq domain相关callback函数包括:
(1)gic_irq_domain_map函数:创建IRQ number和GIC hw interrupt ID之间映射关系的时候,需要调用该回调函数。具体代码如下:
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
if (hw < 32) {------------------SGI或者PPI

irq_set_percpu_devid(irq);--------------------------(a)
irq_set_chip_and_handler(irq, &gic_chip, handle_percpu_devid_irq);-------(b)
set_irq_flags(irq, IRQF_VALID | IRQF_NOAUTOEN);--------------(c)
} else {
irq_set_chip_and_handler(irq, &gic_chip, handle_fasteoi_irq);----------(d)
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
gic_routable_irq_domain_ops->map(d, irq, hw);----------------(e)
}
irq_set_chip_data(irq, d->host_data);-----设定irq chip的私有数据
return 0;
}
(a)SGI或者PPI和SPI最大的不同是per cpu的,SPI是所有CPU共享的,因此需要分配per cpu的内存,设定一些per cpu的flag。
(b)设定该中断描述符的irq chip和high level的handler
(c)设定irq flag是有效的(因为已经设定好了chip和handler了),并且request后不是auto enable的。
(d)对于SPI,设定的high level irq event handler是handle_fasteoi_irq。对于SPI,是可以probe,并且request后是auto enable的。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shumachanpin/article-76887-15.html
绝不手软
北洋水师总吨位4万吨