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

📄 iosapic.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	spin_lock_irqsave(&irq_descp(vector)->lock, flags);	spin_lock(&iosapic_lock);	{		if (gsi_to_vector(gsi) > 0) {			if (list_empty(&iosapic_intr_info[vector].rtes))				free_irq_vector(vector);			spin_unlock(&iosapic_lock);			spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);			goto again;		}		dest = get_target_cpu(gsi, vector);		err = register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY,			      polarity, trigger);		if (err < 0) {			spin_unlock(&iosapic_lock);			spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);			return err;		}		/*		 * If the vector is shared and already unmasked for		 * other interrupt sources, don't mask it.		 */		low32 = iosapic_intr_info[vector].low32;		if (vector_is_shared(vector) && !(low32 & IOSAPIC_MASK))			mask = 0;		set_rte(gsi, vector, dest, mask);	}	spin_unlock(&iosapic_lock);	spin_unlock_irqrestore(&irq_descp(vector)->lock, flags);	printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",	       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),	       cpu_logical_id(dest), dest, vector);	return vector;}voidiosapic_unregister_intr (unsigned int gsi){	unsigned long flags;	int irq, vector, index;	irq_desc_t *idesc;	u32 low32;	unsigned long trigger, polarity;	unsigned int dest;	struct iosapic_rte_info *rte;	/*	 * If the irq associated with the gsi is not found,	 * iosapic_unregister_intr() is unbalanced. We need to check	 * this again after getting locks.	 */	irq = gsi_to_irq(gsi);	if (irq < 0) {		printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);		WARN_ON(1);		return;	}	vector = irq_to_vector(irq);	idesc = irq_descp(irq);	spin_lock_irqsave(&idesc->lock, flags);	spin_lock(&iosapic_lock);	{		if ((rte = gsi_vector_to_rte(gsi, vector)) == NULL) {			printk(KERN_ERR "iosapic_unregister_intr(%u) unbalanced\n", gsi);			WARN_ON(1);			goto out;		}		if (--rte->refcnt > 0)			goto out;		/* Mask the interrupt */		low32 = iosapic_intr_info[vector].low32 | IOSAPIC_MASK;		iosapic_write(rte->addr, IOSAPIC_RTE_LOW(rte->rte_index), low32);		/* Remove the rte entry from the list */		list_del(&rte->rte_list);		iosapic_intr_info[vector].count--;		iosapic_free_rte(rte);		index = find_iosapic(gsi);		iosapic_lists[index].rtes_inuse--;		WARN_ON(iosapic_lists[index].rtes_inuse < 0);		trigger	 = iosapic_intr_info[vector].trigger;		polarity = iosapic_intr_info[vector].polarity;		dest     = iosapic_intr_info[vector].dest;		printk(KERN_INFO "GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d unregistered\n",		       gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),		       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),		       cpu_logical_id(dest), dest, vector);		if (list_empty(&iosapic_intr_info[vector].rtes)) {			/* Sanity check */			BUG_ON(iosapic_intr_info[vector].count);			/* Clear the interrupt controller descriptor */			idesc->handler = &no_irq_type;			/* Clear the interrupt information */			memset(&iosapic_intr_info[vector], 0, sizeof(struct iosapic_intr_info));			iosapic_intr_info[vector].low32 |= IOSAPIC_MASK;			INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);			if (idesc->action) {				printk(KERN_ERR "interrupt handlers still exist on IRQ %u\n", irq);				WARN_ON(1);			}			/* Free the interrupt vector */			free_irq_vector(vector);		}	} out:	spin_unlock(&iosapic_lock);	spin_unlock_irqrestore(&idesc->lock, flags);}/* * ACPI calls this when it finds an entry for a platform interrupt. * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). */int __initiosapic_register_platform_intr (u32 int_type, unsigned int gsi,				int iosapic_vector, u16 eid, u16 id,				unsigned long polarity, unsigned long trigger){	static const char * const name[] = {"unknown", "PMI", "INIT", "CPEI"};	unsigned char delivery;	int vector, mask = 0;	unsigned int dest = ((id << 8) | eid) & 0xffff;	switch (int_type) {	      case ACPI_INTERRUPT_PMI:		vector = iosapic_vector;		/*		 * since PMI vector is alloc'd by FW(ACPI) not by kernel,		 * we need to make sure the vector is available		 */		iosapic_reassign_vector(vector);		delivery = IOSAPIC_PMI;		break;	      case ACPI_INTERRUPT_INIT:		vector = assign_irq_vector(AUTO_ASSIGN);		if (vector < 0)			panic("%s: out of interrupt vectors!\n", __FUNCTION__);		delivery = IOSAPIC_INIT;		break;	      case ACPI_INTERRUPT_CPEI:		vector = IA64_CPE_VECTOR;		delivery = IOSAPIC_LOWEST_PRIORITY;		mask = 1;		break;	      default:		printk(KERN_ERR "iosapic_register_platform_irq(): invalid int type 0x%x\n", int_type);		return -1;	}	register_intr(gsi, vector, delivery, polarity, trigger);	printk(KERN_INFO "PLATFORM int %s (0x%x): GSI %u (%s, %s) -> CPU %d (0x%04x) vector %d\n",	       int_type < ARRAY_SIZE(name) ? name[int_type] : "unknown",	       int_type, gsi, (trigger == IOSAPIC_EDGE ? "edge" : "level"),	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),	       cpu_logical_id(dest), dest, vector);	set_rte(gsi, vector, dest, mask);	return vector;}/* * ACPI calls this when it finds an entry for a legacy ISA IRQ override. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). */void __initiosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,			  unsigned long polarity,			  unsigned long trigger){	int vector;	unsigned int dest = cpu_physical_id(smp_processor_id());	vector = isa_irq_to_vector(isa_irq);	register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger);	DBG("ISA: IRQ %u -> GSI %u (%s,%s) -> CPU %d (0x%04x) vector %d\n",	    isa_irq, gsi, trigger == IOSAPIC_EDGE ? "edge" : "level",	    polarity == IOSAPIC_POL_HIGH ? "high" : "low",	    cpu_logical_id(dest), dest, vector);	set_rte(gsi, vector, dest, 1);}void __initiosapic_system_init (int system_pcat_compat){	int vector;	for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) {		iosapic_intr_info[vector].low32 = IOSAPIC_MASK;		INIT_LIST_HEAD(&iosapic_intr_info[vector].rtes);	/* mark as unused */	}	pcat_compat = system_pcat_compat;	if (pcat_compat) {		/*		 * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support		 * enabled.		 */		printk(KERN_INFO "%s: Disabling PC-AT compatible 8259 interrupts\n", __FUNCTION__);		outb(0xff, 0xA1);		outb(0xff, 0x21);	}}static inline intiosapic_alloc (void){	int index;	for (index = 0; index < NR_IOSAPICS; index++)		if (!iosapic_lists[index].addr)			return index;	printk(KERN_WARNING "%s: failed to allocate iosapic\n", __FUNCTION__);	return -1;}static inline voidiosapic_free (int index){	memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));}static inline intiosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver){	int index;	unsigned int gsi_end, base, end;	/* check gsi range */	gsi_end = gsi_base + ((ver >> 16) & 0xff);	for (index = 0; index < NR_IOSAPICS; index++) {		if (!iosapic_lists[index].addr)			continue;		base = iosapic_lists[index].gsi_base;		end  = base + iosapic_lists[index].num_rte - 1;		if (gsi_base < base && gsi_end < base)			continue;/* OK */		if (gsi_base > end && gsi_end > end)			continue; /* OK */		return -EBUSY;	}	return 0;}int __devinitiosapic_init (unsigned long phys_addr, unsigned int gsi_base){	int num_rte, err, index;	unsigned int isa_irq, ver;	char __iomem *addr;	unsigned long flags;	spin_lock_irqsave(&iosapic_lock, flags);	{		addr = ioremap(phys_addr, 0);		ver = iosapic_version(addr);		if ((err = iosapic_check_gsi_range(gsi_base, ver))) {			iounmap(addr);			spin_unlock_irqrestore(&iosapic_lock, flags);			return err;		}		/*		 * The MAX_REDIR register holds the highest input pin		 * number (starting from 0).		 * We add 1 so that we can use it for number of pins (= RTEs)		 */		num_rte = ((ver >> 16) & 0xff) + 1;		index = iosapic_alloc();		iosapic_lists[index].addr = addr;		iosapic_lists[index].gsi_base = gsi_base;		iosapic_lists[index].num_rte = num_rte;#ifdef CONFIG_NUMA		iosapic_lists[index].node = MAX_NUMNODES;#endif	}	spin_unlock_irqrestore(&iosapic_lock, flags);	if ((gsi_base == 0) && pcat_compat) {		/*		 * Map the legacy ISA devices into the IOSAPIC data.  Some of these may		 * get reprogrammed later on with data from the ACPI Interrupt Source		 * Override table.		 */		for (isa_irq = 0; isa_irq < 16; ++isa_irq)			iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);	}	return 0;}#ifdef CONFIG_HOTPLUGintiosapic_remove (unsigned int gsi_base){	int index, err = 0;	unsigned long flags;	spin_lock_irqsave(&iosapic_lock, flags);	{		index = find_iosapic(gsi_base);		if (index < 0) {			printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",			       __FUNCTION__, gsi_base);			goto out;		}		if (iosapic_lists[index].rtes_inuse) {			err = -EBUSY;			printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",			       __FUNCTION__, gsi_base);			goto out;		}		iounmap(iosapic_lists[index].addr);		iosapic_free(index);	} out:	spin_unlock_irqrestore(&iosapic_lock, flags);	return err;}#endif /* CONFIG_HOTPLUG */#ifdef CONFIG_NUMAvoid __devinitmap_iosapic_to_node(unsigned int gsi_base, int node){	int index;	index = find_iosapic(gsi_base);	if (index < 0) {		printk(KERN_WARNING "%s: No IOSAPIC for GSI %u\n",		       __FUNCTION__, gsi_base);		return;	}	iosapic_lists[index].node = node;	return;}#endifstatic int __init iosapic_enable_kmalloc (void){	iosapic_kmalloc_ok = 1;	return 0;}core_initcall (iosapic_enable_kmalloc);

⌨️ 快捷键说明

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