[patch 4/5] kexec/kdump update (2006-08-17.00)

From: <horms_at_tabatha.lab.ultramonkey.org>
Date: 2006-08-17 17:07:23
> Archived-At: <http://permalink.gmane.org/gmane.linux.ports.ia64/14677>
> 
> This patch is the kexec-kdump patch re-based to 2.6.18-rc4 kernel.
> 
> Changes since last patch include:
> 
> 1. re-base the patch to 2.6.18-rc4
> 2. per-cpu register dumping, so that user space tool can unwind kernel stack.
>    This should really done by INIT event. But unfortunately it seems that the 
>    firmware on the machine I am using does not handle INIT event correctly...
>    So current I dump per-cpu registers by simple IPI. 
> 	
> 3. fix on_line_cpu issue, 
>    previous patch stop APs by smp_send_stop. AP will clear his bit in 
>    cpu_online_map, then crash tools will see a cpu_online_map which only 
>    contains 1 cpu in vmcore file.
> 
> 4. reserve efi memmap area and ia64 boot param area for the first kernel.
> 
> To test crash dump.
> 
> Compile a kernel with CONFIG_KEXEC CONFIG_CRASH_DUMP 
> CONFIG_PROC_VMCORE enabled.
> 
> using this kernel for both host kernel and crash dumping kernel.
> 
> Boot this kernel with kernel parameter "crashkernel=XXX@YYY".
> XXX should be a size big enough for crash kernel to run, YYY should 
> be a physical address which contains more than XXX memory and aligned to 64M.
> you can check it in /proc/iomem.
> Be careful of choosing the size and address to reserve.
> The second kernel may hang silently if there is too few memory to use.
> 
> After the first kernel boots, the "Crash kernel" region will show in /proc/iomem.
> then load the same kernel with command.
> 
> kexec -p vmlinux.gz --initrd=initrd --append="root=... maxcpus=1"
> 
> trigger a crash with echo c > /proc/sysrq-trigger
> 
> after the crash kernel boots, 
> copy /proc/vmcore to disk
> 
> gdb vmlinux-of-first-kernel vmcore
> then you can check the stack and variables of first kernel.
> 
> kexec -l + kexec -e may not work.
> That is because of a recent change in mpt-fusion driver 
> shutdown code. 
> There was some delay in mptscsih_remove path. 
> the code was removed in 2.6.17, that cause MPT fusion driver unable to reinitialize.
> add a delay back to mptscsih_remove can solve this problem.
> 
> 
> Signed-off-by:
>  Zou Nan hai <nanhai.zou@intel.com>

Incremental version of the patch posted by Zou Nan hai

Cc: Zou Nan hai <nanhai.zou@intel.com>
Signed-off-by: Simon Horman <horms@verge.net.au>

 arch/ia64/kernel/crash.c           |   77 ++++++------------
 arch/ia64/kernel/efi.c             |    2 
 arch/ia64/kernel/machine_kexec.c   |   66 ++++++++++------
 arch/ia64/kernel/relocate_kernel.S |  147 ++++++++++++++++++++++++++++++++++--
 arch/ia64/kernel/setup.c           |    9 ++
 arch/ia64/kernel/smp.c             |   18 ++++
 include/asm-ia64/kexec.h           |    6 +
 include/linux/irq.h                |    1 
 kernel/irq/manage.c                |   13 ---
 9 files changed, 243 insertions(+), 96 deletions(-)

diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c
index a1a192c..5b7514c 100644
--- a/arch/ia64/kernel/crash.c
+++ b/arch/ia64/kernel/crash.c
@@ -43,25 +43,23 @@ size_t copy_oldmem_page(unsigned long pf
 
 static void device_shootdown(void)
 {
-       struct pci_dev *dev;
-       irq_desc_t *desc;
-       u16 pci_command;
+	irq_desc_t *idesc;
+	int irq;
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		idesc = irq_desc + irq;
+		if (!idesc || !idesc->action)
+			continue;
+		disable_irq_nosync(irq);
+		idesc->chip->end(irq);
+		idesc->chip->shutdown(irq);
+	}
 
-       list_for_each_entry(dev, &pci_devices, global_list) {
-	       desc = irq_desc + dev->irq;
-               if (!desc->action)
-                       continue;
-               pci_read_config_word(dev, PCI_COMMAND, &pci_command);
-               if (pci_command & PCI_COMMAND_MASTER) {
-                       pci_command &= ~PCI_COMMAND_MASTER;
-                       pci_write_config_word(dev, PCI_COMMAND, pci_command);
-               }
-               disable_irq_nosync(dev->irq);
-               desc->chip->end(dev->irq);
-       }
+#ifdef CONFIG_IA64_HP_ZX1
+	ioc_iova_disable();
+#endif
 }
 
-static Elf64_Word
+static inline Elf64_Word
 *append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
 		size_t data_len)
 {
@@ -83,41 +81,25 @@ final_note(void *buf)
 	memset(buf, 0, sizeof(struct elf_note));
 }
 
