Skip to contentSkip to conversation

take2: [Patch 3/3] Updated patches for PCI IRQ deallocation support

PATCH Kenji Kaneshige 1 participant 1 message Oct 4, 2004 ACPI

lore
Share & tools
lore
#0 lore raw

Andrew and Tony,

This is a patch for IA64 code.
Please note that this patch depends on [patch 2/3]. So [patch 2/3] needs to be applied before applying this patch.

Thanks,
Kenji Kaneshige

----
Name: IRQ_deallocation_ia64.patch
Kernel Version: 2.6.9-rc3
Depends: IRQ_deallocation_acpi.patch
Change Log:

- Ported to 2.6.9-rc3

- Changed pcibios_disable_device() implementation because now that pcibios_disalbe_device() hook is defined by using __attribute__ ((weak)) instead of modifying all arch specific code.

- Fixed a bug in iosapic_unregister_intr(). Missing "spin_unlock(&iosapic_lock);" was added.

- Changed the argument of iosapic_unregister_intr() from Linux IRQ number to GSI number.

Description:

This is an ia64 portion of IRQ resource deallocation. It implements pcibios_disable_device() and acpi_unregister_gsi() for ia64.

o acpi_unregister_gsi()

Summary of changes for implementing this interface:

- Add new function iosapic_unregister_intr() into arch/ia64/kernel/iosapic.c. This function frees an interrupt vector and related data structures.

- Add new function free_irq_vector() into arch/ia64/kernel/irq_ia64.c. This frees an unused vector.

- Change assign_irq_vector() to be able to support free_irq_vector().

o pcibios_disable_device()

This calls acpi_pci_irq_disable() to deallocate IRQ resources.

---

 linux-2.6.9-rc3-kanesige/arch/ia64/Kconfig           |    9 +
 linux-2.6.9-rc3-kanesige/arch/ia64/kernel/acpi.c     |    9 +
 linux-2.6.9-rc3-kanesige/arch/ia64/kernel/iosapic.c  |   96 +++++++++++++++++--
 linux-2.6.9-rc3-kanesige/arch/ia64/kernel/irq.c      |    9 +
 linux-2.6.9-rc3-kanesige/arch/ia64/kernel/irq_ia64.c |   27 ++++-
 linux-2.6.9-rc3-kanesige/arch/ia64/pci/pci.c         |    8 +
 linux-2.6.9-rc3-kanesige/include/asm-ia64/acpi.h     |    4 
 linux-2.6.9-rc3-kanesige/include/asm-ia64/hw_irq.h   |    2 
 linux-2.6.9-rc3-kanesige/include/asm-ia64/iosapic.h  |    4 
 9 files changed, 153 insertions(+), 15 deletions(-)
arch/ia64/Kconfig renamed from arch/ia64/Kconfig~IRQ_deallocation_ia64 +9 -0
diff -puN arch/ia64/Kconfig~IRQ_deallocation_ia64 arch/ia64/Kconfig
@@ -299,6 +299,15 @@ config IA64_PALINFO
 	  To use this option, you have to ensure that the "/proc file system
 	  support" (CONFIG_PROC_FS) is enabled, too.
 
+config IA64_DEALLOCATE_IRQ
+	bool "IRQ resource deallocation support (EXPERIMENTAL)"
+	depends on IOSAPIC && EXPERIMENTAL
+	default n
+	help
+	  Say Y here to experiment with deallocating IRQ resources
+	  dynamically.
+	  Say N if you want to disable IRQ resource deallocation.
+
 source "drivers/firmware/Kconfig"
 
 source "fs/Kconfig.binfmt"
arch/ia64/kernel/acpi.c renamed from arch/ia64/kernel/acpi.c~IRQ_deallocation_ia64 +9 -0
diff -puN arch/ia64/kernel/acpi.c~IRQ_deallocation_ia64 arch/ia64/kernel/acpi.c
@@ -515,6 +515,15 @@ acpi_register_gsi (u32 gsi, int edge_lev
 }
 EXPORT_SYMBOL(acpi_register_gsi);
 
