irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)用于修改通过request_irq 注册中断号的handle
其使用的例程如下:
static int mvebu_pic_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct mvebu_pic *pic;
struct irq_chip *irq_chip;
struct resource *res;
pic = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pic), GFP_KERNEL);
if (!pic)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pic->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pic->base))
return PTR_ERR(pic->base);
irq_chip = &pic->irq_chip;
irq_chip->name = dev_name(&pdev->dev);
irq_chip->irq_mask = mvebu_pic_mask_irq;
irq_chip->irq_unmask = mvebu_pic_unmask_irq;
irq_chip->irq_eoi = mvebu_pic_eoi_irq;
pic->parent_irq = irq_of_parse_and_map(node, 0);
if (pic->parent_irq <= 0) {
dev_err(&pdev->dev, "Failed to parse parent interrupt\n");
return -EINVAL;
}
pic->domain = irq_domain_add_linear(node, PIC_MAX_IRQS,
&mvebu_pic_domain_ops, pic);
if (!pic->domain) {
dev_err(&pdev->dev, "Failed to allocate irq domain\n");
return -ENOMEM;
}
#通过irq_set_chained_handler 来修改pic->parent_irq 中断号的handle
irq_set_chained_handler(pic->parent_irq, mvebu_pic_handle_cascade_irq);
irq_set_handler_data(pic->parent_irq, pic);
on_each_cpu(mvebu_pic_enable_percpu_irq, pic, 1);
platform_set_drvdata(pdev, pic);
return 0;
}
其源码分析如下:
static inline void
irq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle)
{
__irq_set_handler(irq, handle, 1, NULL);
}
继续调用__irq_set_handler
void
__irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
const char *name)
{
unsigned long flags;
#通过irq number获取中断描述符的时候需要通过irq_get_desc_buslock/irq_put_desc_busunlock 这一对函数来保护
struct irq_desc *desc = irq_get_desc_buslock(irq, &flags, 0);
if (!desc)
return;
#继续调用__irq_do_set_handler 来修改irq对应的handle
__irq_do_set_handler(desc, handle, is_chained, name);
irq_put_desc_busunlock(desc, flags);
}
static void
__irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
int is_chained, const char *name)
{
#handle 为null的话,就会被赋值handle_bad_irq,这种情况一般不会存在。如果不想删掉irq,可以通过这种方式来替换irq原本的handle,从而让irq取消执行
#原来的功能
if (!handle) {
handle = handle_bad_irq;
} else {
struct irq_data *irq_data = &desc->irq_data;
#一般不开这个宏
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
/*
* With hierarchical domains we might run into a
* situation where the outermost chip is not yet set
* up, but the inner chips are there. Instead of
* bailing we install the handler, but obviously we
* cannot enable/startup the interrupt at this point.
*/
while (irq_data) {
if (irq_data->chip != &no_irq_chip)
break;
/*
* Bail out if the outer chip is not set up
* and the interrrupt supposed to be started
* right away.
*/
if (WARN_ON(is_chained))
return;
/* Try the parent */
irq_data = irq_data->parent_data;
}
#endif
#如果irq_data为null或者没有之指定irq_chip的话,则退出
if (WARN_ON(!irq_data || irq_data->chip == &no_irq_chip))
return;
}
/* Uninstall? */
#如果当前irq 的handle 是handle_bad_irq,则把irq的state设置为disable,这个case 一般也不会成立
if (handle == handle_bad_irq) {
if (desc->irq_data.chip != &no_irq_chip)
mask_ack_irq(desc);
irq_state_set_disabled(desc);
if (is_chained)
desc->action = NULL;
desc->depth = 1;
}
#这里才是核心代码,给irq对应的中断描述符设置为新的handler
desc->handle_irq = handle;
#设置name,通过这种方式的name强制为null.
desc->name = name;
#通过irq_set_chained_handler 设置的时候,is_chained 会为1,所以这个if条件一般成立
if (handle != handle_bad_irq && is_chained) {
#得到中断触发类型,例如边沿,电平等
unsigned int type = irqd_get_trigger_type(&desc->irq_data);
/*
* We're about to start this interrupt immediately,
* hence the need to set the trigger configuration.
* But the .set_type callback may have overridden the
* flow handler, ignoring that we're dealing with a
* chained interrupt. Reset it immediately because we
* do know better.
*/
#这里有重新设置一遍中断的类型和handle,因为is_chained为1,所以这里的handle 等于被设置了两次
if (type != IRQ_TYPE_NONE) {
__irq_set_trigger(desc, type);
desc->handle_irq = handle;
}
#设置中断描述符的flag
irq_settings_set_noprobe(desc);
irq_settings_set_norequest(desc);
irq_settings_set_nothread(desc);
desc->action = &chained_action;
#重新激活和开始中断
irq_activate_and_startup(desc, IRQ_RESEND);
}
}
中断API之irq_set_chained_handler
最新推荐文章于 2024-07-25 16:19:38 发布