-static void
-crash_save_this_cpu(void)
+extern void ia64_dump_cpu_regs(void *);
+
+void
+crash_save_this_cpu()
 {
 	void *buf;
 	struct elf_prstatus prstatus;
 	int cpu = smp_processor_id();
+	unsigned long cfm, sof, sol;
 	elf_greg_t *dst = (elf_greg_t *)&prstatus.pr_reg;
-
 	memset(&prstatus, 0, sizeof(prstatus));
 	prstatus.pr_pid = current->pid;
 
-    	dst[1] = ia64_getreg(_IA64_REG_GP);
-    	dst[12] = ia64_getreg(_IA64_REG_SP);
-    	dst[13] = ia64_getreg(_IA64_REG_TP);
-
-    	dst[42] = ia64_getreg(_IA64_REG_IP);
-    	dst[45] = ia64_getreg(_IA64_REG_AR_RSC);
-
-	ia64_setreg(_IA64_REG_AR_RSC, 0);
-	ia64_srlz_i();
-
-    	dst[46] = ia64_getreg(_IA64_REG_AR_BSP);
-    	dst[47] = ia64_getreg(_IA64_REG_AR_BSPSTORE);
-
-    	dst[48] = ia64_getreg(_IA64_REG_AR_RNAT);
-    	dst[49] = ia64_getreg(_IA64_REG_AR_CCV);
-    	dst[50] = ia64_getreg(_IA64_REG_AR_UNAT);
-
-    	dst[51] = ia64_getreg(_IA64_REG_AR_FPSR);
-    	dst[52] = ia64_getreg(_IA64_REG_AR_PFS);
-    	dst[53] = ia64_getreg(_IA64_REG_AR_LC);
-
-    	dst[54] = ia64_getreg(_IA64_REG_AR_LC);
-    	dst[55] = ia64_getreg(_IA64_REG_AR_CSD);
-    	dst[56] = ia64_getreg(_IA64_REG_AR_SSD);
+	ia64_dump_cpu_regs(dst);
+        cfm = dst[43];
+        sol = (cfm >> 7) & 0x7f;
+        sof = cfm & 0x7f;
+        dst[46] = (unsigned long)ia64_rse_skip_regs((unsigned long *)dst[46],
+                        sof - sol);
 
         buf = (u64 *) per_cpu_ptr(crash_notes, cpu);
 	if (!buf)
@@ -138,15 +120,10 @@ machine_crash_shutdown(struct pt_regs *p
 	 * In practice this means shooting down the other cpus in
 	 * an SMP system.
 	 */
-	if (in_interrupt()) {
+	if (in_interrupt())
 		ia64_eoi();
-	}
-	crash_save_this_cpu();
 	device_shootdown();
 #ifdef CONFIG_SMP
-	smp_send_stop();
-#endif
-#ifdef CONFIG_IA64_HP_ZX1
-	ioc_iova_disable();
+	kdump_smp_send_stop();
 #endif
 }
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 52729a9..6935452 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -1124,6 +1124,8 @@ efi_initialize_iomem_resources(struct re
 			insert_resource(res, code_resource);
 			insert_resource(res, data_resource);
 #ifdef CONFIG_KEXEC
+                        insert_resource(res, &efi_memmap_res);
+                        insert_resource(res, &boot_param_res);
 			if (crashk_res.end > crashk_res.start)
 				insert_resource(res, &crashk_res);
 #endif
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c
index 573a6b8..2073a3d 100644
--- a/arch/ia64/kernel/machine_kexec.c
+++ b/arch/ia64/kernel/machine_kexec.c
@@ -1,5 +1,5 @@
 /*
- * arch/ia64/kernel/machine_kexec.c 
+ * arch/ia64/kernel/machine_kexec.c
  *
  * Handle transition of Linux booting another kernel
  * Copyright (C) 2005 Hewlett-Packard Development Comapny, L.P.
@@ -27,6 +27,21 @@ #include <asm/meminit.h>
 
 typedef void (*relocate_new_kernel_t)(unsigned long, unsigned long,
 		struct ia64_boot_param *, unsigned long);
+static struct kimage *ia64_kimage;
+struct resource efi_memmap_res = {
+        .name  = "EFI Memory Map",
+        .start = 0,
+        .end   = 0,
+        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+struct resource boot_param_res = {
+        .name  = "Boot parameter",
+        .start = 0,
+        .end   = 0,
+        .flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
 
 /*
  * Do what every setup is needed on image and the
@@ -41,10 +56,11 @@ int machine_kexec_prepare(struct kimage 
 	func = (unsigned long *)&relocate_new_kernel;
 	/* Pre-load control code buffer to minimize work in kexec path */
 	control_code_buffer = page_address(image->control_code_page);
-	memcpy((void *)control_code_buffer, (const void *)func[0], 
+	memcpy((void *)control_code_buffer, (const void *)func[0],
 			relocate_new_kernel_size);
-	flush_icache_range((unsigned long)control_code_buffer, 
+	flush_icache_range((unsigned long)control_code_buffer,
 			(unsigned long)control_code_buffer + relocate_new_kernel_size);
+	ia64_kimage = image;
 
 	return 0;
 }
@@ -55,26 +71,6 @@ void machine_kexec_cleanup(struct kimage
 
 void machine_shutdown(void)
 {
-#ifdef CONFIG_PCI
-	struct pci_dev *dev = NULL;
-	irq_desc_t *idesc;
-	cpumask_t mask = CPU_MASK_NONE;
-	/* Disable all PCI devices */
-	while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
-		if (!(dev->is_enabled))
-			continue;
-		idesc = irq_desc + dev->irq;
-		if (!idesc)
-			continue;
-		cpu_set(0, mask);
-		disable_irq_nosync(dev->irq);
-		idesc->chip->end(dev->irq);
-		idesc->chip->set_affinity(dev->irq, mask);
-		idesc->action = NULL;
-		pci_disable_device(dev);
-	}
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 	{
 		int cpu;
@@ -85,7 +81,25 @@ #ifdef CONFIG_HOTPLUG_CPU
 		}
 	}
 #elif defined(CONFIG_SMP)
-	smp_call_function(kexec_stop_this_cpu, (void *)image->start, 0, 0);
+	smp_call_function(kexec_stop_this_cpu, (void *)ia64_kimage->start, 0, 0);
+#endif
+#ifdef CONFIG_PCI
+	{
+		struct pci_dev *dev = NULL;
+		irq_desc_t *idesc;
+		/* Disable all PCI devices */
+		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
+			if (!(dev->is_enabled))
+				continue;
+			idesc = irq_desc + dev->irq;
+			if (!idesc||!idesc->chip)
+				continue;
+			disable_irq_nosync(dev->irq);
+			idesc->chip->end(dev->irq);
+			idesc->action = NULL;
+			pci_disable_device(dev);
+		}
+	}
 #endif
 
 
@@ -96,7 +110,7 @@ #endif
 
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
- * We are past the point of no return, committed to rebooting now. 
+ * We are past the point of no return, committed to rebooting now.
  */
 extern void *efi_get_pal_addr(void);
 void machine_kexec(struct kimage *image)
@@ -104,6 +118,8 @@ void machine_kexec(struct kimage *image)
 	relocate_new_kernel_t rnk;
 	void *pal_addr = efi_get_pal_addr();
 	unsigned long code_addr = (unsigned long)page_address(image->control_code_page);
+	if (image->type == KEXEC_TYPE_CRASH)
+		crash_save_this_cpu();
 	/* Interrupts aren't acceptable while we reboot */
 	ia64_set_itv(1<<16);
 	local_irq_disable();
diff --git a/arch/ia64/kernel/relocate_kernel.S b/arch/ia64/kernel/relocate_kernel.S
index 09bd041..ffc1bde 100644
--- a/arch/ia64/kernel/relocate_kernel.S
+++ b/arch/ia64/kernel/relocate_kernel.S
@@ -1,5 +1,5 @@
 /*
- * arch/ia64/kernel/relocate_kernel.S 
+ * arch/ia64/kernel/relocate_kernel.S
  *
  * Relocate kexec'able kernel and start it
  *
@@ -304,7 +304,7 @@ check_irr0:
 	cmp.eq	p6,p0=0,r8
 (p6)	br.cond.sptk.few	check_irr0
 	br.few	call_start
-	
+
 check_irr1:
 	mov	r8=cr.irr1
 	;;
@@ -313,7 +313,7 @@ check_irr1:
 	cmp.eq	p6,p0=0,r8
 (p6)	br.cond.sptk.few	check_irr1
 	br.few	call_start
-	
+
 check_irr2:
 	mov	r8=cr.irr2
 	;;
@@ -322,7 +322,7 @@ check_irr2:
 	cmp.eq	p6,p0=0,r8
 (p6)	br.cond.sptk.few	check_irr2
 	br.few	call_start
-	
+
 check_irr3:
 	mov	r8=cr.irr3
 	;;
@@ -331,7 +331,7 @@ check_irr3:
 	cmp.eq	p6,p0=0,r8
 (p6)	br.cond.sptk.few	check_irr3
 	br.few	call_start
-	
+
 call_start:
 	mov	cr.eoi=r0
 	;;
@@ -351,3 +351,140 @@ END(kexec_fake_sal_rendez)
 relocate_new_kernel_size:
 	data8	kexec_fake_sal_rendez_end - relocate_new_kernel
 
+GLOBAL_ENTRY(ia64_dump_cpu_regs)
+        .prologue
+        alloc loc0=ar.pfs,1,2,0,0
+        .body
+        mov     ar.rsc=0                // put RSE in enforced lazy mode
+        add     loc1=4*8, in0           // save r4 and r5 first
+        ;;
+{
+        flushrs                         // flush dirty regs to backing store
+        srlz.i
+}
+        st8 [loc1]=r4, 8
+        ;;
+        st8 [loc1]=r5, 8
+        ;;
+        add loc1=32*8, in0
+        mov r4=ar.rnat
+        ;;
+        st8 [in0]=r0, 8			// r0
+        st8 [loc1]=r4, 8		// rnat
+        mov r5=pr
+        ;;
+        st8 [in0]=r1, 8			// r1
+        st8 [loc1]=r5, 8		// pr
+        mov r4=b0
+        ;;
+        st8 [in0]=r2, 8			// r2
+        st8 [loc1]=r4, 8		// b0
+        mov r5=b1;
+        ;;
+        st8 [in0]=r3, 24		// r3
+        st8 [loc1]=r5, 8		// b1
+        mov r4=b2
+        ;;
+        st8 [in0]=r6, 8			// r6
+        st8 [loc1]=r4, 8		// b2
+	mov r5=b3
+        ;;
+        st8 [in0]=r7, 8			// r7
+        st8 [loc1]=r5, 8		// b3
+        mov r4=b4
+        ;;
+        st8 [in0]=r8, 8			// r8
+        st8 [loc1]=r4, 8		// b4
+        mov r5=b5
+        ;;
+        st8 [in0]=r9, 8			// r9
+        st8 [loc1]=r5, 8		// b5
+        mov r4=b6
+        ;;
+        st8 [in0]=r10, 8		// r10
+        st8 [loc1]=r5, 8		// b6
+        mov r5=b7
+        ;;
+        st8 [in0]=r11, 8		// r11
+        st8 [loc1]=r5, 8		// b7
+        mov r4=b0
+        ;;
+        st8 [in0]=r12, 8		// r12
+        st8 [loc1]=r4, 8		// ip
+        mov r5=loc0
+	;;
+        st8 [in0]=r13, 8		// r13
+        extr.u r5=r5, 0, 38		// ar.pfs.pfm
+	mov r4=r0			// user mask
+        ;;
+        st8 [in0]=r14, 8		// r14
+        st8 [loc1]=r5, 8		// cfm
+        ;;
+        st8 [in0]=r15, 8		// r15
+        st8 [loc1]=r4, 8        	// user mask
+	mov r5=ar.rsc
+        ;;
+        st8 [in0]=r16, 8		// r16
+        st8 [loc1]=r5, 8        	// ar.rsc
+        mov r4=ar.bsp
+        ;;
+        st8 [in0]=r17, 8		// r17
+        st8 [loc1]=r4, 8        	// ar.bsp
+        mov r5=ar.bspstore
+        ;;
+        st8 [in0]=r18, 8		// r18
+        st8 [loc1]=r5, 8        	// ar.bspstore
+        mov r4=ar.rnat
+        ;;
+        st8 [in0]=r19, 8		// r19
+        st8 [loc1]=r4, 8        	// ar.rnat
+        mov r5=ar.ccv
+        ;;
+        st8 [in0]=r20, 8		// r20
+	st8 [loc1]=r5, 8        	// ar.ccv
+        mov r4=ar.unat
+        ;;
+        st8 [in0]=r21, 8		// r21
+        st8 [loc1]=r4, 8        	// ar.unat
+        mov r5 = ar.fpsr
+        ;;
+        st8 [in0]=r22, 8		// r22
+        st8 [loc1]=r5, 8        	// ar.fpsr
+        mov r4 = ar.unat
+        ;;
+        st8 [in0]=r23, 8		// r23
+        st8 [loc1]=r4, 8        	// unat
+        mov r5 = ar.fpsr
+        ;;
+        st8 [in0]=r24, 8		// r24
+        st8 [loc1]=r5, 8        	// fpsr
+        mov r4 = ar.pfs
+        ;;
+        st8 [in0]=r25, 8		// r25
+        st8 [loc1]=r4, 8        	// ar.pfs
+        mov r5 = ar.lc
+        ;;
+        st8 [in0]=r26, 8		// r26
+        st8 [loc1]=r5, 8        	// ar.lc
+        mov r4 = ar.ec
+        ;;
+        st8 [in0]=r27, 8		// r27
+        st8 [loc1]=r4, 8        	// ar.ec
+        mov r5 = ar.csd
+        ;;
+        st8 [in0]=r28, 8		// r28
+        st8 [loc1]=r5, 8        	// ar.csd
+        mov r4 = ar.ssd
+        ;;
+        st8 [in0]=r29, 8		// r29
+        st8 [loc1]=r4, 8        	// ar.ssd
+        ;;
+        st8 [in0]=r30, 8		// r30
+        ;;
+	st8 [in0]=r31, 8		// r31
+        mov ar.pfs=loc0
+        ;;
+        br.ret.sptk.many rp
+END(ia64_dump_cpu_regs)
+
+
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index 74821be..14ee171 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -275,6 +275,15 @@ #ifdef CONFIG_KEXEC
 				n++;
 			}
 		}
+		efi_memmap_res.start = ia64_boot_param->efi_memmap;
+                efi_memmap_res.end = efi_memmap_res.start +
+                        ia64_boot_param->efi_memmap_size;
+                printk("efi_memmap start %lx %lx\n",
+                        efi_memmap_res.start,
+                        efi_memmap_res.end);
+                boot_param_res.start = __pa(ia64_boot_param);
+                boot_param_res.end = boot_param_res.start +
+                        sizeof(*ia64_boot_param);
 	}
 #endif
 
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 6337278..dee9fd7 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -67,6 +67,7 @@ static volatile struct call_data_struct 
 
 #define IPI_CALL_FUNC		0
 #define IPI_CPU_STOP		1
+#define IPI_KDUMP_CPU_STOP	3
 
 /* This needs to be cacheline aligned because it is written to by *other* CPUs.  */
 static DEFINE_PER_CPU(u64, ipi_operation) ____cacheline_aligned;
@@ -184,7 +185,15 @@ handle_IPI (int irq, void *dev_id, struc
 			      case IPI_CPU_STOP:
 				stop_this_cpu();
 				break;
-
+#ifdef CONFIG_CRASH_DUMP
+			      case IPI_KDUMP_CPU_STOP:
+				{
+					local_irq_disable();
+					crash_save_this_cpu();
+					cpu_halt();
+				}
+				break;
+#endif
 			      default:
 				printk(KERN_CRIT "Unknown IPI on CPU %d: %lu\n", this_cpu, which);
 				break;
@@ -400,6 +409,13 @@ smp_send_stop (void)
 {
 	send_IPI_allbutself(IPI_CPU_STOP);
 }
+#ifdef CONFIG_CRASH_DUMP
+void
+kdump_smp_send_stop()
+{
+ 	send_IPI_allbutself(IPI_KDUMP_CPU_STOP);
+}
+#endif
 
 int __init
 setup_profiling_timer (unsigned int multiplier)
diff --git a/include/asm-ia64/kexec.h b/include/asm-ia64/kexec.h
index d45c03f..a035136 100644
--- a/include/asm-ia64/kexec.h
+++ b/include/asm-ia64/kexec.h
@@ -23,7 +23,7 @@ #define POW2(n)		(1ULL << (n))
 DECLARE_PER_CPU(u64, ia64_mca_pal_base);
 const extern unsigned int relocate_new_kernel_size;
 volatile extern long kexec_rendez;
-extern void relocate_new_kernel(unsigned long, unsigned long, 
+extern void relocate_new_kernel(unsigned long, unsigned long,
 		struct ia64_boot_param *, unsigned long);
 extern void kexec_fake_sal_rendez(void *start, unsigned long wake_up,
 		unsigned long pal_base);
@@ -31,4 +31,8 @@ static inline void
 crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
 {
 }
+extern struct resource efi_memmap_res;
+extern struct resource boot_param_res;
+extern void kdump_smp_send_stop(void);
+extern void crash_save_this_cpu(void);
 #endif /* _ASM_IA64_KEXEC_H */
diff --git a/include/asm-ia64/machvec_hpzx1.h b/include/asm-ia64/machvec_hpzx1.h
diff --git a/include/asm-ia64/meminit.h b/include/asm-ia64/meminit.h
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 9b5349f..fbf6d90 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -182,7 +182,6 @@ typedef struct irq_desc		irq_desc_t;
 #include <asm/hw_irq.h>
 
 extern int setup_irq(unsigned int irq, struct irqaction *new);
-extern void terminate_irqs(void);
 
 #ifdef CONFIG_GENERIC_HARDIRQS
 
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index e058bad..a795d6f 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -475,16 +475,3 @@ #endif
 	return retval;
 }
 EXPORT_SYMBOL(request_irq);
-
-/*
- * Terminate any outstanding interrupts
- */
-void terminate_irqs(void)
-{
-	irq_desc_t *desc = irq_desc;
-	int i;
-
-	for (i = 0; i < NR_IRQS; i++, desc++)
-		if (desc->action && desc->chip->end)
-			desc->chip->end(i);
-}

--

-- 
Horms
  H: http://www.vergenet.net/~horms/
  W: http://www.valinux.co.jp/en/

-
To unsubscribe from this list: send the line "unsubscribe linux-ia64" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Received on Thu Aug 17 17:19:20 2006

This archive was generated by hypermail 2.1.8 : 2006-08-17 17:21:31 EST