take2: [Patch 3/3] Updated patches for PCI IRQ deallocation support
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
@@ -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
@@ -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
@@ -874,8 +874,11 @@ int setup_irq(unsigned int irq, struct istruct 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
@@ -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
@@ -431,6 +431,14 @@ pcibios_enable_device (struct pci_dev *dreturn 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
@@ -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
@@ -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
@@ -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)
_