慢慢欣赏linux 中断描述符

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值