本文共 4200 字,大约阅读时间需要 14 分钟。
unsigned int __irq_entry do_IRQ(struct pt_regs *regs){ desc = __this_cpu_read(vector_irq[vector]); 根据硬中断号找到中断描述符}
以RTC时钟中断注册为例
static int mtk_rtc_probe(struct platform_device *pdev){ struct resource *res; struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent); struct mt6397_rtc *rtc; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt6397_rtc), GFP_KERNEL); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); rtc->addr_base = res->start; res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); // 第一步 获取中断资源, 中断号, 高/低 边沿/电平触发 rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start); // 第二步 进行软硬中断映射 =>unsigned int irq_create_mapping(struct irq_domain *domain, irq_hw_number_t hwirq) { struct device_node *of_node; int virq; /* Look for default domain if nececssary */ if (domain == NULL) domain = irq_default_domain; of_node = irq_domain_get_of_node(domain); /* Check if mapping already exists */ virq = irq_find_mapping(domain, hwirq); // 已经映射则返回 =>unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq) { struct irq_data *data; /* Look for default domain if nececssary */ if (domain == NULL) domain = irq_default_domain; if (domain == NULL) return 0; if (hwirq < domain->revmap_direct_max_irq) { data = irq_domain_get_irq_data(domain, hwirq); if (data && data->hwirq == hwirq) return hwirq; } /* Check if the hwirq is in the linear revmap. */ if (hwirq < domain->revmap_size) return domain->linear_revmap[hwirq]; rcu_read_lock(); data = radix_tree_lookup(&domain->revmap_tree, hwirq); // 树查找 rcu_read_unlock(); return data ? data->irq : 0; } if (virq) { return virq; } /* Allocate a virtual interrupt number */ virq = irq_domain_alloc_descs(-1, 1, hwirq, of_node_to_nid(of_node), NULL); =>int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq, int node, const struct cpumask *affinity) { virq = __irq_alloc_descs(virq, virq, cnt, node, THIS_MODULE, affinity); =>int __ref __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, struct module *owner, const struct cpumask *affinity) { start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS, from, cnt, 0); ret = alloc_descs(start, cnt, node, affinity, owner); return ret; } return virq; } irq_domain_associate(domain, virq, hwirq) return virq; } rtc->regmap = mt6397_chip->regmap; rtc->dev = &pdev->dev; mutex_init(&rtc->lock); platform_set_drvdata(pdev, rtc); ret = request_threaded_irq(rtc->irq, NULL, // 第三步 挂接中断action mtk_rtc_irq_handler_thread, IRQF_ONESHOT | IRQF_TRIGGER_HIGH, "mt6397-rtc", rtc); device_init_wakeup(&pdev->dev, 1); rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev, &mtk_rtc_ops, THIS_MODULE); return 0;}
中断描述符的申请使用如下函数:alloc_descs 函数根据条件编译宏分静态分配和动态申请
动态申请如下
static int alloc_descs(unsigned int start, unsigned int cnt, int node, const struct cpumask *affinity, struct module *owner){ const struct cpumask *mask = NULL; struct irq_desc *desc; unsigned int flags; int i; flags = affinity ? IRQD_AFFINITY_MANAGED | IRQD_MANAGED_SHUTDOWN : 0; mask = NULL; for (i = 0; i < cnt; i++) { if (affinity) { node = cpu_to_node(cpumask_first(affinity)); mask = affinity; affinity++; } desc = alloc_desc(start + i, node, flags, mask, owner); irq_insert_desc(start + i, desc); irq_sysfs_add(start + i, desc); irq_add_debugfs_entry(start + i, desc); } bitmap_set(allocated_irqs, start, cnt); return start;}
静态申请
static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, const struct cpumask *affinity, struct module *owner){ u32 i; for (i = 0; i < cnt; i++) { struct irq_desc *desc = irq_to_desc(start + i);' =>struct irq_desc *irq_to_desc(unsigned int irq) { return (irq < NR_IRQS) ? irq_desc + irq : NULL; ==>struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = { // 静态定义数组 [0 ... NR_IRQS-1] = { .handle_irq = handle_bad_irq, .depth = 1, .lock = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock), } }; } desc->owner = owner; } bitmap_set(allocated_irqs, start, cnt); return start;}
转载地址:http://ndlji.baihongyu.com/