⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 manage.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/kernel/irq/manage.c * * Copyright (C) 1992, 1998-2006 Linus Torvalds, Ingo Molnar * Copyright (C) 2005-2006 Thomas Gleixner * * This file contains driver APIs to the irq subsystem. */#include <linux/irq.h>#include <linux/module.h>#include <linux/random.h>#include <linux/interrupt.h>#include <linux/slab.h>#include "internals.h"#ifdef CONFIG_SMPcpumask_t irq_default_affinity = CPU_MASK_ALL;/** *	synchronize_irq - wait for pending IRQ handlers (on other CPUs) *	@irq: interrupt number to wait for * *	This function waits for any pending IRQ handlers for this interrupt *	to complete before returning. If you use this function while *	holding a resource the IRQ handler may need you will deadlock. * *	This function may be called - with care - from IRQ context. */void synchronize_irq(unsigned int irq){	struct irq_desc *desc = irq_desc + irq;	unsigned int status;	if (irq >= NR_IRQS)		return;	do {		unsigned long flags;		/*		 * Wait until we're out of the critical section.  This might		 * give the wrong answer due to the lack of memory barriers.		 */		while (desc->status & IRQ_INPROGRESS)			cpu_relax();		/* Ok, that indicated we're done: double-check carefully. */		spin_lock_irqsave(&desc->lock, flags);		status = desc->status;		spin_unlock_irqrestore(&desc->lock, flags);		/* Oops, that failed? */	} while (status & IRQ_INPROGRESS);}EXPORT_SYMBOL(synchronize_irq);/** *	irq_can_set_affinity - Check if the affinity of a given irq can be set *	@irq:		Interrupt to check * */int irq_can_set_affinity(unsigned int irq){	struct irq_desc *desc = irq_desc + irq;	if (CHECK_IRQ_PER_CPU(desc->status) || !desc->chip ||	    !desc->chip->set_affinity)		return 0;	return 1;}/** *	irq_set_affinity - Set the irq affinity of a given irq *	@irq:		Interrupt to set affinity *	@cpumask:	cpumask * */int irq_set_affinity(unsigned int irq, cpumask_t cpumask){	struct irq_desc *desc = irq_desc + irq;	if (!desc->chip->set_affinity)		return -EINVAL;	set_balance_irq_affinity(irq, cpumask);#ifdef CONFIG_GENERIC_PENDING_IRQ	set_pending_irq(irq, cpumask);#else	desc->affinity = cpumask;	desc->chip->set_affinity(irq, cpumask);#endif	return 0;}#ifndef CONFIG_AUTO_IRQ_AFFINITY/* * Generic version of the affinity autoselector. */int irq_select_affinity(unsigned int irq){	cpumask_t mask;	if (!irq_can_set_affinity(irq))		return 0;	cpus_and(mask, cpu_online_map, irq_default_affinity);	irq_desc[irq].affinity = mask;	irq_desc[irq].chip->set_affinity(irq, mask);	set_balance_irq_affinity(irq, mask);	return 0;}#endif#endif/** *	disable_irq_nosync - disable an irq without waiting *	@irq: Interrupt to disable * *	Disable the selected interrupt line.  Disables and Enables are *	nested. *	Unlike disable_irq(), this function does not ensure existing *	instances of the IRQ handler have completed before returning. * *	This function may be called from IRQ context. */void disable_irq_nosync(unsigned int irq){	struct irq_desc *desc = irq_desc + irq;	unsigned long flags;	if (irq >= NR_IRQS)		return;	spin_lock_irqsave(&desc->lock, flags);	if (!desc->depth++) {		desc->status |= IRQ_DISABLED;		desc->chip->disable(irq);	}	spin_unlock_irqrestore(&desc->lock, flags);}EXPORT_SYMBOL(disable_irq_nosync);/** *	disable_irq - disable an irq and wait for completion *	@irq: Interrupt to disable * *	Disable the selected interrupt line.  Enables and Disables are *	nested. *	This function waits for any pending IRQ handlers for this interrupt *	to complete before returning. If you use this function while *	holding a resource the IRQ handler may need you will deadlock. * *	This function may be called - with care - from IRQ context. */void disable_irq(unsigned int irq){	struct irq_desc *desc = irq_desc + irq;	if (irq >= NR_IRQS)		return;	disable_irq_nosync(irq);	if (desc->action)		synchronize_irq(irq);}EXPORT_SYMBOL(disable_irq);static void __enable_irq(struct irq_desc *desc, unsigned int irq){	switch (desc->depth) {	case 0:		WARN(1, KERN_WARNING "Unbalanced enable for IRQ %d\n", irq);		break;	case 1: {		unsigned int status = desc->status & ~IRQ_DISABLED;		/* Prevent probing on this irq: */		desc->status = status | IRQ_NOPROBE;		check_irq_resend(desc, irq);		/* fall-through */	}	default:		desc->depth--;	}}/** *	enable_irq - enable handling of an irq *	@irq: Interrupt to enable * *	Undoes the effect of one call to disable_irq().  If this *	matches the last disable, processing of interrupts on this *	IRQ line is re-enabled. * *	This function may be called from IRQ context. */void enable_irq(unsigned int irq){	struct irq_desc *desc = irq_desc + irq;	unsigned long flags;	if (irq >= NR_IRQS)		return;	spin_lock_irqsave(&desc->lock, flags);	__enable_irq(desc, irq);	spin_unlock_irqrestore(&desc->lock, flags);}EXPORT_SYMBOL(enable_irq);int set_irq_wake_real(unsigned int irq, unsigned int on){	struct irq_desc *desc = irq_desc + irq;	int ret = -ENXIO;	if (desc->chip->set_wake)		ret = desc->chip->set_wake(irq, on);	return ret;}/** *	set_irq_wake - control irq power management wakeup *	@irq:	interrupt to control *	@on:	enable/disable power management wakeup * *	Enable/disable power management wakeup mode, which is *	disabled by default.  Enables and disables must match, *	just as they match for non-wakeup mode support. * *	Wakeup mode lets this IRQ wake the system from sleep *	states like "suspend to RAM". */int set_irq_wake(unsigned int irq, unsigned int on){	struct irq_desc *desc = irq_desc + irq;	unsigned long flags;	int ret = 0;	/* wakeup-capable irqs can be shared between drivers that	 * don't need to have the same sleep mode behaviors.	 */	spin_lock_irqsave(&desc->lock, flags);	if (on) {		if (desc->wake_depth++ == 0) {			ret = set_irq_wake_real(irq, on);			if (ret)				desc->wake_depth = 0;			else				desc->status |= IRQ_WAKEUP;		}	} else {		if (desc->wake_depth == 0) {			WARN(1, "Unbalanced IRQ %d wake disable\n", irq);		} else if (--desc->wake_depth == 0) {			ret = set_irq_wake_real(irq, on);			if (ret)				desc->wake_depth = 1;			else				desc->status &= ~IRQ_WAKEUP;		}	}	spin_unlock_irqrestore(&desc->lock, flags);	return ret;}EXPORT_SYMBOL(set_irq_wake);/* * Internal function that tells the architecture code whether a * particular irq has been exclusively allocated or is available * for driver use. */int can_request_irq(unsigned int irq, unsigned long irqflags){	struct irqaction *action;	if (irq >= NR_IRQS || irq_desc[irq].status & IRQ_NOREQUEST)		return 0;	action = irq_desc[irq].action;	if (action)		if (irqflags & action->flags & IRQF_SHARED)			action = NULL;	return !action;}void compat_irq_chip_set_default_handler(struct irq_desc *desc){	/*	 * If the architecture still has not overriden	 * the flow handler then zap the default. This	 * should catch incorrect flow-type setting.	 */	if (desc->handle_irq == &handle_bad_irq)		desc->handle_irq = NULL;}static int __irq_set_trigger(struct irq_chip *chip, unsigned int irq,		unsigned long flags){	int ret;	if (!chip || !chip->set_type) {		/*		 * IRQF_TRIGGER_* but the PIC does not support multiple		 * flow-types?		 */		pr_warning("No set_type function for IRQ %d (%s)\n", irq,				chip ? (chip->name ? : "unknown") : "unknown");		return 0;	}	ret = chip->set_type(irq, flags & IRQF_TRIGGER_MASK);	if (ret)		pr_err("setting trigger mode %d for irq %u failed (%pF)\n",				(int)(flags & IRQF_TRIGGER_MASK),				irq, chip->set_type);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -