博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
中断API之irq_set_chained_handler
阅读量:4214 次
发布时间:2019-05-26

本文共 4192 字,大约阅读时间需要 13 分钟。

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 voidirq_set_chained_handler(unsigned int irq, irq_flow_handler_t handle){	__irq_set_handler(irq, handle, 1, NULL);}继续调用__irq_set_handlervoid__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);	}}

转载地址:http://zgjmi.baihongyu.com/

你可能感兴趣的文章
Android中Java代码和XML布局效率问题
查看>>
android TextView属性大全(转)
查看>>
Conclusion for Resource Management
查看>>
Conclusion for Constructors,Destructors,and Assignment Operators
查看>>
Conclusion for Accustoming Yourself to C++
查看>>
面试题1:赋值运算函数(offer)
查看>>
Mark : MessagePack简介及使用
查看>>
Mark : Hadoop Raid-实战经验总结
查看>>
Structured Streaming 实现思路与实现概述
查看>>
Apache Spark 2.2.0 中文文档 - Structured Streaming 编程指南 | ApacheCN
查看>>
Mark:大数据最佳学习路线
查看>>
Spark 多线程模型
查看>>
编程第一性原则
查看>>
Mark : SpringBoot核心-非关系型数据库NoSQL
查看>>
Mark : hive文件存储格式
查看>>
mark : hadoop 四种压缩格式
查看>>
Mark : hive snappy的数据是否支持split的测试
查看>>
Hadoop 压缩格式
查看>>
Mark : Spark Streaming vs. Kafka Stream 哪个更适合你
查看>>
Mark : spark streaming去重
查看>>