int irq_activate(struct irq_desc *desc)用于激活一个中断目前看到只有在__setup_irq中被调用
其源码分析如下:
int irq_activate(struct irq_desc *desc)
{
#得到中断描述符的成员变量irq_data
struct irq_data *d = irq_desc_get_irq_data(desc);
#检查irq_data中是否包含IRQD_AFFINITY_MANAGED 标志,如果没有包含的IRQD_AFFINITY_MANAGED的话,再调用irq_domain_activate_irq
#否则直接返回0
if (!irqd_affinity_is_managed(d))
return irq_domain_activate_irq(d, false);
return 0;
}
int irq_domain_activate_irq(struct irq_data *irq_data, bool early)
{
int ret = 0;
#检查irq_data中是否包含IRQD_ACTIVATED,如果没有包含,则调用__irq_domain_activate_irq
if (!irqd_is_activated(irq_data))
ret = __irq_domain_activate_irq(irq_data, early);
#如果上一句执行成功,则ret等于0,则在irq_data中设置IRQD_ACTIVATED
if (!ret)
irqd_set_activated(irq_data);
return ret;
}
static int __irq_domain_activate_irq(struct irq_data *irqd, bool early)
{
int ret = 0;
#这里要求形参struct irq_data *irqd 和irqd的成员变量domain 不能为null,因为最终过的active 是通过具体的domain来实现的.
if (irqd && irqd->domain) {
struct irq_domain *domain = irqd->domain;
#这里有个递归调用,一直递归直到找到irq的顶层,如果存在上层的话,这里会递归调用__irq_domain_activate_irq
if (irqd->parent_data)
ret = __irq_domain_activate_irq(irqd->parent_data,
early);
#这个if条件是递归的出口,可以看到最终的irq_active是通过调用domain->ops->activate来实现的
if (!ret && domain->ops->activate) {
ret = domain->ops->activate(domain, irqd, early);
/* Rollback in case of error */
if (ret && irqd->parent_data)
#如果domain->ops->activate 返回1的话,就表明可能执行错误了,调用__irq_domain_deactivate_irq 来执行回滚操作.
__irq_domain_deactivate_irq(irqd->parent_data);
}
}
return ret;
}
__irq_domain_deactivate_irq 也是一个递归操作,最终也是调用domain的ops->deactivate 来进行.
static void __irq_domain_deactivate_irq(struct irq_data *irq_data)
{
if (irq_data && irq_data->domain) {
struct irq_domain *domain = irq_data->domain;
if (domain->ops->deactivate)
domain->ops->deactivate(domain, irq_data);
if (irq_data->parent_data)
__irq_domain_deactivate_irq(irq_data->parent_data);
}
}
中断API之irq_activate
最新推荐文章于 2023-01-12 17:03:25 发布