+#ifdef CONFIG_IA64_DEALLOCATE_IRQ
+void
+acpi_unregister_gsi (u32 gsi)
+{
+	iosapic_unregister_intr(gsi);
+}
+EXPORT_SYMBOL(acpi_unregister_gsi);
+#endif
+
 static int __init
 acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
 {
arch/ia64/kernel/iosapic.c renamed from arch/ia64/kernel/iosapic.c~IRQ_deallocation_ia64 +87 -9

141 lines not on this page · raw message

arch/ia64/kernel/irq.c renamed from arch/ia64/kernel/irq.c~IRQ_deallocation_ia64 +7 -2
diff -puN arch/ia64/kernel/irq.c~IRQ_deallocation_ia64 arch/ia64/kernel/irq.c
@@ -874,8 +874,11 @@ int setup_irq(unsigned int irq, struct i
 	struct irqaction *old, **p;
 	irq_desc_t *desc = irq_descp(irq);
 
-	if (desc->handler == &no_irq_type)
+	spin_lock_irqsave(&desc->lock,flags);
+	if (desc->handler == &no_irq_type) {
+		spin_unlock_irqrestore(&desc->lock,flags);
 		return -ENOSYS;
+	}
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
 	 * so we have to be careful not to interfere with a
@@ -901,7 +904,6 @@ int setup_irq(unsigned int irq, struct i
 	/*
 	 * The following block of code has to be executed atomically
 	 */
-	spin_lock_irqsave(&desc->lock,flags);
 	p = &desc->action;
 	if ((old = *p) != NULL) {
 		/* Can't share interrupts unless both agree to */
@@ -1035,6 +1037,9 @@ void move_irq(int irq)
 	irq_desc_t *desc = irq_descp(irq);
 	int redir = test_bit(irq, pending_irq_redir);
 
+	if (unlikely(!desc->handler->set_affinity))
+		return;
+
 	if (!cpus_empty(pending_irq_cpumask[irq])) {
 		cpus_and(tmp, pending_irq_cpumask[irq], cpu_online_map);
 		if (unlikely(!cpus_empty(tmp))) {
arch/ia64/kernel/irq_ia64.c renamed from arch/ia64/kernel/irq_ia64.c~IRQ_deallocation_ia64 +23 -4
diff -puN arch/ia64/kernel/irq_ia64.c~IRQ_deallocation_ia64 arch/ia64/kernel/irq_ia64.c
@@ -74,15 +74,34 @@ irq_exit (void)
 	preempt_enable_no_resched();
 }
 
+static unsigned long ia64_vector_mask[BITS_TO_LONGS(IA64_NUM_DEVICE_VECTORS)];
+
 int
 assign_irq_vector (int irq)
 {
-	static int next_vector = IA64_FIRST_DEVICE_VECTOR;
-
-	if (next_vector > IA64_LAST_DEVICE_VECTOR)
+	int pos, vector;
+ again:
+	pos = find_first_zero_bit(ia64_vector_mask, IA64_NUM_DEVICE_VECTORS);
+	vector = IA64_FIRST_DEVICE_VECTOR + pos;
+	if (vector > IA64_LAST_DEVICE_VECTOR)
 		/* XXX could look for sharable vectors instead of panic'ing... */
 		panic("assign_irq_vector: out of interrupt vectors!");
-	return next_vector++;
+	if (test_and_set_bit(pos, ia64_vector_mask))
+		goto again;
+	return vector;
+}
+
+void
+free_irq_vector (int vector)
+{
+	int pos;
+
+	if (vector < IA64_FIRST_DEVICE_VECTOR || vector > IA64_LAST_DEVICE_VECTOR)
+		return;
+
+	pos = vector - IA64_FIRST_DEVICE_VECTOR;
+	if (!test_and_clear_bit(pos, ia64_vector_mask))
+		printk(KERN_WARNING "%s: double free!\n", __FUNCTION__);
 }
 
 extern unsigned int do_IRQ(unsigned long irq, struct pt_regs *regs);
arch/ia64/pci/pci.c renamed from arch/ia64/pci/pci.c~IRQ_deallocation_ia64 +8 -0
diff -puN arch/ia64/pci/pci.c~IRQ_deallocation_ia64 arch/ia64/pci/pci.c
@@ -431,6 +431,14 @@ pcibios_enable_device (struct pci_dev *d
 	return acpi_pci_irq_enable(dev);
 }
 
+#ifdef CONFIG_IA64_DEALLOCATE_IRQ
+void
+pcibios_disable_device (struct pci_dev *dev)
+{
+	acpi_pci_irq_disable(dev);
+}
+#endif /* CONFIG_IA64_DEALLOCATE_IRQ */
+
 void
 pcibios_align_resource (void *data, struct resource *res,
 		        unsigned long size, unsigned long align)
include/asm-ia64/acpi.h renamed from include/asm-ia64/acpi.h~IRQ_deallocation_ia64 +4 -0
diff -puN include/asm-ia64/acpi.h~IRQ_deallocation_ia64 include/asm-ia64/acpi.h
@@ -112,7 +112,11 @@ extern u16 ia64_acpiid_to_sapicid[];
  * If this matches the last registration, any IRQ resources for gsi
  * are freed.
  */
+#ifdef CONFIG_IA64_DEALLOCATE_IRQ
+void acpi_unregister_gsi (u32 gsi);
+#else
 static inline void acpi_unregister_gsi (u32 gsi) { }
+#endif /* CONFIG_IA64_DEALLOCATE_IRQ */
 
 #endif /*__KERNEL__*/
 
include/asm-ia64/hw_irq.h renamed from include/asm-ia64/hw_irq.h~IRQ_deallocation_ia64 +2 -0
diff -puN include/asm-ia64/hw_irq.h~IRQ_deallocation_ia64 include/asm-ia64/hw_irq.h
@@ -50,6 +50,7 @@ typedef u8 ia64_vector;
  */
 #define IA64_FIRST_DEVICE_VECTOR	0x30
 #define IA64_LAST_DEVICE_VECTOR		0xe7
+#define IA64_NUM_DEVICE_VECTORS		(IA64_LAST_DEVICE_VECTOR - IA64_FIRST_DEVICE_VECTOR + 1)
 
 #define IA64_MCA_RENDEZ_VECTOR		0xe8	/* MCA rendez interrupt */
 #define IA64_PERFMON_VECTOR		0xee	/* performanc monitor interrupt vector */
@@ -83,6 +84,7 @@ extern unsigned long ipi_base_addr;
 extern struct hw_interrupt_type irq_type_ia64_lsapic;	/* CPU-internal interrupt controller */
 
 extern int assign_irq_vector (int irq);	/* allocate a free vector */
+extern void free_irq_vector (int vector);
 extern void ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect);
 extern void register_percpu_irq (ia64_vector vec, struct irqaction *action);
 
include/asm-ia64/iosapic.h renamed from include/asm-ia64/iosapic.h~IRQ_deallocation_ia64 +4 -0
diff -puN include/asm-ia64/iosapic.h~IRQ_deallocation_ia64 include/asm-ia64/iosapic.h
@@ -78,6 +78,9 @@ extern int gsi_to_irq (unsigned int gsi)
 extern void iosapic_enable_intr (unsigned int vector);
 extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity,
 				  unsigned long trigger);
+#ifdef CONFIG_IA64_DEALLOCATE_IRQ
+extern void iosapic_unregister_intr (unsigned int irq);
+#endif
 extern void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi,
 				      unsigned long polarity,
 				      unsigned long trigger);
@@ -97,6 +100,7 @@ extern void __init map_iosapic_to_node (
 #define iosapic_system_init(pcat_compat)			do { } while (0)
 #define iosapic_init(address,gsi_base)				do { } while (0)
 #define iosapic_register_intr(gsi,polarity,trigger)		(gsi)
+#define iosapic_unregister_intr(irq)				do { } while (0)
 #define iosapic_override_isa_irq(isa_irq,gsi,polarity,trigger)	do { } while (0)
 #define iosapic_register_platform_intr(type,gsi,pmi,eid,id, \
 	polarity,trigger)					(gsi)

_