ia64/xen-unstable

changeset 4113:1d420c415398

bitkeeper revision 1.1236.25.9 (42335c497Bt0QbOvYK3fGa02eZ4_Sw)

Update to Linux 2.6.11.
Signed-off-by: Christian Limpach <chris@xensource.com>
author cl349@firebug.cl.cam.ac.uk
date Sat Mar 12 21:16:57 2005 +0000 (2005-03-12)
parents db5a30a327e6
children 508b288d20e2
files .rootkeys linux-2.6.10-xen-sparse/arch/xen/i386/kernel/irq.c linux-2.6.10-xen-sparse/arch/xen/i386/kernel/smp.c linux-2.6.10-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6.10-xen-sparse/arch/xen/kernel/smp.c linux-2.6.10-xen-sparse/drivers/xen/blktap/Makefile linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.h linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_datapath.c linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_userdev.c linux-2.6.10-xen-sparse/drivers/xen/usbback/common.h linux-2.6.10-xen-sparse/drivers/xen/usbback/control.c linux-2.6.10-xen-sparse/drivers/xen/usbback/interface.c linux-2.6.10-xen-sparse/drivers/xen/usbback/usbback.c linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/spinlock.h linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smp.c linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c linux-2.6.11-xen-sparse/drivers/xen/blktap/Makefile linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap.h linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_datapath.c linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_userdev.c linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c linux-2.6.11-xen-sparse/drivers/xen/usbback/common.h linux-2.6.11-xen-sparse/drivers/xen/usbback/control.c linux-2.6.11-xen-sparse/drivers/xen/usbback/interface.c linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/spinlock.h
line diff
     1.1 --- a/.rootkeys	Sat Mar 12 20:44:12 2005 +0000
     1.2 +++ b/.rootkeys	Sat Mar 12 21:16:57 2005 +0000
     1.3 @@ -134,24 +134,6 @@ 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4
     1.4  3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.29-xen-sparse/mm/swapfile.c
     1.5  41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.29-xen-sparse/mm/vmalloc.c
     1.6  41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.29-xen-sparse/net/core/skbuff.c
     1.7 -41d00d82zN8IfLBRxc7G_i7lbwT3cQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/irq.c
     1.8 -41811cac4lkCB-fHir6CcxuEJ2pGsQ linux-2.6.10-xen-sparse/arch/xen/i386/kernel/smp.c
     1.9 -41811ca9mbGpqBrZVrUGEiv8CTV3ng linux-2.6.10-xen-sparse/arch/xen/i386/kernel/smpboot.c
    1.10 -418f90e4lGdeJK9rmbOB1kN-IKSjsQ linux-2.6.10-xen-sparse/arch/xen/kernel/smp.c
    1.11 -41a226e0vjAcDXHOnXE5ummcdUD2mg linux-2.6.10-xen-sparse/drivers/xen/blktap/Makefile
    1.12 -41a226e0VeZA1N8tbU6nvJ3OxUcJmw linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.c
    1.13 -41a226e1k4J5VMLnrYXDWRqElS49YQ linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.h
    1.14 -41a226e1-A_Hy7utS8vJKaXnH_tzfA linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
    1.15 -41a226e19NoUUTOvs7jumDMRYDIO4Q linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_datapath.c
    1.16 -41a226e1MNSyWWK5dEVgvSQ5OW0fDA linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_userdev.c
    1.17 -41ee5e8bYDQkjRVKnFn5uFyy0KreCw linux-2.6.10-xen-sparse/drivers/xen/usbback/common.h
    1.18 -41ee5e8bt7xeBUJqG5XJS-ofukdsgA linux-2.6.10-xen-sparse/drivers/xen/usbback/control.c
    1.19 -41ee5e8bSs3BGC7yegM_ek2Tn0Ahvw linux-2.6.10-xen-sparse/drivers/xen/usbback/interface.c
    1.20 -41ee5e8bglvqKvZSY5uJ5JGQejEwyQ linux-2.6.10-xen-sparse/drivers/xen/usbback/usbback.c
    1.21 -41ee5e8ckZ9xVNvu9NHIZDK7JqApmQ linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c
    1.22 -41ee5e8ck9scpGirfqEZRARbGDyTXA linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h
    1.23 -41811f07Iri9hrvs97t-baxmhOwWDQ linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h
    1.24 -4198c32a8NzmcKVOzKaEJfaQxxiA0A linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/spinlock.h
    1.25  40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.11-xen-sparse/arch/xen/Kconfig
    1.26  40f56237utH41NPukqHksuNf29IC9A linux-2.6.11-xen-sparse/arch/xen/Kconfig.drivers
    1.27  40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.11-xen-sparse/arch/xen/Makefile
    1.28 @@ -169,12 +151,15 @@ 40f56238XDtHSijkAFlbv1PT8Bhw_Q linux-2.6
    1.29  40f56238bnvciAuyzAiMkdzGErYt1A linux-2.6.11-xen-sparse/arch/xen/i386/kernel/head.S
    1.30  40f58a0d31M2EkuPbG94ns_nOi0PVA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/i386_ksyms.c
    1.31  40faa751_zbZlAmLyQgCXdYekVFdWA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ioport.c
    1.32 +41d00d82zN8IfLBRxc7G_i7lbwT3cQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c
    1.33  40f56238ue3YRsK52HG7iccNzP1AwQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/ldt.c
    1.34  41d54a76YMCA67S8J-TBT3J62Wx6yA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/microcode.c
    1.35  4107adf1cNtsuOxOB4T6paAoY2R2PA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/pci-dma.c
    1.36  40f56238a8iOVDEoostsbun_sy2i4g linux-2.6.11-xen-sparse/arch/xen/i386/kernel/process.c
    1.37  40f56238YQIJoYG2ehDGEcdTgLmGbg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/setup.c
    1.38  40f56238nWMQg7CKbyTy0KJNvCzbtg linux-2.6.11-xen-sparse/arch/xen/i386/kernel/signal.c
    1.39 +41811cac4lkCB-fHir6CcxuEJ2pGsQ linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smp.c
    1.40 +41811ca9mbGpqBrZVrUGEiv8CTV3ng linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
    1.41  40f56238qVGkpO_ycnQA8k03kQzAgA linux-2.6.11-xen-sparse/arch/xen/i386/kernel/time.c
    1.42  40f56238NzTgeO63RGoxHrW5NQeO3Q linux-2.6.11-xen-sparse/arch/xen/i386/kernel/timers/Makefile
    1.43  40f56238BMqG5PuSHufpjbvp_helBw linux-2.6.11-xen-sparse/arch/xen/i386/kernel/timers/timer_tsc.c
    1.44 @@ -200,6 +185,7 @@ 4110f478aeQWllIN7J4kouAHiAqrPw linux-2.6
    1.45  412dfae9eA3_6e6bCGUtg1mj8b56fQ linux-2.6.11-xen-sparse/arch/xen/kernel/gnttab.c
    1.46  40f562392LBhwmOxVPsYdkYXMxI_ZQ linux-2.6.11-xen-sparse/arch/xen/kernel/reboot.c
    1.47  414c113396tK1HTVeUalm3u-1DF16g linux-2.6.11-xen-sparse/arch/xen/kernel/skbuff.c
    1.48 +418f90e4lGdeJK9rmbOB1kN-IKSjsQ linux-2.6.11-xen-sparse/arch/xen/kernel/smp.c
    1.49  3f68905c5eiA-lBMQSvXLMWS1ikDEA linux-2.6.11-xen-sparse/arch/xen/kernel/xen_proc.c
    1.50  41261688yS8eAyy-7kzG4KBs0xbYCA linux-2.6.11-xen-sparse/drivers/Makefile
    1.51  4108f5c1WfTIrs0HZFeV39sttekCTw linux-2.6.11-xen-sparse/drivers/char/mem.c
    1.52 @@ -218,6 +204,12 @@ 40f562395atl9x4suKGhPkjqLOXESg linux-2.6
    1.53  40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.11-xen-sparse/drivers/xen/blkfront/blkfront.c
    1.54  40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.11-xen-sparse/drivers/xen/blkfront/block.h
    1.55  40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.11-xen-sparse/drivers/xen/blkfront/vbd.c
    1.56 +41a226e0vjAcDXHOnXE5ummcdUD2mg linux-2.6.11-xen-sparse/drivers/xen/blktap/Makefile
    1.57 +41a226e0VeZA1N8tbU6nvJ3OxUcJmw linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap.c
    1.58 +41a226e1k4J5VMLnrYXDWRqElS49YQ linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap.h
    1.59 +41a226e1-A_Hy7utS8vJKaXnH_tzfA linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
    1.60 +41a226e19NoUUTOvs7jumDMRYDIO4Q linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_datapath.c
    1.61 +41a226e1MNSyWWK5dEVgvSQ5OW0fDA linux-2.6.11-xen-sparse/drivers/xen/blktap/blktap_userdev.c
    1.62  40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.11-xen-sparse/drivers/xen/console/Makefile
    1.63  3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.11-xen-sparse/drivers/xen/console/console.c
    1.64  40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.11-xen-sparse/drivers/xen/evtchn/Makefile
    1.65 @@ -232,6 +224,12 @@ 40f56239Wd4k_ycG_mFsSO1r5xKdtQ linux-2.6
    1.66  405853f6nbeazrNyEWNHBuoSg2PiPA linux-2.6.11-xen-sparse/drivers/xen/netfront/netfront.c
    1.67  4108f5c1ppFXVpQzCOAZ6xXYubsjKA linux-2.6.11-xen-sparse/drivers/xen/privcmd/Makefile
    1.68  3e5a4e65IUfzzMu2kZFlGEB8-rpTaA linux-2.6.11-xen-sparse/drivers/xen/privcmd/privcmd.c
    1.69 +41ee5e8bYDQkjRVKnFn5uFyy0KreCw linux-2.6.11-xen-sparse/drivers/xen/usbback/common.h
    1.70 +41ee5e8bt7xeBUJqG5XJS-ofukdsgA linux-2.6.11-xen-sparse/drivers/xen/usbback/control.c
    1.71 +41ee5e8bSs3BGC7yegM_ek2Tn0Ahvw linux-2.6.11-xen-sparse/drivers/xen/usbback/interface.c
    1.72 +41ee5e8bglvqKvZSY5uJ5JGQejEwyQ linux-2.6.11-xen-sparse/drivers/xen/usbback/usbback.c
    1.73 +41ee5e8ckZ9xVNvu9NHIZDK7JqApmQ linux-2.6.11-xen-sparse/drivers/xen/usbfront/usbfront.c
    1.74 +41ee5e8ck9scpGirfqEZRARbGDyTXA linux-2.6.11-xen-sparse/drivers/xen/usbfront/xhci.h
    1.75  412f47e4RKD-R5IS5gEXvcT8L4v8gA linux-2.6.11-xen-sparse/include/asm-generic/pgtable.h
    1.76  40f56239YAjS52QG2FIAQpHDZAdGHg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/desc.h
    1.77  4107adf1E5O4ztGHNGMzCCNhcvqNow linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/dma-mapping.h
    1.78 @@ -242,6 +240,7 @@ 40f5623aJVXQwpJMOLE99XgvGsfQ8Q linux-2.6
    1.79  40f5623aKXkBBxgpLx2NcvkncQ1Yyw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/irq_vectors.h
    1.80  40f5623aDMCsWOFO0jktZ4e8sjwvEg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_post.h
    1.81  40f5623arsFXkGdPvIqvFi3yFXGR0Q linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/setup_arch_pre.h
    1.82 +41811f07Iri9hrvs97t-baxmhOwWDQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h
    1.83  4120f807GCO0uqsLqdZj9csxR1Wthw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/mmu_context.h
    1.84  40f5623adgjZq9nAgCt0IXdWl7udSA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h
    1.85  40f5623a54NuG-7qHihGYmw4wWQnMA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/param.h
    1.86 @@ -254,6 +253,7 @@ 40f5623aPCkQQfPtJSooGdhcatrvnQ linux-2.6
    1.87  412ea0afQL2CAI-f522TbLjLPMibPQ linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/ptrace.h
    1.88  40f5623bzLvxr7WoJIxVf2OH4rCBJg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/segment.h
    1.89  40f5623bG_LzgG6-qwk292nTc5Wabw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/setup.h
    1.90 +4198c32a8NzmcKVOzKaEJfaQxxiA0A linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/spinlock.h
    1.91  40f5623bgzm_9vwxpzJswlAxg298Gg linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/synch_bitops.h
    1.92  40f5623bVdKP7Dt7qm8twu3NcnGNbA linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h
    1.93  40f5623bc8LKPRO09wY5dGDnY_YCpw linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/tlbflush.h
     2.1 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/irq.c	Sat Mar 12 20:44:12 2005 +0000
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,258 +0,0 @@
     2.4 -/*
     2.5 - *	linux/arch/i386/kernel/irq.c
     2.6 - *
     2.7 - *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
     2.8 - *
     2.9 - * This file contains the lowest level x86-specific interrupt
    2.10 - * entry, irq-stacks and irq statistics code. All the remaining
    2.11 - * irq logic is done by the generic kernel/irq/ code and
    2.12 - * by the x86-specific irq controller code. (e.g. i8259.c and
    2.13 - * io_apic.c.)
    2.14 - */
    2.15 -
    2.16 -#include <asm/uaccess.h>
    2.17 -#include <linux/module.h>
    2.18 -#include <linux/seq_file.h>
    2.19 -#include <linux/interrupt.h>
    2.20 -#include <linux/kernel_stat.h>
    2.21 -
    2.22 -#ifndef CONFIG_X86_LOCAL_APIC
    2.23 -/*
    2.24 - * 'what should we do if we get a hw irq event on an illegal vector'.
    2.25 - * each architecture has to answer this themselves.
    2.26 - */
    2.27 -void ack_bad_irq(unsigned int irq)
    2.28 -{
    2.29 -	printk("unexpected IRQ trap at vector %02x\n", irq);
    2.30 -}
    2.31 -#endif
    2.32 -
    2.33 -#ifdef CONFIG_4KSTACKS
    2.34 -/*
    2.35 - * per-CPU IRQ handling contexts (thread information and stack)
    2.36 - */
    2.37 -union irq_ctx {
    2.38 -	struct thread_info      tinfo;
    2.39 -	u32                     stack[THREAD_SIZE/sizeof(u32)];
    2.40 -};
    2.41 -
    2.42 -static union irq_ctx *hardirq_ctx[NR_CPUS];
    2.43 -static union irq_ctx *softirq_ctx[NR_CPUS];
    2.44 -#endif
    2.45 -
    2.46 -/*
    2.47 - * do_IRQ handles all normal device IRQ's (the special
    2.48 - * SMP cross-CPU interrupts have their own specific
    2.49 - * handlers).
    2.50 - */
    2.51 -fastcall unsigned int do_IRQ(struct pt_regs *regs)
    2.52 -{	
    2.53 -	/* high bits used in ret_from_ code */
    2.54 -	int irq = regs->orig_eax & __IRQ_MASK(HARDIRQ_BITS);
    2.55 -#ifdef CONFIG_4KSTACKS
    2.56 -	union irq_ctx *curctx, *irqctx;
    2.57 -	u32 *isp;
    2.58 -#endif
    2.59 -
    2.60 -	irq_enter();
    2.61 -#ifdef CONFIG_DEBUG_STACKOVERFLOW
    2.62 -	/* Debugging check for stack overflow: is there less than 1KB free? */
    2.63 -	{
    2.64 -		long esp;
    2.65 -
    2.66 -		__asm__ __volatile__("andl %%esp,%0" :
    2.67 -					"=r" (esp) : "0" (THREAD_SIZE - 1));
    2.68 -		if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
    2.69 -			printk("do_IRQ: stack overflow: %ld\n",
    2.70 -				esp - sizeof(struct thread_info));
    2.71 -			dump_stack();
    2.72 -		}
    2.73 -	}
    2.74 -#endif
    2.75 -
    2.76 -#ifdef CONFIG_4KSTACKS
    2.77 -
    2.78 -	curctx = (union irq_ctx *) current_thread_info();
    2.79 -	irqctx = hardirq_ctx[smp_processor_id()];
    2.80 -
    2.81 -	/*
    2.82 -	 * this is where we switch to the IRQ stack. However, if we are
    2.83 -	 * already using the IRQ stack (because we interrupted a hardirq
    2.84 -	 * handler) we can't do that and just have to keep using the
    2.85 -	 * current stack (which is the irq stack already after all)
    2.86 -	 */
    2.87 -	if (curctx != irqctx) {
    2.88 -		int arg1, arg2, ebx;
    2.89 -
    2.90 -		/* build the stack frame on the IRQ stack */
    2.91 -		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
    2.92 -		irqctx->tinfo.task = curctx->tinfo.task;
    2.93 -		irqctx->tinfo.previous_esp = current_stack_pointer;
    2.94 -
    2.95 -		asm volatile(
    2.96 -			"       xchgl   %%ebx,%%esp      \n"
    2.97 -			"       call    __do_IRQ         \n"
    2.98 -			"       movl   %%ebx,%%esp      \n"
    2.99 -			: "=a" (arg1), "=d" (arg2), "=b" (ebx)
   2.100 -			:  "0" (irq),   "1" (regs),  "2" (isp)
   2.101 -			: "memory", "cc", "ecx"
   2.102 -		);
   2.103 -	} else
   2.104 -#endif
   2.105 -		__do_IRQ(irq, regs);
   2.106 -
   2.107 -	irq_exit();
   2.108 -
   2.109 -	return 1;
   2.110 -}
   2.111 -
   2.112 -#ifdef CONFIG_4KSTACKS
   2.113 -
   2.114 -/*
   2.115 - * These should really be __section__(".bss.page_aligned") as well, but
   2.116 - * gcc's 3.0 and earlier don't handle that correctly.
   2.117 - */
   2.118 -static char softirq_stack[NR_CPUS * THREAD_SIZE]
   2.119 -		__attribute__((__aligned__(THREAD_SIZE)));
   2.120 -
   2.121 -static char hardirq_stack[NR_CPUS * THREAD_SIZE]
   2.122 -		__attribute__((__aligned__(THREAD_SIZE)));
   2.123 -
   2.124 -/*
   2.125 - * allocate per-cpu stacks for hardirq and for softirq processing
   2.126 - */
   2.127 -void irq_ctx_init(int cpu)
   2.128 -{
   2.129 -	union irq_ctx *irqctx;
   2.130 -
   2.131 -	if (hardirq_ctx[cpu])
   2.132 -		return;
   2.133 -
   2.134 -	irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
   2.135 -	irqctx->tinfo.task              = NULL;
   2.136 -	irqctx->tinfo.exec_domain       = NULL;
   2.137 -	irqctx->tinfo.cpu               = cpu;
   2.138 -	irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
   2.139 -	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
   2.140 -
   2.141 -	hardirq_ctx[cpu] = irqctx;
   2.142 -
   2.143 -	irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
   2.144 -	irqctx->tinfo.task              = NULL;
   2.145 -	irqctx->tinfo.exec_domain       = NULL;
   2.146 -	irqctx->tinfo.cpu               = cpu;
   2.147 -	irqctx->tinfo.preempt_count     = SOFTIRQ_OFFSET;
   2.148 -	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
   2.149 -
   2.150 -	softirq_ctx[cpu] = irqctx;
   2.151 -
   2.152 -	printk("CPU %u irqstacks, hard=%p soft=%p\n",
   2.153 -		cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
   2.154 -}
   2.155 -
   2.156 -extern asmlinkage void __do_softirq(void);
   2.157 -
   2.158 -asmlinkage void do_softirq(void)
   2.159 -{
   2.160 -	unsigned long flags;
   2.161 -	struct thread_info *curctx;
   2.162 -	union irq_ctx *irqctx;
   2.163 -	u32 *isp;
   2.164 -
   2.165 -	if (in_interrupt())
   2.166 -		return;
   2.167 -
   2.168 -	local_irq_save(flags);
   2.169 -
   2.170 -	if (local_softirq_pending()) {
   2.171 -		curctx = current_thread_info();
   2.172 -		irqctx = softirq_ctx[smp_processor_id()];
   2.173 -		irqctx->tinfo.task = curctx->task;
   2.174 -		irqctx->tinfo.previous_esp = current_stack_pointer;
   2.175 -
   2.176 -		/* build the stack frame on the softirq stack */
   2.177 -		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
   2.178 -
   2.179 -		asm volatile(
   2.180 -			"       xchgl   %%ebx,%%esp     \n"
   2.181 -			"       call    __do_softirq    \n"
   2.182 -			"       movl    %%ebx,%%esp     \n"
   2.183 -			: "=b"(isp)
   2.184 -			: "0"(isp)
   2.185 -			: "memory", "cc", "edx", "ecx", "eax"
   2.186 -		);
   2.187 -	}
   2.188 -
   2.189 -	local_irq_restore(flags);
   2.190 -}
   2.191 -
   2.192 -EXPORT_SYMBOL(do_softirq);
   2.193 -#endif
   2.194 -
   2.195 -/*
   2.196 - * Interrupt statistics:
   2.197 - */
   2.198 -
   2.199 -atomic_t irq_err_count;
   2.200 -
   2.201 -/*
   2.202 - * /proc/interrupts printing:
   2.203 - */
   2.204 -
   2.205 -int show_interrupts(struct seq_file *p, void *v)
   2.206 -{
   2.207 -	int i = *(loff_t *) v, j;
   2.208 -	struct irqaction * action;
   2.209 -	unsigned long flags;
   2.210 -
   2.211 -	if (i == 0) {
   2.212 -		seq_printf(p, "           ");
   2.213 -		for (j=0; j<NR_CPUS; j++)
   2.214 -			if (cpu_online(j))
   2.215 -				seq_printf(p, "CPU%d       ",j);
   2.216 -		seq_putc(p, '\n');
   2.217 -	}
   2.218 -
   2.219 -	if (i < NR_IRQS) {
   2.220 -		spin_lock_irqsave(&irq_desc[i].lock, flags);
   2.221 -		action = irq_desc[i].action;
   2.222 -		if (!action)
   2.223 -			goto skip;
   2.224 -		seq_printf(p, "%3d: ",i);
   2.225 -#ifndef CONFIG_SMP
   2.226 -		seq_printf(p, "%10u ", kstat_irqs(i));
   2.227 -#else
   2.228 -		for (j = 0; j < NR_CPUS; j++)
   2.229 -			if (cpu_online(j))
   2.230 -				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
   2.231 -#endif
   2.232 -		seq_printf(p, " %14s", irq_desc[i].handler->typename);
   2.233 -		seq_printf(p, "  %s", action->name);
   2.234 -
   2.235 -		for (action=action->next; action; action = action->next)
   2.236 -			seq_printf(p, ", %s", action->name);
   2.237 -
   2.238 -		seq_putc(p, '\n');
   2.239 -skip:
   2.240 -		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
   2.241 -	} else if (i == NR_IRQS) {
   2.242 -		seq_printf(p, "NMI: ");
   2.243 -		for (j = 0; j < NR_CPUS; j++)
   2.244 -			if (cpu_online(j))
   2.245 -				seq_printf(p, "%10u ", nmi_count(j));
   2.246 -		seq_putc(p, '\n');
   2.247 -#ifdef CONFIG_X86_LOCAL_APIC
   2.248 -		seq_printf(p, "LOC: ");
   2.249 -		for (j = 0; j < NR_CPUS; j++)
   2.250 -			if (cpu_online(j))
   2.251 -				seq_printf(p, "%10u ",
   2.252 -					irq_stat[j].apic_timer_irqs);
   2.253 -		seq_putc(p, '\n');
   2.254 -#endif
   2.255 -		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
   2.256 -#if defined(CONFIG_X86_IO_APIC)
   2.257 -		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
   2.258 -#endif
   2.259 -	}
   2.260 -	return 0;
   2.261 -}
     3.1 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/smp.c	Sat Mar 12 20:44:12 2005 +0000
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,599 +0,0 @@
     3.4 -/*
     3.5 - *	Intel SMP support routines.
     3.6 - *
     3.7 - *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
     3.8 - *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
     3.9 - *
    3.10 - *	This code is released under the GNU General Public License version 2 or
    3.11 - *	later.
    3.12 - */
    3.13 -
    3.14 -#include <linux/init.h>
    3.15 -
    3.16 -#include <linux/mm.h>
    3.17 -#include <linux/irq.h>
    3.18 -#include <linux/delay.h>
    3.19 -#include <linux/spinlock.h>
    3.20 -#include <linux/smp_lock.h>
    3.21 -#include <linux/kernel_stat.h>
    3.22 -#include <linux/mc146818rtc.h>
    3.23 -#include <linux/cache.h>
    3.24 -#include <linux/interrupt.h>
    3.25 -
    3.26 -#include <asm/mtrr.h>
    3.27 -#include <asm/tlbflush.h>
    3.28 -#if 0
    3.29 -#include <mach_apic.h>
    3.30 -#endif
    3.31 -#include <asm-xen/evtchn.h>
    3.32 -
    3.33 -#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
    3.34 -
    3.35 -/*
    3.36 - *	Some notes on x86 processor bugs affecting SMP operation:
    3.37 - *
    3.38 - *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
    3.39 - *	The Linux implications for SMP are handled as follows:
    3.40 - *
    3.41 - *	Pentium III / [Xeon]
    3.42 - *		None of the E1AP-E3AP errata are visible to the user.
    3.43 - *
    3.44 - *	E1AP.	see PII A1AP
    3.45 - *	E2AP.	see PII A2AP
    3.46 - *	E3AP.	see PII A3AP
    3.47 - *
    3.48 - *	Pentium II / [Xeon]
    3.49 - *		None of the A1AP-A3AP errata are visible to the user.
    3.50 - *
    3.51 - *	A1AP.	see PPro 1AP
    3.52 - *	A2AP.	see PPro 2AP
    3.53 - *	A3AP.	see PPro 7AP
    3.54 - *
    3.55 - *	Pentium Pro
    3.56 - *		None of 1AP-9AP errata are visible to the normal user,
    3.57 - *	except occasional delivery of 'spurious interrupt' as trap #15.
    3.58 - *	This is very rare and a non-problem.
    3.59 - *
    3.60 - *	1AP.	Linux maps APIC as non-cacheable
    3.61 - *	2AP.	worked around in hardware
    3.62 - *	3AP.	fixed in C0 and above steppings microcode update.
    3.63 - *		Linux does not use excessive STARTUP_IPIs.
    3.64 - *	4AP.	worked around in hardware
    3.65 - *	5AP.	symmetric IO mode (normal Linux operation) not affected.
    3.66 - *		'noapic' mode has vector 0xf filled out properly.
    3.67 - *	6AP.	'noapic' mode might be affected - fixed in later steppings
    3.68 - *	7AP.	We do not assume writes to the LVT deassering IRQs
    3.69 - *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
    3.70 - *	9AP.	We do not use mixed mode
    3.71 - *
    3.72 - *	Pentium
    3.73 - *		There is a marginal case where REP MOVS on 100MHz SMP
    3.74 - *	machines with B stepping processors can fail. XXX should provide
    3.75 - *	an L1cache=Writethrough or L1cache=off option.
    3.76 - *
    3.77 - *		B stepping CPUs may hang. There are hardware work arounds
    3.78 - *	for this. We warn about it in case your board doesn't have the work
    3.79 - *	arounds. Basically thats so I can tell anyone with a B stepping
    3.80 - *	CPU and SMP problems "tough".
    3.81 - *
    3.82 - *	Specific items [From Pentium Processor Specification Update]
    3.83 - *
    3.84 - *	1AP.	Linux doesn't use remote read
    3.85 - *	2AP.	Linux doesn't trust APIC errors
    3.86 - *	3AP.	We work around this
    3.87 - *	4AP.	Linux never generated 3 interrupts of the same priority
    3.88 - *		to cause a lost local interrupt.
    3.89 - *	5AP.	Remote read is never used
    3.90 - *	6AP.	not affected - worked around in hardware
    3.91 - *	7AP.	not affected - worked around in hardware
    3.92 - *	8AP.	worked around in hardware - we get explicit CS errors if not
    3.93 - *	9AP.	only 'noapic' mode affected. Might generate spurious
    3.94 - *		interrupts, we log only the first one and count the
    3.95 - *		rest silently.
    3.96 - *	10AP.	not affected - worked around in hardware
    3.97 - *	11AP.	Linux reads the APIC between writes to avoid this, as per
    3.98 - *		the documentation. Make sure you preserve this as it affects
    3.99 - *		the C stepping chips too.
   3.100 - *	12AP.	not affected - worked around in hardware
   3.101 - *	13AP.	not affected - worked around in hardware
   3.102 - *	14AP.	we always deassert INIT during bootup
   3.103 - *	15AP.	not affected - worked around in hardware
   3.104 - *	16AP.	not affected - worked around in hardware
   3.105 - *	17AP.	not affected - worked around in hardware
   3.106 - *	18AP.	not affected - worked around in hardware
   3.107 - *	19AP.	not affected - worked around in BIOS
   3.108 - *
   3.109 - *	If this sounds worrying believe me these bugs are either ___RARE___,
   3.110 - *	or are signal timing bugs worked around in hardware and there's
   3.111 - *	about nothing of note with C stepping upwards.
   3.112 - */
   3.113 -
   3.114 -DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
   3.115 -
   3.116 -/*
   3.117 - * the following functions deal with sending IPIs between CPUs.
   3.118 - *
   3.119 - * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
   3.120 - */
   3.121 -
   3.122 -static inline int __prepare_ICR (unsigned int shortcut, int vector)
   3.123 -{
   3.124 -	return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL;
   3.125 -}
   3.126 -
   3.127 -static inline int __prepare_ICR2 (unsigned int mask)
   3.128 -{
   3.129 -	return SET_APIC_DEST_FIELD(mask);
   3.130 -}
   3.131 -
   3.132 -DECLARE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]);
   3.133 -
   3.134 -static inline void __send_IPI_one(unsigned int cpu, int vector)
   3.135 -{
   3.136 -	unsigned int evtchn;
   3.137 -
   3.138 -	evtchn = per_cpu(ipi_to_evtchn, cpu)[vector];
   3.139 -	// printk("send_IPI_mask_bitmask cpu %d vector %d evtchn %d\n", cpu, vector, evtchn);
   3.140 -	if (evtchn) {
   3.141 -#if 0
   3.142 -		shared_info_t *s = HYPERVISOR_shared_info;
   3.143 -		while (synch_test_bit(evtchn, &s->evtchn_pending[0]) ||
   3.144 -		       synch_test_bit(evtchn, &s->evtchn_mask[0]))
   3.145 -			;
   3.146 -#endif
   3.147 -		notify_via_evtchn(evtchn);
   3.148 -	} else
   3.149 -		printk("send_IPI to unbound port %d/%d",
   3.150 -		       cpu, vector);
   3.151 -}
   3.152 -
   3.153 -void __send_IPI_shortcut(unsigned int shortcut, int vector)
   3.154 -{
   3.155 -	int cpu;
   3.156 -
   3.157 -	switch (shortcut) {
   3.158 -	case APIC_DEST_SELF:
   3.159 -		__send_IPI_one(smp_processor_id(), vector);
   3.160 -		break;
   3.161 -	case APIC_DEST_ALLBUT:
   3.162 -		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
   3.163 -			if (cpu == smp_processor_id())
   3.164 -				continue;
   3.165 -			if (cpu_isset(cpu, cpu_online_map)) {
   3.166 -				__send_IPI_one(cpu, vector);
   3.167 -			}
   3.168 -		}
   3.169 -		break;
   3.170 -	default:
   3.171 -		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
   3.172 -		       vector);
   3.173 -		break;
   3.174 -	}
   3.175 -}
   3.176 -
   3.177 -void fastcall send_IPI_self(int vector)
   3.178 -{
   3.179 -	__send_IPI_shortcut(APIC_DEST_SELF, vector);
   3.180 -}
   3.181 -
   3.182 -/*
   3.183 - * This is only used on smaller machines.
   3.184 - */
   3.185 -void send_IPI_mask_bitmask(cpumask_t mask, int vector)
   3.186 -{
   3.187 -	unsigned long flags;
   3.188 -	unsigned int cpu;
   3.189 -
   3.190 -	local_irq_save(flags);
   3.191 -
   3.192 -	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
   3.193 -		if (cpu_isset(cpu, mask)) {
   3.194 -			__send_IPI_one(cpu, vector);
   3.195 -		}
   3.196 -	}
   3.197 -
   3.198 -	local_irq_restore(flags);
   3.199 -}
   3.200 -
   3.201 -inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
   3.202 -{
   3.203 -
   3.204 -	send_IPI_mask_bitmask(mask, vector);
   3.205 -}
   3.206 -
   3.207 -#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
   3.208 -
   3.209 -/*
   3.210 - *	Smarter SMP flushing macros. 
   3.211 - *		c/o Linus Torvalds.
   3.212 - *
   3.213 - *	These mean you can really definitely utterly forget about
   3.214 - *	writing to user space from interrupts. (Its not allowed anyway).
   3.215 - *
   3.216 - *	Optimizations Manfred Spraul <manfred@colorfullife.com>
   3.217 - */
   3.218 -
   3.219 -static cpumask_t flush_cpumask;
   3.220 -static struct mm_struct * flush_mm;
   3.221 -static unsigned long flush_va;
   3.222 -static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
   3.223 -#define FLUSH_ALL	0xffffffff
   3.224 -
   3.225 -/*
   3.226 - * We cannot call mmdrop() because we are in interrupt context, 
   3.227 - * instead update mm->cpu_vm_mask.
   3.228 - *
   3.229 - * We need to reload %cr3 since the page tables may be going
   3.230 - * away from under us..
   3.231 - */
   3.232 -static inline void leave_mm (unsigned long cpu)
   3.233 -{
   3.234 -	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
   3.235 -		BUG();
   3.236 -	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
   3.237 -	load_cr3(swapper_pg_dir);
   3.238 -}
   3.239 -
   3.240 -/*
   3.241 - *
   3.242 - * The flush IPI assumes that a thread switch happens in this order:
   3.243 - * [cpu0: the cpu that switches]
   3.244 - * 1) switch_mm() either 1a) or 1b)
   3.245 - * 1a) thread switch to a different mm
   3.246 - * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
   3.247 - * 	Stop ipi delivery for the old mm. This is not synchronized with
   3.248 - * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
   3.249 - * 	for the wrong mm, and in the worst case we perform a superflous
   3.250 - * 	tlb flush.
   3.251 - * 1a2) set cpu_tlbstate to TLBSTATE_OK
   3.252 - * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
   3.253 - *	was in lazy tlb mode.
   3.254 - * 1a3) update cpu_tlbstate[].active_mm
   3.255 - * 	Now cpu0 accepts tlb flushes for the new mm.
   3.256 - * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
   3.257 - * 	Now the other cpus will send tlb flush ipis.
   3.258 - * 1a4) change cr3.
   3.259 - * 1b) thread switch without mm change
   3.260 - *	cpu_tlbstate[].active_mm is correct, cpu0 already handles
   3.261 - *	flush ipis.
   3.262 - * 1b1) set cpu_tlbstate to TLBSTATE_OK
   3.263 - * 1b2) test_and_set the cpu bit in cpu_vm_mask.
   3.264 - * 	Atomically set the bit [other cpus will start sending flush ipis],
   3.265 - * 	and test the bit.
   3.266 - * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
   3.267 - * 2) switch %%esp, ie current
   3.268 - *
   3.269 - * The interrupt must handle 2 special cases:
   3.270 - * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
   3.271 - * - the cpu performs speculative tlb reads, i.e. even if the cpu only
   3.272 - *   runs in kernel space, the cpu could load tlb entries for user space
   3.273 - *   pages.
   3.274 - *
   3.275 - * The good news is that cpu_tlbstate is local to each cpu, no
   3.276 - * write/read ordering problems.
   3.277 - */
   3.278 -
   3.279 -/*
   3.280 - * TLB flush IPI:
   3.281 - *
   3.282 - * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
   3.283 - * 2) Leave the mm if we are in the lazy tlb mode.
   3.284 - */
   3.285 -
   3.286 -irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id,
   3.287 -				     struct pt_regs *regs)
   3.288 -{
   3.289 -	unsigned long cpu;
   3.290 -
   3.291 -	cpu = get_cpu();
   3.292 -
   3.293 -	if (!cpu_isset(cpu, flush_cpumask))
   3.294 -		goto out;
   3.295 -		/* 
   3.296 -		 * This was a BUG() but until someone can quote me the
   3.297 -		 * line from the intel manual that guarantees an IPI to
   3.298 -		 * multiple CPUs is retried _only_ on the erroring CPUs
   3.299 -		 * its staying as a return
   3.300 -		 *
   3.301 -		 * BUG();
   3.302 -		 */
   3.303 -		 
   3.304 -	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
   3.305 -		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
   3.306 -			if (flush_va == FLUSH_ALL)
   3.307 -				local_flush_tlb();
   3.308 -			else
   3.309 -				__flush_tlb_one(flush_va);
   3.310 -		} else
   3.311 -			leave_mm(cpu);
   3.312 -	}
   3.313 -	smp_mb__before_clear_bit();
   3.314 -	cpu_clear(cpu, flush_cpumask);
   3.315 -	smp_mb__after_clear_bit();
   3.316 -out:
   3.317 -	put_cpu_no_resched();
   3.318 -
   3.319 -	return IRQ_HANDLED;
   3.320 -}
   3.321 -
   3.322 -static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
   3.323 -						unsigned long va)
   3.324 -{
   3.325 -	cpumask_t tmp;
   3.326 -	/*
   3.327 -	 * A couple of (to be removed) sanity checks:
   3.328 -	 *
   3.329 -	 * - we do not send IPIs to not-yet booted CPUs.
   3.330 -	 * - current CPU must not be in mask
   3.331 -	 * - mask must exist :)
   3.332 -	 */
   3.333 -	BUG_ON(cpus_empty(cpumask));
   3.334 -
   3.335 -	cpus_and(tmp, cpumask, cpu_online_map);
   3.336 -	BUG_ON(!cpus_equal(cpumask, tmp));
   3.337 -	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
   3.338 -	BUG_ON(!mm);
   3.339 -
   3.340 -	/*
   3.341 -	 * i'm not happy about this global shared spinlock in the
   3.342 -	 * MM hot path, but we'll see how contended it is.
   3.343 -	 * Temporarily this turns IRQs off, so that lockups are
   3.344 -	 * detected by the NMI watchdog.
   3.345 -	 */
   3.346 -	spin_lock(&tlbstate_lock);
   3.347 -	
   3.348 -	flush_mm = mm;
   3.349 -	flush_va = va;
   3.350 -#if NR_CPUS <= BITS_PER_LONG
   3.351 -	atomic_set_mask(cpumask, &flush_cpumask);
   3.352 -#else
   3.353 -	{
   3.354 -		int k;
   3.355 -		unsigned long *flush_mask = (unsigned long *)&flush_cpumask;
   3.356 -		unsigned long *cpu_mask = (unsigned long *)&cpumask;
   3.357 -		for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k)
   3.358 -			atomic_set_mask(cpu_mask[k], &flush_mask[k]);
   3.359 -	}
   3.360 -#endif
   3.361 -	/*
   3.362 -	 * We have to send the IPI only to
   3.363 -	 * CPUs affected.
   3.364 -	 */
   3.365 -	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
   3.366 -
   3.367 -	while (!cpus_empty(flush_cpumask))
   3.368 -		/* nothing. lockup detection does not belong here */
   3.369 -		mb();
   3.370 -
   3.371 -	flush_mm = NULL;
   3.372 -	flush_va = 0;
   3.373 -	spin_unlock(&tlbstate_lock);
   3.374 -}
   3.375 -	
   3.376 -void flush_tlb_current_task(void)
   3.377 -{
   3.378 -	struct mm_struct *mm = current->mm;
   3.379 -	cpumask_t cpu_mask;
   3.380 -
   3.381 -	preempt_disable();
   3.382 -	cpu_mask = mm->cpu_vm_mask;
   3.383 -	cpu_clear(smp_processor_id(), cpu_mask);
   3.384 -
   3.385 -	local_flush_tlb();
   3.386 -	if (!cpus_empty(cpu_mask))
   3.387 -		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
   3.388 -	preempt_enable();
   3.389 -}
   3.390 -
   3.391 -void flush_tlb_mm (struct mm_struct * mm)
   3.392 -{
   3.393 -	cpumask_t cpu_mask;
   3.394 -
   3.395 -	preempt_disable();
   3.396 -	cpu_mask = mm->cpu_vm_mask;
   3.397 -	cpu_clear(smp_processor_id(), cpu_mask);
   3.398 -
   3.399 -	if (current->active_mm == mm) {
   3.400 -		if (current->mm)
   3.401 -			local_flush_tlb();
   3.402 -		else
   3.403 -			leave_mm(smp_processor_id());
   3.404 -	}
   3.405 -	if (!cpus_empty(cpu_mask))
   3.406 -		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
   3.407 -
   3.408 -	preempt_enable();
   3.409 -}
   3.410 -
   3.411 -void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
   3.412 -{
   3.413 -	struct mm_struct *mm = vma->vm_mm;
   3.414 -	cpumask_t cpu_mask;
   3.415 -
   3.416 -	preempt_disable();
   3.417 -	cpu_mask = mm->cpu_vm_mask;
   3.418 -	cpu_clear(smp_processor_id(), cpu_mask);
   3.419 -
   3.420 -	if (current->active_mm == mm) {
   3.421 -		if(current->mm)
   3.422 -			__flush_tlb_one(va);
   3.423 -		else
   3.424 -		 	leave_mm(smp_processor_id());
   3.425 -	}
   3.426 -
   3.427 -	if (!cpus_empty(cpu_mask))
   3.428 -		flush_tlb_others(cpu_mask, mm, va);
   3.429 -
   3.430 -	preempt_enable();
   3.431 -}
   3.432 -
   3.433 -static void do_flush_tlb_all(void* info)
   3.434 -{
   3.435 -	unsigned long cpu = smp_processor_id();
   3.436 -
   3.437 -	__flush_tlb_all();
   3.438 -	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
   3.439 -		leave_mm(cpu);
   3.440 -}
   3.441 -
   3.442 -void flush_tlb_all(void)
   3.443 -{
   3.444 -	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
   3.445 -}
   3.446 -
   3.447 -/*
   3.448 - * this function sends a 'reschedule' IPI to another CPU.
   3.449 - * it goes straight through and wastes no time serializing
   3.450 - * anything. Worst case is that we lose a reschedule ...
   3.451 - */
   3.452 -void smp_send_reschedule(int cpu)
   3.453 -{
   3.454 -	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
   3.455 -}
   3.456 -
   3.457 -/*
   3.458 - * Structure and data for smp_call_function(). This is designed to minimise
   3.459 - * static memory requirements. It also looks cleaner.
   3.460 - */
   3.461 -static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
   3.462 -
   3.463 -struct call_data_struct {
   3.464 -	void (*func) (void *info);
   3.465 -	void *info;
   3.466 -	atomic_t started;
   3.467 -	atomic_t finished;
   3.468 -	int wait;
   3.469 -};
   3.470 -
   3.471 -static struct call_data_struct * call_data;
   3.472 -
   3.473 -/*
   3.474 - * this function sends a 'generic call function' IPI to all other CPUs
   3.475 - * in the system.
   3.476 - */
   3.477 -
   3.478 -int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
   3.479 -			int wait)
   3.480 -/*
   3.481 - * [SUMMARY] Run a function on all other CPUs.
   3.482 - * <func> The function to run. This must be fast and non-blocking.
   3.483 - * <info> An arbitrary pointer to pass to the function.
   3.484 - * <nonatomic> currently unused.
   3.485 - * <wait> If true, wait (atomically) until function has completed on other CPUs.
   3.486 - * [RETURNS] 0 on success, else a negative status code. Does not return until
   3.487 - * remote CPUs are nearly ready to execute <<func>> or are or have executed.
   3.488 - *
   3.489 - * You must not call this function with disabled interrupts or from a
   3.490 - * hardware interrupt handler or from a bottom half handler.
   3.491 - */
   3.492 -{
   3.493 -	struct call_data_struct data;
   3.494 -	int cpus = num_online_cpus()-1;
   3.495 -
   3.496 -	if (!cpus)
   3.497 -		return 0;
   3.498 -
   3.499 -	/* Can deadlock when called with interrupts disabled */
   3.500 -	WARN_ON(irqs_disabled());
   3.501 -
   3.502 -	data.func = func;
   3.503 -	data.info = info;
   3.504 -	atomic_set(&data.started, 0);
   3.505 -	data.wait = wait;
   3.506 -	if (wait)
   3.507 -		atomic_set(&data.finished, 0);
   3.508 -
   3.509 -	spin_lock(&call_lock);
   3.510 -	call_data = &data;
   3.511 -	mb();
   3.512 -	
   3.513 -	/* Send a message to all other CPUs and wait for them to respond */
   3.514 -	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
   3.515 -
   3.516 -	/* Wait for response */
   3.517 -	while (atomic_read(&data.started) != cpus)
   3.518 -		barrier();
   3.519 -
   3.520 -	if (wait)
   3.521 -		while (atomic_read(&data.finished) != cpus)
   3.522 -			barrier();
   3.523 -	spin_unlock(&call_lock);
   3.524 -
   3.525 -	return 0;
   3.526 -}
   3.527 -
   3.528 -static void stop_this_cpu (void * dummy)
   3.529 -{
   3.530 -	/*
   3.531 -	 * Remove this CPU:
   3.532 -	 */
   3.533 -	cpu_clear(smp_processor_id(), cpu_online_map);
   3.534 -	local_irq_disable();
   3.535 -#if 1
   3.536 -	xxprint("stop_this_cpu disable_local_APIC\n");
   3.537 -#else
   3.538 -	disable_local_APIC();
   3.539 -#endif
   3.540 -	if (cpu_data[smp_processor_id()].hlt_works_ok)
   3.541 -		for(;;) __asm__("hlt");
   3.542 -	for (;;);
   3.543 -}
   3.544 -
   3.545 -/*
   3.546 - * this function calls the 'stop' function on all other CPUs in the system.
   3.547 - */
   3.548 -
   3.549 -void smp_send_stop(void)
   3.550 -{
   3.551 -	smp_call_function(stop_this_cpu, NULL, 1, 0);
   3.552 -
   3.553 -	local_irq_disable();
   3.554 -#if 1
   3.555 -	xxprint("smp_send_stop disable_local_APIC\n");
   3.556 -#else
   3.557 -	disable_local_APIC();
   3.558 -#endif
   3.559 -	local_irq_enable();
   3.560 -}
   3.561 -
   3.562 -/*
   3.563 - * Reschedule call back. Nothing to do,
   3.564 - * all the work is done automatically when
   3.565 - * we return from the interrupt.
   3.566 - */
   3.567 -irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id,
   3.568 -				     struct pt_regs *regs)
   3.569 -{
   3.570 -
   3.571 -	return IRQ_HANDLED;
   3.572 -}
   3.573 -
   3.574 -#include <linux/kallsyms.h>
   3.575 -irqreturn_t smp_call_function_interrupt(int irq, void *dev_id,
   3.576 -					struct pt_regs *regs)
   3.577 -{
   3.578 -	void (*func) (void *info) = call_data->func;
   3.579 -	void *info = call_data->info;
   3.580 -	int wait = call_data->wait;
   3.581 -
   3.582 -	/*
   3.583 -	 * Notify initiating CPU that I've grabbed the data and am
   3.584 -	 * about to execute the function
   3.585 -	 */
   3.586 -	mb();
   3.587 -	atomic_inc(&call_data->started);
   3.588 -	/*
   3.589 -	 * At this point the info structure may be out of scope unless wait==1
   3.590 -	 */
   3.591 -	irq_enter();
   3.592 -	(*func)(info);
   3.593 -	irq_exit();
   3.594 -
   3.595 -	if (wait) {
   3.596 -		mb();
   3.597 -		atomic_inc(&call_data->finished);
   3.598 -	}
   3.599 -
   3.600 -	return IRQ_HANDLED;
   3.601 -}
   3.602 -
     4.1 --- a/linux-2.6.10-xen-sparse/arch/xen/i386/kernel/smpboot.c	Sat Mar 12 20:44:12 2005 +0000
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,1364 +0,0 @@
     4.4 -/*
     4.5 - *	x86 SMP booting functions
     4.6 - *
     4.7 - *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
     4.8 - *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
     4.9 - *
    4.10 - *	Much of the core SMP work is based on previous work by Thomas Radke, to
    4.11 - *	whom a great many thanks are extended.
    4.12 - *
    4.13 - *	Thanks to Intel for making available several different Pentium,
    4.14 - *	Pentium Pro and Pentium-II/Xeon MP machines.
    4.15 - *	Original development of Linux SMP code supported by Caldera.
    4.16 - *
    4.17 - *	This code is released under the GNU General Public License version 2 or
    4.18 - *	later.
    4.19 - *
    4.20 - *	Fixes
    4.21 - *		Felix Koop	:	NR_CPUS used properly
    4.22 - *		Jose Renau	:	Handle single CPU case.
    4.23 - *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
    4.24 - *		Greg Wright	:	Fix for kernel stacks panic.
    4.25 - *		Erich Boleyn	:	MP v1.4 and additional changes.
    4.26 - *	Matthias Sattler	:	Changes for 2.1 kernel map.
    4.27 - *	Michel Lespinasse	:	Changes for 2.1 kernel map.
    4.28 - *	Michael Chastain	:	Change trampoline.S to gnu as.
    4.29 - *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
    4.30 - *		Ingo Molnar	:	Added APIC timers, based on code
    4.31 - *					from Jose Renau
    4.32 - *		Ingo Molnar	:	various cleanups and rewrites
    4.33 - *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
    4.34 - *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
    4.35 - *		Martin J. Bligh	: 	Added support for multi-quad systems
    4.36 - *		Dave Jones	:	Report invalid combinations of Athlon CPUs.
    4.37 -*		Rusty Russell	:	Hacked into shape for new "hotplug" boot process. */
    4.38 -
    4.39 -#include <linux/module.h>
    4.40 -#include <linux/config.h>
    4.41 -#include <linux/init.h>
    4.42 -#include <linux/kernel.h>
    4.43 -
    4.44 -#include <linux/mm.h>
    4.45 -#include <linux/sched.h>
    4.46 -#include <linux/kernel_stat.h>
    4.47 -#include <linux/smp_lock.h>
    4.48 -#include <linux/irq.h>
    4.49 -#include <linux/bootmem.h>
    4.50 -
    4.51 -#include <linux/delay.h>
    4.52 -#include <linux/mc146818rtc.h>
    4.53 -#include <asm/tlbflush.h>
    4.54 -#include <asm/desc.h>
    4.55 -#include <asm/arch_hooks.h>
    4.56 -
    4.57 -#if 1
    4.58 -#define Dprintk(args...)
    4.59 -#else
    4.60 -#include <mach_apic.h>
    4.61 -#endif
    4.62 -#include <mach_wakecpu.h>
    4.63 -#include <smpboot_hooks.h>
    4.64 -
    4.65 -/* Set if we find a B stepping CPU */
    4.66 -static int __initdata smp_b_stepping;
    4.67 -
    4.68 -/* Number of siblings per CPU package */
    4.69 -int smp_num_siblings = 1;
    4.70 -int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
    4.71 -
    4.72 -/* bitmap of online cpus */
    4.73 -cpumask_t cpu_online_map;
    4.74 -
    4.75 -static cpumask_t cpu_callin_map;
    4.76 -cpumask_t cpu_callout_map;
    4.77 -static cpumask_t smp_commenced_mask;
    4.78 -
    4.79 -/* Per CPU bogomips and other parameters */
    4.80 -struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
    4.81 -
    4.82 -u8 x86_cpu_to_apicid[NR_CPUS] =
    4.83 -			{ [0 ... NR_CPUS-1] = 0xff };
    4.84 -EXPORT_SYMBOL(x86_cpu_to_apicid);
    4.85 -
    4.86 -/* Set when the idlers are all forked */
    4.87 -int smp_threads_ready;
    4.88 -
    4.89 -#if 0
    4.90 -/*
    4.91 - * Trampoline 80x86 program as an array.
    4.92 - */
    4.93 -
    4.94 -extern unsigned char trampoline_data [];
    4.95 -extern unsigned char trampoline_end  [];
    4.96 -static unsigned char *trampoline_base;
    4.97 -static int trampoline_exec;
    4.98 -
    4.99 -/*
   4.100 - * Currently trivial. Write the real->protected mode
   4.101 - * bootstrap into the page concerned. The caller
   4.102 - * has made sure it's suitably aligned.
   4.103 - */
   4.104 -
   4.105 -static unsigned long __init setup_trampoline(void)
   4.106 -{
   4.107 -	memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
   4.108 -	return virt_to_phys(trampoline_base);
   4.109 -}
   4.110 -#endif
   4.111 -
   4.112 -/*
   4.113 - * We are called very early to get the low memory for the
   4.114 - * SMP bootup trampoline page.
   4.115 - */
   4.116 -void __init smp_alloc_memory(void)
   4.117 -{
   4.118 -#if 1
   4.119 -	int cpu;
   4.120 -
   4.121 -	for (cpu = 1; cpu < NR_CPUS; cpu++) {
   4.122 -		cpu_gdt_descr[cpu].address = (unsigned long)
   4.123 -			alloc_bootmem_low_pages(PAGE_SIZE);
   4.124 -		/* XXX free unused pages later */
   4.125 -	}
   4.126 -#else
   4.127 -	trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE);
   4.128 -	/*
   4.129 -	 * Has to be in very low memory so we can execute
   4.130 -	 * real-mode AP code.
   4.131 -	 */
   4.132 -	if (__pa(trampoline_base) >= 0x9F000)
   4.133 -		BUG();
   4.134 -	/*
   4.135 -	 * Make the SMP trampoline executable:
   4.136 -	 */
   4.137 -	trampoline_exec = set_kernel_exec((unsigned long)trampoline_base, 1);
   4.138 -#endif
   4.139 -}
   4.140 -
   4.141 -/*
   4.142 - * The bootstrap kernel entry code has set these up. Save them for
   4.143 - * a given CPU
   4.144 - */
   4.145 -
   4.146 -static void __init smp_store_cpu_info(int id)
   4.147 -{
   4.148 -	struct cpuinfo_x86 *c = cpu_data + id;
   4.149 -
   4.150 -	*c = boot_cpu_data;
   4.151 -	if (id!=0)
   4.152 -		identify_cpu(c);
   4.153 -	/*
   4.154 -	 * Mask B, Pentium, but not Pentium MMX
   4.155 -	 */
   4.156 -	if (c->x86_vendor == X86_VENDOR_INTEL &&
   4.157 -	    c->x86 == 5 &&
   4.158 -	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
   4.159 -	    c->x86_model <= 3)
   4.160 -		/*
   4.161 -		 * Remember we have B step Pentia with bugs
   4.162 -		 */
   4.163 -		smp_b_stepping = 1;
   4.164 -
   4.165 -	/*
   4.166 -	 * Certain Athlons might work (for various values of 'work') in SMP
   4.167 -	 * but they are not certified as MP capable.
   4.168 -	 */
   4.169 -	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
   4.170 -
   4.171 -		/* Athlon 660/661 is valid. */	
   4.172 -		if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
   4.173 -			goto valid_k7;
   4.174 -
   4.175 -		/* Duron 670 is valid */
   4.176 -		if ((c->x86_model==7) && (c->x86_mask==0))
   4.177 -			goto valid_k7;
   4.178 -
   4.179 -		/*
   4.180 -		 * Athlon 662, Duron 671, and Athlon >model 7 have capability bit.
   4.181 -		 * It's worth noting that the A5 stepping (662) of some Athlon XP's
   4.182 -		 * have the MP bit set.
   4.183 -		 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more.
   4.184 -		 */
   4.185 -		if (((c->x86_model==6) && (c->x86_mask>=2)) ||
   4.186 -		    ((c->x86_model==7) && (c->x86_mask>=1)) ||
   4.187 -		     (c->x86_model> 7))
   4.188 -			if (cpu_has_mp)
   4.189 -				goto valid_k7;
   4.190 -
   4.191 -		/* If we get here, it's not a certified SMP capable AMD system. */
   4.192 -		tainted |= TAINT_UNSAFE_SMP;
   4.193 -	}
   4.194 -
   4.195 -valid_k7:
   4.196 -	;
   4.197 -}
   4.198 -
   4.199 -#if 0
   4.200 -/*
   4.201 - * TSC synchronization.
   4.202 - *
   4.203 - * We first check whether all CPUs have their TSC's synchronized,
   4.204 - * then we print a warning if not, and always resync.
   4.205 - */
   4.206 -
   4.207 -static atomic_t tsc_start_flag = ATOMIC_INIT(0);
   4.208 -static atomic_t tsc_count_start = ATOMIC_INIT(0);
   4.209 -static atomic_t tsc_count_stop = ATOMIC_INIT(0);
   4.210 -static unsigned long long tsc_values[NR_CPUS];
   4.211 -
   4.212 -#define NR_LOOPS 5
   4.213 -
   4.214 -static void __init synchronize_tsc_bp (void)
   4.215 -{
   4.216 -	int i;
   4.217 -	unsigned long long t0;
   4.218 -	unsigned long long sum, avg;
   4.219 -	long long delta;
   4.220 -	unsigned long one_usec;
   4.221 -	int buggy = 0;
   4.222 -
   4.223 -	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
   4.224 -
   4.225 -	/* convert from kcyc/sec to cyc/usec */
   4.226 -	one_usec = cpu_khz / 1000;
   4.227 -
   4.228 -	atomic_set(&tsc_start_flag, 1);
   4.229 -	wmb();
   4.230 -
   4.231 -	/*
   4.232 -	 * We loop a few times to get a primed instruction cache,
   4.233 -	 * then the last pass is more or less synchronized and
   4.234 -	 * the BP and APs set their cycle counters to zero all at
   4.235 -	 * once. This reduces the chance of having random offsets
   4.236 -	 * between the processors, and guarantees that the maximum
   4.237 -	 * delay between the cycle counters is never bigger than
   4.238 -	 * the latency of information-passing (cachelines) between
   4.239 -	 * two CPUs.
   4.240 -	 */
   4.241 -	for (i = 0; i < NR_LOOPS; i++) {
   4.242 -		/*
   4.243 -		 * all APs synchronize but they loop on '== num_cpus'
   4.244 -		 */
   4.245 -		while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
   4.246 -			mb();
   4.247 -		atomic_set(&tsc_count_stop, 0);
   4.248 -		wmb();
   4.249 -		/*
   4.250 -		 * this lets the APs save their current TSC:
   4.251 -		 */
   4.252 -		atomic_inc(&tsc_count_start);
   4.253 -
   4.254 -		rdtscll(tsc_values[smp_processor_id()]);
   4.255 -		/*
   4.256 -		 * We clear the TSC in the last loop:
   4.257 -		 */
   4.258 -		if (i == NR_LOOPS-1)
   4.259 -			write_tsc(0, 0);
   4.260 -
   4.261 -		/*
   4.262 -		 * Wait for all APs to leave the synchronization point:
   4.263 -		 */
   4.264 -		while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
   4.265 -			mb();
   4.266 -		atomic_set(&tsc_count_start, 0);
   4.267 -		wmb();
   4.268 -		atomic_inc(&tsc_count_stop);
   4.269 -	}
   4.270 -
   4.271 -	sum = 0;
   4.272 -	for (i = 0; i < NR_CPUS; i++) {
   4.273 -		if (cpu_isset(i, cpu_callout_map)) {
   4.274 -			t0 = tsc_values[i];
   4.275 -			sum += t0;
   4.276 -		}
   4.277 -	}
   4.278 -	avg = sum;
   4.279 -	do_div(avg, num_booting_cpus());
   4.280 -
   4.281 -	sum = 0;
   4.282 -	for (i = 0; i < NR_CPUS; i++) {
   4.283 -		if (!cpu_isset(i, cpu_callout_map))
   4.284 -			continue;
   4.285 -		delta = tsc_values[i] - avg;
   4.286 -		if (delta < 0)
   4.287 -			delta = -delta;
   4.288 -		/*
   4.289 -		 * We report bigger than 2 microseconds clock differences.
   4.290 -		 */
   4.291 -		if (delta > 2*one_usec) {
   4.292 -			long realdelta;
   4.293 -			if (!buggy) {
   4.294 -				buggy = 1;
   4.295 -				printk("\n");
   4.296 -			}
   4.297 -			realdelta = delta;
   4.298 -			do_div(realdelta, one_usec);
   4.299 -			if (tsc_values[i] < avg)
   4.300 -				realdelta = -realdelta;
   4.301 -
   4.302 -			printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
   4.303 -		}
   4.304 -
   4.305 -		sum += delta;
   4.306 -	}
   4.307 -	if (!buggy)
   4.308 -		printk("passed.\n");
   4.309 -}
   4.310 -
   4.311 -static void __init synchronize_tsc_ap (void)
   4.312 -{
   4.313 -	int i;
   4.314 -
   4.315 -	/*
   4.316 -	 * Not every cpu is online at the time
   4.317 -	 * this gets called, so we first wait for the BP to
   4.318 -	 * finish SMP initialization:
   4.319 -	 */
   4.320 -	while (!atomic_read(&tsc_start_flag)) mb();
   4.321 -
   4.322 -	for (i = 0; i < NR_LOOPS; i++) {
   4.323 -		atomic_inc(&tsc_count_start);
   4.324 -		while (atomic_read(&tsc_count_start) != num_booting_cpus())
   4.325 -			mb();
   4.326 -
   4.327 -		rdtscll(tsc_values[smp_processor_id()]);
   4.328 -		if (i == NR_LOOPS-1)
   4.329 -			write_tsc(0, 0);
   4.330 -
   4.331 -		atomic_inc(&tsc_count_stop);
   4.332 -		while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb();
   4.333 -	}
   4.334 -}
   4.335 -#undef NR_LOOPS
   4.336 -#endif
   4.337 -
   4.338 -extern void calibrate_delay(void);
   4.339 -
   4.340 -static atomic_t init_deasserted;
   4.341 -
   4.342 -void __init smp_callin(void)
   4.343 -{
   4.344 -	int cpuid, phys_id;
   4.345 -	unsigned long timeout;
   4.346 -
   4.347 -#if 0
   4.348 -	/*
   4.349 -	 * If waken up by an INIT in an 82489DX configuration
   4.350 -	 * we may get here before an INIT-deassert IPI reaches
   4.351 -	 * our local APIC.  We have to wait for the IPI or we'll
   4.352 -	 * lock up on an APIC access.
   4.353 -	 */
   4.354 -	wait_for_init_deassert(&init_deasserted);
   4.355 -#endif
   4.356 -
   4.357 -	/*
   4.358 -	 * (This works even if the APIC is not enabled.)
   4.359 -	 */
   4.360 -	phys_id = smp_processor_id();
   4.361 -	cpuid = smp_processor_id();
   4.362 -	if (cpu_isset(cpuid, cpu_callin_map)) {
   4.363 -		printk("huh, phys CPU#%d, CPU#%d already present??\n",
   4.364 -					phys_id, cpuid);
   4.365 -		BUG();
   4.366 -	}
   4.367 -	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
   4.368 -
   4.369 -	/*
   4.370 -	 * STARTUP IPIs are fragile beasts as they might sometimes
   4.371 -	 * trigger some glue motherboard logic. Complete APIC bus
   4.372 -	 * silence for 1 second, this overestimates the time the
   4.373 -	 * boot CPU is spending to send the up to 2 STARTUP IPIs
   4.374 -	 * by a factor of two. This should be enough.
   4.375 -	 */
   4.376 -
   4.377 -	/*
   4.378 -	 * Waiting 2s total for startup (udelay is not yet working)
   4.379 -	 */
   4.380 -	timeout = jiffies + 2*HZ;
   4.381 -	while (time_before(jiffies, timeout)) {
   4.382 -		/*
   4.383 -		 * Has the boot CPU finished it's STARTUP sequence?
   4.384 -		 */
   4.385 -		if (cpu_isset(cpuid, cpu_callout_map))
   4.386 -			break;
   4.387 -		rep_nop();
   4.388 -	}
   4.389 -
   4.390 -	if (!time_before(jiffies, timeout)) {
   4.391 -		printk("BUG: CPU%d started up but did not get a callout!\n",
   4.392 -			cpuid);
   4.393 -		BUG();
   4.394 -	}
   4.395 -
   4.396 -#if 0
   4.397 -	/*
   4.398 -	 * the boot CPU has finished the init stage and is spinning
   4.399 -	 * on callin_map until we finish. We are free to set up this
   4.400 -	 * CPU, first the APIC. (this is probably redundant on most
   4.401 -	 * boards)
   4.402 -	 */
   4.403 -
   4.404 -	Dprintk("CALLIN, before setup_local_APIC().\n");
   4.405 -	smp_callin_clear_local_apic();
   4.406 -	setup_local_APIC();
   4.407 -#endif
   4.408 -	map_cpu_to_logical_apicid();
   4.409 -
   4.410 -	local_irq_enable();
   4.411 -
   4.412 -	/*
   4.413 -	 * Get our bogomips.
   4.414 -	 */
   4.415 -	calibrate_delay();
   4.416 -	Dprintk("Stack at about %p\n",&cpuid);
   4.417 -
   4.418 -	/*
   4.419 -	 * Save our processor parameters
   4.420 -	 */
   4.421 - 	smp_store_cpu_info(cpuid);
   4.422 -
   4.423 -#if 0
   4.424 -	disable_APIC_timer();
   4.425 -#endif
   4.426 -	local_irq_disable();
   4.427 -	/*
   4.428 -	 * Allow the master to continue.
   4.429 -	 */
   4.430 -	cpu_set(cpuid, cpu_callin_map);
   4.431 -
   4.432 -#if 0
   4.433 -	/*
   4.434 -	 *      Synchronize the TSC with the BP
   4.435 -	 */
   4.436 -	if (cpu_has_tsc && cpu_khz)
   4.437 -		synchronize_tsc_ap();
   4.438 -#endif
   4.439 -}
   4.440 -
   4.441 -int cpucount;
   4.442 -
   4.443 -extern int cpu_idle(void);
   4.444 -
   4.445 -
   4.446 -static irqreturn_t local_debug_interrupt(int irq, void *dev_id,
   4.447 -					 struct pt_regs *regs)
   4.448 -{
   4.449 -
   4.450 -	return IRQ_HANDLED;
   4.451 -}
   4.452 -
   4.453 -static struct irqaction local_irq_debug = {
   4.454 -	local_debug_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ldebug",
   4.455 -	NULL, NULL
   4.456 -};
   4.457 -
   4.458 -void local_setup_debug(void)
   4.459 -{
   4.460 -	(void)setup_irq(bind_virq_to_irq(VIRQ_DEBUG), &local_irq_debug);
   4.461 -}
   4.462 -
   4.463 -
   4.464 -extern void local_setup_timer(void);
   4.465 -
   4.466 -/*
   4.467 - * Activate a secondary processor.
   4.468 - */
   4.469 -int __init start_secondary(void *unused)
   4.470 -{
   4.471 -	/*
   4.472 -	 * Dont put anything before smp_callin(), SMP
   4.473 -	 * booting is too fragile that we want to limit the
   4.474 -	 * things done here to the most necessary things.
   4.475 -	 */
   4.476 -	cpu_init();
   4.477 -	smp_callin();
   4.478 -	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
   4.479 -		rep_nop();
   4.480 -	local_setup_timer();
   4.481 -	local_setup_debug();	/* XXX */
   4.482 -	smp_intr_init();
   4.483 -	local_irq_enable();
   4.484 -	/*
   4.485 -	 * low-memory mappings have been cleared, flush them from
   4.486 -	 * the local TLBs too.
   4.487 -	 */
   4.488 -	local_flush_tlb();
   4.489 -	cpu_set(smp_processor_id(), cpu_online_map);
   4.490 -	wmb();
   4.491 -	if (0) {
   4.492 -		char *msg2 = "delay2\n";
   4.493 -		int timeout;
   4.494 -		for (timeout = 0; timeout < 50000; timeout++) {
   4.495 -			udelay(1000);
   4.496 -			if (timeout == 2000) {
   4.497 -				(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg2), msg2);
   4.498 -				timeout = 0;
   4.499 -			}
   4.500 -		}
   4.501 -	}
   4.502 -	return cpu_idle();
   4.503 -}
   4.504 -
   4.505 -/*
   4.506 - * Everything has been set up for the secondary
   4.507 - * CPUs - they just need to reload everything
   4.508 - * from the task structure
   4.509 - * This function must not return.
   4.510 - */
   4.511 -void __init initialize_secondary(void)
   4.512 -{
   4.513 -	/*
   4.514 -	 * We don't actually need to load the full TSS,
   4.515 -	 * basically just the stack pointer and the eip.
   4.516 -	 */
   4.517 -
   4.518 -	asm volatile(
   4.519 -		"movl %0,%%esp\n\t"
   4.520 -		"jmp *%1"
   4.521 -		:
   4.522 -		:"r" (current->thread.esp),"r" (current->thread.eip));
   4.523 -}
   4.524 -
   4.525 -extern struct {
   4.526 -	void * esp;
   4.527 -	unsigned short ss;
   4.528 -} stack_start;
   4.529 -
   4.530 -#ifdef CONFIG_NUMA
   4.531 -
   4.532 -/* which logical CPUs are on which nodes */
   4.533 -cpumask_t node_2_cpu_mask[MAX_NUMNODES] =
   4.534 -				{ [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
   4.535 -/* which node each logical CPU is on */
   4.536 -int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
   4.537 -EXPORT_SYMBOL(cpu_2_node);
   4.538 -
   4.539 -/* set up a mapping between cpu and node. */
   4.540 -static inline void map_cpu_to_node(int cpu, int node)
   4.541 -{
   4.542 -	printk("Mapping cpu %d to node %d\n", cpu, node);
   4.543 -	cpu_set(cpu, node_2_cpu_mask[node]);
   4.544 -	cpu_2_node[cpu] = node;
   4.545 -}
   4.546 -
   4.547 -/* undo a mapping between cpu and node. */
   4.548 -static inline void unmap_cpu_to_node(int cpu)
   4.549 -{
   4.550 -	int node;
   4.551 -
   4.552 -	printk("Unmapping cpu %d from all nodes\n", cpu);
   4.553 -	for (node = 0; node < MAX_NUMNODES; node ++)
   4.554 -		cpu_clear(cpu, node_2_cpu_mask[node]);
   4.555 -	cpu_2_node[cpu] = 0;
   4.556 -}
   4.557 -#else /* !CONFIG_NUMA */
   4.558 -
   4.559 -#define map_cpu_to_node(cpu, node)	({})
   4.560 -#define unmap_cpu_to_node(cpu)	({})
   4.561 -
   4.562 -#endif /* CONFIG_NUMA */
   4.563 -
   4.564 -u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
   4.565 -
   4.566 -void map_cpu_to_logical_apicid(void)
   4.567 -{
   4.568 -	int cpu = smp_processor_id();
   4.569 -	int apicid = smp_processor_id();
   4.570 -
   4.571 -	cpu_2_logical_apicid[cpu] = apicid;
   4.572 -	map_cpu_to_node(cpu, apicid_to_node(apicid));
   4.573 -}
   4.574 -
   4.575 -void unmap_cpu_to_logical_apicid(int cpu)
   4.576 -{
   4.577 -	cpu_2_logical_apicid[cpu] = BAD_APICID;
   4.578 -	unmap_cpu_to_node(cpu);
   4.579 -}
   4.580 -
   4.581 -#if APIC_DEBUG
   4.582 -static inline void __inquire_remote_apic(int apicid)
   4.583 -{
   4.584 -	int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
   4.585 -	char *names[] = { "ID", "VERSION", "SPIV" };
   4.586 -	int timeout, status;
   4.587 -
   4.588 -	printk("Inquiring remote APIC #%d...\n", apicid);
   4.589 -
   4.590 -	for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
   4.591 -		printk("... APIC #%d %s: ", apicid, names[i]);
   4.592 -
   4.593 -		/*
   4.594 -		 * Wait for idle.
   4.595 -		 */
   4.596 -		apic_wait_icr_idle();
   4.597 -
   4.598 -		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
   4.599 -		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
   4.600 -
   4.601 -		timeout = 0;
   4.602 -		do {
   4.603 -			udelay(100);
   4.604 -			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
   4.605 -		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
   4.606 -
   4.607 -		switch (status) {
   4.608 -		case APIC_ICR_RR_VALID:
   4.609 -			status = apic_read(APIC_RRR);
   4.610 -			printk("%08x\n", status);
   4.611 -			break;
   4.612 -		default:
   4.613 -			printk("failed\n");
   4.614 -		}
   4.615 -	}
   4.616 -}
   4.617 -#endif
   4.618 -
   4.619 -#if 0
   4.620 -#ifdef WAKE_SECONDARY_VIA_NMI
   4.621 -/* 
   4.622 - * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
   4.623 - * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
   4.624 - * won't ... remember to clear down the APIC, etc later.
   4.625 - */
   4.626 -static int __init
   4.627 -wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
   4.628 -{
   4.629 -	unsigned long send_status = 0, accept_status = 0;
   4.630 -	int timeout, maxlvt;
   4.631 -
   4.632 -	/* Target chip */
   4.633 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
   4.634 -
   4.635 -	/* Boot on the stack */
   4.636 -	/* Kick the second */
   4.637 -	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
   4.638 -
   4.639 -	Dprintk("Waiting for send to finish...\n");
   4.640 -	timeout = 0;
   4.641 -	do {
   4.642 -		Dprintk("+");
   4.643 -		udelay(100);
   4.644 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.645 -	} while (send_status && (timeout++ < 1000));
   4.646 -
   4.647 -	/*
   4.648 -	 * Give the other CPU some time to accept the IPI.
   4.649 -	 */
   4.650 -	udelay(200);
   4.651 -	/*
   4.652 -	 * Due to the Pentium erratum 3AP.
   4.653 -	 */
   4.654 -	maxlvt = get_maxlvt();
   4.655 -	if (maxlvt > 3) {
   4.656 -		apic_read_around(APIC_SPIV);
   4.657 -		apic_write(APIC_ESR, 0);
   4.658 -	}
   4.659 -	accept_status = (apic_read(APIC_ESR) & 0xEF);
   4.660 -	Dprintk("NMI sent.\n");
   4.661 -
   4.662 -	if (send_status)
   4.663 -		printk("APIC never delivered???\n");
   4.664 -	if (accept_status)
   4.665 -		printk("APIC delivery error (%lx).\n", accept_status);
   4.666 -
   4.667 -	return (send_status | accept_status);
   4.668 -}
   4.669 -#endif	/* WAKE_SECONDARY_VIA_NMI */
   4.670 -
   4.671 -#ifdef WAKE_SECONDARY_VIA_INIT
   4.672 -static int __init
   4.673 -wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
   4.674 -{
   4.675 -	unsigned long send_status = 0, accept_status = 0;
   4.676 -	int maxlvt, timeout, num_starts, j;
   4.677 -
   4.678 -	/*
   4.679 -	 * Be paranoid about clearing APIC errors.
   4.680 -	 */
   4.681 -	if (APIC_INTEGRATED(apic_version[phys_apicid])) {
   4.682 -		apic_read_around(APIC_SPIV);
   4.683 -		apic_write(APIC_ESR, 0);
   4.684 -		apic_read(APIC_ESR);
   4.685 -	}
   4.686 -
   4.687 -	Dprintk("Asserting INIT.\n");
   4.688 -
   4.689 -	/*
   4.690 -	 * Turn INIT on target chip
   4.691 -	 */
   4.692 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   4.693 -
   4.694 -	/*
   4.695 -	 * Send IPI
   4.696 -	 */
   4.697 -	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
   4.698 -				| APIC_DM_INIT);
   4.699 -
   4.700 -	Dprintk("Waiting for send to finish...\n");
   4.701 -	timeout = 0;
   4.702 -	do {
   4.703 -		Dprintk("+");
   4.704 -		udelay(100);
   4.705 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.706 -	} while (send_status && (timeout++ < 1000));
   4.707 -
   4.708 -	mdelay(10);
   4.709 -
   4.710 -	Dprintk("Deasserting INIT.\n");
   4.711 -
   4.712 -	/* Target chip */
   4.713 -	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   4.714 -
   4.715 -	/* Send IPI */
   4.716 -	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
   4.717 -
   4.718 -	Dprintk("Waiting for send to finish...\n");
   4.719 -	timeout = 0;
   4.720 -	do {
   4.721 -		Dprintk("+");
   4.722 -		udelay(100);
   4.723 -		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.724 -	} while (send_status && (timeout++ < 1000));
   4.725 -
   4.726 -	atomic_set(&init_deasserted, 1);
   4.727 -
   4.728 -	/*
   4.729 -	 * Should we send STARTUP IPIs ?
   4.730 -	 *
   4.731 -	 * Determine this based on the APIC version.
   4.732 -	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
   4.733 -	 */
   4.734 -	if (APIC_INTEGRATED(apic_version[phys_apicid]))
   4.735 -		num_starts = 2;
   4.736 -	else
   4.737 -		num_starts = 0;
   4.738 -
   4.739 -	/*
   4.740 -	 * Run STARTUP IPI loop.
   4.741 -	 */
   4.742 -	Dprintk("#startup loops: %d.\n", num_starts);
   4.743 -
   4.744 -	maxlvt = get_maxlvt();
   4.745 -
   4.746 -	for (j = 1; j <= num_starts; j++) {
   4.747 -		Dprintk("Sending STARTUP #%d.\n",j);
   4.748 -		apic_read_around(APIC_SPIV);
   4.749 -		apic_write(APIC_ESR, 0);
   4.750 -		apic_read(APIC_ESR);
   4.751 -		Dprintk("After apic_write.\n");
   4.752 -
   4.753 -		/*
   4.754 -		 * STARTUP IPI
   4.755 -		 */
   4.756 -
   4.757 -		/* Target chip */
   4.758 -		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
   4.759 -
   4.760 -		/* Boot on the stack */
   4.761 -		/* Kick the second */
   4.762 -		apic_write_around(APIC_ICR, APIC_DM_STARTUP
   4.763 -					| (start_eip >> 12));
   4.764 -
   4.765 -		/*
   4.766 -		 * Give the other CPU some time to accept the IPI.
   4.767 -		 */
   4.768 -		udelay(300);
   4.769 -
   4.770 -		Dprintk("Startup point 1.\n");
   4.771 -
   4.772 -		Dprintk("Waiting for send to finish...\n");
   4.773 -		timeout = 0;
   4.774 -		do {
   4.775 -			Dprintk("+");
   4.776 -			udelay(100);
   4.777 -			send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
   4.778 -		} while (send_status && (timeout++ < 1000));
   4.779 -
   4.780 -		/*
   4.781 -		 * Give the other CPU some time to accept the IPI.
   4.782 -		 */
   4.783 -		udelay(200);
   4.784 -		/*
   4.785 -		 * Due to the Pentium erratum 3AP.
   4.786 -		 */
   4.787 -		if (maxlvt > 3) {
   4.788 -			apic_read_around(APIC_SPIV);
   4.789 -			apic_write(APIC_ESR, 0);
   4.790 -		}
   4.791 -		accept_status = (apic_read(APIC_ESR) & 0xEF);
   4.792 -		if (send_status || accept_status)
   4.793 -			break;
   4.794 -	}
   4.795 -	Dprintk("After Startup.\n");
   4.796 -
   4.797 -	if (send_status)
   4.798 -		printk("APIC never delivered???\n");
   4.799 -	if (accept_status)
   4.800 -		printk("APIC delivery error (%lx).\n", accept_status);
   4.801 -
   4.802 -	return (send_status | accept_status);
   4.803 -}
   4.804 -#endif	/* WAKE_SECONDARY_VIA_INIT */
   4.805 -#endif
   4.806 -
   4.807 -extern cpumask_t cpu_initialized;
   4.808 -
   4.809 -static int __init do_boot_cpu(int apicid)
   4.810 -/*
   4.811 - * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
   4.812 - * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
   4.813 - * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
   4.814 - */
   4.815 -{
   4.816 -	struct task_struct *idle;
   4.817 -	unsigned long boot_error;
   4.818 -	int timeout, cpu;
   4.819 -	unsigned long start_eip;
   4.820 -#if 0
   4.821 -	unsigned short nmi_high = 0, nmi_low = 0;
   4.822 -#endif
   4.823 -	full_execution_context_t ctxt;
   4.824 -	extern void startup_32_smp(void);
   4.825 -	extern void hypervisor_callback(void);
   4.826 -	extern void failsafe_callback(void);
   4.827 -	extern int smp_trap_init(trap_info_t *);
   4.828 -	int i;
   4.829 -
   4.830 -	cpu = ++cpucount;
   4.831 -	/*
   4.832 -	 * We can't use kernel_thread since we must avoid to
   4.833 -	 * reschedule the child.
   4.834 -	 */
   4.835 -	idle = fork_idle(cpu);
   4.836 -	if (IS_ERR(idle))
   4.837 -		panic("failed fork for CPU %d", cpu);
   4.838 -	idle->thread.eip = (unsigned long) start_secondary;
   4.839 -	/* start_eip had better be page-aligned! */
   4.840 -	start_eip = (unsigned long)startup_32_smp;
   4.841 -
   4.842 -	/* So we see what's up   */
   4.843 -	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
   4.844 -	/* Stack for startup_32 can be just as for start_secondary onwards */
   4.845 -	stack_start.esp = (void *) idle->thread.esp;
   4.846 -
   4.847 -	irq_ctx_init(cpu);
   4.848 -
   4.849 -	/*
   4.850 -	 * This grunge runs the startup process for
   4.851 -	 * the targeted processor.
   4.852 -	 */
   4.853 -
   4.854 -	atomic_set(&init_deasserted, 0);
   4.855 -
   4.856 -#if 1
   4.857 -	if (cpu_gdt_descr[0].size > PAGE_SIZE)
   4.858 -		BUG();
   4.859 -	cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
   4.860 -	memcpy((void *)cpu_gdt_descr[cpu].address,
   4.861 -	       (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
   4.862 -		memset((char *)cpu_gdt_descr[cpu].address +
   4.863 -		       FIRST_RESERVED_GDT_ENTRY * 8, 0,
   4.864 -		       NR_RESERVED_GDT_ENTRIES * 8);
   4.865 -
   4.866 -	memset(&ctxt, 0, sizeof(ctxt));
   4.867 -
   4.868 -	ctxt.cpu_ctxt.ds = __USER_DS;
   4.869 -	ctxt.cpu_ctxt.es = __USER_DS;
   4.870 -	ctxt.cpu_ctxt.fs = 0;
   4.871 -	ctxt.cpu_ctxt.gs = 0;
   4.872 -	ctxt.cpu_ctxt.ss = __KERNEL_DS;
   4.873 -	ctxt.cpu_ctxt.cs = __KERNEL_CS;
   4.874 -	ctxt.cpu_ctxt.eip = start_eip;
   4.875 -	ctxt.cpu_ctxt.esp = idle->thread.esp;
   4.876 -	ctxt.cpu_ctxt.eflags = (1<<9) | (1<<2) | (idle->thread.io_pl<<12);
   4.877 -
   4.878 -	/* FPU is set up to default initial state. */
   4.879 -	memset(ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
   4.880 -
   4.881 -	/* Virtual IDT is empty at start-of-day. */
   4.882 -	for ( i = 0; i < 256; i++ )
   4.883 -	{
   4.884 -		ctxt.trap_ctxt[i].vector = i;
   4.885 -		ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
   4.886 -	}
   4.887 -	ctxt.fast_trap_idx = smp_trap_init(ctxt.trap_ctxt);
   4.888 -
   4.889 -	/* No LDT. */
   4.890 -	ctxt.ldt_ents = 0;
   4.891 -
   4.892 -	{
   4.893 -		unsigned long va;
   4.894 -		int f;
   4.895 -
   4.896 -		for (va = cpu_gdt_descr[cpu].address, f = 0;
   4.897 -		     va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size;
   4.898 -		     va += PAGE_SIZE, f++) {
   4.899 -			ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
   4.900 -			make_page_readonly((void *)va);
   4.901 -		}
   4.902 -		ctxt.gdt_ents = cpu_gdt_descr[cpu].size / 8;
   4.903 -		flush_page_update_queue();
   4.904 -	}
   4.905 -
   4.906 -	/* Ring 1 stack is the initial stack. */
   4.907 -	ctxt.kernel_ss  = __KERNEL_DS;
   4.908 -	ctxt.kernel_esp = idle->thread.esp;
   4.909 -
   4.910 -	/* Callback handlers. */
   4.911 -	ctxt.event_callback_cs     = __KERNEL_CS;
   4.912 -	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
   4.913 -	ctxt.failsafe_callback_cs  = __KERNEL_CS;
   4.914 -	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
   4.915 -
   4.916 -	ctxt.pt_base = (unsigned long)virt_to_machine(swapper_pg_dir);
   4.917 -
   4.918 -	boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt);
   4.919 -
   4.920 -	if (!boot_error) {
   4.921 -		/*
   4.922 -		 * allow APs to start initializing.
   4.923 -		 */
   4.924 -		Dprintk("Before Callout %d.\n", cpu);
   4.925 -		cpu_set(cpu, cpu_callout_map);
   4.926 -		Dprintk("After Callout %d.\n", cpu);
   4.927 -
   4.928 -		/*
   4.929 -		 * Wait 5s total for a response
   4.930 -		 */
   4.931 -		for (timeout = 0; timeout < 50000; timeout++) {
   4.932 -			if (cpu_isset(cpu, cpu_callin_map))
   4.933 -				break;	/* It has booted */
   4.934 -			udelay(100);
   4.935 -		}
   4.936 -
   4.937 -		if (cpu_isset(cpu, cpu_callin_map)) {
   4.938 -			/* number CPUs logically, starting from 1 (BSP is 0) */
   4.939 -			Dprintk("OK.\n");
   4.940 -			printk("CPU%d: ", cpu);
   4.941 -			print_cpu_info(&cpu_data[cpu]);
   4.942 -			Dprintk("CPU has booted.\n");
   4.943 -		} else {
   4.944 -			boot_error= 1;
   4.945 -		}
   4.946 -	}
   4.947 -	x86_cpu_to_apicid[cpu] = apicid;
   4.948 -	if (boot_error) {
   4.949 -		/* Try to put things back the way they were before ... */
   4.950 -		unmap_cpu_to_logical_apicid(cpu);
   4.951 -		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
   4.952 -		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
   4.953 -		cpucount--;
   4.954 -	}
   4.955 -
   4.956 -#else
   4.957 -	Dprintk("Setting warm reset code and vector.\n");
   4.958 -
   4.959 -	store_NMI_vector(&nmi_high, &nmi_low);
   4.960 -
   4.961 -	smpboot_setup_warm_reset_vector(start_eip);
   4.962 -
   4.963 -	/*
   4.964 -	 * Starting actual IPI sequence...
   4.965 -	 */
   4.966 -	boot_error = wakeup_secondary_cpu(apicid, start_eip);
   4.967 -
   4.968 -	if (!boot_error) {
   4.969 -		/*
   4.970 -		 * allow APs to start initializing.
   4.971 -		 */
   4.972 -		Dprintk("Before Callout %d.\n", cpu);
   4.973 -		cpu_set(cpu, cpu_callout_map);
   4.974 -		Dprintk("After Callout %d.\n", cpu);
   4.975 -
   4.976 -		/*
   4.977 -		 * Wait 5s total for a response
   4.978 -		 */
   4.979 -		for (timeout = 0; timeout < 50000; timeout++) {
   4.980 -			if (cpu_isset(cpu, cpu_callin_map))
   4.981 -				break;	/* It has booted */
   4.982 -			udelay(100);
   4.983 -		}
   4.984 -
   4.985 -		if (cpu_isset(cpu, cpu_callin_map)) {
   4.986 -			/* number CPUs logically, starting from 1 (BSP is 0) */
   4.987 -			Dprintk("OK.\n");
   4.988 -			printk("CPU%d: ", cpu);
   4.989 -			print_cpu_info(&cpu_data[cpu]);
   4.990 -			Dprintk("CPU has booted.\n");
   4.991 -		} else {
   4.992 -			boot_error= 1;
   4.993 -			if (*((volatile unsigned char *)trampoline_base)
   4.994 -					== 0xA5)
   4.995 -				/* trampoline started but...? */
   4.996 -				printk("Stuck ??\n");
   4.997 -			else
   4.998 -				/* trampoline code not run */
   4.999 -				printk("Not responding.\n");
  4.1000 -			inquire_remote_apic(apicid);
  4.1001 -		}
  4.1002 -	}
  4.1003 -	x86_cpu_to_apicid[cpu] = apicid;
  4.1004 -	if (boot_error) {
  4.1005 -		/* Try to put things back the way they were before ... */
  4.1006 -		unmap_cpu_to_logical_apicid(cpu);
  4.1007 -		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
  4.1008 -		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
  4.1009 -		cpucount--;
  4.1010 -	}
  4.1011 -
  4.1012 -	/* mark "stuck" area as not stuck */
  4.1013 -	*((volatile unsigned long *)trampoline_base) = 0;
  4.1014 -#endif
  4.1015 -
  4.1016 -	return boot_error;
  4.1017 -}
  4.1018 -
  4.1019 -cycles_t cacheflush_time;
  4.1020 -unsigned long cache_decay_ticks;
  4.1021 -
  4.1022 -static void smp_tune_scheduling (void)
  4.1023 -{
  4.1024 -	unsigned long cachesize;       /* kB   */
  4.1025 -	unsigned long bandwidth = 350; /* MB/s */
  4.1026 -	/*
  4.1027 -	 * Rough estimation for SMP scheduling, this is the number of
  4.1028 -	 * cycles it takes for a fully memory-limited process to flush
  4.1029 -	 * the SMP-local cache.
  4.1030 -	 *
  4.1031 -	 * (For a P5 this pretty much means we will choose another idle
  4.1032 -	 *  CPU almost always at wakeup time (this is due to the small
  4.1033 -	 *  L1 cache), on PIIs it's around 50-100 usecs, depending on
  4.1034 -	 *  the cache size)
  4.1035 -	 */
  4.1036 -
  4.1037 -	if (!cpu_khz) {
  4.1038 -		/*
  4.1039 -		 * this basically disables processor-affinity
  4.1040 -		 * scheduling on SMP without a TSC.
  4.1041 -		 */
  4.1042 -		cacheflush_time = 0;
  4.1043 -		return;
  4.1044 -	} else {
  4.1045 -		cachesize = boot_cpu_data.x86_cache_size;
  4.1046 -		if (cachesize == -1) {
  4.1047 -			cachesize = 16; /* Pentiums, 2x8kB cache */
  4.1048 -			bandwidth = 100;
  4.1049 -		}
  4.1050 -
  4.1051 -		cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
  4.1052 -	}
  4.1053 -
  4.1054 -	cache_decay_ticks = (long)cacheflush_time/cpu_khz + 1;
  4.1055 -
  4.1056 -	printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
  4.1057 -		(long)cacheflush_time/(cpu_khz/1000),
  4.1058 -		((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
  4.1059 -	printk("task migration cache decay timeout: %ld msecs.\n",
  4.1060 -		cache_decay_ticks);
  4.1061 -}
  4.1062 -
  4.1063 -/*
  4.1064 - * Cycle through the processors sending APIC IPIs to boot each.
  4.1065 - */
  4.1066 -
  4.1067 -#if 0
  4.1068 -static int boot_cpu_logical_apicid;
  4.1069 -#endif
  4.1070 -/* Where the IO area was mapped on multiquad, always 0 otherwise */
  4.1071 -void *xquad_portio;
  4.1072 -
  4.1073 -cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
  4.1074 -
  4.1075 -static void __init smp_boot_cpus(unsigned int max_cpus)
  4.1076 -{
  4.1077 -	int cpu, kicked;
  4.1078 -	unsigned long bogosum = 0;
  4.1079 -#if 0
  4.1080 -	int apicid, bit;
  4.1081 -#endif
  4.1082 -
  4.1083 -	/*
  4.1084 -	 * Setup boot CPU information
  4.1085 -	 */
  4.1086 -	smp_store_cpu_info(0); /* Final full version of the data */
  4.1087 -	printk("CPU%d: ", 0);
  4.1088 -	print_cpu_info(&cpu_data[0]);
  4.1089 -
  4.1090 -#if 0
  4.1091 -	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
  4.1092 -	boot_cpu_logical_apicid = logical_smp_processor_id();
  4.1093 -	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
  4.1094 -#else
  4.1095 -	// boot_cpu_physical_apicid = 0;
  4.1096 -	// boot_cpu_logical_apicid = 0;
  4.1097 -	x86_cpu_to_apicid[0] = 0;
  4.1098 -#endif
  4.1099 -
  4.1100 -	current_thread_info()->cpu = 0;
  4.1101 -	smp_tune_scheduling();
  4.1102 -	cpus_clear(cpu_sibling_map[0]);
  4.1103 -	cpu_set(0, cpu_sibling_map[0]);
  4.1104 -
  4.1105 -	/*
  4.1106 -	 * If we couldn't find an SMP configuration at boot time,
  4.1107 -	 * get out of here now!
  4.1108 -	 */
  4.1109 -	if (!smp_found_config /* && !acpi_lapic) */) {
  4.1110 -		printk(KERN_NOTICE "SMP motherboard not detected.\n");
  4.1111 -		smpboot_clear_io_apic_irqs();
  4.1112 -#if 0
  4.1113 -		phys_cpu_present_map = physid_mask_of_physid(0);
  4.1114 -		if (APIC_init_uniprocessor())
  4.1115 -			printk(KERN_NOTICE "Local APIC not detected."
  4.1116 -					   " Using dummy APIC emulation.\n");
  4.1117 -#endif
  4.1118 -		map_cpu_to_logical_apicid();
  4.1119 -		return;
  4.1120 -	}
  4.1121 -
  4.1122 -#if 0
  4.1123 -	/*
  4.1124 -	 * Should not be necessary because the MP table should list the boot
  4.1125 -	 * CPU too, but we do it for the sake of robustness anyway.
  4.1126 -	 * Makes no sense to do this check in clustered apic mode, so skip it
  4.1127 -	 */
  4.1128 -	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
  4.1129 -		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
  4.1130 -				boot_cpu_physical_apicid);
  4.1131 -		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
  4.1132 -	}
  4.1133 -
  4.1134 -	/*
  4.1135 -	 * If we couldn't find a local APIC, then get out of here now!
  4.1136 -	 */
  4.1137 -	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
  4.1138 -		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
  4.1139 -			boot_cpu_physical_apicid);
  4.1140 -		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
  4.1141 -		smpboot_clear_io_apic_irqs();
  4.1142 -		phys_cpu_present_map = physid_mask_of_physid(0);
  4.1143 -		return;
  4.1144 -	}
  4.1145 -
  4.1146 -	verify_local_APIC();
  4.1147 -#endif
  4.1148 -
  4.1149 -	/*
  4.1150 -	 * If SMP should be disabled, then really disable it!
  4.1151 -	 */
  4.1152 -	if (!max_cpus) {
  4.1153 -		HYPERVISOR_shared_info->n_vcpu = 1;
  4.1154 -		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
  4.1155 -		smpboot_clear_io_apic_irqs();
  4.1156 -#if 0
  4.1157 -		phys_cpu_present_map = physid_mask_of_physid(0);
  4.1158 -#endif
  4.1159 -		return;
  4.1160 -	}
  4.1161 -
  4.1162 -	smp_intr_init();
  4.1163 -
  4.1164 -#if 0
  4.1165 -	connect_bsp_APIC();
  4.1166 -	setup_local_APIC();
  4.1167 -#endif
  4.1168 -	map_cpu_to_logical_apicid();
  4.1169 -#if 0
  4.1170 -
  4.1171 -
  4.1172 -	setup_portio_remap();
  4.1173 -
  4.1174 -	/*
  4.1175 -	 * Scan the CPU present map and fire up the other CPUs via do_boot_cpu
  4.1176 -	 *
  4.1177 -	 * In clustered apic mode, phys_cpu_present_map is a constructed thus:
  4.1178 -	 * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the 
  4.1179 -	 * clustered apic ID.
  4.1180 -	 */
  4.1181 -	Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
  4.1182 -#endif
  4.1183 -	Dprintk("CPU present map: %lx\n",
  4.1184 -		(1UL << HYPERVISOR_shared_info->n_vcpu) - 1);
  4.1185 -
  4.1186 -	kicked = 1;
  4.1187 -	for (cpu = 1; kicked < NR_CPUS &&
  4.1188 -		     cpu < HYPERVISOR_shared_info->n_vcpu; cpu++) {
  4.1189 -		if (max_cpus <= cpucount+1)
  4.1190 -			continue;
  4.1191 -
  4.1192 -		if (do_boot_cpu(cpu))
  4.1193 -			printk("CPU #%d not responding - cannot use it.\n",
  4.1194 -								cpu);
  4.1195 -		else
  4.1196 -			++kicked;
  4.1197 -	}
  4.1198 -
  4.1199 -#if 0
  4.1200 -	/*
  4.1201 -	 * Cleanup possible dangling ends...
  4.1202 -	 */
  4.1203 -	smpboot_restore_warm_reset_vector();
  4.1204 -#endif
  4.1205 -
  4.1206 -	/*
  4.1207 -	 * Allow the user to impress friends.
  4.1208 -	 */
  4.1209 -	Dprintk("Before bogomips.\n");
  4.1210 -	for (cpu = 0; cpu < NR_CPUS; cpu++)
  4.1211 -		if (cpu_isset(cpu, cpu_callout_map))
  4.1212 -			bogosum += cpu_data[cpu].loops_per_jiffy;
  4.1213 -	printk(KERN_INFO
  4.1214 -		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
  4.1215 -		cpucount+1,
  4.1216 -		bogosum/(500000/HZ),
  4.1217 -		(bogosum/(5000/HZ))%100);
  4.1218 -	
  4.1219 -	Dprintk("Before bogocount - setting activated=1.\n");
  4.1220 -
  4.1221 -	if (smp_b_stepping)
  4.1222 -		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
  4.1223 -
  4.1224 -	/*
  4.1225 -	 * Don't taint if we are running SMP kernel on a single non-MP
  4.1226 -	 * approved Athlon
  4.1227 -	 */
  4.1228 -	if (tainted & TAINT_UNSAFE_SMP) {
  4.1229 -		if (cpucount)
  4.1230 -			printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
  4.1231 -		else
  4.1232 -			tainted &= ~TAINT_UNSAFE_SMP;
  4.1233 -	}
  4.1234 -
  4.1235 -	Dprintk("Boot done.\n");
  4.1236 -
  4.1237 -	/*
  4.1238 -	 * construct cpu_sibling_map[], so that we can tell sibling CPUs
  4.1239 -	 * efficiently.
  4.1240 -	 */
  4.1241 -	for (cpu = 0; cpu < NR_CPUS; cpu++)
  4.1242 -		cpus_clear(cpu_sibling_map[cpu]);
  4.1243 -
  4.1244 -	for (cpu = 0; cpu < NR_CPUS; cpu++) {
  4.1245 -		int siblings = 0;
  4.1246 -		int i;
  4.1247 -		if (!cpu_isset(cpu, cpu_callout_map))
  4.1248 -			continue;
  4.1249 -
  4.1250 -		if (smp_num_siblings > 1) {
  4.1251 -			for (i = 0; i < NR_CPUS; i++) {
  4.1252 -				if (!cpu_isset(i, cpu_callout_map))
  4.1253 -					continue;
  4.1254 -				if (phys_proc_id[cpu] == phys_proc_id[i]) {
  4.1255 -					siblings++;
  4.1256 -					cpu_set(i, cpu_sibling_map[cpu]);
  4.1257 -				}
  4.1258 -			}
  4.1259 -		} else {
  4.1260 -			siblings++;
  4.1261 -			cpu_set(cpu, cpu_sibling_map[cpu]);
  4.1262 -		}
  4.1263 -
  4.1264 -		if (siblings != smp_num_siblings)
  4.1265 -			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
  4.1266 -	}
  4.1267 -
  4.1268 -#if 0
  4.1269 -	if (nmi_watchdog == NMI_LOCAL_APIC)
  4.1270 -		check_nmi_watchdog();
  4.1271 -
  4.1272 -	smpboot_setup_io_apic();
  4.1273 -
  4.1274 -	setup_boot_APIC_clock();
  4.1275 -
  4.1276 -	/*
  4.1277 -	 * Synchronize the TSC with the AP
  4.1278 -	 */
  4.1279 -	if (cpu_has_tsc && cpucount && cpu_khz)
  4.1280 -		synchronize_tsc_bp();
  4.1281 -#endif
  4.1282 -}
  4.1283 -
  4.1284 -/* These are wrappers to interface to the new boot process.  Someone
  4.1285 -   who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
  4.1286 -void __init smp_prepare_cpus(unsigned int max_cpus)
  4.1287 -{
  4.1288 -	smp_boot_cpus(max_cpus);
  4.1289 -}
  4.1290 -
  4.1291 -void __devinit smp_prepare_boot_cpu(void)
  4.1292 -{
  4.1293 -	cpu_set(smp_processor_id(), cpu_online_map);
  4.1294 -	cpu_set(smp_processor_id(), cpu_callout_map);
  4.1295 -}
  4.1296 -
  4.1297 -int __devinit __cpu_up(unsigned int cpu)
  4.1298 -{
  4.1299 -	/* This only works at boot for x86.  See "rewrite" above. */
  4.1300 -	if (cpu_isset(cpu, smp_commenced_mask)) {
  4.1301 -		local_irq_enable();
  4.1302 -		return -ENOSYS;
  4.1303 -	}
  4.1304 -
  4.1305 -	/* In case one didn't come up */
  4.1306 -	if (!cpu_isset(cpu, cpu_callin_map)) {
  4.1307 -		local_irq_enable();
  4.1308 -		return -EIO;
  4.1309 -	}
  4.1310 -
  4.1311 -	local_irq_enable();
  4.1312 -	/* Unleash the CPU! */
  4.1313 -	cpu_set(cpu, smp_commenced_mask);
  4.1314 -	while (!cpu_isset(cpu, cpu_online_map))
  4.1315 -		mb();
  4.1316 -	return 0;
  4.1317 -}
  4.1318 -
  4.1319 -void __init smp_cpus_done(unsigned int max_cpus)
  4.1320 -{
  4.1321 -#if 1
  4.1322 -#else
  4.1323 -#ifdef CONFIG_X86_IO_APIC
  4.1324 -	setup_ioapic_dest();
  4.1325 -#endif
  4.1326 -	zap_low_mappings();
  4.1327 -	/*
  4.1328 -	 * Disable executability of the SMP trampoline:
  4.1329 -	 */
  4.1330 -	set_kernel_exec((unsigned long)trampoline_base, trampoline_exec);
  4.1331 -#endif
  4.1332 -}
  4.1333 -
  4.1334 -extern irqreturn_t smp_reschedule_interrupt(int, void *, struct pt_regs *);
  4.1335 -
  4.1336 -static struct irqaction reschedule_irq = {
  4.1337 -	smp_reschedule_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "reschedule",
  4.1338 -	NULL, NULL
  4.1339 -};
  4.1340 -
  4.1341 -extern irqreturn_t smp_invalidate_interrupt(int, void *, struct pt_regs *);
  4.1342 -
  4.1343 -static struct irqaction invalidate_irq = {
  4.1344 -	smp_invalidate_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "invalidate",
  4.1345 -	NULL, NULL
  4.1346 -};
  4.1347 -
  4.1348 -extern irqreturn_t smp_call_function_interrupt(int, void *, struct pt_regs *);
  4.1349 -
  4.1350 -static struct irqaction call_function_irq = {
  4.1351 -	smp_call_function_interrupt, SA_INTERRUPT, CPU_MASK_NONE,
  4.1352 -	"call_function", NULL, NULL
  4.1353 -};
  4.1354 -
  4.1355 -void __init smp_intr_init(void)
  4.1356 -{
  4.1357 -
  4.1358 -	(void)setup_irq(
  4.1359 -	    bind_ipi_on_cpu_to_irq(smp_processor_id(), RESCHEDULE_VECTOR),
  4.1360 -	    &reschedule_irq);
  4.1361 -	(void)setup_irq(
  4.1362 -	    bind_ipi_on_cpu_to_irq(smp_processor_id(), INVALIDATE_TLB_VECTOR),
  4.1363 -	    &invalidate_irq);
  4.1364 -	(void)setup_irq(
  4.1365 -	    bind_ipi_on_cpu_to_irq(smp_processor_id(), CALL_FUNCTION_VECTOR),
  4.1366 -	    &call_function_irq);
  4.1367 -}
     5.1 --- a/linux-2.6.10-xen-sparse/arch/xen/kernel/smp.c	Sat Mar 12 20:44:12 2005 +0000
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,19 +0,0 @@
     5.4 -/* Copyright (C) 2004, Christian Limpach */
     5.5 -
     5.6 -#include <linux/init.h>
     5.7 -#include <linux/kernel.h>
     5.8 -#include <linux/threads.h>
     5.9 -
    5.10 -unsigned int __initdata maxcpus = NR_CPUS;
    5.11 -
    5.12 -
    5.13 -/*
    5.14 - * the frequency of the profiling timer can be changed
    5.15 - * by writing a multiplier value into /proc/profile.
    5.16 - */
    5.17 -int setup_profiling_timer(unsigned int multiplier)
    5.18 -{
    5.19 -	printk("setup_profiling_timer\n");
    5.20 -
    5.21 -	return 0;
    5.22 -}
     6.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/Makefile	Sat Mar 12 20:44:12 2005 +0000
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,3 +0,0 @@
     6.4 -
     6.5 -obj-y	:= blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o 
     6.6 -
     7.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.c	Sat Mar 12 20:44:12 2005 +0000
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,87 +0,0 @@
     7.4 -/******************************************************************************
     7.5 - * blktap.c
     7.6 - * 
     7.7 - * XenLinux virtual block-device tap.
     7.8 - * 
     7.9 - * Copyright (c) 2004, Andrew Warfield
    7.10 - *
    7.11 - * Based on the original split block driver:
    7.12 - * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
    7.13 - * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
    7.14 - * Copyright (c) 2004, Christian Limpach
    7.15 - * 
    7.16 - * Note that unlike the split block driver code, this driver has been developed
    7.17 - * strictly for Linux 2.6
    7.18 - */
    7.19 -
    7.20 -#include "blktap.h"
    7.21 -
    7.22 -int __init xlblktap_init(void)
    7.23 -{
    7.24 -    ctrl_msg_t               cmsg;
    7.25 -    blkif_fe_driver_status_t fe_st;
    7.26 -    blkif_be_driver_status_t be_st;
    7.27 -
    7.28 -    printk(KERN_INFO "Initialising Xen block tap device\n");
    7.29 -
    7.30 -    DPRINTK("   tap - Backend connection init:\n");
    7.31 -
    7.32 -
    7.33 -    (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
    7.34 -                                    CALLBACK_IN_BLOCKING_CONTEXT);
    7.35 -
    7.36 -    /* Send a driver-UP notification to the domain controller. */
    7.37 -    cmsg.type      = CMSG_BLKIF_FE;
    7.38 -    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
    7.39 -    cmsg.length    = sizeof(blkif_fe_driver_status_t);
    7.40 -    fe_st.status   = BLKIF_DRIVER_STATUS_UP;
    7.41 -    memcpy(cmsg.msg, &fe_st, sizeof(fe_st));
    7.42 -    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    7.43 -
    7.44 -    DPRINTK("   tap - Frontend connection init:\n");
    7.45 -    
    7.46 -    active_reqs_init();
    7.47 -    blkif_interface_init();
    7.48 -    blkdev_schedule_init();
    7.49 -    
    7.50 -    (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
    7.51 -                                    CALLBACK_IN_BLOCKING_CONTEXT);
    7.52 -
    7.53 -    /* Send a driver-UP notification to the domain controller. */
    7.54 -    cmsg.type      = CMSG_BLKIF_BE;
    7.55 -    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS;
    7.56 -    cmsg.length    = sizeof(blkif_be_driver_status_t);
    7.57 -    be_st.status   = BLKIF_DRIVER_STATUS_UP;
    7.58 -    memcpy(cmsg.msg, &be_st, sizeof(be_st));
    7.59 -    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    7.60 -
    7.61 -    DPRINTK("   tap - Userland channel init:\n");
    7.62 -
    7.63 -    blktap_init();
    7.64 -
    7.65 -    DPRINTK("Blkif tap device initialized.\n");
    7.66 -
    7.67 -    return 0;
    7.68 -}
    7.69 -
    7.70 -#if 0 /* tap doesn't handle suspend/resume */
    7.71 -void blkdev_suspend(void)
    7.72 -{
    7.73 -}
    7.74 -
    7.75 -void blkdev_resume(void)
    7.76 -{
    7.77 -    ctrl_msg_t               cmsg;
    7.78 -    blkif_fe_driver_status_t st;    
    7.79 -
    7.80 -    /* Send a driver-UP notification to the domain controller. */
    7.81 -    cmsg.type      = CMSG_BLKIF_FE;
    7.82 -    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
    7.83 -    cmsg.length    = sizeof(blkif_fe_driver_status_t);
    7.84 -    st.status      = BLKIF_DRIVER_STATUS_UP;
    7.85 -    memcpy(cmsg.msg, &st, sizeof(st));
    7.86 -    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
    7.87 -}
    7.88 -#endif
    7.89 -
    7.90 -__initcall(xlblktap_init);
     8.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap.h	Sat Mar 12 20:44:12 2005 +0000
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,250 +0,0 @@
     8.4 -/*
     8.5 - * blktap.h
     8.6 - * 
     8.7 - * Interfaces for the Xen block tap driver.
     8.8 - * 
     8.9 - * (c) 2004, Andrew Warfield, University of Cambridge
    8.10 - * 
    8.11 - */
    8.12 -
    8.13 -#ifndef __BLKTAP_H__
    8.14 -#define __BLKTAP_H__
    8.15 -
    8.16 -#include <linux/version.h>
    8.17 -#include <linux/blkdev.h>
    8.18 -#include <linux/config.h>
    8.19 -#include <linux/sched.h>
    8.20 -#include <linux/interrupt.h>
    8.21 -#include <asm-xen/ctrl_if.h>
    8.22 -#include <linux/slab.h>
    8.23 -#include <linux/blkdev.h>
    8.24 -#include <asm/io.h>
    8.25 -#include <asm/setup.h>
    8.26 -#include <asm/pgalloc.h>
    8.27 -#include <asm-xen/hypervisor.h>
    8.28 -#include <asm-xen/xen-public/io/blkif.h>
    8.29 -#include <asm-xen/xen-public/io/ring.h>
    8.30 -
    8.31 -/* Used to signal to the backend that this is a tap domain. */
    8.32 -#define BLKTAP_COOKIE 0xbeadfeed
    8.33 -
    8.34 -/* -------[ debug / pretty printing ]--------------------------------- */
    8.35 -
    8.36 -#if 0
    8.37 -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
    8.38 -                           __FILE__ , __LINE__ , ## _a )
    8.39 -#else
    8.40 -#define DPRINTK(_f, _a...) ((void)0)
    8.41 -#endif
    8.42 -
    8.43 -#if 1
    8.44 -#define ASSERT(_p) \
    8.45 -    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
    8.46 -    __LINE__, __FILE__); *(int*)0=0; }
    8.47 -#else
    8.48 -#define ASSERT(_p) ((void)0)
    8.49 -#endif
    8.50 -
    8.51 -#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
    8.52 -
    8.53 -
    8.54 -/* -------[ state descriptors ]--------------------------------------- */
    8.55 -
    8.56 -#define BLKIF_STATE_CLOSED       0
    8.57 -#define BLKIF_STATE_DISCONNECTED 1
    8.58 -#define BLKIF_STATE_CONNECTED    2
    8.59 -
    8.60 -/* -------[ connection tracking ]------------------------------------- */
    8.61 -
    8.62 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
    8.63 -#define VMALLOC_VMADDR(x) ((unsigned long)(x))
    8.64 -#endif
    8.65 -
    8.66 -extern spinlock_t blkif_io_lock;
    8.67 -
    8.68 -typedef struct blkif_st {
    8.69 -    /* Unique identifier for this interface. */
    8.70 -    domid_t             domid;
    8.71 -    unsigned int        handle;
    8.72 -    /* Physical parameters of the comms window. */
    8.73 -    unsigned long       shmem_frame;
    8.74 -    unsigned int        evtchn;
    8.75 -    int                 irq;
    8.76 -    /* Comms information. */
    8.77 -    blkif_back_ring_t   blk_ring;
    8.78 -    
    8.79 -    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
    8.80 -    /*
    8.81 -     * DISCONNECT response is deferred until pending requests are ack'ed.
    8.82 -     * We therefore need to store the id from the original request.
    8.83 -     */    
    8.84 -    u8                  disconnect_rspid;
    8.85 -    struct blkif_st    *hash_next;
    8.86 -    struct list_head    blkdev_list;
    8.87 -    spinlock_t          blk_ring_lock;
    8.88 -    atomic_t            refcnt;
    8.89 -    struct work_struct work;
    8.90 -} blkif_t;
    8.91 -
    8.92 -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle);
    8.93 -void blkif_disconnect_complete(blkif_t *blkif);
    8.94 -#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
    8.95 -#define blkif_put(_b)                             \
    8.96 -    do {                                          \
    8.97 -        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
    8.98 -            blkif_disconnect_complete(_b);        \
    8.99 -    } while (0)
   8.100 -
   8.101 -
   8.102 -/* -------[ active request tracking ]--------------------------------- */
   8.103 -
   8.104 -typedef struct {
   8.105 -    blkif_t       *blkif;
   8.106 -    unsigned long  id;
   8.107 -    int            nr_pages;
   8.108 -    unsigned long  mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   8.109 -    unsigned long  virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   8.110 -    int            next_free;
   8.111 -} active_req_t;
   8.112 -
   8.113 -typedef unsigned int ACTIVE_RING_IDX;
   8.114 -
   8.115 -active_req_t *lookup_active_req(ACTIVE_RING_IDX idx);
   8.116 -
   8.117 -extern inline unsigned int ID_TO_IDX(unsigned long id) 
   8.118 -{ 
   8.119 -    return ( id & 0x0000ffff );
   8.120 -}
   8.121 -
   8.122 -extern inline domid_t ID_TO_DOM(unsigned long id) 
   8.123 -{ 
   8.124 -    return (id >> 16); 
   8.125 -}
   8.126 -
   8.127 -void active_reqs_init(void);
   8.128 -
   8.129 -/* -------[ interposition -> character device interface ]------------- */
   8.130 -
   8.131 -/* /dev/xen/blktap resides at device number major=10, minor=200        */ 
   8.132 -#define BLKTAP_MINOR 202
   8.133 -
   8.134 -/* size of the extra VMA area to map in attached pages. */
   8.135 -#define BLKTAP_VMA_PAGES BLKIF_RING_SIZE
   8.136 -
   8.137 -/* blktap IOCTLs:                                                      */
   8.138 -#define BLKTAP_IOCTL_KICK_FE         1
   8.139 -#define BLKTAP_IOCTL_KICK_BE         2
   8.140 -#define BLKTAP_IOCTL_SETMODE         3
   8.141 -#define BLKTAP_IOCTL_PRINT_IDXS      100  
   8.142 -
   8.143 -/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */
   8.144 -#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
   8.145 -#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
   8.146 -#define BLKTAP_MODE_INTERCEPT_BE     0x00000002
   8.147 -#define BLKTAP_MODE_COPY_FE          0x00000004
   8.148 -#define BLKTAP_MODE_COPY_BE          0x00000008
   8.149 -#define BLKTAP_MODE_COPY_FE_PAGES    0x00000010
   8.150 -#define BLKTAP_MODE_COPY_BE_PAGES    0x00000020
   8.151 -
   8.152 -#define BLKTAP_MODE_INTERPOSE \
   8.153 -           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
   8.154 -
   8.155 -#define BLKTAP_MODE_COPY_BOTH \
   8.156 -           (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE)
   8.157 -
   8.158 -#define BLKTAP_MODE_COPY_BOTH_PAGES \
   8.159 -           (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES)
   8.160 -
   8.161 -static inline int BLKTAP_MODE_VALID(unsigned long arg)
   8.162 -{
   8.163 -    return (
   8.164 -        ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
   8.165 -        ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
   8.166 -        ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
   8.167 -        ( arg == BLKTAP_MODE_INTERPOSE    ) ||
   8.168 -        ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
   8.169 -        ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
   8.170 -        ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
   8.171 -        );
   8.172 -}
   8.173 -
   8.174 -
   8.175 -
   8.176 -/* -------[ Mappings to User VMA ]------------------------------------ */
   8.177 -#define MAX_PENDING_REQS 64
   8.178 -#define BATCH_PER_DOMAIN 16
   8.179 -extern struct vm_area_struct *blktap_vma;
   8.180 -
   8.181 -/* The following are from blkback.c and should probably be put in a
   8.182 - * header and included from there.
   8.183 - * The mmap area described here is where attached data pages eill be mapped.
   8.184 - */
   8.185 - 
   8.186 -extern unsigned long mmap_vstart;
   8.187 -#define MMAP_PAGES_PER_REQUEST \
   8.188 -    (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
   8.189 -#define MMAP_PAGES             \
   8.190 -    (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
   8.191 -#define MMAP_VADDR(_req,_seg)                        \
   8.192 -    (mmap_vstart +                                   \
   8.193 -     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
   8.194 -     ((_seg) * PAGE_SIZE))
   8.195 -
   8.196 -/* immediately before the mmap area, we have a bunch of pages reserved
   8.197 - * for shared memory rings.
   8.198 - */
   8.199 -
   8.200 -#define RING_PAGES 3 /* Ctrl, Front, and Back */ 
   8.201 -extern unsigned long rings_vstart;
   8.202 -
   8.203 -
   8.204 -/* -------[ Here be globals ]----------------------------------------- */
   8.205 -extern unsigned long blktap_mode;
   8.206 -
   8.207 -/* Connection to a single backend domain. */
   8.208 -extern blkif_front_ring_t blktap_be_ring;
   8.209 -extern unsigned int blktap_be_evtchn;
   8.210 -extern unsigned int blktap_be_state;
   8.211 -
   8.212 -/* User ring status. */
   8.213 -extern unsigned long blktap_ring_ok;
   8.214 -
   8.215 -/* -------[ ...and function prototypes. ]----------------------------- */
   8.216 -
   8.217 -/* init function for character device interface.                       */
   8.218 -int blktap_init(void);
   8.219 -
   8.220 -/* init function for the blkif cache. */
   8.221 -void __init blkif_interface_init(void);
   8.222 -void __init blkdev_schedule_init(void);
   8.223 -void blkif_deschedule(blkif_t *blkif);
   8.224 -
   8.225 -/* interfaces to the char driver, passing messages to and from apps.   */
   8.226 -void blktap_kick_user(void);
   8.227 -
   8.228 -/* user ring access functions: */
   8.229 -int blktap_write_fe_ring(blkif_request_t *req);
   8.230 -int blktap_write_be_ring(blkif_response_t *rsp);
   8.231 -int blktap_write_ctrl_ring(ctrl_msg_t *msg);
   8.232 -
   8.233 -/* fe/be ring access functions: */
   8.234 -int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp);
   8.235 -int write_req_to_be_ring(blkif_request_t *req);
   8.236 -
   8.237 -/* event notification functions */
   8.238 -void kick_fe_domain(blkif_t *blkif);
   8.239 -void kick_be_domain(void);
   8.240 -
   8.241 -/* Interrupt handlers. */
   8.242 -irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
   8.243 -                                  struct pt_regs *ptregs);
   8.244 -irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs);
   8.245 -
   8.246 -/* Control message receiver. */
   8.247 -extern void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id);
   8.248 -
   8.249 -/* debug */
   8.250 -void print_vm_ring_idxs(void);
   8.251 -        
   8.252 -#define __BLKINT_H__
   8.253 -#endif
     9.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c	Sat Mar 12 20:44:12 2005 +0000
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,517 +0,0 @@
     9.4 -/******************************************************************************
     9.5 - * blktap_controlmsg.c
     9.6 - * 
     9.7 - * XenLinux virtual block-device tap.
     9.8 - * Control interfaces to the frontend and backend drivers.
     9.9 - * 
    9.10 - * Copyright (c) 2004, Andrew Warfield
    9.11 - *
    9.12 - */
    9.13 - 
    9.14 -#include "blktap.h"
    9.15 -
    9.16 -static char *blkif_state_name[] = {
    9.17 -    [BLKIF_STATE_CLOSED]       = "closed",
    9.18 -    [BLKIF_STATE_DISCONNECTED] = "disconnected",
    9.19 -    [BLKIF_STATE_CONNECTED]    = "connected",
    9.20 -};
    9.21 -
    9.22 -static char * blkif_status_name[] = {
    9.23 -    [BLKIF_INTERFACE_STATUS_CLOSED]       = "closed",
    9.24 -    [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
    9.25 -    [BLKIF_INTERFACE_STATUS_CONNECTED]    = "connected",
    9.26 -    [BLKIF_INTERFACE_STATUS_CHANGED]      = "changed",
    9.27 -};
    9.28 -
    9.29 -static unsigned blktap_be_irq;
    9.30 -unsigned int    blktap_be_state = BLKIF_STATE_CLOSED;
    9.31 -unsigned int    blktap_be_evtchn;
    9.32 -
    9.33 -/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
    9.34 -
    9.35 -#define BLKIF_HASHSZ 1024
    9.36 -#define BLKIF_HASH(_d,_h) (((int)(_d)^(int)(_h))&(BLKIF_HASHSZ-1))
    9.37 -
    9.38 -static kmem_cache_t *blkif_cachep;
    9.39 -static blkif_t      *blkif_hash[BLKIF_HASHSZ];
    9.40 -
    9.41 -blkif_t *blkif_find_by_handle(domid_t domid, unsigned int handle)
    9.42 -{
    9.43 -    blkif_t *blkif = blkif_hash[BLKIF_HASH(domid, handle)];
    9.44 -    while ( (blkif != NULL) && 
    9.45 -            ((blkif->domid != domid) || (blkif->handle != handle)) )
    9.46 -        blkif = blkif->hash_next;
    9.47 -    return blkif;
    9.48 -}
    9.49 -
    9.50 -static void __blkif_disconnect_complete(void *arg)
    9.51 -{
    9.52 -    blkif_t              *blkif = (blkif_t *)arg;
    9.53 -    ctrl_msg_t            cmsg;
    9.54 -    blkif_be_disconnect_t disc;
    9.55 -
    9.56 -    /*
    9.57 -     * These can't be done in blkif_disconnect() because at that point there
    9.58 -     * may be outstanding requests at the disc whose asynchronous responses
    9.59 -     * must still be notified to the remote driver.
    9.60 -     */
    9.61 -    unbind_evtchn_from_irq(blkif->evtchn);
    9.62 -    vfree(blkif->blk_ring.sring);
    9.63 -
    9.64 -    /* Construct the deferred response message. */
    9.65 -    cmsg.type         = CMSG_BLKIF_BE;
    9.66 -    cmsg.subtype      = CMSG_BLKIF_BE_DISCONNECT;
    9.67 -    cmsg.id           = blkif->disconnect_rspid;
    9.68 -    cmsg.length       = sizeof(blkif_be_disconnect_t);
    9.69 -    disc.domid        = blkif->domid;
    9.70 -    disc.blkif_handle = blkif->handle;
    9.71 -    disc.status       = BLKIF_BE_STATUS_OKAY;
    9.72 -    memcpy(cmsg.msg, &disc, sizeof(disc));
    9.73 -
    9.74 -    /*
    9.75 -     * Make sure message is constructed /before/ status change, because
    9.76 -     * after the status change the 'blkif' structure could be deallocated at
    9.77 -     * any time. Also make sure we send the response /after/ status change,
    9.78 -     * as otherwise a subsequent CONNECT request could spuriously fail if
    9.79 -     * another CPU doesn't see the status change yet.
    9.80 -     */
    9.81 -    mb();
    9.82 -    if ( blkif->status != DISCONNECTING )
    9.83 -        BUG();
    9.84 -    blkif->status = DISCONNECTED;
    9.85 -    mb();
    9.86 -
    9.87 -    /* Send the successful response. */
    9.88 -    ctrl_if_send_response(&cmsg);
    9.89 -}
    9.90 -
    9.91 -void blkif_disconnect_complete(blkif_t *blkif)
    9.92 -{
    9.93 -    INIT_WORK(&blkif->work, __blkif_disconnect_complete, (void *)blkif);
    9.94 -    schedule_work(&blkif->work);
    9.95 -}
    9.96 -
    9.97 -void blkif_ptfe_create(blkif_be_create_t *create)
    9.98 -{
    9.99 -    blkif_t      *blkif, **pblkif;
   9.100 -    domid_t       domid  = create->domid;
   9.101 -    unsigned int  handle = create->blkif_handle;
   9.102 -
   9.103 -
   9.104 -    /* May want to store info on the connecting domain here. */
   9.105 -
   9.106 -    DPRINTK("PT got BE_CREATE\n");
   9.107 -
   9.108 -    if ( (blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL)) == NULL )
   9.109 -    {
   9.110 -        DPRINTK("Could not create blkif: out of memory\n");
   9.111 -        create->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   9.112 -        return;
   9.113 -    }
   9.114 -
   9.115 -    /* blkif struct init code from blkback.c */
   9.116 -    memset(blkif, 0, sizeof(*blkif));
   9.117 -    blkif->domid  = domid;
   9.118 -    blkif->handle = handle;
   9.119 -    blkif->status = DISCONNECTED;  
   9.120 -    spin_lock_init(&blkif->blk_ring_lock);
   9.121 -    atomic_set(&blkif->refcnt, 0);
   9.122 -
   9.123 -    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
   9.124 -    while ( *pblkif != NULL )
   9.125 -    {
   9.126 -        if ( ((*pblkif)->domid == domid) && ((*pblkif)->handle == handle) )
   9.127 -        {
   9.128 -            DPRINTK("Could not create blkif: already exists\n");
   9.129 -            create->status = BLKIF_BE_STATUS_INTERFACE_EXISTS;
   9.130 -            kmem_cache_free(blkif_cachep, blkif);
   9.131 -            return;
   9.132 -        }
   9.133 -        pblkif = &(*pblkif)->hash_next;
   9.134 -    }
   9.135 -
   9.136 -    blkif->hash_next = *pblkif;
   9.137 -    *pblkif = blkif;
   9.138 -
   9.139 -    create->status = BLKIF_BE_STATUS_OKAY;
   9.140 -}
   9.141 -
   9.142 -
   9.143 -void blkif_ptfe_destroy(blkif_be_destroy_t *destroy)
   9.144 -{
   9.145 -    /* Clear anything that we initialized above. */
   9.146 -
   9.147 -    domid_t       domid  = destroy->domid;
   9.148 -    unsigned int  handle = destroy->blkif_handle;
   9.149 -    blkif_t     **pblkif, *blkif;
   9.150 -
   9.151 -    DPRINTK("PT got BE_DESTROY\n");
   9.152 -    
   9.153 -    pblkif = &blkif_hash[BLKIF_HASH(domid, handle)];
   9.154 -    while ( (blkif = *pblkif) != NULL )
   9.155 -    {
   9.156 -        if ( (blkif->domid == domid) && (blkif->handle == handle) )
   9.157 -        {
   9.158 -            if ( blkif->status != DISCONNECTED )
   9.159 -                goto still_connected;
   9.160 -            goto destroy;
   9.161 -        }
   9.162 -        pblkif = &blkif->hash_next;
   9.163 -    }
   9.164 -
   9.165 -    destroy->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   9.166 -    return;
   9.167 -
   9.168 - still_connected:
   9.169 -    destroy->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
   9.170 -    return;
   9.171 -
   9.172 - destroy:
   9.173 -    *pblkif = blkif->hash_next;
   9.174 -    kmem_cache_free(blkif_cachep, blkif);
   9.175 -    destroy->status = BLKIF_BE_STATUS_OKAY;
   9.176 -}
   9.177 -
   9.178 -void blkif_ptfe_connect(blkif_be_connect_t *connect)
   9.179 -{
   9.180 -    domid_t        domid  = connect->domid;
   9.181 -    unsigned int   handle = connect->blkif_handle;
   9.182 -    unsigned int   evtchn = connect->evtchn;
   9.183 -    unsigned long  shmem_frame = connect->shmem_frame;
   9.184 -    struct vm_struct *vma;
   9.185 -    pgprot_t       prot;
   9.186 -    int            error;
   9.187 -    blkif_t       *blkif;
   9.188 -    blkif_sring_t *sring;
   9.189 -
   9.190 -    DPRINTK("PT got BE_CONNECT\n");
   9.191 -
   9.192 -    blkif = blkif_find_by_handle(domid, handle);
   9.193 -    if ( unlikely(blkif == NULL) )
   9.194 -    {
   9.195 -        DPRINTK("blkif_connect attempted for non-existent blkif (%u,%u)\n", 
   9.196 -                connect->domid, connect->blkif_handle); 
   9.197 -        connect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   9.198 -        return;
   9.199 -    }
   9.200 -
   9.201 -    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
   9.202 -    {
   9.203 -        connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   9.204 -        return;
   9.205 -    }
   9.206 -
   9.207 -    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
   9.208 -    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
   9.209 -                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
   9.210 -                                    prot, domid);
   9.211 -    if ( error != 0 )
   9.212 -    {
   9.213 -        WPRINTK("BE_CONNECT: error! (%d)\n", error);
   9.214 -        if ( error == -ENOMEM ) 
   9.215 -            connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   9.216 -        else if ( error == -EFAULT ) {
   9.217 -            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
   9.218 -            WPRINTK("BE_CONNECT: MAPPING error!\n");
   9.219 -        }
   9.220 -        else
   9.221 -            connect->status = BLKIF_BE_STATUS_ERROR;
   9.222 -        vfree(vma->addr);
   9.223 -        return;
   9.224 -    }
   9.225 -
   9.226 -    if ( blkif->status != DISCONNECTED )
   9.227 -    {
   9.228 -        connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
   9.229 -        vfree(vma->addr);
   9.230 -        return;
   9.231 -    }
   9.232 -
   9.233 -    sring = (blkif_sring_t *)vma->addr;
   9.234 -    SHARED_RING_INIT(sring);
   9.235 -    BACK_RING_INIT(&blkif->blk_ring, sring);
   9.236 -    
   9.237 -    blkif->evtchn        = evtchn;
   9.238 -    blkif->irq           = bind_evtchn_to_irq(evtchn);
   9.239 -    blkif->shmem_frame   = shmem_frame;
   9.240 -    blkif->status        = CONNECTED;
   9.241 -    blkif_get(blkif);
   9.242 -
   9.243 -    request_irq(blkif->irq, blkif_ptfe_int, 0, "blkif-pt-backend", blkif);
   9.244 -
   9.245 -    connect->status = BLKIF_BE_STATUS_OKAY;
   9.246 -}
   9.247 -
   9.248 -int blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect, u8 rsp_id)
   9.249 -{
   9.250 -    domid_t       domid  = disconnect->domid;
   9.251 -    unsigned int  handle = disconnect->blkif_handle;
   9.252 -    blkif_t      *blkif;
   9.253 -
   9.254 -    DPRINTK("PT got BE_DISCONNECT\n");
   9.255 -    
   9.256 -    blkif = blkif_find_by_handle(domid, handle);
   9.257 -    if ( unlikely(blkif == NULL) )
   9.258 -    {
   9.259 -        DPRINTK("blkif_disconnect attempted for non-existent blkif"
   9.260 -                " (%u,%u)\n", disconnect->domid, disconnect->blkif_handle); 
   9.261 -        disconnect->status = BLKIF_BE_STATUS_INTERFACE_NOT_FOUND;
   9.262 -        return 1; /* Caller will send response error message. */
   9.263 -    }
   9.264 -
   9.265 -    if ( blkif->status == CONNECTED )
   9.266 -    {
   9.267 -        blkif->status = DISCONNECTING;
   9.268 -        blkif->disconnect_rspid = rsp_id;
   9.269 -        wmb(); /* Let other CPUs see the status change. */
   9.270 -        free_irq(blkif->irq, blkif);
   9.271 -        blkif_deschedule(blkif);
   9.272 -        blkif_put(blkif);
   9.273 -        return 0; /* Caller should not send response message. */
   9.274 -    }
   9.275 -
   9.276 -    disconnect->status = BLKIF_BE_STATUS_OKAY;
   9.277 -    return 1;
   9.278 -}
   9.279 -
   9.280 -/*-----[ Control Messages to/from Backend VM ]----------------------------*/
   9.281 -
   9.282 -/* Tell the controller to bring up the interface. */
   9.283 -static void blkif_ptbe_send_interface_connect(void)
   9.284 -{
   9.285 -    ctrl_msg_t cmsg = {
   9.286 -        .type    = CMSG_BLKIF_FE,
   9.287 -        .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
   9.288 -        .length  = sizeof(blkif_fe_interface_connect_t),
   9.289 -    };
   9.290 -    blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
   9.291 -    msg->handle      = 0;
   9.292 -    msg->shmem_frame = virt_to_machine(blktap_be_ring.sring) >> PAGE_SHIFT;
   9.293 -    
   9.294 -    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   9.295 -}
   9.296 -
   9.297 -static void blkif_ptbe_close(void)
   9.298 -{
   9.299 -}
   9.300 -
   9.301 -/* Move from CLOSED to DISCONNECTED state. */
   9.302 -static void blkif_ptbe_disconnect(void)
   9.303 -{
   9.304 -    blkif_sring_t *sring;
   9.305 -    
   9.306 -    sring = (blkif_sring_t *)__get_free_page(GFP_KERNEL);
   9.307 -    SHARED_RING_INIT(sring);
   9.308 -    FRONT_RING_INIT(&blktap_be_ring, sring);
   9.309 -    blktap_be_state  = BLKIF_STATE_DISCONNECTED;
   9.310 -    DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
   9.311 -    blkif_ptbe_send_interface_connect();
   9.312 -}
   9.313 -
   9.314 -static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
   9.315 -{
   9.316 -    int err = 0;
   9.317 -    
   9.318 -    blktap_be_evtchn = status->evtchn;
   9.319 -    blktap_be_irq    = bind_evtchn_to_irq(blktap_be_evtchn);
   9.320 -
   9.321 -    err = request_irq(blktap_be_irq, blkif_ptbe_int, 
   9.322 -                      SA_SAMPLE_RANDOM, "blkif", NULL);
   9.323 -    if ( err ) {
   9.324 -	WPRINTK("blkfront request_irq failed (%d)\n", err);
   9.325 -        return;
   9.326 -    } else {
   9.327 -	/* transtion to connected in case we need to do a 
   9.328 -           a partion probe on a whole disk */
   9.329 -        blktap_be_state = BLKIF_STATE_CONNECTED;
   9.330 -    }
   9.331 -}
   9.332 -
   9.333 -static void unexpected(blkif_fe_interface_status_t *status)
   9.334 -{
   9.335 -    WPRINTK(" TAP: Unexpected blkif status %s in state %s\n", 
   9.336 -           blkif_status_name[status->status],
   9.337 -           blkif_state_name[blktap_be_state]);
   9.338 -}
   9.339 -
   9.340 -static void blkif_ptbe_status(
   9.341 -    blkif_fe_interface_status_t *status)
   9.342 -{
   9.343 -    if ( status->handle != 0 )
   9.344 -    {
   9.345 -        DPRINTK("Status change on unsupported blkif %d\n",
   9.346 -               status->handle);
   9.347 -        return;
   9.348 -    }
   9.349 -
   9.350 -    DPRINTK("ptbe_status: got %s\n", blkif_status_name[status->status]);
   9.351 -    
   9.352 -    switch ( status->status )
   9.353 -    {
   9.354 -    case BLKIF_INTERFACE_STATUS_CLOSED:
   9.355 -        switch ( blktap_be_state )
   9.356 -        {
   9.357 -        case BLKIF_STATE_CLOSED:
   9.358 -            unexpected(status);
   9.359 -            break;
   9.360 -        case BLKIF_STATE_DISCONNECTED:
   9.361 -        case BLKIF_STATE_CONNECTED:
   9.362 -            unexpected(status);
   9.363 -            blkif_ptbe_close();
   9.364 -            break;
   9.365 -        }
   9.366 -        break;
   9.367 -        
   9.368 -    case BLKIF_INTERFACE_STATUS_DISCONNECTED:
   9.369 -        switch ( blktap_be_state )
   9.370 -        {
   9.371 -        case BLKIF_STATE_CLOSED:
   9.372 -            blkif_ptbe_disconnect();
   9.373 -            break;
   9.374 -        case BLKIF_STATE_DISCONNECTED:
   9.375 -        case BLKIF_STATE_CONNECTED:
   9.376 -            printk(KERN_ALERT "*** add recovery code to the tap driver. ***\n");
   9.377 -            unexpected(status);
   9.378 -            break;
   9.379 -        }
   9.380 -        break;
   9.381 -        
   9.382 -    case BLKIF_INTERFACE_STATUS_CONNECTED:
   9.383 -        switch ( blktap_be_state )
   9.384 -        {
   9.385 -        case BLKIF_STATE_CLOSED:
   9.386 -            unexpected(status);
   9.387 -            blkif_ptbe_disconnect();
   9.388 -            blkif_ptbe_connect(status);
   9.389 -            break;
   9.390 -        case BLKIF_STATE_DISCONNECTED:
   9.391 -            blkif_ptbe_connect(status);
   9.392 -            break;
   9.393 -        case BLKIF_STATE_CONNECTED:
   9.394 -            unexpected(status);
   9.395 -            blkif_ptbe_connect(status);
   9.396 -            break;
   9.397 -        }
   9.398 -        break;
   9.399 -
   9.400 -   case BLKIF_INTERFACE_STATUS_CHANGED:
   9.401 -        switch ( blktap_be_state )
   9.402 -        {
   9.403 -        case BLKIF_STATE_CLOSED:
   9.404 -        case BLKIF_STATE_DISCONNECTED:
   9.405 -            unexpected(status);
   9.406 -            break;
   9.407 -        case BLKIF_STATE_CONNECTED:
   9.408 -            /* vbd_update(); */
   9.409 -            /* tap doesn't really get state changes... */
   9.410 -            unexpected(status);
   9.411 -            break;
   9.412 -        }
   9.413 -       break;
   9.414 -       
   9.415 -    default:
   9.416 -        DPRINTK("Status change to unknown value %d\n", status->status);
   9.417 -        break;
   9.418 -    }
   9.419 -}
   9.420 -
   9.421 -/*-----[ All control messages enter here: ]-------------------------------*/
   9.422 -
   9.423 -void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
   9.424 -{
   9.425 -    switch ( msg->type )
   9.426 -    {
   9.427 -    case CMSG_BLKIF_FE:
   9.428 -
   9.429 -        switch ( msg->subtype )
   9.430 -        {
   9.431 -        case CMSG_BLKIF_FE_INTERFACE_STATUS:
   9.432 -            if ( msg->length != sizeof(blkif_fe_interface_status_t) )
   9.433 -                goto parse_error;
   9.434 -            blkif_ptbe_status((blkif_fe_interface_status_t *) &msg->msg[0]);
   9.435 -            break;        
   9.436 -
   9.437 -        default:
   9.438 -            goto parse_error;
   9.439 -        }
   9.440 -
   9.441 -    case CMSG_BLKIF_BE:
   9.442 -        
   9.443 -        /* send a copy of the message to user if wanted */
   9.444 -        
   9.445 -        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
   9.446 -             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
   9.447 -            
   9.448 -            blktap_write_ctrl_ring(msg);
   9.449 -        }
   9.450 -        
   9.451 -        switch ( msg->subtype )
   9.452 -        {
   9.453 -        case CMSG_BLKIF_BE_CREATE:
   9.454 -            if ( msg->length != sizeof(blkif_be_create_t) )
   9.455 -                goto parse_error;
   9.456 -            blkif_ptfe_create((blkif_be_create_t *)&msg->msg[0]);
   9.457 -            break; 
   9.458 -        case CMSG_BLKIF_BE_DESTROY:
   9.459 -            if ( msg->length != sizeof(blkif_be_destroy_t) )
   9.460 -                goto parse_error;
   9.461 -            blkif_ptfe_destroy((blkif_be_destroy_t *)&msg->msg[0]);
   9.462 -            break;        
   9.463 -        case CMSG_BLKIF_BE_CONNECT:
   9.464 -            if ( msg->length != sizeof(blkif_be_connect_t) )
   9.465 -                goto parse_error;
   9.466 -            blkif_ptfe_connect((blkif_be_connect_t *)&msg->msg[0]);
   9.467 -            break;        
   9.468 -        case CMSG_BLKIF_BE_DISCONNECT:
   9.469 -            if ( msg->length != sizeof(blkif_be_disconnect_t) )
   9.470 -                goto parse_error;
   9.471 -            if ( !blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0],
   9.472 -                    msg->id) )
   9.473 -                return;
   9.474 -            break;        
   9.475 -
   9.476 -        /* We just ignore anything to do with vbds for now. */
   9.477 -        
   9.478 -        case CMSG_BLKIF_BE_VBD_CREATE:
   9.479 -            DPRINTK("PT got VBD_CREATE\n");
   9.480 -            ((blkif_be_vbd_create_t *)&msg->msg[0])->status 
   9.481 -                = BLKIF_BE_STATUS_OKAY;
   9.482 -            break;
   9.483 -        case CMSG_BLKIF_BE_VBD_DESTROY:
   9.484 -            DPRINTK("PT got VBD_DESTROY\n");
   9.485 -            ((blkif_be_vbd_destroy_t *)&msg->msg[0])->status
   9.486 -                = BLKIF_BE_STATUS_OKAY;
   9.487 -            break;
   9.488 -        case CMSG_BLKIF_BE_VBD_GROW:
   9.489 -            DPRINTK("PT got VBD_GROW\n");
   9.490 -            ((blkif_be_vbd_grow_t *)&msg->msg[0])->status
   9.491 -                = BLKIF_BE_STATUS_OKAY;
   9.492 -            break;
   9.493 -        case CMSG_BLKIF_BE_VBD_SHRINK:
   9.494 -            DPRINTK("PT got VBD_SHRINK\n");
   9.495 -            ((blkif_be_vbd_shrink_t *)&msg->msg[0])->status
   9.496 -                = BLKIF_BE_STATUS_OKAY;
   9.497 -            break;
   9.498 -        default:
   9.499 -            goto parse_error;
   9.500 -        }
   9.501 -    }
   9.502 -
   9.503 -    ctrl_if_send_response(msg);
   9.504 -    return;
   9.505 -
   9.506 - parse_error:
   9.507 -    msg->length = 0;
   9.508 -    ctrl_if_send_response(msg);
   9.509 -}
   9.510 -
   9.511 -/*-----[ Initialization ]-------------------------------------------------*/
   9.512 -
   9.513 -void __init blkif_interface_init(void)
   9.514 -{
   9.515 -    blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t), 
   9.516 -                                     0, 0, NULL, NULL);
   9.517 -    memset(blkif_hash, 0, sizeof(blkif_hash));
   9.518 -    
   9.519 -    blktap_be_ring.sring = NULL;
   9.520 -}
    10.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_datapath.c	Sat Mar 12 20:44:12 2005 +0000
    10.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.3 @@ -1,472 +0,0 @@
    10.4 -/******************************************************************************
    10.5 - * blktap_datapath.c
    10.6 - * 
    10.7 - * XenLinux virtual block-device tap.
    10.8 - * Block request routing data path.
    10.9 - * 
   10.10 - * Copyright (c) 2004, Andrew Warfield
   10.11 - * -- see full header in blktap.c
   10.12 - */
   10.13 - 
   10.14 -#include "blktap.h"
   10.15 -#include <asm-xen/evtchn.h>
   10.16 -
   10.17 -/*-----[ The data paths ]-------------------------------------------------*/
   10.18 -
   10.19 -/* Connection to a single backend domain. */
   10.20 -blkif_front_ring_t blktap_be_ring;
   10.21 -
   10.22 -/*-----[ Tracking active requests ]---------------------------------------*/
   10.23 -
   10.24 -/* this must be the same as MAX_PENDING_REQS in blkback.c */
   10.25 -#define MAX_ACTIVE_REQS ((ACTIVE_RING_IDX)64U)
   10.26 -
   10.27 -active_req_t     active_reqs[MAX_ACTIVE_REQS];
   10.28 -ACTIVE_RING_IDX  active_req_ring[MAX_ACTIVE_REQS];
   10.29 -spinlock_t       active_req_lock = SPIN_LOCK_UNLOCKED;
   10.30 -ACTIVE_RING_IDX  active_prod, active_cons;
   10.31 -#define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1))
   10.32 -#define ACTIVE_IDX(_ar) (_ar - active_reqs)
   10.33 -#define NR_ACTIVE_REQS (MAX_ACTIVE_REQS - active_prod + active_cons)
   10.34 -
   10.35 -inline active_req_t *get_active_req(void) 
   10.36 -{
   10.37 -    ACTIVE_RING_IDX idx;
   10.38 -    active_req_t *ar;
   10.39 -    unsigned long flags;
   10.40 -        
   10.41 -    ASSERT(active_cons != active_prod);   
   10.42 -    
   10.43 -    spin_lock_irqsave(&active_req_lock, flags);
   10.44 -    idx =  active_req_ring[MASK_ACTIVE_IDX(active_cons++)];
   10.45 -    ar = &active_reqs[idx];
   10.46 -    spin_unlock_irqrestore(&active_req_lock, flags);
   10.47 -    
   10.48 -    return ar;
   10.49 -}
   10.50 -
   10.51 -inline void free_active_req(active_req_t *ar) 
   10.52 -{
   10.53 -    unsigned long flags;
   10.54 -        
   10.55 -    spin_lock_irqsave(&active_req_lock, flags);
   10.56 -    active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
   10.57 -    spin_unlock_irqrestore(&active_req_lock, flags);
   10.58 -}
   10.59 -
   10.60 -active_req_t *lookup_active_req(ACTIVE_RING_IDX idx)
   10.61 -{
   10.62 -    return &active_reqs[idx];   
   10.63 -}
   10.64 -
   10.65 -void active_reqs_init(void)
   10.66 -{
   10.67 -    ACTIVE_RING_IDX i;
   10.68 -    
   10.69 -    active_cons = 0;
   10.70 -    active_prod = MAX_ACTIVE_REQS;
   10.71 -    memset(active_reqs, 0, sizeof(active_reqs));
   10.72 -    for ( i = 0; i < MAX_ACTIVE_REQS; i++ )
   10.73 -        active_req_ring[i] = i;
   10.74 -}
   10.75 -
   10.76 -/* Requests passing through the tap to the backend hijack the id field
   10.77 - * in the request message.  In it we put the AR index _AND_ the fe domid.
   10.78 - * the domid is used by the backend to map the pages properly.
   10.79 - */
   10.80 -
   10.81 -static inline unsigned long MAKE_ID(domid_t fe_dom, ACTIVE_RING_IDX idx)
   10.82 -{
   10.83 -    return ( (fe_dom << 16) | idx );
   10.84 -}
   10.85 -
   10.86 -/*-----[ Ring helpers ]---------------------------------------------------*/
   10.87 -
   10.88 -inline int write_resp_to_fe_ring(blkif_t *blkif, blkif_response_t *rsp)
   10.89 -{
   10.90 -    blkif_response_t *resp_d;
   10.91 -    active_req_t *ar;
   10.92 -    
   10.93 -    ar = &active_reqs[ID_TO_IDX(rsp->id)];
   10.94 -    rsp->id = ar->id;
   10.95 -            
   10.96 -    resp_d = RING_GET_RESPONSE(&blkif->blk_ring,
   10.97 -            blkif->blk_ring.rsp_prod_pvt);
   10.98 -    memcpy(resp_d, rsp, sizeof(blkif_response_t));
   10.99 -    wmb();
  10.100 -    blkif->blk_ring.rsp_prod_pvt++;
  10.101 -            
  10.102 -    blkif_put(ar->blkif);
  10.103 -    free_active_req(ar);
  10.104 -    
  10.105 -    return 0;
  10.106 -}
  10.107 -
  10.108 -inline int write_req_to_be_ring(blkif_request_t *req)
  10.109 -{
  10.110 -    blkif_request_t *req_d;
  10.111 -
  10.112 -    if ( blktap_be_state != BLKIF_STATE_CONNECTED ) {
  10.113 -        WPRINTK("Tap trying to access an unconnected backend!\n");
  10.114 -        return 0;
  10.115 -    }
  10.116 -    
  10.117 -    req_d = RING_GET_REQUEST(&blktap_be_ring,
  10.118 -            blktap_be_ring.req_prod_pvt);
  10.119 -    memcpy(req_d, req, sizeof(blkif_request_t));
  10.120 -    wmb();
  10.121 -    blktap_be_ring.req_prod_pvt++;
  10.122 -            
  10.123 -    return 0;
  10.124 -}
  10.125 -
  10.126 -void kick_fe_domain(blkif_t *blkif) 
  10.127 -{
  10.128 -    RING_PUSH_RESPONSES(&blkif->blk_ring);
  10.129 -    notify_via_evtchn(blkif->evtchn);
  10.130 -    DPRINTK("notified FE(dom %u)\n", blkif->domid);
  10.131 -    
  10.132 -}
  10.133 -
  10.134 -void kick_be_domain(void)
  10.135 -{
  10.136 -    if ( blktap_be_state != BLKIF_STATE_CONNECTED ) 
  10.137 -        return;
  10.138 -    
  10.139 -    wmb(); /* Ensure that the frontend can see the requests. */
  10.140 -    RING_PUSH_REQUESTS(&blktap_be_ring);
  10.141 -    notify_via_evtchn(blktap_be_evtchn);
  10.142 -    DPRINTK("notified BE\n");
  10.143 -}
  10.144 -
  10.145 -/*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/
  10.146 -
  10.147 -/*-----[ Scheduler list maint -from blkback ]--- */
  10.148 -
  10.149 -static struct list_head blkio_schedule_list;
  10.150 -static spinlock_t blkio_schedule_list_lock;
  10.151 -
  10.152 -static int __on_blkdev_list(blkif_t *blkif)
  10.153 -{
  10.154 -    return blkif->blkdev_list.next != NULL;
  10.155 -}
  10.156 -
  10.157 -static void remove_from_blkdev_list(blkif_t *blkif)
  10.158 -{
  10.159 -    unsigned long flags;
  10.160 -    if ( !__on_blkdev_list(blkif) ) return;
  10.161 -    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
  10.162 -    if ( __on_blkdev_list(blkif) )
  10.163 -    {
  10.164 -        list_del(&blkif->blkdev_list);
  10.165 -        blkif->blkdev_list.next = NULL;
  10.166 -        blkif_put(blkif);
  10.167 -    }
  10.168 -    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
  10.169 -}
  10.170 -
  10.171 -static void add_to_blkdev_list_tail(blkif_t *blkif)
  10.172 -{
  10.173 -    unsigned long flags;
  10.174 -    if ( __on_blkdev_list(blkif) ) return;
  10.175 -    spin_lock_irqsave(&blkio_schedule_list_lock, flags);
  10.176 -    if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
  10.177 -    {
  10.178 -        list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
  10.179 -        blkif_get(blkif);
  10.180 -    }
  10.181 -    spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
  10.182 -}
  10.183 -
  10.184 -
  10.185 -/*-----[ Scheduler functions - from blkback ]--- */
  10.186 -
  10.187 -static DECLARE_WAIT_QUEUE_HEAD(blkio_schedule_wait);
  10.188 -
  10.189 -static int do_block_io_op(blkif_t *blkif, int max_to_do);
  10.190 -
  10.191 -static int blkio_schedule(void *arg)
  10.192 -{
  10.193 -    DECLARE_WAITQUEUE(wq, current);
  10.194 -
  10.195 -    blkif_t          *blkif;
  10.196 -    struct list_head *ent;
  10.197 -
  10.198 -    daemonize(
  10.199 -        "xentapd"
  10.200 -        );
  10.201 -
  10.202 -    for ( ; ; )
  10.203 -    {
  10.204 -        /* Wait for work to do. */
  10.205 -        add_wait_queue(&blkio_schedule_wait, &wq);
  10.206 -        set_current_state(TASK_INTERRUPTIBLE);
  10.207 -        if ( (NR_ACTIVE_REQS == MAX_ACTIVE_REQS) || 
  10.208 -             list_empty(&blkio_schedule_list) )
  10.209 -            schedule();
  10.210 -        __set_current_state(TASK_RUNNING);
  10.211 -        remove_wait_queue(&blkio_schedule_wait, &wq);
  10.212 -
  10.213 -        /* Queue up a batch of requests. */
  10.214 -        while ( (NR_ACTIVE_REQS < MAX_ACTIVE_REQS) &&
  10.215 -                !list_empty(&blkio_schedule_list) )
  10.216 -        {
  10.217 -            ent = blkio_schedule_list.next;
  10.218 -            blkif = list_entry(ent, blkif_t, blkdev_list);
  10.219 -            blkif_get(blkif);
  10.220 -            remove_from_blkdev_list(blkif);
  10.221 -            if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
  10.222 -                add_to_blkdev_list_tail(blkif);
  10.223 -            blkif_put(blkif);
  10.224 -        }
  10.225 -
  10.226 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
  10.227 -        /* Push the batch through to disc. */
  10.228 -        run_task_queue(&tq_disk);
  10.229 -#endif
  10.230 -    }
  10.231 -}
  10.232 -
  10.233 -static void maybe_trigger_blkio_schedule(void)
  10.234 -{
  10.235 -    /*
  10.236 -     * Needed so that two processes, who together make the following predicate
  10.237 -     * true, don't both read stale values and evaluate the predicate
  10.238 -     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
  10.239 -     */
  10.240 -    smp_mb();
  10.241 -
  10.242 -    if ( (NR_ACTIVE_REQS < (MAX_ACTIVE_REQS)) && /* XXX!!! was M_A_R/2*/
  10.243 -         !list_empty(&blkio_schedule_list) ) 
  10.244 -        wake_up(&blkio_schedule_wait);
  10.245 -}
  10.246 -
  10.247 -void blkif_deschedule(blkif_t *blkif)
  10.248 -{
  10.249 -    remove_from_blkdev_list(blkif);
  10.250 -}
  10.251 -
  10.252 -void __init blkdev_schedule_init(void)
  10.253 -{
  10.254 -    spin_lock_init(&blkio_schedule_list_lock);
  10.255 -    INIT_LIST_HEAD(&blkio_schedule_list);
  10.256 -
  10.257 -    if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
  10.258 -        BUG();
  10.259 -}
  10.260 -    
  10.261 -/*-----[ Interrupt entry from a frontend ]------ */
  10.262 -
  10.263 -irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)
  10.264 -{
  10.265 -    blkif_t *blkif = dev_id;
  10.266 -
  10.267 -    add_to_blkdev_list_tail(blkif);
  10.268 -    maybe_trigger_blkio_schedule();
  10.269 -    return IRQ_HANDLED;
  10.270 -}
  10.271 -
  10.272 -/*-----[ Other Frontend Ring functions ]-------- */
  10.273 -
  10.274 -/* irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)*/
  10.275 -static int do_block_io_op(blkif_t *blkif, int max_to_do)
  10.276 -{
  10.277 -    /* we have pending messages from the real frontend. */
  10.278 -
  10.279 -    blkif_request_t *req_s;
  10.280 -    RING_IDX i, rp;
  10.281 -    unsigned long flags;
  10.282 -    active_req_t *ar;
  10.283 -    int more_to_do = 0;
  10.284 -    int notify_be = 0, notify_user = 0;
  10.285 -    
  10.286 -    DPRINTK("PT got FE interrupt.\n");
  10.287 -
  10.288 -    if (NR_ACTIVE_REQS == MAX_ACTIVE_REQS) return 1;
  10.289 -    
  10.290 -    /* lock both rings */
  10.291 -    spin_lock_irqsave(&blkif_io_lock, flags);
  10.292 -
  10.293 -    rp = blkif->blk_ring.sring->req_prod;
  10.294 -    rmb();
  10.295 -    
  10.296 -    for ( i = blkif->blk_ring.req_cons; 
  10.297 -         (i != rp) && 
  10.298 -            !RING_REQUEST_CONS_OVERFLOW(&blkif->blk_ring, i);
  10.299 -          i++ )
  10.300 -    {
  10.301 -        
  10.302 -        if ((--max_to_do == 0) || (NR_ACTIVE_REQS == MAX_ACTIVE_REQS)) 
  10.303 -        {
  10.304 -            more_to_do = 1;
  10.305 -            break;
  10.306 -        }
  10.307 -        
  10.308 -        req_s = RING_GET_REQUEST(&blkif->blk_ring, i);
  10.309 -        /* This is a new request:  
  10.310 -         * Assign an active request record, and remap the id. 
  10.311 -         */
  10.312 -        ar = get_active_req();
  10.313 -        ar->id = req_s->id;
  10.314 -        ar->nr_pages = req_s->nr_segments; 
  10.315 -        blkif_get(blkif);
  10.316 -        ar->blkif = blkif;
  10.317 -        req_s->id = MAKE_ID(blkif->domid, ACTIVE_IDX(ar));
  10.318 -        /* WPRINTK("%3u < %3lu\n", ID_TO_IDX(req_s->id), ar->id); */
  10.319 -
  10.320 -        /* FE -> BE interposition point is here. */
  10.321 -        
  10.322 -        /* ------------------------------------------------------------- */
  10.323 -        /* BLKIF_OP_PROBE_HACK:                                          */
  10.324 -        /* Signal to the backend that we are a tap domain.               */
  10.325 -
  10.326 -        if (req_s->operation == BLKIF_OP_PROBE) {
  10.327 -            DPRINTK("Adding BLKTAP_COOKIE to PROBE request.\n");
  10.328 -            req_s->frame_and_sects[1] = BLKTAP_COOKIE;
  10.329 -        }
  10.330 -
  10.331 -        /* ------------------------------------------------------------- */
  10.332 -
  10.333 -        /* If we are in MODE_INTERCEPT_FE or MODE_COPY_FE: */
  10.334 -        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  10.335 -             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
  10.336 -            
  10.337 -            /* Copy the response message to UFERing */
  10.338 -            /* In MODE_INTERCEPT_FE, map attached pages into the app vma */
  10.339 -            /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */
  10.340 -
  10.341 -            DPRINTK("req->UFERing\n"); 
  10.342 -            blktap_write_fe_ring(req_s);
  10.343 -            notify_user = 1;
  10.344 -        }
  10.345 -
  10.346 -        /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */
  10.347 -        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  10.348 -               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
  10.349 -            
  10.350 -            /* be included to prevent noise from the fe when its off */
  10.351 -            /* copy the request message to the BERing */
  10.352 -
  10.353 -            DPRINTK("blktap: FERing[%u] -> BERing[%u]\n", 
  10.354 -                    (unsigned)i & (RING_SIZE(&blktap_be_ring)-1),
  10.355 -                    (unsigned)blktap_be_ring.req_prod_pvt & 
  10.356 -                    (RING_SIZE((&blktap_be_ring)-1)));
  10.357 -            
  10.358 -            write_req_to_be_ring(req_s);
  10.359 -            notify_be = 1;
  10.360 -        }
  10.361 -    }
  10.362 -
  10.363 -    blkif->blk_ring.req_cons = i;
  10.364 -    
  10.365 -    /* unlock rings */
  10.366 -    spin_unlock_irqrestore(&blkif_io_lock, flags);
  10.367 -    
  10.368 -    if (notify_user)
  10.369 -        blktap_kick_user();
  10.370 -    if (notify_be)
  10.371 -        kick_be_domain();
  10.372 -    
  10.373 -    return more_to_do;
  10.374 -}
  10.375 -
  10.376 -/*-----[ Data to/from Backend (server) VM ]------------------------------*/
  10.377 -
  10.378 -
  10.379 -irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
  10.380 -                                  struct pt_regs *ptregs)
  10.381 -{
  10.382 -    blkif_response_t  *resp_s;
  10.383 -    blkif_t *blkif;
  10.384 -    RING_IDX rp, i;
  10.385 -    unsigned long flags;
  10.386 -
  10.387 -    DPRINTK("PT got BE interrupt.\n");
  10.388 -
  10.389 -    /* lock both rings */
  10.390 -    spin_lock_irqsave(&blkif_io_lock, flags);
  10.391 -    
  10.392 -    rp = blktap_be_ring.sring->rsp_prod;
  10.393 -    rmb();
  10.394 -      
  10.395 -    for ( i = blktap_be_ring.rsp_cons; i != rp; i++)
  10.396 -    {
  10.397 -        resp_s = RING_GET_RESPONSE(&blktap_be_ring, i);
  10.398 -        
  10.399 -        /* BE -> FE interposition point is here. */
  10.400 -    
  10.401 -        blkif = active_reqs[ID_TO_IDX(resp_s->id)].blkif;
  10.402 -        
  10.403 -        /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */
  10.404 -        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  10.405 -             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
  10.406 -
  10.407 -            /* Copy the response message to UBERing */
  10.408 -            /* In MODE_INTERCEPT_BE, map attached pages into the app vma */
  10.409 -            /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */
  10.410 -
  10.411 -            DPRINTK("rsp->UBERing\n"); 
  10.412 -            blktap_write_be_ring(resp_s);
  10.413 -            blktap_kick_user();
  10.414 -
  10.415 -        }
  10.416 -       
  10.417 -        /* If we are NOT in MODE_INTERCEPT_BE or MODE_INTERCEPT_FE: */
  10.418 -        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  10.419 -               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
  10.420 -            
  10.421 -            /* (fe included to prevent random interference from the BE) */
  10.422 -            /* Copy the response message to FERing */
  10.423 -         
  10.424 -            DPRINTK("blktap: BERing[%u] -> FERing[%u]\n", 
  10.425 -                    (unsigned)i & (RING_SIZE(&blkif->blk_ring)-1),
  10.426 -                    (unsigned)blkif->blk_ring.rsp_prod_pvt & 
  10.427 -                    (RING_SIZE((&blkif->blk_ring)-1)));
  10.428 -
  10.429 -            write_resp_to_fe_ring(blkif, resp_s);
  10.430 -            kick_fe_domain(blkif);
  10.431 -
  10.432 -        }
  10.433 -    }
  10.434 -    
  10.435 -    blktap_be_ring.rsp_cons = i;
  10.436 -    
  10.437 -
  10.438 -    spin_unlock_irqrestore(&blkif_io_lock, flags);
  10.439 -    
  10.440 -    return IRQ_HANDLED;
  10.441 -}
  10.442 -
  10.443 -/* Debug : print the current ring indices. */
  10.444 -
  10.445 -void print_vm_ring_idxs(void)
  10.446 -{
  10.447 -    int i;
  10.448 -    blkif_t *blkif;
  10.449 -            
  10.450 -    WPRINTK("FE Rings: \n---------\n");
  10.451 -    for ( i = 0; i < 50; i++) { 
  10.452 -        blkif = blkif_find_by_handle((domid_t)i, 0);
  10.453 -        if (blkif != NULL) {
  10.454 -            if (blkif->blk_ring.sring != NULL) {
  10.455 -                WPRINTK("%2d: req_cons: %2d, rsp_prod_prv: %2d "
  10.456 -                    "| req_prod: %2d, rsp_prod: %2d\n", i, 
  10.457 -                    blkif->blk_ring.req_cons,
  10.458 -                    blkif->blk_ring.rsp_prod_pvt,
  10.459 -                    blkif->blk_ring.sring->req_prod,
  10.460 -                    blkif->blk_ring.sring->rsp_prod);
  10.461 -            } else {
  10.462 -                WPRINTK("%2d: [no device channel yet]\n", i);
  10.463 -            }
  10.464 -        }
  10.465 -    }
  10.466 -    if (blktap_be_ring.sring != NULL) {
  10.467 -        WPRINTK("BE Ring: \n--------\n");
  10.468 -        WPRINTK("BE: rsp_cons: %2d, req_prod_prv: %2d "
  10.469 -            "| req_prod: %2d, rsp_prod: %2d\n",
  10.470 -            blktap_be_ring.rsp_cons,
  10.471 -            blktap_be_ring.req_prod_pvt,
  10.472 -            blktap_be_ring.sring->req_prod,
  10.473 -            blktap_be_ring.sring->rsp_prod);
  10.474 -    }
  10.475 -}        
    11.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Sat Mar 12 20:44:12 2005 +0000
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,489 +0,0 @@
    11.4 -/******************************************************************************
    11.5 - * blktap_userdev.c
    11.6 - * 
    11.7 - * XenLinux virtual block-device tap.
    11.8 - * Control interface between the driver and a character device.
    11.9 - * 
   11.10 - * Copyright (c) 2004, Andrew Warfield
   11.11 - *
   11.12 - */
   11.13 -
   11.14 -#include <linux/config.h>
   11.15 -#include <linux/module.h>
   11.16 -#include <linux/kernel.h>
   11.17 -#include <linux/fs.h>
   11.18 -#include <linux/mm.h>
   11.19 -#include <linux/miscdevice.h>
   11.20 -#include <linux/errno.h>
   11.21 -#include <linux/major.h>
   11.22 -#include <linux/gfp.h>
   11.23 -#include <linux/poll.h>
   11.24 -#include <asm/pgalloc.h>
   11.25 -#include <asm-xen/xen-public/io/blkif.h> /* for control ring. */
   11.26 -
   11.27 -#include "blktap.h"
   11.28 -
   11.29 -
   11.30 -unsigned long blktap_mode = BLKTAP_MODE_PASSTHROUGH;
   11.31 -
   11.32 -/* Only one process may open /dev/xen/blktap at any time. */
   11.33 -static unsigned long blktap_dev_inuse;
   11.34 -unsigned long blktap_ring_ok; /* make this ring->state */
   11.35 -
   11.36 -/* for poll: */
   11.37 -static wait_queue_head_t blktap_wait;
   11.38 -
   11.39 -/* Where things are inside the device mapping. */
   11.40 -struct vm_area_struct *blktap_vma;
   11.41 -unsigned long mmap_vstart;
   11.42 -unsigned long rings_vstart;
   11.43 -
   11.44 -/* Rings up to user space. */
   11.45 -static blkif_front_ring_t blktap_ufe_ring;
   11.46 -static blkif_back_ring_t  blktap_ube_ring;
   11.47 -static ctrl_front_ring_t  blktap_uctrl_ring;
   11.48 -
   11.49 -/* local prototypes */
   11.50 -static int blktap_read_fe_ring(void);
   11.51 -static int blktap_read_be_ring(void);
   11.52 -
   11.53 -/* -------[ blktap vm ops ]------------------------------------------- */
   11.54 -
   11.55 -static struct page *blktap_nopage(struct vm_area_struct *vma,
   11.56 -                                             unsigned long address,
   11.57 -                                             int *type)
   11.58 -{
   11.59 -    /*
   11.60 -     * if the page has not been mapped in by the driver then generate
   11.61 -     * a SIGBUS to the domain.
   11.62 -     */
   11.63 -
   11.64 -    force_sig(SIGBUS, current);
   11.65 -
   11.66 -    return 0;
   11.67 -}
   11.68 -
   11.69 -struct vm_operations_struct blktap_vm_ops = {
   11.70 -    nopage:   blktap_nopage,
   11.71 -};
   11.72 -
   11.73 -/* -------[ blktap file ops ]----------------------------------------- */
   11.74 -
   11.75 -static int blktap_open(struct inode *inode, struct file *filp)
   11.76 -{
   11.77 -    blkif_sring_t *sring;
   11.78 -    ctrl_sring_t *csring;
   11.79 -    
   11.80 -    if ( test_and_set_bit(0, &blktap_dev_inuse) )
   11.81 -        return -EBUSY;
   11.82 -
   11.83 -    printk(KERN_ALERT "blktap open.\n");
   11.84 -    
   11.85 -    /* Allocate the ctrl ring. */
   11.86 -    csring = (ctrl_sring_t *)get_zeroed_page(GFP_KERNEL);
   11.87 -    if (csring == NULL)
   11.88 -        goto fail_nomem;
   11.89 -
   11.90 -    SetPageReserved(virt_to_page(csring));
   11.91 -    
   11.92 -    SHARED_RING_INIT(csring);
   11.93 -    FRONT_RING_INIT(&blktap_uctrl_ring, csring);
   11.94 -
   11.95 -
   11.96 -    /* Allocate the fe ring. */
   11.97 -    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
   11.98 -    if (sring == NULL)
   11.99 -        goto fail_free_ctrl;
  11.100 -
  11.101 -    SetPageReserved(virt_to_page(sring));
  11.102 -    
  11.103 -    SHARED_RING_INIT(sring);
  11.104 -    FRONT_RING_INIT(&blktap_ufe_ring, sring);
  11.105 -
  11.106 -    /* Allocate the be ring. */
  11.107 -    sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
  11.108 -    if (sring == NULL)
  11.109 -        goto fail_free_fe;
  11.110 -
  11.111 -    SetPageReserved(virt_to_page(sring));
  11.112 -    
  11.113 -    SHARED_RING_INIT(sring);
  11.114 -    BACK_RING_INIT(&blktap_ube_ring, sring);
  11.115 -
  11.116 -    DPRINTK(KERN_ALERT "blktap open.\n");
  11.117 -
  11.118 -    return 0;
  11.119 -    
  11.120 - fail_free_ctrl:
  11.121 -    free_page( (unsigned long) blktap_uctrl_ring.sring);
  11.122 -
  11.123 - fail_free_fe:
  11.124 -    free_page( (unsigned long) blktap_ufe_ring.sring);
  11.125 -
  11.126 - fail_nomem:
  11.127 -    return -ENOMEM;
  11.128 -}
  11.129 -
  11.130 -static int blktap_release(struct inode *inode, struct file *filp)
  11.131 -{
  11.132 -    blktap_dev_inuse = 0;
  11.133 -    blktap_ring_ok = 0;
  11.134 -
  11.135 -    printk(KERN_ALERT "blktap closed.\n");
  11.136 -
  11.137 -    /* Free the ring page. */
  11.138 -    ClearPageReserved(virt_to_page(blktap_uctrl_ring.sring));
  11.139 -    free_page((unsigned long) blktap_uctrl_ring.sring);
  11.140 -
  11.141 -    ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
  11.142 -    free_page((unsigned long) blktap_ufe_ring.sring);
  11.143 -
  11.144 -    ClearPageReserved(virt_to_page(blktap_ube_ring.sring));
  11.145 -    free_page((unsigned long) blktap_ube_ring.sring);
  11.146 -    
  11.147 -    return 0;
  11.148 -}
  11.149 -
  11.150 -/* Note on mmap:
  11.151 - * remap_pfn_range sets VM_IO on vma->vm_flags.  In trying to make libaio
  11.152 - * work to do direct page access from userspace, this ended up being a
  11.153 - * problem.  The bigger issue seems to be that there is no way to map
  11.154 - * a foreign page in to user space and have the virtual address of that 
  11.155 - * page map sanely down to a mfn.
  11.156 - * Removing the VM_IO flag results in a loop in get_user_pages, as 
  11.157 - * pfn_valid() always fails on a foreign page.
  11.158 - */
  11.159 -static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
  11.160 -{
  11.161 -    int size;
  11.162 -
  11.163 -    printk(KERN_ALERT "blktap mmap (%lx, %lx)\n",
  11.164 -           vma->vm_start, vma->vm_end);
  11.165 -
  11.166 -    vma->vm_ops = &blktap_vm_ops;
  11.167 -
  11.168 -    size = vma->vm_end - vma->vm_start;
  11.169 -    if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
  11.170 -        printk(KERN_INFO 
  11.171 -               "blktap: you _must_ map exactly %d pages!\n",
  11.172 -               MMAP_PAGES + RING_PAGES);
  11.173 -        return -EAGAIN;
  11.174 -    }
  11.175 -
  11.176 -    size >>= PAGE_SHIFT;
  11.177 -    printk(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
  11.178 -    
  11.179 -    rings_vstart = vma->vm_start;
  11.180 -    mmap_vstart  = rings_vstart + (RING_PAGES << PAGE_SHIFT);
  11.181 -    
  11.182 -    /* Map the ring pages to the start of the region and reserve it. */
  11.183 -
  11.184 -    /* not sure if I really need to do this... */
  11.185 -    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  11.186 -
  11.187 -    DPRINTK("Mapping ctrl_ring page %lx.\n", __pa(blktap_uctrl_ring.sring));
  11.188 -    if (remap_pfn_range(vma, vma->vm_start, 
  11.189 -                         __pa(blktap_uctrl_ring.sring) >> PAGE_SHIFT, 
  11.190 -                         PAGE_SIZE, vma->vm_page_prot)) {
  11.191 -        WPRINTK("ctrl_ring: remap_pfn_range failure!\n");
  11.192 -    }
  11.193 -
  11.194 -
  11.195 -    DPRINTK("Mapping be_ring page %lx.\n", __pa(blktap_ube_ring.sring));
  11.196 -    if (remap_pfn_range(vma, vma->vm_start + PAGE_SIZE, 
  11.197 -                         __pa(blktap_ube_ring.sring) >> PAGE_SHIFT, 
  11.198 -                         PAGE_SIZE, vma->vm_page_prot)) {
  11.199 -        WPRINTK("be_ring: remap_pfn_range failure!\n");
  11.200 -    }
  11.201 -
  11.202 -    DPRINTK("Mapping fe_ring page %lx.\n", __pa(blktap_ufe_ring.sring));
  11.203 -    if (remap_pfn_range(vma, vma->vm_start + ( 2 * PAGE_SIZE ), 
  11.204 -                         __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT, 
  11.205 -                         PAGE_SIZE, vma->vm_page_prot)) {
  11.206 -        WPRINTK("fe_ring: remap_pfn_range failure!\n");
  11.207 -    }
  11.208 -            
  11.209 -    blktap_vma = vma;
  11.210 -    blktap_ring_ok = 1;
  11.211 -
  11.212 -    return 0;
  11.213 -}
  11.214 -
  11.215 -static int blktap_ioctl(struct inode *inode, struct file *filp,
  11.216 -                        unsigned int cmd, unsigned long arg)
  11.217 -{
  11.218 -    switch(cmd) {
  11.219 -    case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
  11.220 -        return blktap_read_fe_ring();
  11.221 -
  11.222 -    case BLKTAP_IOCTL_KICK_BE: /* There are be messages to process. */
  11.223 -        return blktap_read_be_ring();
  11.224 -
  11.225 -    case BLKTAP_IOCTL_SETMODE:
  11.226 -        if (BLKTAP_MODE_VALID(arg)) {
  11.227 -            blktap_mode = arg;
  11.228 -            /* XXX: may need to flush rings here. */
  11.229 -            printk(KERN_INFO "blktap: set mode to %lx\n", arg);
  11.230 -            return 0;
  11.231 -        }
  11.232 -    case BLKTAP_IOCTL_PRINT_IDXS:
  11.233 -        {
  11.234 -            print_vm_ring_idxs();
  11.235 -            WPRINTK("User Rings: \n-----------\n");
  11.236 -            WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
  11.237 -                            "| req_prod: %2d, rsp_prod: %2d\n",
  11.238 -                            blktap_ufe_ring.rsp_cons,
  11.239 -                            blktap_ufe_ring.req_prod_pvt,
  11.240 -                            blktap_ufe_ring.sring->req_prod,
  11.241 -                            blktap_ufe_ring.sring->rsp_prod);
  11.242 -            WPRINTK("UB: req_cons: %2d, rsp_prod_prv: %2d "
  11.243 -                            "| req_prod: %2d, rsp_prod: %2d\n",
  11.244 -                            blktap_ube_ring.req_cons,
  11.245 -                            blktap_ube_ring.rsp_prod_pvt,
  11.246 -                            blktap_ube_ring.sring->req_prod,
  11.247 -                            blktap_ube_ring.sring->rsp_prod);
  11.248 -            
  11.249 -        }
  11.250 -    }
  11.251 -    return -ENOIOCTLCMD;
  11.252 -}
  11.253 -
  11.254 -static unsigned int blktap_poll(struct file *file, poll_table *wait)
  11.255 -{
  11.256 -        poll_wait(file, &blktap_wait, wait);
  11.257 -
  11.258 -        if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_uctrl_ring) ||
  11.259 -             RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring)   ||
  11.260 -             RING_HAS_UNPUSHED_RESPONSES(&blktap_ube_ring) ) {
  11.261 -
  11.262 -            RING_PUSH_REQUESTS(&blktap_uctrl_ring);
  11.263 -            RING_PUSH_REQUESTS(&blktap_ufe_ring);
  11.264 -            RING_PUSH_RESPONSES(&blktap_ube_ring);
  11.265 -            return POLLIN | POLLRDNORM;
  11.266 -        }
  11.267 -
  11.268 -        return 0;
  11.269 -}
  11.270 -
  11.271 -void blktap_kick_user(void)
  11.272 -{
  11.273 -    /* blktap_ring->req_prod = blktap_req_prod; */
  11.274 -    wake_up_interruptible(&blktap_wait);
  11.275 -}
  11.276 -
  11.277 -static struct file_operations blktap_fops = {
  11.278 -    owner:    THIS_MODULE,
  11.279 -    poll:     blktap_poll,
  11.280 -    ioctl:    blktap_ioctl,
  11.281 -    open:     blktap_open,
  11.282 -    release:  blktap_release,
  11.283 -    mmap:     blktap_mmap,
  11.284 -};
  11.285 -    
  11.286 -/*-----[ Data to/from user space ]----------------------------------------*/
  11.287 -
  11.288 -
  11.289 -int blktap_write_fe_ring(blkif_request_t *req)
  11.290 -{
  11.291 -    blkif_request_t *target;
  11.292 -    int error, i;
  11.293 -
  11.294 -    /*
  11.295 -     * This is called to pass a request from the real frontend domain's
  11.296 -     * blkif ring to the character device.
  11.297 -     */
  11.298 -
  11.299 -    if ( ! blktap_ring_ok ) {
  11.300 -        DPRINTK("blktap: ufe_ring not ready for a request!\n");
  11.301 -        return 0;
  11.302 -    }
  11.303 -
  11.304 -    if ( RING_FULL(&blktap_ufe_ring) ) {
  11.305 -        DPRINTK("blktap: fe_ring is full, can't add.\n");
  11.306 -        return 0;
  11.307 -    }
  11.308 -
  11.309 -    target = RING_GET_REQUEST(&blktap_ufe_ring,
  11.310 -            blktap_ufe_ring.req_prod_pvt);
  11.311 -    memcpy(target, req, sizeof(*req));
  11.312 -
  11.313 -    /* Attempt to map the foreign pages directly in to the application */
  11.314 -    for (i=0; i<target->nr_segments; i++) {
  11.315 -
  11.316 -        error = direct_remap_area_pages(blktap_vma->vm_mm, 
  11.317 -                                        MMAP_VADDR(ID_TO_IDX(req->id), i), 
  11.318 -                                        target->frame_and_sects[i] & PAGE_MASK,
  11.319 -                                        PAGE_SIZE,
  11.320 -                                        blktap_vma->vm_page_prot,
  11.321 -                                        ID_TO_DOM(req->id));
  11.322 -        if ( error != 0 ) {
  11.323 -            printk(KERN_INFO "remapping attached page failed! (%d)\n", error);
  11.324 -            /* the request is now dropped on the floor. */
  11.325 -            return 0;
  11.326 -        }
  11.327 -    }
  11.328 -    
  11.329 -    blktap_ufe_ring.req_prod_pvt++;
  11.330 -    
  11.331 -    return 0;
  11.332 -}
  11.333 -
  11.334 -int blktap_write_be_ring(blkif_response_t *rsp)
  11.335 -{
  11.336 -    blkif_response_t *target;
  11.337 -
  11.338 -    /*
  11.339 -     * This is called to pass a request from the real backend domain's
  11.340 -     * blkif ring to the character device.
  11.341 -     */
  11.342 -
  11.343 -    if ( ! blktap_ring_ok ) {
  11.344 -        DPRINTK("blktap: be_ring not ready for a request!\n");
  11.345 -        return 0;
  11.346 -    }
  11.347 -
  11.348 -    /* No test for fullness in the response direction. */
  11.349 -
  11.350 -    target = RING_GET_RESPONSE(&blktap_ube_ring,
  11.351 -            blktap_ube_ring.rsp_prod_pvt);
  11.352 -    memcpy(target, rsp, sizeof(*rsp));
  11.353 -
  11.354 -    /* no mapping -- pages were mapped in blktap_write_fe_ring() */
  11.355 -
  11.356 -    blktap_ube_ring.rsp_prod_pvt++;
  11.357 -    
  11.358 -    return 0;
  11.359 -}
  11.360 -
  11.361 -static void blktap_fast_flush_area(int idx, int nr_pages)
  11.362 -{
  11.363 -    multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
  11.364 -    int               i;
  11.365 -
  11.366 -    for ( i = 0; i < nr_pages; i++ )
  11.367 -    {
  11.368 -        mcl[i].op = __HYPERVISOR_update_va_mapping;
  11.369 -        mcl[i].args[0] = MMAP_VADDR(idx, i);
  11.370 -        mcl[i].args[1] = 0;
  11.371 -        mcl[i].args[2] = 0;
  11.372 -    }
  11.373 -
  11.374 -    mcl[nr_pages-1].args[2] = UVMF_FLUSH_TLB;
  11.375 -    if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
  11.376 -        BUG();
  11.377 -}
  11.378 -
  11.379 -static int blktap_read_fe_ring(void)
  11.380 -{
  11.381 -    /* This is called to read responses from the UFE ring. */
  11.382 -
  11.383 -    RING_IDX i, rp;
  11.384 -    blkif_response_t *resp_s;
  11.385 -    blkif_t *blkif;
  11.386 -    active_req_t *ar;
  11.387 -
  11.388 -    DPRINTK("blktap_read_fe_ring()\n");
  11.389 -
  11.390 -    /* if we are forwarding from UFERring to FERing */
  11.391 -    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
  11.392 -
  11.393 -        /* for each outstanding message on the UFEring  */
  11.394 -        rp = blktap_ufe_ring.sring->rsp_prod;
  11.395 -        rmb();
  11.396 -        
  11.397 -        for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
  11.398 -        {
  11.399 -            resp_s = RING_GET_RESPONSE(&blktap_ufe_ring, i);
  11.400 -            
  11.401 -            DPRINTK("resp->fe_ring\n");
  11.402 -            ar = lookup_active_req(ID_TO_IDX(resp_s->id));
  11.403 -            blkif = ar->blkif;
  11.404 -            blktap_fast_flush_area(ID_TO_IDX(resp_s->id), ar->nr_pages);
  11.405 -            write_resp_to_fe_ring(blkif, resp_s);
  11.406 -            kick_fe_domain(blkif);
  11.407 -        }
  11.408 -        
  11.409 -        blktap_ufe_ring.rsp_cons = i;
  11.410 -    }
  11.411 -    return 0;
  11.412 -}
  11.413 -
  11.414 -static int blktap_read_be_ring(void)
  11.415 -{
  11.416 -    /* This is called to read requests from the UBE ring. */
  11.417 -
  11.418 -    RING_IDX i, rp;
  11.419 -    blkif_request_t *req_s;
  11.420 -
  11.421 -    DPRINTK("blktap_read_be_ring()\n");
  11.422 -
  11.423 -    /* if we are forwarding from UFERring to FERing */
  11.424 -    if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
  11.425 -
  11.426 -        /* for each outstanding message on the UFEring  */
  11.427 -        rp = blktap_ube_ring.sring->req_prod;
  11.428 -        rmb();
  11.429 -        for ( i = blktap_ube_ring.req_cons; i != rp; i++ )
  11.430 -        {
  11.431 -            req_s = RING_GET_REQUEST(&blktap_ube_ring, i);
  11.432 -
  11.433 -            DPRINTK("req->be_ring\n");
  11.434 -            write_req_to_be_ring(req_s);
  11.435 -            kick_be_domain();
  11.436 -        }
  11.437 -        
  11.438 -        blktap_ube_ring.req_cons = i;
  11.439 -    }
  11.440 -
  11.441 -    return 0;
  11.442 -}
  11.443 -
  11.444 -int blktap_write_ctrl_ring(ctrl_msg_t *msg)
  11.445 -{
  11.446 -    ctrl_msg_t *target;
  11.447 -
  11.448 -    if ( ! blktap_ring_ok ) {
  11.449 -        DPRINTK("blktap: be_ring not ready for a request!\n");
  11.450 -        return 0;
  11.451 -    }
  11.452 -
  11.453 -    /* No test for fullness in the response direction. */
  11.454 -
  11.455 -    target = RING_GET_REQUEST(&blktap_uctrl_ring,
  11.456 -            blktap_uctrl_ring.req_prod_pvt);
  11.457 -    memcpy(target, msg, sizeof(*msg));
  11.458 -
  11.459 -    blktap_uctrl_ring.req_prod_pvt++;
  11.460 -    
  11.461 -    /* currently treat the ring as unidirectional. */
  11.462 -    blktap_uctrl_ring.rsp_cons = blktap_uctrl_ring.sring->rsp_prod;
  11.463 -    
  11.464 -    return 0;
  11.465 -       
  11.466 -}
  11.467 -
  11.468 -/* -------[ blktap module setup ]------------------------------------- */
  11.469 -
  11.470 -static struct miscdevice blktap_miscdev = {
  11.471 -    .minor        = BLKTAP_MINOR,
  11.472 -    .name         = "blktap",
  11.473 -    .fops         = &blktap_fops,
  11.474 -    .devfs_name   = "misc/blktap",
  11.475 -};
  11.476 -
  11.477 -int blktap_init(void)
  11.478 -{
  11.479 -    int err;
  11.480 -
  11.481 -    err = misc_register(&blktap_miscdev);
  11.482 -    if ( err != 0 )
  11.483 -    {
  11.484 -        printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
  11.485 -        return err;
  11.486 -    }
  11.487 -
  11.488 -    init_waitqueue_head(&blktap_wait);
  11.489 -
  11.490 -
  11.491 -    return 0;
  11.492 -}
    12.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbback/common.h	Sat Mar 12 20:44:12 2005 +0000
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,85 +0,0 @@
    12.4 -
    12.5 -#ifndef __USBIF__BACKEND__COMMON_H__
    12.6 -#define __USBIF__BACKEND__COMMON_H__
    12.7 -
    12.8 -#include <linux/config.h>
    12.9 -#include <linux/version.h>
   12.10 -#include <linux/module.h>
   12.11 -#include <linux/rbtree.h>
   12.12 -#include <linux/interrupt.h>
   12.13 -#include <linux/slab.h>
   12.14 -#include <linux/blkdev.h>
   12.15 -#include <asm/io.h>
   12.16 -#include <asm/setup.h>
   12.17 -#include <asm/pgalloc.h>
   12.18 -#include <asm-xen/ctrl_if.h>
   12.19 -#include <asm-xen/hypervisor.h>
   12.20 -
   12.21 -#include <asm-xen/xen-public/io/usbif.h>
   12.22 -
   12.23 -#if 0
   12.24 -#define ASSERT(_p) \
   12.25 -    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
   12.26 -    __LINE__, __FILE__); *(int*)0=0; }
   12.27 -#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
   12.28 -                           __FILE__ , __LINE__ , ## _a )
   12.29 -#else
   12.30 -#define ASSERT(_p) ((void)0)
   12.31 -#define DPRINTK(_f, _a...) ((void)0)
   12.32 -#endif
   12.33 -
   12.34 -typedef struct usbif_priv_st usbif_priv_t;
   12.35 -
   12.36 -struct usbif_priv_st {
   12.37 -    /* Unique identifier for this interface. */
   12.38 -    domid_t          domid;
   12.39 -    unsigned int     handle;
   12.40 -    /* Physical parameters of the comms window. */
   12.41 -    unsigned long    shmem_frame;
   12.42 -    unsigned int     evtchn;
   12.43 -    int              irq;
   12.44 -    /* Comms Information */
   12.45 -    usbif_back_ring_t usb_ring;
   12.46 -    /* Private fields. */
   12.47 -    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
   12.48 -    /*
   12.49 -     * DISCONNECT response is deferred until pending requests are ack'ed.
   12.50 -     * We therefore need to store the id from the original request.
   12.51 -     */
   12.52 -    u8                   disconnect_rspid;
   12.53 -    usbif_priv_t        *hash_next;
   12.54 -    struct list_head     usbif_list;
   12.55 -    spinlock_t           usb_ring_lock;
   12.56 -    atomic_t             refcnt;
   12.57 -
   12.58 -    struct work_struct work;
   12.59 -};
   12.60 -
   12.61 -void usbif_create(usbif_be_create_t *create);
   12.62 -void usbif_destroy(usbif_be_destroy_t *destroy);
   12.63 -void usbif_connect(usbif_be_connect_t *connect);
   12.64 -int  usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id);
   12.65 -void usbif_disconnect_complete(usbif_priv_t *up);
   12.66 -
   12.67 -void usbif_release_port(usbif_be_release_port_t *msg);
   12.68 -int usbif_claim_port(usbif_be_claim_port_t *msg);
   12.69 -void usbif_release_ports(usbif_priv_t *up);
   12.70 -
   12.71 -usbif_priv_t *usbif_find(domid_t domid);
   12.72 -#define usbif_get(_b) (atomic_inc(&(_b)->refcnt))
   12.73 -#define usbif_put(_b)                             \
   12.74 -    do {                                          \
   12.75 -        if ( atomic_dec_and_test(&(_b)->refcnt) ) \
   12.76 -            usbif_disconnect_complete(_b);        \
   12.77 -    } while (0)
   12.78 -
   12.79 -
   12.80 -void usbif_interface_init(void);
   12.81 -void usbif_ctrlif_init(void);
   12.82 -
   12.83 -void usbif_deschedule(usbif_priv_t *up);
   12.84 -void remove_from_usbif_list(usbif_priv_t *up);
   12.85 -
   12.86 -irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs);
   12.87 -
   12.88 -#endif /* __USBIF__BACKEND__COMMON_H__ */
    13.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbback/control.c	Sat Mar 12 20:44:12 2005 +0000
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,77 +0,0 @@
    13.4 -/******************************************************************************
    13.5 - * arch/xen/drivers/usbif/backend/control.c
    13.6 - * 
    13.7 - * Routines for interfacing with the control plane.
    13.8 - * 
    13.9 - * Copyright (c) 2004, Keir Fraser
   13.10 - */
   13.11 -
   13.12 -#include "common.h"
   13.13 -
   13.14 -static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
   13.15 -{
   13.16 -    DPRINTK("Received usbif backend message, subtype=%d\n", msg->subtype);
   13.17 -    
   13.18 -    switch ( msg->subtype )
   13.19 -    {
   13.20 -    case CMSG_USBIF_BE_CREATE:
   13.21 -        if ( msg->length != sizeof(usbif_be_create_t) )
   13.22 -            goto parse_error;
   13.23 -        usbif_create((usbif_be_create_t *)&msg->msg[0]);
   13.24 -        break;        
   13.25 -    case CMSG_USBIF_BE_DESTROY:
   13.26 -        if ( msg->length != sizeof(usbif_be_destroy_t) )
   13.27 -            goto parse_error;
   13.28 -        usbif_destroy((usbif_be_destroy_t *)&msg->msg[0]);
   13.29 -        break;        
   13.30 -    case CMSG_USBIF_BE_CONNECT:
   13.31 -        if ( msg->length != sizeof(usbif_be_connect_t) )
   13.32 -            goto parse_error;
   13.33 -        usbif_connect((usbif_be_connect_t *)&msg->msg[0]);
   13.34 -        break;        
   13.35 -    case CMSG_USBIF_BE_DISCONNECT:
   13.36 -        if ( msg->length != sizeof(usbif_be_disconnect_t) )
   13.37 -            goto parse_error;
   13.38 -        if ( !usbif_disconnect((usbif_be_disconnect_t *)&msg->msg[0],msg->id) )
   13.39 -            return; /* Sending the response is deferred until later. */
   13.40 -        break;        
   13.41 -    case CMSG_USBIF_BE_CLAIM_PORT:
   13.42 -        if ( msg->length != sizeof(usbif_be_claim_port_t) )
   13.43 -            goto parse_error;
   13.44 -	usbif_claim_port((usbif_be_claim_port_t *)&msg->msg[0]);
   13.45 -        break;
   13.46 -    case CMSG_USBIF_BE_RELEASE_PORT:
   13.47 -        if ( msg->length != sizeof(usbif_be_release_port_t) )
   13.48 -            goto parse_error;
   13.49 -        usbif_release_port((usbif_be_release_port_t *)&msg->msg[0]);
   13.50 -        break;
   13.51 -    default:
   13.52 -        goto parse_error;
   13.53 -    }
   13.54 -
   13.55 -    ctrl_if_send_response(msg);
   13.56 -    return;
   13.57 -
   13.58 - parse_error:
   13.59 -    DPRINTK("Parse error while reading message subtype %d, len %d\n",
   13.60 -            msg->subtype, msg->length);
   13.61 -    msg->length = 0;
   13.62 -    ctrl_if_send_response(msg);
   13.63 -}
   13.64 -
   13.65 -void usbif_ctrlif_init(void)
   13.66 -{
   13.67 -    ctrl_msg_t                       cmsg;
   13.68 -    usbif_be_driver_status_changed_t st;
   13.69 -
   13.70 -    (void)ctrl_if_register_receiver(CMSG_USBIF_BE, usbif_ctrlif_rx, 
   13.71 -                                    CALLBACK_IN_BLOCKING_CONTEXT);
   13.72 -
   13.73 -    /* Send a driver-UP notification to the domain controller. */
   13.74 -    cmsg.type      = CMSG_USBIF_BE;
   13.75 -    cmsg.subtype   = CMSG_USBIF_BE_DRIVER_STATUS_CHANGED;
   13.76 -    cmsg.length    = sizeof(usbif_be_driver_status_changed_t);
   13.77 -    st.status      = USBIF_DRIVER_STATUS_UP;
   13.78 -    memcpy(cmsg.msg, &st, sizeof(st));
   13.79 -    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   13.80 -}
    14.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbback/interface.c	Sat Mar 12 20:44:12 2005 +0000
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,252 +0,0 @@
    14.4 -/******************************************************************************
    14.5 - * arch/xen/drivers/usbif/backend/interface.c
    14.6 - * 
    14.7 - * USB device interface management.
    14.8 - * 
    14.9 - * by Mark Williamson, Copyright (c) 2004
   14.10 - */
   14.11 -
   14.12 -
   14.13 -/******************************************************************************
   14.14 - * arch/xen/drivers/blkif/backend/interface.c
   14.15 - * 
   14.16 - * Block-device interface management.
   14.17 - * 
   14.18 - * Copyright (c) 2004, Keir Fraser
   14.19 - */
   14.20 -
   14.21 -#include "common.h"
   14.22 -
   14.23 -#define USBIF_HASHSZ 1024
   14.24 -#define USBIF_HASH(_d) (((int)(_d))&(USBIF_HASHSZ-1))
   14.25 -
   14.26 -static kmem_cache_t      *usbif_priv_cachep;
   14.27 -static usbif_priv_t      *usbif_priv_hash[USBIF_HASHSZ];
   14.28 -
   14.29 -usbif_priv_t *usbif_find(domid_t domid)
   14.30 -{
   14.31 -    usbif_priv_t *up = usbif_priv_hash[USBIF_HASH(domid)];
   14.32 -    while ( (up != NULL ) && ( up->domid != domid ) )
   14.33 -        up = up->hash_next;
   14.34 -    return up;
   14.35 -}
   14.36 -
   14.37 -static void __usbif_disconnect_complete(void *arg)
   14.38 -{
   14.39 -    usbif_priv_t         *usbif = (usbif_priv_t *)arg;
   14.40 -    ctrl_msg_t            cmsg;
   14.41 -    usbif_be_disconnect_t disc;
   14.42 -
   14.43 -    /*
   14.44 -     * These can't be done in usbif_disconnect() because at that point there
   14.45 -     * may be outstanding requests at the device whose asynchronous responses
   14.46 -     * must still be notified to the remote driver.
   14.47 -     */
   14.48 -    unbind_evtchn_from_irq(usbif->evtchn);
   14.49 -    vfree(usbif->usb_ring.sring);
   14.50 -
   14.51 -    /* Construct the deferred response message. */
   14.52 -    cmsg.type         = CMSG_USBIF_BE;
   14.53 -    cmsg.subtype      = CMSG_USBIF_BE_DISCONNECT;
   14.54 -    cmsg.id           = usbif->disconnect_rspid;
   14.55 -    cmsg.length       = sizeof(usbif_be_disconnect_t);
   14.56 -    disc.domid        = usbif->domid;
   14.57 -    disc.status       = USBIF_BE_STATUS_OKAY;
   14.58 -    memcpy(cmsg.msg, &disc, sizeof(disc));
   14.59 -
   14.60 -    /*
   14.61 -     * Make sure message is constructed /before/ status change, because
   14.62 -     * after the status change the 'usbif' structure could be deallocated at
   14.63 -     * any time. Also make sure we send the response /after/ status change,
   14.64 -     * as otherwise a subsequent CONNECT request could spuriously fail if
   14.65 -     * another CPU doesn't see the status change yet.
   14.66 -     */
   14.67 -    mb();
   14.68 -    if ( usbif->status != DISCONNECTING )
   14.69 -        BUG();
   14.70 -    usbif->status = DISCONNECTED;
   14.71 -    mb();
   14.72 -
   14.73 -    /* Send the successful response. */
   14.74 -    ctrl_if_send_response(&cmsg);
   14.75 -}
   14.76 -
   14.77 -void usbif_disconnect_complete(usbif_priv_t *up)
   14.78 -{
   14.79 -    INIT_WORK(&up->work, __usbif_disconnect_complete, (void *)up);
   14.80 -    schedule_work(&up->work);
   14.81 -}
   14.82 -
   14.83 -void usbif_create(usbif_be_create_t *create)
   14.84 -{
   14.85 -    domid_t       domid  = create->domid;
   14.86 -    usbif_priv_t **pup, *up;
   14.87 -
   14.88 -    if ( (up = kmem_cache_alloc(usbif_priv_cachep, GFP_KERNEL)) == NULL )
   14.89 -    {
   14.90 -        DPRINTK("Could not create usbif: out of memory\n");
   14.91 -        create->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
   14.92 -        return;
   14.93 -    }
   14.94 -
   14.95 -    memset(up, 0, sizeof(*up));
   14.96 -    up->domid  = domid;
   14.97 -    up->status = DISCONNECTED;
   14.98 -    spin_lock_init(&up->usb_ring_lock);
   14.99 -    atomic_set(&up->refcnt, 0);
  14.100 -
  14.101 -    pup = &usbif_priv_hash[USBIF_HASH(domid)];
  14.102 -    while ( *pup != NULL )
  14.103 -    {
  14.104 -        if ( (*pup)->domid == domid )
  14.105 -        {
  14.106 -            create->status = USBIF_BE_STATUS_INTERFACE_EXISTS;
  14.107 -            kmem_cache_free(usbif_priv_cachep, up);
  14.108 -            return;
  14.109 -        }
  14.110 -        pup = &(*pup)->hash_next;
  14.111 -    }
  14.112 -
  14.113 -    up->hash_next = *pup;
  14.114 -    *pup = up;
  14.115 -
  14.116 -    create->status = USBIF_BE_STATUS_OKAY;
  14.117 -}
  14.118 -
  14.119 -void usbif_destroy(usbif_be_destroy_t *destroy)
  14.120 -{
  14.121 -    domid_t       domid  = destroy->domid;
  14.122 -    usbif_priv_t  **pup, *up;
  14.123 -
  14.124 -    pup = &usbif_priv_hash[USBIF_HASH(domid)];
  14.125 -    while ( (up = *pup) != NULL )
  14.126 -    {
  14.127 -        if ( up->domid == domid )
  14.128 -        {
  14.129 -            if ( up->status != DISCONNECTED )
  14.130 -                goto still_connected;
  14.131 -            goto destroy;
  14.132 -        }
  14.133 -        pup = &up->hash_next;
  14.134 -    }
  14.135 -
  14.136 -    destroy->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
  14.137 -    return;
  14.138 -
  14.139 - still_connected:
  14.140 -    destroy->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
  14.141 -    return;
  14.142 -
  14.143 - destroy:
  14.144 -    *pup = up->hash_next;
  14.145 -    usbif_release_ports(up);
  14.146 -    kmem_cache_free(usbif_priv_cachep, up);
  14.147 -    destroy->status = USBIF_BE_STATUS_OKAY;
  14.148 -}
  14.149 -
  14.150 -void usbif_connect(usbif_be_connect_t *connect)
  14.151 -{
  14.152 -    domid_t       domid  = connect->domid;
  14.153 -    unsigned int  evtchn = connect->evtchn;
  14.154 -    unsigned long shmem_frame = connect->shmem_frame;
  14.155 -    struct vm_struct *vma;
  14.156 -    pgprot_t      prot;
  14.157 -    int           error;
  14.158 -    usbif_priv_t *up;
  14.159 -    usbif_sring_t *sring;
  14.160 -
  14.161 -    up = usbif_find(domid);
  14.162 -    if ( unlikely(up == NULL) )
  14.163 -    {
  14.164 -        DPRINTK("usbif_connect attempted for non-existent usbif (%u)\n", 
  14.165 -                connect->domid); 
  14.166 -        connect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
  14.167 -        return;
  14.168 -    }
  14.169 -
  14.170 -    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
  14.171 -    {
  14.172 -        connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
  14.173 -        return;
  14.174 -    }
  14.175 -
  14.176 -    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
  14.177 -    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
  14.178 -                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
  14.179 -                                    prot, domid);
  14.180 -    if ( error != 0 )
  14.181 -    {
  14.182 -        if ( error == -ENOMEM )
  14.183 -            connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
  14.184 -        else if ( error == -EFAULT )
  14.185 -            connect->status = USBIF_BE_STATUS_MAPPING_ERROR;
  14.186 -        else
  14.187 -            connect->status = USBIF_BE_STATUS_ERROR;
  14.188 -        vfree(vma->addr);
  14.189 -        return;
  14.190 -    }
  14.191 -
  14.192 -    if ( up->status != DISCONNECTED )
  14.193 -    {
  14.194 -        connect->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
  14.195 -        vfree(vma->addr);
  14.196 -        return;
  14.197 -    }
  14.198 -
  14.199 -    sring = (usbif_sring_t *)vma->addr;
  14.200 -    SHARED_RING_INIT(sring);
  14.201 -    BACK_RING_INIT(&up->usb_ring, sring);
  14.202 -
  14.203 -    up->evtchn        = evtchn;
  14.204 -    up->irq           = bind_evtchn_to_irq(evtchn);
  14.205 -    up->shmem_frame   = shmem_frame;
  14.206 -    up->status        = CONNECTED;
  14.207 -    usbif_get(up);
  14.208 -
  14.209 -    request_irq(up->irq, usbif_be_int, 0, "usbif-backend", up);
  14.210 -
  14.211 -    connect->status = USBIF_BE_STATUS_OKAY;
  14.212 -}
  14.213 -
  14.214 -/* Remove URBs for this interface before destroying it. */
  14.215 -void usbif_deschedule(usbif_priv_t *up)
  14.216 -{
  14.217 -    remove_from_usbif_list(up);
  14.218 -}
  14.219 -
  14.220 -int usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id)
  14.221 -{
  14.222 -    domid_t       domid  = disconnect->domid;
  14.223 -    usbif_priv_t *up;
  14.224 -
  14.225 -    up = usbif_find(domid);
  14.226 -    if ( unlikely(up == NULL) )
  14.227 -    {
  14.228 -        DPRINTK("usbif_disconnect attempted for non-existent usbif"
  14.229 -                " (%u)\n", disconnect->domid); 
  14.230 -        disconnect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
  14.231 -        return 1; /* Caller will send response error message. */
  14.232 -    }
  14.233 -
  14.234 -    if ( up->status == CONNECTED )
  14.235 -    {
  14.236 -        up->status = DISCONNECTING;
  14.237 -        up->disconnect_rspid = rsp_id;
  14.238 -        wmb(); /* Let other CPUs see the status change. */
  14.239 -        free_irq(up->irq, up);
  14.240 -	usbif_deschedule(up);
  14.241 -        usbif_put(up);
  14.242 -        return 0; /* Caller should not send response message. */
  14.243 -    }
  14.244 -
  14.245 -    disconnect->status = USBIF_BE_STATUS_OKAY;
  14.246 -    return 1;
  14.247 -}
  14.248 -
  14.249 -void __init usbif_interface_init(void)
  14.250 -{
  14.251 -    usbif_priv_cachep = kmem_cache_create("usbif_priv_cache",
  14.252 -					  sizeof(usbif_priv_t), 
  14.253 -					  0, 0, NULL, NULL);
  14.254 -    memset(usbif_priv_hash, 0, sizeof(usbif_priv_hash));
  14.255 -}
    15.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbback/usbback.c	Sat Mar 12 20:44:12 2005 +0000
    15.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.3 @@ -1,1070 +0,0 @@
    15.4 -/******************************************************************************
    15.5 - * arch/xen/drivers/usbif/backend/main.c
    15.6 - * 
    15.7 - * Backend for the Xen virtual USB driver - provides an abstraction of a
    15.8 - * USB host controller to the corresponding frontend driver.
    15.9 - *
   15.10 - * by Mark Williamson
   15.11 - * Copyright (c) 2004 Intel Research Cambridge
   15.12 - * Copyright (c) 2004, 2005 Mark Williamson
   15.13 - *
   15.14 - * Based on arch/xen/drivers/blkif/backend/main.c
   15.15 - * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
   15.16 - */
   15.17 -
   15.18 -#include "common.h"
   15.19 -
   15.20 -
   15.21 -#include <linux/list.h>
   15.22 -#include <linux/usb.h>
   15.23 -#include <linux/spinlock.h>
   15.24 -#include <linux/module.h>
   15.25 -#include <linux/tqueue.h>
   15.26 -
   15.27 -/*
   15.28 - * This is rather arbitrary.
   15.29 - */
   15.30 -#define MAX_PENDING_REQS 4
   15.31 -#define BATCH_PER_DOMAIN 1
   15.32 -
   15.33 -static unsigned long mmap_vstart;
   15.34 -
   15.35 -/* Needs to be sufficiently large that we can map the (large) buffers
   15.36 - * the USB mass storage driver wants. */
   15.37 -#define MMAP_PAGES_PER_REQUEST \
   15.38 -    (128)
   15.39 -#define MMAP_PAGES             \
   15.40 -    (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
   15.41 -
   15.42 -#define MMAP_VADDR(_req,_seg)                        \
   15.43 -    (mmap_vstart +                                   \
   15.44 -     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
   15.45 -     ((_seg) * PAGE_SIZE))
   15.46 -
   15.47 -
   15.48 -static spinlock_t owned_ports_lock;
   15.49 -LIST_HEAD(owned_ports);
   15.50 -
   15.51 -/* A list of these structures is used to track ownership of physical USB
   15.52 - * ports. */
   15.53 -typedef struct 
   15.54 -{
   15.55 -    usbif_priv_t     *usbif_priv;
   15.56 -    char             path[16];
   15.57 -    int               guest_port;
   15.58 -    int enabled;
   15.59 -    struct list_head  list;
   15.60 -    unsigned long guest_address; /* The USB device address that has been
   15.61 -                                  * assigned by the guest. */
   15.62 -    int               dev_present; /* Is there a device present? */
   15.63 -    struct usb_device * dev;
   15.64 -    unsigned long ifaces;  /* What interfaces are present on this device? */
   15.65 -} owned_port_t;
   15.66 -
   15.67 -
   15.68 -/*
   15.69 - * Each outstanding request that we've passed to the lower device layers has a
   15.70 - * 'pending_req' allocated to it.  The request is complete, the specified
   15.71 - * domain has a response queued for it, with the saved 'id' passed back.
   15.72 - */
   15.73 -typedef struct {
   15.74 -    usbif_priv_t       *usbif_priv;
   15.75 -    unsigned long      id;
   15.76 -    int                nr_pages;
   15.77 -    unsigned short     operation;
   15.78 -    int                status;
   15.79 -} pending_req_t;
   15.80 -
   15.81 -/*
   15.82 - * We can't allocate pending_req's in order, since they may complete out of 
   15.83 - * order. We therefore maintain an allocation ring. This ring also indicates 
   15.84 - * when enough work has been passed down -- at that point the allocation ring 
   15.85 - * will be empty.
   15.86 - */
   15.87 -static pending_req_t pending_reqs[MAX_PENDING_REQS];
   15.88 -static unsigned char pending_ring[MAX_PENDING_REQS];
   15.89 -static spinlock_t pend_prod_lock;
   15.90 -
   15.91 -/* NB. We use a different index type to differentiate from shared usb rings. */
   15.92 -typedef unsigned int PEND_RING_IDX;
   15.93 -#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
   15.94 -static PEND_RING_IDX pending_prod, pending_cons;
   15.95 -#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
   15.96 -
   15.97 -static int do_usb_io_op(usbif_priv_t *usbif, int max_to_do);
   15.98 -static void make_response(usbif_priv_t *usbif, unsigned long id, 
   15.99 -                          unsigned short op, int st, int inband,
  15.100 -			  unsigned long actual_length);
  15.101 -static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned long port);
  15.102 -static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req);    
  15.103 -static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid);
  15.104 -static owned_port_t *usbif_find_port(char *);
  15.105 -
  15.106 -/******************************************************************
  15.107 - * PRIVATE DEBUG FUNCTIONS
  15.108 - */
  15.109 -
  15.110 -#undef DEBUG
  15.111 -#ifdef DEBUG
  15.112 -
  15.113 -static void dump_port(owned_port_t *p)
  15.114 -{
  15.115 -    printk(KERN_DEBUG "owned_port_t @ %p\n"
  15.116 -	   "  usbif_priv @ %p\n"
  15.117 -	   "  path: %s\n"
  15.118 -	   "  guest_port: %d\n"
  15.119 -	   "  guest_address: %ld\n"
  15.120 -	   "  dev_present: %d\n"
  15.121 -	   "  dev @ %p\n"
  15.122 -	   "  ifaces: 0x%lx\n",
  15.123 -	   p, p->usbif_priv, p->path, p->guest_port, p->guest_address,
  15.124 -	   p->dev_present, p->dev, p->ifaces);
  15.125 -}
  15.126 -
  15.127 -
  15.128 -static void dump_request(usbif_request_t *req)
  15.129 -{    
  15.130 -    printk(KERN_DEBUG "id = 0x%lx\n"
  15.131 -	   "devnum %d\n"
  15.132 -	   "endpoint 0x%x\n"
  15.133 -	   "direction %d\n"
  15.134 -	   "speed %d\n"
  15.135 -	   "pipe_type 0x%x\n"
  15.136 -	   "transfer_buffer 0x%lx\n"
  15.137 -	   "length 0x%lx\n"
  15.138 -	   "transfer_flags 0x%lx\n"
  15.139 -	   "setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n"
  15.140 -	   "iso_schedule = 0x%lx\n"
  15.141 -	   "num_iso %ld\n",
  15.142 -	   req->id, req->devnum, req->endpoint, req->direction, req->speed,
  15.143 -	   req->pipe_type, req->transfer_buffer, req->length,
  15.144 -	   req->transfer_flags, req->setup[0], req->setup[1], req->setup[2],
  15.145 -	   req->setup[3], req->setup[4], req->setup[5], req->setup[6],
  15.146 -	   req->setup[7], req->iso_schedule, req->num_iso);
  15.147 -}
  15.148 -
  15.149 -static void dump_urb(struct urb *urb)
  15.150 -{
  15.151 -    printk(KERN_DEBUG "dumping urb @ %p\n", urb);
  15.152 -
  15.153 -#define DUMP_URB_FIELD(name, format) \
  15.154 -    printk(KERN_DEBUG "  " # name " " format "\n", urb-> name)
  15.155 -    
  15.156 -    DUMP_URB_FIELD(pipe, "0x%x");
  15.157 -    DUMP_URB_FIELD(status, "%d");
  15.158 -    DUMP_URB_FIELD(transfer_flags, "0x%x");    
  15.159 -    DUMP_URB_FIELD(transfer_buffer, "%p");
  15.160 -    DUMP_URB_FIELD(transfer_buffer_length, "%d");
  15.161 -    DUMP_URB_FIELD(actual_length, "%d");
  15.162 -}
  15.163 -
  15.164 -static void dump_response(usbif_response_t *resp)
  15.165 -{
  15.166 -    printk(KERN_DEBUG "usbback: Sending response:\n"
  15.167 -	   "         id = 0x%x\n"
  15.168 -	   "         op = %d\n"
  15.169 -	   "         status = %d\n"
  15.170 -	   "         data = %d\n"
  15.171 -	   "         length = %d\n",
  15.172 -	   resp->id, resp->op, resp->status, resp->data, resp->length);
  15.173 -}
  15.174 -
  15.175 -#else /* DEBUG */
  15.176 -
  15.177 -#define dump_port(blah)     ((void)0)
  15.178 -#define dump_request(blah)   ((void)0)
  15.179 -#define dump_urb(blah)      ((void)0)
  15.180 -#define dump_response(blah) ((void)0)
  15.181 -
  15.182 -#endif /* DEBUG */
  15.183 -
  15.184 -/******************************************************************
  15.185 - * MEMORY MANAGEMENT
  15.186 - */
  15.187 -
  15.188 -static void fast_flush_area(int idx, int nr_pages)
  15.189 -{
  15.190 -    multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
  15.191 -    int               i;
  15.192 -
  15.193 -    for ( i = 0; i < nr_pages; i++ )
  15.194 -    {
  15.195 -        mcl[i].op = __HYPERVISOR_update_va_mapping;
  15.196 -        mcl[i].args[0] = MMAP_VADDR(idx, i);
  15.197 -        mcl[i].args[1] = 0;
  15.198 -        mcl[i].args[2] = 0;
  15.199 -    }
  15.200 -
  15.201 -    mcl[nr_pages-1].args[2] = UVMF_FLUSH_TLB;
  15.202 -    if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
  15.203 -        BUG();
  15.204 -}
  15.205 -
  15.206 -
  15.207 -/******************************************************************
  15.208 - * USB INTERFACE SCHEDULER LIST MAINTENANCE
  15.209 - */
  15.210 -
  15.211 -static struct list_head usbio_schedule_list;
  15.212 -static spinlock_t usbio_schedule_list_lock;
  15.213 -
  15.214 -static int __on_usbif_list(usbif_priv_t *up)
  15.215 -{
  15.216 -    return up->usbif_list.next != NULL;
  15.217 -}
  15.218 -
  15.219 -void remove_from_usbif_list(usbif_priv_t *up)
  15.220 -{
  15.221 -    unsigned long flags;
  15.222 -    if ( !__on_usbif_list(up) ) return;
  15.223 -    spin_lock_irqsave(&usbio_schedule_list_lock, flags);
  15.224 -    if ( __on_usbif_list(up) )
  15.225 -    {
  15.226 -        list_del(&up->usbif_list);
  15.227 -        up->usbif_list.next = NULL;
  15.228 -        usbif_put(up);
  15.229 -    }
  15.230 -    spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
  15.231 -}
  15.232 -
  15.233 -static void add_to_usbif_list_tail(usbif_priv_t *up)
  15.234 -{
  15.235 -    unsigned long flags;
  15.236 -    if ( __on_usbif_list(up) ) return;
  15.237 -    spin_lock_irqsave(&usbio_schedule_list_lock, flags);
  15.238 -    if ( !__on_usbif_list(up) && (up->status == CONNECTED) )
  15.239 -    {
  15.240 -        list_add_tail(&up->usbif_list, &usbio_schedule_list);
  15.241 -        usbif_get(up);
  15.242 -    }
  15.243 -    spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
  15.244 -}
  15.245 -
  15.246 -void free_pending(int pending_idx)
  15.247 -{
  15.248 -    unsigned long flags;
  15.249 -
  15.250 -    /* Free the pending request. */
  15.251 -    spin_lock_irqsave(&pend_prod_lock, flags);
  15.252 -    pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
  15.253 -    spin_unlock_irqrestore(&pend_prod_lock, flags);
  15.254 -}
  15.255 -
  15.256 -/******************************************************************
  15.257 - * COMPLETION CALLBACK -- Called as urb->complete()
  15.258 - */
  15.259 -
  15.260 -static void maybe_trigger_usbio_schedule(void);
  15.261 -
  15.262 -static void __end_usb_io_op(struct urb *purb)
  15.263 -{
  15.264 -    pending_req_t *pending_req;
  15.265 -    int pending_idx;
  15.266 -
  15.267 -    pending_req = purb->context;
  15.268 -
  15.269 -    pending_idx = pending_req - pending_reqs;
  15.270 -
  15.271 -    ASSERT(purb->actual_length <= purb->transfer_buffer_length);
  15.272 -    ASSERT(purb->actual_length <= pending_req->nr_pages * PAGE_SIZE);
  15.273 -    
  15.274 -    /* An error fails the entire request. */
  15.275 -    if ( purb->status )
  15.276 -    {
  15.277 -        printk(KERN_WARNING "URB @ %p failed. Status %d\n", purb, purb->status);
  15.278 -    }
  15.279 -
  15.280 -    if ( usb_pipetype(purb->pipe) == 0 )
  15.281 -    {
  15.282 -        int i;
  15.283 -        usbif_iso_t *sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, pending_req->nr_pages - 1);
  15.284 -
  15.285 -        /* If we're dealing with an iso pipe, we need to copy back the schedule. */
  15.286 -        for ( i = 0; i < purb->number_of_packets; i++ )
  15.287 -        {
  15.288 -            sched[i].length = purb->iso_frame_desc[i].actual_length;
  15.289 -            ASSERT(sched[i].buffer_offset ==
  15.290 -                   purb->iso_frame_desc[i].offset);
  15.291 -            sched[i].status = purb->iso_frame_desc[i].status;
  15.292 -        }
  15.293 -    }
  15.294 -    
  15.295 -    fast_flush_area(pending_req - pending_reqs, pending_req->nr_pages);
  15.296 -
  15.297 -    kfree(purb->setup_packet);
  15.298 -
  15.299 -    make_response(pending_req->usbif_priv, pending_req->id,
  15.300 -		  pending_req->operation, pending_req->status, 0, purb->actual_length);
  15.301 -    usbif_put(pending_req->usbif_priv);
  15.302 -
  15.303 -    usb_free_urb(purb);
  15.304 -
  15.305 -    free_pending(pending_idx);
  15.306 -    
  15.307 -    rmb();
  15.308 -
  15.309 -    /* Check for anything still waiting in the rings, having freed a request... */
  15.310 -    maybe_trigger_usbio_schedule();
  15.311 -}
  15.312 -
  15.313 -/******************************************************************
  15.314 - * SCHEDULER FUNCTIONS
  15.315 - */
  15.316 -
  15.317 -static DECLARE_WAIT_QUEUE_HEAD(usbio_schedule_wait);
  15.318 -
  15.319 -static int usbio_schedule(void *arg)
  15.320 -{
  15.321 -    DECLARE_WAITQUEUE(wq, current);
  15.322 -
  15.323 -    usbif_priv_t          *up;
  15.324 -    struct list_head *ent;
  15.325 -
  15.326 -    daemonize();
  15.327 -
  15.328 -    for ( ; ; )
  15.329 -    {
  15.330 -        /* Wait for work to do. */
  15.331 -        add_wait_queue(&usbio_schedule_wait, &wq);
  15.332 -        set_current_state(TASK_INTERRUPTIBLE);
  15.333 -        if ( (NR_PENDING_REQS == MAX_PENDING_REQS) || 
  15.334 -             list_empty(&usbio_schedule_list) )
  15.335 -            schedule();
  15.336 -        __set_current_state(TASK_RUNNING);
  15.337 -        remove_wait_queue(&usbio_schedule_wait, &wq);
  15.338 -
  15.339 -        /* Queue up a batch of requests. */
  15.340 -        while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
  15.341 -                !list_empty(&usbio_schedule_list) )
  15.342 -        {
  15.343 -            ent = usbio_schedule_list.next;
  15.344 -            up = list_entry(ent, usbif_priv_t, usbif_list);
  15.345 -            usbif_get(up);
  15.346 -            remove_from_usbif_list(up);
  15.347 -            if ( do_usb_io_op(up, BATCH_PER_DOMAIN) )
  15.348 -                add_to_usbif_list_tail(up);
  15.349 -            usbif_put(up);
  15.350 -        }
  15.351 -    }
  15.352 -}
  15.353 -
  15.354 -static void maybe_trigger_usbio_schedule(void)
  15.355 -{
  15.356 -    /*
  15.357 -     * Needed so that two processes, who together make the following predicate
  15.358 -     * true, don't both read stale values and evaluate the predicate
  15.359 -     * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
  15.360 -     */
  15.361 -    smp_mb();
  15.362 -
  15.363 -    if ( !list_empty(&usbio_schedule_list) )
  15.364 -        wake_up(&usbio_schedule_wait);
  15.365 -}
  15.366 -
  15.367 -
  15.368 -/******************************************************************************
  15.369 - * NOTIFICATION FROM GUEST OS.
  15.370 - */
  15.371 -
  15.372 -irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs)
  15.373 -{
  15.374 -    usbif_priv_t *up = dev_id;
  15.375 -
  15.376 -    smp_mb();
  15.377 -
  15.378 -    add_to_usbif_list_tail(up); 
  15.379 -
  15.380 -    /* Will in fact /always/ trigger an io schedule in this case. */
  15.381 -    maybe_trigger_usbio_schedule();
  15.382 -
  15.383 -    return IRQ_HANDLED;
  15.384 -}
  15.385 -
  15.386 -
  15.387 -
  15.388 -/******************************************************************
  15.389 - * DOWNWARD CALLS -- These interface with the usb-device layer proper.
  15.390 - */
  15.391 -
  15.392 -static int do_usb_io_op(usbif_priv_t *up, int max_to_do)
  15.393 -{
  15.394 -    usbif_back_ring_t *usb_ring = &up->usb_ring;
  15.395 -    usbif_request_t *req;
  15.396 -    RING_IDX i, rp;
  15.397 -    int more_to_do = 0;
  15.398 -
  15.399 -    rp = usb_ring->sring->req_prod;
  15.400 -    rmb(); /* Ensure we see queued requests up to 'rp'. */
  15.401 -    
  15.402 -    /* Take items off the comms ring, taking care not to overflow. */
  15.403 -    for ( i = usb_ring->req_cons; 
  15.404 -          (i != rp) && !RING_REQUEST_CONS_OVERFLOW(usb_ring, i);
  15.405 -          i++ )
  15.406 -    {
  15.407 -        if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
  15.408 -        {
  15.409 -            more_to_do = 1;
  15.410 -            break;
  15.411 -        }
  15.412 -
  15.413 -        req = RING_GET_REQUEST(usb_ring, i);
  15.414 -        
  15.415 -        switch ( req->operation )
  15.416 -        {
  15.417 -        case USBIF_OP_PROBE:
  15.418 -            dispatch_usb_probe(up, req->id, req->port);
  15.419 -            break;
  15.420 -
  15.421 -        case USBIF_OP_IO:
  15.422 -	  /* Assemble an appropriate URB. */
  15.423 -	  dispatch_usb_io(up, req);
  15.424 -          break;
  15.425 -
  15.426 -	case USBIF_OP_RESET:
  15.427 -	  dispatch_usb_reset(up, req->port);
  15.428 -          break;
  15.429 -
  15.430 -        default:
  15.431 -            DPRINTK("error: unknown USB io operation [%d]\n",
  15.432 -                    req->operation);
  15.433 -            make_response(up, req->id, req->operation, -EINVAL, 0, 0);
  15.434 -            break;
  15.435 -        }
  15.436 -    }
  15.437 -
  15.438 -    usb_ring->req_cons = i;
  15.439 -
  15.440 -    return more_to_do;
  15.441 -}
  15.442 -
  15.443 -static owned_port_t *find_guest_port(usbif_priv_t *up, int port)
  15.444 -{
  15.445 -    unsigned long flags;
  15.446 -    struct list_head *l;
  15.447 -
  15.448 -    spin_lock_irqsave(&owned_ports_lock, flags);
  15.449 -    list_for_each(l, &owned_ports)
  15.450 -    {
  15.451 -        owned_port_t *p = list_entry(l, owned_port_t, list);
  15.452 -        if(p->usbif_priv == up && p->guest_port == port)
  15.453 -        {
  15.454 -            spin_unlock_irqrestore(&owned_ports_lock, flags);
  15.455 -            return p;
  15.456 -        }
  15.457 -    }
  15.458 -    spin_unlock_irqrestore(&owned_ports_lock, flags);
  15.459 -
  15.460 -    return NULL;
  15.461 -}
  15.462 -
  15.463 -static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid)
  15.464 -{
  15.465 -    owned_port_t *port = find_guest_port(up, portid);
  15.466 -    int ret = 0;
  15.467 -
  15.468 -
  15.469 -    /* Allowing the guest to actually reset the device causes more problems
  15.470 -     * than it's worth.  We just fake it out in software but we will do a real
  15.471 -     * reset when the interface is destroyed. */
  15.472 -
  15.473 -    dump_port(port);
  15.474 -
  15.475 -    port->guest_address = 0;
  15.476 -    /* If there's an attached device then the port is now enabled. */
  15.477 -    if ( port->dev_present )
  15.478 -        port->enabled = 1;
  15.479 -    else
  15.480 -        port->enabled = 0;
  15.481 -
  15.482 -    make_response(up, 0, USBIF_OP_RESET, ret, 0, 0);
  15.483 -}
  15.484 -
  15.485 -static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned long portid)
  15.486 -{
  15.487 -    owned_port_t *port = find_guest_port(up, portid);
  15.488 -    int ret;
  15.489 - 
  15.490 -    if ( port != NULL )
  15.491 -        ret = port->dev_present;
  15.492 -    else
  15.493 -    {
  15.494 -        ret = -EINVAL;
  15.495 -        printk(KERN_INFO "dispatch_usb_probe(): invalid port probe request "
  15.496 -	       "(port %ld)\n", portid);
  15.497 -    }
  15.498 -
  15.499 -    /* Probe result is sent back in-band.  Probes don't have an associated id
  15.500 -     * right now... */
  15.501 -    make_response(up, id, USBIF_OP_PROBE, ret, portid, 0);
  15.502 -}
  15.503 -
  15.504 -/**
  15.505 - * check_iso_schedule - safety check the isochronous schedule for an URB
  15.506 - * @purb : the URB in question
  15.507 - */
  15.508 -static int check_iso_schedule(struct urb *purb)
  15.509 -{
  15.510 -    int i;
  15.511 -    unsigned long total_length = 0;
  15.512 -    
  15.513 -    for ( i = 0; i < purb->number_of_packets; i++ )
  15.514 -    {
  15.515 -        struct usb_iso_packet_descriptor *desc = &purb->iso_frame_desc[i];
  15.516 -        
  15.517 -        if ( desc->offset >= purb->transfer_buffer_length
  15.518 -            || ( desc->offset + desc->length) > purb->transfer_buffer_length )
  15.519 -            return -EINVAL;
  15.520 -
  15.521 -        total_length += desc->length;
  15.522 -
  15.523 -        if ( total_length > purb->transfer_buffer_length )
  15.524 -            return -EINVAL;
  15.525 -    }
  15.526 -    
  15.527 -    return 0;
  15.528 -}
  15.529 -
  15.530 -owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req);
  15.531 -
  15.532 -static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req)
  15.533 -{
  15.534 -    unsigned long buffer_mach;
  15.535 -    int i = 0, offset = 0,
  15.536 -        pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
  15.537 -    pending_req_t *pending_req;
  15.538 -    unsigned long  remap_prot;
  15.539 -    multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
  15.540 -    struct urb *purb = NULL;
  15.541 -    owned_port_t *port;
  15.542 -    unsigned char *setup;    
  15.543 -
  15.544 -    dump_request(req);
  15.545 -
  15.546 -    if ( NR_PENDING_REQS == MAX_PENDING_REQS )
  15.547 -    {
  15.548 -        printk(KERN_WARNING "usbback: Max requests already queued. "
  15.549 -	       "Giving up!\n");
  15.550 -        
  15.551 -        return;
  15.552 -    }
  15.553 -
  15.554 -    port = find_port_for_request(up, req);
  15.555 -
  15.556 -    if ( port == NULL )
  15.557 -    {
  15.558 -	printk(KERN_WARNING "No such device! (%d)\n", req->devnum);
  15.559 -	dump_request(req);
  15.560 -
  15.561 -        make_response(up, req->id, req->operation, -ENODEV, 0, 0);
  15.562 -	return;
  15.563 -    }
  15.564 -    else if ( !port->dev_present )
  15.565 -    {
  15.566 -        /* In normal operation, we'll only get here if a device is unplugged
  15.567 -         * and the frontend hasn't noticed yet. */
  15.568 -        make_response(up, req->id, req->operation, -ENODEV, 0, 0);
  15.569 -	return;
  15.570 -    }
  15.571 -        
  15.572 -
  15.573 -    setup = kmalloc(8, GFP_KERNEL);
  15.574 -
  15.575 -    if ( setup == NULL )
  15.576 -        goto no_mem;
  15.577 -   
  15.578 -    /* Copy request out for safety. */
  15.579 -    memcpy(setup, req->setup, 8);
  15.580 -
  15.581 -    if( setup[0] == 0x0 && setup[1] == 0x5)
  15.582 -    {
  15.583 -        /* To virtualise the USB address space, we need to intercept
  15.584 -         * set_address messages and emulate.  From the USB specification:
  15.585 -         * bmRequestType = 0x0;
  15.586 -         * Brequest = SET_ADDRESS (i.e. 0x5)
  15.587 -         * wValue = device address
  15.588 -         * wIndex = 0
  15.589 -         * wLength = 0
  15.590 -         * data = None
  15.591 -         */
  15.592 -        /* Store into the guest transfer buffer using cpu_to_le16 */
  15.593 -        port->guest_address = le16_to_cpu(*(u16 *)(setup + 2));
  15.594 -        /* Make a successful response.  That was easy! */
  15.595 -
  15.596 -        make_response(up, req->id, req->operation, 0, 0, 0);
  15.597 -
  15.598 -	kfree(setup);
  15.599 -        return;
  15.600 -    }
  15.601 -    else if ( setup[0] == 0x0 && setup[1] == 0x9 )
  15.602 -    {
  15.603 -        /* The host kernel needs to know what device configuration is in use
  15.604 -         * because various error checks get confused otherwise.  We just do
  15.605 -         * configuration settings here, under controlled conditions.
  15.606 -         */
  15.607 -
  15.608 -      /* Ignore configuration setting and hope that the host kernel
  15.609 -	 did it right. */
  15.610 -        /* usb_set_configuration(port->dev, setup[2]); */
  15.611 -
  15.612 -        make_response(up, req->id, req->operation, 0, 0, 0);
  15.613 -
  15.614 -        kfree(setup);
  15.615 -        return;
  15.616 -    }
  15.617 -    else if ( setup[0] == 0x1 && setup[1] == 0xB )
  15.618 -    {
  15.619 -        /* The host kernel needs to know what device interface is in use
  15.620 -         * because various error checks get confused otherwise.  We just do
  15.621 -         * configuration settings here, under controlled conditions.
  15.622 -         */
  15.623 -        usb_set_interface(port->dev, (setup[4] | setup[5] << 8),
  15.624 -                          (setup[2] | setup[3] << 8) );
  15.625 -
  15.626 -        make_response(up, req->id, req->operation, 0, 0, 0);
  15.627 -
  15.628 -        kfree(setup);
  15.629 -        return;
  15.630 -    }
  15.631 -
  15.632 -    if ( ( req->transfer_buffer - (req->transfer_buffer & PAGE_MASK)
  15.633 -	   + req->length )
  15.634 -	 > MMAP_PAGES_PER_REQUEST * PAGE_SIZE )
  15.635 -    {
  15.636 -        printk(KERN_WARNING "usbback: request of %lu bytes too large\n",
  15.637 -	       req->length);
  15.638 -        make_response(up, req->id, req->operation, -EINVAL, 0, 0);
  15.639 -        kfree(setup);
  15.640 -        return;
  15.641 -    }
  15.642 -    
  15.643 -    buffer_mach = req->transfer_buffer;
  15.644 -
  15.645 -    if( buffer_mach == 0 )
  15.646 -	goto no_remap;
  15.647 -
  15.648 -    ASSERT((req->length >> PAGE_SHIFT) <= MMAP_PAGES_PER_REQUEST);
  15.649 -    ASSERT(buffer_mach);
  15.650 -
  15.651 -    /* Always map writeable for now. */
  15.652 -    remap_prot = _PAGE_PRESENT|_PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_RW;
  15.653 -
  15.654 -    for ( i = 0, offset = 0; offset < req->length;
  15.655 -          i++, offset += PAGE_SIZE )
  15.656 -    {
  15.657 -	mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
  15.658 -	mcl[i].args[0] = MMAP_VADDR(pending_idx, i);
  15.659 -        mcl[i].args[1] = ((buffer_mach & PAGE_MASK) + offset) | remap_prot;
  15.660 -        mcl[i].args[2] = 0;
  15.661 -        mcl[i].args[3] = up->domid;
  15.662 -        
  15.663 -        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
  15.664 -            FOREIGN_FRAME((buffer_mach + offset) >> PAGE_SHIFT);
  15.665 -
  15.666 -        ASSERT(virt_to_machine(MMAP_VADDR(pending_idx, i))
  15.667 -               == buffer_mach + i << PAGE_SHIFT);
  15.668 -    }
  15.669 -
  15.670 -    if ( req->pipe_type == 0 && req->num_iso > 0 ) /* Maybe schedule ISO... */
  15.671 -    {
  15.672 -        /* Map in ISO schedule, if necessary. */
  15.673 -        mcl[i].op = __HYPERVISOR_update_va_mapping_otherdomain;
  15.674 -        mcl[i].args[0] = MMAP_VADDR(pending_idx, i);
  15.675 -        mcl[i].args[1] = (req->iso_schedule & PAGE_MASK) | remap_prot;
  15.676 -        mcl[i].args[2] = 0;
  15.677 -        mcl[i].args[3] = up->domid;
  15.678 -
  15.679 -        phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
  15.680 -            FOREIGN_FRAME(req->iso_schedule >> PAGE_SHIFT);
  15.681 -    
  15.682 -        i++;
  15.683 -    }
  15.684 -
  15.685 -    if ( unlikely(HYPERVISOR_multicall(mcl, i) != 0) )
  15.686 -        BUG();
  15.687 -    
  15.688 -    {
  15.689 -        int j;
  15.690 -        for ( j = 0; j < i; j++ )
  15.691 -        {
  15.692 -            if ( unlikely(mcl[j].args[5] != 0) )
  15.693 -            {
  15.694 -                printk(KERN_WARNING
  15.695 -		       "invalid buffer %d -- could not remap it\n", j);
  15.696 -                fast_flush_area(pending_idx, i);
  15.697 -                goto bad_descriptor;
  15.698 -            }
  15.699 -	}
  15.700 -    }
  15.701 -    
  15.702 - no_remap:
  15.703 -
  15.704 -    ASSERT(i <= MMAP_PAGES_PER_REQUEST);
  15.705 -    ASSERT(i * PAGE_SIZE >= req->length);
  15.706 -
  15.707 -    /* We have to do this because some things might complete out of order. */
  15.708 -    pending_req = &pending_reqs[pending_idx];
  15.709 -    pending_req->usbif_priv= up;
  15.710 -    pending_req->id        = req->id;
  15.711 -    pending_req->operation = req->operation;
  15.712 -    pending_req->nr_pages  = i;
  15.713 -
  15.714 -    pending_cons++;
  15.715 -
  15.716 -    usbif_get(up);
  15.717 -    
  15.718 -    /* Fill out an actual request for the USB layer. */
  15.719 -    purb = usb_alloc_urb(req->num_iso);
  15.720 -
  15.721 -    if ( purb == NULL )
  15.722 -    {
  15.723 -        usbif_put(up);
  15.724 -        free_pending(pending_idx);
  15.725 -        goto no_mem;
  15.726 -    }
  15.727 -
  15.728 -    purb->dev = port->dev;
  15.729 -    purb->context = pending_req;
  15.730 -    purb->transfer_buffer =
  15.731 -        (void *)(MMAP_VADDR(pending_idx, 0) + (buffer_mach & ~PAGE_MASK));
  15.732 -    if(buffer_mach == 0)
  15.733 -      purb->transfer_buffer = NULL;
  15.734 -    purb->complete = __end_usb_io_op;
  15.735 -    purb->transfer_buffer_length = req->length;
  15.736 -    purb->transfer_flags = req->transfer_flags;
  15.737 -
  15.738 -    purb->pipe = 0;
  15.739 -    purb->pipe |= req->direction << 7;
  15.740 -    purb->pipe |= port->dev->devnum << 8;
  15.741 -    purb->pipe |= req->speed << 26;
  15.742 -    purb->pipe |= req->pipe_type << 30;
  15.743 -    purb->pipe |= req->endpoint << 15;
  15.744 -
  15.745 -    purb->number_of_packets = req->num_iso;
  15.746 -
  15.747 -    if ( purb->number_of_packets * sizeof(usbif_iso_t) > PAGE_SIZE )
  15.748 -        goto urb_error;
  15.749 -
  15.750 -    /* Make sure there's always some kind of timeout. */
  15.751 -    purb->timeout = ( req->timeout > 0 ) ? (req->timeout * HZ) / 1000
  15.752 -                    :  1000;
  15.753 -
  15.754 -    purb->setup_packet = setup;
  15.755 -
  15.756 -    if ( req->pipe_type == 0 ) /* ISO */
  15.757 -    {
  15.758 -        int j;
  15.759 -        usbif_iso_t *iso_sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, i - 1);
  15.760 -
  15.761 -        /* If we're dealing with an iso pipe, we need to copy in a schedule. */
  15.762 -        for ( j = 0; j < purb->number_of_packets; j++ )
  15.763 -        {
  15.764 -            purb->iso_frame_desc[j].length = iso_sched[j].length;
  15.765 -            purb->iso_frame_desc[j].offset = iso_sched[j].buffer_offset;
  15.766 -            iso_sched[j].status = 0;
  15.767 -        }
  15.768 -    }
  15.769 -
  15.770 -    if ( check_iso_schedule(purb) != 0 )
  15.771 -        goto urb_error;
  15.772 -
  15.773 -    if ( usb_submit_urb(purb) != 0 )
  15.774 -        goto urb_error;
  15.775 -
  15.776 -    return;
  15.777 -
  15.778 - urb_error:
  15.779 -    dump_urb(purb);    
  15.780 -    usbif_put(up);
  15.781 -    free_pending(pending_idx);
  15.782 -
  15.783 - bad_descriptor:
  15.784 -    kfree ( setup );
  15.785 -    if ( purb != NULL )
  15.786 -        usb_free_urb(purb);
  15.787 -    make_response(up, req->id, req->operation, -EINVAL, 0, 0);
  15.788 -    return;
  15.789 -    
  15.790 - no_mem:
  15.791 -    if ( setup != NULL )
  15.792 -        kfree(setup);
  15.793 -    make_response(up, req->id, req->operation, -ENOMEM, 0, 0);
  15.794 -    return;
  15.795 -} 
  15.796 -
  15.797 -
  15.798 -
  15.799 -/******************************************************************
  15.800 - * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
  15.801 - */
  15.802 -
  15.803 -
  15.804 -static void make_response(usbif_priv_t *up, unsigned long id,
  15.805 -                          unsigned short op, int st, int inband,
  15.806 -			  unsigned long length)
  15.807 -{
  15.808 -    usbif_response_t *resp;
  15.809 -    unsigned long     flags;
  15.810 -    usbif_back_ring_t *usb_ring = &up->usb_ring;
  15.811 -
  15.812 -    /* Place on the response ring for the relevant domain. */ 
  15.813 -    spin_lock_irqsave(&up->usb_ring_lock, flags);
  15.814 -    resp = RING_GET_RESPONSE(usb_ring, usb_ring->rsp_prod_pvt);
  15.815 -    resp->id        = id;
  15.816 -    resp->operation = op;
  15.817 -    resp->status    = st;
  15.818 -    resp->data      = inband;
  15.819 -    resp->length = length;
  15.820 -    wmb(); /* Ensure other side can see the response fields. */
  15.821 -
  15.822 -    dump_response(resp);
  15.823 -
  15.824 -    usb_ring->rsp_prod_pvt++;
  15.825 -    RING_PUSH_RESPONSES(usb_ring);
  15.826 -    spin_unlock_irqrestore(&up->usb_ring_lock, flags);
  15.827 -
  15.828 -    /* Kick the relevant domain. */
  15.829 -    notify_via_evtchn(up->evtchn);
  15.830 -}
  15.831 -
  15.832 -/**
  15.833 - * usbif_claim_port - claim devices on a port on behalf of guest
  15.834 - *
  15.835 - * Once completed, this will ensure that any device attached to that
  15.836 - * port is claimed by this driver for use by the guest.
  15.837 - */
  15.838 -int usbif_claim_port(usbif_be_claim_port_t *msg)
  15.839 -{
  15.840 -    owned_port_t *o_p;
  15.841 -    
  15.842 -    /* Sanity... */
  15.843 -    if ( usbif_find_port(msg->path) != NULL )
  15.844 -    {
  15.845 -        printk(KERN_WARNING "usbback: Attempted to claim USB port "
  15.846 -               "we already own!\n");
  15.847 -        return -EINVAL;
  15.848 -    }
  15.849 -
  15.850 -    /* No need for a slab cache - this should be infrequent. */
  15.851 -    o_p = kmalloc(sizeof(owned_port_t), GFP_KERNEL);
  15.852 -
  15.853 -    if ( o_p == NULL )
  15.854 -        return -ENOMEM;
  15.855 -
  15.856 -    o_p->enabled = 0;
  15.857 -    o_p->usbif_priv = usbif_find(msg->domid);
  15.858 -    o_p->guest_port = msg->usbif_port;
  15.859 -    o_p->dev_present = 0;
  15.860 -    o_p->guest_address = 0; /* Default address. */
  15.861 -
  15.862 -    strcpy(o_p->path, msg->path);
  15.863 -
  15.864 -    spin_lock_irq(&owned_ports_lock);
  15.865 -    
  15.866 -    list_add(&o_p->list, &owned_ports);
  15.867 -
  15.868 -    spin_unlock_irq(&owned_ports_lock);
  15.869 -
  15.870 -    printk(KERN_INFO "usbback: Claimed USB port (%s) for %d.%d\n", o_p->path,
  15.871 -	   msg->domid, msg->usbif_port);
  15.872 -
  15.873 -    /* Force a reprobe for unclaimed devices. */
  15.874 -    usb_scan_devices();
  15.875 -
  15.876 -    return 0;
  15.877 -}
  15.878 -
  15.879 -owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req)
  15.880 -{
  15.881 -    unsigned long flags;
  15.882 -    struct list_head *port;
  15.883 -
  15.884 -    /* I'm assuming this is not called from IRQ context - correct?  I think
  15.885 -     * it's probably only called in response to control messages or plug events
  15.886 -     * in the USB hub kernel thread, so should be OK. */
  15.887 -    spin_lock_irqsave(&owned_ports_lock, flags);
  15.888 -    list_for_each(port, &owned_ports)
  15.889 -    {
  15.890 -        owned_port_t *p = list_entry(port, owned_port_t, list);
  15.891 -        if(p->usbif_priv == up && p->guest_address == req->devnum && p->enabled )
  15.892 -	  {
  15.893 -              dump_port(p);
  15.894 -
  15.895 -	      spin_unlock_irqrestore(&owned_ports_lock, flags);
  15.896 -              return p;
  15.897 -	  }
  15.898 -    }
  15.899 -    spin_unlock_irqrestore(&owned_ports_lock, flags);
  15.900 -
  15.901 -    return NULL;    
  15.902 -}
  15.903 -
  15.904 -owned_port_t *__usbif_find_port(char *path)
  15.905 -{
  15.906 -    struct list_head *port;
  15.907 -
  15.908 -    list_for_each(port, &owned_ports)
  15.909 -    {
  15.910 -        owned_port_t *p = list_entry(port, owned_port_t, list);
  15.911 -        if(!strcmp(path, p->path))
  15.912 -        {
  15.913 -            return p;
  15.914 -        }
  15.915 -    }
  15.916 -
  15.917 -    return NULL;
  15.918 -}
  15.919 -
  15.920 -owned_port_t *usbif_find_port(char *path)
  15.921 -{
  15.922 -    owned_port_t *ret;
  15.923 -    unsigned long flags;
  15.924 -
  15.925 -    spin_lock_irqsave(&owned_ports_lock, flags);
  15.926 -    ret = __usbif_find_port(path);    
  15.927 -    spin_unlock_irqrestore(&owned_ports_lock, flags);
  15.928 -
  15.929 -    return ret;
  15.930 -}
  15.931 -
  15.932 -
  15.933 -static void *probe(struct usb_device *dev, unsigned iface,
  15.934 -                   const struct usb_device_id *id)
  15.935 -{
  15.936 -    owned_port_t *p;
  15.937 -
  15.938 -    /* We don't care what the device is - if we own the port, we want it.  We
  15.939 -     * don't deal with device-specifics in this driver, so we don't care what
  15.940 -     * the device actually is ;-) */
  15.941 -    if ( ( p = usbif_find_port(dev->devpath) ) != NULL )
  15.942 -    {
  15.943 -        printk(KERN_INFO "usbback: claimed device attached to owned port\n");
  15.944 -
  15.945 -        p->dev_present = 1;
  15.946 -        p->dev = dev;
  15.947 -        set_bit(iface, &p->ifaces);
  15.948 -        
  15.949 -        return p->usbif_priv;
  15.950 -    }
  15.951 -    else
  15.952 -        printk(KERN_INFO "usbback: hotplug for non-owned port (%s), ignoring\n",
  15.953 -	       dev->devpath);
  15.954 -   
  15.955 -
  15.956 -    return NULL;
  15.957 -}
  15.958 -
  15.959 -static void disconnect(struct usb_device *dev, void *usbif)
  15.960 -{
  15.961 -    /* Note the device is removed so we can tell the guest when it probes. */
  15.962 -    owned_port_t *port = usbif_find_port(dev->devpath);
  15.963 -    port->dev_present = 0;
  15.964 -    port->dev = NULL;
  15.965 -    port->ifaces = 0;
  15.966 -}
  15.967 -
  15.968 -
  15.969 -struct usb_driver driver =
  15.970 -{
  15.971 -    .owner      = THIS_MODULE,
  15.972 -    .name       = "Xen USB Backend",
  15.973 -    .probe      = probe,
  15.974 -    .disconnect = disconnect,
  15.975 -    .id_table   = NULL,
  15.976 -};
  15.977 -
  15.978 -/* __usbif_release_port - internal mechanics for releasing a port */
  15.979 -void __usbif_release_port(owned_port_t *p)
  15.980 -{
  15.981 -    int i;
  15.982 -
  15.983 -    for ( i = 0; p->ifaces != 0; i++)
  15.984 -        if ( p->ifaces & 1 << i )
  15.985 -        {
  15.986 -            usb_driver_release_interface(&driver, usb_ifnum_to_if(p->dev, i));
  15.987 -            clear_bit(i, &p->ifaces);
  15.988 -        }
  15.989 -    list_del(&p->list);
  15.990 -
  15.991 -    /* Reset the real device.  We don't simulate disconnect / probe for other
  15.992 -     * drivers in this kernel because we assume the device is completely under
  15.993 -     * the control of ourselves (i.e. the guest!).  This should ensure that the
  15.994 -     * device is in a sane state for the next customer ;-) */
  15.995 -
  15.996 -    /* MAW NB: we're not resetting the real device here.  This looks perfectly
  15.997 -     * valid to me but it causes memory corruption.  We seem to get away with not
  15.998 -     * resetting for now, although it'd be nice to have this tracked down. */
  15.999 -/*     if ( p->dev != NULL) */
 15.1000 -/*         usb_reset_device(p->dev); */
 15.1001 -
 15.1002 -    kfree(p);
 15.1003 -}
 15.1004 -
 15.1005 -
 15.1006 -/**
 15.1007 - * usbif_release_port - stop claiming devices on a port on behalf of guest
 15.1008 - */
 15.1009 -void usbif_release_port(usbif_be_release_port_t *msg)
 15.1010 -{
 15.1011 -    owned_port_t *p;
 15.1012 -
 15.1013 -    spin_lock_irq(&owned_ports_lock);
 15.1014 -    p = __usbif_find_port(msg->path);
 15.1015 -    __usbif_release_port(p);
 15.1016 -    spin_unlock_irq(&owned_ports_lock);
 15.1017 -}
 15.1018 -
 15.1019 -void usbif_release_ports(usbif_priv_t *up)
 15.1020 -{
 15.1021 -    struct list_head *port, *tmp;
 15.1022 -    unsigned long flags;
 15.1023 -    
 15.1024 -    spin_lock_irqsave(&owned_ports_lock, flags);
 15.1025 -    list_for_each_safe(port, tmp, &owned_ports)
 15.1026 -    {
 15.1027 -        owned_port_t *p = list_entry(port, owned_port_t, list);
 15.1028 -        if ( p->usbif_priv == up )
 15.1029 -            __usbif_release_port(p);
 15.1030 -    }
 15.1031 -    spin_unlock_irqrestore(&owned_ports_lock, flags);
 15.1032 -}
 15.1033 -
 15.1034 -static int __init usbif_init(void)
 15.1035 -{
 15.1036 -    int i;
 15.1037 -
 15.1038 -    if ( !(xen_start_info.flags & SIF_INITDOMAIN) &&
 15.1039 -         !(xen_start_info.flags & SIF_USB_BE_DOMAIN) )
 15.1040 -        return 0;
 15.1041 -    
 15.1042 -    if ( (mmap_vstart = allocate_empty_lowmem_region(MMAP_PAGES)) == 0 )
 15.1043 -        BUG();
 15.1044 -
 15.1045 -    pending_cons = 0;
 15.1046 -    pending_prod = MAX_PENDING_REQS;
 15.1047 -    memset(pending_reqs, 0, sizeof(pending_reqs));
 15.1048 -    for ( i = 0; i < MAX_PENDING_REQS; i++ )
 15.1049 -        pending_ring[i] = i;
 15.1050 -
 15.1051 -    spin_lock_init(&pend_prod_lock);
 15.1052 -
 15.1053 -    spin_lock_init(&owned_ports_lock);
 15.1054 -    INIT_LIST_HEAD(&owned_ports);
 15.1055 -
 15.1056 -    spin_lock_init(&usbio_schedule_list_lock);
 15.1057 -    INIT_LIST_HEAD(&usbio_schedule_list);
 15.1058 -
 15.1059 -    if ( kernel_thread(usbio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
 15.1060 -        BUG();
 15.1061 -    
 15.1062 -    usbif_interface_init();
 15.1063 -
 15.1064 -    usbif_ctrlif_init();
 15.1065 -
 15.1066 -    usb_register(&driver);
 15.1067 -
 15.1068 -    printk(KERN_INFO "Xen USB Backend Initialised");
 15.1069 -
 15.1070 -    return 0;
 15.1071 -}
 15.1072 -
 15.1073 -__initcall(usbif_init);
    16.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/usbfront.c	Sat Mar 12 20:44:12 2005 +0000
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,1664 +0,0 @@
    16.4 -/*
    16.5 - * Xen Virtual USB Frontend Driver 
    16.6 - *
    16.7 - * This file contains the first version of the Xen virtual USB hub
    16.8 - * that I've managed not to delete by mistake (3rd time lucky!).
    16.9 - *
   16.10 - * Based on Linux's uhci.c, original copyright notices are displayed
   16.11 - * below.  Portions also (c) 2004 Intel Research Cambridge
   16.12 - * and (c) 2004, 2005 Mark Williamson
   16.13 - *
   16.14 - * Contact <mark.williamson@cl.cam.ac.uk> or
   16.15 - * <xen-devel@lists.sourceforge.net> regarding this code.
   16.16 - *
   16.17 - * Still to be (maybe) implemented:
   16.18 - * - migration / backend restart support?
   16.19 - * - support for building / using as a module
   16.20 - */
   16.21 -
   16.22 -/*
   16.23 - * Universal Host Controller Interface driver for USB.
   16.24 - *
   16.25 - * Maintainer: Johannes Erdfelt <johannes@erdfelt.com>
   16.26 - *
   16.27 - * (C) Copyright 1999 Linus Torvalds
   16.28 - * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
   16.29 - * (C) Copyright 1999 Randy Dunlap
   16.30 - * (C) Copyright 1999 Georg Acher, acher@in.tum.de
   16.31 - * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
   16.32 - * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
   16.33 - * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
   16.34 - * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
   16.35 - *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
   16.36 - * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
   16.37 - *
   16.38 - * Intel documents this fairly well, and as far as I know there
   16.39 - * are no royalties or anything like that, but even so there are
   16.40 - * people who decided that they want to do the same thing in a
   16.41 - * completely different way.
   16.42 - *
   16.43 - * WARNING! The USB documentation is downright evil. Most of it
   16.44 - * is just crap, written by a committee. You're better off ignoring
   16.45 - * most of it, the important stuff is:
   16.46 - *  - the low-level protocol (fairly simple but lots of small details)
   16.47 - *  - working around the horridness of the rest
   16.48 - */
   16.49 -
   16.50 -#include <linux/config.h>
   16.51 -#include <linux/module.h>
   16.52 -#include <linux/kernel.h>
   16.53 -#include <linux/init.h>
   16.54 -#include <linux/sched.h>
   16.55 -#include <linux/delay.h>
   16.56 -#include <linux/slab.h>
   16.57 -#include <linux/smp_lock.h>
   16.58 -#include <linux/errno.h>
   16.59 -#include <linux/interrupt.h>
   16.60 -#include <linux/spinlock.h>
   16.61 -#ifdef CONFIG_USB_DEBUG
   16.62 -#define DEBUG
   16.63 -#else
   16.64 -#undef DEBUG
   16.65 -#endif
   16.66 -#include <linux/usb.h>
   16.67 -
   16.68 -#include <asm/irq.h>
   16.69 -#include <asm/system.h>
   16.70 -
   16.71 -#include "xhci.h"
   16.72 -
   16.73 -#include "../../../../../drivers/usb/hcd.h"
   16.74 -
   16.75 -#include <asm-xen/xen-public/io/usbif.h>
   16.76 -#include <asm/ctrl_if.h>
   16.77 -#include <asm/xen-public/io/domain_controller.h>
   16.78 -
   16.79 -/*
   16.80 - * Version Information
   16.81 - */
   16.82 -#define DRIVER_VERSION "v1.0"
   16.83 -#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, " \
   16.84 -                      "Randy Dunlap, Georg Acher, Deti Fliegl, " \
   16.85 -                      "Thomas Sailer, Roman Weissgaerber, Mark Williamson"
   16.86 -#define DRIVER_DESC "Xen Virtual USB Host Controller Interface"
   16.87 -
   16.88 -/*
   16.89 - * debug = 0, no debugging messages
   16.90 - * debug = 1, dump failed URB's except for stalls
   16.91 - * debug = 2, dump all failed URB's (including stalls)
   16.92 - */
   16.93 -#ifdef DEBUG
   16.94 -static int debug = 1;
   16.95 -#else
   16.96 -static int debug = 0;
   16.97 -#endif
   16.98 -MODULE_PARM(debug, "i");
   16.99 -MODULE_PARM_DESC(debug, "Debug level");
  16.100 -static char *errbuf;
  16.101 -#define ERRBUF_LEN    (PAGE_SIZE * 8)
  16.102 -
  16.103 -static int rh_submit_urb(struct urb *urb);
  16.104 -static int rh_unlink_urb(struct urb *urb);
  16.105 -static int xhci_unlink_urb(struct urb *urb);
  16.106 -static void xhci_call_completion(struct urb *urb);
  16.107 -static void xhci_drain_ring(void);
  16.108 -static void xhci_transfer_result(struct xhci *xhci, struct urb *urb);
  16.109 -static void xhci_finish_completion(void);
  16.110 -
  16.111 -#define MAX_URB_LOOP	2048		/* Maximum number of linked URB's */
  16.112 -
  16.113 -static kmem_cache_t *xhci_up_cachep;	/* urb_priv cache */
  16.114 -static struct xhci *xhci;               /* XHCI structure for the interface */
  16.115 -
  16.116 -/******************************************************************************
  16.117 - * DEBUGGING
  16.118 - */
  16.119 -
  16.120 -#ifdef DEBUG
  16.121 -
  16.122 -static void dump_urb(struct urb *urb)
  16.123 -{
  16.124 -    printk(KERN_DEBUG "dumping urb @ %p\n"
  16.125 -           "  hcpriv = %p\n"
  16.126 -           "  next = %p\n"
  16.127 -           "  dev = %p\n"
  16.128 -           "  pipe = 0x%lx\n"
  16.129 -           "  status = %d\n"
  16.130 -           "  transfer_flags = 0x%lx\n"
  16.131 -           "  transfer_buffer = %p\n"
  16.132 -           "  transfer_buffer_length = %d\n"
  16.133 -           "  actual_length = %d\n"
  16.134 -           "  bandwidth = %d\n"
  16.135 -           "  setup_packet = %p\n",
  16.136 -           urb, urb->hcpriv, urb->next, urb->dev, urb->pipe, urb->status,
  16.137 -           urb->transfer_flags, urb->transfer_buffer,
  16.138 -           urb->transfer_buffer_length, urb->actual_length, urb->bandwidth,
  16.139 -           urb->setup_packet);
  16.140 -    if ( urb->setup_packet != NULL )
  16.141 -        printk(KERN_DEBUG
  16.142 -               "setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n",
  16.143 -               urb->setup_packet[0], urb->setup_packet[1],
  16.144 -               urb->setup_packet[2], urb->setup_packet[3],
  16.145 -               urb->setup_packet[4], urb->setup_packet[5],
  16.146 -               urb->setup_packet[6], urb->setup_packet[7]);
  16.147 -    printk(KERN_DEBUG "complete = %p\n"
  16.148 -           "interval = %d\n", urb->complete, urb->interval);
  16.149 -        
  16.150 -}
  16.151 -
  16.152 -static void xhci_show_resp(usbif_response_t *r)
  16.153 -{
  16.154 -        printk(KERN_DEBUG "dumping response @ %p\n"
  16.155 -               "  id=0x%lx\n"
  16.156 -               "  op=0x%x\n"
  16.157 -               "  data=0x%x\n"
  16.158 -               "  status=0x%x\n"
  16.159 -               "  length=0x%lx\n",
  16.160 -               r->id, r->operation, r->data, r->status, r->length);
  16.161 -}
  16.162 -
  16.163 -#define DPRINK(...) printk(KERN_DEBUG __VA_ARGS__)
  16.164 -
  16.165 -#else /* DEBUG */
  16.166 -
  16.167 -#define dump_urb(blah) ((void)0)
  16.168 -#define xhci_show_resp(blah) ((void)0)
  16.169 -#define DPRINTK(blah,...) ((void)0)
  16.170 -
  16.171 -#endif /* DEBUG */
  16.172 -
  16.173 -/******************************************************************************
  16.174 - * RING REQUEST HANDLING
  16.175 - */
  16.176 -
  16.177 -/**
  16.178 - * xhci_construct_isoc - add isochronous information to a request
  16.179 - */
  16.180 -static int xhci_construct_isoc(usbif_request_t *req, struct urb *urb)
  16.181 -{
  16.182 -        usbif_iso_t *schedule;
  16.183 -        int i;
  16.184 -        struct urb_priv *urb_priv = urb->hcpriv;
  16.185 -        
  16.186 -        req->num_iso = urb->number_of_packets;
  16.187 -        schedule = (usbif_iso_t *)__get_free_page(GFP_KERNEL);
  16.188 -
  16.189 -        if ( schedule == NULL )
  16.190 -            return -ENOMEM;
  16.191 -
  16.192 -        for ( i = 0; i < req->num_iso; i++ )
  16.193 -        {
  16.194 -                schedule[i].buffer_offset = urb->iso_frame_desc[i].offset;
  16.195 -                schedule[i].length = urb->iso_frame_desc[i].length;
  16.196 -        }
  16.197 -
  16.198 -        urb_priv->schedule = schedule;
  16.199 -	req->iso_schedule = virt_to_machine(schedule);
  16.200 -
  16.201 -        return 0;
  16.202 -}
  16.203 -
  16.204 -/**
  16.205 - * xhci_queue_req - construct and queue request for an URB
  16.206 - */
  16.207 -static int xhci_queue_req(struct urb *urb)
  16.208 -{
  16.209 -        usbif_request_t *req;
  16.210 -        usbif_front_ring_t *usb_ring = &xhci->usb_ring;
  16.211 -
  16.212 -#if DEBUG
  16.213 -        printk(KERN_DEBUG
  16.214 -               "usbif = %p, req_prod = %d (@ 0x%lx), resp_prod = %d, resp_cons = %d\n",
  16.215 -               usbif, usbif->req_prod, virt_to_machine(&usbif->req_prod),
  16.216 -               usbif->resp_prod, xhci->usb_resp_cons);
  16.217 -#endif
  16.218 -        
  16.219 -
  16.220 -        if ( RING_FULL(usb_ring) )
  16.221 -        {
  16.222 -                printk(KERN_WARNING
  16.223 -                       "xhci_queue_req(): USB ring full, not queuing request\n");
  16.224 -                return -ENOBUFS;
  16.225 -        }
  16.226 -
  16.227 -        /* Stick something in the shared communications ring. */
  16.228 -	req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
  16.229 -
  16.230 -        req->operation       = USBIF_OP_IO;
  16.231 -        req->port            = 0; /* We don't care what the port is. */
  16.232 -        req->id              = (unsigned long) urb->hcpriv;
  16.233 -        req->transfer_buffer = virt_to_machine(urb->transfer_buffer);
  16.234 -	req->devnum          = usb_pipedevice(urb->pipe);
  16.235 -        req->direction       = usb_pipein(urb->pipe);
  16.236 -	req->speed           = usb_pipeslow(urb->pipe);
  16.237 -        req->pipe_type       = usb_pipetype(urb->pipe);
  16.238 -        req->length          = urb->transfer_buffer_length;
  16.239 -        req->transfer_flags  = urb->transfer_flags;
  16.240 -	req->endpoint        = usb_pipeendpoint(urb->pipe);
  16.241 -	req->speed           = usb_pipeslow(urb->pipe);
  16.242 -	req->timeout         = urb->timeout * (1000 / HZ);
  16.243 -
  16.244 -        if ( usb_pipetype(urb->pipe) == 0 ) /* ISO */
  16.245 -        {
  16.246 -            int ret = xhci_construct_isoc(req, urb);
  16.247 -            if ( ret != 0 )
  16.248 -                return ret;
  16.249 -        }
  16.250 -
  16.251 -	if(urb->setup_packet != NULL)
  16.252 -                memcpy(req->setup, urb->setup_packet, 8);
  16.253 -        else
  16.254 -                memset(req->setup, 0, 8);
  16.255 -        
  16.256 -        usb_ring->req_prod_pvt++;
  16.257 -        RING_PUSH_REQUESTS(usb_ring);
  16.258 -
  16.259 -	notify_via_evtchn(xhci->evtchn);
  16.260 -
  16.261 -        DPRINTK("Queued request for an URB.\n");
  16.262 -        dump_urb(urb);
  16.263 -
  16.264 -        return -EINPROGRESS;
  16.265 -}
  16.266 -
  16.267 -/**
  16.268 - * xhci_queue_probe - queue a probe request for a particular port
  16.269 - */
  16.270 -static inline usbif_request_t *xhci_queue_probe(usbif_vdev_t port)
  16.271 -{
  16.272 -        usbif_request_t *req;
  16.273 -        usbif_front_ring_t *usb_ring = &xhci->usb_ring;
  16.274 -
  16.275 -#if DEBUG
  16.276 -	printk(KERN_DEBUG
  16.277 -               "queuing probe: req_prod = %d (@ 0x%lx), resp_prod = %d, "
  16.278 -               "resp_cons = %d\n", usbif->req_prod,
  16.279 -               virt_to_machine(&usbif->req_prod),
  16.280 -	       usbif->resp_prod, xhci->usb_resp_cons);
  16.281 -#endif
  16.282 -        
  16.283 -        if ( RING_FULL(usb_ring) )
  16.284 -        {
  16.285 -                printk(KERN_WARNING
  16.286 -                       "xhci_queue_probe(): ring full, not queuing request\n");
  16.287 -                return NULL;
  16.288 -        }
  16.289 -
  16.290 -        /* Stick something in the shared communications ring. */
  16.291 -        req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
  16.292 -
  16.293 -        memset(req, sizeof(*req), 0);
  16.294 -
  16.295 -        req->operation       = USBIF_OP_PROBE;
  16.296 -        req->port            = port;
  16.297 -
  16.298 -        usb_ring->req_prod_pvt++;
  16.299 -        RING_PUSH_REQUESTS(usb_ring);
  16.300 -
  16.301 -	notify_via_evtchn(xhci->evtchn);
  16.302 -
  16.303 -        return req;
  16.304 -}
  16.305 -
  16.306 -/**
  16.307 - * xhci_port_reset - queue a reset request for a particular port
  16.308 - */
  16.309 -static int xhci_port_reset(usbif_vdev_t port)
  16.310 -{
  16.311 -        usbif_request_t *req;
  16.312 -        usbif_front_ring_t *usb_ring = &xhci->usb_ring;
  16.313 -
  16.314 -        /* We only reset one port at a time, so we only need one variable per
  16.315 -         * hub. */
  16.316 -        xhci->awaiting_reset = 1;
  16.317 -        
  16.318 -        /* Stick something in the shared communications ring. */
  16.319 -	req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
  16.320 -
  16.321 -        memset(req, sizeof(*req), 0);
  16.322 -
  16.323 -        req->operation       = USBIF_OP_RESET;
  16.324 -        req->port            = port;
  16.325 -        
  16.326 -        usb_ring->req_prod_pvt++;
  16.327 -	RING_PUSH_REQUESTS(usb_ring);
  16.328 -
  16.329 -	notify_via_evtchn(xhci->evtchn);
  16.330 -
  16.331 -        while ( xhci->awaiting_reset > 0 )
  16.332 -        {
  16.333 -                mdelay(1);
  16.334 -                xhci_drain_ring();
  16.335 -        }
  16.336 -
  16.337 -	xhci->rh.ports[port].pe = 1;
  16.338 -	xhci->rh.ports[port].pe_chg = 1;
  16.339 -
  16.340 -        return xhci->awaiting_reset;
  16.341 -}
  16.342 -
  16.343 -
  16.344 -/******************************************************************************
  16.345 - * RING RESPONSE HANDLING
  16.346 - */
  16.347 -
  16.348 -static void receive_usb_reset(usbif_response_t *resp)
  16.349 -{
  16.350 -    xhci->awaiting_reset = resp->status;
  16.351 -    rmb();
  16.352 -    
  16.353 -}
  16.354 -
  16.355 -static void receive_usb_probe(usbif_response_t *resp)
  16.356 -{
  16.357 -    spin_lock(&xhci->rh.port_state_lock);
  16.358 -
  16.359 -    if ( resp->status > 0 )
  16.360 -    {
  16.361 -        if ( resp->status == 1 )
  16.362 -        {
  16.363 -            /* If theres a device there and there wasn't one before there must
  16.364 -             * have been a connection status change. */
  16.365 -            if( xhci->rh.ports[resp->data].cs == 0 )
  16.366 -	    {
  16.367 -                xhci->rh.ports[resp->data].cs = 1;
  16.368 -                xhci->rh.ports[resp->data].ccs = 1;
  16.369 -                xhci->rh.ports[resp->data].cs_chg = 1;
  16.370 -	    }
  16.371 -        }
  16.372 -        else
  16.373 -            printk(KERN_WARNING "receive_usb_probe(): unexpected status %d "
  16.374 -                   "for port %d\n", resp->status, resp->data);
  16.375 -    }
  16.376 -    else if ( resp->status < 0)
  16.377 -        printk(KERN_WARNING "receive_usb_probe(): got error status %d\n",
  16.378 -               resp->status);
  16.379 -
  16.380 -    spin_unlock(&xhci->rh.port_state_lock);
  16.381 -}
  16.382 -
  16.383 -static void receive_usb_io(usbif_response_t *resp)
  16.384 -{
  16.385 -        struct urb_priv *urbp = (struct urb_priv *)resp->id;
  16.386 -        struct urb *urb = urbp->urb;
  16.387 -
  16.388 -        urb->actual_length = resp->length;
  16.389 -        urbp->in_progress = 0;
  16.390 -
  16.391 -        if( usb_pipetype(urb->pipe) == 0 ) /* ISO */
  16.392 -        {
  16.393 -                int i;
  16.394 -              
  16.395 -                /* Copy ISO schedule results back in. */
  16.396 -                for ( i = 0; i < urb->number_of_packets; i++ )
  16.397 -                {
  16.398 -                        urb->iso_frame_desc[i].status
  16.399 -                                = urbp->schedule[i].status;
  16.400 -                        urb->iso_frame_desc[i].actual_length
  16.401 -                                = urbp->schedule[i].length;
  16.402 -                }
  16.403 -                free_page((unsigned long)urbp->schedule);
  16.404 -        }
  16.405 -
  16.406 -        /* Only set status if it's not been changed since submission.  It might
  16.407 -         * have been changed if the URB has been unlinked asynchronously, for
  16.408 -         * instance. */
  16.409 -	if ( urb->status == -EINPROGRESS )
  16.410 -                urbp->status = urb->status = resp->status;
  16.411 -}
  16.412 -
  16.413 -/**
  16.414 - * xhci_drain_ring - drain responses from the ring, calling handlers
  16.415 - *
  16.416 - * This may be called from interrupt context when an event is received from the
  16.417 - * backend domain, or sometimes in process context whilst waiting for a port
  16.418 - * reset or URB completion.
  16.419 - */
  16.420 -static void xhci_drain_ring(void)
  16.421 -{
  16.422 -	struct list_head *tmp, *head;
  16.423 -	usbif_front_ring_t *usb_ring = &xhci->usb_ring;
  16.424 -	usbif_response_t *resp;
  16.425 -        RING_IDX i, rp;
  16.426 -
  16.427 -        /* Walk the ring here to get responses, updating URBs to show what
  16.428 -         * completed. */
  16.429 -        
  16.430 -        rp = usb_ring->sring->rsp_prod;
  16.431 -        rmb(); /* Ensure we see queued requests up to 'rp'. */
  16.432 -
  16.433 -        /* Take items off the comms ring, taking care not to overflow. */
  16.434 -        for ( i = usb_ring->rsp_cons; i != rp; i++ )
  16.435 -        {
  16.436 -            resp = RING_GET_RESPONSE(usb_ring, i);
  16.437 -            
  16.438 -            /* May need to deal with batching and with putting a ceiling on
  16.439 -               the number dispatched for performance and anti-dos reasons */
  16.440 -
  16.441 -            xhci_show_resp(resp);
  16.442 -
  16.443 -            switch ( resp->operation )
  16.444 -            {
  16.445 -            case USBIF_OP_PROBE:
  16.446 -                receive_usb_probe(resp);
  16.447 -                break;
  16.448 -                
  16.449 -            case USBIF_OP_IO:
  16.450 -                receive_usb_io(resp);
  16.451 -                break;
  16.452 -
  16.453 -            case USBIF_OP_RESET:
  16.454 -                receive_usb_reset(resp);
  16.455 -                break;
  16.456 -
  16.457 -            default:
  16.458 -                printk(KERN_WARNING
  16.459 -                       "error: unknown USB io operation response [%d]\n",
  16.460 -                       resp->operation);
  16.461 -                break;
  16.462 -            }
  16.463 -        }
  16.464 -
  16.465 -        usb_ring->rsp_cons = i;
  16.466 -
  16.467 -	/* Walk the list of pending URB's to see which ones completed and do
  16.468 -         * callbacks, etc. */
  16.469 -	spin_lock(&xhci->urb_list_lock);
  16.470 -	head = &xhci->urb_list;
  16.471 -	tmp = head->next;
  16.472 -	while (tmp != head) {
  16.473 -		struct urb *urb = list_entry(tmp, struct urb, urb_list);
  16.474 -
  16.475 -		tmp = tmp->next;
  16.476 -
  16.477 -		/* Checks the status and does all of the magic necessary */
  16.478 -		xhci_transfer_result(xhci, urb);
  16.479 -	}
  16.480 -	spin_unlock(&xhci->urb_list_lock);
  16.481 -
  16.482 -	xhci_finish_completion();
  16.483 -}
  16.484 -
  16.485 -
  16.486 -static void xhci_interrupt(int irq, void *__xhci, struct pt_regs *regs)
  16.487 -{
  16.488 -        xhci_drain_ring();
  16.489 -}
  16.490 -
  16.491 -/******************************************************************************
  16.492 - * HOST CONTROLLER FUNCTIONALITY
  16.493 - */
  16.494 -
  16.495 -/**
  16.496 - * no-op implementation of private device alloc / free routines
  16.497 - */
  16.498 -static int xhci_do_nothing_dev(struct usb_device *dev)
  16.499 -{
  16.500 -	return 0;
  16.501 -}
  16.502 -
  16.503 -static inline void xhci_add_complete(struct urb *urb)
  16.504 -{
  16.505 -	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
  16.506 -	unsigned long flags;
  16.507 -
  16.508 -	spin_lock_irqsave(&xhci->complete_list_lock, flags);
  16.509 -	list_add_tail(&urbp->complete_list, &xhci->complete_list);
  16.510 -	spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
  16.511 -}
  16.512 -
  16.513 -/* When this returns, the owner of the URB may free its
  16.514 - * storage.
  16.515 - *
  16.516 - * We spin and wait for the URB to complete before returning.
  16.517 - *
  16.518 - * Call with urb->lock acquired.
  16.519 - */
  16.520 -static void xhci_delete_urb(struct urb *urb)
  16.521 -{
  16.522 -        struct urb_priv *urbp;
  16.523 -
  16.524 -	urbp = urb->hcpriv;
  16.525 -
  16.526 -        /* If there's no urb_priv structure for this URB then it can't have
  16.527 -         * been submitted at all. */
  16.528 -	if ( urbp == NULL )
  16.529 -		return;
  16.530 -
  16.531 -	/* For now we just spin until the URB completes.  It shouldn't take too
  16.532 -         * long and we don't expect to have to do this very often. */
  16.533 -	while ( urb->status == -EINPROGRESS )
  16.534 -        {
  16.535 -            xhci_drain_ring();
  16.536 -            mdelay(1);
  16.537 -        }
  16.538 -
  16.539 -	/* Now we know that further transfers to the buffer won't
  16.540 -	 * occur, so we can safely return. */
  16.541 -}
  16.542 -
  16.543 -static struct urb_priv *xhci_alloc_urb_priv(struct urb *urb)
  16.544 -{
  16.545 -	struct urb_priv *urbp;
  16.546 -
  16.547 -	urbp = kmem_cache_alloc(xhci_up_cachep, SLAB_ATOMIC);
  16.548 -	if (!urbp) {
  16.549 -		err("xhci_alloc_urb_priv: couldn't allocate memory for urb_priv\n");
  16.550 -		return NULL;
  16.551 -	}
  16.552 -
  16.553 -	memset((void *)urbp, 0, sizeof(*urbp));
  16.554 -
  16.555 -	urbp->inserttime = jiffies;
  16.556 -	urbp->urb = urb;
  16.557 -	urbp->dev = urb->dev;
  16.558 -	
  16.559 -	INIT_LIST_HEAD(&urbp->complete_list);
  16.560 -
  16.561 -	urb->hcpriv = urbp;
  16.562 -
  16.563 -	return urbp;
  16.564 -}
  16.565 -
  16.566 -/*
  16.567 - * MUST be called with urb->lock acquired
  16.568 - */
  16.569 -/* When is this called?  Do we need to stop the transfer (as we
  16.570 - * currently do)? */
  16.571 -static void xhci_destroy_urb_priv(struct urb *urb)
  16.572 -{
  16.573 -    struct urb_priv *urbp;
  16.574 -    
  16.575 -    urbp = (struct urb_priv *)urb->hcpriv;
  16.576 -    if (!urbp)
  16.577 -        return;
  16.578 -
  16.579 -    if (!list_empty(&urb->urb_list))
  16.580 -        warn("xhci_destroy_urb_priv: urb %p still on xhci->urb_list", urb);
  16.581 -    
  16.582 -    if (!list_empty(&urbp->complete_list))
  16.583 -        warn("xhci_destroy_urb_priv: urb %p still on xhci->complete_list", urb);
  16.584 -    
  16.585 -    kmem_cache_free(xhci_up_cachep, urb->hcpriv);
  16.586 -
  16.587 -    urb->hcpriv = NULL;
  16.588 -}
  16.589 -
  16.590 -/**
  16.591 - * Try to find URBs in progress on the same pipe to the same device.
  16.592 - *
  16.593 - * MUST be called with xhci->urb_list_lock acquired
  16.594 - */
  16.595 -static struct urb *xhci_find_urb_ep(struct xhci *xhci, struct urb *urb)
  16.596 -{
  16.597 -	struct list_head *tmp, *head;
  16.598 -
  16.599 -	/* We don't match Isoc transfers since they are special */
  16.600 -	if (usb_pipeisoc(urb->pipe))
  16.601 -		return NULL;
  16.602 -
  16.603 -	head = &xhci->urb_list;
  16.604 -	tmp = head->next;
  16.605 -	while (tmp != head) {
  16.606 -		struct urb *u = list_entry(tmp, struct urb, urb_list);
  16.607 -
  16.608 -		tmp = tmp->next;
  16.609 -
  16.610 -		if (u->dev == urb->dev && u->pipe == urb->pipe &&
  16.611 -		    u->status == -EINPROGRESS)
  16.612 -			return u;
  16.613 -	}
  16.614 -
  16.615 -	return NULL;
  16.616 -}
  16.617 -
  16.618 -static int xhci_submit_urb(struct urb *urb)
  16.619 -{
  16.620 -	int ret = -EINVAL;
  16.621 -	unsigned long flags;
  16.622 -	struct urb *eurb;
  16.623 -	int bustime;
  16.624 -
  16.625 -        DPRINTK("URB submitted to XHCI driver.\n");
  16.626 -        dump_urb(urb);
  16.627 -
  16.628 -	if (!urb)
  16.629 -		return -EINVAL;
  16.630 -
  16.631 -	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
  16.632 -		warn("xhci_submit_urb: urb %p belongs to disconnected device or bus?", urb);
  16.633 -		return -ENODEV;
  16.634 -	}
  16.635 -
  16.636 -        if ( urb->dev->devpath == NULL )
  16.637 -                BUG();
  16.638 -
  16.639 -	usb_inc_dev_use(urb->dev);
  16.640 -
  16.641 -	spin_lock_irqsave(&xhci->urb_list_lock, flags);
  16.642 -	spin_lock(&urb->lock);
  16.643 -
  16.644 -	if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
  16.645 -	    urb->status == -ECONNABORTED) {
  16.646 -		dbg("xhci_submit_urb: urb not available to submit (status = %d)", urb->status);
  16.647 -		/* Since we can have problems on the out path */
  16.648 -		spin_unlock(&urb->lock);
  16.649 -		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.650 -		usb_dec_dev_use(urb->dev);
  16.651 -
  16.652 -		return ret;
  16.653 -	}
  16.654 -
  16.655 -	INIT_LIST_HEAD(&urb->urb_list);
  16.656 -	if (!xhci_alloc_urb_priv(urb)) {
  16.657 -		ret = -ENOMEM;
  16.658 -
  16.659 -		goto out;
  16.660 -	}
  16.661 -
  16.662 -        ( (struct urb_priv *)urb->hcpriv )->in_progress = 1;
  16.663 -
  16.664 -	eurb = xhci_find_urb_ep(xhci, urb);
  16.665 -	if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
  16.666 -		ret = -ENXIO;
  16.667 -
  16.668 -		goto out;
  16.669 -	}
  16.670 -
  16.671 -	/* Short circuit the virtual root hub */
  16.672 -	if (urb->dev == xhci->rh.dev) {
  16.673 -		ret = rh_submit_urb(urb);
  16.674 -
  16.675 -		goto out;
  16.676 -	}
  16.677 -
  16.678 -	switch (usb_pipetype(urb->pipe)) {
  16.679 -	case PIPE_CONTROL:
  16.680 -	case PIPE_BULK:
  16.681 -		ret = xhci_queue_req(urb);
  16.682 -		break;
  16.683 -
  16.684 -	case PIPE_INTERRUPT:
  16.685 -		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
  16.686 -			bustime = usb_check_bandwidth(urb->dev, urb);
  16.687 -			if (bustime < 0)
  16.688 -				ret = bustime;
  16.689 -			else {
  16.690 -				ret = xhci_queue_req(urb);
  16.691 -				if (ret == -EINPROGRESS)
  16.692 -					usb_claim_bandwidth(urb->dev, urb,
  16.693 -                                                            bustime, 0);
  16.694 -			}
  16.695 -		} else		/* bandwidth is already set */
  16.696 -			ret = xhci_queue_req(urb);
  16.697 -		break;
  16.698 -
  16.699 -	case PIPE_ISOCHRONOUS:
  16.700 -		if (urb->bandwidth == 0) {	/* not yet checked/allocated */
  16.701 -			if (urb->number_of_packets <= 0) {
  16.702 -				ret = -EINVAL;
  16.703 -				break;
  16.704 -			}
  16.705 -			bustime = usb_check_bandwidth(urb->dev, urb);
  16.706 -			if (bustime < 0) {
  16.707 -				ret = bustime;
  16.708 -				break;
  16.709 -			}
  16.710 -
  16.711 -			ret = xhci_queue_req(urb);
  16.712 -			if (ret == -EINPROGRESS)
  16.713 -				usb_claim_bandwidth(urb->dev, urb, bustime, 1);
  16.714 -		} else		/* bandwidth is already set */
  16.715 -			ret = xhci_queue_req(urb);
  16.716 -		break;
  16.717 -	}
  16.718 -out:
  16.719 -	urb->status = ret;
  16.720 -
  16.721 -	if (ret == -EINPROGRESS) {
  16.722 -		/* We use _tail to make find_urb_ep more efficient */
  16.723 -		list_add_tail(&urb->urb_list, &xhci->urb_list);
  16.724 -
  16.725 -		spin_unlock(&urb->lock);
  16.726 -		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.727 -
  16.728 -		return 0;
  16.729 -	}
  16.730 -
  16.731 -	xhci_delete_urb(urb);
  16.732 -
  16.733 -	spin_unlock(&urb->lock);
  16.734 -	spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.735 -
  16.736 -	/* Only call completion if it was successful */
  16.737 -	if (!ret)
  16.738 -		xhci_call_completion(urb);
  16.739 -
  16.740 -	return ret;
  16.741 -}
  16.742 -
  16.743 -/*
  16.744 - * Return the result of a transfer
  16.745 - *
  16.746 - * MUST be called with urb_list_lock acquired
  16.747 - */
  16.748 -static void xhci_transfer_result(struct xhci *xhci, struct urb *urb)
  16.749 -{
  16.750 -	int ret = 0;
  16.751 -	unsigned long flags;
  16.752 -	struct urb_priv *urbp;
  16.753 -
  16.754 -	/* The root hub is special */
  16.755 -	if (urb->dev == xhci->rh.dev)
  16.756 -		return;
  16.757 -
  16.758 -	spin_lock_irqsave(&urb->lock, flags);
  16.759 -
  16.760 -	urbp = (struct urb_priv *)urb->hcpriv;
  16.761 -
  16.762 -        if ( ( (struct urb_priv *)urb->hcpriv )->in_progress )
  16.763 -                ret = -EINPROGRESS;
  16.764 -
  16.765 -        if (urb->actual_length < urb->transfer_buffer_length) {
  16.766 -                if (urb->transfer_flags & USB_DISABLE_SPD) {
  16.767 -                        ret = -EREMOTEIO;
  16.768 -                }
  16.769 -        }
  16.770 -
  16.771 -	if (urb->status == -EPIPE)
  16.772 -        {
  16.773 -                ret = urb->status;
  16.774 -		/* endpoint has stalled - mark it halted */
  16.775 -		usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe),
  16.776 -                                  usb_pipeout(urb->pipe));
  16.777 -        }
  16.778 -
  16.779 -	if ((debug == 1 && ret != 0 && ret != -EPIPE) ||
  16.780 -            (ret != 0 && debug > 1)) {
  16.781 -		/* Some debugging code */
  16.782 -		dbg("xhci_result_interrupt/bulk() failed with status %x",
  16.783 -			status);
  16.784 -	}
  16.785 -
  16.786 -	if (ret == -EINPROGRESS)
  16.787 -		goto out;
  16.788 -
  16.789 -	switch (usb_pipetype(urb->pipe)) {
  16.790 -	case PIPE_CONTROL:
  16.791 -	case PIPE_BULK:
  16.792 -	case PIPE_ISOCHRONOUS:
  16.793 -		/* Release bandwidth for Interrupt or Isoc. transfers */
  16.794 -		/* Spinlock needed ? */
  16.795 -		if (urb->bandwidth)
  16.796 -			usb_release_bandwidth(urb->dev, urb, 1);
  16.797 -		xhci_delete_urb(urb);
  16.798 -		break;
  16.799 -	case PIPE_INTERRUPT:
  16.800 -		/* Interrupts are an exception */
  16.801 -		if (urb->interval)
  16.802 -			goto out_complete;
  16.803 -
  16.804 -		/* Release bandwidth for Interrupt or Isoc. transfers */
  16.805 -		/* Spinlock needed ? */
  16.806 -		if (urb->bandwidth)
  16.807 -			usb_release_bandwidth(urb->dev, urb, 0);
  16.808 -		xhci_delete_urb(urb);
  16.809 -		break;
  16.810 -	default:
  16.811 -		info("xhci_transfer_result: unknown pipe type %d for urb %p\n",
  16.812 -                     usb_pipetype(urb->pipe), urb);
  16.813 -	}
  16.814 -
  16.815 -	/* Remove it from xhci->urb_list */
  16.816 -	list_del_init(&urb->urb_list);
  16.817 -
  16.818 -out_complete:
  16.819 -	xhci_add_complete(urb);
  16.820 -
  16.821 -out:
  16.822 -	spin_unlock_irqrestore(&urb->lock, flags);
  16.823 -}
  16.824 -
  16.825 -static int xhci_unlink_urb(struct urb *urb)
  16.826 -{
  16.827 -	unsigned long flags;
  16.828 -	struct urb_priv *urbp = urb->hcpriv;
  16.829 -
  16.830 -	if (!urb)
  16.831 -		return -EINVAL;
  16.832 -
  16.833 -	if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
  16.834 -		return -ENODEV;
  16.835 -
  16.836 -	spin_lock_irqsave(&xhci->urb_list_lock, flags);
  16.837 -	spin_lock(&urb->lock);
  16.838 -
  16.839 -	/* Release bandwidth for Interrupt or Isoc. transfers */
  16.840 -	/* Spinlock needed ? */
  16.841 -	if (urb->bandwidth) {
  16.842 -		switch (usb_pipetype(urb->pipe)) {
  16.843 -		case PIPE_INTERRUPT:
  16.844 -			usb_release_bandwidth(urb->dev, urb, 0);
  16.845 -			break;
  16.846 -		case PIPE_ISOCHRONOUS:
  16.847 -			usb_release_bandwidth(urb->dev, urb, 1);
  16.848 -			break;
  16.849 -		default:
  16.850 -			break;
  16.851 -		}
  16.852 -	}
  16.853 -
  16.854 -	if (urb->status != -EINPROGRESS) {
  16.855 -		spin_unlock(&urb->lock);
  16.856 -		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.857 -		return 0;
  16.858 -	}
  16.859 -
  16.860 -	list_del_init(&urb->urb_list);
  16.861 -
  16.862 -	/* Short circuit the virtual root hub */
  16.863 -	if (urb->dev == xhci->rh.dev) {
  16.864 -		rh_unlink_urb(urb);
  16.865 -
  16.866 -		spin_unlock(&urb->lock);
  16.867 -		spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.868 -
  16.869 -		xhci_call_completion(urb);
  16.870 -	} else {
  16.871 -		if (urb->transfer_flags & USB_ASYNC_UNLINK) {
  16.872 -                        /* We currently don't currently attempt to cancel URBs
  16.873 -                         * that have been queued in the ring.  We handle async
  16.874 -                         * unlinked URBs when they complete. */
  16.875 -			urbp->status = urb->status = -ECONNABORTED;
  16.876 -			spin_unlock(&urb->lock);
  16.877 -			spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.878 -		} else {
  16.879 -			urb->status = -ENOENT;
  16.880 -
  16.881 -			spin_unlock(&urb->lock);
  16.882 -			spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
  16.883 -
  16.884 -			if (in_interrupt()) {	/* wait at least 1 frame */
  16.885 -				static int errorcount = 10;
  16.886 -
  16.887 -				if (errorcount--)
  16.888 -					dbg("xhci_unlink_urb called from interrupt for urb %p", urb);
  16.889 -				udelay(1000);
  16.890 -			} else
  16.891 -				schedule_timeout(1+1*HZ/1000); 
  16.892 -
  16.893 -                        xhci_delete_urb(urb);
  16.894 -
  16.895 -			xhci_call_completion(urb);
  16.896 -		}
  16.897 -	}
  16.898 -
  16.899 -	return 0;
  16.900 -}
  16.901 -
  16.902 -static void xhci_call_completion(struct urb *urb)
  16.903 -{
  16.904 -	struct urb_priv *urbp;
  16.905 -	struct usb_device *dev = urb->dev;
  16.906 -	int is_ring = 0, killed, resubmit_interrupt, status;
  16.907 -	struct urb *nurb;
  16.908 -	unsigned long flags;
  16.909 -
  16.910 -	spin_lock_irqsave(&urb->lock, flags);
  16.911 -
  16.912 -	urbp = (struct urb_priv *)urb->hcpriv;
  16.913 -	if (!urbp || !urb->dev) {
  16.914 -		spin_unlock_irqrestore(&urb->lock, flags);
  16.915 -		return;
  16.916 -	}
  16.917 -
  16.918 -	killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
  16.919 -			urb->status == -ECONNRESET);
  16.920 -	resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
  16.921 -			urb->interval);
  16.922 -
  16.923 -	nurb = urb->next;
  16.924 -	if (nurb && !killed) {
  16.925 -		int count = 0;
  16.926 -
  16.927 -		while (nurb && nurb != urb && count < MAX_URB_LOOP) {
  16.928 -			if (nurb->status == -ENOENT ||
  16.929 -			    nurb->status == -ECONNABORTED ||
  16.930 -			    nurb->status == -ECONNRESET) {
  16.931 -				killed = 1;
  16.932 -				break;
  16.933 -			}
  16.934 -
  16.935 -			nurb = nurb->next;
  16.936 -			count++;
  16.937 -		}
  16.938 -
  16.939 -		if (count == MAX_URB_LOOP)
  16.940 -			err("xhci_call_completion: too many linked URB's, loop? (first loop)");
  16.941 -
  16.942 -		/* Check to see if chain is a ring */
  16.943 -		is_ring = (nurb == urb);
  16.944 -	}
  16.945 -
  16.946 -	status = urbp->status;
  16.947 -	if (!resubmit_interrupt || killed)
  16.948 -		/* We don't need urb_priv anymore */
  16.949 -		xhci_destroy_urb_priv(urb);
  16.950 -
  16.951 -	if (!killed)
  16.952 -		urb->status = status;
  16.953 -
  16.954 -	spin_unlock_irqrestore(&urb->lock, flags);
  16.955 -
  16.956 -	if (urb->complete)
  16.957 -		urb->complete(urb);
  16.958 -
  16.959 -	if (resubmit_interrupt)
  16.960 -		/* Recheck the status. The completion handler may have */
  16.961 -		/*  unlinked the resubmitting interrupt URB */
  16.962 -		killed = (urb->status == -ENOENT ||
  16.963 -			  urb->status == -ECONNABORTED ||
  16.964 -			  urb->status == -ECONNRESET);
  16.965 -
  16.966 -	if (resubmit_interrupt && !killed) {
  16.967 -                if ( urb->dev != xhci->rh.dev )
  16.968 -                        xhci_queue_req(urb); /* XXX What if this fails? */
  16.969 -                /* Don't need to resubmit URBs for the virtual root dev. */
  16.970 -	} else {
  16.971 -		if (is_ring && !killed) {
  16.972 -			urb->dev = dev;
  16.973 -			xhci_submit_urb(urb);
  16.974 -		} else {
  16.975 -			/* We decrement the usage count after we're done */
  16.976 -			/*  with everything */
  16.977 -			usb_dec_dev_use(dev);
  16.978 -		}
  16.979 -	}
  16.980 -}
  16.981 -
  16.982 -static void xhci_finish_completion(void)
  16.983 -{
  16.984 -	struct list_head *tmp, *head;
  16.985 -	unsigned long flags;
  16.986 -
  16.987 -	spin_lock_irqsave(&xhci->complete_list_lock, flags);
  16.988 -	head = &xhci->complete_list;
  16.989 -	tmp = head->next;
  16.990 -	while (tmp != head) {
  16.991 -		struct urb_priv *urbp = list_entry(tmp, struct urb_priv,
  16.992 -                                                   complete_list);
  16.993 -		struct urb *urb = urbp->urb;
  16.994 -
  16.995 -		list_del_init(&urbp->complete_list);
  16.996 -		spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
  16.997 -
  16.998 -		xhci_call_completion(urb);
  16.999 -
 16.1000 -		spin_lock_irqsave(&xhci->complete_list_lock, flags);
 16.1001 -		head = &xhci->complete_list;
 16.1002 -		tmp = head->next;
 16.1003 -	}
 16.1004 -	spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
 16.1005 -}
 16.1006 -
 16.1007 -static struct usb_operations xhci_device_operations = {
 16.1008 -	.allocate = xhci_do_nothing_dev,
 16.1009 -	.deallocate = xhci_do_nothing_dev,
 16.1010 -        /* It doesn't look like any drivers actually care what the frame number
 16.1011 -	 * is at the moment!  If necessary, we could approximate the current
 16.1012 -	 * frame nubmer by passing it from the backend in response messages. */
 16.1013 -	.get_frame_number = NULL,
 16.1014 -	.submit_urb = xhci_submit_urb,
 16.1015 -	.unlink_urb = xhci_unlink_urb
 16.1016 -};
 16.1017 -
 16.1018 -/******************************************************************************
 16.1019 - * VIRTUAL ROOT HUB EMULATION
 16.1020 - */
 16.1021 -
 16.1022 -static __u8 root_hub_dev_des[] =
 16.1023 -{
 16.1024 - 	0x12,			/*  __u8  bLength; */
 16.1025 -	0x01,			/*  __u8  bDescriptorType; Device */
 16.1026 -	0x00,			/*  __u16 bcdUSB; v1.0 */
 16.1027 -	0x01,
 16.1028 -	0x09,			/*  __u8  bDeviceClass; HUB_CLASSCODE */
 16.1029 -	0x00,			/*  __u8  bDeviceSubClass; */
 16.1030 -	0x00,			/*  __u8  bDeviceProtocol; */
 16.1031 -	0x08,			/*  __u8  bMaxPacketSize0; 8 Bytes */
 16.1032 -	0x00,			/*  __u16 idVendor; */
 16.1033 -	0x00,
 16.1034 -	0x00,			/*  __u16 idProduct; */
 16.1035 -	0x00,
 16.1036 -	0x00,			/*  __u16 bcdDevice; */
 16.1037 -	0x00,
 16.1038 -	0x00,			/*  __u8  iManufacturer; */
 16.1039 -	0x02,			/*  __u8  iProduct; */
 16.1040 -	0x01,			/*  __u8  iSerialNumber; */
 16.1041 -	0x01			/*  __u8  bNumConfigurations; */
 16.1042 -};
 16.1043 -
 16.1044 -
 16.1045 -/* Configuration descriptor */
 16.1046 -static __u8 root_hub_config_des[] =
 16.1047 -{
 16.1048 -	0x09,			/*  __u8  bLength; */
 16.1049 -	0x02,			/*  __u8  bDescriptorType; Configuration */
 16.1050 -	0x19,			/*  __u16 wTotalLength; */
 16.1051 -	0x00,
 16.1052 -	0x01,			/*  __u8  bNumInterfaces; */
 16.1053 -	0x01,			/*  __u8  bConfigurationValue; */
 16.1054 -	0x00,			/*  __u8  iConfiguration; */
 16.1055 -	0x40,			/*  __u8  bmAttributes;
 16.1056 -					Bit 7: Bus-powered, 6: Self-powered,
 16.1057 -					Bit 5 Remote-wakeup, 4..0: resvd */
 16.1058 -	0x00,			/*  __u8  MaxPower; */
 16.1059 -
 16.1060 -	/* interface */
 16.1061 -	0x09,			/*  __u8  if_bLength; */
 16.1062 -	0x04,			/*  __u8  if_bDescriptorType; Interface */
 16.1063 -	0x00,			/*  __u8  if_bInterfaceNumber; */
 16.1064 -	0x00,			/*  __u8  if_bAlternateSetting; */
 16.1065 -	0x01,			/*  __u8  if_bNumEndpoints; */
 16.1066 -	0x09,			/*  __u8  if_bInterfaceClass; HUB_CLASSCODE */
 16.1067 -	0x00,			/*  __u8  if_bInterfaceSubClass; */
 16.1068 -	0x00,			/*  __u8  if_bInterfaceProtocol; */
 16.1069 -	0x00,			/*  __u8  if_iInterface; */
 16.1070 -
 16.1071 -	/* endpoint */
 16.1072 -	0x07,			/*  __u8  ep_bLength; */
 16.1073 -	0x05,			/*  __u8  ep_bDescriptorType; Endpoint */
 16.1074 -	0x81,			/*  __u8  ep_bEndpointAddress; IN Endpoint 1 */
 16.1075 -	0x03,			/*  __u8  ep_bmAttributes; Interrupt */
 16.1076 -	0x08,			/*  __u16 ep_wMaxPacketSize; 8 Bytes */
 16.1077 -	0x00,
 16.1078 -	0xff			/*  __u8  ep_bInterval; 255 ms */
 16.1079 -};
 16.1080 -
 16.1081 -static __u8 root_hub_hub_des[] =
 16.1082 -{
 16.1083 -	0x09,			/*  __u8  bLength; */
 16.1084 -	0x29,			/*  __u8  bDescriptorType; Hub-descriptor */
 16.1085 -	0x02,			/*  __u8  bNbrPorts; */
 16.1086 -	0x00,			/* __u16  wHubCharacteristics; */
 16.1087 -	0x00,
 16.1088 -	0x01,			/*  __u8  bPwrOn2pwrGood; 2ms */
 16.1089 -	0x00,			/*  __u8  bHubContrCurrent; 0 mA */
 16.1090 -	0x00,			/*  __u8  DeviceRemovable; *** 7 Ports max *** */
 16.1091 -	0xff			/*  __u8  PortPwrCtrlMask; *** 7 ports max *** */
 16.1092 -};
 16.1093 -
 16.1094 -/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
 16.1095 -static int rh_send_irq(struct urb *urb)
 16.1096 -{
 16.1097 -	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 16.1098 -        xhci_port_t *ports = xhci->rh.ports;
 16.1099 -	unsigned long flags;
 16.1100 -	int i, len = 1;
 16.1101 -	__u16 data = 0;
 16.1102 -
 16.1103 -	spin_lock_irqsave(&urb->lock, flags);
 16.1104 -	for (i = 0; i < xhci->rh.numports; i++) {
 16.1105 -                /* Set a bit if anything at all has changed on the port, as per
 16.1106 -		 * USB spec 11.12 */
 16.1107 -		data |= (ports[i].cs_chg || ports[i].pe_chg )
 16.1108 -                        ? (1 << (i + 1))
 16.1109 -                        : 0;
 16.1110 -
 16.1111 -		len = (i + 1) / 8 + 1;
 16.1112 -	}
 16.1113 -
 16.1114 -	*(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
 16.1115 -	urb->actual_length = len;
 16.1116 -	urbp->status = 0;
 16.1117 -
 16.1118 -	spin_unlock_irqrestore(&urb->lock, flags);
 16.1119 -
 16.1120 -	if ((data > 0) && (xhci->rh.send != 0)) {
 16.1121 -		dbg("root-hub INT complete: data: %x", data);
 16.1122 -		xhci_call_completion(urb);
 16.1123 -	}
 16.1124 -
 16.1125 -	return 0;
 16.1126 -}
 16.1127 -
 16.1128 -/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
 16.1129 -static int rh_init_int_timer(struct urb *urb);
 16.1130 -
 16.1131 -static void rh_int_timer_do(unsigned long ptr)
 16.1132 -{
 16.1133 -	struct urb *urb = (struct urb *)ptr;
 16.1134 -	struct list_head list, *tmp, *head;
 16.1135 -	unsigned long flags;
 16.1136 -	int i;
 16.1137 -
 16.1138 -	for ( i = 0; i < xhci->rh.numports; i++)
 16.1139 -                xhci_queue_probe(i);
 16.1140 -
 16.1141 -	if (xhci->rh.send)
 16.1142 -		rh_send_irq(urb);
 16.1143 -
 16.1144 -	INIT_LIST_HEAD(&list);
 16.1145 -
 16.1146 -	spin_lock_irqsave(&xhci->urb_list_lock, flags);
 16.1147 -	head = &xhci->urb_list;
 16.1148 -	tmp = head->next;
 16.1149 -	while (tmp != head) {
 16.1150 -		struct urb *u = list_entry(tmp, struct urb, urb_list);
 16.1151 -		struct urb_priv *up = (struct urb_priv *)u->hcpriv;
 16.1152 -
 16.1153 -		tmp = tmp->next;
 16.1154 -
 16.1155 -		spin_lock(&u->lock);
 16.1156 -
 16.1157 -		/* Check if the URB timed out */
 16.1158 -		if (u->timeout && time_after_eq(jiffies,
 16.1159 -                                                up->inserttime + u->timeout)) {
 16.1160 -			list_del(&u->urb_list);
 16.1161 -			list_add_tail(&u->urb_list, &list);
 16.1162 -		}
 16.1163 -
 16.1164 -		spin_unlock(&u->lock);
 16.1165 -	}
 16.1166 -	spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
 16.1167 -
 16.1168 -	head = &list;
 16.1169 -	tmp = head->next;
 16.1170 -	while (tmp != head) {
 16.1171 -		struct urb *u = list_entry(tmp, struct urb, urb_list);
 16.1172 -
 16.1173 -		tmp = tmp->next;
 16.1174 -
 16.1175 -		u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
 16.1176 -		xhci_unlink_urb(u);
 16.1177 -	}
 16.1178 -
 16.1179 -	rh_init_int_timer(urb);
 16.1180 -}
 16.1181 -
 16.1182 -/* Root Hub INTs are polled by this timer */
 16.1183 -static int rh_init_int_timer(struct urb *urb)
 16.1184 -{
 16.1185 -	xhci->rh.interval = urb->interval;
 16.1186 -	init_timer(&xhci->rh.rh_int_timer);
 16.1187 -	xhci->rh.rh_int_timer.function = rh_int_timer_do;
 16.1188 -	xhci->rh.rh_int_timer.data = (unsigned long)urb;
 16.1189 -	xhci->rh.rh_int_timer.expires = jiffies
 16.1190 -                + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
 16.1191 -	add_timer(&xhci->rh.rh_int_timer);
 16.1192 -
 16.1193 -	return 0;
 16.1194 -}
 16.1195 -
 16.1196 -#define OK(x)			len = (x); break
 16.1197 -
 16.1198 -/* Root Hub Control Pipe */
 16.1199 -static int rh_submit_urb(struct urb *urb)
 16.1200 -{
 16.1201 -	unsigned int pipe = urb->pipe;
 16.1202 -	struct usb_ctrlrequest *cmd =
 16.1203 -                (struct usb_ctrlrequest *)urb->setup_packet;
 16.1204 -	void *data = urb->transfer_buffer;
 16.1205 -	int leni = urb->transfer_buffer_length;
 16.1206 -	int len = 0;
 16.1207 -	xhci_port_t *status;
 16.1208 -	int stat = 0;
 16.1209 -	int i;
 16.1210 -	int retstatus;
 16.1211 -        unsigned long flags;
 16.1212 -        
 16.1213 -	__u16 cstatus;
 16.1214 -	__u16 bmRType_bReq;
 16.1215 -	__u16 wValue;
 16.1216 -	__u16 wIndex;
 16.1217 -	__u16 wLength;
 16.1218 -
 16.1219 -	if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
 16.1220 -		xhci->rh.urb = urb;
 16.1221 -		xhci->rh.send = 1;
 16.1222 -		xhci->rh.interval = urb->interval;
 16.1223 -		rh_init_int_timer(urb);
 16.1224 -
 16.1225 -		return -EINPROGRESS;
 16.1226 -	}
 16.1227 -
 16.1228 -	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
 16.1229 -	wValue = le16_to_cpu(cmd->wValue);
 16.1230 -	wIndex = le16_to_cpu(cmd->wIndex);
 16.1231 -	wLength = le16_to_cpu(cmd->wLength);
 16.1232 -
 16.1233 -	for (i = 0; i < 8; i++)
 16.1234 -		xhci->rh.c_p_r[i] = 0;
 16.1235 -
 16.1236 -        status = &xhci->rh.ports[wIndex - 1];
 16.1237 -
 16.1238 -        spin_lock_irqsave(&xhci->rh.port_state_lock, flags);
 16.1239 -
 16.1240 -	switch (bmRType_bReq) {
 16.1241 -		/* Request Destination:
 16.1242 -		   without flags: Device,
 16.1243 -		   RH_INTERFACE: interface,
 16.1244 -		   RH_ENDPOINT: endpoint,
 16.1245 -		   RH_CLASS means HUB here,
 16.1246 -		   RH_OTHER | RH_CLASS  almost ever means HUB_PORT here
 16.1247 -		*/
 16.1248 -
 16.1249 -	case RH_GET_STATUS:
 16.1250 -		*(__u16 *)data = cpu_to_le16(1);
 16.1251 -		OK(2);
 16.1252 -	case RH_GET_STATUS | RH_INTERFACE:
 16.1253 -		*(__u16 *)data = cpu_to_le16(0);
 16.1254 -		OK(2);
 16.1255 -	case RH_GET_STATUS | RH_ENDPOINT:
 16.1256 -		*(__u16 *)data = cpu_to_le16(0);
 16.1257 -		OK(2);
 16.1258 -	case RH_GET_STATUS | RH_CLASS:
 16.1259 -		*(__u32 *)data = cpu_to_le32(0);
 16.1260 -		OK(4);		/* hub power */
 16.1261 -	case RH_GET_STATUS | RH_OTHER | RH_CLASS:
 16.1262 -		cstatus = (status->cs_chg) |
 16.1263 -			(status->pe_chg << 1) |
 16.1264 -			(xhci->rh.c_p_r[wIndex - 1] << 4);
 16.1265 -		retstatus = (status->ccs) |
 16.1266 -			(status->pe << 1) |
 16.1267 -			(status->susp << 2) |
 16.1268 -			(status->pr << 8) |
 16.1269 -			(1 << 8) |      /* power on */
 16.1270 -			(status->lsda << 9);
 16.1271 -		*(__u16 *)data = cpu_to_le16(retstatus);
 16.1272 -		*(__u16 *)(data + 2) = cpu_to_le16(cstatus);
 16.1273 -		OK(4);
 16.1274 -	case RH_CLEAR_FEATURE | RH_ENDPOINT:
 16.1275 -		switch (wValue) {
 16.1276 -		case RH_ENDPOINT_STALL:
 16.1277 -			OK(0);
 16.1278 -		}
 16.1279 -		break;
 16.1280 -	case RH_CLEAR_FEATURE | RH_CLASS:
 16.1281 -		switch (wValue) {
 16.1282 -		case RH_C_HUB_OVER_CURRENT:
 16.1283 -			OK(0);	/* hub power over current */
 16.1284 -		}
 16.1285 -		break;
 16.1286 -	case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
 16.1287 -		switch (wValue) {
 16.1288 -		case RH_PORT_ENABLE:
 16.1289 -                        status->pe     = 0;
 16.1290 -			OK(0);
 16.1291 -		case RH_PORT_SUSPEND:
 16.1292 -                        status->susp   = 0;
 16.1293 -			OK(0);
 16.1294 -		case RH_PORT_POWER:
 16.1295 -			OK(0);	/* port power */
 16.1296 -		case RH_C_PORT_CONNECTION:
 16.1297 -                        status->cs_chg = 0;
 16.1298 -			OK(0);
 16.1299 -		case RH_C_PORT_ENABLE:
 16.1300 -                        status->pe_chg = 0;
 16.1301 -			OK(0);
 16.1302 -		case RH_C_PORT_SUSPEND:
 16.1303 -			/*** WR_RH_PORTSTAT(RH_PS_PSSC); */
 16.1304 -			OK(0);
 16.1305 -		case RH_C_PORT_OVER_CURRENT:
 16.1306 -			OK(0);	/* port power over current */
 16.1307 -		case RH_C_PORT_RESET:
 16.1308 -			xhci->rh.c_p_r[wIndex - 1] = 0;
 16.1309 -			OK(0);
 16.1310 -		}
 16.1311 -		break;
 16.1312 -	case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
 16.1313 -		switch (wValue) {
 16.1314 -		case RH_PORT_SUSPEND:
 16.1315 -                        status->susp = 1;	
 16.1316 -			OK(0);
 16.1317 -		case RH_PORT_RESET:
 16.1318 -                {
 16.1319 -                        int ret;
 16.1320 -                        xhci->rh.c_p_r[wIndex - 1] = 1;
 16.1321 -                        status->pr = 0;
 16.1322 -                        status->pe = 1;
 16.1323 -                        ret = xhci_port_reset(wIndex - 1);
 16.1324 -                        /* XXX MAW: should probably cancel queued transfers during reset... *\/ */
 16.1325 -                        if ( ret == 0 ) { OK(0); }
 16.1326 -                        else { return ret; }
 16.1327 -                }
 16.1328 -                break;
 16.1329 -		case RH_PORT_POWER:
 16.1330 -			OK(0); /* port power ** */
 16.1331 -		case RH_PORT_ENABLE:
 16.1332 -                        status->pe = 1;
 16.1333 -			OK(0);
 16.1334 -		}
 16.1335 -		break;
 16.1336 -	case RH_SET_ADDRESS:
 16.1337 -		xhci->rh.devnum = wValue;
 16.1338 -		OK(0);
 16.1339 -	case RH_GET_DESCRIPTOR:
 16.1340 -		switch ((wValue & 0xff00) >> 8) {
 16.1341 -		case 0x01:	/* device descriptor */
 16.1342 -			len = min_t(unsigned int, leni,
 16.1343 -				  min_t(unsigned int,
 16.1344 -				      sizeof(root_hub_dev_des), wLength));
 16.1345 -			memcpy(data, root_hub_dev_des, len);
 16.1346 -			OK(len);
 16.1347 -		case 0x02:	/* configuration descriptor */
 16.1348 -			len = min_t(unsigned int, leni,
 16.1349 -				  min_t(unsigned int,
 16.1350 -				      sizeof(root_hub_config_des), wLength));
 16.1351 -			memcpy (data, root_hub_config_des, len);
 16.1352 -			OK(len);
 16.1353 -		case 0x03:	/* string descriptors */
 16.1354 -			len = usb_root_hub_string (wValue & 0xff,
 16.1355 -				0, "XHCI-alt",
 16.1356 -				data, wLength);
 16.1357 -			if (len > 0) {
 16.1358 -				OK(min_t(int, leni, len));
 16.1359 -			} else 
 16.1360 -				stat = -EPIPE;
 16.1361 -		}
 16.1362 -		break;
 16.1363 -	case RH_GET_DESCRIPTOR | RH_CLASS:
 16.1364 -		root_hub_hub_des[2] = xhci->rh.numports;
 16.1365 -		len = min_t(unsigned int, leni,
 16.1366 -			  min_t(unsigned int, sizeof(root_hub_hub_des), wLength));
 16.1367 -		memcpy(data, root_hub_hub_des, len);
 16.1368 -		OK(len);
 16.1369 -	case RH_GET_CONFIGURATION:
 16.1370 -		*(__u8 *)data = 0x01;
 16.1371 -		OK(1);
 16.1372 -	case RH_SET_CONFIGURATION:
 16.1373 -		OK(0);
 16.1374 -	case RH_GET_INTERFACE | RH_INTERFACE:
 16.1375 -		*(__u8 *)data = 0x00;
 16.1376 -		OK(1);
 16.1377 -	case RH_SET_INTERFACE | RH_INTERFACE:
 16.1378 -		OK(0);
 16.1379 -	default:
 16.1380 -		stat = -EPIPE;
 16.1381 -	}
 16.1382 -
 16.1383 -        spin_unlock_irqrestore(&xhci->rh.port_state_lock, flags);
 16.1384 -
 16.1385 -	urb->actual_length = len;
 16.1386 -
 16.1387 -	return stat;
 16.1388 -}
 16.1389 -
 16.1390 -/*
 16.1391 - * MUST be called with urb->lock acquired
 16.1392 - */
 16.1393 -static int rh_unlink_urb(struct urb *urb)
 16.1394 -{
 16.1395 -	if (xhci->rh.urb == urb) {
 16.1396 -		urb->status = -ENOENT;
 16.1397 -		xhci->rh.send = 0;
 16.1398 -		xhci->rh.urb = NULL;
 16.1399 -		del_timer(&xhci->rh.rh_int_timer);
 16.1400 -	}
 16.1401 -	return 0;
 16.1402 -}
 16.1403 -
 16.1404 -/******************************************************************************
 16.1405 - * CONTROL PLANE FUNCTIONALITY
 16.1406 - */
 16.1407 -
 16.1408 -/**
 16.1409 - * alloc_xhci - initialise a new virtual root hub for a new USB device channel
 16.1410 - */
 16.1411 -static int alloc_xhci(void)
 16.1412 -{
 16.1413 -	int retval;
 16.1414 -	struct usb_bus *bus;
 16.1415 -
 16.1416 -	retval = -EBUSY;
 16.1417 -
 16.1418 -	xhci = kmalloc(sizeof(*xhci), GFP_KERNEL);
 16.1419 -	if (!xhci) {
 16.1420 -		err("couldn't allocate xhci structure");
 16.1421 -		retval = -ENOMEM;
 16.1422 -		goto err_alloc_xhci;
 16.1423 -	}
 16.1424 -
 16.1425 -	xhci->state = USBIF_STATE_CLOSED;
 16.1426 -
 16.1427 -	spin_lock_init(&xhci->urb_list_lock);
 16.1428 -	INIT_LIST_HEAD(&xhci->urb_list);
 16.1429 -
 16.1430 -	spin_lock_init(&xhci->complete_list_lock);
 16.1431 -	INIT_LIST_HEAD(&xhci->complete_list);
 16.1432 -
 16.1433 -	spin_lock_init(&xhci->frame_list_lock);
 16.1434 -
 16.1435 -	bus = usb_alloc_bus(&xhci_device_operations);
 16.1436 -
 16.1437 -	if (!bus) {
 16.1438 -		err("unable to allocate bus");
 16.1439 -		goto err_alloc_bus;
 16.1440 -	}
 16.1441 -
 16.1442 -	xhci->bus = bus;
 16.1443 -	bus->bus_name = "XHCI";
 16.1444 -	bus->hcpriv = xhci;
 16.1445 -
 16.1446 -	usb_register_bus(xhci->bus);
 16.1447 -
 16.1448 -	/* Initialize the root hub */
 16.1449 -
 16.1450 -	xhci->rh.numports = 0;
 16.1451 -
 16.1452 -	xhci->bus->root_hub = xhci->rh.dev = usb_alloc_dev(NULL, xhci->bus);
 16.1453 -	if (!xhci->rh.dev) {
 16.1454 -		err("unable to allocate root hub");
 16.1455 -		goto err_alloc_root_hub;
 16.1456 -	}
 16.1457 -
 16.1458 -	xhci->state = 0;
 16.1459 -
 16.1460 -	return 0;
 16.1461 -
 16.1462 -/*
 16.1463 - * error exits:
 16.1464 - */
 16.1465 -err_alloc_root_hub:
 16.1466 -        usb_deregister_bus(xhci->bus);
 16.1467 -	usb_free_bus(xhci->bus);
 16.1468 -	xhci->bus = NULL;
 16.1469 -
 16.1470 -err_alloc_bus:
 16.1471 -	kfree(xhci);
 16.1472 -
 16.1473 -err_alloc_xhci:
 16.1474 -	return retval;
 16.1475 -}
 16.1476 -
 16.1477 -/**
 16.1478 - * usbif_status_change - deal with an incoming USB_INTERFACE_STATUS_ message
 16.1479 - */
 16.1480 -static void usbif_status_change(usbif_fe_interface_status_changed_t *status)
 16.1481 -{
 16.1482 -    ctrl_msg_t                   cmsg;
 16.1483 -    usbif_fe_interface_connect_t up;
 16.1484 -    long rc;
 16.1485 -    usbif_sring_t *sring;
 16.1486 -
 16.1487 -    switch ( status->status )
 16.1488 -    {
 16.1489 -    case USBIF_INTERFACE_STATUS_DESTROYED:
 16.1490 -        printk(KERN_WARNING "Unexpected usbif-DESTROYED message in state %d\n",
 16.1491 -               xhci->state);
 16.1492 -        break;
 16.1493 -
 16.1494 -    case USBIF_INTERFACE_STATUS_DISCONNECTED:
 16.1495 -        if ( xhci->state != USBIF_STATE_CLOSED )
 16.1496 -        {
 16.1497 -            printk(KERN_WARNING "Unexpected usbif-DISCONNECTED message"
 16.1498 -                   " in state %d\n", xhci->state);
 16.1499 -            break;
 16.1500 -            /* Not bothering to do recovery here for now.  Keep things
 16.1501 -             * simple. */
 16.1502 -        }
 16.1503 -
 16.1504 -        /* Move from CLOSED to DISCONNECTED state. */
 16.1505 -        sring = (usbif_sring_t *)__get_free_page(GFP_KERNEL);
 16.1506 -        SHARED_RING_INIT(sring);
 16.1507 -        FRONT_RING_INIT(&xhci->usb_ring, sring);
 16.1508 -        xhci->state  = USBIF_STATE_DISCONNECTED;
 16.1509 -
 16.1510 -        /* Construct an interface-CONNECT message for the domain controller. */
 16.1511 -        cmsg.type      = CMSG_USBIF_FE;
 16.1512 -        cmsg.subtype   = CMSG_USBIF_FE_INTERFACE_CONNECT;
 16.1513 -        cmsg.length    = sizeof(usbif_fe_interface_connect_t);
 16.1514 -        up.shmem_frame = virt_to_machine(sring) >> PAGE_SHIFT;
 16.1515 -        memcpy(cmsg.msg, &up, sizeof(up));
 16.1516 -        
 16.1517 -        /* Tell the controller to bring up the interface. */
 16.1518 -        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
 16.1519 -        break;
 16.1520 -
 16.1521 -    case USBIF_INTERFACE_STATUS_CONNECTED:
 16.1522 -        if ( xhci->state == USBIF_STATE_CLOSED )
 16.1523 -        {
 16.1524 -            printk(KERN_WARNING "Unexpected usbif-CONNECTED message"
 16.1525 -                   " in state %d\n", xhci->state);
 16.1526 -            break;
 16.1527 -        }
 16.1528 -
 16.1529 -        xhci->evtchn = status->evtchn;
 16.1530 -        xhci->irq = bind_evtchn_to_irq(xhci->evtchn);
 16.1531 -	xhci->bandwidth = status->bandwidth;
 16.1532 -	xhci->rh.numports = status->num_ports;
 16.1533 -
 16.1534 -        xhci->rh.ports = kmalloc (sizeof(xhci_port_t) * xhci->rh.numports, GFP_KERNEL);
 16.1535 -        memset(xhci->rh.ports, 0, sizeof(xhci_port_t) * xhci->rh.numports);
 16.1536 -
 16.1537 -	usb_connect(xhci->rh.dev);
 16.1538 -
 16.1539 -	if (usb_new_device(xhci->rh.dev) != 0) {
 16.1540 -		err("unable to start root hub");
 16.1541 -	}
 16.1542 -
 16.1543 -	/* Allocate the appropriate USB bandwidth here...  Need to
 16.1544 -         * somehow know what the total available is thought to be so we
 16.1545 -         * can calculate the reservation correctly. */
 16.1546 - 	usb_claim_bandwidth(xhci->rh.dev, xhci->rh.urb,
 16.1547 - 			    1000 - xhci->bandwidth, 0);
 16.1548 -
 16.1549 -        if ( (rc = request_irq(xhci->irq, xhci_interrupt, 
 16.1550 -                               SA_SAMPLE_RANDOM, "usbif", xhci)) )
 16.1551 -                printk(KERN_ALERT"usbfront request_irq failed (%ld)\n",rc);
 16.1552 -
 16.1553 -	DPRINTK(KERN_INFO __FILE__
 16.1554 -                ": USB XHCI: SHM at %p (0x%lx), EVTCHN %d IRQ %d\n",
 16.1555 -                xhci->usb_ring.sring, virt_to_machine(xhci->usbif),
 16.1556 -                xhci->evtchn, xhci->irq);
 16.1557 -
 16.1558 -        xhci->state = USBIF_STATE_CONNECTED;
 16.1559 -        
 16.1560 -        break;
 16.1561 -
 16.1562 -    default:
 16.1563 -        printk(KERN_WARNING "Status change to unknown value %d\n", 
 16.1564 -               status->status);
 16.1565 -        break;
 16.1566 -    }
 16.1567 -}
 16.1568 -
 16.1569 -/**
 16.1570 - * usbif_ctrlif_rx - demux control messages by subtype
 16.1571 - */
 16.1572 -static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
 16.1573 -{
 16.1574 -    switch ( msg->subtype )
 16.1575 -    {
 16.1576 -    case CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED:
 16.1577 -        if ( msg->length != sizeof(usbif_fe_interface_status_changed_t) )
 16.1578 -            goto parse_error;
 16.1579 -        usbif_status_change((usbif_fe_interface_status_changed_t *)
 16.1580 -                            &msg->msg[0]);
 16.1581 -        break;        
 16.1582 -
 16.1583 -        /* New interface...? */
 16.1584 -    default:
 16.1585 -        goto parse_error;
 16.1586 -    }
 16.1587 -
 16.1588 -    ctrl_if_send_response(msg);
 16.1589 -    return;
 16.1590 -
 16.1591 - parse_error:
 16.1592 -    msg->length = 0;
 16.1593 -    ctrl_if_send_response(msg);
 16.1594 -}
 16.1595 -
 16.1596 -
 16.1597 -static int __init xhci_hcd_init(void)
 16.1598 -{
 16.1599 -	int retval = -ENOMEM, i;
 16.1600 -        usbif_fe_interface_status_changed_t st;
 16.1601 -        control_msg_t cmsg;
 16.1602 -
 16.1603 -	if ( (xen_start_info.flags & SIF_INITDOMAIN)
 16.1604 -	     || (xen_start_info.flags & SIF_USB_BE_DOMAIN) )
 16.1605 -                return 0;
 16.1606 -
 16.1607 -	info(DRIVER_DESC " " DRIVER_VERSION);
 16.1608 -
 16.1609 -	if (debug) {
 16.1610 -		errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
 16.1611 -		if (!errbuf)
 16.1612 -			goto errbuf_failed;
 16.1613 -	}
 16.1614 -
 16.1615 -	xhci_up_cachep = kmem_cache_create("xhci_urb_priv",
 16.1616 -		sizeof(struct urb_priv), 0, 0, NULL, NULL);
 16.1617 -	if (!xhci_up_cachep)
 16.1618 -		goto up_failed;
 16.1619 -
 16.1620 -        /* Let the domain controller know we're here.  For now we wait until
 16.1621 -         * connection, as for the block and net drivers.  This is only strictly
 16.1622 -         * necessary if we're going to boot off a USB device. */
 16.1623 -        printk(KERN_INFO "Initialising Xen virtual USB hub\n");
 16.1624 -    
 16.1625 -        (void)ctrl_if_register_receiver(CMSG_USBIF_FE, usbif_ctrlif_rx,
 16.1626 -                                        CALLBACK_IN_BLOCKING_CONTEXT);
 16.1627 -        
 16.1628 -	alloc_xhci();
 16.1629 -
 16.1630 -        /* Send a driver-UP notification to the domain controller. */
 16.1631 -        cmsg.type      = CMSG_USBIF_FE;
 16.1632 -        cmsg.subtype   = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
 16.1633 -        cmsg.length    = sizeof(usbif_fe_driver_status_changed_t);
 16.1634 -        st.status      = USBIF_DRIVER_STATUS_UP;
 16.1635 -        memcpy(cmsg.msg, &st, sizeof(st));
 16.1636 -        ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
 16.1637 -        
 16.1638 -        /*
 16.1639 -         * We should read 'nr_interfaces' from response message and wait
 16.1640 -         * for notifications before proceeding. For now we assume that we
 16.1641 -         * will be notified of exactly one interface.
 16.1642 -         */
 16.1643 -        for ( i=0; (xhci->state != USBIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
 16.1644 -        {
 16.1645 -            set_current_state(TASK_INTERRUPTIBLE);
 16.1646 -            schedule_timeout(1);
 16.1647 -        }
 16.1648 -        
 16.1649 -        if (xhci->state != USBIF_STATE_CONNECTED)
 16.1650 -            printk(KERN_WARNING "Timeout connecting USB frontend driver!\n");
 16.1651 -	
 16.1652 -	return 0;
 16.1653 -
 16.1654 -up_failed:
 16.1655 -	if (errbuf)
 16.1656 -		kfree(errbuf);
 16.1657 -
 16.1658 -errbuf_failed:
 16.1659 -	return retval;
 16.1660 -}
 16.1661 -
 16.1662 -module_init(xhci_hcd_init);
 16.1663 -
 16.1664 -MODULE_AUTHOR(DRIVER_AUTHOR);
 16.1665 -MODULE_DESCRIPTION(DRIVER_DESC);
 16.1666 -MODULE_LICENSE("GPL");
 16.1667 -
    17.1 --- a/linux-2.6.10-xen-sparse/drivers/xen/usbfront/xhci.h	Sat Mar 12 20:44:12 2005 +0000
    17.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.3 @@ -1,180 +0,0 @@
    17.4 -/******************************************************************************
    17.5 - * xhci.h
    17.6 - *
    17.7 - * Private definitions for the Xen Virtual USB Controller.  Based on
    17.8 - * drivers/usb/host/uhci.h from Linux.  Copyright for the imported content is
    17.9 - * retained by the original authors.
   17.10 - *
   17.11 - * Modifications are:
   17.12 - * Copyright (C) 2004 Intel Research Cambridge
   17.13 - * Copyright (C) 2004, 2005 Mark Williamson
   17.14 - */
   17.15 -
   17.16 -#ifndef __LINUX_XHCI_H
   17.17 -#define __LINUX_XHCI_H
   17.18 -
   17.19 -#include <linux/list.h>
   17.20 -#include <linux/usb.h>
   17.21 -#include <asm-xen/xen-public/io/usbif.h>
   17.22 -#include <linux/spinlock.h>
   17.23 -
   17.24 -/* xhci_port_t - current known state of a virtual hub ports */
   17.25 -typedef struct {
   17.26 -        unsigned int cs     :1; /* Connection status.  do we really need this /and/ ccs? */
   17.27 -        unsigned int cs_chg :1; /* Connection status change.  */
   17.28 -        unsigned int pe     :1; /* Port enable.               */
   17.29 -        unsigned int pe_chg :1; /* Port enable change.        */
   17.30 -        unsigned int ccs    :1; /* Current connect status.    */
   17.31 -        unsigned int susp   :1; /* Suspended.                 */
   17.32 -        unsigned int lsda   :1; /* Low speed device attached. */
   17.33 -        unsigned int pr     :1; /* Port reset.                */
   17.34 -} xhci_port_t;
   17.35 -
   17.36 -/* struct virt_root_hub - state related to the virtual root hub */
   17.37 -struct virt_root_hub {
   17.38 -	struct usb_device *dev;
   17.39 -	int devnum;		/* Address of Root Hub endpoint */
   17.40 -	struct urb *urb;
   17.41 -	void *int_addr;
   17.42 -	int send;
   17.43 -	int interval;
   17.44 -	int numports;
   17.45 -	int c_p_r[8];
   17.46 -	struct timer_list rh_int_timer;
   17.47 -        spinlock_t port_state_lock;
   17.48 -        xhci_port_t *ports;
   17.49 -};
   17.50 -
   17.51 -/* struct xhci - contains the state associated with a single USB interface */
   17.52 -struct xhci {
   17.53 -
   17.54 -#ifdef CONFIG_PROC_FS
   17.55 -	/* procfs */
   17.56 -	int num;
   17.57 -	struct proc_dir_entry *proc_entry;
   17.58 -#endif
   17.59 -
   17.60 -        int evtchn;                        /* Interdom channel to backend */
   17.61 -        int irq;                           /* Bound to evtchn */
   17.62 -        enum { USBIF_STATE_CONNECTED    = 2,
   17.63 -               USBIF_STATE_DISCONNECTED = 1,
   17.64 -               USBIF_STATE_CLOSED       = 0
   17.65 -        } state; /* State of this USB interface */
   17.66 -        unsigned long bandwidth;
   17.67 -
   17.68 -	struct usb_bus *bus;
   17.69 -
   17.70 -	/* Main list of URB's currently controlled by this HC */
   17.71 -	spinlock_t urb_list_lock;
   17.72 -	struct list_head urb_list;		/* P: xhci->urb_list_lock */
   17.73 -
   17.74 -	/* List of URB's awaiting completion callback */
   17.75 -	spinlock_t complete_list_lock;
   17.76 -	struct list_head complete_list;		/* P: xhci->complete_list_lock */
   17.77 -
   17.78 -	struct virt_root_hub rh;	/* private data of the virtual root hub */
   17.79 -
   17.80 -        usbif_front_ring_t usb_ring;
   17.81 -
   17.82 -        int awaiting_reset;
   17.83 -};
   17.84 -
   17.85 -/* per-URB private data structure for the host controller */
   17.86 -struct urb_priv {
   17.87 -	struct urb *urb;
   17.88 -        usbif_iso_t *schedule;
   17.89 -	struct usb_device *dev;
   17.90 -
   17.91 -        int in_progress : 1;	        /* QH was queued (not linked in) */
   17.92 -	int short_control_packet : 1;	/* If we get a short packet during */
   17.93 -					/*  a control transfer, retrigger */
   17.94 -					/*  the status phase */
   17.95 -
   17.96 -	int status;			/* Final status */
   17.97 -
   17.98 -	unsigned long inserttime;	/* In jiffies */
   17.99 -
  17.100 -	struct list_head complete_list;	/* P: xhci->complete_list_lock */
  17.101 -};
  17.102 -
  17.103 -/*
  17.104 - * Locking in xhci.c
  17.105 - *
  17.106 - * spinlocks are used extensively to protect the many lists and data
  17.107 - * structures we have. It's not that pretty, but it's necessary. We
  17.108 - * need to be done with all of the locks (except complete_list_lock) when
  17.109 - * we call urb->complete. I've tried to make it simple enough so I don't
  17.110 - * have to spend hours racking my brain trying to figure out if the
  17.111 - * locking is safe.
  17.112 - *
  17.113 - * Here's the safe locking order to prevent deadlocks:
  17.114 - *
  17.115 - * #1 xhci->urb_list_lock
  17.116 - * #2 urb->lock
  17.117 - * #3 xhci->urb_remove_list_lock
  17.118 - * #4 xhci->complete_list_lock
  17.119 - *
  17.120 - * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
  17.121 - * at the lowest level FIRST and NEVER grab locks at the same level at the
  17.122 - * same time.
  17.123 - * 
  17.124 - * So, if you need xhci->urb_list_lock, grab it before you grab urb->lock
  17.125 - */
  17.126 -
  17.127 -/* -------------------------------------------------------------------------
  17.128 -   Virtual Root HUB
  17.129 -   ------------------------------------------------------------------------- */
  17.130 -/* destination of request */
  17.131 -#define RH_DEVICE		0x00
  17.132 -#define RH_INTERFACE		0x01
  17.133 -#define RH_ENDPOINT		0x02
  17.134 -#define RH_OTHER		0x03
  17.135 -
  17.136 -#define RH_CLASS		0x20
  17.137 -#define RH_VENDOR		0x40
  17.138 -
  17.139 -/* Requests: bRequest << 8 | bmRequestType */
  17.140 -#define RH_GET_STATUS		0x0080
  17.141 -#define RH_CLEAR_FEATURE	0x0100
  17.142 -#define RH_SET_FEATURE		0x0300
  17.143 -#define RH_SET_ADDRESS		0x0500
  17.144 -#define RH_GET_DESCRIPTOR	0x0680
  17.145 -#define RH_SET_DESCRIPTOR	0x0700
  17.146 -#define RH_GET_CONFIGURATION	0x0880
  17.147 -#define RH_SET_CONFIGURATION	0x0900
  17.148 -#define RH_GET_STATE		0x0280
  17.149 -#define RH_GET_INTERFACE	0x0A80
  17.150 -#define RH_SET_INTERFACE	0x0B00
  17.151 -#define RH_SYNC_FRAME		0x0C80
  17.152 -/* Our Vendor Specific Request */
  17.153 -#define RH_SET_EP		0x2000
  17.154 -
  17.155 -/* Hub port features */
  17.156 -#define RH_PORT_CONNECTION	0x00
  17.157 -#define RH_PORT_ENABLE		0x01
  17.158 -#define RH_PORT_SUSPEND		0x02
  17.159 -#define RH_PORT_OVER_CURRENT	0x03
  17.160 -#define RH_PORT_RESET		0x04
  17.161 -#define RH_PORT_POWER		0x08
  17.162 -#define RH_PORT_LOW_SPEED	0x09
  17.163 -#define RH_C_PORT_CONNECTION	0x10
  17.164 -#define RH_C_PORT_ENABLE	0x11
  17.165 -#define RH_C_PORT_SUSPEND	0x12
  17.166 -#define RH_C_PORT_OVER_CURRENT	0x13
  17.167 -#define RH_C_PORT_RESET		0x14
  17.168 -
  17.169 -/* Hub features */
  17.170 -#define RH_C_HUB_LOCAL_POWER	0x00
  17.171 -#define RH_C_HUB_OVER_CURRENT	0x01
  17.172 -#define RH_DEVICE_REMOTE_WAKEUP	0x00
  17.173 -#define RH_ENDPOINT_STALL	0x01
  17.174 -
  17.175 -/* Our Vendor Specific feature */
  17.176 -#define RH_REMOVE_EP		0x00
  17.177 -
  17.178 -#define RH_ACK			0x01
  17.179 -#define RH_REQ_ERR		-1
  17.180 -#define RH_NACK			0x00
  17.181 -
  17.182 -#endif
  17.183 -
    18.1 --- a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h	Sat Mar 12 20:44:12 2005 +0000
    18.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.3 @@ -1,59 +0,0 @@
    18.4 -/* two abstractions specific to kernel/smpboot.c, mainly to cater to visws
    18.5 - * which needs to alter them. */
    18.6 -
    18.7 -static inline void smpboot_clear_io_apic_irqs(void)
    18.8 -{
    18.9 -#if 1
   18.10 -	printk("smpboot_clear_io_apic_irqs\n");
   18.11 -#else
   18.12 -	io_apic_irqs = 0;
   18.13 -#endif
   18.14 -}
   18.15 -
   18.16 -static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
   18.17 -{
   18.18 -#if 1
   18.19 -	printk("smpboot_setup_warm_reset_vector\n");
   18.20 -#else
   18.21 -	CMOS_WRITE(0xa, 0xf);
   18.22 -	local_flush_tlb();
   18.23 -	Dprintk("1.\n");
   18.24 -	*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
   18.25 -	Dprintk("2.\n");
   18.26 -	*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
   18.27 -	Dprintk("3.\n");
   18.28 -#endif
   18.29 -}
   18.30 -
   18.31 -static inline void smpboot_restore_warm_reset_vector(void)
   18.32 -{
   18.33 -	/*
   18.34 -	 * Install writable page 0 entry to set BIOS data area.
   18.35 -	 */
   18.36 -	local_flush_tlb();
   18.37 -
   18.38 -	/*
   18.39 -	 * Paranoid:  Set warm reset code and vector here back
   18.40 -	 * to default values.
   18.41 -	 */
   18.42 -	CMOS_WRITE(0, 0xf);
   18.43 -
   18.44 -	*((volatile long *) phys_to_virt(0x467)) = 0;
   18.45 -}
   18.46 -
   18.47 -static inline void smpboot_setup_io_apic(void)
   18.48 -{
   18.49 -#if 1
   18.50 -	printk("smpboot_setup_io_apic\n");
   18.51 -#else
   18.52 -	/*
   18.53 -	 * Here we can be sure that there is an IO-APIC in the system. Let's
   18.54 -	 * go and set it up:
   18.55 -	 */
   18.56 -	if (!skip_ioapic_setup && nr_ioapics)
   18.57 -		setup_IO_APIC();
   18.58 -#endif
   18.59 -}
   18.60 -
   18.61 -
   18.62 -#define	smp_found_config	(HYPERVISOR_shared_info->n_vcpu > 1)
    19.1 --- a/linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/spinlock.h	Sat Mar 12 20:44:12 2005 +0000
    19.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.3 @@ -1,224 +0,0 @@
    19.4 -#ifndef __ASM_SPINLOCK_H
    19.5 -#define __ASM_SPINLOCK_H
    19.6 -
    19.7 -#include <asm/atomic.h>
    19.8 -#include <asm/rwlock.h>
    19.9 -#include <asm/page.h>
   19.10 -#include <linux/config.h>
   19.11 -#include <linux/compiler.h>
   19.12 -
   19.13 -asmlinkage int printk(const char * fmt, ...)
   19.14 -	__attribute__ ((format (printf, 1, 2)));
   19.15 -
   19.16 -/*
   19.17 - * Your basic SMP spinlocks, allowing only a single CPU anywhere
   19.18 - */
   19.19 -
   19.20 -typedef struct {
   19.21 -	volatile unsigned int lock;
   19.22 -#ifdef CONFIG_DEBUG_SPINLOCK
   19.23 -	unsigned magic;
   19.24 -#endif
   19.25 -} spinlock_t;
   19.26 -
   19.27 -#define SPINLOCK_MAGIC	0xdead4ead
   19.28 -
   19.29 -#ifdef CONFIG_DEBUG_SPINLOCK
   19.30 -#define SPINLOCK_MAGIC_INIT	, SPINLOCK_MAGIC
   19.31 -#else
   19.32 -#define SPINLOCK_MAGIC_INIT	/* */
   19.33 -#endif
   19.34 -
   19.35 -#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT }
   19.36 -
   19.37 -#define spin_lock_init(x)	do { *(x) = SPIN_LOCK_UNLOCKED; } while(0)
   19.38 -
   19.39 -/*
   19.40 - * Simple spin lock operations.  There are two variants, one clears IRQ's
   19.41 - * on the local processor, one does not.
   19.42 - *
   19.43 - * We make no fairness assumptions. They have a cost.
   19.44 - */
   19.45 -
   19.46 -#define spin_is_locked(x)	(*(volatile signed char *)(&(x)->lock) <= 0)
   19.47 -#define spin_unlock_wait(x)	do { barrier(); } while(spin_is_locked(x))
   19.48 -
   19.49 -#define spin_lock_string \
   19.50 -	"\n1:\t" \
   19.51 -	"lock ; decb %0\n\t" \
   19.52 -	"jns 3f\n" \
   19.53 -	"2:\t" \
   19.54 -	"rep;nop\n\t" \
   19.55 -	"cmpb $0,%0\n\t" \
   19.56 -	"jle 2b\n\t" \
   19.57 -	"jmp 1b\n" \
   19.58 -	"3:\n\t"
   19.59 -
   19.60 -#define spin_lock_string_flags \
   19.61 -	"\n1:\t" \
   19.62 -	"lock ; decb %0\n\t" \
   19.63 -	"jns 4f\n\t" \
   19.64 -	"2:\t" \
   19.65 -	"testl $0x200, %1\n\t" \
   19.66 -	"jz 3f\n\t" \
   19.67 -	"#sti\n\t" \
   19.68 -	"3:\t" \
   19.69 -	"rep;nop\n\t" \
   19.70 -	"cmpb $0, %0\n\t" \
   19.71 -	"jle 3b\n\t" \
   19.72 -	"#cli\n\t" \
   19.73 -	"jmp 1b\n" \
   19.74 -	"4:\n\t"
   19.75 -
   19.76 -/*
   19.77 - * This works. Despite all the confusion.
   19.78 - * (except on PPro SMP or if we are using OOSTORE)
   19.79 - * (PPro errata 66, 92)
   19.80 - */
   19.81 - 
   19.82 -#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE)
   19.83 -
   19.84 -#define spin_unlock_string \
   19.85 -	"movb $1,%0" \
   19.86 -		:"=m" (lock->lock) : : "memory"
   19.87 -
   19.88 -
   19.89 -static inline void _raw_spin_unlock(spinlock_t *lock)
   19.90 -{
   19.91 -#ifdef CONFIG_DEBUG_SPINLOCK
   19.92 -	BUG_ON(lock->magic != SPINLOCK_MAGIC);
   19.93 -	BUG_ON(!spin_is_locked(lock));
   19.94 -#endif
   19.95 -	__asm__ __volatile__(
   19.96 -		spin_unlock_string
   19.97 -	);
   19.98 -}
   19.99 -
  19.100 -#else
  19.101 -
  19.102 -#define spin_unlock_string \
  19.103 -	"xchgb %b0, %1" \
  19.104 -		:"=q" (oldval), "=m" (lock->lock) \
  19.105 -		:"0" (oldval) : "memory"
  19.106 -
  19.107 -static inline void _raw_spin_unlock(spinlock_t *lock)
  19.108 -{
  19.109 -	char oldval = 1;
  19.110 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.111 -	BUG_ON(lock->magic != SPINLOCK_MAGIC);
  19.112 -	BUG_ON(!spin_is_locked(lock));
  19.113 -#endif
  19.114 -	__asm__ __volatile__(
  19.115 -		spin_unlock_string
  19.116 -	);
  19.117 -}
  19.118 -
  19.119 -#endif
  19.120 -
  19.121 -static inline int _raw_spin_trylock(spinlock_t *lock)
  19.122 -{
  19.123 -	char oldval;
  19.124 -	__asm__ __volatile__(
  19.125 -		"xchgb %b0,%1"
  19.126 -		:"=q" (oldval), "=m" (lock->lock)
  19.127 -		:"0" (0) : "memory");
  19.128 -	return oldval > 0;
  19.129 -}
  19.130 -
  19.131 -static inline void _raw_spin_lock(spinlock_t *lock)
  19.132 -{
  19.133 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.134 -	if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
  19.135 -		printk("eip: %p\n", __builtin_return_address(0));
  19.136 -		BUG();
  19.137 -	}
  19.138 -#endif
  19.139 -	__asm__ __volatile__(
  19.140 -		spin_lock_string
  19.141 -		:"=m" (lock->lock) : : "memory");
  19.142 -}
  19.143 -
  19.144 -static inline void _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags)
  19.145 -{
  19.146 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.147 -	if (unlikely(lock->magic != SPINLOCK_MAGIC)) {
  19.148 -		printk("eip: %p\n", __builtin_return_address(0));
  19.149 -		BUG();
  19.150 -	}
  19.151 -#endif
  19.152 -	__asm__ __volatile__(
  19.153 -		spin_lock_string_flags
  19.154 -		:"=m" (lock->lock) : "r" (flags) : "memory");
  19.155 -}
  19.156 -
  19.157 -/*
  19.158 - * Read-write spinlocks, allowing multiple readers
  19.159 - * but only one writer.
  19.160 - *
  19.161 - * NOTE! it is quite common to have readers in interrupts
  19.162 - * but no interrupt writers. For those circumstances we
  19.163 - * can "mix" irq-safe locks - any writer needs to get a
  19.164 - * irq-safe write-lock, but readers can get non-irqsafe
  19.165 - * read-locks.
  19.166 - */
  19.167 -typedef struct {
  19.168 -	volatile unsigned int lock;
  19.169 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.170 -	unsigned magic;
  19.171 -#endif
  19.172 -} rwlock_t;
  19.173 -
  19.174 -#define RWLOCK_MAGIC	0xdeaf1eed
  19.175 -
  19.176 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.177 -#define RWLOCK_MAGIC_INIT	, RWLOCK_MAGIC
  19.178 -#else
  19.179 -#define RWLOCK_MAGIC_INIT	/* */
  19.180 -#endif
  19.181 -
  19.182 -#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT }
  19.183 -
  19.184 -#define rwlock_init(x)	do { *(x) = RW_LOCK_UNLOCKED; } while(0)
  19.185 -
  19.186 -#define rwlock_is_locked(x) ((x)->lock != RW_LOCK_BIAS)
  19.187 -
  19.188 -/*
  19.189 - * On x86, we implement read-write locks as a 32-bit counter
  19.190 - * with the high bit (sign) being the "contended" bit.
  19.191 - *
  19.192 - * The inline assembly is non-obvious. Think about it.
  19.193 - *
  19.194 - * Changed to use the same technique as rw semaphores.  See
  19.195 - * semaphore.h for details.  -ben
  19.196 - */
  19.197 -/* the spinlock helpers are in arch/i386/kernel/semaphore.c */
  19.198 -
  19.199 -static inline void _raw_read_lock(rwlock_t *rw)
  19.200 -{
  19.201 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.202 -	BUG_ON(rw->magic != RWLOCK_MAGIC);
  19.203 -#endif
  19.204 -	__build_read_lock(rw, "__read_lock_failed");
  19.205 -}
  19.206 -
  19.207 -static inline void _raw_write_lock(rwlock_t *rw)
  19.208 -{
  19.209 -#ifdef CONFIG_DEBUG_SPINLOCK
  19.210 -	BUG_ON(rw->magic != RWLOCK_MAGIC);
  19.211 -#endif
  19.212 -	__build_write_lock(rw, "__write_lock_failed");
  19.213 -}
  19.214 -
  19.215 -#define _raw_read_unlock(rw)		asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
  19.216 -#define _raw_write_unlock(rw)	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
  19.217 -
  19.218 -static inline int _raw_write_trylock(rwlock_t *lock)
  19.219 -{
  19.220 -	atomic_t *count = (atomic_t *)lock;
  19.221 -	if (atomic_sub_and_test(RW_LOCK_BIAS, count))
  19.222 -		return 1;
  19.223 -	atomic_add(RW_LOCK_BIAS, count);
  19.224 -	return 0;
  19.225 -}
  19.226 -
  19.227 -#endif /* __ASM_SPINLOCK_H */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/irq.c	Sat Mar 12 21:16:57 2005 +0000
    20.3 @@ -0,0 +1,258 @@
    20.4 +/*
    20.5 + *	linux/arch/i386/kernel/irq.c
    20.6 + *
    20.7 + *	Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
    20.8 + *
    20.9 + * This file contains the lowest level x86-specific interrupt
   20.10 + * entry, irq-stacks and irq statistics code. All the remaining
   20.11 + * irq logic is done by the generic kernel/irq/ code and
   20.12 + * by the x86-specific irq controller code. (e.g. i8259.c and
   20.13 + * io_apic.c.)
   20.14 + */
   20.15 +
   20.16 +#include <asm/uaccess.h>
   20.17 +#include <linux/module.h>
   20.18 +#include <linux/seq_file.h>
   20.19 +#include <linux/interrupt.h>
   20.20 +#include <linux/kernel_stat.h>
   20.21 +
   20.22 +#ifndef CONFIG_X86_LOCAL_APIC
   20.23 +/*
   20.24 + * 'what should we do if we get a hw irq event on an illegal vector'.
   20.25 + * each architecture has to answer this themselves.
   20.26 + */
   20.27 +void ack_bad_irq(unsigned int irq)
   20.28 +{
   20.29 +	printk("unexpected IRQ trap at vector %02x\n", irq);
   20.30 +}
   20.31 +#endif
   20.32 +
   20.33 +#ifdef CONFIG_4KSTACKS
   20.34 +/*
   20.35 + * per-CPU IRQ handling contexts (thread information and stack)
   20.36 + */
   20.37 +union irq_ctx {
   20.38 +	struct thread_info      tinfo;
   20.39 +	u32                     stack[THREAD_SIZE/sizeof(u32)];
   20.40 +};
   20.41 +
   20.42 +static union irq_ctx *hardirq_ctx[NR_CPUS];
   20.43 +static union irq_ctx *softirq_ctx[NR_CPUS];
   20.44 +#endif
   20.45 +
   20.46 +/*
   20.47 + * do_IRQ handles all normal device IRQ's (the special
   20.48 + * SMP cross-CPU interrupts have their own specific
   20.49 + * handlers).
   20.50 + */
   20.51 +fastcall unsigned int do_IRQ(struct pt_regs *regs)
   20.52 +{	
   20.53 +	/* high bits used in ret_from_ code */
   20.54 +	int irq = regs->orig_eax & __IRQ_MASK(HARDIRQ_BITS);
   20.55 +#ifdef CONFIG_4KSTACKS
   20.56 +	union irq_ctx *curctx, *irqctx;
   20.57 +	u32 *isp;
   20.58 +#endif
   20.59 +
   20.60 +	irq_enter();
   20.61 +#ifdef CONFIG_DEBUG_STACKOVERFLOW
   20.62 +	/* Debugging check for stack overflow: is there less than 1KB free? */
   20.63 +	{
   20.64 +		long esp;
   20.65 +
   20.66 +		__asm__ __volatile__("andl %%esp,%0" :
   20.67 +					"=r" (esp) : "0" (THREAD_SIZE - 1));
   20.68 +		if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
   20.69 +			printk("do_IRQ: stack overflow: %ld\n",
   20.70 +				esp - sizeof(struct thread_info));
   20.71 +			dump_stack();
   20.72 +		}
   20.73 +	}
   20.74 +#endif
   20.75 +
   20.76 +#ifdef CONFIG_4KSTACKS
   20.77 +
   20.78 +	curctx = (union irq_ctx *) current_thread_info();
   20.79 +	irqctx = hardirq_ctx[smp_processor_id()];
   20.80 +
   20.81 +	/*
   20.82 +	 * this is where we switch to the IRQ stack. However, if we are
   20.83 +	 * already using the IRQ stack (because we interrupted a hardirq
   20.84 +	 * handler) we can't do that and just have to keep using the
   20.85 +	 * current stack (which is the irq stack already after all)
   20.86 +	 */
   20.87 +	if (curctx != irqctx) {
   20.88 +		int arg1, arg2, ebx;
   20.89 +
   20.90 +		/* build the stack frame on the IRQ stack */
   20.91 +		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
   20.92 +		irqctx->tinfo.task = curctx->tinfo.task;
   20.93 +		irqctx->tinfo.previous_esp = current_stack_pointer;
   20.94 +
   20.95 +		asm volatile(
   20.96 +			"       xchgl   %%ebx,%%esp      \n"
   20.97 +			"       call    __do_IRQ         \n"
   20.98 +			"       movl   %%ebx,%%esp      \n"
   20.99 +			: "=a" (arg1), "=d" (arg2), "=b" (ebx)
  20.100 +			:  "0" (irq),   "1" (regs),  "2" (isp)
  20.101 +			: "memory", "cc", "ecx"
  20.102 +		);
  20.103 +	} else
  20.104 +#endif
  20.105 +		__do_IRQ(irq, regs);
  20.106 +
  20.107 +	irq_exit();
  20.108 +
  20.109 +	return 1;
  20.110 +}
  20.111 +
  20.112 +#ifdef CONFIG_4KSTACKS
  20.113 +
  20.114 +/*
  20.115 + * These should really be __section__(".bss.page_aligned") as well, but
  20.116 + * gcc's 3.0 and earlier don't handle that correctly.
  20.117 + */
  20.118 +static char softirq_stack[NR_CPUS * THREAD_SIZE]
  20.119 +		__attribute__((__aligned__(THREAD_SIZE)));
  20.120 +
  20.121 +static char hardirq_stack[NR_CPUS * THREAD_SIZE]
  20.122 +		__attribute__((__aligned__(THREAD_SIZE)));
  20.123 +
  20.124 +/*
  20.125 + * allocate per-cpu stacks for hardirq and for softirq processing
  20.126 + */
  20.127 +void irq_ctx_init(int cpu)
  20.128 +{
  20.129 +	union irq_ctx *irqctx;
  20.130 +
  20.131 +	if (hardirq_ctx[cpu])
  20.132 +		return;
  20.133 +
  20.134 +	irqctx = (union irq_ctx*) &hardirq_stack[cpu*THREAD_SIZE];
  20.135 +	irqctx->tinfo.task              = NULL;
  20.136 +	irqctx->tinfo.exec_domain       = NULL;
  20.137 +	irqctx->tinfo.cpu               = cpu;
  20.138 +	irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;
  20.139 +	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
  20.140 +
  20.141 +	hardirq_ctx[cpu] = irqctx;
  20.142 +
  20.143 +	irqctx = (union irq_ctx*) &softirq_stack[cpu*THREAD_SIZE];
  20.144 +	irqctx->tinfo.task              = NULL;
  20.145 +	irqctx->tinfo.exec_domain       = NULL;
  20.146 +	irqctx->tinfo.cpu               = cpu;
  20.147 +	irqctx->tinfo.preempt_count     = SOFTIRQ_OFFSET;
  20.148 +	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
  20.149 +
  20.150 +	softirq_ctx[cpu] = irqctx;
  20.151 +
  20.152 +	printk("CPU %u irqstacks, hard=%p soft=%p\n",
  20.153 +		cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
  20.154 +}
  20.155 +
  20.156 +extern asmlinkage void __do_softirq(void);
  20.157 +
  20.158 +asmlinkage void do_softirq(void)
  20.159 +{
  20.160 +	unsigned long flags;
  20.161 +	struct thread_info *curctx;
  20.162 +	union irq_ctx *irqctx;
  20.163 +	u32 *isp;
  20.164 +
  20.165 +	if (in_interrupt())
  20.166 +		return;
  20.167 +
  20.168 +	local_irq_save(flags);
  20.169 +
  20.170 +	if (local_softirq_pending()) {
  20.171 +		curctx = current_thread_info();
  20.172 +		irqctx = softirq_ctx[smp_processor_id()];
  20.173 +		irqctx->tinfo.task = curctx->task;
  20.174 +		irqctx->tinfo.previous_esp = current_stack_pointer;
  20.175 +
  20.176 +		/* build the stack frame on the softirq stack */
  20.177 +		isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
  20.178 +
  20.179 +		asm volatile(
  20.180 +			"       xchgl   %%ebx,%%esp     \n"
  20.181 +			"       call    __do_softirq    \n"
  20.182 +			"       movl    %%ebx,%%esp     \n"
  20.183 +			: "=b"(isp)
  20.184 +			: "0"(isp)
  20.185 +			: "memory", "cc", "edx", "ecx", "eax"
  20.186 +		);
  20.187 +	}
  20.188 +
  20.189 +	local_irq_restore(flags);
  20.190 +}
  20.191 +
  20.192 +EXPORT_SYMBOL(do_softirq);
  20.193 +#endif
  20.194 +
  20.195 +/*
  20.196 + * Interrupt statistics:
  20.197 + */
  20.198 +
  20.199 +atomic_t irq_err_count;
  20.200 +
  20.201 +/*
  20.202 + * /proc/interrupts printing:
  20.203 + */
  20.204 +
  20.205 +int show_interrupts(struct seq_file *p, void *v)
  20.206 +{
  20.207 +	int i = *(loff_t *) v, j;
  20.208 +	struct irqaction * action;
  20.209 +	unsigned long flags;
  20.210 +
  20.211 +	if (i == 0) {
  20.212 +		seq_printf(p, "           ");
  20.213 +		for (j=0; j<NR_CPUS; j++)
  20.214 +			if (cpu_online(j))
  20.215 +				seq_printf(p, "CPU%d       ",j);
  20.216 +		seq_putc(p, '\n');
  20.217 +	}
  20.218 +
  20.219 +	if (i < NR_IRQS) {
  20.220 +		spin_lock_irqsave(&irq_desc[i].lock, flags);
  20.221 +		action = irq_desc[i].action;
  20.222 +		if (!action)
  20.223 +			goto skip;
  20.224 +		seq_printf(p, "%3d: ",i);
  20.225 +#ifndef CONFIG_SMP
  20.226 +		seq_printf(p, "%10u ", kstat_irqs(i));
  20.227 +#else
  20.228 +		for (j = 0; j < NR_CPUS; j++)
  20.229 +			if (cpu_online(j))
  20.230 +				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
  20.231 +#endif
  20.232 +		seq_printf(p, " %14s", irq_desc[i].handler->typename);
  20.233 +		seq_printf(p, "  %s", action->name);
  20.234 +
  20.235 +		for (action=action->next; action; action = action->next)
  20.236 +			seq_printf(p, ", %s", action->name);
  20.237 +
  20.238 +		seq_putc(p, '\n');
  20.239 +skip:
  20.240 +		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
  20.241 +	} else if (i == NR_IRQS) {
  20.242 +		seq_printf(p, "NMI: ");
  20.243 +		for (j = 0; j < NR_CPUS; j++)
  20.244 +			if (cpu_online(j))
  20.245 +				seq_printf(p, "%10u ", nmi_count(j));
  20.246 +		seq_putc(p, '\n');
  20.247 +#ifdef CONFIG_X86_LOCAL_APIC
  20.248 +		seq_printf(p, "LOC: ");
  20.249 +		for (j = 0; j < NR_CPUS; j++)
  20.250 +			if (cpu_online(j))
  20.251 +				seq_printf(p, "%10u ",
  20.252 +					irq_stat[j].apic_timer_irqs);
  20.253 +		seq_putc(p, '\n');
  20.254 +#endif
  20.255 +		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
  20.256 +#if defined(CONFIG_X86_IO_APIC)
  20.257 +		seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
  20.258 +#endif
  20.259 +	}
  20.260 +	return 0;
  20.261 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smp.c	Sat Mar 12 21:16:57 2005 +0000
    21.3 @@ -0,0 +1,599 @@
    21.4 +/*
    21.5 + *	Intel SMP support routines.
    21.6 + *
    21.7 + *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
    21.8 + *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
    21.9 + *
   21.10 + *	This code is released under the GNU General Public License version 2 or
   21.11 + *	later.
   21.12 + */
   21.13 +
   21.14 +#include <linux/init.h>
   21.15 +
   21.16 +#include <linux/mm.h>
   21.17 +#include <linux/irq.h>
   21.18 +#include <linux/delay.h>
   21.19 +#include <linux/spinlock.h>
   21.20 +#include <linux/smp_lock.h>
   21.21 +#include <linux/kernel_stat.h>
   21.22 +#include <linux/mc146818rtc.h>
   21.23 +#include <linux/cache.h>
   21.24 +#include <linux/interrupt.h>
   21.25 +
   21.26 +#include <asm/mtrr.h>
   21.27 +#include <asm/tlbflush.h>
   21.28 +#if 0
   21.29 +#include <mach_apic.h>
   21.30 +#endif
   21.31 +#include <asm-xen/evtchn.h>
   21.32 +
   21.33 +#define xxprint(msg) HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg), msg)
   21.34 +
   21.35 +/*
   21.36 + *	Some notes on x86 processor bugs affecting SMP operation:
   21.37 + *
   21.38 + *	Pentium, Pentium Pro, II, III (and all CPUs) have bugs.
   21.39 + *	The Linux implications for SMP are handled as follows:
   21.40 + *
   21.41 + *	Pentium III / [Xeon]
   21.42 + *		None of the E1AP-E3AP errata are visible to the user.
   21.43 + *
   21.44 + *	E1AP.	see PII A1AP
   21.45 + *	E2AP.	see PII A2AP
   21.46 + *	E3AP.	see PII A3AP
   21.47 + *
   21.48 + *	Pentium II / [Xeon]
   21.49 + *		None of the A1AP-A3AP errata are visible to the user.
   21.50 + *
   21.51 + *	A1AP.	see PPro 1AP
   21.52 + *	A2AP.	see PPro 2AP
   21.53 + *	A3AP.	see PPro 7AP
   21.54 + *
   21.55 + *	Pentium Pro
   21.56 + *		None of 1AP-9AP errata are visible to the normal user,
   21.57 + *	except occasional delivery of 'spurious interrupt' as trap #15.
   21.58 + *	This is very rare and a non-problem.
   21.59 + *
   21.60 + *	1AP.	Linux maps APIC as non-cacheable
   21.61 + *	2AP.	worked around in hardware
   21.62 + *	3AP.	fixed in C0 and above steppings microcode update.
   21.63 + *		Linux does not use excessive STARTUP_IPIs.
   21.64 + *	4AP.	worked around in hardware
   21.65 + *	5AP.	symmetric IO mode (normal Linux operation) not affected.
   21.66 + *		'noapic' mode has vector 0xf filled out properly.
   21.67 + *	6AP.	'noapic' mode might be affected - fixed in later steppings
   21.68 + *	7AP.	We do not assume writes to the LVT deassering IRQs
   21.69 + *	8AP.	We do not enable low power mode (deep sleep) during MP bootup
   21.70 + *	9AP.	We do not use mixed mode
   21.71 + *
   21.72 + *	Pentium
   21.73 + *		There is a marginal case where REP MOVS on 100MHz SMP
   21.74 + *	machines with B stepping processors can fail. XXX should provide
   21.75 + *	an L1cache=Writethrough or L1cache=off option.
   21.76 + *
   21.77 + *		B stepping CPUs may hang. There are hardware work arounds
   21.78 + *	for this. We warn about it in case your board doesn't have the work
   21.79 + *	arounds. Basically thats so I can tell anyone with a B stepping
   21.80 + *	CPU and SMP problems "tough".
   21.81 + *
   21.82 + *	Specific items [From Pentium Processor Specification Update]
   21.83 + *
   21.84 + *	1AP.	Linux doesn't use remote read
   21.85 + *	2AP.	Linux doesn't trust APIC errors
   21.86 + *	3AP.	We work around this
   21.87 + *	4AP.	Linux never generated 3 interrupts of the same priority
   21.88 + *		to cause a lost local interrupt.
   21.89 + *	5AP.	Remote read is never used
   21.90 + *	6AP.	not affected - worked around in hardware
   21.91 + *	7AP.	not affected - worked around in hardware
   21.92 + *	8AP.	worked around in hardware - we get explicit CS errors if not
   21.93 + *	9AP.	only 'noapic' mode affected. Might generate spurious
   21.94 + *		interrupts, we log only the first one and count the
   21.95 + *		rest silently.
   21.96 + *	10AP.	not affected - worked around in hardware
   21.97 + *	11AP.	Linux reads the APIC between writes to avoid this, as per
   21.98 + *		the documentation. Make sure you preserve this as it affects
   21.99 + *		the C stepping chips too.
  21.100 + *	12AP.	not affected - worked around in hardware
  21.101 + *	13AP.	not affected - worked around in hardware
  21.102 + *	14AP.	we always deassert INIT during bootup
  21.103 + *	15AP.	not affected - worked around in hardware
  21.104 + *	16AP.	not affected - worked around in hardware
  21.105 + *	17AP.	not affected - worked around in hardware
  21.106 + *	18AP.	not affected - worked around in hardware
  21.107 + *	19AP.	not affected - worked around in BIOS
  21.108 + *
  21.109 + *	If this sounds worrying believe me these bugs are either ___RARE___,
  21.110 + *	or are signal timing bugs worked around in hardware and there's
  21.111 + *	about nothing of note with C stepping upwards.
  21.112 + */
  21.113 +
  21.114 +DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) ____cacheline_aligned = { &init_mm, 0, };
  21.115 +
  21.116 +/*
  21.117 + * the following functions deal with sending IPIs between CPUs.
  21.118 + *
  21.119 + * We use 'broadcast', CPU->CPU IPIs and self-IPIs too.
  21.120 + */
  21.121 +
  21.122 +static inline int __prepare_ICR (unsigned int shortcut, int vector)
  21.123 +{
  21.124 +	return APIC_DM_FIXED | shortcut | vector | APIC_DEST_LOGICAL;
  21.125 +}
  21.126 +
  21.127 +static inline int __prepare_ICR2 (unsigned int mask)
  21.128 +{
  21.129 +	return SET_APIC_DEST_FIELD(mask);
  21.130 +}
  21.131 +
  21.132 +DECLARE_PER_CPU(int, ipi_to_evtchn[NR_IPIS]);
  21.133 +
  21.134 +static inline void __send_IPI_one(unsigned int cpu, int vector)
  21.135 +{
  21.136 +	unsigned int evtchn;
  21.137 +
  21.138 +	evtchn = per_cpu(ipi_to_evtchn, cpu)[vector];
  21.139 +	// printk("send_IPI_mask_bitmask cpu %d vector %d evtchn %d\n", cpu, vector, evtchn);
  21.140 +	if (evtchn) {
  21.141 +#if 0
  21.142 +		shared_info_t *s = HYPERVISOR_shared_info;
  21.143 +		while (synch_test_bit(evtchn, &s->evtchn_pending[0]) ||
  21.144 +		       synch_test_bit(evtchn, &s->evtchn_mask[0]))
  21.145 +			;
  21.146 +#endif
  21.147 +		notify_via_evtchn(evtchn);
  21.148 +	} else
  21.149 +		printk("send_IPI to unbound port %d/%d",
  21.150 +		       cpu, vector);
  21.151 +}
  21.152 +
  21.153 +void __send_IPI_shortcut(unsigned int shortcut, int vector)
  21.154 +{
  21.155 +	int cpu;
  21.156 +
  21.157 +	switch (shortcut) {
  21.158 +	case APIC_DEST_SELF:
  21.159 +		__send_IPI_one(smp_processor_id(), vector);
  21.160 +		break;
  21.161 +	case APIC_DEST_ALLBUT:
  21.162 +		for (cpu = 0; cpu < NR_CPUS; ++cpu) {
  21.163 +			if (cpu == smp_processor_id())
  21.164 +				continue;
  21.165 +			if (cpu_isset(cpu, cpu_online_map)) {
  21.166 +				__send_IPI_one(cpu, vector);
  21.167 +			}
  21.168 +		}
  21.169 +		break;
  21.170 +	default:
  21.171 +		printk("XXXXXX __send_IPI_shortcut %08x vector %d\n", shortcut,
  21.172 +		       vector);
  21.173 +		break;
  21.174 +	}
  21.175 +}
  21.176 +
  21.177 +void fastcall send_IPI_self(int vector)
  21.178 +{
  21.179 +	__send_IPI_shortcut(APIC_DEST_SELF, vector);
  21.180 +}
  21.181 +
  21.182 +/*
  21.183 + * This is only used on smaller machines.
  21.184 + */
  21.185 +void send_IPI_mask_bitmask(cpumask_t mask, int vector)
  21.186 +{
  21.187 +	unsigned long flags;
  21.188 +	unsigned int cpu;
  21.189 +
  21.190 +	local_irq_save(flags);
  21.191 +
  21.192 +	for (cpu = 0; cpu < NR_CPUS; ++cpu) {
  21.193 +		if (cpu_isset(cpu, mask)) {
  21.194 +			__send_IPI_one(cpu, vector);
  21.195 +		}
  21.196 +	}
  21.197 +
  21.198 +	local_irq_restore(flags);
  21.199 +}
  21.200 +
  21.201 +inline void send_IPI_mask_sequence(cpumask_t mask, int vector)
  21.202 +{
  21.203 +
  21.204 +	send_IPI_mask_bitmask(mask, vector);
  21.205 +}
  21.206 +
  21.207 +#include <mach_ipi.h> /* must come after the send_IPI functions above for inlining */
  21.208 +
  21.209 +/*
  21.210 + *	Smarter SMP flushing macros. 
  21.211 + *		c/o Linus Torvalds.
  21.212 + *
  21.213 + *	These mean you can really definitely utterly forget about
  21.214 + *	writing to user space from interrupts. (Its not allowed anyway).
  21.215 + *
  21.216 + *	Optimizations Manfred Spraul <manfred@colorfullife.com>
  21.217 + */
  21.218 +
  21.219 +static cpumask_t flush_cpumask;
  21.220 +static struct mm_struct * flush_mm;
  21.221 +static unsigned long flush_va;
  21.222 +static DEFINE_SPINLOCK(tlbstate_lock);
  21.223 +#define FLUSH_ALL	0xffffffff
  21.224 +
  21.225 +/*
  21.226 + * We cannot call mmdrop() because we are in interrupt context, 
  21.227 + * instead update mm->cpu_vm_mask.
  21.228 + *
  21.229 + * We need to reload %cr3 since the page tables may be going
  21.230 + * away from under us..
  21.231 + */
  21.232 +static inline void leave_mm (unsigned long cpu)
  21.233 +{
  21.234 +	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
  21.235 +		BUG();
  21.236 +	cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
  21.237 +	load_cr3(swapper_pg_dir);
  21.238 +}
  21.239 +
  21.240 +/*
  21.241 + *
  21.242 + * The flush IPI assumes that a thread switch happens in this order:
  21.243 + * [cpu0: the cpu that switches]
  21.244 + * 1) switch_mm() either 1a) or 1b)
  21.245 + * 1a) thread switch to a different mm
  21.246 + * 1a1) cpu_clear(cpu, old_mm->cpu_vm_mask);
  21.247 + * 	Stop ipi delivery for the old mm. This is not synchronized with
  21.248 + * 	the other cpus, but smp_invalidate_interrupt ignore flush ipis
  21.249 + * 	for the wrong mm, and in the worst case we perform a superflous
  21.250 + * 	tlb flush.
  21.251 + * 1a2) set cpu_tlbstate to TLBSTATE_OK
  21.252 + * 	Now the smp_invalidate_interrupt won't call leave_mm if cpu0
  21.253 + *	was in lazy tlb mode.
  21.254 + * 1a3) update cpu_tlbstate[].active_mm
  21.255 + * 	Now cpu0 accepts tlb flushes for the new mm.
  21.256 + * 1a4) cpu_set(cpu, new_mm->cpu_vm_mask);
  21.257 + * 	Now the other cpus will send tlb flush ipis.
  21.258 + * 1a4) change cr3.
  21.259 + * 1b) thread switch without mm change
  21.260 + *	cpu_tlbstate[].active_mm is correct, cpu0 already handles
  21.261 + *	flush ipis.
  21.262 + * 1b1) set cpu_tlbstate to TLBSTATE_OK
  21.263 + * 1b2) test_and_set the cpu bit in cpu_vm_mask.
  21.264 + * 	Atomically set the bit [other cpus will start sending flush ipis],
  21.265 + * 	and test the bit.
  21.266 + * 1b3) if the bit was 0: leave_mm was called, flush the tlb.
  21.267 + * 2) switch %%esp, ie current
  21.268 + *
  21.269 + * The interrupt must handle 2 special cases:
  21.270 + * - cr3 is changed before %%esp, ie. it cannot use current->{active_,}mm.
  21.271 + * - the cpu performs speculative tlb reads, i.e. even if the cpu only
  21.272 + *   runs in kernel space, the cpu could load tlb entries for user space
  21.273 + *   pages.
  21.274 + *
  21.275 + * The good news is that cpu_tlbstate is local to each cpu, no
  21.276 + * write/read ordering problems.
  21.277 + */
  21.278 +
  21.279 +/*
  21.280 + * TLB flush IPI:
  21.281 + *
  21.282 + * 1) Flush the tlb entries if the cpu uses the mm that's being flushed.
  21.283 + * 2) Leave the mm if we are in the lazy tlb mode.
  21.284 + */
  21.285 +
  21.286 +irqreturn_t smp_invalidate_interrupt(int irq, void *dev_id,
  21.287 +				     struct pt_regs *regs)
  21.288 +{
  21.289 +	unsigned long cpu;
  21.290 +
  21.291 +	cpu = get_cpu();
  21.292 +
  21.293 +	if (!cpu_isset(cpu, flush_cpumask))
  21.294 +		goto out;
  21.295 +		/* 
  21.296 +		 * This was a BUG() but until someone can quote me the
  21.297 +		 * line from the intel manual that guarantees an IPI to
  21.298 +		 * multiple CPUs is retried _only_ on the erroring CPUs
  21.299 +		 * its staying as a return
  21.300 +		 *
  21.301 +		 * BUG();
  21.302 +		 */
  21.303 +		 
  21.304 +	if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
  21.305 +		if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
  21.306 +			if (flush_va == FLUSH_ALL)
  21.307 +				local_flush_tlb();
  21.308 +			else
  21.309 +				__flush_tlb_one(flush_va);
  21.310 +		} else
  21.311 +			leave_mm(cpu);
  21.312 +	}
  21.313 +	smp_mb__before_clear_bit();
  21.314 +	cpu_clear(cpu, flush_cpumask);
  21.315 +	smp_mb__after_clear_bit();
  21.316 +out:
  21.317 +	put_cpu_no_resched();
  21.318 +
  21.319 +	return IRQ_HANDLED;
  21.320 +}
  21.321 +
  21.322 +static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
  21.323 +						unsigned long va)
  21.324 +{
  21.325 +	cpumask_t tmp;
  21.326 +	/*
  21.327 +	 * A couple of (to be removed) sanity checks:
  21.328 +	 *
  21.329 +	 * - we do not send IPIs to not-yet booted CPUs.
  21.330 +	 * - current CPU must not be in mask
  21.331 +	 * - mask must exist :)
  21.332 +	 */
  21.333 +	BUG_ON(cpus_empty(cpumask));
  21.334 +
  21.335 +	cpus_and(tmp, cpumask, cpu_online_map);
  21.336 +	BUG_ON(!cpus_equal(cpumask, tmp));
  21.337 +	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
  21.338 +	BUG_ON(!mm);
  21.339 +
  21.340 +	/*
  21.341 +	 * i'm not happy about this global shared spinlock in the
  21.342 +	 * MM hot path, but we'll see how contended it is.
  21.343 +	 * Temporarily this turns IRQs off, so that lockups are
  21.344 +	 * detected by the NMI watchdog.
  21.345 +	 */
  21.346 +	spin_lock(&tlbstate_lock);
  21.347 +	
  21.348 +	flush_mm = mm;
  21.349 +	flush_va = va;
  21.350 +#if NR_CPUS <= BITS_PER_LONG
  21.351 +	atomic_set_mask(cpumask, &flush_cpumask);
  21.352 +#else
  21.353 +	{
  21.354 +		int k;
  21.355 +		unsigned long *flush_mask = (unsigned long *)&flush_cpumask;
  21.356 +		unsigned long *cpu_mask = (unsigned long *)&cpumask;
  21.357 +		for (k = 0; k < BITS_TO_LONGS(NR_CPUS); ++k)
  21.358 +			atomic_set_mask(cpu_mask[k], &flush_mask[k]);
  21.359 +	}
  21.360 +#endif
  21.361 +	/*
  21.362 +	 * We have to send the IPI only to
  21.363 +	 * CPUs affected.
  21.364 +	 */
  21.365 +	send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR);
  21.366 +
  21.367 +	while (!cpus_empty(flush_cpumask))
  21.368 +		/* nothing. lockup detection does not belong here */
  21.369 +		mb();
  21.370 +
  21.371 +	flush_mm = NULL;
  21.372 +	flush_va = 0;
  21.373 +	spin_unlock(&tlbstate_lock);
  21.374 +}
  21.375 +	
  21.376 +void flush_tlb_current_task(void)
  21.377 +{
  21.378 +	struct mm_struct *mm = current->mm;
  21.379 +	cpumask_t cpu_mask;
  21.380 +
  21.381 +	preempt_disable();
  21.382 +	cpu_mask = mm->cpu_vm_mask;
  21.383 +	cpu_clear(smp_processor_id(), cpu_mask);
  21.384 +
  21.385 +	local_flush_tlb();
  21.386 +	if (!cpus_empty(cpu_mask))
  21.387 +		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
  21.388 +	preempt_enable();
  21.389 +}
  21.390 +
  21.391 +void flush_tlb_mm (struct mm_struct * mm)
  21.392 +{
  21.393 +	cpumask_t cpu_mask;
  21.394 +
  21.395 +	preempt_disable();
  21.396 +	cpu_mask = mm->cpu_vm_mask;
  21.397 +	cpu_clear(smp_processor_id(), cpu_mask);
  21.398 +
  21.399 +	if (current->active_mm == mm) {
  21.400 +		if (current->mm)
  21.401 +			local_flush_tlb();
  21.402 +		else
  21.403 +			leave_mm(smp_processor_id());
  21.404 +	}
  21.405 +	if (!cpus_empty(cpu_mask))
  21.406 +		flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
  21.407 +
  21.408 +	preempt_enable();
  21.409 +}
  21.410 +
  21.411 +void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
  21.412 +{
  21.413 +	struct mm_struct *mm = vma->vm_mm;
  21.414 +	cpumask_t cpu_mask;
  21.415 +
  21.416 +	preempt_disable();
  21.417 +	cpu_mask = mm->cpu_vm_mask;
  21.418 +	cpu_clear(smp_processor_id(), cpu_mask);
  21.419 +
  21.420 +	if (current->active_mm == mm) {
  21.421 +		if(current->mm)
  21.422 +			__flush_tlb_one(va);
  21.423 +		else
  21.424 +		 	leave_mm(smp_processor_id());
  21.425 +	}
  21.426 +
  21.427 +	if (!cpus_empty(cpu_mask))
  21.428 +		flush_tlb_others(cpu_mask, mm, va);
  21.429 +
  21.430 +	preempt_enable();
  21.431 +}
  21.432 +
  21.433 +static void do_flush_tlb_all(void* info)
  21.434 +{
  21.435 +	unsigned long cpu = smp_processor_id();
  21.436 +
  21.437 +	__flush_tlb_all();
  21.438 +	if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
  21.439 +		leave_mm(cpu);
  21.440 +}
  21.441 +
  21.442 +void flush_tlb_all(void)
  21.443 +{
  21.444 +	on_each_cpu(do_flush_tlb_all, NULL, 1, 1);
  21.445 +}
  21.446 +
  21.447 +/*
  21.448 + * this function sends a 'reschedule' IPI to another CPU.
  21.449 + * it goes straight through and wastes no time serializing
  21.450 + * anything. Worst case is that we lose a reschedule ...
  21.451 + */
  21.452 +void smp_send_reschedule(int cpu)
  21.453 +{
  21.454 +	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
  21.455 +}
  21.456 +
  21.457 +/*
  21.458 + * Structure and data for smp_call_function(). This is designed to minimise
  21.459 + * static memory requirements. It also looks cleaner.
  21.460 + */
  21.461 +static DEFINE_SPINLOCK(call_lock);
  21.462 +
  21.463 +struct call_data_struct {
  21.464 +	void (*func) (void *info);
  21.465 +	void *info;
  21.466 +	atomic_t started;
  21.467 +	atomic_t finished;
  21.468 +	int wait;
  21.469 +};
  21.470 +
  21.471 +static struct call_data_struct * call_data;
  21.472 +
  21.473 +/*
  21.474 + * this function sends a 'generic call function' IPI to all other CPUs
  21.475 + * in the system.
  21.476 + */
  21.477 +
  21.478 +int smp_call_function (void (*func) (void *info), void *info, int nonatomic,
  21.479 +			int wait)
  21.480 +/*
  21.481 + * [SUMMARY] Run a function on all other CPUs.
  21.482 + * <func> The function to run. This must be fast and non-blocking.
  21.483 + * <info> An arbitrary pointer to pass to the function.
  21.484 + * <nonatomic> currently unused.
  21.485 + * <wait> If true, wait (atomically) until function has completed on other CPUs.
  21.486 + * [RETURNS] 0 on success, else a negative status code. Does not return until
  21.487 + * remote CPUs are nearly ready to execute <<func>> or are or have executed.
  21.488 + *
  21.489 + * You must not call this function with disabled interrupts or from a
  21.490 + * hardware interrupt handler or from a bottom half handler.
  21.491 + */
  21.492 +{
  21.493 +	struct call_data_struct data;
  21.494 +	int cpus = num_online_cpus()-1;
  21.495 +
  21.496 +	if (!cpus)
  21.497 +		return 0;
  21.498 +
  21.499 +	/* Can deadlock when called with interrupts disabled */
  21.500 +	WARN_ON(irqs_disabled());
  21.501 +
  21.502 +	data.func = func;
  21.503 +	data.info = info;
  21.504 +	atomic_set(&data.started, 0);
  21.505 +	data.wait = wait;
  21.506 +	if (wait)
  21.507 +		atomic_set(&data.finished, 0);
  21.508 +
  21.509 +	spin_lock(&call_lock);
  21.510 +	call_data = &data;
  21.511 +	mb();
  21.512 +	
  21.513 +	/* Send a message to all other CPUs and wait for them to respond */
  21.514 +	send_IPI_allbutself(CALL_FUNCTION_VECTOR);
  21.515 +
  21.516 +	/* Wait for response */
  21.517 +	while (atomic_read(&data.started) != cpus)
  21.518 +		barrier();
  21.519 +
  21.520 +	if (wait)
  21.521 +		while (atomic_read(&data.finished) != cpus)
  21.522 +			barrier();
  21.523 +	spin_unlock(&call_lock);
  21.524 +
  21.525 +	return 0;
  21.526 +}
  21.527 +
  21.528 +static void stop_this_cpu (void * dummy)
  21.529 +{
  21.530 +	/*
  21.531 +	 * Remove this CPU:
  21.532 +	 */
  21.533 +	cpu_clear(smp_processor_id(), cpu_online_map);
  21.534 +	local_irq_disable();
  21.535 +#if 1
  21.536 +	xxprint("stop_this_cpu disable_local_APIC\n");
  21.537 +#else
  21.538 +	disable_local_APIC();
  21.539 +#endif
  21.540 +	if (cpu_data[smp_processor_id()].hlt_works_ok)
  21.541 +		for(;;) __asm__("hlt");
  21.542 +	for (;;);
  21.543 +}
  21.544 +
  21.545 +/*
  21.546 + * this function calls the 'stop' function on all other CPUs in the system.
  21.547 + */
  21.548 +
  21.549 +void smp_send_stop(void)
  21.550 +{
  21.551 +	smp_call_function(stop_this_cpu, NULL, 1, 0);
  21.552 +
  21.553 +	local_irq_disable();
  21.554 +#if 1
  21.555 +	xxprint("smp_send_stop disable_local_APIC\n");
  21.556 +#else
  21.557 +	disable_local_APIC();
  21.558 +#endif
  21.559 +	local_irq_enable();
  21.560 +}
  21.561 +
  21.562 +/*
  21.563 + * Reschedule call back. Nothing to do,
  21.564 + * all the work is done automatically when
  21.565 + * we return from the interrupt.
  21.566 + */
  21.567 +irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id,
  21.568 +				     struct pt_regs *regs)
  21.569 +{
  21.570 +
  21.571 +	return IRQ_HANDLED;
  21.572 +}
  21.573 +
  21.574 +#include <linux/kallsyms.h>
  21.575 +irqreturn_t smp_call_function_interrupt(int irq, void *dev_id,
  21.576 +					struct pt_regs *regs)
  21.577 +{
  21.578 +	void (*func) (void *info) = call_data->func;
  21.579 +	void *info = call_data->info;
  21.580 +	int wait = call_data->wait;
  21.581 +
  21.582 +	/*
  21.583 +	 * Notify initiating CPU that I've grabbed the data and am
  21.584 +	 * about to execute the function
  21.585 +	 */
  21.586 +	mb();
  21.587 +	atomic_inc(&call_data->started);
  21.588 +	/*
  21.589 +	 * At this point the info structure may be out of scope unless wait==1
  21.590 +	 */
  21.591 +	irq_enter();
  21.592 +	(*func)(info);
  21.593 +	irq_exit();
  21.594 +
  21.595 +	if (wait) {
  21.596 +		mb();
  21.597 +		atomic_inc(&call_data->finished);
  21.598 +	}
  21.599 +
  21.600 +	return IRQ_HANDLED;
  21.601 +}
  21.602 +
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c	Sat Mar 12 21:16:57 2005 +0000
    22.3 @@ -0,0 +1,1365 @@
    22.4 +/*
    22.5 + *	x86 SMP booting functions
    22.6 + *
    22.7 + *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
    22.8 + *	(c) 1998, 1999, 2000 Ingo Molnar <mingo@redhat.com>
    22.9 + *
   22.10 + *	Much of the core SMP work is based on previous work by Thomas Radke, to
   22.11 + *	whom a great many thanks are extended.
   22.12 + *
   22.13 + *	Thanks to Intel for making available several different Pentium,
   22.14 + *	Pentium Pro and Pentium-II/Xeon MP machines.
   22.15 + *	Original development of Linux SMP code supported by Caldera.
   22.16 + *
   22.17 + *	This code is released under the GNU General Public License version 2 or
   22.18 + *	later.
   22.19 + *
   22.20 + *	Fixes
   22.21 + *		Felix Koop	:	NR_CPUS used properly
   22.22 + *		Jose Renau	:	Handle single CPU case.
   22.23 + *		Alan Cox	:	By repeated request 8) - Total BogoMIPS report.
   22.24 + *		Greg Wright	:	Fix for kernel stacks panic.
   22.25 + *		Erich Boleyn	:	MP v1.4 and additional changes.
   22.26 + *	Matthias Sattler	:	Changes for 2.1 kernel map.
   22.27 + *	Michel Lespinasse	:	Changes for 2.1 kernel map.
   22.28 + *	Michael Chastain	:	Change trampoline.S to gnu as.
   22.29 + *		Alan Cox	:	Dumb bug: 'B' step PPro's are fine
   22.30 + *		Ingo Molnar	:	Added APIC timers, based on code
   22.31 + *					from Jose Renau
   22.32 + *		Ingo Molnar	:	various cleanups and rewrites
   22.33 + *		Tigran Aivazian	:	fixed "0.00 in /proc/uptime on SMP" bug.
   22.34 + *	Maciej W. Rozycki	:	Bits for genuine 82489DX APICs
   22.35 + *		Martin J. Bligh	: 	Added support for multi-quad systems
   22.36 + *		Dave Jones	:	Report invalid combinations of Athlon CPUs.
   22.37 +*		Rusty Russell	:	Hacked into shape for new "hotplug" boot process. */
   22.38 +
   22.39 +#include <linux/module.h>
   22.40 +#include <linux/config.h>
   22.41 +#include <linux/init.h>
   22.42 +#include <linux/kernel.h>
   22.43 +
   22.44 +#include <linux/mm.h>
   22.45 +#include <linux/sched.h>
   22.46 +#include <linux/kernel_stat.h>
   22.47 +#include <linux/smp_lock.h>
   22.48 +#include <linux/irq.h>
   22.49 +#include <linux/bootmem.h>
   22.50 +
   22.51 +#include <linux/delay.h>
   22.52 +#include <linux/mc146818rtc.h>
   22.53 +#include <asm/tlbflush.h>
   22.54 +#include <asm/desc.h>
   22.55 +#include <asm/arch_hooks.h>
   22.56 +
   22.57 +#if 1
   22.58 +#define Dprintk(args...)
   22.59 +#else
   22.60 +#include <mach_apic.h>
   22.61 +#endif
   22.62 +#include <mach_wakecpu.h>
   22.63 +#include <smpboot_hooks.h>
   22.64 +
   22.65 +/* Set if we find a B stepping CPU */
   22.66 +static int __initdata smp_b_stepping;
   22.67 +
   22.68 +/* Number of siblings per CPU package */
   22.69 +int smp_num_siblings = 1;
   22.70 +int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
   22.71 +EXPORT_SYMBOL(phys_proc_id);
   22.72 +
   22.73 +/* bitmap of online cpus */
   22.74 +cpumask_t cpu_online_map;
   22.75 +
   22.76 +cpumask_t cpu_callin_map;
   22.77 +cpumask_t cpu_callout_map;
   22.78 +static cpumask_t smp_commenced_mask;
   22.79 +
   22.80 +/* Per CPU bogomips and other parameters */
   22.81 +struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
   22.82 +
   22.83 +u8 x86_cpu_to_apicid[NR_CPUS] =
   22.84 +			{ [0 ... NR_CPUS-1] = 0xff };
   22.85 +EXPORT_SYMBOL(x86_cpu_to_apicid);
   22.86 +
   22.87 +/* Set when the idlers are all forked */
   22.88 +int smp_threads_ready;
   22.89 +
   22.90 +#if 0
   22.91 +/*
   22.92 + * Trampoline 80x86 program as an array.
   22.93 + */
   22.94 +
   22.95 +extern unsigned char trampoline_data [];
   22.96 +extern unsigned char trampoline_end  [];
   22.97 +static unsigned char *trampoline_base;
   22.98 +static int trampoline_exec;
   22.99 +
  22.100 +/*
  22.101 + * Currently trivial. Write the real->protected mode
  22.102 + * bootstrap into the page concerned. The caller
  22.103 + * has made sure it's suitably aligned.
  22.104 + */
  22.105 +
  22.106 +static unsigned long __init setup_trampoline(void)
  22.107 +{
  22.108 +	memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
  22.109 +	return virt_to_phys(trampoline_base);
  22.110 +}
  22.111 +#endif
  22.112 +
  22.113 +/*
  22.114 + * We are called very early to get the low memory for the
  22.115 + * SMP bootup trampoline page.
  22.116 + */
  22.117 +void __init smp_alloc_memory(void)
  22.118 +{
  22.119 +#if 1
  22.120 +	int cpu;
  22.121 +
  22.122 +	for (cpu = 1; cpu < NR_CPUS; cpu++) {
  22.123 +		cpu_gdt_descr[cpu].address = (unsigned long)
  22.124 +			alloc_bootmem_low_pages(PAGE_SIZE);
  22.125 +		/* XXX free unused pages later */
  22.126 +	}
  22.127 +#else
  22.128 +	trampoline_base = (void *) alloc_bootmem_low_pages(PAGE_SIZE);
  22.129 +	/*
  22.130 +	 * Has to be in very low memory so we can execute
  22.131 +	 * real-mode AP code.
  22.132 +	 */
  22.133 +	if (__pa(trampoline_base) >= 0x9F000)
  22.134 +		BUG();
  22.135 +	/*
  22.136 +	 * Make the SMP trampoline executable:
  22.137 +	 */
  22.138 +	trampoline_exec = set_kernel_exec((unsigned long)trampoline_base, 1);
  22.139 +#endif
  22.140 +}
  22.141 +
  22.142 +/*
  22.143 + * The bootstrap kernel entry code has set these up. Save them for
  22.144 + * a given CPU
  22.145 + */
  22.146 +
  22.147 +static void __init smp_store_cpu_info(int id)
  22.148 +{
  22.149 +	struct cpuinfo_x86 *c = cpu_data + id;
  22.150 +
  22.151 +	*c = boot_cpu_data;
  22.152 +	if (id!=0)
  22.153 +		identify_cpu(c);
  22.154 +	/*
  22.155 +	 * Mask B, Pentium, but not Pentium MMX
  22.156 +	 */
  22.157 +	if (c->x86_vendor == X86_VENDOR_INTEL &&
  22.158 +	    c->x86 == 5 &&
  22.159 +	    c->x86_mask >= 1 && c->x86_mask <= 4 &&
  22.160 +	    c->x86_model <= 3)
  22.161 +		/*
  22.162 +		 * Remember we have B step Pentia with bugs
  22.163 +		 */
  22.164 +		smp_b_stepping = 1;
  22.165 +
  22.166 +	/*
  22.167 +	 * Certain Athlons might work (for various values of 'work') in SMP
  22.168 +	 * but they are not certified as MP capable.
  22.169 +	 */
  22.170 +	if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
  22.171 +
  22.172 +		/* Athlon 660/661 is valid. */	
  22.173 +		if ((c->x86_model==6) && ((c->x86_mask==0) || (c->x86_mask==1)))
  22.174 +			goto valid_k7;
  22.175 +
  22.176 +		/* Duron 670 is valid */
  22.177 +		if ((c->x86_model==7) && (c->x86_mask==0))
  22.178 +			goto valid_k7;
  22.179 +
  22.180 +		/*
  22.181 +		 * Athlon 662, Duron 671, and Athlon >model 7 have capability bit.
  22.182 +		 * It's worth noting that the A5 stepping (662) of some Athlon XP's
  22.183 +		 * have the MP bit set.
  22.184 +		 * See http://www.heise.de/newsticker/data/jow-18.10.01-000 for more.
  22.185 +		 */
  22.186 +		if (((c->x86_model==6) && (c->x86_mask>=2)) ||
  22.187 +		    ((c->x86_model==7) && (c->x86_mask>=1)) ||
  22.188 +		     (c->x86_model> 7))
  22.189 +			if (cpu_has_mp)
  22.190 +				goto valid_k7;
  22.191 +
  22.192 +		/* If we get here, it's not a certified SMP capable AMD system. */
  22.193 +		tainted |= TAINT_UNSAFE_SMP;
  22.194 +	}
  22.195 +
  22.196 +valid_k7:
  22.197 +	;
  22.198 +}
  22.199 +
  22.200 +#if 0
  22.201 +/*
  22.202 + * TSC synchronization.
  22.203 + *
  22.204 + * We first check whether all CPUs have their TSC's synchronized,
  22.205 + * then we print a warning if not, and always resync.
  22.206 + */
  22.207 +
  22.208 +static atomic_t tsc_start_flag = ATOMIC_INIT(0);
  22.209 +static atomic_t tsc_count_start = ATOMIC_INIT(0);
  22.210 +static atomic_t tsc_count_stop = ATOMIC_INIT(0);
  22.211 +static unsigned long long tsc_values[NR_CPUS];
  22.212 +
  22.213 +#define NR_LOOPS 5
  22.214 +
  22.215 +static void __init synchronize_tsc_bp (void)
  22.216 +{
  22.217 +	int i;
  22.218 +	unsigned long long t0;
  22.219 +	unsigned long long sum, avg;
  22.220 +	long long delta;
  22.221 +	unsigned long one_usec;
  22.222 +	int buggy = 0;
  22.223 +
  22.224 +	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
  22.225 +
  22.226 +	/* convert from kcyc/sec to cyc/usec */
  22.227 +	one_usec = cpu_khz / 1000;
  22.228 +
  22.229 +	atomic_set(&tsc_start_flag, 1);
  22.230 +	wmb();
  22.231 +
  22.232 +	/*
  22.233 +	 * We loop a few times to get a primed instruction cache,
  22.234 +	 * then the last pass is more or less synchronized and
  22.235 +	 * the BP and APs set their cycle counters to zero all at
  22.236 +	 * once. This reduces the chance of having random offsets
  22.237 +	 * between the processors, and guarantees that the maximum
  22.238 +	 * delay between the cycle counters is never bigger than
  22.239 +	 * the latency of information-passing (cachelines) between
  22.240 +	 * two CPUs.
  22.241 +	 */
  22.242 +	for (i = 0; i < NR_LOOPS; i++) {
  22.243 +		/*
  22.244 +		 * all APs synchronize but they loop on '== num_cpus'
  22.245 +		 */
  22.246 +		while (atomic_read(&tsc_count_start) != num_booting_cpus()-1)
  22.247 +			mb();
  22.248 +		atomic_set(&tsc_count_stop, 0);
  22.249 +		wmb();
  22.250 +		/*
  22.251 +		 * this lets the APs save their current TSC:
  22.252 +		 */
  22.253 +		atomic_inc(&tsc_count_start);
  22.254 +
  22.255 +		rdtscll(tsc_values[smp_processor_id()]);
  22.256 +		/*
  22.257 +		 * We clear the TSC in the last loop:
  22.258 +		 */
  22.259 +		if (i == NR_LOOPS-1)
  22.260 +			write_tsc(0, 0);
  22.261 +
  22.262 +		/*
  22.263 +		 * Wait for all APs to leave the synchronization point:
  22.264 +		 */
  22.265 +		while (atomic_read(&tsc_count_stop) != num_booting_cpus()-1)
  22.266 +			mb();
  22.267 +		atomic_set(&tsc_count_start, 0);
  22.268 +		wmb();
  22.269 +		atomic_inc(&tsc_count_stop);
  22.270 +	}
  22.271 +
  22.272 +	sum = 0;
  22.273 +	for (i = 0; i < NR_CPUS; i++) {
  22.274 +		if (cpu_isset(i, cpu_callout_map)) {
  22.275 +			t0 = tsc_values[i];
  22.276 +			sum += t0;
  22.277 +		}
  22.278 +	}
  22.279 +	avg = sum;
  22.280 +	do_div(avg, num_booting_cpus());
  22.281 +
  22.282 +	sum = 0;
  22.283 +	for (i = 0; i < NR_CPUS; i++) {
  22.284 +		if (!cpu_isset(i, cpu_callout_map))
  22.285 +			continue;
  22.286 +		delta = tsc_values[i] - avg;
  22.287 +		if (delta < 0)
  22.288 +			delta = -delta;
  22.289 +		/*
  22.290 +		 * We report bigger than 2 microseconds clock differences.
  22.291 +		 */
  22.292 +		if (delta > 2*one_usec) {
  22.293 +			long realdelta;
  22.294 +			if (!buggy) {
  22.295 +				buggy = 1;
  22.296 +				printk("\n");
  22.297 +			}
  22.298 +			realdelta = delta;
  22.299 +			do_div(realdelta, one_usec);
  22.300 +			if (tsc_values[i] < avg)
  22.301 +				realdelta = -realdelta;
  22.302 +
  22.303 +			printk(KERN_INFO "CPU#%d had %ld usecs TSC skew, fixed it up.\n", i, realdelta);
  22.304 +		}
  22.305 +
  22.306 +		sum += delta;
  22.307 +	}
  22.308 +	if (!buggy)
  22.309 +		printk("passed.\n");
  22.310 +}
  22.311 +
  22.312 +static void __init synchronize_tsc_ap (void)
  22.313 +{
  22.314 +	int i;
  22.315 +
  22.316 +	/*
  22.317 +	 * Not every cpu is online at the time
  22.318 +	 * this gets called, so we first wait for the BP to
  22.319 +	 * finish SMP initialization:
  22.320 +	 */
  22.321 +	while (!atomic_read(&tsc_start_flag)) mb();
  22.322 +
  22.323 +	for (i = 0; i < NR_LOOPS; i++) {
  22.324 +		atomic_inc(&tsc_count_start);
  22.325 +		while (atomic_read(&tsc_count_start) != num_booting_cpus())
  22.326 +			mb();
  22.327 +
  22.328 +		rdtscll(tsc_values[smp_processor_id()]);
  22.329 +		if (i == NR_LOOPS-1)
  22.330 +			write_tsc(0, 0);
  22.331 +
  22.332 +		atomic_inc(&tsc_count_stop);
  22.333 +		while (atomic_read(&tsc_count_stop) != num_booting_cpus()) mb();
  22.334 +	}
  22.335 +}
  22.336 +#undef NR_LOOPS
  22.337 +#endif
  22.338 +
  22.339 +extern void calibrate_delay(void);
  22.340 +
  22.341 +static atomic_t init_deasserted;
  22.342 +
  22.343 +void __init smp_callin(void)
  22.344 +{
  22.345 +	int cpuid, phys_id;
  22.346 +	unsigned long timeout;
  22.347 +
  22.348 +#if 0
  22.349 +	/*
  22.350 +	 * If waken up by an INIT in an 82489DX configuration
  22.351 +	 * we may get here before an INIT-deassert IPI reaches
  22.352 +	 * our local APIC.  We have to wait for the IPI or we'll
  22.353 +	 * lock up on an APIC access.
  22.354 +	 */
  22.355 +	wait_for_init_deassert(&init_deasserted);
  22.356 +#endif
  22.357 +
  22.358 +	/*
  22.359 +	 * (This works even if the APIC is not enabled.)
  22.360 +	 */
  22.361 +	phys_id = smp_processor_id();
  22.362 +	cpuid = smp_processor_id();
  22.363 +	if (cpu_isset(cpuid, cpu_callin_map)) {
  22.364 +		printk("huh, phys CPU#%d, CPU#%d already present??\n",
  22.365 +					phys_id, cpuid);
  22.366 +		BUG();
  22.367 +	}
  22.368 +	Dprintk("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);
  22.369 +
  22.370 +	/*
  22.371 +	 * STARTUP IPIs are fragile beasts as they might sometimes
  22.372 +	 * trigger some glue motherboard logic. Complete APIC bus
  22.373 +	 * silence for 1 second, this overestimates the time the
  22.374 +	 * boot CPU is spending to send the up to 2 STARTUP IPIs
  22.375 +	 * by a factor of two. This should be enough.
  22.376 +	 */
  22.377 +
  22.378 +	/*
  22.379 +	 * Waiting 2s total for startup (udelay is not yet working)
  22.380 +	 */
  22.381 +	timeout = jiffies + 2*HZ;
  22.382 +	while (time_before(jiffies, timeout)) {
  22.383 +		/*
  22.384 +		 * Has the boot CPU finished it's STARTUP sequence?
  22.385 +		 */
  22.386 +		if (cpu_isset(cpuid, cpu_callout_map))
  22.387 +			break;
  22.388 +		rep_nop();
  22.389 +	}
  22.390 +
  22.391 +	if (!time_before(jiffies, timeout)) {
  22.392 +		printk("BUG: CPU%d started up but did not get a callout!\n",
  22.393 +			cpuid);
  22.394 +		BUG();
  22.395 +	}
  22.396 +
  22.397 +#if 0
  22.398 +	/*
  22.399 +	 * the boot CPU has finished the init stage and is spinning
  22.400 +	 * on callin_map until we finish. We are free to set up this
  22.401 +	 * CPU, first the APIC. (this is probably redundant on most
  22.402 +	 * boards)
  22.403 +	 */
  22.404 +
  22.405 +	Dprintk("CALLIN, before setup_local_APIC().\n");
  22.406 +	smp_callin_clear_local_apic();
  22.407 +	setup_local_APIC();
  22.408 +#endif
  22.409 +	map_cpu_to_logical_apicid();
  22.410 +
  22.411 +	/*
  22.412 +	 * Get our bogomips.
  22.413 +	 */
  22.414 +	calibrate_delay();
  22.415 +	Dprintk("Stack at about %p\n",&cpuid);
  22.416 +
  22.417 +	/*
  22.418 +	 * Save our processor parameters
  22.419 +	 */
  22.420 + 	smp_store_cpu_info(cpuid);
  22.421 +
  22.422 +#if 0
  22.423 +	disable_APIC_timer();
  22.424 +#endif
  22.425 +
  22.426 +	/*
  22.427 +	 * Allow the master to continue.
  22.428 +	 */
  22.429 +	cpu_set(cpuid, cpu_callin_map);
  22.430 +
  22.431 +#if 0
  22.432 +	/*
  22.433 +	 *      Synchronize the TSC with the BP
  22.434 +	 */
  22.435 +	if (cpu_has_tsc && cpu_khz)
  22.436 +		synchronize_tsc_ap();
  22.437 +#endif
  22.438 +}
  22.439 +
  22.440 +int cpucount;
  22.441 +
  22.442 +
  22.443 +static irqreturn_t local_debug_interrupt(int irq, void *dev_id,
  22.444 +					 struct pt_regs *regs)
  22.445 +{
  22.446 +
  22.447 +	return IRQ_HANDLED;
  22.448 +}
  22.449 +
  22.450 +static struct irqaction local_irq_debug = {
  22.451 +	local_debug_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "ldebug",
  22.452 +	NULL, NULL
  22.453 +};
  22.454 +
  22.455 +void local_setup_debug(void)
  22.456 +{
  22.457 +	(void)setup_irq(bind_virq_to_irq(VIRQ_DEBUG), &local_irq_debug);
  22.458 +}
  22.459 +
  22.460 +
  22.461 +extern void local_setup_timer(void);
  22.462 +
  22.463 +/*
  22.464 + * Activate a secondary processor.
  22.465 + */
  22.466 +static int __init start_secondary(void *unused)
  22.467 +{
  22.468 +	/*
  22.469 +	 * Dont put anything before smp_callin(), SMP
  22.470 +	 * booting is too fragile that we want to limit the
  22.471 +	 * things done here to the most necessary things.
  22.472 +	 */
  22.473 +	cpu_init();
  22.474 +	smp_callin();
  22.475 +	while (!cpu_isset(smp_processor_id(), smp_commenced_mask))
  22.476 +		rep_nop();
  22.477 +	local_setup_timer();
  22.478 +	local_setup_debug();	/* XXX */
  22.479 +	smp_intr_init();
  22.480 +	local_irq_enable();
  22.481 +	/*
  22.482 +	 * low-memory mappings have been cleared, flush them from
  22.483 +	 * the local TLBs too.
  22.484 +	 */
  22.485 +	local_flush_tlb();
  22.486 +	cpu_set(smp_processor_id(), cpu_online_map);
  22.487 +
  22.488 +	/* We can take interrupts now: we're officially "up". */
  22.489 +	local_irq_enable();
  22.490 +
  22.491 +	wmb();
  22.492 +	if (0) {
  22.493 +		char *msg2 = "delay2\n";
  22.494 +		int timeout;
  22.495 +		for (timeout = 0; timeout < 50000; timeout++) {
  22.496 +			udelay(1000);
  22.497 +			if (timeout == 2000) {
  22.498 +				(void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(msg2), msg2);
  22.499 +				timeout = 0;
  22.500 +			}
  22.501 +		}
  22.502 +	}
  22.503 +	cpu_idle();
  22.504 +}
  22.505 +
  22.506 +/*
  22.507 + * Everything has been set up for the secondary
  22.508 + * CPUs - they just need to reload everything
  22.509 + * from the task structure
  22.510 + * This function must not return.
  22.511 + */
  22.512 +void __init initialize_secondary(void)
  22.513 +{
  22.514 +	/*
  22.515 +	 * We don't actually need to load the full TSS,
  22.516 +	 * basically just the stack pointer and the eip.
  22.517 +	 */
  22.518 +
  22.519 +	asm volatile(
  22.520 +		"movl %0,%%esp\n\t"
  22.521 +		"jmp *%1"
  22.522 +		:
  22.523 +		:"r" (current->thread.esp),"r" (current->thread.eip));
  22.524 +}
  22.525 +
  22.526 +extern struct {
  22.527 +	void * esp;
  22.528 +	unsigned short ss;
  22.529 +} stack_start;
  22.530 +
  22.531 +#ifdef CONFIG_NUMA
  22.532 +
  22.533 +/* which logical CPUs are on which nodes */
  22.534 +cpumask_t node_2_cpu_mask[MAX_NUMNODES] =
  22.535 +				{ [0 ... MAX_NUMNODES-1] = CPU_MASK_NONE };
  22.536 +/* which node each logical CPU is on */
  22.537 +int cpu_2_node[NR_CPUS] = { [0 ... NR_CPUS-1] = 0 };
  22.538 +EXPORT_SYMBOL(cpu_2_node);
  22.539 +
  22.540 +/* set up a mapping between cpu and node. */
  22.541 +static inline void map_cpu_to_node(int cpu, int node)
  22.542 +{
  22.543 +	printk("Mapping cpu %d to node %d\n", cpu, node);
  22.544 +	cpu_set(cpu, node_2_cpu_mask[node]);
  22.545 +	cpu_2_node[cpu] = node;
  22.546 +}
  22.547 +
  22.548 +/* undo a mapping between cpu and node. */
  22.549 +static inline void unmap_cpu_to_node(int cpu)
  22.550 +{
  22.551 +	int node;
  22.552 +
  22.553 +	printk("Unmapping cpu %d from all nodes\n", cpu);
  22.554 +	for (node = 0; node < MAX_NUMNODES; node ++)
  22.555 +		cpu_clear(cpu, node_2_cpu_mask[node]);
  22.556 +	cpu_2_node[cpu] = 0;
  22.557 +}
  22.558 +#else /* !CONFIG_NUMA */
  22.559 +
  22.560 +#define map_cpu_to_node(cpu, node)	({})
  22.561 +#define unmap_cpu_to_node(cpu)	({})
  22.562 +
  22.563 +#endif /* CONFIG_NUMA */
  22.564 +
  22.565 +u8 cpu_2_logical_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
  22.566 +
  22.567 +void map_cpu_to_logical_apicid(void)
  22.568 +{
  22.569 +	int cpu = smp_processor_id();
  22.570 +	int apicid = smp_processor_id();
  22.571 +
  22.572 +	cpu_2_logical_apicid[cpu] = apicid;
  22.573 +	map_cpu_to_node(cpu, apicid_to_node(apicid));
  22.574 +}
  22.575 +
  22.576 +void unmap_cpu_to_logical_apicid(int cpu)
  22.577 +{
  22.578 +	cpu_2_logical_apicid[cpu] = BAD_APICID;
  22.579 +	unmap_cpu_to_node(cpu);
  22.580 +}
  22.581 +
  22.582 +#if APIC_DEBUG
  22.583 +static inline void __inquire_remote_apic(int apicid)
  22.584 +{
  22.585 +	int i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
  22.586 +	char *names[] = { "ID", "VERSION", "SPIV" };
  22.587 +	int timeout, status;
  22.588 +
  22.589 +	printk("Inquiring remote APIC #%d...\n", apicid);
  22.590 +
  22.591 +	for (i = 0; i < sizeof(regs) / sizeof(*regs); i++) {
  22.592 +		printk("... APIC #%d %s: ", apicid, names[i]);
  22.593 +
  22.594 +		/*
  22.595 +		 * Wait for idle.
  22.596 +		 */
  22.597 +		apic_wait_icr_idle();
  22.598 +
  22.599 +		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
  22.600 +		apic_write_around(APIC_ICR, APIC_DM_REMRD | regs[i]);
  22.601 +
  22.602 +		timeout = 0;
  22.603 +		do {
  22.604 +			udelay(100);
  22.605 +			status = apic_read(APIC_ICR) & APIC_ICR_RR_MASK;
  22.606 +		} while (status == APIC_ICR_RR_INPROG && timeout++ < 1000);
  22.607 +
  22.608 +		switch (status) {
  22.609 +		case APIC_ICR_RR_VALID:
  22.610 +			status = apic_read(APIC_RRR);
  22.611 +			printk("%08x\n", status);
  22.612 +			break;
  22.613 +		default:
  22.614 +			printk("failed\n");
  22.615 +		}
  22.616 +	}
  22.617 +}
  22.618 +#endif
  22.619 +
  22.620 +#if 0
  22.621 +#ifdef WAKE_SECONDARY_VIA_NMI
  22.622 +/* 
  22.623 + * Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
  22.624 + * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
  22.625 + * won't ... remember to clear down the APIC, etc later.
  22.626 + */
  22.627 +static int __init
  22.628 +wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
  22.629 +{
  22.630 +	unsigned long send_status = 0, accept_status = 0;
  22.631 +	int timeout, maxlvt;
  22.632 +
  22.633 +	/* Target chip */
  22.634 +	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(logical_apicid));
  22.635 +
  22.636 +	/* Boot on the stack */
  22.637 +	/* Kick the second */
  22.638 +	apic_write_around(APIC_ICR, APIC_DM_NMI | APIC_DEST_LOGICAL);
  22.639 +
  22.640 +	Dprintk("Waiting for send to finish...\n");
  22.641 +	timeout = 0;
  22.642 +	do {
  22.643 +		Dprintk("+");
  22.644 +		udelay(100);
  22.645 +		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
  22.646 +	} while (send_status && (timeout++ < 1000));
  22.647 +
  22.648 +	/*
  22.649 +	 * Give the other CPU some time to accept the IPI.
  22.650 +	 */
  22.651 +	udelay(200);
  22.652 +	/*
  22.653 +	 * Due to the Pentium erratum 3AP.
  22.654 +	 */
  22.655 +	maxlvt = get_maxlvt();
  22.656 +	if (maxlvt > 3) {
  22.657 +		apic_read_around(APIC_SPIV);
  22.658 +		apic_write(APIC_ESR, 0);
  22.659 +	}
  22.660 +	accept_status = (apic_read(APIC_ESR) & 0xEF);
  22.661 +	Dprintk("NMI sent.\n");
  22.662 +
  22.663 +	if (send_status)
  22.664 +		printk("APIC never delivered???\n");
  22.665 +	if (accept_status)
  22.666 +		printk("APIC delivery error (%lx).\n", accept_status);
  22.667 +
  22.668 +	return (send_status | accept_status);
  22.669 +}
  22.670 +#endif	/* WAKE_SECONDARY_VIA_NMI */
  22.671 +
  22.672 +#ifdef WAKE_SECONDARY_VIA_INIT
  22.673 +static int __init
  22.674 +wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
  22.675 +{
  22.676 +	unsigned long send_status = 0, accept_status = 0;
  22.677 +	int maxlvt, timeout, num_starts, j;
  22.678 +
  22.679 +	/*
  22.680 +	 * Be paranoid about clearing APIC errors.
  22.681 +	 */
  22.682 +	if (APIC_INTEGRATED(apic_version[phys_apicid])) {
  22.683 +		apic_read_around(APIC_SPIV);
  22.684 +		apic_write(APIC_ESR, 0);
  22.685 +		apic_read(APIC_ESR);
  22.686 +	}
  22.687 +
  22.688 +	Dprintk("Asserting INIT.\n");
  22.689 +
  22.690 +	/*
  22.691 +	 * Turn INIT on target chip
  22.692 +	 */
  22.693 +	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
  22.694 +
  22.695 +	/*
  22.696 +	 * Send IPI
  22.697 +	 */
  22.698 +	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
  22.699 +				| APIC_DM_INIT);
  22.700 +
  22.701 +	Dprintk("Waiting for send to finish...\n");
  22.702 +	timeout = 0;
  22.703 +	do {
  22.704 +		Dprintk("+");
  22.705 +		udelay(100);
  22.706 +		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
  22.707 +	} while (send_status && (timeout++ < 1000));
  22.708 +
  22.709 +	mdelay(10);
  22.710 +
  22.711 +	Dprintk("Deasserting INIT.\n");
  22.712 +
  22.713 +	/* Target chip */
  22.714 +	apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
  22.715 +
  22.716 +	/* Send IPI */
  22.717 +	apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
  22.718 +
  22.719 +	Dprintk("Waiting for send to finish...\n");
  22.720 +	timeout = 0;
  22.721 +	do {
  22.722 +		Dprintk("+");
  22.723 +		udelay(100);
  22.724 +		send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
  22.725 +	} while (send_status && (timeout++ < 1000));
  22.726 +
  22.727 +	atomic_set(&init_deasserted, 1);
  22.728 +
  22.729 +	/*
  22.730 +	 * Should we send STARTUP IPIs ?
  22.731 +	 *
  22.732 +	 * Determine this based on the APIC version.
  22.733 +	 * If we don't have an integrated APIC, don't send the STARTUP IPIs.
  22.734 +	 */
  22.735 +	if (APIC_INTEGRATED(apic_version[phys_apicid]))
  22.736 +		num_starts = 2;
  22.737 +	else
  22.738 +		num_starts = 0;
  22.739 +
  22.740 +	/*
  22.741 +	 * Run STARTUP IPI loop.
  22.742 +	 */
  22.743 +	Dprintk("#startup loops: %d.\n", num_starts);
  22.744 +
  22.745 +	maxlvt = get_maxlvt();
  22.746 +
  22.747 +	for (j = 1; j <= num_starts; j++) {
  22.748 +		Dprintk("Sending STARTUP #%d.\n",j);
  22.749 +		apic_read_around(APIC_SPIV);
  22.750 +		apic_write(APIC_ESR, 0);
  22.751 +		apic_read(APIC_ESR);
  22.752 +		Dprintk("After apic_write.\n");
  22.753 +
  22.754 +		/*
  22.755 +		 * STARTUP IPI
  22.756 +		 */
  22.757 +
  22.758 +		/* Target chip */
  22.759 +		apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(phys_apicid));
  22.760 +
  22.761 +		/* Boot on the stack */
  22.762 +		/* Kick the second */
  22.763 +		apic_write_around(APIC_ICR, APIC_DM_STARTUP
  22.764 +					| (start_eip >> 12));
  22.765 +
  22.766 +		/*
  22.767 +		 * Give the other CPU some time to accept the IPI.
  22.768 +		 */
  22.769 +		udelay(300);
  22.770 +
  22.771 +		Dprintk("Startup point 1.\n");
  22.772 +
  22.773 +		Dprintk("Waiting for send to finish...\n");
  22.774 +		timeout = 0;
  22.775 +		do {
  22.776 +			Dprintk("+");
  22.777 +			udelay(100);
  22.778 +			send_status = apic_read(APIC_ICR) & APIC_ICR_BUSY;
  22.779 +		} while (send_status && (timeout++ < 1000));
  22.780 +
  22.781 +		/*
  22.782 +		 * Give the other CPU some time to accept the IPI.
  22.783 +		 */
  22.784 +		udelay(200);
  22.785 +		/*
  22.786 +		 * Due to the Pentium erratum 3AP.
  22.787 +		 */
  22.788 +		if (maxlvt > 3) {
  22.789 +			apic_read_around(APIC_SPIV);
  22.790 +			apic_write(APIC_ESR, 0);
  22.791 +		}
  22.792 +		accept_status = (apic_read(APIC_ESR) & 0xEF);
  22.793 +		if (send_status || accept_status)
  22.794 +			break;
  22.795 +	}
  22.796 +	Dprintk("After Startup.\n");
  22.797 +
  22.798 +	if (send_status)
  22.799 +		printk("APIC never delivered???\n");
  22.800 +	if (accept_status)
  22.801 +		printk("APIC delivery error (%lx).\n", accept_status);
  22.802 +
  22.803 +	return (send_status | accept_status);
  22.804 +}
  22.805 +#endif	/* WAKE_SECONDARY_VIA_INIT */
  22.806 +#endif
  22.807 +
  22.808 +extern cpumask_t cpu_initialized;
  22.809 +
  22.810 +static int __init do_boot_cpu(int apicid)
  22.811 +/*
  22.812 + * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
  22.813 + * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
  22.814 + * Returns zero if CPU booted OK, else error code from wakeup_secondary_cpu.
  22.815 + */
  22.816 +{
  22.817 +	struct task_struct *idle;
  22.818 +	unsigned long boot_error;
  22.819 +	int timeout, cpu;
  22.820 +	unsigned long start_eip;
  22.821 +#if 0
  22.822 +	unsigned short nmi_high = 0, nmi_low = 0;
  22.823 +#endif
  22.824 +	full_execution_context_t ctxt;
  22.825 +	extern void startup_32_smp(void);
  22.826 +	extern void hypervisor_callback(void);
  22.827 +	extern void failsafe_callback(void);
  22.828 +	extern int smp_trap_init(trap_info_t *);
  22.829 +	int i;
  22.830 +
  22.831 +	cpu = ++cpucount;
  22.832 +	/*
  22.833 +	 * We can't use kernel_thread since we must avoid to
  22.834 +	 * reschedule the child.
  22.835 +	 */
  22.836 +	idle = fork_idle(cpu);
  22.837 +	if (IS_ERR(idle))
  22.838 +		panic("failed fork for CPU %d", cpu);
  22.839 +	idle->thread.eip = (unsigned long) start_secondary;
  22.840 +	/* start_eip had better be page-aligned! */
  22.841 +	start_eip = (unsigned long)startup_32_smp;
  22.842 +
  22.843 +	/* So we see what's up   */
  22.844 +	printk("Booting processor %d/%d eip %lx\n", cpu, apicid, start_eip);
  22.845 +	/* Stack for startup_32 can be just as for start_secondary onwards */
  22.846 +	stack_start.esp = (void *) idle->thread.esp;
  22.847 +
  22.848 +	irq_ctx_init(cpu);
  22.849 +
  22.850 +	/*
  22.851 +	 * This grunge runs the startup process for
  22.852 +	 * the targeted processor.
  22.853 +	 */
  22.854 +
  22.855 +	atomic_set(&init_deasserted, 0);
  22.856 +
  22.857 +#if 1
  22.858 +	if (cpu_gdt_descr[0].size > PAGE_SIZE)
  22.859 +		BUG();
  22.860 +	cpu_gdt_descr[cpu].size = cpu_gdt_descr[0].size;
  22.861 +	memcpy((void *)cpu_gdt_descr[cpu].address,
  22.862 +	       (void *)cpu_gdt_descr[0].address, cpu_gdt_descr[0].size);
  22.863 +		memset((char *)cpu_gdt_descr[cpu].address +
  22.864 +		       FIRST_RESERVED_GDT_ENTRY * 8, 0,
  22.865 +		       NR_RESERVED_GDT_ENTRIES * 8);
  22.866 +
  22.867 +	memset(&ctxt, 0, sizeof(ctxt));
  22.868 +
  22.869 +	ctxt.cpu_ctxt.ds = __USER_DS;
  22.870 +	ctxt.cpu_ctxt.es = __USER_DS;
  22.871 +	ctxt.cpu_ctxt.fs = 0;
  22.872 +	ctxt.cpu_ctxt.gs = 0;
  22.873 +	ctxt.cpu_ctxt.ss = __KERNEL_DS;
  22.874 +	ctxt.cpu_ctxt.cs = __KERNEL_CS;
  22.875 +	ctxt.cpu_ctxt.eip = start_eip;
  22.876 +	ctxt.cpu_ctxt.esp = idle->thread.esp;
  22.877 +	ctxt.cpu_ctxt.eflags = (1<<9) | (1<<2) | (idle->thread.io_pl<<12);
  22.878 +
  22.879 +	/* FPU is set up to default initial state. */
  22.880 +	memset(ctxt.fpu_ctxt, 0, sizeof(ctxt.fpu_ctxt));
  22.881 +
  22.882 +	/* Virtual IDT is empty at start-of-day. */
  22.883 +	for ( i = 0; i < 256; i++ )
  22.884 +	{
  22.885 +		ctxt.trap_ctxt[i].vector = i;
  22.886 +		ctxt.trap_ctxt[i].cs     = FLAT_KERNEL_CS;
  22.887 +	}
  22.888 +	ctxt.fast_trap_idx = smp_trap_init(ctxt.trap_ctxt);
  22.889 +
  22.890 +	/* No LDT. */
  22.891 +	ctxt.ldt_ents = 0;
  22.892 +
  22.893 +	{
  22.894 +		unsigned long va;
  22.895 +		int f;
  22.896 +
  22.897 +		for (va = cpu_gdt_descr[cpu].address, f = 0;
  22.898 +		     va < cpu_gdt_descr[cpu].address + cpu_gdt_descr[cpu].size;
  22.899 +		     va += PAGE_SIZE, f++) {
  22.900 +			ctxt.gdt_frames[f] = virt_to_machine(va) >> PAGE_SHIFT;
  22.901 +			make_page_readonly((void *)va);
  22.902 +		}
  22.903 +		ctxt.gdt_ents = cpu_gdt_descr[cpu].size / 8;
  22.904 +		flush_page_update_queue();
  22.905 +	}
  22.906 +
  22.907 +	/* Ring 1 stack is the initial stack. */
  22.908 +	ctxt.kernel_ss  = __KERNEL_DS;
  22.909 +	ctxt.kernel_esp = idle->thread.esp;
  22.910 +
  22.911 +	/* Callback handlers. */
  22.912 +	ctxt.event_callback_cs     = __KERNEL_CS;
  22.913 +	ctxt.event_callback_eip    = (unsigned long)hypervisor_callback;
  22.914 +	ctxt.failsafe_callback_cs  = __KERNEL_CS;
  22.915 +	ctxt.failsafe_callback_eip = (unsigned long)failsafe_callback;
  22.916 +
  22.917 +	ctxt.pt_base = (unsigned long)virt_to_machine(swapper_pg_dir);
  22.918 +
  22.919 +	boot_error = HYPERVISOR_boot_vcpu(cpu, &ctxt);
  22.920 +
  22.921 +	if (!boot_error) {
  22.922 +		/*
  22.923 +		 * allow APs to start initializing.
  22.924 +		 */
  22.925 +		Dprintk("Before Callout %d.\n", cpu);
  22.926 +		cpu_set(cpu, cpu_callout_map);
  22.927 +		Dprintk("After Callout %d.\n", cpu);
  22.928 +
  22.929 +		/*
  22.930 +		 * Wait 5s total for a response
  22.931 +		 */
  22.932 +		for (timeout = 0; timeout < 50000; timeout++) {
  22.933 +			if (cpu_isset(cpu, cpu_callin_map))
  22.934 +				break;	/* It has booted */
  22.935 +			udelay(100);
  22.936 +		}
  22.937 +
  22.938 +		if (cpu_isset(cpu, cpu_callin_map)) {
  22.939 +			/* number CPUs logically, starting from 1 (BSP is 0) */
  22.940 +			Dprintk("OK.\n");
  22.941 +			printk("CPU%d: ", cpu);
  22.942 +			print_cpu_info(&cpu_data[cpu]);
  22.943 +			Dprintk("CPU has booted.\n");
  22.944 +		} else {
  22.945 +			boot_error= 1;
  22.946 +		}
  22.947 +	}
  22.948 +	x86_cpu_to_apicid[cpu] = apicid;
  22.949 +	if (boot_error) {
  22.950 +		/* Try to put things back the way they were before ... */
  22.951 +		unmap_cpu_to_logical_apicid(cpu);
  22.952 +		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
  22.953 +		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
  22.954 +		cpucount--;
  22.955 +	}
  22.956 +
  22.957 +#else
  22.958 +	Dprintk("Setting warm reset code and vector.\n");
  22.959 +
  22.960 +	store_NMI_vector(&nmi_high, &nmi_low);
  22.961 +
  22.962 +	smpboot_setup_warm_reset_vector(start_eip);
  22.963 +
  22.964 +	/*
  22.965 +	 * Starting actual IPI sequence...
  22.966 +	 */
  22.967 +	boot_error = wakeup_secondary_cpu(apicid, start_eip);
  22.968 +
  22.969 +	if (!boot_error) {
  22.970 +		/*
  22.971 +		 * allow APs to start initializing.
  22.972 +		 */
  22.973 +		Dprintk("Before Callout %d.\n", cpu);
  22.974 +		cpu_set(cpu, cpu_callout_map);
  22.975 +		Dprintk("After Callout %d.\n", cpu);
  22.976 +
  22.977 +		/*
  22.978 +		 * Wait 5s total for a response
  22.979 +		 */
  22.980 +		for (timeout = 0; timeout < 50000; timeout++) {
  22.981 +			if (cpu_isset(cpu, cpu_callin_map))
  22.982 +				break;	/* It has booted */
  22.983 +			udelay(100);
  22.984 +		}
  22.985 +
  22.986 +		if (cpu_isset(cpu, cpu_callin_map)) {
  22.987 +			/* number CPUs logically, starting from 1 (BSP is 0) */
  22.988 +			Dprintk("OK.\n");
  22.989 +			printk("CPU%d: ", cpu);
  22.990 +			print_cpu_info(&cpu_data[cpu]);
  22.991 +			Dprintk("CPU has booted.\n");
  22.992 +		} else {
  22.993 +			boot_error= 1;
  22.994 +			if (*((volatile unsigned char *)trampoline_base)
  22.995 +					== 0xA5)
  22.996 +				/* trampoline started but...? */
  22.997 +				printk("Stuck ??\n");
  22.998 +			else
  22.999 +				/* trampoline code not run */
 22.1000 +				printk("Not responding.\n");
 22.1001 +			inquire_remote_apic(apicid);
 22.1002 +		}
 22.1003 +	}
 22.1004 +	x86_cpu_to_apicid[cpu] = apicid;
 22.1005 +	if (boot_error) {
 22.1006 +		/* Try to put things back the way they were before ... */
 22.1007 +		unmap_cpu_to_logical_apicid(cpu);
 22.1008 +		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
 22.1009 +		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
 22.1010 +		cpucount--;
 22.1011 +	}
 22.1012 +
 22.1013 +	/* mark "stuck" area as not stuck */
 22.1014 +	*((volatile unsigned long *)trampoline_base) = 0;
 22.1015 +#endif
 22.1016 +
 22.1017 +	return boot_error;
 22.1018 +}
 22.1019 +
 22.1020 +cycles_t cacheflush_time;
 22.1021 +unsigned long cache_decay_ticks;
 22.1022 +
 22.1023 +static void smp_tune_scheduling (void)
 22.1024 +{
 22.1025 +	unsigned long cachesize;       /* kB   */
 22.1026 +	unsigned long bandwidth = 350; /* MB/s */
 22.1027 +	/*
 22.1028 +	 * Rough estimation for SMP scheduling, this is the number of
 22.1029 +	 * cycles it takes for a fully memory-limited process to flush
 22.1030 +	 * the SMP-local cache.
 22.1031 +	 *
 22.1032 +	 * (For a P5 this pretty much means we will choose another idle
 22.1033 +	 *  CPU almost always at wakeup time (this is due to the small
 22.1034 +	 *  L1 cache), on PIIs it's around 50-100 usecs, depending on
 22.1035 +	 *  the cache size)
 22.1036 +	 */
 22.1037 +
 22.1038 +	if (!cpu_khz) {
 22.1039 +		/*
 22.1040 +		 * this basically disables processor-affinity
 22.1041 +		 * scheduling on SMP without a TSC.
 22.1042 +		 */
 22.1043 +		cacheflush_time = 0;
 22.1044 +		return;
 22.1045 +	} else {
 22.1046 +		cachesize = boot_cpu_data.x86_cache_size;
 22.1047 +		if (cachesize == -1) {
 22.1048 +			cachesize = 16; /* Pentiums, 2x8kB cache */
 22.1049 +			bandwidth = 100;
 22.1050 +		}
 22.1051 +
 22.1052 +		cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth;
 22.1053 +	}
 22.1054 +
 22.1055 +	cache_decay_ticks = (long)cacheflush_time/cpu_khz + 1;
 22.1056 +
 22.1057 +	printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
 22.1058 +		(long)cacheflush_time/(cpu_khz/1000),
 22.1059 +		((long)cacheflush_time*100/(cpu_khz/1000)) % 100);
 22.1060 +	printk("task migration cache decay timeout: %ld msecs.\n",
 22.1061 +		cache_decay_ticks);
 22.1062 +}
 22.1063 +
 22.1064 +/*
 22.1065 + * Cycle through the processors sending APIC IPIs to boot each.
 22.1066 + */
 22.1067 +
 22.1068 +#if 0
 22.1069 +static int boot_cpu_logical_apicid;
 22.1070 +#endif
 22.1071 +/* Where the IO area was mapped on multiquad, always 0 otherwise */
 22.1072 +void *xquad_portio;
 22.1073 +
 22.1074 +cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 22.1075 +
 22.1076 +static void __init smp_boot_cpus(unsigned int max_cpus)
 22.1077 +{
 22.1078 +	int cpu, kicked;
 22.1079 +	unsigned long bogosum = 0;
 22.1080 +#if 0
 22.1081 +	int apicid, bit;
 22.1082 +#endif
 22.1083 +
 22.1084 +	/*
 22.1085 +	 * Setup boot CPU information
 22.1086 +	 */
 22.1087 +	smp_store_cpu_info(0); /* Final full version of the data */
 22.1088 +	printk("CPU%d: ", 0);
 22.1089 +	print_cpu_info(&cpu_data[0]);
 22.1090 +
 22.1091 +#if 0
 22.1092 +	boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID));
 22.1093 +	boot_cpu_logical_apicid = logical_smp_processor_id();
 22.1094 +	x86_cpu_to_apicid[0] = boot_cpu_physical_apicid;
 22.1095 +#else
 22.1096 +	// boot_cpu_physical_apicid = 0;
 22.1097 +	// boot_cpu_logical_apicid = 0;
 22.1098 +	x86_cpu_to_apicid[0] = 0;
 22.1099 +#endif
 22.1100 +
 22.1101 +	current_thread_info()->cpu = 0;
 22.1102 +	smp_tune_scheduling();
 22.1103 +	cpus_clear(cpu_sibling_map[0]);
 22.1104 +	cpu_set(0, cpu_sibling_map[0]);
 22.1105 +
 22.1106 +	/*
 22.1107 +	 * If we couldn't find an SMP configuration at boot time,
 22.1108 +	 * get out of here now!
 22.1109 +	 */
 22.1110 +	if (!smp_found_config /* && !acpi_lapic) */) {
 22.1111 +		printk(KERN_NOTICE "SMP motherboard not detected.\n");
 22.1112 +		smpboot_clear_io_apic_irqs();
 22.1113 +#if 0
 22.1114 +		phys_cpu_present_map = physid_mask_of_physid(0);
 22.1115 +		if (APIC_init_uniprocessor())
 22.1116 +			printk(KERN_NOTICE "Local APIC not detected."
 22.1117 +					   " Using dummy APIC emulation.\n");
 22.1118 +#endif
 22.1119 +		map_cpu_to_logical_apicid();
 22.1120 +		return;
 22.1121 +	}
 22.1122 +
 22.1123 +#if 0
 22.1124 +	/*
 22.1125 +	 * Should not be necessary because the MP table should list the boot
 22.1126 +	 * CPU too, but we do it for the sake of robustness anyway.
 22.1127 +	 * Makes no sense to do this check in clustered apic mode, so skip it
 22.1128 +	 */
 22.1129 +	if (!check_phys_apicid_present(boot_cpu_physical_apicid)) {
 22.1130 +		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
 22.1131 +				boot_cpu_physical_apicid);
 22.1132 +		physid_set(hard_smp_processor_id(), phys_cpu_present_map);
 22.1133 +	}
 22.1134 +
 22.1135 +	/*
 22.1136 +	 * If we couldn't find a local APIC, then get out of here now!
 22.1137 +	 */
 22.1138 +	if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) && !cpu_has_apic) {
 22.1139 +		printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
 22.1140 +			boot_cpu_physical_apicid);
 22.1141 +		printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n");
 22.1142 +		smpboot_clear_io_apic_irqs();
 22.1143 +		phys_cpu_present_map = physid_mask_of_physid(0);
 22.1144 +		return;
 22.1145 +	}
 22.1146 +
 22.1147 +	verify_local_APIC();
 22.1148 +#endif
 22.1149 +
 22.1150 +	/*
 22.1151 +	 * If SMP should be disabled, then really disable it!
 22.1152 +	 */
 22.1153 +	if (!max_cpus) {
 22.1154 +		HYPERVISOR_shared_info->n_vcpu = 1;
 22.1155 +		printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
 22.1156 +		smpboot_clear_io_apic_irqs();
 22.1157 +#if 0
 22.1158 +		phys_cpu_present_map = physid_mask_of_physid(0);
 22.1159 +#endif
 22.1160 +		return;
 22.1161 +	}
 22.1162 +
 22.1163 +	smp_intr_init();
 22.1164 +
 22.1165 +#if 0
 22.1166 +	connect_bsp_APIC();
 22.1167 +	setup_local_APIC();
 22.1168 +#endif
 22.1169 +	map_cpu_to_logical_apicid();
 22.1170 +#if 0
 22.1171 +
 22.1172 +
 22.1173 +	setup_portio_remap();
 22.1174 +
 22.1175 +	/*
 22.1176 +	 * Scan the CPU present map and fire up the other CPUs via do_boot_cpu
 22.1177 +	 *
 22.1178 +	 * In clustered apic mode, phys_cpu_present_map is a constructed thus:
 22.1179 +	 * bits 0-3 are quad0, 4-7 are quad1, etc. A perverse twist on the 
 22.1180 +	 * clustered apic ID.
 22.1181 +	 */
 22.1182 +	Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
 22.1183 +#endif
 22.1184 +	Dprintk("CPU present map: %lx\n",
 22.1185 +		(1UL << HYPERVISOR_shared_info->n_vcpu) - 1);
 22.1186 +
 22.1187 +	kicked = 1;
 22.1188 +	for (cpu = 1; kicked < NR_CPUS &&
 22.1189 +		     cpu < HYPERVISOR_shared_info->n_vcpu; cpu++) {
 22.1190 +		if (max_cpus <= cpucount+1)
 22.1191 +			continue;
 22.1192 +
 22.1193 +		if (do_boot_cpu(cpu))
 22.1194 +			printk("CPU #%d not responding - cannot use it.\n",
 22.1195 +								cpu);
 22.1196 +		else
 22.1197 +			++kicked;
 22.1198 +	}
 22.1199 +
 22.1200 +#if 0
 22.1201 +	/*
 22.1202 +	 * Cleanup possible dangling ends...
 22.1203 +	 */
 22.1204 +	smpboot_restore_warm_reset_vector();
 22.1205 +#endif
 22.1206 +
 22.1207 +	/*
 22.1208 +	 * Allow the user to impress friends.
 22.1209 +	 */
 22.1210 +	Dprintk("Before bogomips.\n");
 22.1211 +	for (cpu = 0; cpu < NR_CPUS; cpu++)
 22.1212 +		if (cpu_isset(cpu, cpu_callout_map))
 22.1213 +			bogosum += cpu_data[cpu].loops_per_jiffy;
 22.1214 +	printk(KERN_INFO
 22.1215 +		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 22.1216 +		cpucount+1,
 22.1217 +		bogosum/(500000/HZ),
 22.1218 +		(bogosum/(5000/HZ))%100);
 22.1219 +	
 22.1220 +	Dprintk("Before bogocount - setting activated=1.\n");
 22.1221 +
 22.1222 +	if (smp_b_stepping)
 22.1223 +		printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
 22.1224 +
 22.1225 +	/*
 22.1226 +	 * Don't taint if we are running SMP kernel on a single non-MP
 22.1227 +	 * approved Athlon
 22.1228 +	 */
 22.1229 +	if (tainted & TAINT_UNSAFE_SMP) {
 22.1230 +		if (cpucount)
 22.1231 +			printk (KERN_INFO "WARNING: This combination of AMD processors is not suitable for SMP.\n");
 22.1232 +		else
 22.1233 +			tainted &= ~TAINT_UNSAFE_SMP;
 22.1234 +	}
 22.1235 +
 22.1236 +	Dprintk("Boot done.\n");
 22.1237 +
 22.1238 +	/*
 22.1239 +	 * construct cpu_sibling_map[], so that we can tell sibling CPUs
 22.1240 +	 * efficiently.
 22.1241 +	 */
 22.1242 +	for (cpu = 0; cpu < NR_CPUS; cpu++)
 22.1243 +		cpus_clear(cpu_sibling_map[cpu]);
 22.1244 +
 22.1245 +	for (cpu = 0; cpu < NR_CPUS; cpu++) {
 22.1246 +		int siblings = 0;
 22.1247 +		int i;
 22.1248 +		if (!cpu_isset(cpu, cpu_callout_map))
 22.1249 +			continue;
 22.1250 +
 22.1251 +		if (smp_num_siblings > 1) {
 22.1252 +			for (i = 0; i < NR_CPUS; i++) {
 22.1253 +				if (!cpu_isset(i, cpu_callout_map))
 22.1254 +					continue;
 22.1255 +				if (phys_proc_id[cpu] == phys_proc_id[i]) {
 22.1256 +					siblings++;
 22.1257 +					cpu_set(i, cpu_sibling_map[cpu]);
 22.1258 +				}
 22.1259 +			}
 22.1260 +		} else {
 22.1261 +			siblings++;
 22.1262 +			cpu_set(cpu, cpu_sibling_map[cpu]);
 22.1263 +		}
 22.1264 +
 22.1265 +		if (siblings != smp_num_siblings)
 22.1266 +			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
 22.1267 +	}
 22.1268 +
 22.1269 +#if 0
 22.1270 +	if (nmi_watchdog == NMI_LOCAL_APIC)
 22.1271 +		check_nmi_watchdog();
 22.1272 +
 22.1273 +	smpboot_setup_io_apic();
 22.1274 +
 22.1275 +	setup_boot_APIC_clock();
 22.1276 +
 22.1277 +	/*
 22.1278 +	 * Synchronize the TSC with the AP
 22.1279 +	 */
 22.1280 +	if (cpu_has_tsc && cpucount && cpu_khz)
 22.1281 +		synchronize_tsc_bp();
 22.1282 +#endif
 22.1283 +}
 22.1284 +
 22.1285 +/* These are wrappers to interface to the new boot process.  Someone
 22.1286 +