ia64/xen-unstable

changeset 11605:432f978d1cd1

merge with xen-unstable.hg
author awilliam@xenbuild.aw
date Sun Sep 24 13:10:13 2006 -0600 (2006-09-24)
parents da942e577e5e c4f3f719d997
children 1824ee11fc53
files patches/linux-2.6.16.13/blktap-aio-16_03_06.patch patches/linux-2.6.16.13/device_bind.patch patches/linux-2.6.16.13/fix-hz-suspend.patch patches/linux-2.6.16.13/fix-ide-cd-pio-mode.patch patches/linux-2.6.16.13/i386-mach-io-check-nmi.patch patches/linux-2.6.16.13/ipv6-no-autoconf.patch patches/linux-2.6.16.13/net-csum.patch patches/linux-2.6.16.13/net-gso-0-base.patch patches/linux-2.6.16.13/net-gso-1-check-dodgy.patch patches/linux-2.6.16.13/net-gso-2-checksum-fix.patch patches/linux-2.6.16.13/net-gso-3-fix-errorcheck.patch patches/linux-2.6.16.13/net-gso-4-kill-warnon.patch patches/linux-2.6.16.13/pmd-shared.patch patches/linux-2.6.16.13/rcu_needs_cpu.patch patches/linux-2.6.16.13/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch patches/linux-2.6.16.13/series patches/linux-2.6.16.13/smp-alts.patch patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch patches/linux-2.6.16.13/x86-elfnote-as-preprocessor-macro.patch patches/linux-2.6.16.13/x86-increase-interrupt-vector-range.patch patches/linux-2.6.16.13/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch patches/linux-2.6.16.13/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch patches/linux-2.6.16.13/xen-hotplug.patch patches/linux-2.6.16.13/xenoprof-generic.patch tools/python/xen/xm/sysrq.py xen/arch/powerpc/dom0_ops.c
line diff
     1.1 --- a/.hgignore	Thu Sep 21 15:35:45 2006 -0600
     1.2 +++ b/.hgignore	Sun Sep 24 13:10:13 2006 -0600
     1.3 @@ -139,12 +139,15 @@
     1.4  ^tools/security/secpol_tool$
     1.5  ^tools/security/xen/.*$
     1.6  ^tools/tests/test_x86_emulator$
     1.7 +^tools/vnet/Make.local$
     1.8 +^tools/vnet/build/.*$
     1.9  ^tools/vnet/gc$
    1.10  ^tools/vnet/gc.*/.*$
    1.11  ^tools/vnet/vnet-module/.*\.ko$
    1.12  ^tools/vnet/vnet-module/\..*\.cmd$
    1.13  ^tools/vnet/vnet-module/\.tmp_versions/.*$
    1.14  ^tools/vnet/vnet-module/vnet_module\.mod\..*$
    1.15 +^tools/vnet/vnetd/vnetd$
    1.16  ^tools/vtpm/tpm_emulator-.*\.tar\.gz$
    1.17  ^tools/vtpm/tpm_emulator/.*$
    1.18  ^tools/vtpm/vtpm/.*$
     2.1 --- a/buildconfigs/linux-defconfig_xen0_ia64	Thu Sep 21 15:35:45 2006 -0600
     2.2 +++ b/buildconfigs/linux-defconfig_xen0_ia64	Sun Sep 24 13:10:13 2006 -0600
     2.3 @@ -1040,6 +1040,7 @@ CONFIG_SND_ATIIXP=y
     2.4  # CONFIG_SND_ES1938 is not set
     2.5  # CONFIG_SND_ES1968 is not set
     2.6  CONFIG_SND_FM801=y
     2.7 +# CONFIG_SND_FM801_TEA575X_BOOL is not set
     2.8  CONFIG_SND_FM801_TEA575X=y
     2.9  # CONFIG_SND_HDA_INTEL is not set
    2.10  # CONFIG_SND_HDSP is not set
     3.1 --- a/buildconfigs/linux-defconfig_xenU_ia64	Thu Sep 21 15:35:45 2006 -0600
     3.2 +++ b/buildconfigs/linux-defconfig_xenU_ia64	Sun Sep 24 13:10:13 2006 -0600
     3.3 @@ -939,6 +939,7 @@ CONFIG_SND_AC97_BUS=y
     3.4  # CONFIG_SND_ES1938 is not set
     3.5  # CONFIG_SND_ES1968 is not set
     3.6  CONFIG_SND_FM801=y
     3.7 +# CONFIG_SND_FM801_TEA575X_BOOL is not set
     3.8  CONFIG_SND_FM801_TEA575X=y
     3.9  # CONFIG_SND_HDA_INTEL is not set
    3.10  # CONFIG_SND_HDSP is not set
     4.1 --- a/buildconfigs/linux-defconfig_xen_ia64	Thu Sep 21 15:35:45 2006 -0600
     4.2 +++ b/buildconfigs/linux-defconfig_xen_ia64	Sun Sep 24 13:10:13 2006 -0600
     4.3 @@ -1046,6 +1046,7 @@ CONFIG_SND_ATIIXP=y
     4.4  # CONFIG_SND_ES1938 is not set
     4.5  # CONFIG_SND_ES1968 is not set
     4.6  CONFIG_SND_FM801=y
     4.7 +# CONFIG_SND_FM801_TEA575X_BOOL is not set
     4.8  CONFIG_SND_FM801_TEA575X=y
     4.9  # CONFIG_SND_HDA_INTEL is not set
    4.10  # CONFIG_SND_HDSP is not set
     5.1 --- a/buildconfigs/linux-defconfig_xen_x86_32	Thu Sep 21 15:35:45 2006 -0600
     5.2 +++ b/buildconfigs/linux-defconfig_xen_x86_32	Sun Sep 24 13:10:13 2006 -0600
     5.3 @@ -2377,6 +2377,7 @@ CONFIG_SND_ENS1371=m
     5.4  CONFIG_SND_ES1938=m
     5.5  CONFIG_SND_ES1968=m
     5.6  CONFIG_SND_FM801=m
     5.7 +# CONFIG_SND_FM801_TEA575X_BOOL is not set
     5.8  CONFIG_SND_FM801_TEA575X=m
     5.9  CONFIG_SND_HDA_INTEL=m
    5.10  CONFIG_SND_HDSP=m
     6.1 --- a/buildconfigs/linux-defconfig_xen_x86_64	Thu Sep 21 15:35:45 2006 -0600
     6.2 +++ b/buildconfigs/linux-defconfig_xen_x86_64	Sun Sep 24 13:10:13 2006 -0600
     6.3 @@ -2237,6 +2237,7 @@ CONFIG_SND_ENS1371=m
     6.4  CONFIG_SND_ES1938=m
     6.5  CONFIG_SND_ES1968=m
     6.6  CONFIG_SND_FM801=m
     6.7 +# CONFIG_SND_FM801_TEA575X_BOOL is not set
     6.8  CONFIG_SND_FM801_TEA575X=m
     6.9  CONFIG_SND_HDA_INTEL=m
    6.10  CONFIG_SND_HDSP=m
     7.1 --- a/buildconfigs/mk.linux-2.6-xen	Thu Sep 21 15:35:45 2006 -0600
     7.2 +++ b/buildconfigs/mk.linux-2.6-xen	Sun Sep 24 13:10:13 2006 -0600
     7.3 @@ -1,5 +1,5 @@
     7.4  LINUX_SERIES = 2.6
     7.5 -LINUX_VER    = 2.6.16.13
     7.6 +LINUX_VER    = 2.6.16.29
     7.7  
     7.8  EXTRAVERSION ?= xen
     7.9  
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/extras/mini-os/arch/x86/setup.c	Sun Sep 24 13:10:13 2006 -0600
     8.3 @@ -0,0 +1,108 @@
     8.4 +/******************************************************************************
     8.5 + * common.c
     8.6 + * 
     8.7 + * Common stuff special to x86 goes here.
     8.8 + * 
     8.9 + * Copyright (c) 2002-2003, K A Fraser & R Neugebauer
    8.10 + * Copyright (c) 2005, Grzegorz Milos, Intel Research Cambridge
    8.11 + * 
    8.12 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    8.13 + * of this software and associated documentation files (the "Software"), to
    8.14 + * deal in the Software without restriction, including without limitation the
    8.15 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    8.16 + * sell copies of the Software, and to permit persons to whom the Software is
    8.17 + * furnished to do so, subject to the following conditions:
    8.18 + * 
    8.19 + * The above copyright notice and this permission notice shall be included in
    8.20 + * all copies or substantial portions of the Software.
    8.21 + * 
    8.22 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
    8.23 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
    8.24 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
    8.25 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
    8.26 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
    8.27 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    8.28 + * DEALINGS IN THE SOFTWARE.
    8.29 + *
    8.30 + */
    8.31 +
    8.32 +#include <os.h>
    8.33 +
    8.34 +
    8.35 +/*
    8.36 + * Shared page for communicating with the hypervisor.
    8.37 + * Events flags go here, for example.
    8.38 + */
    8.39 +shared_info_t *HYPERVISOR_shared_info;
    8.40 +
    8.41 +/*
    8.42 + * This structure contains start-of-day info, such as pagetable base pointer,
    8.43 + * address of the shared_info structure, and things like that.
    8.44 + */
    8.45 +union start_info_union start_info_union;
    8.46 +
    8.47 +/*
    8.48 + * Just allocate the kernel stack here. SS:ESP is set up to point here
    8.49 + * in head.S.
    8.50 + */
    8.51 +char stack[8192];
    8.52 +
    8.53 +extern char shared_info[PAGE_SIZE];
    8.54 +
    8.55 +/* Assembler interface fns in entry.S. */
    8.56 +void hypervisor_callback(void);
    8.57 +void failsafe_callback(void);
    8.58 +
    8.59 +#if !defined(CONFIG_X86_PAE)
    8.60 +#define __pte(x) ((pte_t) { (x) } )
    8.61 +#else
    8.62 +#define __pte(x) ({ unsigned long long _x = (x);        \
    8.63 +    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
    8.64 +#endif
    8.65 +
    8.66 +static
    8.67 +shared_info_t *map_shared_info(unsigned long pa)
    8.68 +{
    8.69 +	if ( HYPERVISOR_update_va_mapping(
    8.70 +		(unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) )
    8.71 +	{
    8.72 +		printk("Failed to map shared_info!!\n");
    8.73 +		do_exit();
    8.74 +	}
    8.75 +	return (shared_info_t *)shared_info;
    8.76 +}
    8.77 +
    8.78 +void
    8.79 +arch_init(start_info_t *si)
    8.80 +{
    8.81 +	/* Copy the start_info struct to a globally-accessible area. */
    8.82 +	/* WARN: don't do printk before here, it uses information from
    8.83 +	   shared_info. Use xprintk instead. */
    8.84 +	memcpy(&start_info, si, sizeof(*si));
    8.85 +
    8.86 +	/* set up minimal memory infos */
    8.87 +	phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
    8.88 +
    8.89 +	/* Grab the shared_info pointer and put it in a safe place. */
    8.90 +	HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
    8.91 +
    8.92 +	    /* Set up event and failsafe callback addresses. */
    8.93 +#ifdef __i386__
    8.94 +	HYPERVISOR_set_callbacks(
    8.95 +		__KERNEL_CS, (unsigned long)hypervisor_callback,
    8.96 +		__KERNEL_CS, (unsigned long)failsafe_callback);
    8.97 +#else
    8.98 +	HYPERVISOR_set_callbacks(
    8.99 +		(unsigned long)hypervisor_callback,
   8.100 +		(unsigned long)failsafe_callback, 0);
   8.101 +#endif
   8.102 +
   8.103 +}
   8.104 +
   8.105 +void
   8.106 +arch_print_info(void)
   8.107 +{
   8.108 +	printk("  stack:      %p-%p\n", stack, stack + 8192);
   8.109 +}
   8.110 +
   8.111 +
     9.1 --- a/extras/mini-os/events.c	Thu Sep 21 15:35:45 2006 -0600
     9.2 +++ b/extras/mini-os/events.c	Sun Sep 24 13:10:13 2006 -0600
     9.3 @@ -88,19 +88,18 @@ void unbind_evtchn(evtchn_port_t port )
     9.4  
     9.5  int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
     9.6  {
     9.7 -	evtchn_op_t op;
     9.8 +	evtchn_bind_virq_t op;
     9.9  
    9.10  	/* Try to bind the virq to a port */
    9.11 -	op.cmd = EVTCHNOP_bind_virq;
    9.12 -	op.u.bind_virq.virq = virq;
    9.13 -	op.u.bind_virq.vcpu = smp_processor_id();
    9.14 +	op.virq = virq;
    9.15 +	op.vcpu = smp_processor_id();
    9.16  
    9.17 -	if ( HYPERVISOR_event_channel_op(&op) != 0 )
    9.18 +	if ( HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op) != 0 )
    9.19  	{
    9.20  		printk("Failed to bind virtual IRQ %d\n", virq);
    9.21  		return 1;
    9.22      }
    9.23 -    bind_evtchn(op.u.bind_virq.port, handler, data);
    9.24 +    bind_evtchn(op.port, handler, data);
    9.25  	return 0;
    9.26  }
    9.27  
    9.28 @@ -151,14 +150,13 @@ void default_handler(evtchn_port_t port,
    9.29  int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
    9.30  						 void *data, evtchn_port_t *port)
    9.31  {
    9.32 -    evtchn_op_t op;
    9.33 -    op.cmd = EVTCHNOP_alloc_unbound;
    9.34 -    op.u.alloc_unbound.dom = DOMID_SELF;
    9.35 -    op.u.alloc_unbound.remote_dom = pal;
    9.36 -    int err = HYPERVISOR_event_channel_op(&op);
    9.37 +    evtchn_alloc_unbound_t op;
    9.38 +    op.dom = DOMID_SELF;
    9.39 +    op.remote_dom = pal;
    9.40 +    int err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
    9.41      if (err)
    9.42  		return err;
    9.43 -    *port = bind_evtchn(op.u.alloc_unbound.port, handler, data);
    9.44 +    *port = bind_evtchn(op.port, handler, data);
    9.45      return err;
    9.46  }
    9.47  
    9.48 @@ -169,14 +167,13 @@ int evtchn_bind_interdomain(domid_t pal,
    9.49  			    evtchn_handler_t handler, void *data,
    9.50  			    evtchn_port_t *local_port)
    9.51  {
    9.52 -    evtchn_op_t op;
    9.53 -    op.cmd = EVTCHNOP_bind_interdomain;
    9.54 -    op.u.bind_interdomain.remote_dom = pal;
    9.55 -    op.u.bind_interdomain.remote_port = remote_port;
    9.56 -    int err = HYPERVISOR_event_channel_op(&op);
    9.57 +    evtchn_bind_interdomain_t op;
    9.58 +    op.remote_dom = pal;
    9.59 +    op.remote_port = remote_port;
    9.60 +    int err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
    9.61      if (err)
    9.62  		return err;
    9.63 -	evtchn_port_t port = op.u.bind_interdomain.local_port;
    9.64 +	evtchn_port_t port = op.local_port;
    9.65      clear_evtchn(port);	      /* Without, handler gets invoked now! */
    9.66      *local_port = bind_evtchn(port, handler, data);
    9.67      return err;
    10.1 --- a/extras/mini-os/include/events.h	Thu Sep 21 15:35:45 2006 -0600
    10.2 +++ b/extras/mini-os/include/events.h	Sun Sep 24 13:10:13 2006 -0600
    10.3 @@ -39,10 +39,9 @@ int evtchn_bind_interdomain(domid_t pal,
    10.4  
    10.5  static inline int notify_remote_via_evtchn(evtchn_port_t port)
    10.6  {
    10.7 -    evtchn_op_t op;
    10.8 -    op.cmd = EVTCHNOP_send;
    10.9 -    op.u.send.port = port;
   10.10 -    return HYPERVISOR_event_channel_op(&op);
   10.11 +    evtchn_send_t op;
   10.12 +    op.port = port;
   10.13 +    return HYPERVISOR_event_channel_op(EVTCHNOP_send, &op);
   10.14  }
   10.15  
   10.16  
    11.1 --- a/extras/mini-os/include/x86/os.h	Thu Sep 21 15:35:45 2006 -0600
    11.2 +++ b/extras/mini-os/include/x86/os.h	Sun Sep 24 13:10:13 2006 -0600
    11.3 @@ -61,6 +61,11 @@ extern shared_info_t *HYPERVISOR_shared_
    11.4  
    11.5  void trap_init(void);
    11.6  
    11.7 +void arch_init(start_info_t *si);
    11.8 +void arch_print_info(void);
    11.9 +
   11.10 +
   11.11 +
   11.12  
   11.13  
   11.14  /* 
    12.1 --- a/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h	Thu Sep 21 15:35:45 2006 -0600
    12.2 +++ b/extras/mini-os/include/x86/x86_32/hypercall-x86_32.h	Sun Sep 24 13:10:13 2006 -0600
    12.3 @@ -238,9 +238,9 @@ HYPERVISOR_update_va_mapping(
    12.4  
    12.5  static inline int
    12.6  HYPERVISOR_event_channel_op(
    12.7 -	void *op)
    12.8 +	int cmd, void *op)
    12.9  {
   12.10 -	return _hypercall1(int, event_channel_op, op);
   12.11 +	return _hypercall2(int, event_channel_op, cmd, op);
   12.12  }
   12.13  
   12.14  static inline int
    13.1 --- a/extras/mini-os/kernel.c	Thu Sep 21 15:35:45 2006 -0600
    13.2 +++ b/extras/mini-os/kernel.c	Sun Sep 24 13:10:13 2006 -0600
    13.3 @@ -39,49 +39,6 @@
    13.4  #include <xen/features.h>
    13.5  #include <xen/version.h>
    13.6  
    13.7 -/*
    13.8 - * Shared page for communicating with the hypervisor.
    13.9 - * Events flags go here, for example.
   13.10 - */
   13.11 -shared_info_t *HYPERVISOR_shared_info;
   13.12 -
   13.13 -/*
   13.14 - * This structure contains start-of-day info, such as pagetable base pointer,
   13.15 - * address of the shared_info structure, and things like that.
   13.16 - */
   13.17 -union start_info_union start_info_union;
   13.18 -
   13.19 -/*
   13.20 - * Just allocate the kernel stack here. SS:ESP is set up to point here
   13.21 - * in head.S.
   13.22 - */
   13.23 -char stack[8192];
   13.24 -
   13.25 -
   13.26 -/* Assembler interface fns in entry.S. */
   13.27 -void hypervisor_callback(void);
   13.28 -void failsafe_callback(void);
   13.29 -
   13.30 -extern char shared_info[PAGE_SIZE];
   13.31 -
   13.32 -#if !defined(CONFIG_X86_PAE)
   13.33 -#define __pte(x) ((pte_t) { (x) } )
   13.34 -#else
   13.35 -#define __pte(x) ({ unsigned long long _x = (x);        \
   13.36 -    ((pte_t) {(unsigned long)(_x), (unsigned long)(_x>>32)}); })
   13.37 -#endif
   13.38 -
   13.39 -static shared_info_t *map_shared_info(unsigned long pa)
   13.40 -{
   13.41 -    if ( HYPERVISOR_update_va_mapping(
   13.42 -        (unsigned long)shared_info, __pte(pa | 7), UVMF_INVLPG) )
   13.43 -    {
   13.44 -        printk("Failed to map shared_info!!\n");
   13.45 -        do_exit();
   13.46 -    }
   13.47 -    return (shared_info_t *)shared_info;
   13.48 -}
   13.49 -
   13.50  
   13.51  u8 xen_features[XENFEAT_NR_SUBMAPS * 32];
   13.52  
   13.53 @@ -126,27 +83,8 @@ void start_kernel(start_info_t *si)
   13.54  
   13.55      (void)HYPERVISOR_console_io(CONSOLEIO_write, strlen(hello), hello);
   13.56  
   13.57 -    /* Copy the start_info struct to a globally-accessible area. */
   13.58 -    /* WARN: don't do printk before here, it uses information from
   13.59 -       shared_info. Use xprintk instead. */
   13.60 -    memcpy(&start_info, si, sizeof(*si));
   13.61 -    
   13.62 -    /* set up minimal memory infos */
   13.63 -    phys_to_machine_mapping = (unsigned long *)start_info.mfn_list;
   13.64 +    arch_init(si);
   13.65  
   13.66 -    /* Grab the shared_info pointer and put it in a safe place. */
   13.67 -    HYPERVISOR_shared_info = map_shared_info(start_info.shared_info);
   13.68 -
   13.69 -    /* Set up event and failsafe callback addresses. */
   13.70 -#ifdef __i386__
   13.71 -    HYPERVISOR_set_callbacks(
   13.72 -        __KERNEL_CS, (unsigned long)hypervisor_callback,
   13.73 -        __KERNEL_CS, (unsigned long)failsafe_callback);
   13.74 -#else
   13.75 -    HYPERVISOR_set_callbacks(
   13.76 -        (unsigned long)hypervisor_callback,
   13.77 -        (unsigned long)failsafe_callback, 0);
   13.78 -#endif
   13.79      trap_init();
   13.80  
   13.81      /* ENABLE EVENT DELIVERY. This is disabled at start of day. */
   13.82 @@ -163,7 +101,8 @@ void start_kernel(start_info_t *si)
   13.83      printk("  flags:      0x%x\n",  (unsigned int)si->flags);
   13.84      printk("  cmd_line:   %s\n",  
   13.85             si->cmd_line ? (const char *)si->cmd_line : "NULL");
   13.86 -    printk("  stack:      %p-%p\n", stack, stack + 8192);
   13.87 +
   13.88 +    arch_print_info();
   13.89  
   13.90      setup_xen_features();
   13.91  
    14.1 --- a/linux-2.6-xen-sparse/arch/i386/Kconfig	Thu Sep 21 15:35:45 2006 -0600
    14.2 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig	Sun Sep 24 13:10:13 2006 -0600
    14.3 @@ -789,6 +789,9 @@ config DOUBLEFAULT
    14.4  
    14.5  endmenu
    14.6  
    14.7 +config ARCH_ENABLE_MEMORY_HOTPLUG
    14.8 +	def_bool y
    14.9 +	depends on HIGHMEM
   14.10  
   14.11  menu "Power management options (ACPI, APM)"
   14.12  	depends on !(X86_VOYAGER || XEN_UNPRIVILEGED_GUEST)
    15.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Thu Sep 21 15:35:45 2006 -0600
    15.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c	Sun Sep 24 13:10:13 2006 -0600
    15.3 @@ -65,6 +65,7 @@
    15.4  #include <xen/interface/physdev.h>
    15.5  #include <xen/interface/memory.h>
    15.6  #include <xen/features.h>
    15.7 +#include <xen/xencons.h>
    15.8  #include "setup_arch_pre.h"
    15.9  #include <bios_ebda.h>
   15.10  
   15.11 @@ -155,6 +156,9 @@ struct ist_info ist_info;
   15.12  EXPORT_SYMBOL(ist_info);
   15.13  #endif
   15.14  struct e820map e820;
   15.15 +#ifdef CONFIG_XEN
   15.16 +struct e820map machine_e820;
   15.17 +#endif
   15.18  
   15.19  extern void early_cpu_init(void);
   15.20  extern void generic_apic_probe(char *);
   15.21 @@ -1450,7 +1454,6 @@ e820_setup_gap(struct e820entry *e820, i
   15.22  static void __init register_memory(void)
   15.23  {
   15.24  #ifdef CONFIG_XEN
   15.25 -	struct e820entry *machine_e820;
   15.26  	struct xen_memory_map memmap;
   15.27  #endif
   15.28  	int	      i;
   15.29 @@ -1460,14 +1463,14 @@ static void __init register_memory(void)
   15.30  		return;
   15.31  
   15.32  #ifdef CONFIG_XEN
   15.33 -	machine_e820 = alloc_bootmem_low_pages(PAGE_SIZE);
   15.34 -
   15.35  	memmap.nr_entries = E820MAX;
   15.36 -	set_xen_guest_handle(memmap.buffer, machine_e820);
   15.37 +	set_xen_guest_handle(memmap.buffer, machine_e820.map);
   15.38  
   15.39 -	BUG_ON(HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap));
   15.40 +	if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap))
   15.41 +		BUG();
   15.42 +	machine_e820.nr_map = memmap.nr_entries;
   15.43  
   15.44 -	legacy_init_iomem_resources(machine_e820, memmap.nr_entries,
   15.45 +	legacy_init_iomem_resources(machine_e820.map, machine_e820.nr_map,
   15.46  				    &code_resource, &data_resource);
   15.47  #else
   15.48  	if (efi_enabled)
   15.49 @@ -1485,8 +1488,7 @@ static void __init register_memory(void)
   15.50  		request_resource(&ioport_resource, &standard_io_resources[i]);
   15.51  
   15.52  #ifdef CONFIG_XEN
   15.53 -	e820_setup_gap(machine_e820, memmap.nr_entries);
   15.54 -	free_bootmem(__pa(machine_e820), PAGE_SIZE);
   15.55 +	e820_setup_gap(machine_e820.map, machine_e820.nr_map);
   15.56  #else
   15.57  	e820_setup_gap(e820.map, e820.nr_map);
   15.58  #endif
   15.59 @@ -1665,33 +1667,15 @@ void __init setup_arch(char **cmdline_p)
   15.60  		screen_info.orig_video_cols = 80;
   15.61  		screen_info.orig_video_ega_bx = 3;
   15.62  		screen_info.orig_video_points = 16;
   15.63 +		screen_info.orig_y = screen_info.orig_video_lines - 1;
   15.64  		if (xen_start_info->console.dom0.info_size >=
   15.65  		    sizeof(struct dom0_vga_console_info)) {
   15.66  			const struct dom0_vga_console_info *info =
   15.67  				(struct dom0_vga_console_info *)(
   15.68  					(char *)xen_start_info +
   15.69  					xen_start_info->console.dom0.info_off);
   15.70 -			screen_info.orig_video_mode = info->txt_mode;
   15.71 -			screen_info.orig_video_isVGA = info->video_type;
   15.72 -			screen_info.orig_video_lines = info->video_height;
   15.73 -			screen_info.orig_video_cols = info->video_width;
   15.74 -			screen_info.orig_video_points = info->txt_points;
   15.75 -			screen_info.lfb_width = info->video_width;
   15.76 -			screen_info.lfb_height = info->video_height;
   15.77 -			screen_info.lfb_depth = info->lfb_depth;
   15.78 -			screen_info.lfb_base = info->lfb_base;
   15.79 -			screen_info.lfb_size = info->lfb_size;
   15.80 -			screen_info.lfb_linelength = info->lfb_linelen;
   15.81 -			screen_info.red_size = info->red_size;
   15.82 -			screen_info.red_pos = info->red_pos;
   15.83 -			screen_info.green_size = info->green_size;
   15.84 -			screen_info.green_pos = info->green_pos;
   15.85 -			screen_info.blue_size = info->blue_size;
   15.86 -			screen_info.blue_pos = info->blue_pos;
   15.87 -			screen_info.rsvd_size = info->rsvd_size;
   15.88 -			screen_info.rsvd_pos = info->rsvd_pos;
   15.89 +			dom0_init_screen_info(info);
   15.90  		}
   15.91 -		screen_info.orig_y = screen_info.orig_video_lines - 1;
   15.92  		xen_start_info->console.domU.mfn = 0;
   15.93  		xen_start_info->console.domU.evtchn = 0;
   15.94  	} else
    16.1 --- a/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c	Thu Sep 21 15:35:45 2006 -0600
    16.2 +++ b/linux-2.6-xen-sparse/arch/i386/oprofile/xenoprof.c	Sun Sep 24 13:10:13 2006 -0600
    16.3 @@ -32,6 +32,8 @@
    16.4  #include <../../../drivers/oprofile/cpu_buffer.h>
    16.5  #include <../../../drivers/oprofile/event_buffer.h>
    16.6  
    16.7 +#define MAX_XENOPROF_SAMPLES 16
    16.8 +
    16.9  static int xenoprof_start(void);
   16.10  static void xenoprof_stop(void);
   16.11  
   16.12 @@ -43,7 +45,7 @@ static int active_defined;
   16.13  /* sample buffers shared with Xen */
   16.14  xenoprof_buf_t * xenoprof_buf[MAX_VIRT_CPUS];
   16.15  /* Shared buffer area */
   16.16 -char * shared_buffer;
   16.17 +char * shared_buffer = NULL;
   16.18  /* Number of buffers in shared area (one per VCPU) */
   16.19  int nbuf;
   16.20  /* Mappings of VIRQ_XENOPROF to irq number (per cpu) */
   16.21 @@ -233,13 +235,57 @@ static int bind_virq(void)
   16.22  }
   16.23  
   16.24  
   16.25 +static int map_xenoprof_buffer(int max_samples)
   16.26 +{
   16.27 +	struct xenoprof_get_buffer get_buffer;
   16.28 +	struct xenoprof_buf *buf;
   16.29 +	int npages, ret, i;
   16.30 +	struct vm_struct *area;
   16.31 +
   16.32 +	if ( shared_buffer )
   16.33 +		return 0;
   16.34 +
   16.35 +	get_buffer.max_samples = max_samples;
   16.36 +
   16.37 +	if ( (ret = HYPERVISOR_xenoprof_op(XENOPROF_get_buffer, &get_buffer)) )
   16.38 +		return ret;
   16.39 +
   16.40 +	nbuf = get_buffer.nbuf;
   16.41 +	npages = (get_buffer.bufsize * nbuf - 1) / PAGE_SIZE + 1;
   16.42 +
   16.43 +	area = alloc_vm_area(npages * PAGE_SIZE);
   16.44 +	if (area == NULL)
   16.45 +		return -ENOMEM;
   16.46 +
   16.47 +	if ( (ret = direct_kernel_remap_pfn_range(
   16.48 +		      (unsigned long)area->addr,
   16.49 +		      get_buffer.buf_maddr >> PAGE_SHIFT,
   16.50 +		      npages * PAGE_SIZE, __pgprot(_KERNPG_TABLE), DOMID_SELF)) ) {
   16.51 +		vunmap(area->addr);
   16.52 +		return ret;
   16.53 +	}
   16.54 +
   16.55 +	shared_buffer = area->addr;
   16.56 +	for (i=0; i< nbuf; i++) {
   16.57 +		buf = (struct xenoprof_buf*) 
   16.58 +			&shared_buffer[i * get_buffer.bufsize];
   16.59 +		BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
   16.60 +		xenoprof_buf[buf->vcpu_id] = buf;
   16.61 +	}
   16.62 +
   16.63 +	return 0;
   16.64 +}
   16.65 +
   16.66 +
   16.67  static int xenoprof_setup(void)
   16.68  {
   16.69  	int ret;
   16.70  	int i;
   16.71  
   16.72 -	ret = bind_virq();
   16.73 -	if (ret)
   16.74 +	if ( (ret = map_xenoprof_buffer(MAX_XENOPROF_SAMPLES)) )
   16.75 +		return ret;
   16.76 +
   16.77 +	if ( (ret = bind_virq()) )
   16.78  		return ret;
   16.79  
   16.80  	if (is_primary) {
   16.81 @@ -482,51 +528,19 @@ static int using_xenoprof;
   16.82  int __init oprofile_arch_init(struct oprofile_operations * ops)
   16.83  {
   16.84  	struct xenoprof_init init;
   16.85 -	struct xenoprof_buf *buf;
   16.86 -	int npages, ret, i;
   16.87 -	struct vm_struct *area;
   16.88 +	int ret, i;
   16.89  
   16.90 -	init.max_samples = 16;
   16.91  	ret = HYPERVISOR_xenoprof_op(XENOPROF_init, &init);
   16.92  
   16.93  	if (!ret) {
   16.94 -		pgprot_t prot = __pgprot(_KERNPG_TABLE);
   16.95 -
   16.96  		num_events = init.num_events;
   16.97  		is_primary = init.is_primary;
   16.98 -		nbuf = init.nbuf;
   16.99  
  16.100  		/* just in case - make sure we do not overflow event list 
  16.101 -                   (i.e. counter_config list) */
  16.102 +		   (i.e. counter_config list) */
  16.103  		if (num_events > OP_MAX_COUNTER)
  16.104  			num_events = OP_MAX_COUNTER;
  16.105  
  16.106 -		npages = (init.bufsize * nbuf - 1) / PAGE_SIZE + 1;
  16.107 -
  16.108 -		area = alloc_vm_area(npages * PAGE_SIZE);
  16.109 -		if (area == NULL) {
  16.110 -			ret = -ENOMEM;
  16.111 -			goto out;
  16.112 -		}
  16.113 -
  16.114 -		ret = direct_kernel_remap_pfn_range(
  16.115 -			(unsigned long)area->addr,
  16.116 -			init.buf_maddr >> PAGE_SHIFT,
  16.117 -			npages * PAGE_SIZE, prot, DOMID_SELF);
  16.118 -		if (ret) {
  16.119 -			vunmap(area->addr);
  16.120 -			goto out;
  16.121 -		}
  16.122 -
  16.123 -		shared_buffer = area->addr;
  16.124 -
  16.125 -		for (i=0; i< nbuf; i++) {
  16.126 -			buf = (struct xenoprof_buf*) 
  16.127 -				&shared_buffer[i * init.bufsize];
  16.128 -			BUG_ON(buf->vcpu_id >= MAX_VIRT_CPUS);
  16.129 -			xenoprof_buf[buf->vcpu_id] = buf;
  16.130 -		}
  16.131 -
  16.132  		/*  cpu_type is detected by Xen */
  16.133  		cpu_type[XENOPROF_CPU_TYPE_SIZE-1] = 0;
  16.134  		strncpy(cpu_type, init.cpu_type, XENOPROF_CPU_TYPE_SIZE - 1);
  16.135 @@ -541,7 +555,6 @@ int __init oprofile_arch_init(struct opr
  16.136  
  16.137  		active_defined = 0;
  16.138  	}
  16.139 - out:
  16.140  	printk(KERN_INFO "oprofile_arch_init: ret %d, events %d, "
  16.141  	       "is_primary %d\n", ret, num_events, is_primary);
  16.142  	return ret;
    17.1 --- a/linux-2.6-xen-sparse/arch/ia64/Kconfig	Thu Sep 21 15:35:45 2006 -0600
    17.2 +++ b/linux-2.6-xen-sparse/arch/ia64/Kconfig	Sun Sep 24 13:10:13 2006 -0600
    17.3 @@ -276,6 +276,9 @@ config HOTPLUG_CPU
    17.4  	  can be controlled through /sys/devices/system/cpu/cpu#.
    17.5  	  Say N if you want to disable CPU hotplug.
    17.6  
    17.7 +config ARCH_ENABLE_MEMORY_HOTPLUG
    17.8 +	def_bool y
    17.9 +
   17.10  config SCHED_SMT
   17.11  	bool "SMT scheduler support"
   17.12  	depends on SMP
    18.1 --- a/linux-2.6-xen-sparse/arch/ia64/dig/setup.c	Thu Sep 21 15:35:45 2006 -0600
    18.2 +++ b/linux-2.6-xen-sparse/arch/ia64/dig/setup.c	Sun Sep 24 13:10:13 2006 -0600
    18.3 @@ -25,6 +25,8 @@
    18.4  #include <asm/machvec.h>
    18.5  #include <asm/system.h>
    18.6  
    18.7 +#include <xen/xencons.h>
    18.8 +
    18.9  void __init
   18.10  dig_setup (char **cmdline_p)
   18.11  {
   18.12 @@ -78,27 +80,8 @@ dig_setup (char **cmdline_p)
   18.13  		        (struct dom0_vga_console_info *)(
   18.14  		                (char *)xen_start_info +
   18.15  		                xen_start_info->console.dom0.info_off);
   18.16 -		screen_info.orig_video_mode = info->txt_mode;
   18.17 -		screen_info.orig_video_isVGA = info->video_type;
   18.18 -		screen_info.orig_video_lines = info->video_height;
   18.19 -		screen_info.orig_video_cols = info->video_width;
   18.20 -		screen_info.orig_video_points = info->txt_points;
   18.21 -		screen_info.lfb_width = info->video_width;
   18.22 -		screen_info.lfb_height = info->video_height;
   18.23 -		screen_info.lfb_depth = info->lfb_depth;
   18.24 -		screen_info.lfb_base = info->lfb_base;
   18.25 -		screen_info.lfb_size = info->lfb_size;
   18.26 -		screen_info.lfb_linelength = info->lfb_linelen;
   18.27 -		screen_info.red_size = info->red_size;
   18.28 -		screen_info.red_pos = info->red_pos;
   18.29 -		screen_info.green_size = info->green_size;
   18.30 -		screen_info.green_pos = info->green_pos;
   18.31 -		screen_info.blue_size = info->blue_size;
   18.32 -		screen_info.blue_pos = info->blue_pos;
   18.33 -		screen_info.rsvd_size = info->rsvd_size;
   18.34 -		screen_info.rsvd_pos = info->rsvd_pos;
   18.35 +		dom0_init_screen_info(info);
   18.36  	}
   18.37 -	screen_info.orig_y = screen_info.orig_video_lines - 1;
   18.38  	xen_start_info->console.domU.mfn = 0;
   18.39  	xen_start_info->console.domU.evtchn = 0;
   18.40  #endif
    19.1 --- a/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Thu Sep 21 15:35:45 2006 -0600
    19.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/Kconfig	Sun Sep 24 13:10:13 2006 -0600
    19.3 @@ -368,6 +368,8 @@ config HOTPLUG_CPU
    19.4  		can be controlled through /sys/devices/system/cpu/cpu#.
    19.5  		Say N if you want to disable CPU hotplug.
    19.6  
    19.7 +config ARCH_ENABLE_MEMORY_HOTPLUG
    19.8 +	def_bool y
    19.9  
   19.10  config HPET_TIMER
   19.11  	bool
    20.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S	Thu Sep 21 15:35:45 2006 -0600
    20.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/entry-xen.S	Sun Sep 24 13:10:13 2006 -0600
    20.3 @@ -316,12 +316,7 @@ tracesys:
    20.4  	ja  1f
    20.5  	movq %r10,%rcx	/* fixup for C */
    20.6  	call *sys_call_table(,%rax,8)
    20.7 -	movq %rax,RAX-ARGOFFSET(%rsp)
    20.8 -1:	SAVE_REST
    20.9 -	movq %rsp,%rdi
   20.10 -	call syscall_trace_leave
   20.11 -	RESTORE_TOP_OF_STACK %rbx
   20.12 -	RESTORE_REST
   20.13 +1:	movq %rax,RAX-ARGOFFSET(%rsp)
   20.14  	/* Use IRET because user could have changed frame */
   20.15  	jmp int_ret_from_sys_call
   20.16  	CFI_ENDPROC
    21.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Thu Sep 21 15:35:45 2006 -0600
    21.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c	Sun Sep 24 13:10:13 2006 -0600
    21.3 @@ -74,6 +74,7 @@
    21.4  #include <asm/hypervisor.h>
    21.5  #include <xen/interface/nmi.h>
    21.6  #include <xen/features.h>
    21.7 +#include <xen/xencons.h>
    21.8  #define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
    21.9  #define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
   21.10  #include <asm/mach-xen/setup_arch_post.h>
   21.11 @@ -143,6 +144,9 @@ struct sys_desc_table_struct {
   21.12  
   21.13  struct edid_info edid_info;
   21.14  struct e820map e820;
   21.15 +#ifdef CONFIG_XEN
   21.16 +struct e820map machine_e820;
   21.17 +#endif
   21.18  
   21.19  extern int root_mountflags;
   21.20  
   21.21 @@ -625,7 +629,6 @@ static void __init reserve_ebda_region(v
   21.22  void __init setup_arch(char **cmdline_p)
   21.23  {
   21.24  	unsigned long kernel_end;
   21.25 -	struct e820entry *machine_e820;
   21.26  	struct xen_memory_map memmap;
   21.27  
   21.28  #ifdef CONFIG_XEN
   21.29 @@ -645,33 +648,15 @@ void __init setup_arch(char **cmdline_p)
   21.30  		screen_info.orig_video_cols = 80;
   21.31  		screen_info.orig_video_ega_bx = 3;
   21.32  		screen_info.orig_video_points = 16;
   21.33 +		screen_info.orig_y = screen_info.orig_video_lines - 1;
   21.34  		if (xen_start_info->console.dom0.info_size >=
   21.35  		    sizeof(struct dom0_vga_console_info)) {
   21.36  			const struct dom0_vga_console_info *info =
   21.37  				(struct dom0_vga_console_info *)(
   21.38  					(char *)xen_start_info +
   21.39  					xen_start_info->console.dom0.info_off);
   21.40 -			screen_info.orig_video_mode = info->txt_mode;
   21.41 -			screen_info.orig_video_isVGA = info->video_type;
   21.42 -			screen_info.orig_video_lines = info->video_height;
   21.43 -			screen_info.orig_video_cols = info->video_width;
   21.44 -			screen_info.orig_video_points = info->txt_points;
   21.45 -			screen_info.lfb_width = info->video_width;
   21.46 -			screen_info.lfb_height = info->video_height;
   21.47 -			screen_info.lfb_depth = info->lfb_depth;
   21.48 -			screen_info.lfb_base = info->lfb_base;
   21.49 -			screen_info.lfb_size = info->lfb_size;
   21.50 -			screen_info.lfb_linelength = info->lfb_linelen;
   21.51 -			screen_info.red_size = info->red_size;
   21.52 -			screen_info.red_pos = info->red_pos;
   21.53 -			screen_info.green_size = info->green_size;
   21.54 -			screen_info.green_pos = info->green_pos;
   21.55 -			screen_info.blue_size = info->blue_size;
   21.56 -			screen_info.blue_pos = info->blue_pos;
   21.57 -			screen_info.rsvd_size = info->rsvd_size;
   21.58 -			screen_info.rsvd_pos = info->rsvd_pos;
   21.59 +			dom0_init_screen_info(info);
   21.60  		}
   21.61 -		screen_info.orig_y = screen_info.orig_video_lines - 1;
   21.62  		xen_start_info->console.domU.mfn = 0;
   21.63  		xen_start_info->console.domU.evtchn = 0;
   21.64  	} else
   21.65 @@ -936,14 +921,14 @@ void __init setup_arch(char **cmdline_p)
   21.66  	probe_roms();
   21.67  #ifdef CONFIG_XEN
   21.68  	if (is_initial_xendomain()) {
   21.69 -		machine_e820 = alloc_bootmem_low_pages(PAGE_SIZE);
   21.70 -
   21.71  		memmap.nr_entries = E820MAX;
   21.72 -		set_xen_guest_handle(memmap.buffer, machine_e820);
   21.73 +		set_xen_guest_handle(memmap.buffer, machine_e820.map);
   21.74  
   21.75 -		BUG_ON(HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap));
   21.76 +		if (HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap))
   21.77 +			BUG();
   21.78 +		machine_e820.nr_map = memmap.nr_entries;
   21.79  
   21.80 -		e820_reserve_resources(machine_e820, memmap.nr_entries);
   21.81 +		e820_reserve_resources(machine_e820.map, machine_e820.nr_map);
   21.82  	}
   21.83  #else
   21.84  	e820_reserve_resources(e820.map, e820.nr_map);
   21.85 @@ -959,10 +944,8 @@ void __init setup_arch(char **cmdline_p)
   21.86  	}
   21.87  
   21.88  #ifdef CONFIG_XEN
   21.89 -	if (is_initial_xendomain()) {
   21.90 -		e820_setup_gap(machine_e820, memmap.nr_entries);
   21.91 -		free_bootmem(__pa(machine_e820), PAGE_SIZE);
   21.92 -	}
   21.93 +	if (is_initial_xendomain())
   21.94 +		e820_setup_gap(machine_e820.map, machine_e820.nr_map);
   21.95  #else
   21.96  	e820_setup_gap(e820.map, e820.nr_map);
   21.97  #endif
    22.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c	Thu Sep 21 15:35:45 2006 -0600
    22.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/traps-xen.c	Sun Sep 24 13:10:13 2006 -0600
    22.3 @@ -30,6 +30,7 @@
    22.4  #include <linux/moduleparam.h>
    22.5  #include <linux/nmi.h>
    22.6  #include <linux/kprobes.h>
    22.7 +#include <linux/kexec.h>
    22.8  
    22.9  #include <asm/system.h>
   22.10  #include <asm/uaccess.h>
   22.11 @@ -438,6 +439,8 @@ void __kprobes __die(const char * str, s
   22.12  	printk(KERN_ALERT "RIP ");
   22.13  	printk_address(regs->rip); 
   22.14  	printk(" RSP <%016lx>\n", regs->rsp); 
   22.15 +	if (kexec_should_crash(current))
   22.16 +		crash_kexec(regs);
   22.17  }
   22.18  
   22.19  void die(const char * str, struct pt_regs * regs, long err)
   22.20 @@ -461,6 +464,8 @@ void __kprobes die_nmi(char *str, struct
   22.21  	 */
   22.22  	printk(str, safe_smp_processor_id());
   22.23  	show_registers(regs);
   22.24 +	if (kexec_should_crash(current))
   22.25 +		crash_kexec(regs);
   22.26  	if (panic_on_timeout || panic_on_oops)
   22.27  		panic("nmi watchdog");
   22.28  	printk("console shuts up ...\n");
    23.1 --- a/linux-2.6-xen-sparse/drivers/char/tty_io.c	Thu Sep 21 15:35:45 2006 -0600
    23.2 +++ b/linux-2.6-xen-sparse/drivers/char/tty_io.c	Sun Sep 24 13:10:13 2006 -0600
    23.3 @@ -2761,7 +2761,7 @@ static void flush_to_ldisc(void *private
    23.4  	struct tty_struct *tty = (struct tty_struct *) private_;
    23.5  	unsigned long 	flags;
    23.6  	struct tty_ldisc *disc;
    23.7 -	struct tty_buffer *tbuf;
    23.8 +	struct tty_buffer *tbuf, *head;
    23.9  	int count;
   23.10  	char *char_buf;
   23.11  	unsigned char *flag_buf;
   23.12 @@ -2778,7 +2778,9 @@ static void flush_to_ldisc(void *private
   23.13  		goto out;
   23.14  	}
   23.15  	spin_lock_irqsave(&tty->buf.lock, flags);
   23.16 -	while((tbuf = tty->buf.head) != NULL) {
   23.17 +	head = tty->buf.head;
   23.18 +	tty->buf.head = NULL;
   23.19 +	while((tbuf = head) != NULL) {
   23.20  		while ((count = tbuf->commit - tbuf->read) != 0) {
   23.21  			char_buf = tbuf->char_buf_ptr + tbuf->read;
   23.22  			flag_buf = tbuf->flag_buf_ptr + tbuf->read;
   23.23 @@ -2787,10 +2789,12 @@ static void flush_to_ldisc(void *private
   23.24  			disc->receive_buf(tty, char_buf, flag_buf, count);
   23.25  			spin_lock_irqsave(&tty->buf.lock, flags);
   23.26  		}
   23.27 -		if (tbuf->active)
   23.28 +		if (tbuf->active) {
   23.29 +			tty->buf.head = head;
   23.30  			break;
   23.31 -		tty->buf.head = tbuf->next;
   23.32 -		if (tty->buf.head == NULL)
   23.33 +		}
   23.34 +		head = tbuf->next;
   23.35 +		if (head == NULL)
   23.36  			tty->buf.tail = NULL;
   23.37  		tty_buffer_free(tty, tbuf);
   23.38  	}
    24.1 --- a/linux-2.6-xen-sparse/drivers/serial/Kconfig	Thu Sep 21 15:35:45 2006 -0600
    24.2 +++ b/linux-2.6-xen-sparse/drivers/serial/Kconfig	Sun Sep 24 13:10:13 2006 -0600
    24.3 @@ -821,6 +821,7 @@ config SERIAL_ICOM
    24.4  	tristate "IBM Multiport Serial Adapter"
    24.5  	depends on PCI && (PPC_ISERIES || PPC_PSERIES)
    24.6  	select SERIAL_CORE
    24.7 +	select FW_LOADER
    24.8  	help
    24.9  	  This driver is for a family of multiport serial adapters
   24.10  	  including 2 port RVX, 2 port internal modem, 4 port internal
    25.1 --- a/linux-2.6-xen-sparse/drivers/xen/console/console.c	Thu Sep 21 15:35:45 2006 -0600
    25.2 +++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c	Sun Sep 24 13:10:13 2006 -0600
    25.3 @@ -49,6 +49,7 @@
    25.4  #include <linux/console.h>
    25.5  #include <linux/bootmem.h>
    25.6  #include <linux/sysrq.h>
    25.7 +#include <linux/screen_info.h>
    25.8  #include <asm/io.h>
    25.9  #include <asm/irq.h>
   25.10  #include <asm/uaccess.h>
   25.11 @@ -266,6 +267,41 @@ void xencons_force_flush(void)
   25.12  }
   25.13  
   25.14  
   25.15 +void dom0_init_screen_info(const struct dom0_vga_console_info *info)
   25.16 +{
   25.17 +	switch (info->video_type) {
   25.18 +	case XEN_VGATYPE_TEXT_MODE_3:
   25.19 +		screen_info.orig_video_mode = 3;
   25.20 +		screen_info.orig_video_ega_bx = 3;
   25.21 +		screen_info.orig_video_isVGA = 1;
   25.22 +		screen_info.orig_video_lines = info->u.text_mode_3.rows;
   25.23 +		screen_info.orig_video_cols = info->u.text_mode_3.columns;
   25.24 +		screen_info.orig_x = info->u.text_mode_3.cursor_x;
   25.25 +		screen_info.orig_y = info->u.text_mode_3.cursor_y;
   25.26 +		screen_info.orig_video_points =
   25.27 +			info->u.text_mode_3.font_height;
   25.28 +		break;
   25.29 +	case XEN_VGATYPE_VESA_LFB:
   25.30 +		screen_info.orig_video_isVGA = VIDEO_TYPE_VLFB;
   25.31 +		screen_info.lfb_width = info->u.vesa_lfb.width;
   25.32 +		screen_info.lfb_height = info->u.vesa_lfb.height;
   25.33 +		screen_info.lfb_depth = info->u.vesa_lfb.bits_per_pixel;
   25.34 +		screen_info.lfb_base = info->u.vesa_lfb.lfb_base;
   25.35 +		screen_info.lfb_size = info->u.vesa_lfb.lfb_size;
   25.36 +		screen_info.lfb_linelength = info->u.vesa_lfb.bytes_per_line;
   25.37 +		screen_info.red_size = info->u.vesa_lfb.red_size;
   25.38 +		screen_info.red_pos = info->u.vesa_lfb.red_pos;
   25.39 +		screen_info.green_size = info->u.vesa_lfb.green_size;
   25.40 +		screen_info.green_pos = info->u.vesa_lfb.green_pos;
   25.41 +		screen_info.blue_size = info->u.vesa_lfb.blue_size;
   25.42 +		screen_info.blue_pos = info->u.vesa_lfb.blue_pos;
   25.43 +		screen_info.rsvd_size = info->u.vesa_lfb.rsvd_size;
   25.44 +		screen_info.rsvd_pos = info->u.vesa_lfb.rsvd_pos;
   25.45 +		break;
   25.46 +	}
   25.47 +}
   25.48 +
   25.49 +
   25.50  /******************** User-space console driver (/dev/console) ************/
   25.51  
   25.52  #define DRV(_d)         (_d)
    26.1 --- a/linux-2.6-xen-sparse/include/xen/xencons.h	Thu Sep 21 15:35:45 2006 -0600
    26.2 +++ b/linux-2.6-xen-sparse/include/xen/xencons.h	Sun Sep 24 13:10:13 2006 -0600
    26.3 @@ -1,6 +1,9 @@
    26.4  #ifndef __ASM_XENCONS_H__
    26.5  #define __ASM_XENCONS_H__
    26.6  
    26.7 +struct dom0_vga_console_info;
    26.8 +void dom0_init_screen_info(const struct dom0_vga_console_info *info);
    26.9 +
   26.10  void xencons_force_flush(void);
   26.11  void xencons_resume(void);
   26.12  
    27.1 --- a/linux-2.6-xen-sparse/mm/Kconfig	Thu Sep 21 15:35:45 2006 -0600
    27.2 +++ b/linux-2.6-xen-sparse/mm/Kconfig	Sun Sep 24 13:10:13 2006 -0600
    27.3 @@ -115,7 +115,7 @@ config SPARSEMEM_EXTREME
    27.4  # eventually, we can have this option just 'select SPARSEMEM'
    27.5  config MEMORY_HOTPLUG
    27.6  	bool "Allow for memory hot-add"
    27.7 -	depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND
    27.8 +	depends on SPARSEMEM && HOTPLUG && !SOFTWARE_SUSPEND && ARCH_ENABLE_MEMORY_HOTPLUG
    27.9  
   27.10  comment "Memory hotplug is currently incompatible with Software Suspend"
   27.11  	depends on SPARSEMEM && HOTPLUG && SOFTWARE_SUSPEND
    28.1 --- a/linux-2.6-xen-sparse/mm/page_alloc.c	Thu Sep 21 15:35:45 2006 -0600
    28.2 +++ b/linux-2.6-xen-sparse/mm/page_alloc.c	Sun Sep 24 13:10:13 2006 -0600
    28.3 @@ -951,7 +951,8 @@ restart:
    28.4  		alloc_flags |= ALLOC_HARDER;
    28.5  	if (gfp_mask & __GFP_HIGH)
    28.6  		alloc_flags |= ALLOC_HIGH;
    28.7 -	alloc_flags |= ALLOC_CPUSET;
    28.8 +	if (wait)
    28.9 +		alloc_flags |= ALLOC_CPUSET;
   28.10  
   28.11  	/*
   28.12  	 * Go through the zonelist again. Let __GFP_HIGH and allocations
    29.1 --- a/patches/linux-2.6.16.13/blktap-aio-16_03_06.patch	Thu Sep 21 15:35:45 2006 -0600
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,297 +0,0 @@
    29.4 -diff -pruN ../pristine-linux-2.6.16-rc5/fs/aio.c ./fs/aio.c
    29.5 ---- ../pristine-linux-2.6.16-rc5/fs/aio.c	2006-03-14 14:10:10.827401387 +0000
    29.6 -+++ ./fs/aio.c	2006-03-16 09:57:53.898316582 +0000
    29.7 -@@ -34,6 +34,11 @@
    29.8 - #include <asm/uaccess.h>
    29.9 - #include <asm/mmu_context.h>
   29.10 - 
   29.11 -+#ifdef CONFIG_EPOLL
   29.12 -+#include <linux/poll.h>
   29.13 -+#include <linux/eventpoll.h>
   29.14 -+#endif
   29.15 -+
   29.16 - #if DEBUG > 1
   29.17 - #define dprintk		printk
   29.18 - #else
   29.19 -@@ -1016,6 +1021,10 @@ put_rq:
   29.20 - 	if (waitqueue_active(&ctx->wait))
   29.21 - 		wake_up(&ctx->wait);
   29.22 - 
   29.23 -+#ifdef CONFIG_EPOLL
   29.24 -+	if (ctx->file && waitqueue_active(&ctx->poll_wait))
   29.25 -+		wake_up(&ctx->poll_wait);
   29.26 -+#endif
   29.27 - 	if (ret)
   29.28 - 		put_ioctx(ctx);
   29.29 - 
   29.30 -@@ -1025,6 +1034,8 @@ put_rq:
   29.31 - /* aio_read_evt
   29.32 -  *	Pull an event off of the ioctx's event ring.  Returns the number of 
   29.33 -  *	events fetched (0 or 1 ;-)
   29.34 -+ *	If ent parameter is 0, just returns the number of events that would
   29.35 -+ *	be fetched.
   29.36 -  *	FIXME: make this use cmpxchg.
   29.37 -  *	TODO: make the ringbuffer user mmap()able (requires FIXME).
   29.38 -  */
   29.39 -@@ -1047,13 +1058,18 @@ static int aio_read_evt(struct kioctx *i
   29.40 - 
   29.41 - 	head = ring->head % info->nr;
   29.42 - 	if (head != ring->tail) {
   29.43 --		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
   29.44 --		*ent = *evp;
   29.45 --		head = (head + 1) % info->nr;
   29.46 --		smp_mb(); /* finish reading the event before updatng the head */
   29.47 --		ring->head = head;
   29.48 --		ret = 1;
   29.49 --		put_aio_ring_event(evp, KM_USER1);
   29.50 -+		if (ent) { /* event requested */
   29.51 -+			struct io_event *evp =
   29.52 -+				aio_ring_event(info, head, KM_USER1);
   29.53 -+			*ent = *evp;
   29.54 -+			head = (head + 1) % info->nr;
   29.55 -+			/* finish reading the event before updatng the head */
   29.56 -+			smp_mb();
   29.57 -+			ring->head = head;
   29.58 -+			ret = 1;
   29.59 -+			put_aio_ring_event(evp, KM_USER1);
   29.60 -+		} else /* only need to know availability */
   29.61 -+			ret = 1;
   29.62 - 	}
   29.63 - 	spin_unlock(&info->ring_lock);
   29.64 - 
   29.65 -@@ -1236,9 +1252,78 @@ static void io_destroy(struct kioctx *io
   29.66 - 
   29.67 - 	aio_cancel_all(ioctx);
   29.68 - 	wait_for_all_aios(ioctx);
   29.69 -+#ifdef CONFIG_EPOLL
   29.70 -+	/* forget the poll file, but it's up to the user to close it */
   29.71 -+	if (ioctx->file) {
   29.72 -+		ioctx->file->private_data = 0;
   29.73 -+		ioctx->file = 0;
   29.74 -+	}
   29.75 -+#endif
   29.76 - 	put_ioctx(ioctx);	/* once for the lookup */
   29.77 - }
   29.78 - 
   29.79 -+#ifdef CONFIG_EPOLL
   29.80 -+
   29.81 -+static int aio_queue_fd_close(struct inode *inode, struct file *file)
   29.82 -+{
   29.83 -+	struct kioctx *ioctx = file->private_data;
   29.84 -+	if (ioctx) {
   29.85 -+		file->private_data = 0;
   29.86 -+		spin_lock_irq(&ioctx->ctx_lock);
   29.87 -+		ioctx->file = 0;
   29.88 -+		spin_unlock_irq(&ioctx->ctx_lock);
   29.89 -+	}
   29.90 -+	return 0;
   29.91 -+}
   29.92 -+
   29.93 -+static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
   29.94 -+{	unsigned int pollflags = 0;
   29.95 -+	struct kioctx *ioctx = file->private_data;
   29.96 -+
   29.97 -+	if (ioctx) {
   29.98 -+
   29.99 -+		spin_lock_irq(&ioctx->ctx_lock);
  29.100 -+		/* Insert inside our poll wait queue */
  29.101 -+		poll_wait(file, &ioctx->poll_wait, wait);
  29.102 -+
  29.103 -+		/* Check our condition */
  29.104 -+		if (aio_read_evt(ioctx, 0))
  29.105 -+			pollflags = POLLIN | POLLRDNORM;
  29.106 -+		spin_unlock_irq(&ioctx->ctx_lock);
  29.107 -+	}
  29.108 -+
  29.109 -+	return pollflags;
  29.110 -+}
  29.111 -+
  29.112 -+static struct file_operations aioq_fops = {
  29.113 -+	.release	= aio_queue_fd_close,
  29.114 -+	.poll		= aio_queue_fd_poll
  29.115 -+};
  29.116 -+
  29.117 -+/* make_aio_fd:
  29.118 -+ *  Create a file descriptor that can be used to poll the event queue.
  29.119 -+ *  Based and piggybacked on the excellent epoll code.
  29.120 -+ */
  29.121 -+
  29.122 -+static int make_aio_fd(struct kioctx *ioctx)
  29.123 -+{
  29.124 -+	int error, fd;
  29.125 -+	struct inode *inode;
  29.126 -+	struct file *file;
  29.127 -+
  29.128 -+	error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
  29.129 -+	if (error)
  29.130 -+		return error;
  29.131 -+
  29.132 -+	/* associate the file with the IO context */
  29.133 -+	file->private_data = ioctx;
  29.134 -+	ioctx->file = file;
  29.135 -+	init_waitqueue_head(&ioctx->poll_wait);
  29.136 -+	return fd;
  29.137 -+}
  29.138 -+#endif
  29.139 -+
  29.140 -+
  29.141 - /* sys_io_setup:
  29.142 -  *	Create an aio_context capable of receiving at least nr_events.
  29.143 -  *	ctxp must not point to an aio_context that already exists, and
  29.144 -@@ -1251,18 +1336,30 @@ static void io_destroy(struct kioctx *io
  29.145 -  *	resources are available.  May fail with -EFAULT if an invalid
  29.146 -  *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
  29.147 -  *	implemented.
  29.148 -+ *
  29.149 -+ *	To request a selectable fd, the user context has to be initialized
  29.150 -+ *	to 1, instead of 0, and the return value is the fd.
  29.151 -+ *	This keeps the system call compatible, since a non-zero value
  29.152 -+ *	was not allowed so far.
  29.153 -  */
  29.154 - asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
  29.155 - {
  29.156 - 	struct kioctx *ioctx = NULL;
  29.157 - 	unsigned long ctx;
  29.158 - 	long ret;
  29.159 -+	int make_fd = 0;
  29.160 - 
  29.161 - 	ret = get_user(ctx, ctxp);
  29.162 - 	if (unlikely(ret))
  29.163 - 		goto out;
  29.164 - 
  29.165 - 	ret = -EINVAL;
  29.166 -+#ifdef CONFIG_EPOLL
  29.167 -+	if (ctx == 1) {
  29.168 -+		make_fd = 1;
  29.169 -+		ctx = 0;
  29.170 -+	}
  29.171 -+#endif
  29.172 - 	if (unlikely(ctx || nr_events == 0)) {
  29.173 - 		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
  29.174 - 		         ctx, nr_events);
  29.175 -@@ -1273,8 +1370,12 @@ asmlinkage long sys_io_setup(unsigned nr
  29.176 - 	ret = PTR_ERR(ioctx);
  29.177 - 	if (!IS_ERR(ioctx)) {
  29.178 - 		ret = put_user(ioctx->user_id, ctxp);
  29.179 --		if (!ret)
  29.180 --			return 0;
  29.181 -+#ifdef CONFIG_EPOLL
  29.182 -+		if (make_fd && ret >= 0)
  29.183 -+			ret = make_aio_fd(ioctx);
  29.184 -+#endif
  29.185 -+		if (ret >= 0)
  29.186 -+			return ret;
  29.187 - 
  29.188 - 		get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
  29.189 - 		io_destroy(ioctx);
  29.190 -
  29.191 -diff -pruN ../pristine-linux-2.6.16-rc5/fs/eventpoll.c ./fs/eventpoll.c
  29.192 ---- ../pristine-linux-2.6.16-rc5/fs/eventpoll.c	2006-01-03 03:21:10.000000000 +0000
  29.193 -+++ ./fs/eventpoll.c	2006-03-16 10:04:35.469956167 +0000
  29.194 -@@ -235,8 +235,6 @@ struct ep_pqueue {
  29.195 - 
  29.196 - static void ep_poll_safewake_init(struct poll_safewake *psw);
  29.197 - static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
  29.198 --static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  29.199 --		    struct eventpoll *ep);
  29.200 - static int ep_alloc(struct eventpoll **pep);
  29.201 - static void ep_free(struct eventpoll *ep);
  29.202 - static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
  29.203 -@@ -266,7 +264,7 @@ static int ep_events_transfer(struct eve
  29.204 - static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
  29.205 - 		   int maxevents, long timeout);
  29.206 - static int eventpollfs_delete_dentry(struct dentry *dentry);
  29.207 --static struct inode *ep_eventpoll_inode(void);
  29.208 -+static struct inode *ep_eventpoll_inode(struct file_operations *fops);
  29.209 - static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
  29.210 - 					      int flags, const char *dev_name,
  29.211 - 					      void *data);
  29.212 -@@ -525,7 +523,7 @@ asmlinkage long sys_epoll_create(int siz
  29.213 - 	 * Creates all the items needed to setup an eventpoll file. That is,
  29.214 - 	 * a file structure, and inode and a free file descriptor.
  29.215 - 	 */
  29.216 --	error = ep_getfd(&fd, &inode, &file, ep);
  29.217 -+	error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
  29.218 - 	if (error)
  29.219 - 		goto eexit_2;
  29.220 - 
  29.221 -@@ -710,8 +708,8 @@ eexit_1:
  29.222 - /*
  29.223 -  * Creates the file descriptor to be used by the epoll interface.
  29.224 -  */
  29.225 --static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  29.226 --		    struct eventpoll *ep)
  29.227 -+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  29.228 -+		    struct eventpoll *ep, struct file_operations *fops)
  29.229 - {
  29.230 - 	struct qstr this;
  29.231 - 	char name[32];
  29.232 -@@ -727,7 +725,7 @@ static int ep_getfd(int *efd, struct ino
  29.233 - 		goto eexit_1;
  29.234 - 
  29.235 - 	/* Allocates an inode from the eventpoll file system */
  29.236 --	inode = ep_eventpoll_inode();
  29.237 -+	inode = ep_eventpoll_inode(fops);
  29.238 - 	error = PTR_ERR(inode);
  29.239 - 	if (IS_ERR(inode))
  29.240 - 		goto eexit_2;
  29.241 -@@ -758,7 +756,7 @@ static int ep_getfd(int *efd, struct ino
  29.242 - 
  29.243 - 	file->f_pos = 0;
  29.244 - 	file->f_flags = O_RDONLY;
  29.245 --	file->f_op = &eventpoll_fops;
  29.246 -+	file->f_op = fops;
  29.247 - 	file->f_mode = FMODE_READ;
  29.248 - 	file->f_version = 0;
  29.249 - 	file->private_data = ep;
  29.250 -@@ -1574,7 +1572,7 @@ static int eventpollfs_delete_dentry(str
  29.251 - }
  29.252 - 
  29.253 - 
  29.254 --static struct inode *ep_eventpoll_inode(void)
  29.255 -+static struct inode *ep_eventpoll_inode(struct file_operations *fops)
  29.256 - {
  29.257 - 	int error = -ENOMEM;
  29.258 - 	struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
  29.259 -@@ -1582,7 +1580,7 @@ static struct inode *ep_eventpoll_inode(
  29.260 - 	if (!inode)
  29.261 - 		goto eexit_1;
  29.262 - 
  29.263 --	inode->i_fop = &eventpoll_fops;
  29.264 -+	inode->i_fop = fops;
  29.265 - 
  29.266 - 	/*
  29.267 - 	 * Mark the inode dirty from the very beginning,
  29.268 -
  29.269 -diff -pruN ../pristine-linux-2.6.16-rc5/include/linux/aio.h ./include/linux/aio.h
  29.270 ---- ../pristine-linux-2.6.16-rc5/include/linux/aio.h	2006-03-14 14:10:21.597916731 +0000
  29.271 -+++ ./include/linux/aio.h	2006-03-16 10:05:39.848833028 +0000
  29.272 -@@ -191,6 +191,11 @@ struct kioctx {
  29.273 - 	struct aio_ring_info	ring_info;
  29.274 - 
  29.275 - 	struct work_struct	wq;
  29.276 -+#ifdef CONFIG_EPOLL
  29.277 -+	// poll integration
  29.278 -+	wait_queue_head_t       poll_wait;
  29.279 -+	struct file		*file;
  29.280 -+#endif
  29.281 - };
  29.282 - 
  29.283 - /* prototypes */
  29.284 -
  29.285 -diff -pruN ../pristine-linux-2.6.16-rc5/include/linux/eventpoll.h ./include/linux/eventpoll.h
  29.286 ---- ../pristine-linux-2.6.16-rc5/include/linux/eventpoll.h	2006-01-03 03:21:10.000000000 +0000
  29.287 -+++ ./include/linux/eventpoll.h	2006-03-16 10:08:51.577809317 +0000
  29.288 -@@ -86,6 +86,12 @@ static inline void eventpoll_release(str
  29.289 - }
  29.290 - 
  29.291 - 
  29.292 -+/*
  29.293 -+ * called by aio code to create fd that can poll the  aio event queueQ
  29.294 -+ */
  29.295 -+struct eventpoll;
  29.296 -+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  29.297 -+             struct eventpoll *ep, struct file_operations *fops);
  29.298 - #else
  29.299 - 
  29.300 - static inline void eventpoll_init_file(struct file *file) {}
    30.1 --- a/patches/linux-2.6.16.13/device_bind.patch	Thu Sep 21 15:35:45 2006 -0600
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,15 +0,0 @@
    30.4 -diff -pruN ../pristine-linux-2.6.16.13/drivers/base/bus.c ./drivers/base/bus.c
    30.5 ---- ../pristine-linux-2.6.16.13/drivers/base/bus.c	2006-05-02 22:38:44.000000000 +0100
    30.6 -+++ ./drivers/base/bus.c	2006-05-04 17:41:30.000000000 +0100
    30.7 -@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device
    30.8 - 		up(&dev->sem);
    30.9 - 		if (dev->parent)
   30.10 - 			up(&dev->parent->sem);
   30.11 -+
   30.12 -+		if (err > 0) 		/* success */
   30.13 -+			err = count;
   30.14 -+		else if (err == 0)	/* driver didn't accept device */
   30.15 -+			err = -ENODEV;
   30.16 - 	}
   30.17 - 	put_device(dev);
   30.18 - 	put_bus(bus);
    31.1 --- a/patches/linux-2.6.16.13/fix-hz-suspend.patch	Thu Sep 21 15:35:45 2006 -0600
    31.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3 @@ -1,26 +0,0 @@
    31.4 -diff -pruN ../pristine-linux-2.6.16.13/kernel/timer.c ./kernel/timer.c
    31.5 ---- ../pristine-linux-2.6.16.13/kernel/timer.c	2006-05-02 22:38:44.000000000 +0100
    31.6 -+++ ./kernel/timer.c	2006-06-29 14:34:12.788957720 +0100
    31.7 -@@ -555,6 +555,22 @@ found:
    31.8 - 	}
    31.9 - 	spin_unlock(&base->t_base.lock);
   31.10 - 
   31.11 -+	/*
   31.12 -+	 * It can happen that other CPUs service timer IRQs and increment
   31.13 -+	 * jiffies, but we have not yet got a local timer tick to process
   31.14 -+	 * the timer wheels.  In that case, the expiry time can be before
   31.15 -+	 * jiffies, but since the high-resolution timer here is relative to
   31.16 -+	 * jiffies, the default expression when high-resolution timers are
   31.17 -+	 * not active,
   31.18 -+	 *
   31.19 -+	 *   time_before(MAX_JIFFY_OFFSET + jiffies, expires)
   31.20 -+	 *
   31.21 -+	 * would falsely evaluate to true.  If that is the case, just
   31.22 -+	 * return jiffies so that we can immediately fire the local timer
   31.23 -+	 */
   31.24 -+	if (time_before(expires, jiffies))
   31.25 -+		return jiffies;
   31.26 -+
   31.27 - 	if (time_before(hr_expires, expires))
   31.28 - 		return hr_expires;
   31.29 - 
    32.1 --- a/patches/linux-2.6.16.13/fix-ide-cd-pio-mode.patch	Thu Sep 21 15:35:45 2006 -0600
    32.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3 @@ -1,18 +0,0 @@
    32.4 -diff -ru ../pristine-linux-2.6.16.13/drivers/ide/ide-lib.c ./drivers/ide/ide-lib.c
    32.5 ---- ../pristine-linux-2.6.16.13/drivers/ide/ide-lib.c	2006-05-02 22:38:44.000000000 +0100
    32.6 -+++ ./drivers/ide/ide-lib.c	2006-05-24 18:37:05.000000000 +0100
    32.7 -@@ -410,10 +410,10 @@
    32.8 - {
    32.9 - 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
   32.10 - 
   32.11 --	if (!PCI_DMA_BUS_IS_PHYS) {
   32.12 --		addr = BLK_BOUNCE_ANY;
   32.13 --	} else if (on && drive->media == ide_disk) {
   32.14 --		if (HWIF(drive)->pci_dev)
   32.15 -+	if (on && drive->media == ide_disk) {
   32.16 -+		if (!PCI_DMA_BUS_IS_PHYS)
   32.17 -+			addr = BLK_BOUNCE_ANY;
   32.18 -+		else if (HWIF(drive)->pci_dev)
   32.19 - 			addr = HWIF(drive)->pci_dev->dma_mask;
   32.20 - 	}
   32.21 - 
    33.1 --- a/patches/linux-2.6.16.13/i386-mach-io-check-nmi.patch	Thu Sep 21 15:35:45 2006 -0600
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,45 +0,0 @@
    33.4 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c
    33.5 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/traps.c	2006-05-02 22:38:44.000000000 +0100
    33.6 -+++ ./arch/i386/kernel/traps.c	2006-05-04 17:41:34.000000000 +0100
    33.7 -@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
    33.8 - 
    33.9 - static void io_check_error(unsigned char reason, struct pt_regs * regs)
   33.10 - {
   33.11 --	unsigned long i;
   33.12 --
   33.13 - 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
   33.14 - 	show_registers(regs);
   33.15 - 
   33.16 - 	/* Re-enable the IOCK line, wait for a few seconds */
   33.17 --	reason = (reason & 0xf) | 8;
   33.18 --	outb(reason, 0x61);
   33.19 --	i = 2000;
   33.20 --	while (--i) udelay(1000);
   33.21 --	reason &= ~8;
   33.22 --	outb(reason, 0x61);
   33.23 -+	clear_io_check_error(reason);
   33.24 - }
   33.25 - 
   33.26 - static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
   33.27 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/mach-default/mach_traps.h ./include/asm-i386/mach-default/mach_traps.h
   33.28 ---- ../pristine-linux-2.6.16.13/include/asm-i386/mach-default/mach_traps.h	2006-05-02 22:38:44.000000000 +0100
   33.29 -+++ ./include/asm-i386/mach-default/mach_traps.h	2006-05-04 17:41:34.000000000 +0100
   33.30 -@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
   33.31 - 	outb(reason, 0x61);
   33.32 - }
   33.33 - 
   33.34 -+static inline void clear_io_check_error(unsigned char reason)
   33.35 -+{
   33.36 -+	unsigned long i;
   33.37 -+
   33.38 -+	reason = (reason & 0xf) | 8;
   33.39 -+	outb(reason, 0x61);
   33.40 -+	i = 2000;
   33.41 -+	while (--i) udelay(1000);
   33.42 -+	reason &= ~8;
   33.43 -+	outb(reason, 0x61);
   33.44 -+}
   33.45 -+
   33.46 - static inline unsigned char get_nmi_reason(void)
   33.47 - {
   33.48 - 	return inb(0x61);
    34.1 --- a/patches/linux-2.6.16.13/ipv6-no-autoconf.patch	Thu Sep 21 15:35:45 2006 -0600
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,23 +0,0 @@
    34.4 - net/ipv6/addrconf.c |    2 ++
    34.5 - 1 files changed, 2 insertions(+)
    34.6 -
    34.7 -Index: build/net/ipv6/addrconf.c
    34.8 -===================================================================
    34.9 ---- build.orig/net/ipv6/addrconf.c
   34.10 -+++ build/net/ipv6/addrconf.c
   34.11 -@@ -2462,6 +2462,7 @@ static void addrconf_dad_start(struct in
   34.12 - 	spin_lock_bh(&ifp->lock);
   34.13 - 
   34.14 - 	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
   34.15 -+	    !(dev->flags&IFF_MULTICAST) ||
   34.16 - 	    !(ifp->flags&IFA_F_TENTATIVE)) {
   34.17 - 		ifp->flags &= ~IFA_F_TENTATIVE;
   34.18 - 		spin_unlock_bh(&ifp->lock);
   34.19 -@@ -2546,6 +2547,7 @@ static void addrconf_dad_completed(struc
   34.20 - 	if (ifp->idev->cnf.forwarding == 0 &&
   34.21 - 	    ifp->idev->cnf.rtr_solicits > 0 &&
   34.22 - 	    (dev->flags&IFF_LOOPBACK) == 0 &&
   34.23 -+	    (dev->flags & IFF_MULTICAST) &&
   34.24 - 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
   34.25 - 		struct in6_addr all_routers;
   34.26 - 
    35.1 --- a/patches/linux-2.6.16.13/net-csum.patch	Thu Sep 21 15:35:45 2006 -0600
    35.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.3 @@ -1,63 +0,0 @@
    35.4 -diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_tcp.c ./net/ipv4/netfilter/ip_nat_proto_tcp.c
    35.5 ---- ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-05-02 22:38:44.000000000 +0100
    35.6 -+++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-05-16 13:28:19.000000000 +0100
    35.7 -@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb,
    35.8 - 	if (hdrsize < sizeof(*hdr))
    35.9 - 		return 1;
   35.10 - 
   35.11 --	hdr->check = ip_nat_cheat_check(~oldip, newip,
   35.12 -+#ifdef CONFIG_XEN
   35.13 -+	if ((*pskb)->proto_csum_blank)
   35.14 -+		hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   35.15 -+	else
   35.16 -+#endif
   35.17 -+		hdr->check = ip_nat_cheat_check(~oldip, newip,
   35.18 - 					ip_nat_cheat_check(oldport ^ 0xFFFF,
   35.19 - 							   newport,
   35.20 - 							   hdr->check));
   35.21 -diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_udp.c ./net/ipv4/netfilter/ip_nat_proto_udp.c
   35.22 ---- ../pristine-linux-2.6.16.13/net/ipv4/netfilter/ip_nat_proto_udp.c	2006-05-02 22:38:44.000000000 +0100
   35.23 -+++ ./net/ipv4/netfilter/ip_nat_proto_udp.c	2006-05-16 13:30:14.000000000 +0100
   35.24 -@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb,
   35.25 - 		newport = tuple->dst.u.udp.port;
   35.26 - 		portptr = &hdr->dest;
   35.27 - 	}
   35.28 --	if (hdr->check) /* 0 is a special case meaning no checksum */
   35.29 --		hdr->check = ip_nat_cheat_check(~oldip, newip,
   35.30 -+	if (hdr->check) { /* 0 is a special case meaning no checksum */
   35.31 -+#ifdef CONFIG_XEN
   35.32 -+		if ((*pskb)->proto_csum_blank)
   35.33 -+			hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   35.34 -+		else
   35.35 -+#endif
   35.36 -+			hdr->check = ip_nat_cheat_check(~oldip, newip,
   35.37 - 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
   35.38 - 							   newport,
   35.39 - 							   hdr->check));
   35.40 -+	}
   35.41 - 	*portptr = newport;
   35.42 - 	return 1;
   35.43 - }
   35.44 -diff -pruN ../pristine-linux-2.6.16.13/net/ipv4/xfrm4_output.c ./net/ipv4/xfrm4_output.c
   35.45 ---- ../pristine-linux-2.6.16.13/net/ipv4/xfrm4_output.c	2006-05-02 22:38:44.000000000 +0100
   35.46 -+++ ./net/ipv4/xfrm4_output.c	2006-05-04 17:41:37.000000000 +0100
   35.47 -@@ -17,6 +17,8 @@
   35.48 - #include <net/xfrm.h>
   35.49 - #include <net/icmp.h>
   35.50 - 
   35.51 -+extern int skb_checksum_setup(struct sk_buff *skb);
   35.52 -+
   35.53 - /* Add encapsulation header.
   35.54 -  *
   35.55 -  * In transport mode, the IP header will be moved forward to make space
   35.56 -@@ -103,6 +105,10 @@ static int xfrm4_output_one(struct sk_bu
   35.57 - 	struct xfrm_state *x = dst->xfrm;
   35.58 - 	int err;
   35.59 - 	
   35.60 -+	err = skb_checksum_setup(skb);
   35.61 -+	if (err)
   35.62 -+		goto error_nolock;
   35.63 -+
   35.64 - 	if (skb->ip_summed == CHECKSUM_HW) {
   35.65 - 		err = skb_checksum_help(skb, 0);
   35.66 - 		if (err)
    36.1 --- a/patches/linux-2.6.16.13/net-gso-0-base.patch	Thu Sep 21 15:35:45 2006 -0600
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,2907 +0,0 @@
    36.4 -diff --git a/Documentation/networking/netdevices.txt b/Documentation/networking/netdevices.txt
    36.5 -index 3c0a5ba..847cedb 100644
    36.6 ---- a/Documentation/networking/netdevices.txt
    36.7 -+++ b/Documentation/networking/netdevices.txt
    36.8 -@@ -42,9 +42,9 @@ dev->get_stats:
    36.9 - 	Context: nominally process, but don't sleep inside an rwlock
   36.10 - 
   36.11 - dev->hard_start_xmit:
   36.12 --	Synchronization: dev->xmit_lock spinlock.
   36.13 -+	Synchronization: netif_tx_lock spinlock.
   36.14 - 	When the driver sets NETIF_F_LLTX in dev->features this will be
   36.15 --	called without holding xmit_lock. In this case the driver 
   36.16 -+	called without holding netif_tx_lock. In this case the driver
   36.17 - 	has to lock by itself when needed. It is recommended to use a try lock
   36.18 - 	for this and return -1 when the spin lock fails. 
   36.19 - 	The locking there should also properly protect against 
   36.20 -@@ -62,12 +62,12 @@ dev->hard_start_xmit:
   36.21 - 	  Only valid when NETIF_F_LLTX is set.
   36.22 - 
   36.23 - dev->tx_timeout:
   36.24 --	Synchronization: dev->xmit_lock spinlock.
   36.25 -+	Synchronization: netif_tx_lock spinlock.
   36.26 - 	Context: BHs disabled
   36.27 - 	Notes: netif_queue_stopped() is guaranteed true
   36.28 - 
   36.29 - dev->set_multicast_list:
   36.30 --	Synchronization: dev->xmit_lock spinlock.
   36.31 -+	Synchronization: netif_tx_lock spinlock.
   36.32 - 	Context: BHs disabled
   36.33 - 
   36.34 - dev->poll:
   36.35 -diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
   36.36 -index 4be9769..2e7cac7 100644
   36.37 ---- a/drivers/block/aoe/aoenet.c
   36.38 -+++ b/drivers/block/aoe/aoenet.c
   36.39 -@@ -95,9 +95,8 @@ mac_addr(char addr[6])
   36.40 - static struct sk_buff *
   36.41 - skb_check(struct sk_buff *skb)
   36.42 - {
   36.43 --	if (skb_is_nonlinear(skb))
   36.44 - 	if ((skb = skb_share_check(skb, GFP_ATOMIC)))
   36.45 --	if (skb_linearize(skb, GFP_ATOMIC) < 0) {
   36.46 -+	if (skb_linearize(skb)) {
   36.47 - 		dev_kfree_skb(skb);
   36.48 - 		return NULL;
   36.49 - 	}
   36.50 -diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
   36.51 -index a2408d7..c90e620 100644
   36.52 ---- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
   36.53 -+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
   36.54 -@@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_
   36.55 - 
   36.56 - 	ipoib_mcast_stop_thread(dev, 0);
   36.57 - 
   36.58 --	spin_lock_irqsave(&dev->xmit_lock, flags);
   36.59 -+	local_irq_save(flags);
   36.60 -+	netif_tx_lock(dev);
   36.61 - 	spin_lock(&priv->lock);
   36.62 - 
   36.63 - 	/*
   36.64 -@@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_
   36.65 - 	}
   36.66 - 
   36.67 - 	spin_unlock(&priv->lock);
   36.68 --	spin_unlock_irqrestore(&dev->xmit_lock, flags);
   36.69 -+	netif_tx_unlock(dev);
   36.70 -+	local_irq_restore(flags);
   36.71 - 
   36.72 - 	/* We have to cancel outside of the spinlock */
   36.73 - 	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
   36.74 -diff --git a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c
   36.75 -index 6711eb6..8d2351f 100644
   36.76 ---- a/drivers/media/dvb/dvb-core/dvb_net.c
   36.77 -+++ b/drivers/media/dvb/dvb-core/dvb_net.c
   36.78 -@@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void 
   36.79 - 
   36.80 - 	dvb_net_feed_stop(dev);
   36.81 - 	priv->rx_mode = RX_MODE_UNI;
   36.82 --	spin_lock_bh(&dev->xmit_lock);
   36.83 -+	netif_tx_lock_bh(dev);
   36.84 - 
   36.85 - 	if (dev->flags & IFF_PROMISC) {
   36.86 - 		dprintk("%s: promiscuous mode\n", dev->name);
   36.87 -@@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void 
   36.88 - 		}
   36.89 - 	}
   36.90 - 
   36.91 --	spin_unlock_bh(&dev->xmit_lock);
   36.92 -+	netif_tx_unlock_bh(dev);
   36.93 - 	dvb_net_feed_start(dev);
   36.94 - }
   36.95 - 
   36.96 -diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
   36.97 -index dd41049..6615583 100644
   36.98 ---- a/drivers/net/8139cp.c
   36.99 -+++ b/drivers/net/8139cp.c
  36.100 -@@ -794,7 +794,7 @@ #endif
  36.101 - 	entry = cp->tx_head;
  36.102 - 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
  36.103 - 	if (dev->features & NETIF_F_TSO)
  36.104 --		mss = skb_shinfo(skb)->tso_size;
  36.105 -+		mss = skb_shinfo(skb)->gso_size;
  36.106 - 
  36.107 - 	if (skb_shinfo(skb)->nr_frags == 0) {
  36.108 - 		struct cp_desc *txd = &cp->tx_ring[entry];
  36.109 -diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
  36.110 -index a24200d..b5e39a1 100644
  36.111 ---- a/drivers/net/bnx2.c
  36.112 -+++ b/drivers/net/bnx2.c
  36.113 -@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
  36.114 - 		skb = tx_buf->skb;
  36.115 - #ifdef BCM_TSO 
  36.116 - 		/* partial BD completions possible with TSO packets */
  36.117 --		if (skb_shinfo(skb)->tso_size) {
  36.118 -+		if (skb_shinfo(skb)->gso_size) {
  36.119 - 			u16 last_idx, last_ring_idx;
  36.120 - 
  36.121 - 			last_idx = sw_cons +
  36.122 -@@ -1948,7 +1948,7 @@ bnx2_poll(struct net_device *dev, int *b
  36.123 - 	return 1;
  36.124 - }
  36.125 - 
  36.126 --/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
  36.127 -+/* Called with rtnl_lock from vlan functions and also netif_tx_lock
  36.128 -  * from set_multicast.
  36.129 -  */
  36.130 - static void
  36.131 -@@ -4403,7 +4403,7 @@ bnx2_vlan_rx_kill_vid(struct net_device 
  36.132 - }
  36.133 - #endif
  36.134 - 
  36.135 --/* Called with dev->xmit_lock.
  36.136 -+/* Called with netif_tx_lock.
  36.137 -  * hard_start_xmit is pseudo-lockless - a lock is only required when
  36.138 -  * the tx queue is full. This way, we get the benefit of lockless
  36.139 -  * operations most of the time without the complexities to handle
  36.140 -@@ -4441,7 +4441,7 @@ bnx2_start_xmit(struct sk_buff *skb, str
  36.141 - 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
  36.142 - 	}
  36.143 - #ifdef BCM_TSO 
  36.144 --	if ((mss = skb_shinfo(skb)->tso_size) &&
  36.145 -+	if ((mss = skb_shinfo(skb)->gso_size) &&
  36.146 - 		(skb->len > (bp->dev->mtu + ETH_HLEN))) {
  36.147 - 		u32 tcp_opt_len, ip_tcp_len;
  36.148 - 
  36.149 -diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
  36.150 -index bcf9f17..e970921 100644
  36.151 ---- a/drivers/net/bonding/bond_main.c
  36.152 -+++ b/drivers/net/bonding/bond_main.c
  36.153 -@@ -1145,8 +1145,7 @@ int bond_sethwaddr(struct net_device *bo
  36.154 - }
  36.155 - 
  36.156 - #define BOND_INTERSECT_FEATURES \
  36.157 --	(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
  36.158 --	NETIF_F_TSO|NETIF_F_UFO)
  36.159 -+	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
  36.160 - 
  36.161 - /* 
  36.162 -  * Compute the common dev->feature set available to all slaves.  Some
  36.163 -@@ -1164,9 +1163,7 @@ static int bond_compute_features(struct 
  36.164 - 		features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
  36.165 - 
  36.166 - 	if ((features & NETIF_F_SG) && 
  36.167 --	    !(features & (NETIF_F_IP_CSUM |
  36.168 --			  NETIF_F_NO_CSUM |
  36.169 --			  NETIF_F_HW_CSUM)))
  36.170 -+	    !(features & NETIF_F_ALL_CSUM))
  36.171 - 		features &= ~NETIF_F_SG;
  36.172 - 
  36.173 - 	/* 
  36.174 -@@ -4147,7 +4144,7 @@ static int bond_init(struct net_device *
  36.175 - 	 */
  36.176 - 	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
  36.177 - 
  36.178 --	/* don't acquire bond device's xmit_lock when 
  36.179 -+	/* don't acquire bond device's netif_tx_lock when
  36.180 - 	 * transmitting */
  36.181 - 	bond_dev->features |= NETIF_F_LLTX;
  36.182 - 
  36.183 -diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
  36.184 -index 30ff8ea..7b7d360 100644
  36.185 ---- a/drivers/net/chelsio/sge.c
  36.186 -+++ b/drivers/net/chelsio/sge.c
  36.187 -@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
  36.188 - 	struct cpl_tx_pkt *cpl;
  36.189 - 
  36.190 - #ifdef NETIF_F_TSO
  36.191 --	if (skb_shinfo(skb)->tso_size) {
  36.192 -+	if (skb_shinfo(skb)->gso_size) {
  36.193 - 		int eth_type;
  36.194 - 		struct cpl_tx_pkt_lso *hdr;
  36.195 - 
  36.196 -@@ -1434,7 +1434,7 @@ #ifdef NETIF_F_TSO
  36.197 - 		hdr->ip_hdr_words = skb->nh.iph->ihl;
  36.198 - 		hdr->tcp_hdr_words = skb->h.th->doff;
  36.199 - 		hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
  36.200 --						skb_shinfo(skb)->tso_size));
  36.201 -+						skb_shinfo(skb)->gso_size));
  36.202 - 		hdr->len = htonl(skb->len - sizeof(*hdr));
  36.203 - 		cpl = (struct cpl_tx_pkt *)hdr;
  36.204 - 		sge->stats.tx_lso_pkts++;
  36.205 -diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
  36.206 -index fa29402..681d284 100644
  36.207 ---- a/drivers/net/e1000/e1000_main.c
  36.208 -+++ b/drivers/net/e1000/e1000_main.c
  36.209 -@@ -2526,7 +2526,7 @@ #ifdef NETIF_F_TSO
  36.210 - 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
  36.211 - 	int err;
  36.212 - 
  36.213 --	if (skb_shinfo(skb)->tso_size) {
  36.214 -+	if (skb_shinfo(skb)->gso_size) {
  36.215 - 		if (skb_header_cloned(skb)) {
  36.216 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
  36.217 - 			if (err)
  36.218 -@@ -2534,7 +2534,7 @@ #ifdef NETIF_F_TSO
  36.219 - 		}
  36.220 - 
  36.221 - 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
  36.222 --		mss = skb_shinfo(skb)->tso_size;
  36.223 -+		mss = skb_shinfo(skb)->gso_size;
  36.224 - 		if (skb->protocol == ntohs(ETH_P_IP)) {
  36.225 - 			skb->nh.iph->tot_len = 0;
  36.226 - 			skb->nh.iph->check = 0;
  36.227 -@@ -2651,7 +2651,7 @@ #ifdef NETIF_F_TSO
  36.228 - 		 * tso gets written back prematurely before the data is fully
  36.229 - 		 * DMAd to the controller */
  36.230 - 		if (!skb->data_len && tx_ring->last_tx_tso &&
  36.231 --				!skb_shinfo(skb)->tso_size) {
  36.232 -+				!skb_shinfo(skb)->gso_size) {
  36.233 - 			tx_ring->last_tx_tso = 0;
  36.234 - 			size -= 4;
  36.235 - 		}
  36.236 -@@ -2893,7 +2893,7 @@ #endif
  36.237 - 	}
  36.238 - 
  36.239 - #ifdef NETIF_F_TSO
  36.240 --	mss = skb_shinfo(skb)->tso_size;
  36.241 -+	mss = skb_shinfo(skb)->gso_size;
  36.242 - 	/* The controller does a simple calculation to 
  36.243 - 	 * make sure there is enough room in the FIFO before
  36.244 - 	 * initiating the DMA for each buffer.  The calc is:
  36.245 -@@ -2935,7 +2935,7 @@ #endif
  36.246 - #ifdef NETIF_F_TSO
  36.247 - 	/* Controller Erratum workaround */
  36.248 - 	if (!skb->data_len && tx_ring->last_tx_tso &&
  36.249 --		!skb_shinfo(skb)->tso_size)
  36.250 -+		!skb_shinfo(skb)->gso_size)
  36.251 - 		count++;
  36.252 - #endif
  36.253 - 
  36.254 -diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
  36.255 -index 3682ec6..c35f16e 100644
  36.256 ---- a/drivers/net/forcedeth.c
  36.257 -+++ b/drivers/net/forcedeth.c
  36.258 -@@ -482,9 +482,9 @@ #define LPA_1000HALF	0x0400
  36.259 -  * critical parts:
  36.260 -  * - rx is (pseudo-) lockless: it relies on the single-threading provided
  36.261 -  *	by the arch code for interrupts.
  36.262 -- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
  36.263 -+ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
  36.264 -  *	needs dev->priv->lock :-(
  36.265 -- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
  36.266 -+ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
  36.267 -  */
  36.268 - 
  36.269 - /* in dev: base, irq */
  36.270 -@@ -1016,7 +1016,7 @@ static void drain_ring(struct net_device
  36.271 - 
  36.272 - /*
  36.273 -  * nv_start_xmit: dev->hard_start_xmit function
  36.274 -- * Called with dev->xmit_lock held.
  36.275 -+ * Called with netif_tx_lock held.
  36.276 -  */
  36.277 - static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
  36.278 - {
  36.279 -@@ -1105,8 +1105,8 @@ static int nv_start_xmit(struct sk_buff 
  36.280 - 	np->tx_skbuff[nr] = skb;
  36.281 - 
  36.282 - #ifdef NETIF_F_TSO
  36.283 --	if (skb_shinfo(skb)->tso_size)
  36.284 --		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
  36.285 -+	if (skb_shinfo(skb)->gso_size)
  36.286 -+		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
  36.287 - 	else
  36.288 - #endif
  36.289 - 	tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
  36.290 -@@ -1203,7 +1203,7 @@ static void nv_tx_done(struct net_device
  36.291 - 
  36.292 - /*
  36.293 -  * nv_tx_timeout: dev->tx_timeout function
  36.294 -- * Called with dev->xmit_lock held.
  36.295 -+ * Called with netif_tx_lock held.
  36.296 -  */
  36.297 - static void nv_tx_timeout(struct net_device *dev)
  36.298 - {
  36.299 -@@ -1524,7 +1524,7 @@ static int nv_change_mtu(struct net_devi
  36.300 - 		 * Changing the MTU is a rare event, it shouldn't matter.
  36.301 - 		 */
  36.302 - 		disable_irq(dev->irq);
  36.303 --		spin_lock_bh(&dev->xmit_lock);
  36.304 -+		netif_tx_lock_bh(dev);
  36.305 - 		spin_lock(&np->lock);
  36.306 - 		/* stop engines */
  36.307 - 		nv_stop_rx(dev);
  36.308 -@@ -1559,7 +1559,7 @@ static int nv_change_mtu(struct net_devi
  36.309 - 		nv_start_rx(dev);
  36.310 - 		nv_start_tx(dev);
  36.311 - 		spin_unlock(&np->lock);
  36.312 --		spin_unlock_bh(&dev->xmit_lock);
  36.313 -+		netif_tx_unlock_bh(dev);
  36.314 - 		enable_irq(dev->irq);
  36.315 - 	}
  36.316 - 	return 0;
  36.317 -@@ -1594,7 +1594,7 @@ static int nv_set_mac_address(struct net
  36.318 - 	memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
  36.319 - 
  36.320 - 	if (netif_running(dev)) {
  36.321 --		spin_lock_bh(&dev->xmit_lock);
  36.322 -+		netif_tx_lock_bh(dev);
  36.323 - 		spin_lock_irq(&np->lock);
  36.324 - 
  36.325 - 		/* stop rx engine */
  36.326 -@@ -1606,7 +1606,7 @@ static int nv_set_mac_address(struct net
  36.327 - 		/* restart rx engine */
  36.328 - 		nv_start_rx(dev);
  36.329 - 		spin_unlock_irq(&np->lock);
  36.330 --		spin_unlock_bh(&dev->xmit_lock);
  36.331 -+		netif_tx_unlock_bh(dev);
  36.332 - 	} else {
  36.333 - 		nv_copy_mac_to_hw(dev);
  36.334 - 	}
  36.335 -@@ -1615,7 +1615,7 @@ static int nv_set_mac_address(struct net
  36.336 - 
  36.337 - /*
  36.338 -  * nv_set_multicast: dev->set_multicast function
  36.339 -- * Called with dev->xmit_lock held.
  36.340 -+ * Called with netif_tx_lock held.
  36.341 -  */
  36.342 - static void nv_set_multicast(struct net_device *dev)
  36.343 - {
  36.344 -diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
  36.345 -index 102c1f0..d12605f 100644
  36.346 ---- a/drivers/net/hamradio/6pack.c
  36.347 -+++ b/drivers/net/hamradio/6pack.c
  36.348 -@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net
  36.349 - {
  36.350 - 	struct sockaddr_ax25 *sa = addr;
  36.351 - 
  36.352 --	spin_lock_irq(&dev->xmit_lock);
  36.353 -+	netif_tx_lock_bh(dev);
  36.354 - 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
  36.355 --	spin_unlock_irq(&dev->xmit_lock);
  36.356 -+	netif_tx_unlock_bh(dev);
  36.357 - 
  36.358 - 	return 0;
  36.359 - }
  36.360 -@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_stru
  36.361 - 			break;
  36.362 - 		}
  36.363 - 
  36.364 --		spin_lock_irq(&dev->xmit_lock);
  36.365 -+		netif_tx_lock_bh(dev);
  36.366 - 		memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
  36.367 --		spin_unlock_irq(&dev->xmit_lock);
  36.368 -+		netif_tx_unlock_bh(dev);
  36.369 - 
  36.370 - 		err = 0;
  36.371 - 		break;
  36.372 -diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
  36.373 -index dc5e9d5..5c66f5a 100644
  36.374 ---- a/drivers/net/hamradio/mkiss.c
  36.375 -+++ b/drivers/net/hamradio/mkiss.c
  36.376 -@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net
  36.377 - {
  36.378 - 	struct sockaddr_ax25 *sa = addr;
  36.379 - 
  36.380 --	spin_lock_irq(&dev->xmit_lock);
  36.381 -+	netif_tx_lock_bh(dev);
  36.382 - 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
  36.383 --	spin_unlock_irq(&dev->xmit_lock);
  36.384 -+	netif_tx_unlock_bh(dev);
  36.385 - 
  36.386 - 	return 0;
  36.387 - }
  36.388 -@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct
  36.389 - 			break;
  36.390 - 		}
  36.391 - 
  36.392 --		spin_lock_irq(&dev->xmit_lock);
  36.393 -+		netif_tx_lock_bh(dev);
  36.394 - 		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
  36.395 --		spin_unlock_irq(&dev->xmit_lock);
  36.396 -+		netif_tx_unlock_bh(dev);
  36.397 - 
  36.398 - 		err = 0;
  36.399 - 		break;
  36.400 -diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
  36.401 -index 31fb2d7..2e222ef 100644
  36.402 ---- a/drivers/net/ifb.c
  36.403 -+++ b/drivers/net/ifb.c
  36.404 -@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev
  36.405 - 	dp->st_task_enter++;
  36.406 - 	if ((skb = skb_peek(&dp->tq)) == NULL) {
  36.407 - 		dp->st_txq_refl_try++;
  36.408 --		if (spin_trylock(&_dev->xmit_lock)) {
  36.409 -+		if (netif_tx_trylock(_dev)) {
  36.410 - 			dp->st_rxq_enter++;
  36.411 - 			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
  36.412 - 				skb_queue_tail(&dp->tq, skb);
  36.413 - 				dp->st_rx2tx_tran++;
  36.414 - 			}
  36.415 --			spin_unlock(&_dev->xmit_lock);
  36.416 -+			netif_tx_unlock(_dev);
  36.417 - 		} else {
  36.418 - 			/* reschedule */
  36.419 - 			dp->st_rxq_notenter++;
  36.420 -@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev
  36.421 - 		}
  36.422 - 	}
  36.423 - 
  36.424 --	if (spin_trylock(&_dev->xmit_lock)) {
  36.425 -+	if (netif_tx_trylock(_dev)) {
  36.426 - 		dp->st_rxq_check++;
  36.427 - 		if ((skb = skb_peek(&dp->rq)) == NULL) {
  36.428 - 			dp->tasklet_pending = 0;
  36.429 -@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev
  36.430 - 				netif_wake_queue(_dev);
  36.431 - 		} else {
  36.432 - 			dp->st_rxq_rsch++;
  36.433 --			spin_unlock(&_dev->xmit_lock);
  36.434 -+			netif_tx_unlock(_dev);
  36.435 - 			goto resched;
  36.436 - 		}
  36.437 --		spin_unlock(&_dev->xmit_lock);
  36.438 -+		netif_tx_unlock(_dev);
  36.439 - 	} else {
  36.440 - resched:
  36.441 - 		dp->tasklet_pending = 1;
  36.442 -diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
  36.443 -index a9f49f0..339d4a7 100644
  36.444 ---- a/drivers/net/irda/vlsi_ir.c
  36.445 -+++ b/drivers/net/irda/vlsi_ir.c
  36.446 -@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct s
  36.447 - 			    ||  (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
  36.448 - 			    	break;
  36.449 - 			udelay(100);
  36.450 --			/* must not sleep here - we are called under xmit_lock! */
  36.451 -+			/* must not sleep here - called under netif_tx_lock! */
  36.452 - 		}
  36.453 - 	}
  36.454 - 
  36.455 -diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
  36.456 -index f9f77e4..bdab369 100644
  36.457 ---- a/drivers/net/ixgb/ixgb_main.c
  36.458 -+++ b/drivers/net/ixgb/ixgb_main.c
  36.459 -@@ -1163,7 +1163,7 @@ #ifdef NETIF_F_TSO
  36.460 - 	uint16_t ipcse, tucse, mss;
  36.461 - 	int err;
  36.462 - 
  36.463 --	if(likely(skb_shinfo(skb)->tso_size)) {
  36.464 -+	if(likely(skb_shinfo(skb)->gso_size)) {
  36.465 - 		if (skb_header_cloned(skb)) {
  36.466 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
  36.467 - 			if (err)
  36.468 -@@ -1171,7 +1171,7 @@ #ifdef NETIF_F_TSO
  36.469 - 		}
  36.470 - 
  36.471 - 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
  36.472 --		mss = skb_shinfo(skb)->tso_size;
  36.473 -+		mss = skb_shinfo(skb)->gso_size;
  36.474 - 		skb->nh.iph->tot_len = 0;
  36.475 - 		skb->nh.iph->check = 0;
  36.476 - 		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
  36.477 -diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
  36.478 -index 690a1aa..9bcaa80 100644
  36.479 ---- a/drivers/net/loopback.c
  36.480 -+++ b/drivers/net/loopback.c
  36.481 -@@ -74,7 +74,7 @@ static void emulate_large_send_offload(s
  36.482 - 	struct iphdr *iph = skb->nh.iph;
  36.483 - 	struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4));
  36.484 - 	unsigned int doffset = (iph->ihl + th->doff) * 4;
  36.485 --	unsigned int mtu = skb_shinfo(skb)->tso_size + doffset;
  36.486 -+	unsigned int mtu = skb_shinfo(skb)->gso_size + doffset;
  36.487 - 	unsigned int offset = 0;
  36.488 - 	u32 seq = ntohl(th->seq);
  36.489 - 	u16 id  = ntohs(iph->id);
  36.490 -@@ -139,7 +139,7 @@ #ifndef LOOPBACK_MUST_CHECKSUM
  36.491 - #endif
  36.492 - 
  36.493 - #ifdef LOOPBACK_TSO
  36.494 --	if (skb_shinfo(skb)->tso_size) {
  36.495 -+	if (skb_shinfo(skb)->gso_size) {
  36.496 - 		BUG_ON(skb->protocol != htons(ETH_P_IP));
  36.497 - 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
  36.498 - 
  36.499 -diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
  36.500 -index c0998ef..0fac9d5 100644
  36.501 ---- a/drivers/net/mv643xx_eth.c
  36.502 -+++ b/drivers/net/mv643xx_eth.c
  36.503 -@@ -1107,7 +1107,7 @@ static int mv643xx_eth_start_xmit(struct
  36.504 - 
  36.505 - #ifdef MV643XX_CHECKSUM_OFFLOAD_TX
  36.506 - 	if (has_tiny_unaligned_frags(skb)) {
  36.507 --		if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
  36.508 -+		if (__skb_linearize(skb)) {
  36.509 - 			stats->tx_dropped++;
  36.510 - 			printk(KERN_DEBUG "%s: failed to linearize tiny "
  36.511 - 					"unaligned fragment\n", dev->name);
  36.512 -diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
  36.513 -index 9d6d254..c9ed624 100644
  36.514 ---- a/drivers/net/natsemi.c
  36.515 -+++ b/drivers/net/natsemi.c
  36.516 -@@ -323,12 +323,12 @@ performance critical codepaths:
  36.517 - The rx process only runs in the interrupt handler. Access from outside
  36.518 - the interrupt handler is only permitted after disable_irq().
  36.519 - 
  36.520 --The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
  36.521 -+The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
  36.522 - is set, then access is permitted under spin_lock_irq(&np->lock).
  36.523 - 
  36.524 - Thus configuration functions that want to access everything must call
  36.525 - 	disable_irq(dev->irq);
  36.526 --	spin_lock_bh(dev->xmit_lock);
  36.527 -+	netif_tx_lock_bh(dev);
  36.528 - 	spin_lock_irq(&np->lock);
  36.529 - 
  36.530 - IV. Notes
  36.531 -diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
  36.532 -index 8cc0d0b..e53b313 100644
  36.533 ---- a/drivers/net/r8169.c
  36.534 -+++ b/drivers/net/r8169.c
  36.535 -@@ -2171,7 +2171,7 @@ static int rtl8169_xmit_frags(struct rtl
  36.536 - static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
  36.537 - {
  36.538 - 	if (dev->features & NETIF_F_TSO) {
  36.539 --		u32 mss = skb_shinfo(skb)->tso_size;
  36.540 -+		u32 mss = skb_shinfo(skb)->gso_size;
  36.541 - 
  36.542 - 		if (mss)
  36.543 - 			return LargeSend | ((mss & MSSMask) << MSSShift);
  36.544 -diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
  36.545 -index b7f00d6..439f45f 100644
  36.546 ---- a/drivers/net/s2io.c
  36.547 -+++ b/drivers/net/s2io.c
  36.548 -@@ -3522,8 +3522,8 @@ #endif
  36.549 - 	txdp->Control_1 = 0;
  36.550 - 	txdp->Control_2 = 0;
  36.551 - #ifdef NETIF_F_TSO
  36.552 --	mss = skb_shinfo(skb)->tso_size;
  36.553 --	if (mss) {
  36.554 -+	mss = skb_shinfo(skb)->gso_size;
  36.555 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
  36.556 - 		txdp->Control_1 |= TXD_TCP_LSO_EN;
  36.557 - 		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
  36.558 - 	}
  36.559 -@@ -3543,10 +3543,10 @@ #endif
  36.560 - 	}
  36.561 - 
  36.562 - 	frg_len = skb->len - skb->data_len;
  36.563 --	if (skb_shinfo(skb)->ufo_size) {
  36.564 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
  36.565 - 		int ufo_size;
  36.566 - 
  36.567 --		ufo_size = skb_shinfo(skb)->ufo_size;
  36.568 -+		ufo_size = skb_shinfo(skb)->gso_size;
  36.569 - 		ufo_size &= ~7;
  36.570 - 		txdp->Control_1 |= TXD_UFO_EN;
  36.571 - 		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
  36.572 -@@ -3572,7 +3572,7 @@ #endif
  36.573 - 	txdp->Host_Control = (unsigned long) skb;
  36.574 - 	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
  36.575 - 
  36.576 --	if (skb_shinfo(skb)->ufo_size)
  36.577 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  36.578 - 		txdp->Control_1 |= TXD_UFO_EN;
  36.579 - 
  36.580 - 	frg_cnt = skb_shinfo(skb)->nr_frags;
  36.581 -@@ -3587,12 +3587,12 @@ #endif
  36.582 - 		    (sp->pdev, frag->page, frag->page_offset,
  36.583 - 		     frag->size, PCI_DMA_TODEVICE);
  36.584 - 		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
  36.585 --		if (skb_shinfo(skb)->ufo_size)
  36.586 -+		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  36.587 - 			txdp->Control_1 |= TXD_UFO_EN;
  36.588 - 	}
  36.589 - 	txdp->Control_1 |= TXD_GATHER_CODE_LAST;
  36.590 - 
  36.591 --	if (skb_shinfo(skb)->ufo_size)
  36.592 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  36.593 - 		frg_cnt++; /* as Txd0 was used for inband header */
  36.594 - 
  36.595 - 	tx_fifo = mac_control->tx_FIFO_start[queue];
  36.596 -@@ -3606,7 +3606,7 @@ #ifdef NETIF_F_TSO
  36.597 - 	if (mss)
  36.598 - 		val64 |= TX_FIFO_SPECIAL_FUNC;
  36.599 - #endif
  36.600 --	if (skb_shinfo(skb)->ufo_size)
  36.601 -+	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  36.602 - 		val64 |= TX_FIFO_SPECIAL_FUNC;
  36.603 - 	writeq(val64, &tx_fifo->List_Control);
  36.604 - 
  36.605 -diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
  36.606 -index 0618cd5..2a55eb3 100644
  36.607 ---- a/drivers/net/sky2.c
  36.608 -+++ b/drivers/net/sky2.c
  36.609 -@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
  36.610 - 	count = sizeof(dma_addr_t) / sizeof(u32);
  36.611 - 	count += skb_shinfo(skb)->nr_frags * count;
  36.612 - 
  36.613 --	if (skb_shinfo(skb)->tso_size)
  36.614 -+	if (skb_shinfo(skb)->gso_size)
  36.615 - 		++count;
  36.616 - 
  36.617 - 	if (skb->ip_summed == CHECKSUM_HW)
  36.618 -@@ -1197,7 +1197,7 @@ static int sky2_xmit_frame(struct sk_buf
  36.619 - 	}
  36.620 - 
  36.621 - 	/* Check for TCP Segmentation Offload */
  36.622 --	mss = skb_shinfo(skb)->tso_size;
  36.623 -+	mss = skb_shinfo(skb)->gso_size;
  36.624 - 	if (mss != 0) {
  36.625 - 		/* just drop the packet if non-linear expansion fails */
  36.626 - 		if (skb_header_cloned(skb) &&
  36.627 -diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
  36.628 -index caf4102..fc9164a 100644
  36.629 ---- a/drivers/net/tg3.c
  36.630 -+++ b/drivers/net/tg3.c
  36.631 -@@ -3664,7 +3664,7 @@ static int tg3_start_xmit(struct sk_buff
  36.632 - #if TG3_TSO_SUPPORT != 0
  36.633 - 	mss = 0;
  36.634 - 	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
  36.635 --	    (mss = skb_shinfo(skb)->tso_size) != 0) {
  36.636 -+	    (mss = skb_shinfo(skb)->gso_size) != 0) {
  36.637 - 		int tcp_opt_len, ip_tcp_len;
  36.638 - 
  36.639 - 		if (skb_header_cloned(skb) &&
  36.640 -diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
  36.641 -index 5b1af39..11de5af 100644
  36.642 ---- a/drivers/net/tulip/winbond-840.c
  36.643 -+++ b/drivers/net/tulip/winbond-840.c
  36.644 -@@ -1605,11 +1605,11 @@ #ifdef CONFIG_PM
  36.645 -  * - get_stats:
  36.646 -  * 	spin_lock_irq(np->lock), doesn't touch hw if not present
  36.647 -  * - hard_start_xmit:
  36.648 -- * 	netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
  36.649 -+ * 	synchronize_irq + netif_tx_disable;
  36.650 -  * - tx_timeout:
  36.651 -- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  36.652 -+ * 	netif_device_detach + netif_tx_disable;
  36.653 -  * - set_multicast_list
  36.654 -- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  36.655 -+ * 	netif_device_detach + netif_tx_disable;
  36.656 -  * - interrupt handler
  36.657 -  * 	doesn't touch hw if not present, synchronize_irq waits for
  36.658 -  * 	running instances of the interrupt handler.
  36.659 -@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev 
  36.660 - 		netif_device_detach(dev);
  36.661 - 		update_csr6(dev, 0);
  36.662 - 		iowrite32(0, ioaddr + IntrEnable);
  36.663 --		netif_stop_queue(dev);
  36.664 - 		spin_unlock_irq(&np->lock);
  36.665 - 
  36.666 --		spin_unlock_wait(&dev->xmit_lock);
  36.667 - 		synchronize_irq(dev->irq);
  36.668 -+		netif_tx_disable(dev);
  36.669 - 	
  36.670 - 		np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
  36.671 - 
  36.672 -diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
  36.673 -index 4c76cb7..30c48c9 100644
  36.674 ---- a/drivers/net/typhoon.c
  36.675 -+++ b/drivers/net/typhoon.c
  36.676 -@@ -340,7 +340,7 @@ #define typhoon_synchronize_irq(x) synch
  36.677 - #endif
  36.678 - 
  36.679 - #if defined(NETIF_F_TSO)
  36.680 --#define skb_tso_size(x)		(skb_shinfo(x)->tso_size)
  36.681 -+#define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
  36.682 - #define TSO_NUM_DESCRIPTORS	2
  36.683 - #define TSO_OFFLOAD_ON		TYPHOON_OFFLOAD_TCP_SEGMENT
  36.684 - #else
  36.685 -diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
  36.686 -index ed1f837..2eb6b5f 100644
  36.687 ---- a/drivers/net/via-velocity.c
  36.688 -+++ b/drivers/net/via-velocity.c
  36.689 -@@ -1899,6 +1899,13 @@ static int velocity_xmit(struct sk_buff 
  36.690 - 
  36.691 - 	int pktlen = skb->len;
  36.692 - 
  36.693 -+#ifdef VELOCITY_ZERO_COPY_SUPPORT
  36.694 -+	if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
  36.695 -+		kfree_skb(skb);
  36.696 -+		return 0;
  36.697 -+	}
  36.698 -+#endif
  36.699 -+
  36.700 - 	spin_lock_irqsave(&vptr->lock, flags);
  36.701 - 
  36.702 - 	index = vptr->td_curr[qnum];
  36.703 -@@ -1914,8 +1921,6 @@ static int velocity_xmit(struct sk_buff 
  36.704 - 	 */
  36.705 - 	if (pktlen < ETH_ZLEN) {
  36.706 - 		/* Cannot occur until ZC support */
  36.707 --		if(skb_linearize(skb, GFP_ATOMIC))
  36.708 --			return 0; 
  36.709 - 		pktlen = ETH_ZLEN;
  36.710 - 		memcpy(tdinfo->buf, skb->data, skb->len);
  36.711 - 		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
  36.712 -@@ -1933,7 +1938,6 @@ #ifdef VELOCITY_ZERO_COPY_SUPPORT
  36.713 - 		int nfrags = skb_shinfo(skb)->nr_frags;
  36.714 - 		tdinfo->skb = skb;
  36.715 - 		if (nfrags > 6) {
  36.716 --			skb_linearize(skb, GFP_ATOMIC);
  36.717 - 			memcpy(tdinfo->buf, skb->data, skb->len);
  36.718 - 			tdinfo->skb_dma[0] = tdinfo->buf_dma;
  36.719 - 			td_ptr->tdesc0.pktsize = 
  36.720 -diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
  36.721 -index 6fd0bf7..75237c1 100644
  36.722 ---- a/drivers/net/wireless/orinoco.c
  36.723 -+++ b/drivers/net/wireless/orinoco.c
  36.724 -@@ -1835,7 +1835,9 @@ static int __orinoco_program_rids(struct
  36.725 - 	/* Set promiscuity / multicast*/
  36.726 - 	priv->promiscuous = 0;
  36.727 - 	priv->mc_count = 0;
  36.728 --	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
  36.729 -+
  36.730 -+	/* FIXME: what about netif_tx_lock */
  36.731 -+	__orinoco_set_multicast_list(dev);
  36.732 - 
  36.733 - 	return 0;
  36.734 - }
  36.735 -diff --git a/drivers/s390/net/qeth_eddp.c b/drivers/s390/net/qeth_eddp.c
  36.736 -index 82cb4af..57cec40 100644
  36.737 ---- a/drivers/s390/net/qeth_eddp.c
  36.738 -+++ b/drivers/s390/net/qeth_eddp.c
  36.739 -@@ -421,7 +421,7 @@ #endif /* CONFIG_QETH_VLAN */
  36.740 -        }
  36.741 - 	tcph = eddp->skb->h.th;
  36.742 - 	while (eddp->skb_offset < eddp->skb->len) {
  36.743 --		data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
  36.744 -+		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
  36.745 - 			       (int)(eddp->skb->len - eddp->skb_offset));
  36.746 - 		/* prepare qdio hdr */
  36.747 - 		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
  36.748 -@@ -516,20 +516,20 @@ qeth_eddp_calc_num_pages(struct qeth_edd
  36.749 - 	
  36.750 - 	QETH_DBF_TEXT(trace, 5, "eddpcanp");
  36.751 - 	/* can we put multiple skbs in one page? */
  36.752 --	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
  36.753 -+	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
  36.754 - 	if (skbs_per_page > 1){
  36.755 --		ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
  36.756 -+		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
  36.757 - 				 skbs_per_page + 1;
  36.758 - 		ctx->elements_per_skb = 1;
  36.759 - 	} else {
  36.760 - 		/* no -> how many elements per skb? */
  36.761 --		ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
  36.762 -+		ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
  36.763 - 				     PAGE_SIZE) >> PAGE_SHIFT;
  36.764 - 		ctx->num_pages = ctx->elements_per_skb *
  36.765 --				 (skb_shinfo(skb)->tso_segs + 1);
  36.766 -+				 (skb_shinfo(skb)->gso_segs + 1);
  36.767 - 	}
  36.768 - 	ctx->num_elements = ctx->elements_per_skb *
  36.769 --			    (skb_shinfo(skb)->tso_segs + 1);
  36.770 -+			    (skb_shinfo(skb)->gso_segs + 1);
  36.771 - }
  36.772 - 
  36.773 - static inline struct qeth_eddp_context *
  36.774 -diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
  36.775 -index dba7f7f..d9cc997 100644
  36.776 ---- a/drivers/s390/net/qeth_main.c
  36.777 -+++ b/drivers/s390/net/qeth_main.c
  36.778 -@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
  36.779 - 	queue = card->qdio.out_qs
  36.780 - 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
  36.781 - 
  36.782 --	if (skb_shinfo(skb)->tso_size)
  36.783 -+	if (skb_shinfo(skb)->gso_size)
  36.784 - 		large_send = card->options.large_send;
  36.785 - 
  36.786 - 	/*are we able to do TSO ? If so ,prepare and send it from here */
  36.787 -@@ -4501,7 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
  36.788 - 		card->stats.tx_packets++;
  36.789 - 		card->stats.tx_bytes += skb->len;
  36.790 - #ifdef CONFIG_QETH_PERF_STATS
  36.791 --		if (skb_shinfo(skb)->tso_size &&
  36.792 -+		if (skb_shinfo(skb)->gso_size &&
  36.793 - 		   !(large_send == QETH_LARGE_SEND_NO)) {
  36.794 - 			card->perf_stats.large_send_bytes += skb->len;
  36.795 - 			card->perf_stats.large_send_cnt++;
  36.796 -diff --git a/drivers/s390/net/qeth_tso.h b/drivers/s390/net/qeth_tso.h
  36.797 -index 1286dde..89cbf34 100644
  36.798 ---- a/drivers/s390/net/qeth_tso.h
  36.799 -+++ b/drivers/s390/net/qeth_tso.h
  36.800 -@@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *c
  36.801 - 	hdr->ext.hdr_version = 1;
  36.802 - 	hdr->ext.hdr_len     = 28;
  36.803 - 	/*insert non-fix values */
  36.804 --	hdr->ext.mss = skb_shinfo(skb)->tso_size;
  36.805 -+	hdr->ext.mss = skb_shinfo(skb)->gso_size;
  36.806 - 	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
  36.807 - 	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
  36.808 - 				       sizeof(struct qeth_hdr_tso));
  36.809 -diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
  36.810 -index 93535f0..9269df7 100644
  36.811 ---- a/include/linux/ethtool.h
  36.812 -+++ b/include/linux/ethtool.h
  36.813 -@@ -408,6 +408,8 @@ #define ETHTOOL_STSO		0x0000001f /* Set 
  36.814 - #define ETHTOOL_GPERMADDR	0x00000020 /* Get permanent hardware address */
  36.815 - #define ETHTOOL_GUFO		0x00000021 /* Get UFO enable (ethtool_value) */
  36.816 - #define ETHTOOL_SUFO		0x00000022 /* Set UFO enable (ethtool_value) */
  36.817 -+#define ETHTOOL_GGSO		0x00000023 /* Get GSO enable (ethtool_value) */
  36.818 -+#define ETHTOOL_SGSO		0x00000024 /* Set GSO enable (ethtool_value) */
  36.819 - 
  36.820 - /* compatibility with older code */
  36.821 - #define SPARC_ETH_GSET		ETHTOOL_GSET
  36.822 -diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
  36.823 -index 7fda03d..47b0965 100644
  36.824 ---- a/include/linux/netdevice.h
  36.825 -+++ b/include/linux/netdevice.h
  36.826 -@@ -230,7 +230,8 @@ enum netdev_state_t
  36.827 - 	__LINK_STATE_SCHED,
  36.828 - 	__LINK_STATE_NOCARRIER,
  36.829 - 	__LINK_STATE_RX_SCHED,
  36.830 --	__LINK_STATE_LINKWATCH_PENDING
  36.831 -+	__LINK_STATE_LINKWATCH_PENDING,
  36.832 -+	__LINK_STATE_QDISC_RUNNING,
  36.833 - };
  36.834 - 
  36.835 - 
  36.836 -@@ -306,9 +307,17 @@ #define NETIF_F_HW_VLAN_TX	128	/* Transm
  36.837 - #define NETIF_F_HW_VLAN_RX	256	/* Receive VLAN hw acceleration */
  36.838 - #define NETIF_F_HW_VLAN_FILTER	512	/* Receive filtering on VLAN */
  36.839 - #define NETIF_F_VLAN_CHALLENGED	1024	/* Device cannot handle VLAN packets */
  36.840 --#define NETIF_F_TSO		2048	/* Can offload TCP/IP segmentation */
  36.841 -+#define NETIF_F_GSO		2048	/* Enable software GSO. */
  36.842 - #define NETIF_F_LLTX		4096	/* LockLess TX */
  36.843 --#define NETIF_F_UFO             8192    /* Can offload UDP Large Send*/
  36.844 -+
  36.845 -+	/* Segmentation offload features */
  36.846 -+#define NETIF_F_GSO_SHIFT	16
  36.847 -+#define NETIF_F_TSO		(SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
  36.848 -+#define NETIF_F_UFO		(SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
  36.849 -+#define NETIF_F_GSO_ROBUST	(SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
  36.850 -+
  36.851 -+#define NETIF_F_GEN_CSUM	(NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
  36.852 -+#define NETIF_F_ALL_CSUM	(NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
  36.853 - 
  36.854 - 	struct net_device	*next_sched;
  36.855 - 
  36.856 -@@ -394,6 +403,9 @@ #define NETIF_F_UFO             8192    
  36.857 - 	struct list_head	qdisc_list;
  36.858 - 	unsigned long		tx_queue_len;	/* Max frames per queue allowed */
  36.859 - 
  36.860 -+	/* Partially transmitted GSO packet. */
  36.861 -+	struct sk_buff		*gso_skb;
  36.862 -+
  36.863 - 	/* ingress path synchronizer */
  36.864 - 	spinlock_t		ingress_lock;
  36.865 - 	struct Qdisc		*qdisc_ingress;
  36.866 -@@ -402,7 +414,7 @@ #define NETIF_F_UFO             8192    
  36.867 -  * One part is mostly used on xmit path (device)
  36.868 -  */
  36.869 - 	/* hard_start_xmit synchronizer */
  36.870 --	spinlock_t		xmit_lock ____cacheline_aligned_in_smp;
  36.871 -+	spinlock_t		_xmit_lock ____cacheline_aligned_in_smp;
  36.872 - 	/* cpu id of processor entered to hard_start_xmit or -1,
  36.873 - 	   if nobody entered there.
  36.874 - 	 */
  36.875 -@@ -527,6 +539,8 @@ struct packet_type {
  36.876 - 					 struct net_device *,
  36.877 - 					 struct packet_type *,
  36.878 - 					 struct net_device *);
  36.879 -+	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
  36.880 -+						int features);
  36.881 - 	void			*af_packet_priv;
  36.882 - 	struct list_head	list;
  36.883 - };
  36.884 -@@ -693,7 +707,8 @@ extern int		dev_change_name(struct net_d
  36.885 - extern int		dev_set_mtu(struct net_device *, int);
  36.886 - extern int		dev_set_mac_address(struct net_device *,
  36.887 - 					    struct sockaddr *);
  36.888 --extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
  36.889 -+extern int		dev_hard_start_xmit(struct sk_buff *skb,
  36.890 -+					    struct net_device *dev);
  36.891 - 
  36.892 - extern void		dev_init(void);
  36.893 - 
  36.894 -@@ -900,11 +915,43 @@ static inline void __netif_rx_complete(s
  36.895 - 	clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
  36.896 - }
  36.897 - 
  36.898 -+static inline void netif_tx_lock(struct net_device *dev)
  36.899 -+{
  36.900 -+	spin_lock(&dev->_xmit_lock);
  36.901 -+	dev->xmit_lock_owner = smp_processor_id();
  36.902 -+}
  36.903 -+
  36.904 -+static inline void netif_tx_lock_bh(struct net_device *dev)
  36.905 -+{
  36.906 -+	spin_lock_bh(&dev->_xmit_lock);
  36.907 -+	dev->xmit_lock_owner = smp_processor_id();
  36.908 -+}
  36.909 -+
  36.910 -+static inline int netif_tx_trylock(struct net_device *dev)
  36.911 -+{
  36.912 -+	int err = spin_trylock(&dev->_xmit_lock);
  36.913 -+	if (!err)
  36.914 -+		dev->xmit_lock_owner = smp_processor_id();
  36.915 -+	return err;
  36.916 -+}
  36.917 -+
  36.918 -+static inline void netif_tx_unlock(struct net_device *dev)
  36.919 -+{
  36.920 -+	dev->xmit_lock_owner = -1;
  36.921 -+	spin_unlock(&dev->_xmit_lock);
  36.922 -+}
  36.923 -+
  36.924 -+static inline void netif_tx_unlock_bh(struct net_device *dev)
  36.925 -+{
  36.926 -+	dev->xmit_lock_owner = -1;
  36.927 -+	spin_unlock_bh(&dev->_xmit_lock);
  36.928 -+}
  36.929 -+
  36.930 - static inline void netif_tx_disable(struct net_device *dev)
  36.931 - {
  36.932 --	spin_lock_bh(&dev->xmit_lock);
  36.933 -+	netif_tx_lock_bh(dev);
  36.934 - 	netif_stop_queue(dev);
  36.935 --	spin_unlock_bh(&dev->xmit_lock);
  36.936 -+	netif_tx_unlock_bh(dev);
  36.937 - }
  36.938 - 
  36.939 - /* These functions live elsewhere (drivers/net/net_init.c, but related) */
  36.940 -@@ -932,6 +979,7 @@ extern int		netdev_max_backlog;
  36.941 - extern int		weight_p;
  36.942 - extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
  36.943 - extern int skb_checksum_help(struct sk_buff *skb, int inward);
  36.944 -+extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
  36.945 - #ifdef CONFIG_BUG
  36.946 - extern void netdev_rx_csum_fault(struct net_device *dev);
  36.947 - #else
  36.948 -@@ -951,6 +999,18 @@ #endif
  36.949 - 
  36.950 - extern void linkwatch_run_queue(void);
  36.951 - 
  36.952 -+static inline int skb_gso_ok(struct sk_buff *skb, int features)
  36.953 -+{
  36.954 -+	int feature = skb_shinfo(skb)->gso_size ?
  36.955 -+		      skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
  36.956 -+	return (features & feature) == feature;
  36.957 -+}
  36.958 -+
  36.959 -+static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
  36.960 -+{
  36.961 -+	return !skb_gso_ok(skb, dev->features);
  36.962 -+}
  36.963 -+
  36.964 - #endif /* __KERNEL__ */
  36.965 - 
  36.966 - #endif	/* _LINUX_DEV_H */
  36.967 -diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
  36.968 -index ad7cc22..b19d45d 100644
  36.969 ---- a/include/linux/skbuff.h
  36.970 -+++ b/include/linux/skbuff.h
  36.971 -@@ -134,9 +134,10 @@ struct skb_frag_struct {
  36.972 - struct skb_shared_info {
  36.973 - 	atomic_t	dataref;
  36.974 - 	unsigned short	nr_frags;
  36.975 --	unsigned short	tso_size;
  36.976 --	unsigned short	tso_segs;
  36.977 --	unsigned short  ufo_size;
  36.978 -+	unsigned short	gso_size;
  36.979 -+	/* Warning: this field is not always filled in (UFO)! */
  36.980 -+	unsigned short	gso_segs;
  36.981 -+	unsigned short  gso_type;
  36.982 - 	unsigned int    ip6_frag_id;
  36.983 - 	struct sk_buff	*frag_list;
  36.984 - 	skb_frag_t	frags[MAX_SKB_FRAGS];
  36.985 -@@ -168,6 +169,14 @@ enum {
  36.986 - 	SKB_FCLONE_CLONE,
  36.987 - };
  36.988 - 
  36.989 -+enum {
  36.990 -+	SKB_GSO_TCPV4 = 1 << 0,
  36.991 -+	SKB_GSO_UDPV4 = 1 << 1,
  36.992 -+
  36.993 -+	/* This indicates the skb is from an untrusted source. */
  36.994 -+	SKB_GSO_DODGY = 1 << 2,
  36.995 -+};
  36.996 -+
  36.997 - /** 
  36.998 -  *	struct sk_buff - socket buffer
  36.999 -  *	@next: Next buffer in list
 36.1000 -@@ -1148,18 +1157,34 @@ static inline int skb_can_coalesce(struc
 36.1001 - 	return 0;
 36.1002 - }
 36.1003 - 
 36.1004 -+static inline int __skb_linearize(struct sk_buff *skb)
 36.1005 -+{
 36.1006 -+	return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
 36.1007 -+}
 36.1008 -+
 36.1009 - /**
 36.1010 -  *	skb_linearize - convert paged skb to linear one
 36.1011 -  *	@skb: buffer to linarize
 36.1012 -- *	@gfp: allocation mode
 36.1013 -  *
 36.1014 -  *	If there is no free memory -ENOMEM is returned, otherwise zero
 36.1015 -  *	is returned and the old skb data released.
 36.1016 -  */
 36.1017 --extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp);
 36.1018 --static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
 36.1019 -+static inline int skb_linearize(struct sk_buff *skb)
 36.1020 -+{
 36.1021 -+	return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
 36.1022 -+}
 36.1023 -+
 36.1024 -+/**
 36.1025 -+ *	skb_linearize_cow - make sure skb is linear and writable
 36.1026 -+ *	@skb: buffer to process
 36.1027 -+ *
 36.1028 -+ *	If there is no free memory -ENOMEM is returned, otherwise zero
 36.1029 -+ *	is returned and the old skb data released.
 36.1030 -+ */
 36.1031 -+static inline int skb_linearize_cow(struct sk_buff *skb)
 36.1032 - {
 36.1033 --	return __skb_linearize(skb, gfp);
 36.1034 -+	return skb_is_nonlinear(skb) || skb_cloned(skb) ?
 36.1035 -+	       __skb_linearize(skb) : 0;
 36.1036 - }
 36.1037 - 
 36.1038 - /**
 36.1039 -@@ -1254,6 +1279,7 @@ extern void	       skb_split(struct sk_b
 36.1040 - 				 struct sk_buff *skb1, const u32 len);
 36.1041 - 
 36.1042 - extern void	       skb_release_data(struct sk_buff *skb);
 36.1043 -+extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
 36.1044 - 
 36.1045 - static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
 36.1046 - 				       int len, void *buffer)
 36.1047 -diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
 36.1048 -index b94d1ad..75b5b93 100644
 36.1049 ---- a/include/net/pkt_sched.h
 36.1050 -+++ b/include/net/pkt_sched.h
 36.1051 -@@ -218,12 +218,13 @@ extern struct qdisc_rate_table *qdisc_ge
 36.1052 - 		struct rtattr *tab);
 36.1053 - extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 36.1054 - 
 36.1055 --extern int qdisc_restart(struct net_device *dev);
 36.1056 -+extern void __qdisc_run(struct net_device *dev);
 36.1057 - 
 36.1058 - static inline void qdisc_run(struct net_device *dev)
 36.1059 - {
 36.1060 --	while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0)
 36.1061 --		/* NOTHING */;
 36.1062 -+	if (!netif_queue_stopped(dev) &&
 36.1063 -+	    !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
 36.1064 -+		__qdisc_run(dev);
 36.1065 - }
 36.1066 - 
 36.1067 - extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
 36.1068 -diff --git a/include/net/protocol.h b/include/net/protocol.h
 36.1069 -index 6dc5970..0d2dcdb 100644
 36.1070 ---- a/include/net/protocol.h
 36.1071 -+++ b/include/net/protocol.h
 36.1072 -@@ -37,6 +37,8 @@ #define MAX_INET_PROTOS	256		/* Must be 
 36.1073 - struct net_protocol {
 36.1074 - 	int			(*handler)(struct sk_buff *skb);
 36.1075 - 	void			(*err_handler)(struct sk_buff *skb, u32 info);
 36.1076 -+	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
 36.1077 -+					       int features);
 36.1078 - 	int			no_policy;
 36.1079 - };
 36.1080 - 
 36.1081 -diff --git a/include/net/sock.h b/include/net/sock.h
 36.1082 -index f63d0d5..a8e8d21 100644
 36.1083 ---- a/include/net/sock.h
 36.1084 -+++ b/include/net/sock.h
 36.1085 -@@ -1064,9 +1064,13 @@ static inline void sk_setup_caps(struct 
 36.1086 - {
 36.1087 - 	__sk_dst_set(sk, dst);
 36.1088 - 	sk->sk_route_caps = dst->dev->features;
 36.1089 -+	if (sk->sk_route_caps & NETIF_F_GSO)
 36.1090 -+		sk->sk_route_caps |= NETIF_F_TSO;
 36.1091 - 	if (sk->sk_route_caps & NETIF_F_TSO) {
 36.1092 - 		if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
 36.1093 - 			sk->sk_route_caps &= ~NETIF_F_TSO;
 36.1094 -+		else 
 36.1095 -+			sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
 36.1096 - 	}
 36.1097 - }
 36.1098 - 
 36.1099 -diff --git a/include/net/tcp.h b/include/net/tcp.h
 36.1100 -index 77f21c6..70e1d5f 100644
 36.1101 ---- a/include/net/tcp.h
 36.1102 -+++ b/include/net/tcp.h
 36.1103 -@@ -552,13 +552,13 @@ #include <net/tcp_ecn.h>
 36.1104 -  */
 36.1105 - static inline int tcp_skb_pcount(const struct sk_buff *skb)
 36.1106 - {
 36.1107 --	return skb_shinfo(skb)->tso_segs;
 36.1108 -+	return skb_shinfo(skb)->gso_segs;
 36.1109 - }
 36.1110 - 
 36.1111 - /* This is valid iff tcp_skb_pcount() > 1. */
 36.1112 - static inline int tcp_skb_mss(const struct sk_buff *skb)
 36.1113 - {
 36.1114 --	return skb_shinfo(skb)->tso_size;
 36.1115 -+	return skb_shinfo(skb)->gso_size;
 36.1116 - }
 36.1117 - 
 36.1118 - static inline void tcp_dec_pcount_approx(__u32 *count,
 36.1119 -@@ -1063,6 +1063,8 @@ extern struct request_sock_ops tcp_reque
 36.1120 - 
 36.1121 - extern int tcp_v4_destroy_sock(struct sock *sk);
 36.1122 - 
 36.1123 -+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
 36.1124 -+
 36.1125 - #ifdef CONFIG_PROC_FS
 36.1126 - extern int  tcp4_proc_init(void);
 36.1127 - extern void tcp4_proc_exit(void);
 36.1128 -diff --git a/net/atm/clip.c b/net/atm/clip.c
 36.1129 -index 1842a4e..6dc21a7 100644
 36.1130 ---- a/net/atm/clip.c
 36.1131 -+++ b/net/atm/clip.c
 36.1132 -@@ -101,7 +101,7 @@ static void unlink_clip_vcc(struct clip_
 36.1133 - 		printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
 36.1134 - 		return;
 36.1135 - 	}
 36.1136 --	spin_lock_bh(&entry->neigh->dev->xmit_lock);	/* block clip_start_xmit() */
 36.1137 -+	netif_tx_lock_bh(entry->neigh->dev);	/* block clip_start_xmit() */
 36.1138 - 	entry->neigh->used = jiffies;
 36.1139 - 	for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
 36.1140 - 		if (*walk == clip_vcc) {
 36.1141 -@@ -125,7 +125,7 @@ static void unlink_clip_vcc(struct clip_
 36.1142 - 	printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
 36.1143 - 	  "0x%p)\n",entry,clip_vcc);
 36.1144 - out:
 36.1145 --	spin_unlock_bh(&entry->neigh->dev->xmit_lock);
 36.1146 -+	netif_tx_unlock_bh(entry->neigh->dev);
 36.1147 - }
 36.1148 - 
 36.1149 - /* The neighbour entry n->lock is held. */
 36.1150 -diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
 36.1151 -index 0b33a7b..180e79b 100644
 36.1152 ---- a/net/bridge/br_device.c
 36.1153 -+++ b/net/bridge/br_device.c
 36.1154 -@@ -146,9 +146,9 @@ static int br_set_tx_csum(struct net_dev
 36.1155 - 	struct net_bridge *br = netdev_priv(dev);
 36.1156 - 
 36.1157 - 	if (data)
 36.1158 --		br->feature_mask |= NETIF_F_IP_CSUM;
 36.1159 -+		br->feature_mask |= NETIF_F_NO_CSUM;
 36.1160 - 	else
 36.1161 --		br->feature_mask &= ~NETIF_F_IP_CSUM;
 36.1162 -+		br->feature_mask &= ~NETIF_F_ALL_CSUM;
 36.1163 - 
 36.1164 - 	br_features_recompute(br);
 36.1165 - 	return 0;
 36.1166 -@@ -185,6 +185,6 @@ void br_dev_setup(struct net_device *dev
 36.1167 - 	dev->set_mac_address = br_set_mac_address;
 36.1168 - 	dev->priv_flags = IFF_EBRIDGE;
 36.1169 - 
 36.1170 -- 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
 36.1171 -- 		| NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
 36.1172 -+ 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
 36.1173 -+ 			NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
 36.1174 - }
 36.1175 -diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
 36.1176 -index 2d24fb4..00b1128 100644
 36.1177 ---- a/net/bridge/br_forward.c
 36.1178 -+++ b/net/bridge/br_forward.c
 36.1179 -@@ -32,7 +32,7 @@ static inline int should_deliver(const s
 36.1180 - int br_dev_queue_push_xmit(struct sk_buff *skb)
 36.1181 - {
 36.1182 - 	/* drop mtu oversized packets except tso */
 36.1183 --	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
 36.1184 -+	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
 36.1185 - 		kfree_skb(skb);
 36.1186 - 	else {
 36.1187 - #ifdef CONFIG_BRIDGE_NETFILTER
 36.1188 -diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
 36.1189 -index f36b35e..0617146 100644
 36.1190 ---- a/net/bridge/br_if.c
 36.1191 -+++ b/net/bridge/br_if.c
 36.1192 -@@ -385,17 +385,28 @@ void br_features_recompute(struct net_br
 36.1193 - 	struct net_bridge_port *p;
 36.1194 - 	unsigned long features, checksum;
 36.1195 - 
 36.1196 --	features = br->feature_mask &~ NETIF_F_IP_CSUM;
 36.1197 --	checksum = br->feature_mask & NETIF_F_IP_CSUM;
 36.1198 -+	checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0;
 36.1199 -+	features = br->feature_mask & ~NETIF_F_ALL_CSUM;
 36.1200 - 
 36.1201 - 	list_for_each_entry(p, &br->port_list, list) {
 36.1202 --		if (!(p->dev->features 
 36.1203 --		      & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)))
 36.1204 -+		unsigned long feature = p->dev->features;
 36.1205 -+
 36.1206 -+		if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
 36.1207 -+			checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
 36.1208 -+		if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
 36.1209 -+			checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
 36.1210 -+		if (!(feature & NETIF_F_IP_CSUM))
 36.1211 - 			checksum = 0;
 36.1212 --		features &= p->dev->features;
 36.1213 -+
 36.1214 -+		if (feature & NETIF_F_GSO)
 36.1215 -+			feature |= NETIF_F_TSO;
 36.1216 -+		feature |= NETIF_F_GSO;
 36.1217 -+
 36.1218 -+		features &= feature;
 36.1219 - 	}
 36.1220 - 
 36.1221 --	br->dev->features = features | checksum | NETIF_F_LLTX;
 36.1222 -+	br->dev->features = features | checksum | NETIF_F_LLTX |
 36.1223 -+			    NETIF_F_GSO_ROBUST;
 36.1224 - }
 36.1225 - 
 36.1226 - /* called with RTNL */
 36.1227 -diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
 36.1228 -index 9e27373..588207f 100644
 36.1229 ---- a/net/bridge/br_netfilter.c
 36.1230 -+++ b/net/bridge/br_netfilter.c
 36.1231 -@@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
 36.1232 - {
 36.1233 - 	if (skb->protocol == htons(ETH_P_IP) &&
 36.1234 - 	    skb->len > skb->dev->mtu &&
 36.1235 --	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
 36.1236 -+	    !skb_shinfo(skb)->gso_size)
 36.1237 - 		return ip_fragment(skb, br_dev_queue_push_xmit);
 36.1238 - 	else
 36.1239 - 		return br_dev_queue_push_xmit(skb);
 36.1240 -diff --git a/net/core/dev.c b/net/core/dev.c
 36.1241 -index 12a214c..32e1056 100644
 36.1242 ---- a/net/core/dev.c
 36.1243 -+++ b/net/core/dev.c
 36.1244 -@@ -115,6 +115,7 @@ #include <linux/wireless.h>		/* Note : w
 36.1245 - #include <net/iw_handler.h>
 36.1246 - #endif	/* CONFIG_NET_RADIO */
 36.1247 - #include <asm/current.h>
 36.1248 -+#include <linux/err.h>
 36.1249 - 
 36.1250 - /*
 36.1251 -  *	The list of packet types we will receive (as opposed to discard)
 36.1252 -@@ -1032,7 +1033,7 @@ static inline void net_timestamp(struct 
 36.1253 -  *	taps currently in use.
 36.1254 -  */
 36.1255 - 
 36.1256 --void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 36.1257 -+static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
 36.1258 - {
 36.1259 - 	struct packet_type *ptype;
 36.1260 - 
 36.1261 -@@ -1106,6 +1107,45 @@ out:	
 36.1262 - 	return ret;
 36.1263 - }
 36.1264 - 
 36.1265 -+/**
 36.1266 -+ *	skb_gso_segment - Perform segmentation on skb.
 36.1267 -+ *	@skb: buffer to segment
 36.1268 -+ *	@features: features for the output path (see dev->features)
 36.1269 -+ *
 36.1270 -+ *	This function segments the given skb and returns a list of segments.
 36.1271 -+ *
 36.1272 -+ *	It may return NULL if the skb requires no segmentation.  This is
 36.1273 -+ *	only possible when GSO is used for verifying header integrity.
 36.1274 -+ */
 36.1275 -+struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
 36.1276 -+{
 36.1277 -+	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
 36.1278 -+	struct packet_type *ptype;
 36.1279 -+	int type = skb->protocol;
 36.1280 -+
 36.1281 -+	BUG_ON(skb_shinfo(skb)->frag_list);
 36.1282 -+	BUG_ON(skb->ip_summed != CHECKSUM_HW);
 36.1283 -+
 36.1284 -+	skb->mac.raw = skb->data;
 36.1285 -+	skb->mac_len = skb->nh.raw - skb->data;
 36.1286 -+	__skb_pull(skb, skb->mac_len);
 36.1287 -+
 36.1288 -+	rcu_read_lock();
 36.1289 -+	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
 36.1290 -+		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
 36.1291 -+			segs = ptype->gso_segment(skb, features);
 36.1292 -+			break;
 36.1293 -+		}
 36.1294 -+	}
 36.1295 -+	rcu_read_unlock();
 36.1296 -+
 36.1297 -+	__skb_push(skb, skb->data - skb->mac.raw);
 36.1298 -+
 36.1299 -+	return segs;
 36.1300 -+}
 36.1301 -+
 36.1302 -+EXPORT_SYMBOL(skb_gso_segment);
 36.1303 -+
 36.1304 - /* Take action when hardware reception checksum errors are detected. */
 36.1305 - #ifdef CONFIG_BUG
 36.1306 - void netdev_rx_csum_fault(struct net_device *dev)
 36.1307 -@@ -1142,75 +1182,108 @@ #else
 36.1308 - #define illegal_highdma(dev, skb)	(0)
 36.1309 - #endif
 36.1310 - 
 36.1311 --/* Keep head the same: replace data */
 36.1312 --int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
 36.1313 --{
 36.1314 --	unsigned int size;
 36.1315 --	u8 *data;
 36.1316 --	long offset;
 36.1317 --	struct skb_shared_info *ninfo;
 36.1318 --	int headerlen = skb->data - skb->head;
 36.1319 --	int expand = (skb->tail + skb->data_len) - skb->end;
 36.1320 --
 36.1321 --	if (skb_shared(skb))
 36.1322 --		BUG();
 36.1323 --
 36.1324 --	if (expand <= 0)
 36.1325 --		expand = 0;
 36.1326 --
 36.1327 --	size = skb->end - skb->head + expand;
 36.1328 --	size = SKB_DATA_ALIGN(size);
 36.1329 --	data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
 36.1330 --	if (!data)
 36.1331 --		return -ENOMEM;
 36.1332 --
 36.1333 --	/* Copy entire thing */
 36.1334 --	if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
 36.1335 --		BUG();
 36.1336 --
 36.1337 --	/* Set up shinfo */
 36.1338 --	ninfo = (struct skb_shared_info*)(data + size);
 36.1339 --	atomic_set(&ninfo->dataref, 1);
 36.1340 --	ninfo->tso_size = skb_shinfo(skb)->tso_size;
 36.1341 --	ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
 36.1342 --	ninfo->nr_frags = 0;
 36.1343 --	ninfo->frag_list = NULL;
 36.1344 --
 36.1345 --	/* Offset between the two in bytes */
 36.1346 --	offset = data - skb->head;
 36.1347 --
 36.1348 --	/* Free old data. */
 36.1349 --	skb_release_data(skb);
 36.1350 --
 36.1351 --	skb->head = data;
 36.1352 --	skb->end  = data + size;
 36.1353 --
 36.1354 --	/* Set up new pointers */
 36.1355 --	skb->h.raw   += offset;
 36.1356 --	skb->nh.raw  += offset;
 36.1357 --	skb->mac.raw += offset;
 36.1358 --	skb->tail    += offset;
 36.1359 --	skb->data    += offset;
 36.1360 --
 36.1361 --	/* We are no longer a clone, even if we were. */
 36.1362 --	skb->cloned    = 0;
 36.1363 --
 36.1364 --	skb->tail     += skb->data_len;
 36.1365 --	skb->data_len  = 0;
 36.1366 -+struct dev_gso_cb {
 36.1367 -+	void (*destructor)(struct sk_buff *skb);
 36.1368 -+};
 36.1369 -+
 36.1370 -+#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb)
 36.1371 -+
 36.1372 -+static void dev_gso_skb_destructor(struct sk_buff *skb)
 36.1373 -+{
 36.1374 -+	struct dev_gso_cb *cb;
 36.1375 -+
 36.1376 -+	do {
 36.1377 -+		struct sk_buff *nskb = skb->next;
 36.1378 -+
 36.1379 -+		skb->next = nskb->next;
 36.1380 -+		nskb->next = NULL;
 36.1381 -+		kfree_skb(nskb);
 36.1382 -+	} while (skb->next);
 36.1383 -+
 36.1384 -+	cb = DEV_GSO_CB(skb);
 36.1385 -+	if (cb->destructor)
 36.1386 -+		cb->destructor(skb);
 36.1387 -+}
 36.1388 -+
 36.1389 -+/**
 36.1390 -+ *	dev_gso_segment - Perform emulated hardware segmentation on skb.
 36.1391 -+ *	@skb: buffer to segment
 36.1392 -+ *
 36.1393 -+ *	This function segments the given skb and stores the list of segments
 36.1394 -+ *	in skb->next.
 36.1395 -+ */
 36.1396 -+static int dev_gso_segment(struct sk_buff *skb)
 36.1397 -+{
 36.1398 -+	struct net_device *dev = skb->dev;
 36.1399 -+	struct sk_buff *segs;
 36.1400 -+	int features = dev->features & ~(illegal_highdma(dev, skb) ?
 36.1401 -+					 NETIF_F_SG : 0);
 36.1402 -+
 36.1403 -+	segs = skb_gso_segment(skb, features);
 36.1404 -+
 36.1405 -+	/* Verifying header integrity only. */
 36.1406 -+	if (!segs)
 36.1407 -+		return 0;
 36.1408 -+
 36.1409 -+	if (unlikely(IS_ERR(segs)))
 36.1410 -+		return PTR_ERR(segs);
 36.1411 -+
 36.1412 -+	skb->next = segs;
 36.1413 -+	DEV_GSO_CB(skb)->destructor = skb->destructor;
 36.1414 -+	skb->destructor = dev_gso_skb_destructor;
 36.1415 -+
 36.1416 -+	return 0;
 36.1417 -+}
 36.1418 -+
 36.1419 -+int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 36.1420 -+{
 36.1421 -+	if (likely(!skb->next)) {
 36.1422 -+		if (netdev_nit)
 36.1423 -+			dev_queue_xmit_nit(skb, dev);
 36.1424 -+
 36.1425 -+		if (netif_needs_gso(dev, skb)) {
 36.1426 -+			if (unlikely(dev_gso_segment(skb)))
 36.1427 -+				goto out_kfree_skb;
 36.1428 -+			if (skb->next)
 36.1429 -+				goto gso;
 36.1430 -+		}
 36.1431 -+
 36.1432 -+		return dev->hard_start_xmit(skb, dev);
 36.1433 -+	}
 36.1434 -+
 36.1435 -+gso:
 36.1436 -+	do {
 36.1437 -+		struct sk_buff *nskb = skb->next;
 36.1438 -+		int rc;
 36.1439 -+
 36.1440 -+		skb->next = nskb->next;
 36.1441 -+		nskb->next = NULL;
 36.1442 -+		rc = dev->hard_start_xmit(nskb, dev);
 36.1443 -+		if (unlikely(rc)) {
 36.1444 -+			nskb->next = skb->next;
 36.1445 -+			skb->next = nskb;
 36.1446 -+			return rc;
 36.1447 -+		}
 36.1448 -+		if (unlikely(netif_queue_stopped(dev) && skb->next))
 36.1449 -+			return NETDEV_TX_BUSY;
 36.1450 -+	} while (skb->next);
 36.1451 -+	
 36.1452 -+	skb->destructor = DEV_GSO_CB(skb)->destructor;
 36.1453 -+
 36.1454 -+out_kfree_skb:
 36.1455 -+	kfree_skb(skb);
 36.1456 - 	return 0;
 36.1457 - }
 36.1458 - 
 36.1459 - #define HARD_TX_LOCK(dev, cpu) {			\
 36.1460 - 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
 36.1461 --		spin_lock(&dev->xmit_lock);		\
 36.1462 --		dev->xmit_lock_owner = cpu;		\
 36.1463 -+		netif_tx_lock(dev);			\
 36.1464 - 	}						\
 36.1465 - }
 36.1466 - 
 36.1467 - #define HARD_TX_UNLOCK(dev) {				\
 36.1468 - 	if ((dev->features & NETIF_F_LLTX) == 0) {	\
 36.1469 --		dev->xmit_lock_owner = -1;		\
 36.1470 --		spin_unlock(&dev->xmit_lock);		\
 36.1471 -+		netif_tx_unlock(dev);			\
 36.1472 - 	}						\
 36.1473 - }
 36.1474 - 
 36.1475 -@@ -1246,9 +1319,13 @@ int dev_queue_xmit(struct sk_buff *skb)
 36.1476 - 	struct Qdisc *q;
 36.1477 - 	int rc = -ENOMEM;
 36.1478 - 
 36.1479 -+	/* GSO will handle the following emulations directly. */
 36.1480 -+	if (netif_needs_gso(dev, skb))
 36.1481 -+		goto gso;
 36.1482 -+
 36.1483 - 	if (skb_shinfo(skb)->frag_list &&
 36.1484 - 	    !(dev->features & NETIF_F_FRAGLIST) &&
 36.1485 --	    __skb_linearize(skb, GFP_ATOMIC))
 36.1486 -+	    __skb_linearize(skb))
 36.1487 - 		goto out_kfree_skb;
 36.1488 - 
 36.1489 - 	/* Fragmented skb is linearized if device does not support SG,
 36.1490 -@@ -1257,25 +1334,26 @@ int dev_queue_xmit(struct sk_buff *skb)
 36.1491 - 	 */
 36.1492 - 	if (skb_shinfo(skb)->nr_frags &&
 36.1493 - 	    (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
 36.1494 --	    __skb_linearize(skb, GFP_ATOMIC))
 36.1495 -+	    __skb_linearize(skb))
 36.1496 - 		goto out_kfree_skb;
 36.1497 - 
 36.1498 - 	/* If packet is not checksummed and device does not support
 36.1499 - 	 * checksumming for this protocol, complete checksumming here.
 36.1500 - 	 */
 36.1501 - 	if (skb->ip_summed == CHECKSUM_HW &&
 36.1502 --	    (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
 36.1503 -+	    (!(dev->features & NETIF_F_GEN_CSUM) &&
 36.1504 - 	     (!(dev->features & NETIF_F_IP_CSUM) ||
 36.1505 - 	      skb->protocol != htons(ETH_P_IP))))
 36.1506 - 	      	if (skb_checksum_help(skb, 0))
 36.1507 - 	      		goto out_kfree_skb;
 36.1508 - 
 36.1509 -+gso:
 36.1510 - 	spin_lock_prefetch(&dev->queue_lock);
 36.1511 - 
 36.1512 - 	/* Disable soft irqs for various locks below. Also 
 36.1513 - 	 * stops preemption for RCU. 
 36.1514 - 	 */
 36.1515 --	local_bh_disable(); 
 36.1516 -+	rcu_read_lock_bh(); 
 36.1517 - 
 36.1518 - 	/* Updates of qdisc are serialized by queue_lock. 
 36.1519 - 	 * The struct Qdisc which is pointed to by qdisc is now a 
 36.1520 -@@ -1309,8 +1387,8 @@ #endif
 36.1521 - 	/* The device has no queue. Common case for software devices:
 36.1522 - 	   loopback, all the sorts of tunnels...
 36.1523 - 
 36.1524 --	   Really, it is unlikely that xmit_lock protection is necessary here.
 36.1525 --	   (f.e. loopback and IP tunnels are clean ignoring statistics
 36.1526 -+	   Really, it is unlikely that netif_tx_lock protection is necessary
 36.1527 -+	   here.  (f.e. loopback and IP tunnels are clean ignoring statistics
 36.1528 - 	   counters.)
 36.1529 - 	   However, it is possible, that they rely on protection
 36.1530 - 	   made by us here.
 36.1531 -@@ -1326,11 +1404,8 @@ #endif
 36.1532 - 			HARD_TX_LOCK(dev, cpu);
 36.1533 - 
 36.1534 - 			if (!netif_queue_stopped(dev)) {
 36.1535 --				if (netdev_nit)
 36.1536 --					dev_queue_xmit_nit(skb, dev);
 36.1537 --
 36.1538 - 				rc = 0;
 36.1539 --				if (!dev->hard_start_xmit(skb, dev)) {
 36.1540 -+				if (!dev_hard_start_xmit(skb, dev)) {
 36.1541 - 					HARD_TX_UNLOCK(dev);
 36.1542 - 					goto out;
 36.1543 - 				}
 36.1544 -@@ -1349,13 +1424,13 @@ #endif
 36.1545 - 	}
 36.1546 - 
 36.1547 - 	rc = -ENETDOWN;
 36.1548 --	local_bh_enable();
 36.1549 -+	rcu_read_unlock_bh();
 36.1550 - 
 36.1551 - out_kfree_skb:
 36.1552 - 	kfree_skb(skb);
 36.1553 - 	return rc;
 36.1554 - out:
 36.1555 --	local_bh_enable();
 36.1556 -+	rcu_read_unlock_bh();
 36.1557 - 	return rc;
 36.1558 - }
 36.1559 - 
 36.1560 -@@ -2670,7 +2745,7 @@ int register_netdevice(struct net_device
 36.1561 - 	BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
 36.1562 - 
 36.1563 - 	spin_lock_init(&dev->queue_lock);
 36.1564 --	spin_lock_init(&dev->xmit_lock);
 36.1565 -+	spin_lock_init(&dev->_xmit_lock);
 36.1566 - 	dev->xmit_lock_owner = -1;
 36.1567 - #ifdef CONFIG_NET_CLS_ACT
 36.1568 - 	spin_lock_init(&dev->ingress_lock);
 36.1569 -@@ -2714,9 +2789,7 @@ #endif
 36.1570 - 
 36.1571 - 	/* Fix illegal SG+CSUM combinations. */
 36.1572 - 	if ((dev->features & NETIF_F_SG) &&
 36.1573 --	    !(dev->features & (NETIF_F_IP_CSUM |
 36.1574 --			       NETIF_F_NO_CSUM |
 36.1575 --			       NETIF_F_HW_CSUM))) {
 36.1576 -+	    !(dev->features & NETIF_F_ALL_CSUM)) {
 36.1577 - 		printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
 36.1578 - 		       dev->name);
 36.1579 - 		dev->features &= ~NETIF_F_SG;
 36.1580 -@@ -3268,7 +3341,6 @@ subsys_initcall(net_dev_init);
 36.1581 - EXPORT_SYMBOL(__dev_get_by_index);
 36.1582 - EXPORT_SYMBOL(__dev_get_by_name);
 36.1583 - EXPORT_SYMBOL(__dev_remove_pack);
 36.1584 --EXPORT_SYMBOL(__skb_linearize);
 36.1585 - EXPORT_SYMBOL(dev_valid_name);
 36.1586 - EXPORT_SYMBOL(dev_add_pack);
 36.1587 - EXPORT_SYMBOL(dev_alloc_name);
 36.1588 -diff --git a/net/core/dev_mcast.c b/net/core/dev_mcast.c
 36.1589 -index 05d6085..c57d887 100644
 36.1590 ---- a/net/core/dev_mcast.c
 36.1591 -+++ b/net/core/dev_mcast.c
 36.1592 -@@ -62,7 +62,7 @@ #include <net/arp.h>
 36.1593 -  *	Device mc lists are changed by bh at least if IPv6 is enabled,
 36.1594 -  *	so that it must be bh protected.
 36.1595 -  *
 36.1596 -- *	We block accesses to device mc filters with dev->xmit_lock.
 36.1597 -+ *	We block accesses to device mc filters with netif_tx_lock.
 36.1598 -  */
 36.1599 - 
 36.1600 - /*
 36.1601 -@@ -93,9 +93,9 @@ static void __dev_mc_upload(struct net_d
 36.1602 - 
 36.1603 - void dev_mc_upload(struct net_device *dev)
 36.1604 - {
 36.1605 --	spin_lock_bh(&dev->xmit_lock);
 36.1606 -+	netif_tx_lock_bh(dev);
 36.1607 - 	__dev_mc_upload(dev);
 36.1608 --	spin_unlock_bh(&dev->xmit_lock);
 36.1609 -+	netif_tx_unlock_bh(dev);
 36.1610 - }
 36.1611 - 
 36.1612 - /*
 36.1613 -@@ -107,7 +107,7 @@ int dev_mc_delete(struct net_device *dev
 36.1614 - 	int err = 0;
 36.1615 - 	struct dev_mc_list *dmi, **dmip;
 36.1616 - 
 36.1617 --	spin_lock_bh(&dev->xmit_lock);
 36.1618 -+	netif_tx_lock_bh(dev);
 36.1619 - 
 36.1620 - 	for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
 36.1621 - 		/*
 36.1622 -@@ -139,13 +139,13 @@ int dev_mc_delete(struct net_device *dev
 36.1623 - 			 */
 36.1624 - 			__dev_mc_upload(dev);
 36.1625 - 			
 36.1626 --			spin_unlock_bh(&dev->xmit_lock);
 36.1627 -+			netif_tx_unlock_bh(dev);
 36.1628 - 			return 0;
 36.1629 - 		}
 36.1630 - 	}
 36.1631 - 	err = -ENOENT;
 36.1632 - done:
 36.1633 --	spin_unlock_bh(&dev->xmit_lock);
 36.1634 -+	netif_tx_unlock_bh(dev);
 36.1635 - 	return err;
 36.1636 - }
 36.1637 - 
 36.1638 -@@ -160,7 +160,7 @@ int dev_mc_add(struct net_device *dev, v
 36.1639 - 
 36.1640 - 	dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
 36.1641 - 
 36.1642 --	spin_lock_bh(&dev->xmit_lock);
 36.1643 -+	netif_tx_lock_bh(dev);
 36.1644 - 	for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
 36.1645 - 		if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
 36.1646 - 		    dmi->dmi_addrlen == alen) {
 36.1647 -@@ -176,7 +176,7 @@ int dev_mc_add(struct net_device *dev, v
 36.1648 - 	}
 36.1649 - 
 36.1650 - 	if ((dmi = dmi1) == NULL) {
 36.1651 --		spin_unlock_bh(&dev->xmit_lock);
 36.1652 -+		netif_tx_unlock_bh(dev);
 36.1653 - 		return -ENOMEM;
 36.1654 - 	}
 36.1655 - 	memcpy(dmi->dmi_addr, addr, alen);
 36.1656 -@@ -189,11 +189,11 @@ int dev_mc_add(struct net_device *dev, v
 36.1657 - 
 36.1658 - 	__dev_mc_upload(dev);
 36.1659 - 	
 36.1660 --	spin_unlock_bh(&dev->xmit_lock);
 36.1661 -+	netif_tx_unlock_bh(dev);
 36.1662 - 	return 0;
 36.1663 - 
 36.1664 - done:
 36.1665 --	spin_unlock_bh(&dev->xmit_lock);
 36.1666 -+	netif_tx_unlock_bh(dev);
 36.1667 - 	kfree(dmi1);
 36.1668 - 	return err;
 36.1669 - }
 36.1670 -@@ -204,7 +204,7 @@ done:
 36.1671 - 
 36.1672 - void dev_mc_discard(struct net_device *dev)
 36.1673 - {
 36.1674 --	spin_lock_bh(&dev->xmit_lock);
 36.1675 -+	netif_tx_lock_bh(dev);
 36.1676 - 	
 36.1677 - 	while (dev->mc_list != NULL) {
 36.1678 - 		struct dev_mc_list *tmp = dev->mc_list;
 36.1679 -@@ -215,7 +215,7 @@ void dev_mc_discard(struct net_device *d
 36.1680 - 	}
 36.1681 - 	dev->mc_count = 0;
 36.1682 - 
 36.1683 --	spin_unlock_bh(&dev->xmit_lock);
 36.1684 -+	netif_tx_unlock_bh(dev);
 36.1685 - }
 36.1686 - 
 36.1687 - #ifdef CONFIG_PROC_FS
 36.1688 -@@ -250,7 +250,7 @@ static int dev_mc_seq_show(struct seq_fi
 36.1689 - 	struct dev_mc_list *m;
 36.1690 - 	struct net_device *dev = v;
 36.1691 - 
 36.1692 --	spin_lock_bh(&dev->xmit_lock);
 36.1693 -+	netif_tx_lock_bh(dev);
 36.1694 - 	for (m = dev->mc_list; m; m = m->next) {
 36.1695 - 		int i;
 36.1696 - 
 36.1697 -@@ -262,7 +262,7 @@ static int dev_mc_seq_show(struct seq_fi
 36.1698 - 
 36.1699 - 		seq_putc(seq, '\n');
 36.1700 - 	}
 36.1701 --	spin_unlock_bh(&dev->xmit_lock);
 36.1702 -+	netif_tx_unlock_bh(dev);
 36.1703 - 	return 0;
 36.1704 - }
 36.1705 - 
 36.1706 -diff --git a/net/core/ethtool.c b/net/core/ethtool.c
 36.1707 -index e6f7610..27ce168 100644
 36.1708 ---- a/net/core/ethtool.c
 36.1709 -+++ b/net/core/ethtool.c
 36.1710 -@@ -30,7 +30,7 @@ u32 ethtool_op_get_link(struct net_devic
 36.1711 - 
 36.1712 - u32 ethtool_op_get_tx_csum(struct net_device *dev)
 36.1713 - {
 36.1714 --	return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
 36.1715 -+	return (dev->features & NETIF_F_ALL_CSUM) != 0;
 36.1716 - }
 36.1717 - 
 36.1718 - int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 36.1719 -@@ -551,9 +551,7 @@ static int ethtool_set_sg(struct net_dev
 36.1720 - 		return -EFAULT;
 36.1721 - 
 36.1722 - 	if (edata.data && 
 36.1723 --	    !(dev->features & (NETIF_F_IP_CSUM |
 36.1724 --			       NETIF_F_NO_CSUM |
 36.1725 --			       NETIF_F_HW_CSUM)))
 36.1726 -+	    !(dev->features & NETIF_F_ALL_CSUM))
 36.1727 - 		return -EINVAL;
 36.1728 - 
 36.1729 - 	return __ethtool_set_sg(dev, edata.data);
 36.1730 -@@ -591,7 +589,7 @@ static int ethtool_set_tso(struct net_de
 36.1731 - 
 36.1732 - static int ethtool_get_ufo(struct net_device *dev, char __user *useraddr)
 36.1733 - {
 36.1734 --	struct ethtool_value edata = { ETHTOOL_GTSO };
 36.1735 -+	struct ethtool_value edata = { ETHTOOL_GUFO };
 36.1736 - 
 36.1737 - 	if (!dev->ethtool_ops->get_ufo)
 36.1738 - 		return -EOPNOTSUPP;
 36.1739 -@@ -600,6 +598,7 @@ static int ethtool_get_ufo(struct net_de
 36.1740 - 		 return -EFAULT;
 36.1741 - 	return 0;
 36.1742 - }
 36.1743 -+
 36.1744 - static int ethtool_set_ufo(struct net_device *dev, char __user *useraddr)
 36.1745 - {
 36.1746 - 	struct ethtool_value edata;
 36.1747 -@@ -615,6 +614,29 @@ static int ethtool_set_ufo(struct net_de
 36.1748 - 	return dev->ethtool_ops->set_ufo(dev, edata.data);
 36.1749 - }
 36.1750 - 
 36.1751 -+static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
 36.1752 -+{
 36.1753 -+	struct ethtool_value edata = { ETHTOOL_GGSO };
 36.1754 -+
 36.1755 -+	edata.data = dev->features & NETIF_F_GSO;
 36.1756 -+	if (copy_to_user(useraddr, &edata, sizeof(edata)))
 36.1757 -+		 return -EFAULT;
 36.1758 -+	return 0;
 36.1759 -+}
 36.1760 -+
 36.1761 -+static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
 36.1762 -+{
 36.1763 -+	struct ethtool_value edata;
 36.1764 -+
 36.1765 -+	if (copy_from_user(&edata, useraddr, sizeof(edata)))
 36.1766 -+		return -EFAULT;
 36.1767 -+	if (edata.data)
 36.1768 -+		dev->features |= NETIF_F_GSO;
 36.1769 -+	else
 36.1770 -+		dev->features &= ~NETIF_F_GSO;
 36.1771 -+	return 0;
 36.1772 -+}
 36.1773 -+
 36.1774 - static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
 36.1775 - {
 36.1776 - 	struct ethtool_test test;
 36.1777 -@@ -906,6 +928,12 @@ int dev_ethtool(struct ifreq *ifr)
 36.1778 - 	case ETHTOOL_SUFO:
 36.1779 - 		rc = ethtool_set_ufo(dev, useraddr);
 36.1780 - 		break;
 36.1781 -+	case ETHTOOL_GGSO:
 36.1782 -+		rc = ethtool_get_gso(dev, useraddr);
 36.1783 -+		break;
 36.1784 -+	case ETHTOOL_SGSO:
 36.1785 -+		rc = ethtool_set_gso(dev, useraddr);
 36.1786 -+		break;
 36.1787 - 	default:
 36.1788 - 		rc =  -EOPNOTSUPP;
 36.1789 - 	}
 36.1790 -diff --git a/net/core/netpoll.c b/net/core/netpoll.c
 36.1791 -index ea51f8d..ec28d3b 100644
 36.1792 ---- a/net/core/netpoll.c
 36.1793 -+++ b/net/core/netpoll.c
 36.1794 -@@ -273,24 +273,21 @@ static void netpoll_send_skb(struct netp
 36.1795 - 
 36.1796 - 	do {
 36.1797 - 		npinfo->tries--;
 36.1798 --		spin_lock(&np->dev->xmit_lock);
 36.1799 --		np->dev->xmit_lock_owner = smp_processor_id();
 36.1800 -+		netif_tx_lock(np->dev);
 36.1801 - 
 36.1802 - 		/*
 36.1803 - 		 * network drivers do not expect to be called if the queue is
 36.1804 - 		 * stopped.
 36.1805 - 		 */
 36.1806 - 		if (netif_queue_stopped(np->dev)) {
 36.1807 --			np->dev->xmit_lock_owner = -1;
 36.1808 --			spin_unlock(&np->dev->xmit_lock);
 36.1809 -+			netif_tx_unlock(np->dev);
 36.1810 - 			netpoll_poll(np);
 36.1811 - 			udelay(50);
 36.1812 - 			continue;
 36.1813 - 		}
 36.1814 - 
 36.1815 - 		status = np->dev->hard_start_xmit(skb, np->dev);
 36.1816 --		np->dev->xmit_lock_owner = -1;
 36.1817 --		spin_unlock(&np->dev->xmit_lock);
 36.1818 -+		netif_tx_unlock(np->dev);
 36.1819 - 
 36.1820 - 		/* success */
 36.1821 - 		if(!status) {
 36.1822 -diff --git a/net/core/pktgen.c b/net/core/pktgen.c
 36.1823 -index da16f8f..2380347 100644
 36.1824 ---- a/net/core/pktgen.c
 36.1825 -+++ b/net/core/pktgen.c
 36.1826 -@@ -2582,7 +2582,7 @@ static __inline__ void pktgen_xmit(struc
 36.1827 - 		}
 36.1828 - 	}
 36.1829 - 	
 36.1830 --	spin_lock_bh(&odev->xmit_lock);
 36.1831 -+	netif_tx_lock_bh(odev);
 36.1832 - 	if (!netif_queue_stopped(odev)) {
 36.1833 - 
 36.1834 - 		atomic_inc(&(pkt_dev->skb->users));
 36.1835 -@@ -2627,7 +2627,7 @@ retry_now:
 36.1836 - 		pkt_dev->next_tx_ns = 0;
 36.1837 -         }
 36.1838 - 
 36.1839 --	spin_unlock_bh(&odev->xmit_lock);
 36.1840 -+	netif_tx_unlock_bh(odev);
 36.1841 - 	
 36.1842 - 	/* If pkt_dev->count is zero, then run forever */
 36.1843 - 	if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
 36.1844 -diff --git a/net/core/skbuff.c b/net/core/skbuff.c
 36.1845 -index 2144952..46f56af 100644
 36.1846 ---- a/net/core/skbuff.c
 36.1847 -+++ b/net/core/skbuff.c
 36.1848 -@@ -164,9 +164,9 @@ struct sk_buff *__alloc_skb(unsigned int
 36.1849 - 	shinfo = skb_shinfo(skb);
 36.1850 - 	atomic_set(&shinfo->dataref, 1);
 36.1851 - 	shinfo->nr_frags  = 0;
 36.1852 --	shinfo->tso_size = 0;
 36.1853 --	shinfo->tso_segs = 0;
 36.1854 --	shinfo->ufo_size = 0;
 36.1855 -+	shinfo->gso_size = 0;
 36.1856 -+	shinfo->gso_segs = 0;
 36.1857 -+	shinfo->gso_type = 0;
 36.1858 - 	shinfo->ip6_frag_id = 0;
 36.1859 - 	shinfo->frag_list = NULL;
 36.1860 - 
 36.1861 -@@ -230,8 +230,9 @@ struct sk_buff *alloc_skb_from_cache(kme
 36.1862 - 
 36.1863 - 	atomic_set(&(skb_shinfo(skb)->dataref), 1);
 36.1864 - 	skb_shinfo(skb)->nr_frags  = 0;
 36.1865 --	skb_shinfo(skb)->tso_size = 0;
 36.1866 --	skb_shinfo(skb)->tso_segs = 0;
 36.1867 -+	skb_shinfo(skb)->gso_size = 0;
 36.1868 -+	skb_shinfo(skb)->gso_segs = 0;
 36.1869 -+	skb_shinfo(skb)->gso_type = 0;
 36.1870 - 	skb_shinfo(skb)->frag_list = NULL;
 36.1871 - out:
 36.1872 - 	return skb;
 36.1873 -@@ -501,8 +502,9 @@ #endif
 36.1874 - 	new->tc_index	= old->tc_index;
 36.1875 - #endif
 36.1876 - 	atomic_set(&new->users, 1);
 36.1877 --	skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size;
 36.1878 --	skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs;
 36.1879 -+	skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
 36.1880 -+	skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
 36.1881 -+	skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
 36.1882 - }
 36.1883 - 
 36.1884 - /**
 36.1885 -@@ -1777,6 +1779,133 @@ int skb_append_datato_frags(struct sock 
 36.1886 - 	return 0;
 36.1887 - }
 36.1888 - 
 36.1889 -+/**
 36.1890 -+ *	skb_segment - Perform protocol segmentation on skb.
 36.1891 -+ *	@skb: buffer to segment
 36.1892 -+ *	@features: features for the output path (see dev->features)
 36.1893 -+ *
 36.1894 -+ *	This function performs segmentation on the given skb.  It returns
 36.1895 -+ *	the segment at the given position.  It returns NULL if there are
 36.1896 -+ *	no more segments to generate, or when an error is encountered.
 36.1897 -+ */
 36.1898 -+struct sk_buff *skb_segment(struct sk_buff *skb, int features)
 36.1899 -+{
 36.1900 -+	struct sk_buff *segs = NULL;
 36.1901 -+	struct sk_buff *tail = NULL;
 36.1902 -+	unsigned int mss = skb_shinfo(skb)->gso_size;
 36.1903 -+	unsigned int doffset = skb->data - skb->mac.raw;
 36.1904 -+	unsigned int offset = doffset;
 36.1905 -+	unsigned int headroom;
 36.1906 -+	unsigned int len;
 36.1907 -+	int sg = features & NETIF_F_SG;
 36.1908 -+	int nfrags = skb_shinfo(skb)->nr_frags;
 36.1909 -+	int err = -ENOMEM;
 36.1910 -+	int i = 0;
 36.1911 -+	int pos;
 36.1912 -+
 36.1913 -+	__skb_push(skb, doffset);
 36.1914 -+	headroom = skb_headroom(skb);
 36.1915 -+	pos = skb_headlen(skb);
 36.1916 -+
 36.1917 -+	do {
 36.1918 -+		struct sk_buff *nskb;
 36.1919 -+		skb_frag_t *frag;
 36.1920 -+		int hsize, nsize;
 36.1921 -+		int k;
 36.1922 -+		int size;
 36.1923 -+
 36.1924 -+		len = skb->len - offset;
 36.1925 -+		if (len > mss)
 36.1926 -+			len = mss;
 36.1927 -+
 36.1928 -+		hsize = skb_headlen(skb) - offset;
 36.1929 -+		if (hsize < 0)
 36.1930 -+			hsize = 0;
 36.1931 -+		nsize = hsize + doffset;
 36.1932 -+		if (nsize > len + doffset || !sg)
 36.1933 -+			nsize = len + doffset;
 36.1934 -+
 36.1935 -+		nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
 36.1936 -+		if (unlikely(!nskb))
 36.1937 -+			goto err;
 36.1938 -+
 36.1939 -+		if (segs)
 36.1940 -+			tail->next = nskb;
 36.1941 -+		else
 36.1942 -+			segs = nskb;
 36.1943 -+		tail = nskb;
 36.1944 -+
 36.1945 -+		nskb->dev = skb->dev;
 36.1946 -+		nskb->priority = skb->priority;
 36.1947 -+		nskb->protocol = skb->protocol;
 36.1948 -+		nskb->dst = dst_clone(skb->dst);
 36.1949 -+		memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
 36.1950 -+		nskb->pkt_type = skb->pkt_type;
 36.1951 -+		nskb->mac_len = skb->mac_len;
 36.1952 -+
 36.1953 -+		skb_reserve(nskb, headroom);
 36.1954 -+		nskb->mac.raw = nskb->data;
 36.1955 -+		nskb->nh.raw = nskb->data + skb->mac_len;
 36.1956 -+		nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw);
 36.1957 -+		memcpy(skb_put(nskb, doffset), skb->data, doffset);
 36.1958 -+
 36.1959 -+		if (!sg) {
 36.1960 -+			nskb->csum = skb_copy_and_csum_bits(skb, offset,
 36.1961 -+							    skb_put(nskb, len),
 36.1962 -+							    len, 0);
 36.1963 -+			continue;
 36.1964 -+		}
 36.1965 -+
 36.1966 -+		frag = skb_shinfo(nskb)->frags;
 36.1967 -+		k = 0;
 36.1968 -+
 36.1969 -+		nskb->ip_summed = CHECKSUM_HW;
 36.1970 -+		nskb->csum = skb->csum;
 36.1971 -+		memcpy(skb_put(nskb, hsize), skb->data + offset, hsize);
 36.1972 -+
 36.1973 -+		while (pos < offset + len) {
 36.1974 -+			BUG_ON(i >= nfrags);
 36.1975 -+
 36.1976 -+			*frag = skb_shinfo(skb)->frags[i];
 36.1977 -+			get_page(frag->page);
 36.1978 -+			size = frag->size;
 36.1979 -+
 36.1980 -+			if (pos < offset) {
 36.1981 -+				frag->page_offset += offset - pos;
 36.1982 -+				frag->size -= offset - pos;
 36.1983 -+			}
 36.1984 -+
 36.1985 -+			k++;
 36.1986 -+
 36.1987 -+			if (pos + size <= offset + len) {
 36.1988 -+				i++;
 36.1989 -+				pos += size;
 36.1990 -+			} else {
 36.1991 -+				frag->size -= pos + size - (offset + len);
 36.1992 -+				break;
 36.1993 -+			}
 36.1994 -+
 36.1995 -+			frag++;
 36.1996 -+		}
 36.1997 -+
 36.1998 -+		skb_shinfo(nskb)->nr_frags = k;
 36.1999 -+		nskb->data_len = len - hsize;
 36.2000 -+		nskb->len += nskb->data_len;
 36.2001 -+		nskb->truesize += nskb->data_len;
 36.2002 -+	} while ((offset += len) < skb->len);
 36.2003 -+
 36.2004 -+	return segs;
 36.2005 -+
 36.2006 -+err:
 36.2007 -+	while ((skb = segs)) {
 36.2008 -+		segs = skb->next;
 36.2009 -+		kfree(skb);
 36.2010 -+	}
 36.2011 -+	return ERR_PTR(err);
 36.2012 -+}
 36.2013 -+
 36.2014 -+EXPORT_SYMBOL_GPL(skb_segment);
 36.2015 -+
 36.2016 - void __init skb_init(void)
 36.2017 - {
 36.2018 - 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
 36.2019 -diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
 36.2020 -index 44bda85..2e3323a 100644
 36.2021 ---- a/net/decnet/dn_nsp_in.c
 36.2022 -+++ b/net/decnet/dn_nsp_in.c
 36.2023 -@@ -801,8 +801,7 @@ got_it:
 36.2024 - 		 * We linearize everything except data segments here.
 36.2025 - 		 */
 36.2026 - 		if (cb->nsp_flags & ~0x60) {
 36.2027 --			if (unlikely(skb_is_nonlinear(skb)) &&
 36.2028 --			    skb_linearize(skb, GFP_ATOMIC) != 0)
 36.2029 -+			if (unlikely(skb_linearize(skb)))
 36.2030 - 				goto free_out;
 36.2031 - 		}
 36.2032 - 
 36.2033 -diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
 36.2034 -index 3407f19..a0a25e0 100644
 36.2035 ---- a/net/decnet/dn_route.c
 36.2036 -+++ b/net/decnet/dn_route.c
 36.2037 -@@ -629,8 +629,7 @@ int dn_route_rcv(struct sk_buff *skb, st
 36.2038 - 			padlen);
 36.2039 - 
 36.2040 -         if (flags & DN_RT_PKT_CNTL) {
 36.2041 --		if (unlikely(skb_is_nonlinear(skb)) &&
 36.2042 --		    skb_linearize(skb, GFP_ATOMIC) != 0)
 36.2043 -+		if (unlikely(skb_linearize(skb)))
 36.2044 - 			goto dump_it;
 36.2045 - 
 36.2046 -                 switch(flags & DN_RT_CNTL_MSK) {
 36.2047 -diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
 36.2048 -index 97c276f..5ba719e 100644
 36.2049 ---- a/net/ipv4/af_inet.c
 36.2050 -+++ b/net/ipv4/af_inet.c
 36.2051 -@@ -68,6 +68,7 @@
 36.2052 -  */
 36.2053 - 
 36.2054 - #include <linux/config.h>
 36.2055 -+#include <linux/err.h>
 36.2056 - #include <linux/errno.h>
 36.2057 - #include <linux/types.h>
 36.2058 - #include <linux/socket.h>
 36.2059 -@@ -1084,6 +1085,54 @@ int inet_sk_rebuild_header(struct sock *
 36.2060 - 
 36.2061 - EXPORT_SYMBOL(inet_sk_rebuild_header);
 36.2062 - 
 36.2063 -+static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 36.2064 -+{
 36.2065 -+	struct sk_buff *segs = ERR_PTR(-EINVAL);
 36.2066 -+	struct iphdr *iph;
 36.2067 -+	struct net_protocol *ops;
 36.2068 -+	int proto;
 36.2069 -+	int ihl;
 36.2070 -+	int id;
 36.2071 -+
 36.2072 -+	if (!pskb_may_pull(skb, sizeof(*iph)))
 36.2073 -+		goto out;
 36.2074 -+
 36.2075 -+	iph = skb->nh.iph;
 36.2076 -+	ihl = iph->ihl * 4;
 36.2077 -+	if (ihl < sizeof(*iph))
 36.2078 -+		goto out;
 36.2079 -+
 36.2080 -+	if (!pskb_may_pull(skb, ihl))
 36.2081 -+		goto out;
 36.2082 -+
 36.2083 -+	skb->h.raw = __skb_pull(skb, ihl);
 36.2084 -+	iph = skb->nh.iph;
 36.2085 -+	id = ntohs(iph->id);
 36.2086 -+	proto = iph->protocol & (MAX_INET_PROTOS - 1);
 36.2087 -+	segs = ERR_PTR(-EPROTONOSUPPORT);
 36.2088 -+
 36.2089 -+	rcu_read_lock();
 36.2090 -+	ops = rcu_dereference(inet_protos[proto]);
 36.2091 -+	if (ops && ops->gso_segment)
 36.2092 -+		segs = ops->gso_segment(skb, features);
 36.2093 -+	rcu_read_unlock();
 36.2094 -+
 36.2095 -+	if (!segs || unlikely(IS_ERR(segs)))
 36.2096 -+		goto out;
 36.2097 -+
 36.2098 -+	skb = segs;
 36.2099 -+	do {
 36.2100 -+		iph = skb->nh.iph;
 36.2101 -+		iph->id = htons(id++);
 36.2102 -+		iph->tot_len = htons(skb->len - skb->mac_len);
 36.2103 -+		iph->check = 0;
 36.2104 -+		iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
 36.2105 -+	} while ((skb = skb->next));
 36.2106 -+
 36.2107 -+out:
 36.2108 -+	return segs;
 36.2109 -+}
 36.2110 -+
 36.2111 - #ifdef CONFIG_IP_MULTICAST
 36.2112 - static struct net_protocol igmp_protocol = {
 36.2113 - 	.handler =	igmp_rcv,
 36.2114 -@@ -1093,6 +1142,7 @@ #endif
 36.2115 - static struct net_protocol tcp_protocol = {
 36.2116 - 	.handler =	tcp_v4_rcv,
 36.2117 - 	.err_handler =	tcp_v4_err,
 36.2118 -+	.gso_segment =	tcp_tso_segment,
 36.2119 - 	.no_policy =	1,
 36.2120 - };
 36.2121 - 
 36.2122 -@@ -1138,6 +1188,7 @@ static int ipv4_proc_init(void);
 36.2123 - static struct packet_type ip_packet_type = {
 36.2124 - 	.type = __constant_htons(ETH_P_IP),
 36.2125 - 	.func = ip_rcv,
 36.2126 -+	.gso_segment = inet_gso_segment,
 36.2127 - };
 36.2128 - 
 36.2129 - static int __init inet_init(void)
 36.2130 -diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
 36.2131 -index 8dcba38..19c3c73 100644
 36.2132 ---- a/net/ipv4/ip_output.c
 36.2133 -+++ b/net/ipv4/ip_output.c
 36.2134 -@@ -210,8 +210,7 @@ #if defined(CONFIG_NETFILTER) && defined
 36.2135 - 		return dst_output(skb);
 36.2136 - 	}
 36.2137 - #endif
 36.2138 --	if (skb->len > dst_mtu(skb->dst) &&
 36.2139 --	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
 36.2140 -+	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
 36.2141 - 		return ip_fragment(skb, ip_finish_output2);
 36.2142 - 	else
 36.2143 - 		return ip_finish_output2(skb);
 36.2144 -@@ -362,7 +361,7 @@ packet_routed:
 36.2145 - 	}
 36.2146 - 
 36.2147 - 	ip_select_ident_more(iph, &rt->u.dst, sk,
 36.2148 --			     (skb_shinfo(skb)->tso_segs ?: 1) - 1);
 36.2149 -+			     (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 36.2150 - 
 36.2151 - 	/* Add an IP checksum. */
 36.2152 - 	ip_send_check(iph);
 36.2153 -@@ -743,7 +742,8 @@ static inline int ip_ufo_append_data(str
 36.2154 - 			       (length - transhdrlen));
 36.2155 - 	if (!err) {
 36.2156 - 		/* specify the length of each IP datagram fragment*/
 36.2157 --		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
 36.2158 -+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
 36.2159 -+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 36.2160 - 		__skb_queue_tail(&sk->sk_write_queue, skb);
 36.2161 - 
 36.2162 - 		return 0;
 36.2163 -@@ -839,7 +839,7 @@ int ip_append_data(struct sock *sk,
 36.2164 - 	 */
 36.2165 - 	if (transhdrlen &&
 36.2166 - 	    length + fragheaderlen <= mtu &&
 36.2167 --	    rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
 36.2168 -+	    rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
 36.2169 - 	    !exthdrlen)
 36.2170 - 		csummode = CHECKSUM_HW;
 36.2171 - 
 36.2172 -@@ -1086,14 +1086,16 @@ ssize_t	ip_append_page(struct sock *sk, 
 36.2173 - 
 36.2174 - 	inet->cork.length += size;
 36.2175 - 	if ((sk->sk_protocol == IPPROTO_UDP) &&
 36.2176 --	    (rt->u.dst.dev->features & NETIF_F_UFO))
 36.2177 --		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
 36.2178 -+	    (rt->u.dst.dev->features & NETIF_F_UFO)) {
 36.2179 -+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
 36.2180 -+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 36.2181 -+	}
 36.2182 - 
 36.2183 - 
 36.2184 - 	while (size > 0) {
 36.2185 - 		int i;
 36.2186 - 
 36.2187 --		if (skb_shinfo(skb)->ufo_size)
 36.2188 -+		if (skb_shinfo(skb)->gso_size)
 36.2189 - 			len = size;
 36.2190 - 		else {
 36.2191 - 
 36.2192 -diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
 36.2193 -index d64e2ec..7494823 100644
 36.2194 ---- a/net/ipv4/ipcomp.c
 36.2195 -+++ b/net/ipv4/ipcomp.c
 36.2196 -@@ -84,7 +84,7 @@ static int ipcomp_input(struct xfrm_stat
 36.2197 -                         struct xfrm_decap_state *decap, struct sk_buff *skb)
 36.2198 - {
 36.2199 - 	u8 nexthdr;
 36.2200 --	int err = 0;
 36.2201 -+	int err = -ENOMEM;
 36.2202 - 	struct iphdr *iph;
 36.2203 - 	union {
 36.2204 - 		struct iphdr	iph;
 36.2205 -@@ -92,11 +92,8 @@ static int ipcomp_input(struct xfrm_stat
 36.2206 - 	} tmp_iph;
 36.2207 - 
 36.2208 - 
 36.2209 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 36.2210 --	    skb_linearize(skb, GFP_ATOMIC) != 0) {
 36.2211 --	    	err = -ENOMEM;
 36.2212 -+	if (skb_linearize_cow(skb))
 36.2213 - 	    	goto out;
 36.2214 --	}
 36.2215 - 
 36.2216 - 	skb->ip_summed = CHECKSUM_NONE;
 36.2217 - 
 36.2218 -@@ -171,10 +168,8 @@ static int ipcomp_output(struct xfrm_sta
 36.2219 - 		goto out_ok;
 36.2220 - 	}
 36.2221 - 
 36.2222 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 36.2223 --	    skb_linearize(skb, GFP_ATOMIC) != 0) {
 36.2224 -+	if (skb_linearize_cow(skb))
 36.2225 - 		goto out_ok;
 36.2226 --	}
 36.2227 - 	
 36.2228 - 	err = ipcomp_compress(x, skb);
 36.2229 - 	iph = skb->nh.iph;
 36.2230 -diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
 36.2231 -index 00aa80e..84130c9 100644
 36.2232 ---- a/net/ipv4/tcp.c
 36.2233 -+++ b/net/ipv4/tcp.c
 36.2234 -@@ -257,6 +257,7 @@ #include <linux/smp_lock.h>
 36.2235 - #include <linux/fs.h>
 36.2236 - #include <linux/random.h>
 36.2237 - #include <linux/bootmem.h>
 36.2238 -+#include <linux/err.h>
 36.2239 - 
 36.2240 - #include <net/icmp.h>
 36.2241 - #include <net/tcp.h>
 36.2242 -@@ -570,7 +571,7 @@ new_segment:
 36.2243 - 		skb->ip_summed = CHECKSUM_HW;
 36.2244 - 		tp->write_seq += copy;
 36.2245 - 		TCP_SKB_CB(skb)->end_seq += copy;
 36.2246 --		skb_shinfo(skb)->tso_segs = 0;
 36.2247 -+		skb_shinfo(skb)->gso_segs = 0;
 36.2248 - 
 36.2249 - 		if (!copied)
 36.2250 - 			TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
 36.2251 -@@ -621,14 +622,10 @@ ssize_t tcp_sendpage(struct socket *sock
 36.2252 - 	ssize_t res;
 36.2253 - 	struct sock *sk = sock->sk;
 36.2254 - 
 36.2255 --#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
 36.2256 --
 36.2257 - 	if (!(sk->sk_route_caps & NETIF_F_SG) ||
 36.2258 --	    !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS))
 36.2259 -+	    !(sk->sk_route_caps & NETIF_F_ALL_CSUM))
 36.2260 - 		return sock_no_sendpage(sock, page, offset, size, flags);
 36.2261 - 
 36.2262 --#undef TCP_ZC_CSUM_FLAGS
 36.2263 --
 36.2264 - 	lock_sock(sk);
 36.2265 - 	TCP_CHECK_TIMER(sk);
 36.2266 - 	res = do_tcp_sendpages(sk, &page, offset, size, flags);
 36.2267 -@@ -725,9 +722,7 @@ new_segment:
 36.2268 - 				/*
 36.2269 - 				 * Check whether we can use HW checksum.
 36.2270 - 				 */
 36.2271 --				if (sk->sk_route_caps &
 36.2272 --				    (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |
 36.2273 --				     NETIF_F_HW_CSUM))
 36.2274 -+				if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
 36.2275 - 					skb->ip_summed = CHECKSUM_HW;
 36.2276 - 
 36.2277 - 				skb_entail(sk, tp, skb);
 36.2278 -@@ -823,7 +818,7 @@ new_segment:
 36.2279 - 
 36.2280 - 			tp->write_seq += copy;
 36.2281 - 			TCP_SKB_CB(skb)->end_seq += copy;
 36.2282 --			skb_shinfo(skb)->tso_segs = 0;
 36.2283 -+			skb_shinfo(skb)->gso_segs = 0;
 36.2284 - 
 36.2285 - 			from += copy;
 36.2286 - 			copied += copy;
 36.2287 -@@ -2026,6 +2021,71 @@ int tcp_getsockopt(struct sock *sk, int 
 36.2288 - }
 36.2289 - 
 36.2290 - 
 36.2291 -+struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 36.2292 -+{
 36.2293 -+	struct sk_buff *segs = ERR_PTR(-EINVAL);
 36.2294 -+	struct tcphdr *th;
 36.2295 -+	unsigned thlen;
 36.2296 -+	unsigned int seq;
 36.2297 -+	unsigned int delta;
 36.2298 -+	unsigned int oldlen;
 36.2299 -+	unsigned int len;
 36.2300 -+
 36.2301 -+	if (!pskb_may_pull(skb, sizeof(*th)))
 36.2302 -+		goto out;
 36.2303 -+
 36.2304 -+	th = skb->h.th;
 36.2305 -+	thlen = th->doff * 4;
 36.2306 -+	if (thlen < sizeof(*th))
 36.2307 -+		goto out;
 36.2308 -+
 36.2309 -+	if (!pskb_may_pull(skb, thlen))
 36.2310 -+		goto out;
 36.2311 -+
 36.2312 -+	segs = NULL;
 36.2313 -+	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
 36.2314 -+		goto out;
 36.2315 -+
 36.2316 -+	oldlen = (u16)~skb->len;
 36.2317 -+	__skb_pull(skb, thlen);
 36.2318 -+
 36.2319 -+	segs = skb_segment(skb, features);
 36.2320 -+	if (IS_ERR(segs))
 36.2321 -+		goto out;
 36.2322 -+
 36.2323 -+	len = skb_shinfo(skb)->gso_size;
 36.2324 -+	delta = htonl(oldlen + (thlen + len));
 36.2325 -+
 36.2326 -+	skb = segs;
 36.2327 -+	th = skb->h.th;
 36.2328 -+	seq = ntohl(th->seq);
 36.2329 -+
 36.2330 -+	do {
 36.2331 -+		th->fin = th->psh = 0;
 36.2332 -+
 36.2333 -+		th->check = ~csum_fold(th->check + delta);
 36.2334 -+		if (skb->ip_summed != CHECKSUM_HW)
 36.2335 -+			th->check = csum_fold(csum_partial(skb->h.raw, thlen,
 36.2336 -+							   skb->csum));
 36.2337 -+
 36.2338 -+		seq += len;
 36.2339 -+		skb = skb->next;
 36.2340 -+		th = skb->h.th;
 36.2341 -+
 36.2342 -+		th->seq = htonl(seq);
 36.2343 -+		th->cwr = 0;
 36.2344 -+	} while (skb->next);
 36.2345 -+
 36.2346 -+	delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
 36.2347 -+	th->check = ~csum_fold(th->check + delta);
 36.2348 -+	if (skb->ip_summed != CHECKSUM_HW)
 36.2349 -+		th->check = csum_fold(csum_partial(skb->h.raw, thlen,
 36.2350 -+						   skb->csum));
 36.2351 -+
 36.2352 -+out:
 36.2353 -+	return segs;
 36.2354 -+}
 36.2355 -+
 36.2356 - extern void __skb_cb_too_small_for_tcp(int, int);
 36.2357 - extern struct tcp_congestion_ops tcp_reno;
 36.2358 - 
 36.2359 -diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
 36.2360 -index e9a54ae..defe77a 100644
 36.2361 ---- a/net/ipv4/tcp_input.c
 36.2362 -+++ b/net/ipv4/tcp_input.c
 36.2363 -@@ -1072,7 +1072,7 @@ tcp_sacktag_write_queue(struct sock *sk,
 36.2364 - 				else
 36.2365 - 					pkt_len = (end_seq -
 36.2366 - 						   TCP_SKB_CB(skb)->seq);
 36.2367 --				if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->tso_size))
 36.2368 -+				if (tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size))
 36.2369 - 					break;
 36.2370 - 				pcount = tcp_skb_pcount(skb);
 36.2371 - 			}
 36.2372 -diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
 36.2373 -index 310f2e6..ee01f69 100644
 36.2374 ---- a/net/ipv4/tcp_output.c
 36.2375 -+++ b/net/ipv4/tcp_output.c
 36.2376 -@@ -497,15 +497,17 @@ static void tcp_set_skb_tso_segs(struct 
 36.2377 - 		/* Avoid the costly divide in the normal
 36.2378 - 		 * non-TSO case.
 36.2379 - 		 */
 36.2380 --		skb_shinfo(skb)->tso_segs = 1;
 36.2381 --		skb_shinfo(skb)->tso_size = 0;
 36.2382 -+		skb_shinfo(skb)->gso_segs = 1;
 36.2383 -+		skb_shinfo(skb)->gso_size = 0;
 36.2384 -+		skb_shinfo(skb)->gso_type = 0;
 36.2385 - 	} else {
 36.2386 - 		unsigned int factor;
 36.2387 - 
 36.2388 - 		factor = skb->len + (mss_now - 1);
 36.2389 - 		factor /= mss_now;
 36.2390 --		skb_shinfo(skb)->tso_segs = factor;
 36.2391 --		skb_shinfo(skb)->tso_size = mss_now;
 36.2392 -+		skb_shinfo(skb)->gso_segs = factor;
 36.2393 -+		skb_shinfo(skb)->gso_size = mss_now;
 36.2394 -+		skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
 36.2395 - 	}
 36.2396 - }
 36.2397 - 
 36.2398 -@@ -850,7 +852,7 @@ static int tcp_init_tso_segs(struct sock
 36.2399 - 
 36.2400 - 	if (!tso_segs ||
 36.2401 - 	    (tso_segs > 1 &&
 36.2402 --	     skb_shinfo(skb)->tso_size != mss_now)) {
 36.2403 -+	     tcp_skb_mss(skb) != mss_now)) {
 36.2404 - 		tcp_set_skb_tso_segs(sk, skb, mss_now);
 36.2405 - 		tso_segs = tcp_skb_pcount(skb);
 36.2406 - 	}
 36.2407 -@@ -1510,8 +1512,9 @@ int tcp_retransmit_skb(struct sock *sk, 
 36.2408 - 	   tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
 36.2409 - 		if (!pskb_trim(skb, 0)) {
 36.2410 - 			TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
 36.2411 --			skb_shinfo(skb)->tso_segs = 1;
 36.2412 --			skb_shinfo(skb)->tso_size = 0;
 36.2413 -+			skb_shinfo(skb)->gso_segs = 1;
 36.2414 -+			skb_shinfo(skb)->gso_size = 0;
 36.2415 -+			skb_shinfo(skb)->gso_type = 0;
 36.2416 - 			skb->ip_summed = CHECKSUM_NONE;
 36.2417 - 			skb->csum = 0;
 36.2418 - 		}
 36.2419 -@@ -1716,8 +1719,9 @@ void tcp_send_fin(struct sock *sk)
 36.2420 - 		skb->csum = 0;
 36.2421 - 		TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
 36.2422 - 		TCP_SKB_CB(skb)->sacked = 0;
 36.2423 --		skb_shinfo(skb)->tso_segs = 1;
 36.2424 --		skb_shinfo(skb)->tso_size = 0;
 36.2425 -+		skb_shinfo(skb)->gso_segs = 1;
 36.2426 -+		skb_shinfo(skb)->gso_size = 0;
 36.2427 -+		skb_shinfo(skb)->gso_type = 0;
 36.2428 - 
 36.2429 - 		/* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */
 36.2430 - 		TCP_SKB_CB(skb)->seq = tp->write_seq;
 36.2431 -@@ -1749,8 +1753,9 @@ void tcp_send_active_reset(struct sock *
 36.2432 - 	skb->csum = 0;
 36.2433 - 	TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
 36.2434 - 	TCP_SKB_CB(skb)->sacked = 0;
 36.2435 --	skb_shinfo(skb)->tso_segs = 1;
 36.2436 --	skb_shinfo(skb)->tso_size = 0;
 36.2437 -+	skb_shinfo(skb)->gso_segs = 1;
 36.2438 -+	skb_shinfo(skb)->gso_size = 0;
 36.2439 -+	skb_shinfo(skb)->gso_type = 0;
 36.2440 - 
 36.2441 - 	/* Send it off. */
 36.2442 - 	TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
 36.2443 -@@ -1833,8 +1838,9 @@ struct sk_buff * tcp_make_synack(struct 
 36.2444 - 	TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
 36.2445 - 	TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
 36.2446 - 	TCP_SKB_CB(skb)->sacked = 0;
 36.2447 --	skb_shinfo(skb)->tso_segs = 1;
 36.2448 --	skb_shinfo(skb)->tso_size = 0;
 36.2449 -+	skb_shinfo(skb)->gso_segs = 1;
 36.2450 -+	skb_shinfo(skb)->gso_size = 0;
 36.2451 -+	skb_shinfo(skb)->gso_type = 0;
 36.2452 - 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
 36.2453 - 	th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 36.2454 - 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
 36.2455 -@@ -1937,8 +1943,9 @@ int tcp_connect(struct sock *sk)
 36.2456 - 	TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
 36.2457 - 	TCP_ECN_send_syn(sk, tp, buff);
 36.2458 - 	TCP_SKB_CB(buff)->sacked = 0;
 36.2459 --	skb_shinfo(buff)->tso_segs = 1;
 36.2460 --	skb_shinfo(buff)->tso_size = 0;
 36.2461 -+	skb_shinfo(buff)->gso_segs = 1;
 36.2462 -+	skb_shinfo(buff)->gso_size = 0;
 36.2463 -+	skb_shinfo(buff)->gso_type = 0;
 36.2464 - 	buff->csum = 0;
 36.2465 - 	TCP_SKB_CB(buff)->seq = tp->write_seq++;
 36.2466 - 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
 36.2467 -@@ -2042,8 +2049,9 @@ void tcp_send_ack(struct sock *sk)
 36.2468 - 		buff->csum = 0;
 36.2469 - 		TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
 36.2470 - 		TCP_SKB_CB(buff)->sacked = 0;
 36.2471 --		skb_shinfo(buff)->tso_segs = 1;
 36.2472 --		skb_shinfo(buff)->tso_size = 0;
 36.2473 -+		skb_shinfo(buff)->gso_segs = 1;
 36.2474 -+		skb_shinfo(buff)->gso_size = 0;
 36.2475 -+		skb_shinfo(buff)->gso_type = 0;
 36.2476 - 
 36.2477 - 		/* Send it off, this clears delayed acks for us. */
 36.2478 - 		TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq = tcp_acceptable_seq(sk, tp);
 36.2479 -@@ -2078,8 +2086,9 @@ static int tcp_xmit_probe_skb(struct soc
 36.2480 - 	skb->csum = 0;
 36.2481 - 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 36.2482 - 	TCP_SKB_CB(skb)->sacked = urgent;
 36.2483 --	skb_shinfo(skb)->tso_segs = 1;
 36.2484 --	skb_shinfo(skb)->tso_size = 0;
 36.2485 -+	skb_shinfo(skb)->gso_segs = 1;
 36.2486 -+	skb_shinfo(skb)->gso_size = 0;
 36.2487 -+	skb_shinfo(skb)->gso_type = 0;
 36.2488 - 
 36.2489 - 	/* Use a previous sequence.  This should cause the other
 36.2490 - 	 * end to send an ack.  Don't queue or clone SKB, just
 36.2491 -diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
 36.2492 -index 32ad229..737c1db 100644
 36.2493 ---- a/net/ipv4/xfrm4_output.c
 36.2494 -+++ b/net/ipv4/xfrm4_output.c
 36.2495 -@@ -9,6 +9,8 @@
 36.2496 -  */
 36.2497 - 
 36.2498 - #include <linux/compiler.h>
 36.2499 -+#include <linux/if_ether.h>
 36.2500 -+#include <linux/kernel.h>
 36.2501 - #include <linux/skbuff.h>
 36.2502 - #include <linux/spinlock.h>
 36.2503 - #include <linux/netfilter_ipv4.h>
 36.2504 -@@ -152,16 +154,10 @@ error_nolock:
 36.2505 - 	goto out_exit;
 36.2506 - }
 36.2507 - 
 36.2508 --static int xfrm4_output_finish(struct sk_buff *skb)
 36.2509 -+static int xfrm4_output_finish2(struct sk_buff *skb)
 36.2510 - {
 36.2511 - 	int err;
 36.2512 - 
 36.2513 --#ifdef CONFIG_NETFILTER
 36.2514 --	if (!skb->dst->xfrm) {
 36.2515 --		IPCB(skb)->flags |= IPSKB_REROUTED;
 36.2516 --		return dst_output(skb);
 36.2517 --	}
 36.2518 --#endif
 36.2519 - 	while (likely((err = xfrm4_output_one(skb)) == 0)) {
 36.2520 - 		nf_reset(skb);
 36.2521 - 
 36.2522 -@@ -174,7 +170,7 @@ #endif
 36.2523 - 			return dst_output(skb);
 36.2524 - 
 36.2525 - 		err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
 36.2526 --			      skb->dst->dev, xfrm4_output_finish);
 36.2527 -+			      skb->dst->dev, xfrm4_output_finish2);
 36.2528 - 		if (unlikely(err != 1))
 36.2529 - 			break;
 36.2530 - 	}
 36.2531 -@@ -182,6 +178,48 @@ #endif
 36.2532 - 	return err;
 36.2533 - }
 36.2534 - 
 36.2535 -+static int xfrm4_output_finish(struct sk_buff *skb)
 36.2536 -+{
 36.2537 -+	struct sk_buff *segs;
 36.2538 -+
 36.2539 -+#ifdef CONFIG_NETFILTER
 36.2540 -+	if (!skb->dst->xfrm) {
 36.2541 -+		IPCB(skb)->flags |= IPSKB_REROUTED;
 36.2542 -+		return dst_output(skb);
 36.2543 -+	}
 36.2544 -+#endif
 36.2545 -+
 36.2546 -+	if (!skb_shinfo(skb)->gso_size)
 36.2547 -+		return xfrm4_output_finish2(skb);
 36.2548 -+
 36.2549 -+	skb->protocol = htons(ETH_P_IP);
 36.2550 -+	segs = skb_gso_segment(skb, 0);
 36.2551 -+	kfree_skb(skb);
 36.2552 -+	if (unlikely(IS_ERR(segs)))
 36.2553 -+		return PTR_ERR(segs);
 36.2554 -+
 36.2555 -+	do {
 36.2556 -+		struct sk_buff *nskb = segs->next;
 36.2557 -+		int err;
 36.2558 -+
 36.2559 -+		segs->next = NULL;
 36.2560 -+		err = xfrm4_output_finish2(segs);
 36.2561 -+
 36.2562 -+		if (unlikely(err)) {
 36.2563 -+			while ((segs = nskb)) {
 36.2564 -+				nskb = segs->next;
 36.2565 -+				segs->next = NULL;
 36.2566 -+				kfree_skb(segs);
 36.2567 -+			}
 36.2568 -+			return err;
 36.2569 -+		}
 36.2570 -+
 36.2571 -+		segs = nskb;
 36.2572 -+	} while (segs);
 36.2573 -+
 36.2574 -+	return 0;
 36.2575 -+}
 36.2576 -+
 36.2577 - int xfrm4_output(struct sk_buff *skb)
 36.2578 - {
 36.2579 - 	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
 36.2580 -diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
 36.2581 -index 5bf70b1..cf5d17e 100644
 36.2582 ---- a/net/ipv6/ip6_output.c
 36.2583 -+++ b/net/ipv6/ip6_output.c
 36.2584 -@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
 36.2585 - 
 36.2586 - int ip6_output(struct sk_buff *skb)
 36.2587 - {
 36.2588 --	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
 36.2589 -+	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
 36.2590 - 				dst_allfrag(skb->dst))
 36.2591 - 		return ip6_fragment(skb, ip6_output2);
 36.2592 - 	else
 36.2593 -@@ -829,8 +829,9 @@ static inline int ip6_ufo_append_data(st
 36.2594 - 		struct frag_hdr fhdr;
 36.2595 - 
 36.2596 - 		/* specify the length of each IP datagram fragment*/
 36.2597 --		skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) - 
 36.2598 --						sizeof(struct frag_hdr);
 36.2599 -+		skb_shinfo(skb)->gso_size = mtu - fragheaderlen - 
 36.2600 -+					    sizeof(struct frag_hdr);
 36.2601 -+		skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
 36.2602 - 		ipv6_select_ident(skb, &fhdr);
 36.2603 - 		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 36.2604 - 		__skb_queue_tail(&sk->sk_write_queue, skb);
 36.2605 -diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
 36.2606 -index d511a88..ef56d5d 100644
 36.2607 ---- a/net/ipv6/ipcomp6.c
 36.2608 -+++ b/net/ipv6/ipcomp6.c
 36.2609 -@@ -64,7 +64,7 @@ static LIST_HEAD(ipcomp6_tfms_list);
 36.2610 - 
 36.2611 - static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
 36.2612 - {
 36.2613 --	int err = 0;
 36.2614 -+	int err = -ENOMEM;
 36.2615 - 	u8 nexthdr = 0;
 36.2616 - 	int hdr_len = skb->h.raw - skb->nh.raw;
 36.2617 - 	unsigned char *tmp_hdr = NULL;
 36.2618 -@@ -75,11 +75,8 @@ static int ipcomp6_input(struct xfrm_sta
 36.2619 - 	struct crypto_tfm *tfm;
 36.2620 - 	int cpu;
 36.2621 - 
 36.2622 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 36.2623 --		skb_linearize(skb, GFP_ATOMIC) != 0) {
 36.2624 --		err = -ENOMEM;
 36.2625 -+	if (skb_linearize_cow(skb))
 36.2626 - 		goto out;
 36.2627 --	}
 36.2628 - 
 36.2629 - 	skb->ip_summed = CHECKSUM_NONE;
 36.2630 - 
 36.2631 -@@ -158,10 +155,8 @@ static int ipcomp6_output(struct xfrm_st
 36.2632 - 		goto out_ok;
 36.2633 - 	}
 36.2634 - 
 36.2635 --	if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
 36.2636 --		skb_linearize(skb, GFP_ATOMIC) != 0) {
 36.2637 -+	if (skb_linearize_cow(skb))
 36.2638 - 		goto out_ok;
 36.2639 --	}
 36.2640 - 
 36.2641 - 	/* compression */
 36.2642 - 	plen = skb->len - hdr_len;
 36.2643 -diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
 36.2644 -index 8024217..39bdeec 100644
 36.2645 ---- a/net/ipv6/xfrm6_output.c
 36.2646 -+++ b/net/ipv6/xfrm6_output.c
 36.2647 -@@ -151,7 +151,7 @@ error_nolock:
 36.2648 - 	goto out_exit;
 36.2649 - }
 36.2650 - 
 36.2651 --static int xfrm6_output_finish(struct sk_buff *skb)
 36.2652 -+static int xfrm6_output_finish2(struct sk_buff *skb)
 36.2653 - {
 36.2654 - 	int err;
 36.2655 - 
 36.2656 -@@ -167,7 +167,7 @@ static int xfrm6_output_finish(struct sk
 36.2657 - 			return dst_output(skb);
 36.2658 - 
 36.2659 - 		err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
 36.2660 --			      skb->dst->dev, xfrm6_output_finish);
 36.2661 -+			      skb->dst->dev, xfrm6_output_finish2);
 36.2662 - 		if (unlikely(err != 1))
 36.2663 - 			break;
 36.2664 - 	}
 36.2665 -@@ -175,6 +175,41 @@ static int xfrm6_output_finish(struct sk
 36.2666 - 	return err;
 36.2667 - }
 36.2668 - 
 36.2669 -+static int xfrm6_output_finish(struct sk_buff *skb)
 36.2670 -+{
 36.2671 -+	struct sk_buff *segs;
 36.2672 -+
 36.2673 -+	if (!skb_shinfo(skb)->gso_size)
 36.2674 -+		return xfrm6_output_finish2(skb);
 36.2675 -+
 36.2676 -+	skb->protocol = htons(ETH_P_IP);
 36.2677 -+	segs = skb_gso_segment(skb, 0);
 36.2678 -+	kfree_skb(skb);
 36.2679 -+	if (unlikely(IS_ERR(segs)))
 36.2680 -+		return PTR_ERR(segs);
 36.2681 -+
 36.2682 -+	do {
 36.2683 -+		struct sk_buff *nskb = segs->next;
 36.2684 -+		int err;
 36.2685 -+
 36.2686 -+		segs->next = NULL;
 36.2687 -+		err = xfrm6_output_finish2(segs);
 36.2688 -+
 36.2689 -+		if (unlikely(err)) {
 36.2690 -+			while ((segs = nskb)) {
 36.2691 -+				nskb = segs->next;
 36.2692 -+				segs->next = NULL;
 36.2693 -+				kfree_skb(segs);
 36.2694 -+			}
 36.2695 -+			return err;
 36.2696 -+		}
 36.2697 -+
 36.2698 -+		segs = nskb;
 36.2699 -+	} while (segs);
 36.2700 -+
 36.2701 -+	return 0;
 36.2702 -+}
 36.2703 -+
 36.2704 - int xfrm6_output(struct sk_buff *skb)
 36.2705 - {
 36.2706 - 	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,
 36.2707 -diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
 36.2708 -index 99ceb91..28c9efd 100644
 36.2709 ---- a/net/sched/sch_generic.c
 36.2710 -+++ b/net/sched/sch_generic.c
 36.2711 -@@ -72,9 +72,9 @@ void qdisc_unlock_tree(struct net_device
 36.2712 -    dev->queue_lock serializes queue accesses for this device
 36.2713 -    AND dev->qdisc pointer itself.
 36.2714 - 
 36.2715 --   dev->xmit_lock serializes accesses to device driver.
 36.2716 -+   netif_tx_lock serializes accesses to device driver.
 36.2717 - 
 36.2718 --   dev->queue_lock and dev->xmit_lock are mutually exclusive,
 36.2719 -+   dev->queue_lock and netif_tx_lock are mutually exclusive,
 36.2720 -    if one is grabbed, another must be free.
 36.2721 -  */
 36.2722 - 
 36.2723 -@@ -90,14 +90,17 @@ void qdisc_unlock_tree(struct net_device
 36.2724 -    NOTE: Called under dev->queue_lock with locally disabled BH.
 36.2725 - */
 36.2726 - 
 36.2727 --int qdisc_restart(struct net_device *dev)
 36.2728 -+static inline int qdisc_restart(struct net_device *dev)
 36.2729 - {
 36.2730 - 	struct Qdisc *q = dev->qdisc;
 36.2731 - 	struct sk_buff *skb;
 36.2732 - 
 36.2733 - 	/* Dequeue packet */
 36.2734 --	if ((skb = q->dequeue(q)) != NULL) {
 36.2735 -+	if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
 36.2736 - 		unsigned nolock = (dev->features & NETIF_F_LLTX);
 36.2737 -+
 36.2738 -+		dev->gso_skb = NULL;
 36.2739 -+
 36.2740 - 		/*
 36.2741 - 		 * When the driver has LLTX set it does its own locking
 36.2742 - 		 * in start_xmit. No need to add additional overhead by
 36.2743 -@@ -108,7 +111,7 @@ int qdisc_restart(struct net_device *dev
 36.2744 - 		 * will be requeued.
 36.2745 - 		 */
 36.2746 - 		if (!nolock) {
 36.2747 --			if (!spin_trylock(&dev->xmit_lock)) {
 36.2748 -+			if (!netif_tx_trylock(dev)) {
 36.2749 - 			collision:
 36.2750 - 				/* So, someone grabbed the driver. */
 36.2751 - 				
 36.2752 -@@ -126,8 +129,6 @@ int qdisc_restart(struct net_device *dev
 36.2753 - 				__get_cpu_var(netdev_rx_stat).cpu_collision++;
 36.2754 - 				goto requeue;
 36.2755 - 			}
 36.2756 --			/* Remember that the driver is grabbed by us. */
 36.2757 --			dev->xmit_lock_owner = smp_processor_id();
 36.2758 - 		}
 36.2759 - 		
 36.2760 - 		{
 36.2761 -@@ -136,14 +137,11 @@ int qdisc_restart(struct net_device *dev
 36.2762 - 
 36.2763 - 			if (!netif_queue_stopped(dev)) {
 36.2764 - 				int ret;
 36.2765 --				if (netdev_nit)
 36.2766 --					dev_queue_xmit_nit(skb, dev);
 36.2767 - 
 36.2768 --				ret = dev->hard_start_xmit(skb, dev);
 36.2769 -+				ret = dev_hard_start_xmit(skb, dev);
 36.2770 - 				if (ret == NETDEV_TX_OK) { 
 36.2771 - 					if (!nolock) {
 36.2772 --						dev->xmit_lock_owner = -1;
 36.2773 --						spin_unlock(&dev->xmit_lock);
 36.2774 -+						netif_tx_unlock(dev);
 36.2775 - 					}
 36.2776 - 					spin_lock(&dev->queue_lock);
 36.2777 - 					return -1;
 36.2778 -@@ -157,8 +155,7 @@ int qdisc_restart(struct net_device *dev
 36.2779 - 			/* NETDEV_TX_BUSY - we need to requeue */
 36.2780 - 			/* Release the driver */
 36.2781 - 			if (!nolock) { 
 36.2782 --				dev->xmit_lock_owner = -1;
 36.2783 --				spin_unlock(&dev->xmit_lock);
 36.2784 -+				netif_tx_unlock(dev);
 36.2785 - 			} 
 36.2786 - 			spin_lock(&dev->queue_lock);
 36.2787 - 			q = dev->qdisc;
 36.2788 -@@ -175,7 +172,10 @@ int qdisc_restart(struct net_device *dev
 36.2789 - 		 */
 36.2790 - 
 36.2791 - requeue:
 36.2792 --		q->ops->requeue(skb, q);
 36.2793 -+		if (skb->next)
 36.2794 -+			dev->gso_skb = skb;
 36.2795 -+		else
 36.2796 -+			q->ops->requeue(skb, q);
 36.2797 - 		netif_schedule(dev);
 36.2798 - 		return 1;
 36.2799 - 	}
 36.2800 -@@ -183,11 +183,23 @@ requeue:
 36.2801 - 	return q->q.qlen;
 36.2802 - }
 36.2803 - 
 36.2804 -+void __qdisc_run(struct net_device *dev)
 36.2805 -+{
 36.2806 -+	if (unlikely(dev->qdisc == &noop_qdisc))
 36.2807 -+		goto out;
 36.2808 -+
 36.2809 -+	while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
 36.2810 -+		/* NOTHING */;
 36.2811 -+
 36.2812 -+out:
 36.2813 -+	clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
 36.2814 -+}
 36.2815 -+
 36.2816 - static void dev_watchdog(unsigned long arg)
 36.2817 - {
 36.2818 - 	struct net_device *dev = (struct net_device *)arg;
 36.2819 - 
 36.2820 --	spin_lock(&dev->xmit_lock);
 36.2821 -+	netif_tx_lock(dev);
 36.2822 - 	if (dev->qdisc != &noop_qdisc) {
 36.2823 - 		if (netif_device_present(dev) &&
 36.2824 - 		    netif_running(dev) &&
 36.2825 -@@ -201,7 +213,7 @@ static void dev_watchdog(unsigned long a
 36.2826 - 				dev_hold(dev);
 36.2827 - 		}
 36.2828 - 	}
 36.2829 --	spin_unlock(&dev->xmit_lock);
 36.2830 -+	netif_tx_unlock(dev);
 36.2831 - 
 36.2832 - 	dev_put(dev);
 36.2833 - }
 36.2834 -@@ -225,17 +237,17 @@ void __netdev_watchdog_up(struct net_dev
 36.2835 - 
 36.2836 - static void dev_watchdog_up(struct net_device *dev)
 36.2837 - {
 36.2838 --	spin_lock_bh(&dev->xmit_lock);
 36.2839 -+	netif_tx_lock_bh(dev);
 36.2840 - 	__netdev_watchdog_up(dev);
 36.2841 --	spin_unlock_bh(&dev->xmit_lock);
 36.2842 -+	netif_tx_unlock_bh(dev);
 36.2843 - }
 36.2844 - 
 36.2845 - static void dev_watchdog_down(struct net_device *dev)
 36.2846 - {
 36.2847 --	spin_lock_bh(&dev->xmit_lock);
 36.2848 -+	netif_tx_lock_bh(dev);
 36.2849 - 	if (del_timer(&dev->watchdog_timer))
 36.2850 - 		__dev_put(dev);
 36.2851 --	spin_unlock_bh(&dev->xmit_lock);
 36.2852 -+	netif_tx_unlock_bh(dev);
 36.2853 - }
 36.2854 - 
 36.2855 - void netif_carrier_on(struct net_device *dev)
 36.2856 -@@ -577,10 +589,17 @@ void dev_deactivate(struct net_device *d
 36.2857 - 
 36.2858 - 	dev_watchdog_down(dev);
 36.2859 - 
 36.2860 --	while (test_bit(__LINK_STATE_SCHED, &dev->state))
 36.2861 -+	/* Wait for outstanding dev_queue_xmit calls. */
 36.2862 -+	synchronize_rcu();
 36.2863 -+
 36.2864 -+	/* Wait for outstanding qdisc_run calls. */
 36.2865 -+	while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
 36.2866 - 		yield();
 36.2867 - 
 36.2868 --	spin_unlock_wait(&dev->xmit_lock);
 36.2869 -+	if (dev->gso_skb) {
 36.2870 -+		kfree_skb(dev->gso_skb);
 36.2871 -+		dev->gso_skb = NULL;
 36.2872 -+	}
 36.2873 - }
 36.2874 - 
 36.2875 - void dev_init_scheduler(struct net_device *dev)
 36.2876 -@@ -622,6 +641,5 @@ EXPORT_SYMBOL(qdisc_create_dflt);
 36.2877 - EXPORT_SYMBOL(qdisc_alloc);
 36.2878 - EXPORT_SYMBOL(qdisc_destroy);
 36.2879 - EXPORT_SYMBOL(qdisc_reset);
 36.2880 --EXPORT_SYMBOL(qdisc_restart);
 36.2881 - EXPORT_SYMBOL(qdisc_lock_tree);
 36.2882 - EXPORT_SYMBOL(qdisc_unlock_tree);
 36.2883 -diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
 36.2884 -index 79b8ef3..4c16ad5 100644
 36.2885 ---- a/net/sched/sch_teql.c
 36.2886 -+++ b/net/sched/sch_teql.c
 36.2887 -@@ -302,20 +302,17 @@ restart:
 36.2888 - 
 36.2889 - 		switch (teql_resolve(skb, skb_res, slave)) {
 36.2890 - 		case 0:
 36.2891 --			if (spin_trylock(&slave->xmit_lock)) {
 36.2892 --				slave->xmit_lock_owner = smp_processor_id();
 36.2893 -+			if (netif_tx_trylock(slave)) {
 36.2894 - 				if (!netif_queue_stopped(slave) &&
 36.2895 - 				    slave->hard_start_xmit(skb, slave) == 0) {
 36.2896 --					slave->xmit_lock_owner = -1;
 36.2897 --					spin_unlock(&slave->xmit_lock);
 36.2898 -+					netif_tx_unlock(slave);
 36.2899 - 					master->slaves = NEXT_SLAVE(q);
 36.2900 - 					netif_wake_queue(dev);
 36.2901 - 					master->stats.tx_packets++;
 36.2902 - 					master->stats.tx_bytes += len;
 36.2903 - 					return 0;
 36.2904 - 				}
 36.2905 --				slave->xmit_lock_owner = -1;
 36.2906 --				spin_unlock(&slave->xmit_lock);
 36.2907 -+				netif_tx_unlock(slave);
 36.2908 - 			}
 36.2909 - 			if (netif_queue_stopped(dev))
 36.2910 - 				busy = 1;
    37.1 --- a/patches/linux-2.6.16.13/net-gso-1-check-dodgy.patch	Thu Sep 21 15:35:45 2006 -0600
    37.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.3 @@ -1,27 +0,0 @@
    37.4 -diff -urp a/net/ipv4/tcp.c b/net/ipv4/tcp.c
    37.5 ---- a/net/ipv4/tcp.c	2006-07-25 14:42:53.194910626 +0100
    37.6 -+++ b/net/ipv4/tcp.c	2006-07-25 14:41:00.955501910 +0100
    37.7 -@@ -2042,13 +2042,19 @@ struct sk_buff *tcp_tso_segment(struct s
    37.8 - 	if (!pskb_may_pull(skb, thlen))
    37.9 - 		goto out;
   37.10 - 
   37.11 --	segs = NULL;
   37.12 --	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
   37.13 --		goto out;
   37.14 --
   37.15 - 	oldlen = (u16)~skb->len;
   37.16 - 	__skb_pull(skb, thlen);
   37.17 - 
   37.18 -+	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
   37.19 -+		/* Packet is from an untrusted source, reset gso_segs. */
   37.20 -+		int mss = skb_shinfo(skb)->gso_size;
   37.21 -+
   37.22 -+		skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
   37.23 -+
   37.24 -+		segs = NULL;
   37.25 -+		goto out;
   37.26 -+	}
   37.27 -+
   37.28 - 	segs = skb_segment(skb, features);
   37.29 - 	if (IS_ERR(segs))
   37.30 - 		goto out;
    38.1 --- a/patches/linux-2.6.16.13/net-gso-2-checksum-fix.patch	Thu Sep 21 15:35:45 2006 -0600
    38.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.3 @@ -1,451 +0,0 @@
    38.4 -diff -urp a/drivers/net/bnx2.c b/drivers/net/bnx2.c
    38.5 ---- a/drivers/net/bnx2.c	2006-07-25 14:41:00.905507519 +0100
    38.6 -+++ b/drivers/net/bnx2.c	2006-07-25 14:36:00.288561400 +0100
    38.7 -@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
    38.8 - 		skb = tx_buf->skb;
    38.9 - #ifdef BCM_TSO 
   38.10 - 		/* partial BD completions possible with TSO packets */
   38.11 --		if (skb_shinfo(skb)->gso_size) {
   38.12 -+		if (skb_is_gso(skb)) {
   38.13 - 			u16 last_idx, last_ring_idx;
   38.14 - 
   38.15 - 			last_idx = sw_cons +
   38.16 -diff -urp a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
   38.17 ---- a/drivers/net/chelsio/sge.c	2006-07-25 14:41:00.908507183 +0100
   38.18 -+++ b/drivers/net/chelsio/sge.c	2006-07-25 14:36:00.291561087 +0100
   38.19 -@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
   38.20 - 	struct cpl_tx_pkt *cpl;
   38.21 - 
   38.22 - #ifdef NETIF_F_TSO
   38.23 --	if (skb_shinfo(skb)->gso_size) {
   38.24 -+	if (skb_is_gso(skb)) {
   38.25 - 		int eth_type;
   38.26 - 		struct cpl_tx_pkt_lso *hdr;
   38.27 - 
   38.28 -diff -urp a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
   38.29 ---- a/drivers/net/e1000/e1000_main.c	2006-07-25 14:41:00.910506958 +0100
   38.30 -+++ b/drivers/net/e1000/e1000_main.c	2006-07-25 14:36:00.293560878 +0100
   38.31 -@@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
   38.32 - 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
   38.33 - 	int err;
   38.34 - 
   38.35 --	if (skb_shinfo(skb)->gso_size) {
   38.36 -+	if (skb_is_gso(skb)) {
   38.37 - 		if (skb_header_cloned(skb)) {
   38.38 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
   38.39 - 			if (err)
   38.40 -@@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
   38.41 - 		 * tso gets written back prematurely before the data is fully
   38.42 - 		 * DMAd to the controller */
   38.43 - 		if (!skb->data_len && tx_ring->last_tx_tso &&
   38.44 --				!skb_shinfo(skb)->gso_size) {
   38.45 -+		    !skb_is_gso(skb)) {
   38.46 - 			tx_ring->last_tx_tso = 0;
   38.47 - 			size -= 4;
   38.48 - 		}
   38.49 -@@ -2934,8 +2934,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
   38.50 - 
   38.51 - #ifdef NETIF_F_TSO
   38.52 - 	/* Controller Erratum workaround */
   38.53 --	if (!skb->data_len && tx_ring->last_tx_tso &&
   38.54 --		!skb_shinfo(skb)->gso_size)
   38.55 -+	if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
   38.56 - 		count++;
   38.57 - #endif
   38.58 - 
   38.59 -diff -urp a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
   38.60 ---- a/drivers/net/forcedeth.c	2006-07-25 14:41:00.912506734 +0100
   38.61 -+++ b/drivers/net/forcedeth.c	2006-07-25 14:36:00.295560669 +0100
   38.62 -@@ -1105,7 +1105,7 @@ static int nv_start_xmit(struct sk_buff 
   38.63 - 	np->tx_skbuff[nr] = skb;
   38.64 - 
   38.65 - #ifdef NETIF_F_TSO
   38.66 --	if (skb_shinfo(skb)->gso_size)
   38.67 -+	if (skb_is_gso(skb))
   38.68 - 		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
   38.69 - 	else
   38.70 - #endif
   38.71 -diff -urp a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
   38.72 ---- a/drivers/net/ixgb/ixgb_main.c	2006-07-25 14:41:00.915506397 +0100
   38.73 -+++ b/drivers/net/ixgb/ixgb_main.c	2006-07-25 14:36:00.298560355 +0100
   38.74 -@@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
   38.75 - 	uint16_t ipcse, tucse, mss;
   38.76 - 	int err;
   38.77 - 
   38.78 --	if(likely(skb_shinfo(skb)->gso_size)) {
   38.79 -+	if (likely(skb_is_gso(skb))) {
   38.80 - 		if (skb_header_cloned(skb)) {
   38.81 - 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
   38.82 - 			if (err)
   38.83 -diff -urp a/drivers/net/loopback.c b/drivers/net/loopback.c
   38.84 ---- a/drivers/net/loopback.c	2006-07-25 14:41:00.915506397 +0100
   38.85 -+++ b/drivers/net/loopback.c	2006-07-25 14:36:00.298560355 +0100
   38.86 -@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff 
   38.87 - #endif
   38.88 - 
   38.89 - #ifdef LOOPBACK_TSO
   38.90 --	if (skb_shinfo(skb)->gso_size) {
   38.91 -+	if (skb_is_gso(skb)) {
   38.92 - 		BUG_ON(skb->protocol != htons(ETH_P_IP));
   38.93 - 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
   38.94 - 
   38.95 -diff -urp a/drivers/net/sky2.c b/drivers/net/sky2.c
   38.96 ---- a/drivers/net/sky2.c	2006-07-25 14:41:00.924505388 +0100
   38.97 -+++ b/drivers/net/sky2.c	2006-07-25 14:36:00.306559519 +0100
   38.98 -@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
   38.99 - 	count = sizeof(dma_addr_t) / sizeof(u32);
  38.100 - 	count += skb_shinfo(skb)->nr_frags * count;
  38.101 - 
  38.102 --	if (skb_shinfo(skb)->gso_size)
  38.103 -+	if (skb_is_gso(skb))
  38.104 - 		++count;
  38.105 - 
  38.106 - 	if (skb->ip_summed == CHECKSUM_HW)
  38.107 -diff -urp a/drivers/net/typhoon.c b/drivers/net/typhoon.c
  38.108 ---- a/drivers/net/typhoon.c	2006-07-25 14:41:00.931504603 +0100
  38.109 -+++ b/drivers/net/typhoon.c	2006-07-25 14:36:00.314558683 +0100
  38.110 -@@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, st
  38.111 - 	 * If problems develop with TSO, check this first.
  38.112 - 	 */
  38.113 - 	numDesc = skb_shinfo(skb)->nr_frags + 1;
  38.114 --	if(skb_tso_size(skb))
  38.115 -+	if (skb_is_gso(skb))
  38.116 - 		numDesc++;
  38.117 - 
  38.118 - 	/* When checking for free space in the ring, we need to also
  38.119 -@@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, st
  38.120 - 				TYPHOON_TX_PF_VLAN_TAG_SHIFT);
  38.121 - 	}
  38.122 - 
  38.123 --	if(skb_tso_size(skb)) {
  38.124 -+	if (skb_is_gso(skb)) {
  38.125 - 		first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
  38.126 - 		first_txd->numDesc++;
  38.127 - 
  38.128 -diff -urp a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
  38.129 ---- a/drivers/s390/net/qeth_main.c	2006-07-25 14:41:00.939503705 +0100
  38.130 -+++ b/drivers/s390/net/qeth_main.c	2006-07-25 14:36:00.321557952 +0100
  38.131 -@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
  38.132 - 	queue = card->qdio.out_qs
  38.133 - 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
  38.134 - 
  38.135 --	if (skb_shinfo(skb)->gso_size)
  38.136 -+	if (skb_is_gso(skb))
  38.137 - 		large_send = card->options.large_send;
  38.138 - 
  38.139 - 	/*are we able to do TSO ? If so ,prepare and send it from here */
  38.140 -@@ -4501,8 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
  38.141 - 		card->stats.tx_packets++;
  38.142 - 		card->stats.tx_bytes += skb->len;
  38.143 - #ifdef CONFIG_QETH_PERF_STATS
  38.144 --		if (skb_shinfo(skb)->gso_size &&
  38.145 --		   !(large_send == QETH_LARGE_SEND_NO)) {
  38.146 -+		if (skb_is_gso(skb) && !(large_send == QETH_LARGE_SEND_NO)) {
  38.147 - 			card->perf_stats.large_send_bytes += skb->len;
  38.148 - 			card->perf_stats.large_send_cnt++;
  38.149 - 		}
  38.150 -diff -urp a/include/linux/netdevice.h b/include/linux/netdevice.h
  38.151 ---- a/include/linux/netdevice.h	2006-07-25 14:41:00.940503593 +0100
  38.152 -+++ b/include/linux/netdevice.h	2006-07-25 14:36:00.323557743 +0100
  38.153 -@@ -541,6 +541,7 @@ struct packet_type {
  38.154 - 					 struct net_device *);
  38.155 - 	struct sk_buff		*(*gso_segment)(struct sk_buff *skb,
  38.156 - 						int features);
  38.157 -+	int			(*gso_send_check)(struct sk_buff *skb);
  38.158 - 	void			*af_packet_priv;
  38.159 - 	struct list_head	list;
  38.160 - };
  38.161 -@@ -1001,14 +1002,15 @@ extern void linkwatch_run_queue(void);
  38.162 - 
  38.163 - static inline int skb_gso_ok(struct sk_buff *skb, int features)
  38.164 - {
  38.165 --	int feature = skb_shinfo(skb)->gso_size ?
  38.166 --		      skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
  38.167 -+	int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
  38.168 - 	return (features & feature) == feature;
  38.169 - }
  38.170 - 
  38.171 - static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
  38.172 - {
  38.173 --	return !skb_gso_ok(skb, dev->features);
  38.174 -+	return skb_is_gso(skb) &&
  38.175 -+	       (!skb_gso_ok(skb, dev->features) ||
  38.176 -+		unlikely(skb->ip_summed != CHECKSUM_HW));
  38.177 - }
  38.178 - 
  38.179 - #endif /* __KERNEL__ */
  38.180 -diff -urp a/include/linux/skbuff.h b/include/linux/skbuff.h
  38.181 ---- a/include/linux/skbuff.h	2006-07-25 14:41:00.941503481 +0100
  38.182 -+++ b/include/linux/skbuff.h	2006-07-25 14:36:00.323557743 +0100
  38.183 -@@ -1403,5 +1403,10 @@ static inline void nf_bridge_get(struct 
  38.184 - static inline void nf_reset(struct sk_buff *skb) {}
  38.185 - #endif /* CONFIG_NETFILTER */
  38.186 - 
  38.187 -+static inline int skb_is_gso(const struct sk_buff *skb)
  38.188 -+{
  38.189 -+	return skb_shinfo(skb)->gso_size;
  38.190 -+}
  38.191 -+
  38.192 - #endif	/* __KERNEL__ */
  38.193 - #endif	/* _LINUX_SKBUFF_H */
  38.194 -diff -urp a/include/net/protocol.h b/include/net/protocol.h
  38.195 ---- a/include/net/protocol.h	2006-07-25 14:41:00.942503369 +0100
  38.196 -+++ b/include/net/protocol.h	2006-07-25 14:36:00.324557639 +0100
  38.197 -@@ -37,6 +37,7 @@
  38.198 - struct net_protocol {
  38.199 - 	int			(*handler)(struct sk_buff *skb);
  38.200 - 	void			(*err_handler)(struct sk_buff *skb, u32 info);
  38.201 -+	int			(*gso_send_check)(struct sk_buff *skb);
  38.202 - 	struct sk_buff	       *(*gso_segment)(struct sk_buff *skb,
  38.203 - 					       int features);
  38.204 - 	int			no_policy;
  38.205 -diff -urp a/include/net/tcp.h b/include/net/tcp.h
  38.206 ---- a/include/net/tcp.h	2006-07-25 14:41:00.943503256 +0100
  38.207 -+++ b/include/net/tcp.h	2006-07-25 14:36:00.325557534 +0100
  38.208 -@@ -1063,6 +1063,7 @@ extern struct request_sock_ops tcp_reque
  38.209 - 
  38.210 - extern int tcp_v4_destroy_sock(struct sock *sk);
  38.211 - 
  38.212 -+extern int tcp_v4_gso_send_check(struct sk_buff *skb);
  38.213 - extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
  38.214 - 
  38.215 - #ifdef CONFIG_PROC_FS
  38.216 -diff -urp a/net/bridge/br_forward.c b/net/bridge/br_forward.c
  38.217 ---- a/net/bridge/br_forward.c	2006-07-25 14:41:00.944503144 +0100
  38.218 -+++ b/net/bridge/br_forward.c	2006-07-25 14:36:00.326557430 +0100
  38.219 -@@ -32,7 +32,7 @@ static inline int should_deliver(const s
  38.220 - int br_dev_queue_push_xmit(struct sk_buff *skb)
  38.221 - {
  38.222 - 	/* drop mtu oversized packets except tso */
  38.223 --	if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
  38.224 -+	if (skb->len > skb->dev->mtu && !skb_is_gso(skb))
  38.225 - 		kfree_skb(skb);
  38.226 - 	else {
  38.227 - #ifdef CONFIG_BRIDGE_NETFILTER
  38.228 -diff -urp a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
  38.229 ---- a/net/bridge/br_netfilter.c	2006-07-25 14:41:00.945503032 +0100
  38.230 -+++ b/net/bridge/br_netfilter.c	2006-07-25 14:36:00.327557325 +0100
  38.231 -@@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
  38.232 - {
  38.233 - 	if (skb->protocol == htons(ETH_P_IP) &&
  38.234 - 	    skb->len > skb->dev->mtu &&
  38.235 --	    !skb_shinfo(skb)->gso_size)
  38.236 -+	    !skb_is_gso(skb))
  38.237 - 		return ip_fragment(skb, br_dev_queue_push_xmit);
  38.238 - 	else
  38.239 - 		return br_dev_queue_push_xmit(skb);
  38.240 -diff -urp a/net/core/dev.c b/net/core/dev.c
  38.241 ---- a/net/core/dev.c	2006-07-25 14:41:00.947502808 +0100
  38.242 -+++ b/net/core/dev.c	2006-07-25 14:36:00.329557116 +0100
  38.243 -@@ -1083,9 +1083,17 @@ int skb_checksum_help(struct sk_buff *sk
  38.244 - 	unsigned int csum;
  38.245 - 	int ret = 0, offset = skb->h.raw - skb->data;
  38.246 - 
  38.247 --	if (inward) {
  38.248 --		skb->ip_summed = CHECKSUM_NONE;
  38.249 --		goto out;
  38.250 -+	if (inward)
  38.251 -+		goto out_set_summed;
  38.252 -+
  38.253 -+	if (unlikely(skb_shinfo(skb)->gso_size)) {
  38.254 -+		static int warned;
  38.255 -+
  38.256 -+		WARN_ON(!warned);
  38.257 -+		warned = 1;
  38.258 -+
  38.259 -+		/* Let GSO fix up the checksum. */
  38.260 -+		goto out_set_summed;
  38.261 - 	}
  38.262 - 
  38.263 - 	if (skb_cloned(skb)) {
  38.264 -@@ -1102,6 +1110,8 @@ int skb_checksum_help(struct sk_buff *sk
  38.265 - 	BUG_ON(skb->csum + 2 > offset);
  38.266 - 
  38.267 - 	*(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
  38.268 -+
  38.269 -+out_set_summed:
  38.270 - 	skb->ip_summed = CHECKSUM_NONE;
  38.271 - out:	
  38.272 - 	return ret;
  38.273 -@@ -1122,17 +1132,35 @@ struct sk_buff *skb_gso_segment(struct s
  38.274 - 	struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
  38.275 - 	struct packet_type *ptype;
  38.276 - 	int type = skb->protocol;
  38.277 -+	int err;
  38.278 - 
  38.279 - 	BUG_ON(skb_shinfo(skb)->frag_list);
  38.280 --	BUG_ON(skb->ip_summed != CHECKSUM_HW);
  38.281 - 
  38.282 - 	skb->mac.raw = skb->data;
  38.283 - 	skb->mac_len = skb->nh.raw - skb->data;
  38.284 - 	__skb_pull(skb, skb->mac_len);
  38.285 - 
  38.286 -+	if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
  38.287 -+		static int warned;
  38.288 -+
  38.289 -+		WARN_ON(!warned);
  38.290 -+		warned = 1;
  38.291 -+
  38.292 -+		if (skb_header_cloned(skb) &&
  38.293 -+		    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
  38.294 -+			return ERR_PTR(err);
  38.295 -+	}
  38.296 -+
  38.297 - 	rcu_read_lock();
  38.298 - 	list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
  38.299 - 		if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
  38.300 -+			if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
  38.301 -+				err = ptype->gso_send_check(skb);
  38.302 -+				segs = ERR_PTR(err);
  38.303 -+				if (err || skb_gso_ok(skb, features))
  38.304 -+					break;
  38.305 -+				__skb_push(skb, skb->data - skb->nh.raw);
  38.306 -+			}
  38.307 - 			segs = ptype->gso_segment(skb, features);
  38.308 - 			break;
  38.309 - 		}
  38.310 -diff -urp a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
  38.311 ---- a/net/ipv4/af_inet.c	2006-07-25 14:41:00.952502247 +0100
  38.312 -+++ b/net/ipv4/af_inet.c	2006-07-25 14:36:00.334556594 +0100
  38.313 -@@ -1085,6 +1085,40 @@ int inet_sk_rebuild_header(struct sock *
  38.314 - 
  38.315 - EXPORT_SYMBOL(inet_sk_rebuild_header);
  38.316 - 
  38.317 -+static int inet_gso_send_check(struct sk_buff *skb)
  38.318 -+{
  38.319 -+	struct iphdr *iph;
  38.320 -+	struct net_protocol *ops;
  38.321 -+	int proto;
  38.322 -+	int ihl;
  38.323 -+	int err = -EINVAL;
  38.324 -+
  38.325 -+	if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
  38.326 -+		goto out;
  38.327 -+
  38.328 -+	iph = skb->nh.iph;
  38.329 -+	ihl = iph->ihl * 4;
  38.330 -+	if (ihl < sizeof(*iph))
  38.331 -+		goto out;
  38.332 -+
  38.333 -+	if (unlikely(!pskb_may_pull(skb, ihl)))
  38.334 -+		goto out;
  38.335 -+
  38.336 -+	skb->h.raw = __skb_pull(skb, ihl);
  38.337 -+	iph = skb->nh.iph;
  38.338 -+	proto = iph->protocol & (MAX_INET_PROTOS - 1);
  38.339 -+	err = -EPROTONOSUPPORT;
  38.340 -+
  38.341 -+	rcu_read_lock();
  38.342 -+	ops = rcu_dereference(inet_protos[proto]);
  38.343 -+	if (likely(ops && ops->gso_send_check))
  38.344 -+		err = ops->gso_send_check(skb);
  38.345 -+	rcu_read_unlock();
  38.346 -+
  38.347 -+out:
  38.348 -+	return err;
  38.349 -+}
  38.350 -+
  38.351 - static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
  38.352 - {
  38.353 - 	struct sk_buff *segs = ERR_PTR(-EINVAL);
  38.354 -@@ -1142,6 +1176,7 @@ static struct net_protocol igmp_protocol
  38.355 - static struct net_protocol tcp_protocol = {
  38.356 - 	.handler =	tcp_v4_rcv,
  38.357 - 	.err_handler =	tcp_v4_err,
  38.358 -+	.gso_send_check = tcp_v4_gso_send_check,
  38.359 - 	.gso_segment =	tcp_tso_segment,
  38.360 - 	.no_policy =	1,
  38.361 - };
  38.362 -@@ -1188,6 +1223,7 @@ static int ipv4_proc_init(void);
  38.363 - static struct packet_type ip_packet_type = {
  38.364 - 	.type = __constant_htons(ETH_P_IP),
  38.365 - 	.func = ip_rcv,
  38.366 -+	.gso_send_check = inet_gso_send_check,
  38.367 - 	.gso_segment = inet_gso_segment,
  38.368 - };
  38.369 - 
  38.370 -diff -urp a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
  38.371 ---- a/net/ipv4/ip_output.c	2006-07-25 14:41:00.953502135 +0100
  38.372 -+++ b/net/ipv4/ip_output.c	2006-07-25 14:36:00.335556489 +0100
  38.373 -@@ -210,7 +210,7 @@ static inline int ip_finish_output(struc
  38.374 - 		return dst_output(skb);
  38.375 - 	}
  38.376 - #endif
  38.377 --	if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
  38.378 -+	if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
  38.379 - 		return ip_fragment(skb, ip_finish_output2);
  38.380 - 	else
  38.381 - 		return ip_finish_output2(skb);
  38.382 -@@ -1095,7 +1095,7 @@ ssize_t	ip_append_page(struct sock *sk, 
  38.383 - 	while (size > 0) {
  38.384 - 		int i;
  38.385 - 
  38.386 --		if (skb_shinfo(skb)->gso_size)
  38.387 -+		if (skb_is_gso(skb))
  38.388 - 			len = size;
  38.389 - 		else {
  38.390 - 
  38.391 -diff -urp a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
  38.392 ---- a/net/ipv4/tcp_ipv4.c	2006-07-25 14:39:15.985080788 +0100
  38.393 -+++ b/net/ipv4/tcp_ipv4.c	2006-07-25 14:36:00.339556071 +0100
  38.394 -@@ -495,6 +495,24 @@ void tcp_v4_send_check(struct sock *sk, 
  38.395 - 	}
  38.396 - }
  38.397 - 
  38.398 -+int tcp_v4_gso_send_check(struct sk_buff *skb)
  38.399 -+{
  38.400 -+	struct iphdr *iph;
  38.401 -+	struct tcphdr *th;
  38.402 -+
  38.403 -+	if (!pskb_may_pull(skb, sizeof(*th)))
  38.404 -+		return -EINVAL;
  38.405 -+
  38.406 -+	iph = skb->nh.iph;
  38.407 -+	th = skb->h.th;
  38.408 -+
  38.409 -+	th->check = 0;
  38.410 -+	th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
  38.411 -+	skb->csum = offsetof(struct tcphdr, check);
  38.412 -+	skb->ip_summed = CHECKSUM_HW;
  38.413 -+	return 0;
  38.414 -+}
  38.415 -+
  38.416 - /*
  38.417 -  *	This routine will send an RST to the other tcp.
  38.418 -  *
  38.419 -diff -urp a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
  38.420 ---- a/net/ipv4/xfrm4_output.c	2006-07-25 14:41:00.958501574 +0100
  38.421 -+++ b/net/ipv4/xfrm4_output.c	2006-07-25 14:36:00.341555862 +0100
  38.422 -@@ -189,7 +189,7 @@ static int xfrm4_output_finish(struct sk
  38.423 - 	}
  38.424 - #endif
  38.425 - 
  38.426 --	if (!skb_shinfo(skb)->gso_size)
  38.427 -+	if (!skb_is_gso(skb))
  38.428 - 		return xfrm4_output_finish2(skb);
  38.429 - 
  38.430 - 	skb->protocol = htons(ETH_P_IP);
  38.431 -diff -urp a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
  38.432 ---- a/net/ipv6/ip6_output.c	2006-07-25 14:41:00.959501461 +0100
  38.433 -+++ b/net/ipv6/ip6_output.c	2006-07-25 14:36:00.341555862 +0100
  38.434 -@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
  38.435 - 
  38.436 - int ip6_output(struct sk_buff *skb)
  38.437 - {
  38.438 --	if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
  38.439 -+	if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
  38.440 - 				dst_allfrag(skb->dst))
  38.441 - 		return ip6_fragment(skb, ip6_output2);
  38.442 - 	else
  38.443 -diff -urp a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
  38.444 ---- a/net/ipv6/xfrm6_output.c	2006-07-25 14:41:00.960501349 +0100
  38.445 -+++ b/net/ipv6/xfrm6_output.c	2006-07-25 14:36:00.342555758 +0100
  38.446 -@@ -179,7 +179,7 @@ static int xfrm6_output_finish(struct sk
  38.447 - {
  38.448 - 	struct sk_buff *segs;
  38.449 - 
  38.450 --	if (!skb_shinfo(skb)->gso_size)
  38.451 -+	if (!skb_is_gso(skb))
  38.452 - 		return xfrm6_output_finish2(skb);
  38.453 - 
  38.454 - 	skb->protocol = htons(ETH_P_IP);
    39.1 --- a/patches/linux-2.6.16.13/net-gso-3-fix-errorcheck.patch	Thu Sep 21 15:35:45 2006 -0600
    39.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.3 @@ -1,17 +0,0 @@
    39.4 -diff -urp a/include/linux/netdevice.h b/include/linux/netdevice.h
    39.5 ---- a/include/linux/netdevice.h	2006-07-25 15:16:39.314333975 +0100
    39.6 -+++ b/include/linux/netdevice.h	2006-07-25 15:19:37.298320799 +0100
    39.7 -@@ -930,10 +930,10 @@ static inline void netif_tx_lock_bh(stru
    39.8 - 
    39.9 - static inline int netif_tx_trylock(struct net_device *dev)
   39.10 - {
   39.11 --	int err = spin_trylock(&dev->_xmit_lock);
   39.12 --	if (!err)
   39.13 -+	int ok = spin_trylock(&dev->_xmit_lock);
   39.14 -+	if (likely(ok))
   39.15 - 		dev->xmit_lock_owner = smp_processor_id();
   39.16 --	return err;
   39.17 -+	return ok;
   39.18 - }
   39.19 - 
   39.20 - static inline void netif_tx_unlock(struct net_device *dev)
    40.1 --- a/patches/linux-2.6.16.13/net-gso-4-kill-warnon.patch	Thu Sep 21 15:35:45 2006 -0600
    40.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.3 @@ -1,29 +0,0 @@
    40.4 -508c578140642a641bb9b888369719c510ae2a00
    40.5 -diff --git a/net/core/dev.c b/net/core/dev.c
    40.6 -index e814a89..240773b 100644
    40.7 ---- a/net/core/dev.c
    40.8 -+++ b/net/core/dev.c
    40.9 -@@ -1087,11 +1087,6 @@ int skb_checksum_help(struct sk_buff *sk
   40.10 - 		goto out_set_summed;
   40.11 - 
   40.12 - 	if (unlikely(skb_shinfo(skb)->gso_size)) {
   40.13 --		static int warned;
   40.14 --
   40.15 --		WARN_ON(!warned);
   40.16 --		warned = 1;
   40.17 --
   40.18 - 		/* Let GSO fix up the checksum. */
   40.19 - 		goto out_set_summed;
   40.20 - 	}
   40.21 -@@ -1141,11 +1136,6 @@ struct sk_buff *skb_gso_segment(struct s
   40.22 - 	__skb_pull(skb, skb->mac_len);
   40.23 - 
   40.24 - 	if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
   40.25 --		static int warned;
   40.26 --
   40.27 --		WARN_ON(!warned);
   40.28 --		warned = 1;
   40.29 --
   40.30 - 		if (skb_header_cloned(skb) &&
   40.31 - 		    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
   40.32 - 			return ERR_PTR(err);
    41.1 --- a/patches/linux-2.6.16.13/pmd-shared.patch	Thu Sep 21 15:35:45 2006 -0600
    41.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.3 @@ -1,111 +0,0 @@
    41.4 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/mm/pageattr.c ./arch/i386/mm/pageattr.c
    41.5 ---- ../pristine-linux-2.6.16.13/arch/i386/mm/pageattr.c	2006-05-02 22:38:44.000000000 +0100
    41.6 -+++ ./arch/i386/mm/pageattr.c	2006-05-04 17:41:40.000000000 +0100
    41.7 -@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
    41.8 - 	unsigned long flags;
    41.9 - 
   41.10 - 	set_pte_atomic(kpte, pte); 	/* change init_mm */
   41.11 --	if (PTRS_PER_PMD > 1)
   41.12 -+	if (HAVE_SHARED_KERNEL_PMD)
   41.13 - 		return;
   41.14 - 
   41.15 - 	spin_lock_irqsave(&pgd_lock, flags);
   41.16 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/mm/pgtable.c ./arch/i386/mm/pgtable.c
   41.17 ---- ../pristine-linux-2.6.16.13/arch/i386/mm/pgtable.c	2006-05-02 22:38:44.000000000 +0100
   41.18 -+++ ./arch/i386/mm/pgtable.c	2006-05-04 17:41:40.000000000 +0100
   41.19 -@@ -215,9 +215,10 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
   41.20 - 		spin_lock_irqsave(&pgd_lock, flags);
   41.21 - 	}
   41.22 - 
   41.23 --	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   41.24 --			swapper_pg_dir + USER_PTRS_PER_PGD,
   41.25 --			KERNEL_PGD_PTRS);
   41.26 -+	if (PTRS_PER_PMD == 1 || HAVE_SHARED_KERNEL_PMD)
   41.27 -+		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
   41.28 -+				swapper_pg_dir + USER_PTRS_PER_PGD,
   41.29 -+				KERNEL_PGD_PTRS);
   41.30 - 	if (PTRS_PER_PMD > 1)
   41.31 - 		return;
   41.32 - 
   41.33 -@@ -249,6 +250,30 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
   41.34 - 			goto out_oom;
   41.35 - 		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
   41.36 - 	}
   41.37 -+
   41.38 -+	if (!HAVE_SHARED_KERNEL_PMD) {
   41.39 -+		unsigned long flags;
   41.40 -+
   41.41 -+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   41.42 -+			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
   41.43 -+			if (!pmd)
   41.44 -+				goto out_oom;
   41.45 -+			set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
   41.46 -+		}
   41.47 -+
   41.48 -+		spin_lock_irqsave(&pgd_lock, flags);
   41.49 -+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   41.50 -+			unsigned long v = (unsigned long)i << PGDIR_SHIFT;
   41.51 -+			pgd_t *kpgd = pgd_offset_k(v);
   41.52 -+			pud_t *kpud = pud_offset(kpgd, v);
   41.53 -+			pmd_t *kpmd = pmd_offset(kpud, v);
   41.54 -+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   41.55 -+			memcpy(pmd, kpmd, PAGE_SIZE);
   41.56 -+		}
   41.57 -+		pgd_list_add(pgd);
   41.58 -+		spin_unlock_irqrestore(&pgd_lock, flags);
   41.59 -+	}
   41.60 -+
   41.61 - 	return pgd;
   41.62 - 
   41.63 - out_oom:
   41.64 -@@ -263,9 +288,23 @@ void pgd_free(pgd_t *pgd)
   41.65 - 	int i;
   41.66 - 
   41.67 - 	/* in the PAE case user pgd entries are overwritten before usage */
   41.68 --	if (PTRS_PER_PMD > 1)
   41.69 --		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
   41.70 --			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
   41.71 -+	if (PTRS_PER_PMD > 1) {
   41.72 -+		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
   41.73 -+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   41.74 -+			kmem_cache_free(pmd_cache, pmd);
   41.75 -+		}
   41.76 -+		if (!HAVE_SHARED_KERNEL_PMD) {
   41.77 -+			unsigned long flags;
   41.78 -+			spin_lock_irqsave(&pgd_lock, flags);
   41.79 -+			pgd_list_del(pgd);
   41.80 -+			spin_unlock_irqrestore(&pgd_lock, flags);
   41.81 -+			for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
   41.82 -+				pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
   41.83 -+				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
   41.84 -+				kmem_cache_free(pmd_cache, pmd);
   41.85 -+			}
   41.86 -+		}
   41.87 -+	}
   41.88 - 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
   41.89 - 	kmem_cache_free(pgd_cache, pgd);
   41.90 - }
   41.91 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/pgtable-2level-defs.h ./include/asm-i386/pgtable-2level-defs.h
   41.92 ---- ../pristine-linux-2.6.16.13/include/asm-i386/pgtable-2level-defs.h	2006-05-02 22:38:44.000000000 +0100
   41.93 -+++ ./include/asm-i386/pgtable-2level-defs.h	2006-05-04 17:41:40.000000000 +0100
   41.94 -@@ -1,6 +1,8 @@
   41.95 - #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
   41.96 - #define _I386_PGTABLE_2LEVEL_DEFS_H
   41.97 - 
   41.98 -+#define HAVE_SHARED_KERNEL_PMD 0
   41.99 -+
  41.100 - /*
  41.101 -  * traditional i386 two-level paging structure:
  41.102 -  */
  41.103 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/pgtable-3level-defs.h ./include/asm-i386/pgtable-3level-defs.h
  41.104 ---- ../pristine-linux-2.6.16.13/include/asm-i386/pgtable-3level-defs.h	2006-05-02 22:38:44.000000000 +0100
  41.105 -+++ ./include/asm-i386/pgtable-3level-defs.h	2006-05-04 17:41:40.000000000 +0100
  41.106 -@@ -1,6 +1,8 @@
  41.107 - #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
  41.108 - #define _I386_PGTABLE_3LEVEL_DEFS_H
  41.109 - 
  41.110 -+#define HAVE_SHARED_KERNEL_PMD 1
  41.111 -+
  41.112 - /*
  41.113 -  * PGDIR_SHIFT determines what a top-level page table entry can map
  41.114 -  */
    42.1 --- a/patches/linux-2.6.16.13/rcu_needs_cpu.patch	Thu Sep 21 15:35:45 2006 -0600
    42.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.3 @@ -1,33 +0,0 @@
    42.4 ---- ../pristine-linux-2.6.16.13/kernel/rcupdate.c	2006-05-02 22:38:44.000000000 +0100
    42.5 -+++ ./kernel/rcupdate.c	2006-06-09 20:27:45.000000000 +0100
    42.6 -@@ -485,6 +485,20 @@ int rcu_pending(int cpu)
    42.7 - 		__rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
    42.8 - }
    42.9 - 
   42.10 -+/*
   42.11 -+ * Check to see if any future RCU-related work will need to be done
   42.12 -+ * by the current CPU, even if none need be done immediately, returning
   42.13 -+ * 1 if so.  This function is part of the RCU implementation; it is -not-
   42.14 -+ * an exported member of the RCU API.
   42.15 -+ */
   42.16 -+int rcu_needs_cpu(int cpu)
   42.17 -+{
   42.18 -+	struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
   42.19 -+	struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu);
   42.20 -+
   42.21 -+	return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu));
   42.22 -+}
   42.23 -+
   42.24 - void rcu_check_callbacks(int cpu, int user)
   42.25 - {
   42.26 - 	if (user || 
   42.27 ---- ../pristine-linux-2.6.16.13/include/linux/rcupdate.h	2006-05-02 22:38:44.000000000 +0100
   42.28 -+++ ./include/linux/rcupdate.h	2006-06-09 20:28:57.000000000 +0100
   42.29 -@@ -134,6 +134,7 @@ static inline void rcu_bh_qsctr_inc(int 
   42.30 - }
   42.31 - 
   42.32 - extern int rcu_pending(int cpu);
   42.33 -+extern int rcu_needs_cpu(int cpu);
   42.34 - 
   42.35 - /**
   42.36 -  * rcu_read_lock - mark the beginning of an RCU read-side critical section.
    43.1 --- a/patches/linux-2.6.16.13/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch	Thu Sep 21 15:35:45 2006 -0600
    43.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.3 @@ -1,30 +0,0 @@
    43.4 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/entry.S ./arch/i386/kernel/entry.S
    43.5 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/entry.S	2006-05-02 22:38:44.000000000 +0100
    43.6 -+++ ./arch/i386/kernel/entry.S	2006-05-04 17:41:44.000000000 +0100
    43.7 -@@ -177,7 +177,7 @@ need_resched:
    43.8 - 
    43.9 - 	# sysenter call handler stub
   43.10 - ENTRY(sysenter_entry)
   43.11 --	movl TSS_sysenter_esp0(%esp),%esp
   43.12 -+	movl SYSENTER_stack_esp0(%esp),%esp
   43.13 - sysenter_past_esp:
   43.14 - 	sti
   43.15 - 	pushl $(__USER_DS)
   43.16 -@@ -492,7 +492,7 @@ device_not_available_emulate:
   43.17 -  * that sets up the real kernel stack. Check here, since we can't
   43.18 -  * allow the wrong stack to be used.
   43.19 -  *
   43.20 -- * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
   43.21 -+ * "SYSENTER_stack_esp0+12" is because the NMI/debug handler will have
   43.22 -  * already pushed 3 words if it hits on the sysenter instruction:
   43.23 -  * eflags, cs and eip.
   43.24 -  *
   43.25 -@@ -504,7 +504,7 @@ device_not_available_emulate:
   43.26 - 	cmpw $__KERNEL_CS,4(%esp);		\
   43.27 - 	jne ok;					\
   43.28 - label:						\
   43.29 --	movl TSS_sysenter_esp0+offset(%esp),%esp;	\
   43.30 -+	movl SYSENTER_stack_esp0+offset(%esp),%esp;	\
   43.31 - 	pushfl;					\
   43.32 - 	pushl $__KERNEL_CS;			\
   43.33 - 	pushl $sysenter_past_esp
    44.1 --- a/patches/linux-2.6.16.13/series	Thu Sep 21 15:35:45 2006 -0600
    44.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.3 @@ -1,23 +0,0 @@
    44.4 -blktap-aio-16_03_06.patch
    44.5 -device_bind.patch
    44.6 -fix-hz-suspend.patch
    44.7 -fix-ide-cd-pio-mode.patch
    44.8 -i386-mach-io-check-nmi.patch
    44.9 -ipv6-no-autoconf.patch
   44.10 -net-csum.patch
   44.11 -net-gso-0-base.patch
   44.12 -net-gso-1-check-dodgy.patch
   44.13 -net-gso-2-checksum-fix.patch
   44.14 -net-gso-3-fix-errorcheck.patch
   44.15 -net-gso-4-kill-warnon.patch
   44.16 -pmd-shared.patch
   44.17 -rcu_needs_cpu.patch
   44.18 -rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
   44.19 -smp-alts.patch
   44.20 -tpm_plugin_2.6.17.patch
   44.21 -x86-increase-interrupt-vector-range.patch
   44.22 -xen-hotplug.patch
   44.23 -xenoprof-generic.patch
   44.24 -x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
   44.25 -x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
   44.26 -x86-elfnote-as-preprocessor-macro.patch
    45.1 --- a/patches/linux-2.6.16.13/smp-alts.patch	Thu Sep 21 15:35:45 2006 -0600
    45.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.3 @@ -1,591 +0,0 @@
    45.4 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/Kconfig ./arch/i386/Kconfig
    45.5 ---- ../pristine-linux-2.6.16.13/arch/i386/Kconfig	2006-05-02 22:38:44.000000000 +0100
    45.6 -+++ ./arch/i386/Kconfig	2006-05-04 17:41:45.000000000 +0100
    45.7 -@@ -202,6 +202,19 @@ config SMP
    45.8 - 
    45.9 - 	  If you don't know what to do here, say N.
   45.10 - 
   45.11 -+config SMP_ALTERNATIVES
   45.12 -+	bool "SMP alternatives support (EXPERIMENTAL)"
   45.13 -+	depends on SMP && EXPERIMENTAL
   45.14 -+	help
   45.15 -+	  Try to reduce the overhead of running an SMP kernel on a uniprocessor
   45.16 -+	  host slightly by replacing certain key instruction sequences
   45.17 -+	  according to whether we currently have more than one CPU available.
   45.18 -+	  This should provide a noticeable boost to performance when
   45.19 -+	  running SMP kernels on UP machines, and have negligible impact
   45.20 -+	  when running on an true SMP host.
   45.21 -+
   45.22 -+          If unsure, say N.
   45.23 -+	  
   45.24 - config NR_CPUS
   45.25 - 	int "Maximum number of CPUs (2-255)"
   45.26 - 	range 2 255
   45.27 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/Makefile ./arch/i386/kernel/Makefile
   45.28 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/Makefile	2006-05-02 22:38:44.000000000 +0100
   45.29 -+++ ./arch/i386/kernel/Makefile	2006-05-04 17:41:45.000000000 +0100
   45.30 -@@ -37,6 +37,7 @@ obj-$(CONFIG_EFI) 		+= efi.o efi_stub.o
   45.31 - obj-$(CONFIG_DOUBLEFAULT) 	+= doublefault.o
   45.32 - obj-$(CONFIG_VM86)		+= vm86.o
   45.33 - obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
   45.34 -+obj-$(CONFIG_SMP_ALTERNATIVES)  += smpalts.o
   45.35 - 
   45.36 - EXTRA_AFLAGS   := -traditional
   45.37 - 
   45.38 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/smpalts.c ./arch/i386/kernel/smpalts.c
   45.39 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/smpalts.c	1970-01-01 01:00:00.000000000 +0100
   45.40 -+++ ./arch/i386/kernel/smpalts.c	2006-05-04 17:41:45.000000000 +0100
   45.41 -@@ -0,0 +1,85 @@
   45.42 -+#include <linux/kernel.h>
   45.43 -+#include <asm/system.h>
   45.44 -+#include <asm/smp_alt.h>
   45.45 -+#include <asm/processor.h>
   45.46 -+#include <asm/string.h>
   45.47 -+
   45.48 -+struct smp_replacement_record {
   45.49 -+	unsigned char targ_size;
   45.50 -+	unsigned char smp1_size;
   45.51 -+	unsigned char smp2_size;
   45.52 -+	unsigned char up_size;
   45.53 -+	unsigned char feature;
   45.54 -+	unsigned char data[0];
   45.55 -+};
   45.56 -+
   45.57 -+struct smp_alternative_record {
   45.58 -+	void *targ_start;
   45.59 -+	struct smp_replacement_record *repl;
   45.60 -+};
   45.61 -+
   45.62 -+extern struct smp_alternative_record __start_smp_alternatives_table,
   45.63 -+  __stop_smp_alternatives_table;
   45.64 -+extern unsigned long __init_begin, __init_end;
   45.65 -+
   45.66 -+void prepare_for_smp(void)
   45.67 -+{
   45.68 -+	struct smp_alternative_record *r;
   45.69 -+	printk(KERN_INFO "Enabling SMP...\n");
   45.70 -+	for (r = &__start_smp_alternatives_table;
   45.71 -+	     r != &__stop_smp_alternatives_table;
   45.72 -+	     r++) {
   45.73 -+		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
   45.74 -+		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
   45.75 -+		BUG_ON(r->repl->targ_size < r->repl->up_size);
   45.76 -+               if (system_state == SYSTEM_RUNNING &&
   45.77 -+                   r->targ_start >= (void *)&__init_begin &&
   45.78 -+                   r->targ_start < (void *)&__init_end)
   45.79 -+                       continue;
   45.80 -+		if (r->repl->feature != (unsigned char)-1 &&
   45.81 -+		    boot_cpu_has(r->repl->feature)) {
   45.82 -+			memcpy(r->targ_start,
   45.83 -+			       r->repl->data + r->repl->smp1_size,
   45.84 -+			       r->repl->smp2_size);
   45.85 -+			memset(r->targ_start + r->repl->smp2_size,
   45.86 -+			       0x90,
   45.87 -+			       r->repl->targ_size - r->repl->smp2_size);
   45.88 -+		} else {
   45.89 -+			memcpy(r->targ_start,
   45.90 -+			       r->repl->data,
   45.91 -+			       r->repl->smp1_size);
   45.92 -+			memset(r->targ_start + r->repl->smp1_size,
   45.93 -+			       0x90,
   45.94 -+			       r->repl->targ_size - r->repl->smp1_size);
   45.95 -+		}
   45.96 -+	}
   45.97 -+	/* Paranoia */
   45.98 -+	asm volatile ("jmp 1f\n1:");
   45.99 -+	mb();
  45.100 -+}
  45.101 -+
  45.102 -+void unprepare_for_smp(void)
  45.103 -+{
  45.104 -+	struct smp_alternative_record *r;
  45.105 -+	printk(KERN_INFO "Disabling SMP...\n");
  45.106 -+	for (r = &__start_smp_alternatives_table;
  45.107 -+	     r != &__stop_smp_alternatives_table;
  45.108 -+	     r++) {
  45.109 -+		BUG_ON(r->repl->targ_size < r->repl->smp1_size);
  45.110 -+		BUG_ON(r->repl->targ_size < r->repl->smp2_size);
  45.111 -+		BUG_ON(r->repl->targ_size < r->repl->up_size);
  45.112 -+               if (system_state == SYSTEM_RUNNING &&
  45.113 -+                   r->targ_start >= (void *)&__init_begin &&
  45.114 -+                   r->targ_start < (void *)&__init_end)
  45.115 -+                       continue;
  45.116 -+		memcpy(r->targ_start,
  45.117 -+		       r->repl->data + r->repl->smp1_size + r->repl->smp2_size,
  45.118 -+		       r->repl->up_size);
  45.119 -+		memset(r->targ_start + r->repl->up_size,
  45.120 -+		       0x90,
  45.121 -+		       r->repl->targ_size - r->repl->up_size);
  45.122 -+	}
  45.123 -+	/* Paranoia */
  45.124 -+	asm volatile ("jmp 1f\n1:");
  45.125 -+	mb();
  45.126 -+}
  45.127 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/smpboot.c ./arch/i386/kernel/smpboot.c
  45.128 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/smpboot.c	2006-05-02 22:38:44.000000000 +0100
  45.129 -+++ ./arch/i386/kernel/smpboot.c	2006-05-04 17:41:45.000000000 +0100
  45.130 -@@ -1218,6 +1218,11 @@ static void __init smp_boot_cpus(unsigne
  45.131 - 		if (max_cpus <= cpucount+1)
  45.132 - 			continue;
  45.133 - 
  45.134 -+#ifdef CONFIG_SMP_ALTERNATIVES
  45.135 -+		if (kicked == 1)
  45.136 -+			prepare_for_smp();
  45.137 -+#endif
  45.138 -+
  45.139 - 		if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
  45.140 - 			printk("CPU #%d not responding - cannot use it.\n",
  45.141 - 								apicid);
  45.142 -@@ -1396,6 +1401,11 @@ int __devinit __cpu_up(unsigned int cpu)
  45.143 - 		return -EIO;
  45.144 - 	}
  45.145 - 
  45.146 -+#ifdef CONFIG_SMP_ALTERNATIVES
  45.147 -+	if (num_online_cpus() == 1)
  45.148 -+		prepare_for_smp();
  45.149 -+#endif
  45.150 -+
  45.151 - 	local_irq_enable();
  45.152 - 	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
  45.153 - 	/* Unleash the CPU! */
  45.154 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/vmlinux.lds.S ./arch/i386/kernel/vmlinux.lds.S
  45.155 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/vmlinux.lds.S	2006-05-02 22:38:44.000000000 +0100
  45.156 -+++ ./arch/i386/kernel/vmlinux.lds.S	2006-05-04 17:41:45.000000000 +0100
  45.157 -@@ -34,6 +34,13 @@ SECTIONS
  45.158 -   __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
  45.159 -   __stop___ex_table = .;
  45.160 - 
  45.161 -+  . = ALIGN(16);
  45.162 -+  __start_smp_alternatives_table = .;
  45.163 -+  __smp_alternatives : { *(__smp_alternatives) }
  45.164 -+  __stop_smp_alternatives_table = .;
  45.165 -+
  45.166 -+  __smp_replacements : { *(__smp_replacements) }
  45.167 -+
  45.168 -   RODATA
  45.169 - 
  45.170 -   /* writeable */
  45.171 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/atomic.h ./include/asm-i386/atomic.h
  45.172 ---- ../pristine-linux-2.6.16.13/include/asm-i386/atomic.h	2006-05-02 22:38:44.000000000 +0100
  45.173 -+++ ./include/asm-i386/atomic.h	2006-05-04 17:41:45.000000000 +0100
  45.174 -@@ -4,18 +4,13 @@
  45.175 - #include <linux/config.h>
  45.176 - #include <linux/compiler.h>
  45.177 - #include <asm/processor.h>
  45.178 -+#include <asm/smp_alt.h>
  45.179 - 
  45.180 - /*
  45.181 -  * Atomic operations that C can't guarantee us.  Useful for
  45.182 -  * resource counting etc..
  45.183 -  */
  45.184 - 
  45.185 --#ifdef CONFIG_SMP
  45.186 --#define LOCK "lock ; "
  45.187 --#else
  45.188 --#define LOCK ""
  45.189 --#endif
  45.190 --
  45.191 - /*
  45.192 -  * Make sure gcc doesn't try to be clever and move things around
  45.193 -  * on us. We need to use _exactly_ the address the user gave us,
  45.194 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/bitops.h ./include/asm-i386/bitops.h
  45.195 ---- ../pristine-linux-2.6.16.13/include/asm-i386/bitops.h	2006-05-02 22:38:44.000000000 +0100
  45.196 -+++ ./include/asm-i386/bitops.h	2006-05-04 17:41:45.000000000 +0100
  45.197 -@@ -7,6 +7,7 @@
  45.198 - 
  45.199 - #include <linux/config.h>
  45.200 - #include <linux/compiler.h>
  45.201 -+#include <asm/smp_alt.h>
  45.202 - 
  45.203 - /*
  45.204 -  * These have to be done with inline assembly: that way the bit-setting
  45.205 -@@ -16,12 +17,6 @@
  45.206 -  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
  45.207 -  */
  45.208 - 
  45.209 --#ifdef CONFIG_SMP
  45.210 --#define LOCK_PREFIX "lock ; "
  45.211 --#else
  45.212 --#define LOCK_PREFIX ""
  45.213 --#endif
  45.214 --
  45.215 - #define ADDR (*(volatile long *) addr)
  45.216 - 
  45.217 - /**
  45.218 -@@ -41,7 +36,7 @@
  45.219 -  */
  45.220 - static inline void set_bit(int nr, volatile unsigned long * addr)
  45.221 - {
  45.222 --	__asm__ __volatile__( LOCK_PREFIX
  45.223 -+	__asm__ __volatile__( LOCK
  45.224 - 		"btsl %1,%0"
  45.225 - 		:"+m" (ADDR)
  45.226 - 		:"Ir" (nr));
  45.227 -@@ -76,7 +71,7 @@ static inline void __set_bit(int nr, vol
  45.228 -  */
  45.229 - static inline void clear_bit(int nr, volatile unsigned long * addr)
  45.230 - {
  45.231 --	__asm__ __volatile__( LOCK_PREFIX
  45.232 -+	__asm__ __volatile__( LOCK
  45.233 - 		"btrl %1,%0"
  45.234 - 		:"+m" (ADDR)
  45.235 - 		:"Ir" (nr));
  45.236 -@@ -121,7 +116,7 @@ static inline void __change_bit(int nr, 
  45.237 -  */
  45.238 - static inline void change_bit(int nr, volatile unsigned long * addr)
  45.239 - {
  45.240 --	__asm__ __volatile__( LOCK_PREFIX
  45.241 -+	__asm__ __volatile__( LOCK
  45.242 - 		"btcl %1,%0"
  45.243 - 		:"+m" (ADDR)
  45.244 - 		:"Ir" (nr));
  45.245 -@@ -140,7 +135,7 @@ static inline int test_and_set_bit(int n
  45.246 - {
  45.247 - 	int oldbit;
  45.248 - 
  45.249 --	__asm__ __volatile__( LOCK_PREFIX
  45.250 -+	__asm__ __volatile__( LOCK
  45.251 - 		"btsl %2,%1\n\tsbbl %0,%0"
  45.252 - 		:"=r" (oldbit),"+m" (ADDR)
  45.253 - 		:"Ir" (nr) : "memory");
  45.254 -@@ -180,7 +175,7 @@ static inline int test_and_clear_bit(int
  45.255 - {
  45.256 - 	int oldbit;
  45.257 - 
  45.258 --	__asm__ __volatile__( LOCK_PREFIX
  45.259 -+	__asm__ __volatile__( LOCK
  45.260 - 		"btrl %2,%1\n\tsbbl %0,%0"
  45.261 - 		:"=r" (oldbit),"+m" (ADDR)
  45.262 - 		:"Ir" (nr) : "memory");
  45.263 -@@ -231,7 +226,7 @@ static inline int test_and_change_bit(in
  45.264 - {
  45.265 - 	int oldbit;
  45.266 - 
  45.267 --	__asm__ __volatile__( LOCK_PREFIX
  45.268 -+	__asm__ __volatile__( LOCK
  45.269 - 		"btcl %2,%1\n\tsbbl %0,%0"
  45.270 - 		:"=r" (oldbit),"+m" (ADDR)
  45.271 - 		:"Ir" (nr) : "memory");
  45.272 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/futex.h ./include/asm-i386/futex.h
  45.273 ---- ../pristine-linux-2.6.16.13/include/asm-i386/futex.h	2006-05-02 22:38:44.000000000 +0100
  45.274 -+++ ./include/asm-i386/futex.h	2006-05-04 17:41:45.000000000 +0100
  45.275 -@@ -28,7 +28,7 @@
  45.276 - "1:	movl	%2, %0\n\
  45.277 - 	movl	%0, %3\n"					\
  45.278 - 	insn "\n"						\
  45.279 --"2:	" LOCK_PREFIX "cmpxchgl %3, %2\n\
  45.280 -+"2:	" LOCK "cmpxchgl %3, %2\n\
  45.281 - 	jnz	1b\n\
  45.282 - 3:	.section .fixup,\"ax\"\n\
  45.283 - 4:	mov	%5, %1\n\
  45.284 -@@ -68,7 +68,7 @@ futex_atomic_op_inuser (int encoded_op, 
  45.285 - #endif
  45.286 - 		switch (op) {
  45.287 - 		case FUTEX_OP_ADD:
  45.288 --			__futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
  45.289 -+			__futex_atomic_op1(LOCK "xaddl %0, %2", ret,
  45.290 - 					   oldval, uaddr, oparg);
  45.291 - 			break;
  45.292 - 		case FUTEX_OP_OR:
  45.293 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/rwsem.h ./include/asm-i386/rwsem.h
  45.294 ---- ../pristine-linux-2.6.16.13/include/asm-i386/rwsem.h	2006-05-02 22:38:44.000000000 +0100
  45.295 -+++ ./include/asm-i386/rwsem.h	2006-05-04 17:41:45.000000000 +0100
  45.296 -@@ -40,6 +40,7 @@
  45.297 - 
  45.298 - #include <linux/list.h>
  45.299 - #include <linux/spinlock.h>
  45.300 -+#include <asm/smp_alt.h>
  45.301 - 
  45.302 - struct rwsem_waiter;
  45.303 - 
  45.304 -@@ -99,7 +100,7 @@ static inline void __down_read(struct rw
  45.305 - {
  45.306 - 	__asm__ __volatile__(
  45.307 - 		"# beginning down_read\n\t"
  45.308 --LOCK_PREFIX	"  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  45.309 -+LOCK	        "  incl      (%%eax)\n\t" /* adds 0x00000001, returns the old value */
  45.310 - 		"  js        2f\n\t" /* jump if we weren't granted the lock */
  45.311 - 		"1:\n\t"
  45.312 - 		LOCK_SECTION_START("")
  45.313 -@@ -130,7 +131,7 @@ static inline int __down_read_trylock(st
  45.314 - 		"  movl	     %1,%2\n\t"
  45.315 - 		"  addl      %3,%2\n\t"
  45.316 - 		"  jle	     2f\n\t"
  45.317 --LOCK_PREFIX	"  cmpxchgl  %2,%0\n\t"
  45.318 -+LOCK	        "  cmpxchgl  %2,%0\n\t"
  45.319 - 		"  jnz	     1b\n\t"
  45.320 - 		"2:\n\t"
  45.321 - 		"# ending __down_read_trylock\n\t"
  45.322 -@@ -150,7 +151,7 @@ static inline void __down_write(struct r
  45.323 - 	tmp = RWSEM_ACTIVE_WRITE_BIAS;
  45.324 - 	__asm__ __volatile__(
  45.325 - 		"# beginning down_write\n\t"
  45.326 --LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  45.327 -+LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns the old value */
  45.328 - 		"  testl     %%edx,%%edx\n\t" /* was the count 0 before? */
  45.329 - 		"  jnz       2f\n\t" /* jump if we weren't granted the lock */
  45.330 - 		"1:\n\t"
  45.331 -@@ -188,7 +189,7 @@ static inline void __up_read(struct rw_s
  45.332 - 	__s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
  45.333 - 	__asm__ __volatile__(
  45.334 - 		"# beginning __up_read\n\t"
  45.335 --LOCK_PREFIX	"  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  45.336 -+LOCK	        "  xadd      %%edx,(%%eax)\n\t" /* subtracts 1, returns the old value */
  45.337 - 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  45.338 - 		"1:\n\t"
  45.339 - 		LOCK_SECTION_START("")
  45.340 -@@ -214,7 +215,7 @@ static inline void __up_write(struct rw_
  45.341 - 	__asm__ __volatile__(
  45.342 - 		"# beginning __up_write\n\t"
  45.343 - 		"  movl      %2,%%edx\n\t"
  45.344 --LOCK_PREFIX	"  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  45.345 -+LOCK	        "  xaddl     %%edx,(%%eax)\n\t" /* tries to transition 0xffff0001 -> 0x00000000 */
  45.346 - 		"  jnz       2f\n\t" /* jump if the lock is being waited upon */
  45.347 - 		"1:\n\t"
  45.348 - 		LOCK_SECTION_START("")
  45.349 -@@ -239,7 +240,7 @@ static inline void __downgrade_write(str
  45.350 - {
  45.351 - 	__asm__ __volatile__(
  45.352 - 		"# beginning __downgrade_write\n\t"
  45.353 --LOCK_PREFIX	"  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  45.354 -+LOCK	        "  addl      %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 -> 0xYYYY0001 */
  45.355 - 		"  js        2f\n\t" /* jump if the lock is being waited upon */
  45.356 - 		"1:\n\t"
  45.357 - 		LOCK_SECTION_START("")
  45.358 -@@ -263,7 +264,7 @@ LOCK_PREFIX	"  addl      %2,(%%eax)\n\t"
  45.359 - static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  45.360 - {
  45.361 - 	__asm__ __volatile__(
  45.362 --LOCK_PREFIX	"addl %1,%0"
  45.363 -+LOCK	          "addl %1,%0"
  45.364 - 		: "=m"(sem->count)
  45.365 - 		: "ir"(delta), "m"(sem->count));
  45.366 - }
  45.367 -@@ -276,7 +277,7 @@ static inline int rwsem_atomic_update(in
  45.368 - 	int tmp = delta;
  45.369 - 
  45.370 - 	__asm__ __volatile__(
  45.371 --LOCK_PREFIX	"xadd %0,(%2)"
  45.372 -+LOCK  	          "xadd %0,(%2)"
  45.373 - 		: "+r"(tmp), "=m"(sem->count)
  45.374 - 		: "r"(sem), "m"(sem->count)
  45.375 - 		: "memory");
  45.376 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/smp_alt.h ./include/asm-i386/smp_alt.h
  45.377 ---- ../pristine-linux-2.6.16.13/include/asm-i386/smp_alt.h	1970-01-01 01:00:00.000000000 +0100
  45.378 -+++ ./include/asm-i386/smp_alt.h	2006-05-04 17:41:45.000000000 +0100
  45.379 -@@ -0,0 +1,32 @@
  45.380 -+#ifndef __ASM_SMP_ALT_H__
  45.381 -+#define __ASM_SMP_ALT_H__
  45.382 -+
  45.383 -+#include <linux/config.h>
  45.384 -+
  45.385 -+#ifdef CONFIG_SMP
  45.386 -+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  45.387 -+#define LOCK \
  45.388 -+        "6677: nop\n" \
  45.389 -+	".section __smp_alternatives,\"a\"\n" \
  45.390 -+	".long 6677b\n" \
  45.391 -+	".long 6678f\n" \
  45.392 -+	".previous\n" \
  45.393 -+	".section __smp_replacements,\"a\"\n" \
  45.394 -+	"6678: .byte 1\n" \
  45.395 -+	".byte 1\n" \
  45.396 -+	".byte 0\n" \
  45.397 -+        ".byte 1\n" \
  45.398 -+	".byte -1\n" \
  45.399 -+	"lock\n" \
  45.400 -+	"nop\n" \
  45.401 -+	".previous\n"
  45.402 -+void prepare_for_smp(void);
  45.403 -+void unprepare_for_smp(void);
  45.404 -+#else
  45.405 -+#define LOCK "lock ; "
  45.406 -+#endif
  45.407 -+#else
  45.408 -+#define LOCK ""
  45.409 -+#endif
  45.410 -+
  45.411 -+#endif /* __ASM_SMP_ALT_H__ */
  45.412 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/spinlock.h ./include/asm-i386/spinlock.h
  45.413 ---- ../pristine-linux-2.6.16.13/include/asm-i386/spinlock.h	2006-05-02 22:38:44.000000000 +0100
  45.414 -+++ ./include/asm-i386/spinlock.h	2006-05-04 17:41:45.000000000 +0100
  45.415 -@@ -6,6 +6,7 @@
  45.416 - #include <asm/page.h>
  45.417 - #include <linux/config.h>
  45.418 - #include <linux/compiler.h>
  45.419 -+#include <asm/smp_alt.h>
  45.420 - 
  45.421 - /*
  45.422 -  * Your basic SMP spinlocks, allowing only a single CPU anywhere
  45.423 -@@ -23,7 +24,8 @@
  45.424 - 
  45.425 - #define __raw_spin_lock_string \
  45.426 - 	"\n1:\t" \
  45.427 --	"lock ; decb %0\n\t" \
  45.428 -+	LOCK \
  45.429 -+	"decb %0\n\t" \
  45.430 - 	"jns 3f\n" \
  45.431 - 	"2:\t" \
  45.432 - 	"rep;nop\n\t" \
  45.433 -@@ -34,7 +36,8 @@
  45.434 - 
  45.435 - #define __raw_spin_lock_string_flags \
  45.436 - 	"\n1:\t" \
  45.437 --	"lock ; decb %0\n\t" \
  45.438 -+	LOCK \
  45.439 -+	"decb %0\n\t" \
  45.440 - 	"jns 4f\n\t" \
  45.441 - 	"2:\t" \
  45.442 - 	"testl $0x200, %1\n\t" \
  45.443 -@@ -65,10 +68,34 @@ static inline void __raw_spin_lock_flags
  45.444 - static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  45.445 - {
  45.446 - 	char oldval;
  45.447 -+#ifdef CONFIG_SMP_ALTERNATIVES
  45.448 - 	__asm__ __volatile__(
  45.449 --		"xchgb %b0,%1"
  45.450 -+		"1:movb %1,%b0\n"
  45.451 -+		"movb $0,%1\n"
  45.452 -+		"2:"
  45.453 -+		".section __smp_alternatives,\"a\"\n"
  45.454 -+		".long 1b\n"
  45.455 -+		".long 3f\n"
  45.456 -+		".previous\n"
  45.457 -+		".section __smp_replacements,\"a\"\n"
  45.458 -+		"3: .byte 2b - 1b\n"
  45.459 -+		".byte 5f-4f\n"
  45.460 -+		".byte 0\n"
  45.461 -+		".byte 6f-5f\n"
  45.462 -+		".byte -1\n"
  45.463 -+		"4: xchgb %b0,%1\n"
  45.464 -+		"5: movb %1,%b0\n"
  45.465 -+		"movb $0,%1\n"
  45.466 -+		"6:\n"
  45.467 -+		".previous\n"
  45.468 - 		:"=q" (oldval), "=m" (lock->slock)
  45.469 - 		:"0" (0) : "memory");
  45.470 -+#else
  45.471 -+	__asm__ __volatile__(
  45.472 -+		"xchgb %b0,%1\n"
  45.473 -+		:"=q" (oldval), "=m" (lock->slock)
  45.474 -+		:"0" (0) : "memory");
  45.475 -+#endif
  45.476 - 	return oldval > 0;
  45.477 - }
  45.478 - 
  45.479 -@@ -178,12 +205,12 @@ static inline int __raw_write_trylock(ra
  45.480 - 
  45.481 - static inline void __raw_read_unlock(raw_rwlock_t *rw)
  45.482 - {
  45.483 --	asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
  45.484 -+	asm volatile(LOCK "incl %0" :"=m" (rw->lock) : : "memory");
  45.485 - }
  45.486 - 
  45.487 - static inline void __raw_write_unlock(raw_rwlock_t *rw)
  45.488 - {
  45.489 --	asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
  45.490 -+	asm volatile(LOCK "addl $" RW_LOCK_BIAS_STR ", %0"
  45.491 - 				 : "=m" (rw->lock) : : "memory");
  45.492 - }
  45.493 - 
  45.494 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-i386/system.h ./include/asm-i386/system.h
  45.495 ---- ../pristine-linux-2.6.16.13/include/asm-i386/system.h	2006-05-02 22:38:44.000000000 +0100
  45.496 -+++ ./include/asm-i386/system.h	2006-05-04 17:41:45.000000000 +0100
  45.497 -@@ -5,7 +5,7 @@
  45.498 - #include <linux/kernel.h>
  45.499 - #include <asm/segment.h>
  45.500 - #include <asm/cpufeature.h>
  45.501 --#include <linux/bitops.h> /* for LOCK_PREFIX */
  45.502 -+#include <asm/smp_alt.h>
  45.503 - 
  45.504 - #ifdef __KERNEL__
  45.505 - 
  45.506 -@@ -271,19 +271,19 @@ static inline unsigned long __cmpxchg(vo
  45.507 - 	unsigned long prev;
  45.508 - 	switch (size) {
  45.509 - 	case 1:
  45.510 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
  45.511 -+		__asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
  45.512 - 				     : "=a"(prev)
  45.513 - 				     : "q"(new), "m"(*__xg(ptr)), "0"(old)
  45.514 - 				     : "memory");
  45.515 - 		return prev;
  45.516 - 	case 2:
  45.517 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
  45.518 -+		__asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
  45.519 - 				     : "=a"(prev)
  45.520 - 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  45.521 - 				     : "memory");
  45.522 - 		return prev;
  45.523 - 	case 4:
  45.524 --		__asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
  45.525 -+		__asm__ __volatile__(LOCK "cmpxchgl %1,%2"
  45.526 - 				     : "=a"(prev)
  45.527 - 				     : "r"(new), "m"(*__xg(ptr)), "0"(old)
  45.528 - 				     : "memory");
  45.529 -@@ -336,7 +336,7 @@ static inline unsigned long long __cmpxc
  45.530 - 				      unsigned long long new)
  45.531 - {
  45.532 - 	unsigned long long prev;
  45.533 --	__asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
  45.534 -+	__asm__ __volatile__(LOCK "cmpxchg8b %3"
  45.535 - 			     : "=A"(prev)
  45.536 - 			     : "b"((unsigned long)new),
  45.537 - 			       "c"((unsigned long)(new >> 32)),
  45.538 -@@ -503,11 +503,55 @@ struct alt_instr { 
  45.539 - #endif
  45.540 - 
  45.541 - #ifdef CONFIG_SMP
  45.542 -+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
  45.543 -+#define smp_alt_mb(instr)                                           \
  45.544 -+__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
  45.545 -+		     ".section __smp_alternatives,\"a\"\n"          \
  45.546 -+		     ".long 6667b\n"                                \
  45.547 -+                     ".long 6673f\n"                                \
  45.548 -+		     ".previous\n"                                  \
  45.549 -+		     ".section __smp_replacements,\"a\"\n"          \
  45.550 -+		     "6673:.byte 6668b-6667b\n"                     \
  45.551 -+		     ".byte 6670f-6669f\n"                          \
  45.552 -+		     ".byte 6671f-6670f\n"                          \
  45.553 -+                     ".byte 0\n"                                    \
  45.554 -+		     ".byte %c0\n"                                  \
  45.555 -+		     "6669:lock;addl $0,0(%%esp)\n"                 \
  45.556 -+		     "6670:" instr "\n"                             \
  45.557 -+		     "6671:\n"                                      \
  45.558 -+		     ".previous\n"                                  \
  45.559 -+		     :                                              \
  45.560 -+		     : "i" (X86_FEATURE_XMM2)                       \
  45.561 -+		     : "memory")
  45.562 -+#define smp_rmb() smp_alt_mb("lfence")
  45.563 -+#define smp_mb()  smp_alt_mb("mfence")
  45.564 -+#define set_mb(var, value) do {                                     \
  45.565 -+unsigned long __set_mb_temp;                                        \
  45.566 -+__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
  45.567 -+		     ".section __smp_alternatives,\"a\"\n"          \
  45.568 -+		     ".long 6667b\n"                                \
  45.569 -+		     ".long 6673f\n"                                \
  45.570 -+		     ".previous\n"                                  \
  45.571 -+		     ".section __smp_replacements,\"a\"\n"          \
  45.572 -+		     "6673: .byte 6668b-6667b\n"                    \
  45.573 -+		     ".byte 6670f-6669f\n"                          \
  45.574 -+		     ".byte 0\n"                                    \
  45.575 -+		     ".byte 6671f-6670f\n"                          \
  45.576 -+		     ".byte -1\n"                                   \
  45.577 -+		     "6669: xchg %1, %0\n"                          \
  45.578 -+		     "6670:movl %1, %0\n"                           \
  45.579 -+		     "6671:\n"                                      \
  45.580 -+		     ".previous\n"                                  \
  45.581 -+		     : "=m" (var), "=r" (__set_mb_temp)             \
  45.582 -+		     : "1" (value)                                  \
  45.583 -+		     : "memory"); } while (0)
  45.584 -+#else
  45.585 - #define smp_mb()	mb()
  45.586 - #define smp_rmb()	rmb()
  45.587 -+#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  45.588 -+#endif
  45.589 - #define smp_wmb()	wmb()
  45.590 - #define smp_read_barrier_depends()	read_barrier_depends()
  45.591 --#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
  45.592 - #else
  45.593 - #define smp_mb()	barrier()
  45.594 - #define smp_rmb()	barrier()
    46.1 --- a/patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch	Thu Sep 21 15:35:45 2006 -0600
    46.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.3 @@ -1,1546 +0,0 @@
    46.4 -diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c ./drivers/char/tpm/tpm_atmel.c
    46.5 ---- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.c	2006-06-26 18:05:03.000000000 -0400
    46.6 -+++ ./drivers/char/tpm/tpm_atmel.c	2006-06-26 18:16:33.000000000 -0400
    46.7 -@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip
    46.8 - 		return -EIO;
    46.9 - 
   46.10 - 	for (i = 0; i < 6; i++) {
   46.11 --		status = ioread8(chip->vendor->iobase + 1);
   46.12 -+		status = ioread8(chip->vendor.iobase + 1);
   46.13 - 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   46.14 - 			dev_err(chip->dev, "error reading header\n");
   46.15 - 			return -EIO;
   46.16 - 		}
   46.17 --		*buf++ = ioread8(chip->vendor->iobase);
   46.18 -+		*buf++ = ioread8(chip->vendor.iobase);
   46.19 - 	}
   46.20 - 
   46.21 - 	/* size of the data received */
   46.22 -@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip
   46.23 - 		dev_err(chip->dev,
   46.24 - 			"Recv size(%d) less than available space\n", size);
   46.25 - 		for (; i < size; i++) {	/* clear the waiting data anyway */
   46.26 --			status = ioread8(chip->vendor->iobase + 1);
   46.27 -+			status = ioread8(chip->vendor.iobase + 1);
   46.28 - 			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   46.29 - 				dev_err(chip->dev, "error reading data\n");
   46.30 - 				return -EIO;
   46.31 -@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip
   46.32 - 
   46.33 - 	/* read all the data available */
   46.34 - 	for (; i < size; i++) {
   46.35 --		status = ioread8(chip->vendor->iobase + 1);
   46.36 -+		status = ioread8(chip->vendor.iobase + 1);
   46.37 - 		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
   46.38 - 			dev_err(chip->dev, "error reading data\n");
   46.39 - 			return -EIO;
   46.40 - 		}
   46.41 --		*buf++ = ioread8(chip->vendor->iobase);
   46.42 -+		*buf++ = ioread8(chip->vendor.iobase);
   46.43 - 	}
   46.44 - 
   46.45 - 	/* make sure data available is gone */
   46.46 --	status = ioread8(chip->vendor->iobase + 1);
   46.47 -+	status = ioread8(chip->vendor.iobase + 1);
   46.48 - 
   46.49 - 	if (status & ATML_STATUS_DATA_AVAIL) {
   46.50 - 		dev_err(chip->dev, "data available is stuck\n");
   46.51 -@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip
   46.52 - 	dev_dbg(chip->dev, "tpm_atml_send:\n");
   46.53 - 	for (i = 0; i < count; i++) {
   46.54 - 		dev_dbg(chip->dev, "%d 0x%x(%d)\n",  i, buf[i], buf[i]);
   46.55 -- 		iowrite8(buf[i], chip->vendor->iobase);
   46.56 -+ 		iowrite8(buf[i], chip->vendor.iobase);
   46.57 - 	}
   46.58 - 
   46.59 - 	return count;
   46.60 -@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip
   46.61 - 
   46.62 - static void tpm_atml_cancel(struct tpm_chip *chip)
   46.63 - {
   46.64 --	iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
   46.65 -+	iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
   46.66 - }
   46.67 - 
   46.68 - static u8 tpm_atml_status(struct tpm_chip *chip)
   46.69 - {
   46.70 --	return ioread8(chip->vendor->iobase + 1);
   46.71 -+	return ioread8(chip->vendor.iobase + 1);
   46.72 - }
   46.73 - 
   46.74 - static struct file_operations atmel_ops = {
   46.75 -@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] =
   46.76 - 
   46.77 - static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
   46.78 - 
   46.79 --static struct tpm_vendor_specific tpm_atmel = {
   46.80 -+static const struct tpm_vendor_specific tpm_atmel = {
   46.81 - 	.recv = tpm_atml_recv,
   46.82 - 	.send = tpm_atml_send,
   46.83 - 	.cancel = tpm_atml_cancel,
   46.84 -@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
   46.85 - 	struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
   46.86 - 
   46.87 - 	if (chip) {
   46.88 --		if (chip->vendor->have_region)
   46.89 --			atmel_release_region(chip->vendor->base,
   46.90 --					     chip->vendor->region_size);
   46.91 --		atmel_put_base_addr(chip->vendor);
   46.92 -+		if (chip->vendor.have_region)
   46.93 -+			atmel_release_region(chip->vendor.base,
   46.94 -+					     chip->vendor.region_size);
   46.95 -+		atmel_put_base_addr(chip->vendor.iobase);
   46.96 - 		tpm_remove_hardware(chip->dev);
   46.97 - 		platform_device_unregister(pdev);
   46.98 - 	}
   46.99 -@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
  46.100 - static int __init init_atmel(void)
  46.101 - {
  46.102 - 	int rc = 0;
  46.103 -+	void __iomem *iobase = NULL;
  46.104 -+	int have_region, region_size;
  46.105 -+	unsigned long base;
  46.106 -+	struct  tpm_chip *chip;
  46.107 - 
  46.108 - 	driver_register(&atml_drv);
  46.109 - 
  46.110 --	if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
  46.111 -+	if ((iobase = atmel_get_base_addr(&base, &region_size)) == NULL) {
  46.112 - 		rc = -ENODEV;
  46.113 - 		goto err_unreg_drv;
  46.114 - 	}
  46.115 - 
  46.116 --	tpm_atmel.have_region =
  46.117 -+	have_region =
  46.118 - 	    (atmel_request_region
  46.119 --	     (tpm_atmel.base, tpm_atmel.region_size,
  46.120 --	      "tpm_atmel0") == NULL) ? 0 : 1;
  46.121 -+	     (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
  46.122 -+
  46.123 - 
  46.124 - 	if (IS_ERR
  46.125 - 	    (pdev =
  46.126 -@@ -199,17 +203,25 @@ static int __init init_atmel(void)
  46.127 - 		goto err_rel_reg;
  46.128 - 	}
  46.129 - 
  46.130 --	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
  46.131 -+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
  46.132 -+		rc = -ENODEV;
  46.133 - 		goto err_unreg_dev;
  46.134 -+	}
  46.135 -+
  46.136 -+	chip->vendor.iobase = iobase;
  46.137 -+	chip->vendor.base = base;
  46.138 -+	chip->vendor.have_region = have_region;
  46.139 -+	chip->vendor.region_size = region_size;
  46.140 -+
  46.141 - 	return 0;
  46.142 - 
  46.143 - err_unreg_dev:
  46.144 - 	platform_device_unregister(pdev);
  46.145 - err_rel_reg:
  46.146 --	atmel_put_base_addr(&tpm_atmel);
  46.147 --	if (tpm_atmel.have_region)
  46.148 --		atmel_release_region(tpm_atmel.base,
  46.149 --				     tpm_atmel.region_size);
  46.150 -+	atmel_put_base_addr(iobase);
  46.151 -+	if (have_region)
  46.152 -+		atmel_release_region(base,
  46.153 -+				     region_size);
  46.154 - err_unreg_drv:
  46.155 - 	driver_unregister(&atml_drv);
  46.156 - 	return rc;
  46.157 -diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h ./drivers/char/tpm/tpm_atmel.h
  46.158 ---- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_atmel.h	2006-06-26 18:05:03.000000000 -0400
  46.159 -+++ ./drivers/char/tpm/tpm_atmel.h	2006-06-26 18:16:33.000000000 -0400
  46.160 -@@ -28,13 +28,12 @@
  46.161 - #define atmel_request_region request_mem_region
  46.162 - #define atmel_release_region release_mem_region
  46.163 - 
  46.164 --static inline void atmel_put_base_addr(struct tpm_vendor_specific
  46.165 --					 *vendor)
  46.166 -+static inline void atmel_put_base_addr(void __iomem *iobase)
  46.167 - {
  46.168 --	iounmap(vendor->iobase);
  46.169 -+	iounmap(iobase);
  46.170 - }
  46.171 - 
  46.172 --static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
  46.173 -+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
  46.174 - {
  46.175 - 	struct device_node *dn;
  46.176 - 	unsigned long address, size;
  46.177 -@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add
  46.178 - 	else
  46.179 - 		size = reg[naddrc];
  46.180 - 
  46.181 --	vendor->base = address;
  46.182 --	vendor->region_size = size;
  46.183 --	return ioremap(vendor->base, vendor->region_size);
  46.184 -+	*base = address;
  46.185 -+	*region_size = size;
  46.186 -+	return ioremap(*base, *region_size);
  46.187 - }
  46.188 - #else
  46.189 - #define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
  46.190 -@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
  46.191 - 	return 0;
  46.192 - }
  46.193 - 
  46.194 --static inline void atmel_put_base_addr(struct tpm_vendor_specific
  46.195 --					 *vendor)
  46.196 -+static inline void atmel_put_base_addr(void __iomem *iobase)
  46.197 - {
  46.198 - }
  46.199 - 
  46.200 - /* Determine where to talk to device */
  46.201 --static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
  46.202 --					 *vendor)
  46.203 -+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
  46.204 - {
  46.205 - 	int lo, hi;
  46.206 - 
  46.207 -@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add
  46.208 - 	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
  46.209 - 	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
  46.210 - 
  46.211 --	vendor->base = (hi << 8) | lo;
  46.212 --	vendor->region_size = 2;
  46.213 -+	*base = (hi << 8) | lo;
  46.214 -+	*region_size = 2;
  46.215 - 
  46.216 --	return ioport_map(vendor->base, vendor->region_size);
  46.217 -+	return ioport_map(*base, *region_size);
  46.218 - }
  46.219 - #endif
  46.220 -diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c ./drivers/char/tpm/tpm_bios.c
  46.221 ---- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_bios.c	2006-06-26 18:05:03.000000000 -0400
  46.222 -+++ ./drivers/char/tpm/tpm_bios.c	2006-06-26 18:16:33.000000000 -0400
  46.223 -@@ -29,6 +29,11 @@
  46.224 - #define MAX_TEXT_EVENT		1000	/* Max event string length */
  46.225 - #define ACPI_TCPA_SIG		"TCPA"	/* 0x41504354 /'TCPA' */
  46.226 - 
  46.227 -+enum bios_platform_class {
  46.228 -+	BIOS_CLIENT = 0x00,
  46.229 -+	BIOS_SERVER = 0x01,
  46.230 -+};
  46.231 -+
  46.232 - struct tpm_bios_log {
  46.233 - 	void *bios_event_log;
  46.234 - 	void *bios_event_log_end;
  46.235 -@@ -36,9 +41,18 @@ struct tpm_bios_log {
  46.236 - 
  46.237 - struct acpi_tcpa {
  46.238 - 	struct acpi_table_header hdr;
  46.239 --	u16 reserved;
  46.240 --	u32 log_max_len __attribute__ ((packed));
  46.241 --	u32 log_start_addr __attribute__ ((packed));
  46.242 -+	u16 platform_class;
  46.243 -+	union {
  46.244 -+		struct client_hdr {
  46.245 -+			u32 log_max_len __attribute__ ((packed));
  46.246 -+			u64 log_start_addr __attribute__ ((packed));
  46.247 -+		} client;
  46.248 -+		struct server_hdr {
  46.249 -+			u16 reserved;
  46.250 -+			u64 log_max_len __attribute__ ((packed));
  46.251 -+			u64 log_start_addr __attribute__ ((packed));
  46.252 -+		} server;
  46.253 -+	};
  46.254 - };
  46.255 - 
  46.256 - struct tcpa_event {
  46.257 -@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin
  46.258 - 	"Non-Host Info"
  46.259 - };
  46.260 - 
  46.261 -+struct tcpa_pc_event {
  46.262 -+	u32 event_id;
  46.263 -+	u32 event_size;
  46.264 -+	u8 event_data[0];
  46.265 -+};
  46.266 -+
  46.267 - enum tcpa_pc_event_ids {
  46.268 - 	SMBIOS = 1,
  46.269 - 	BIS_CERT,
  46.270 -@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids {
  46.271 - 	NVRAM,
  46.272 - 	OPTION_ROM_EXEC,
  46.273 - 	OPTION_ROM_CONFIG,
  46.274 --	OPTION_ROM_MICROCODE,
  46.275 -+	OPTION_ROM_MICROCODE = 10,
  46.276 - 	S_CRTM_VERSION,
  46.277 - 	S_CRTM_CONTENTS,
  46.278 - 	POST_CONTENTS,
  46.279 -+	HOST_TABLE_OF_DEVICES,
  46.280 - };
  46.281 - 
  46.282 - static const char* tcpa_pc_event_id_strings[] = {
  46.283 --	""
  46.284 -+	"",
  46.285 - 	"SMBIOS",
  46.286 - 	"BIS Certificate",
  46.287 - 	"POST BIOS ",
  46.288 -@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri
  46.289 - 	"NVRAM",
  46.290 - 	"Option ROM",
  46.291 - 	"Option ROM config",
  46.292 --	"Option ROM microcode",
  46.293 -+	"",
  46.294 -+	"Option ROM microcode ",
  46.295 - 	"S-CRTM Version",
  46.296 --	"S-CRTM Contents",
  46.297 --	"S-CRTM POST Contents",
  46.298 -+	"S-CRTM Contents ",
  46.299 -+	"POST Contents ",
  46.300 -+	"Table of Devices",
  46.301 - };
  46.302 - 
  46.303 - /* returns pointer to start of pos. entry of tcg log */
  46.304 -@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st
  46.305 - 	const char *name = "";
  46.306 - 	char data[40] = "";
  46.307 - 	int i, n_len = 0, d_len = 0;
  46.308 --	u32 event_id;
  46.309 -+	struct tcpa_pc_event *pc_event;
  46.310 - 
  46.311 - 	switch(event->event_type) {
  46.312 - 	case PREBOOT:
  46.313 -@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st
  46.314 - 		}
  46.315 - 		break;
  46.316 - 	case EVENT_TAG:
  46.317 --		event_id = be32_to_cpu(*((u32 *)event_entry));
  46.318 -+		pc_event = (struct tcpa_pc_event *)event_entry;
  46.319 - 
  46.320 - 		/* ToDo Row data -> Base64 */
  46.321 - 
  46.322 --		switch (event_id) {
  46.323 -+		switch (pc_event->event_id) {
  46.324 - 		case SMBIOS:
  46.325 - 		case BIS_CERT:
  46.326 - 		case CMOS:
  46.327 - 		case NVRAM:
  46.328 - 		case OPTION_ROM_EXEC:
  46.329 - 		case OPTION_ROM_CONFIG:
  46.330 --		case OPTION_ROM_MICROCODE:
  46.331 - 		case S_CRTM_VERSION:
  46.332 --		case S_CRTM_CONTENTS:
  46.333 --		case POST_CONTENTS:
  46.334 --			name = tcpa_pc_event_id_strings[event_id];
  46.335 -+			name = tcpa_pc_event_id_strings[pc_event->event_id];
  46.336 - 			n_len = strlen(name);
  46.337 - 			break;
  46.338 -+		/* hash data */
  46.339 - 		case POST_BIOS_ROM:
  46.340 - 		case ESCD:
  46.341 --			name = tcpa_pc_event_id_strings[event_id];
  46.342 -+		case OPTION_ROM_MICROCODE:
  46.343 -+		case S_CRTM_CONTENTS:
  46.344 -+		case POST_CONTENTS:
  46.345 -+			name = tcpa_pc_event_id_strings[pc_event->event_id];
  46.346 - 			n_len = strlen(name);
  46.347 - 			for (i = 0; i < 20; i++)
  46.348 --				d_len += sprintf(data, "%02x",
  46.349 --						event_entry[8 + i]);
  46.350 -+				d_len += sprintf(&data[2*i], "%02x",
  46.351 -+						pc_event->event_data[i]);
  46.352 - 			break;
  46.353 - 		default:
  46.354 - 			break;
  46.355 -@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st
  46.356 - 
  46.357 - static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
  46.358 - {
  46.359 -+	struct tcpa_event *event = v;
  46.360 -+	char *data = v;
  46.361 -+	int i;
  46.362 - 
  46.363 --	char *eventname;
  46.364 --	char data[4];
  46.365 --	u32 help;
  46.366 --	int i, len;
  46.367 --	struct tcpa_event *event = (struct tcpa_event *) v;
  46.368 --	unsigned char *event_entry =
  46.369 --	    (unsigned char *) (v + sizeof(struct tcpa_event));
  46.370 --
  46.371 --	eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
  46.372 --	if (!eventname) {
  46.373 --		printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
  46.374 --		       __func__);
  46.375 --		return -ENOMEM;
  46.376 --	}
  46.377 --
  46.378 --	/* 1st: PCR used is in little-endian format (4 bytes) */
  46.379 --	help = le32_to_cpu(event->pcr_index);
  46.380 --	memcpy(data, &help, 4);
  46.381 --	for (i = 0; i < 4; i++)
  46.382 --		seq_putc(m, data[i]);
  46.383 --
  46.384 --	/* 2nd: SHA1 (20 bytes) */
  46.385 --	for (i = 0; i < 20; i++)
  46.386 --		seq_putc(m, event->pcr_value[i]);
  46.387 --
  46.388 --	/* 3rd: event type identifier (4 bytes) */
  46.389 --	help = le32_to_cpu(event->event_type);
  46.390 --	memcpy(data, &help, 4);
  46.391 --	for (i = 0; i < 4; i++)
  46.392 -+	for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
  46.393 - 		seq_putc(m, data[i]);
  46.394 - 
  46.395 --	len = 0;
  46.396 --
  46.397 --	len += get_event_name(eventname, event, event_entry);
  46.398 --
  46.399 --	/* 4th:  filename <= 255 + \'0' delimiter */
  46.400 --	if (len > TCG_EVENT_NAME_LEN_MAX)
  46.401 --		len = TCG_EVENT_NAME_LEN_MAX;
  46.402 --
  46.403 --	for (i = 0; i < len; i++)
  46.404 --		seq_putc(m, eventname[i]);
  46.405 --
  46.406 --	/* 5th: delimiter */
  46.407 --	seq_putc(m, '\0');
  46.408 --
  46.409 - 	return 0;
  46.410 - }
  46.411 - 
  46.412 -@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s
  46.413 - 	/* 4th: eventname <= max + \'0' delimiter */
  46.414 - 	seq_printf(m, " %s\n", eventname);
  46.415 - 
  46.416 -+	kfree(eventname);
  46.417 - 	return 0;
  46.418 - }
  46.419 - 
  46.420 -@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log 
  46.421 - 	struct acpi_tcpa *buff;
  46.422 - 	acpi_status status;
  46.423 - 	struct acpi_table_header *virt;
  46.424 -+	u64 len, start;
  46.425 - 
  46.426 - 	if (log->bios_event_log != NULL) {
  46.427 - 		printk(KERN_ERR
  46.428 -@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log 
  46.429 - 		return -EIO;
  46.430 - 	}
  46.431 - 
  46.432 --	if (buff->log_max_len == 0) {
  46.433 -+	switch(buff->platform_class) {
  46.434 -+	case BIOS_SERVER:
  46.435 -+		len = buff->server.log_max_len;
  46.436 -+		start = buff->server.log_start_addr;
  46.437 -+		break;
  46.438 -+	case BIOS_CLIENT:
  46.439 -+	default:
  46.440 -+		len = buff->client.log_max_len;
  46.441 -+		start = buff->client.log_start_addr;
  46.442 -+		break;
  46.443 -+	}
  46.444 -+	if (!len) {
  46.445 - 		printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
  46.446 - 		return -EIO;
  46.447 - 	}
  46.448 - 
  46.449 - 	/* malloc EventLog space */
  46.450 --	log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
  46.451 -+	log->bios_event_log = kmalloc(len, GFP_KERNEL);
  46.452 - 	if (!log->bios_event_log) {
  46.453 --		printk
  46.454 --		    ("%s: ERROR - Not enough  Memory for BIOS measurements\n",
  46.455 --		     __func__);
  46.456 -+		printk("%s: ERROR - Not enough  Memory for BIOS measurements\n",
  46.457 -+			__func__);
  46.458 - 		return -ENOMEM;
  46.459 - 	}
  46.460 - 
  46.461 --	log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
  46.462 -+	log->bios_event_log_end = log->bios_event_log + len;
  46.463 - 
  46.464 --	acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *) &virt);
  46.465 -+	acpi_os_map_memory(start, len, (void *) &virt);
  46.466 - 
  46.467 --	memcpy(log->bios_event_log, virt, buff->log_max_len);
  46.468 -+	memcpy(log->bios_event_log, virt, len);
  46.469 - 
  46.470 --	acpi_os_unmap_memory(virt, buff->log_max_len);
  46.471 -+	acpi_os_unmap_memory(virt, len);
  46.472 - 	return 0;
  46.473 - }
  46.474 - 
  46.475 -diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c ./drivers/char/tpm/tpm_infineon.c
  46.476 ---- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_infineon.c	2006-06-26 18:05:03.000000000 -0400
  46.477 -+++ ./drivers/char/tpm/tpm_infineon.c	2006-06-26 18:16:33.000000000 -0400
  46.478 -@@ -15,6 +15,7 @@
  46.479 -  * License.
  46.480 -  */
  46.481 - 
  46.482 -+#include <linux/init.h>
  46.483 - #include <linux/pnp.h>
  46.484 - #include "tpm.h"
  46.485 - 
  46.486 -@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c
  46.487 - 
  46.488 - 	if (clear_wrfifo) {
  46.489 - 		for (i = 0; i < 4096; i++) {
  46.490 --			status = inb(chip->vendor->base + WRFIFO);
  46.491 -+			status = inb(chip->vendor.base + WRFIFO);
  46.492 - 			if (status == 0xff) {
  46.493 - 				if (check == 5)
  46.494 - 					break;
  46.495 -@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c
  46.496 - 	 */
  46.497 - 	i = 0;
  46.498 - 	do {
  46.499 --		status = inb(chip->vendor->base + RDFIFO);
  46.500 --		status = inb(chip->vendor->base + STAT);
  46.501 -+		status = inb(chip->vendor.base + RDFIFO);
  46.502 -+		status = inb(chip->vendor.base + STAT);
  46.503 - 		i++;
  46.504 - 		if (i == TPM_MAX_TRIES)
  46.505 - 			return -EIO;
  46.506 -@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i
  46.507 - 	int status;
  46.508 - 	int i;
  46.509 - 	for (i = 0; i < TPM_MAX_TRIES; i++) {
  46.510 --		status = inb(chip->vendor->base + STAT);
  46.511 -+		status = inb(chip->vendor.base + STAT);
  46.512 - 		/* check the status-register if wait_for_bit is set */
  46.513 - 		if (status & 1 << wait_for_bit)
  46.514 - 			break;
  46.515 -@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i
  46.516 - static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
  46.517 - {
  46.518 - 	wait(chip, STAT_XFE);
  46.519 --	outb(sendbyte, chip->vendor->base + WRFIFO);
  46.520 -+	outb(sendbyte, chip->vendor.base + WRFIFO);
  46.521 - }
  46.522 - 
  46.523 -     /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
  46.524 -@@ -204,7 +205,7 @@ recv_begin:
  46.525 - 		ret = wait(chip, STAT_RDA);
  46.526 - 		if (ret)
  46.527 - 			return -EIO;
  46.528 --		buf[i] = inb(chip->vendor->base + RDFIFO);
  46.529 -+		buf[i] = inb(chip->vendor.base + RDFIFO);
  46.530 - 	}
  46.531 - 
  46.532 - 	if (buf[0] != TPM_VL_VER) {
  46.533 -@@ -219,7 +220,7 @@ recv_begin:
  46.534 - 
  46.535 - 		for (i = 0; i < size; i++) {
  46.536 - 			wait(chip, STAT_RDA);
  46.537 --			buf[i] = inb(chip->vendor->base + RDFIFO);
  46.538 -+			buf[i] = inb(chip->vendor.base + RDFIFO);
  46.539 - 		}
  46.540 - 
  46.541 - 		if ((size == 0x6D00) && (buf[1] == 0x80)) {
  46.542 -@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip 
  46.543 - 	u8 count_high, count_low, count_4, count_3, count_2, count_1;
  46.544 - 
  46.545 - 	/* Disabling Reset, LP and IRQC */
  46.546 --	outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
  46.547 -+	outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
  46.548 - 
  46.549 - 	ret = empty_fifo(chip, 1);
  46.550 - 	if (ret) {
  46.551 -@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch
  46.552 - 
  46.553 - static u8 tpm_inf_status(struct tpm_chip *chip)
  46.554 - {
  46.555 --	return inb(chip->vendor->base + STAT);
  46.556 -+	return inb(chip->vendor.base + STAT);
  46.557 - }
  46.558 - 
  46.559 - static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
  46.560 -@@ -346,7 +347,7 @@ static struct file_operations inf_ops = 
  46.561 - 	.release = tpm_release,
  46.562 - };
  46.563 - 
  46.564 --static struct tpm_vendor_specific tpm_inf = {
  46.565 -+static const struct tpm_vendor_specific tpm_inf = {
  46.566 - 	.recv = tpm_inf_recv,
  46.567 - 	.send = tpm_inf_send,
  46.568 - 	.cancel = tpm_inf_cancel,
  46.569 -@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s
  46.570 - 	int version[2];
  46.571 - 	int productid[2];
  46.572 - 	char chipname[20];
  46.573 -+	struct tpm_chip *chip;
  46.574 - 
  46.575 - 	/* read IO-ports through PnP */
  46.576 - 	if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
  46.577 -@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s
  46.578 - 			goto err_last;
  46.579 - 		}
  46.580 - 		/* publish my base address and request region */
  46.581 --		tpm_inf.base = TPM_INF_BASE;
  46.582 - 		if (request_region
  46.583 --		    (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
  46.584 -+		    (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
  46.585 - 			rc = -EINVAL;
  46.586 - 			goto err_last;
  46.587 - 		}
  46.588 --		if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
  46.589 --				"tpm_infineon0") == NULL) {
  46.590 -+		if (request_region
  46.591 -+		    (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
  46.592 - 			rc = -EINVAL;
  46.593 - 			goto err_last;
  46.594 - 		}
  46.595 -@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s
  46.596 - 
  46.597 - 		/* configure TPM with IO-ports */
  46.598 - 		outb(IOLIMH, TPM_INF_ADDR);
  46.599 --		outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
  46.600 -+		outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
  46.601 - 		outb(IOLIML, TPM_INF_ADDR);
  46.602 --		outb((tpm_inf.base & 0xff), TPM_INF_DATA);
  46.603 -+		outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
  46.604 - 
  46.605 - 		/* control if IO-ports are set correctly */
  46.606 - 		outb(IOLIMH, TPM_INF_ADDR);
  46.607 -@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s
  46.608 - 		outb(IOLIML, TPM_INF_ADDR);
  46.609 - 		iol = inb(TPM_INF_DATA);
  46.610 - 
  46.611 --		if ((ioh << 8 | iol) != tpm_inf.base) {
  46.612 -+		if ((ioh << 8 | iol) != TPM_INF_BASE) {
  46.613 - 			dev_err(&dev->dev,
  46.614 --				"Could not set IO-ports to 0x%lx\n",
  46.615 --				tpm_inf.base);
  46.616 -+				"Could not set IO-ports to 0x%x\n",
  46.617 -+				TPM_INF_BASE);
  46.618 - 			rc = -EIO;
  46.619 - 			goto err_release_region;
  46.620 - 		}
  46.621 -@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s
  46.622 - 		outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
  46.623 - 
  46.624 - 		/* disable RESET, LP and IRQC */
  46.625 --		outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
  46.626 -+		outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
  46.627 - 
  46.628 - 		/* Finally, we're done, print some infos */
  46.629 - 		dev_info(&dev->dev, "TPM found: "
  46.630 - 			 "config base 0x%x, "
  46.631 - 			 "io base 0x%x, "
  46.632 --			 "chip version %02x%02x, "
  46.633 --			 "vendor id %x%x (Infineon), "
  46.634 --			 "product id %02x%02x"
  46.635 -+			 "chip version 0x%02x%02x, "
  46.636 -+			 "vendor id 0x%x%x (Infineon), "
  46.637 -+			 "product id 0x%02x%02x"
  46.638 - 			 "%s\n",
  46.639 - 			 TPM_INF_ADDR,
  46.640 - 			 TPM_INF_BASE,
  46.641 -@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s
  46.642 - 			 vendorid[0], vendorid[1],
  46.643 - 			 productid[0], productid[1], chipname);
  46.644 - 
  46.645 --		rc = tpm_register_hardware(&dev->dev, &tpm_inf);
  46.646 --		if (rc < 0) {
  46.647 --			rc = -ENODEV;
  46.648 -+		if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
  46.649 - 			goto err_release_region;
  46.650 - 		}
  46.651 -+		chip->vendor.base = TPM_INF_BASE;
  46.652 - 		return 0;
  46.653 - 	} else {
  46.654 - 		rc = -ENODEV;
  46.655 -@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s
  46.656 - 	}
  46.657 - 
  46.658 - err_release_region:
  46.659 --	release_region(tpm_inf.base, TPM_INF_PORT_LEN);
  46.660 -+	release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
  46.661 - 	release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
  46.662 - 
  46.663 - err_last:
  46.664 -@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove
  46.665 - 	struct tpm_chip *chip = pnp_get_drvdata(dev);
  46.666 - 
  46.667 - 	if (chip) {
  46.668 --		release_region(chip->vendor->base, TPM_INF_PORT_LEN);
  46.669 -+		release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
  46.670 -+		release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
  46.671 - 		tpm_remove_hardware(chip->dev);
  46.672 - 	}
  46.673 - }
  46.674 -@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = {
  46.675 - 	},
  46.676 - 	.id_table = tpm_pnp_tbl,
  46.677 - 	.probe = tpm_inf_pnp_probe,
  46.678 --	.remove = tpm_inf_pnp_remove,
  46.679 -+	.remove = __devexit_p(tpm_inf_pnp_remove),
  46.680 - };
  46.681 - 
  46.682 - static int __init init_inf(void)
  46.683 -@@ -538,5 +539,5 @@ module_exit(cleanup_inf);
  46.684 - 
  46.685 - MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
  46.686 - MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
  46.687 --MODULE_VERSION("1.7");
  46.688 -+MODULE_VERSION("1.8");
  46.689 - MODULE_LICENSE("GPL");
  46.690 -diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c ./drivers/char/tpm/tpm_nsc.c
  46.691 ---- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_nsc.c	2006-06-26 18:05:03.000000000 -0400
  46.692 -+++ ./drivers/char/tpm/tpm_nsc.c	2006-06-26 18:16:33.000000000 -0400
  46.693 -@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip
  46.694 - 	unsigned long stop;
  46.695 - 
  46.696 - 	/* status immediately available check */
  46.697 --	*data = inb(chip->vendor->base + NSC_STATUS);
  46.698 -+	*data = inb(chip->vendor.base + NSC_STATUS);
  46.699 - 	if ((*data & mask) == val)
  46.700 - 		return 0;
  46.701 - 
  46.702 -@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip
  46.703 - 	stop = jiffies + 10 * HZ;
  46.704 - 	do {
  46.705 - 		msleep(TPM_TIMEOUT);
  46.706 --		*data = inb(chip->vendor->base + 1);
  46.707 -+		*data = inb(chip->vendor.base + 1);
  46.708 - 		if ((*data & mask) == val)
  46.709 - 			return 0;
  46.710 - 	}
  46.711 -@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm
  46.712 - 	unsigned long stop;
  46.713 - 
  46.714 - 	/* status immediately available check */
  46.715 --	status = inb(chip->vendor->base + NSC_STATUS);
  46.716 -+	status = inb(chip->vendor.base + NSC_STATUS);
  46.717 - 	if (status & NSC_STATUS_OBF)
  46.718 --		status = inb(chip->vendor->base + NSC_DATA);
  46.719 -+		status = inb(chip->vendor.base + NSC_DATA);
  46.720 - 	if (status & NSC_STATUS_RDY)
  46.721 - 		return 0;
  46.722 - 
  46.723 -@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm
  46.724 - 	stop = jiffies + 100;
  46.725 - 	do {
  46.726 - 		msleep(TPM_TIMEOUT);
  46.727 --		status = inb(chip->vendor->base + NSC_STATUS);
  46.728 -+		status = inb(chip->vendor.base + NSC_STATUS);
  46.729 - 		if (status & NSC_STATUS_OBF)
  46.730 --			status = inb(chip->vendor->base + NSC_DATA);
  46.731 -+			status = inb(chip->vendor.base + NSC_DATA);
  46.732 - 		if (status & NSC_STATUS_RDY)
  46.733 - 			return 0;
  46.734 - 	}
  46.735 -@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip 
  46.736 - 		return -EIO;
  46.737 - 	}
  46.738 - 	if ((data =
  46.739 --	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
  46.740 -+	     inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
  46.741 - 		dev_err(chip->dev, "not in normal mode (0x%x)\n",
  46.742 - 			data);
  46.743 - 		return -EIO;
  46.744 -@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip 
  46.745 - 		}
  46.746 - 		if (data & NSC_STATUS_F0)
  46.747 - 			break;
  46.748 --		*p = inb(chip->vendor->base + NSC_DATA);
  46.749 -+		*p = inb(chip->vendor.base + NSC_DATA);
  46.750 - 	}
  46.751 - 
  46.752 - 	if ((data & NSC_STATUS_F0) == 0 &&
  46.753 -@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip 
  46.754 - 		dev_err(chip->dev, "F0 not set\n");
  46.755 - 		return -EIO;
  46.756 - 	}
  46.757 --	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
  46.758 -+	if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
  46.759 - 		dev_err(chip->dev,
  46.760 - 			"expected end of command(0x%x)\n", data);
  46.761 - 		return -EIO;
  46.762 -@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip 
  46.763 - 	 * fix it. Not sure why this is needed, we followed the flow
  46.764 - 	 * chart in the manual to the letter.
  46.765 - 	 */
  46.766 --	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
  46.767 -+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
  46.768 - 
  46.769 - 	if (nsc_wait_for_ready(chip) != 0)
  46.770 - 		return -EIO;
  46.771 -@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip 
  46.772 - 		return -EIO;
  46.773 - 	}
  46.774 - 
  46.775 --	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
  46.776 -+	outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
  46.777 - 	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
  46.778 - 		dev_err(chip->dev, "IBR timeout\n");
  46.779 - 		return -EIO;
  46.780 -@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip 
  46.781 - 				"IBF timeout (while writing data)\n");
  46.782 - 			return -EIO;
  46.783 - 		}
  46.784 --		outb(buf[i], chip->vendor->base + NSC_DATA);
  46.785 -+		outb(buf[i], chip->vendor.base + NSC_DATA);
  46.786 - 	}
  46.787 - 
  46.788 - 	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
  46.789 - 		dev_err(chip->dev, "IBF timeout\n");
  46.790 - 		return -EIO;
  46.791 - 	}
  46.792 --	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
  46.793 -+	outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
  46.794 - 
  46.795 - 	return count;
  46.796 - }
  46.797 - 
  46.798 - static void tpm_nsc_cancel(struct tpm_chip *chip)
  46.799 - {
  46.800 --	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
  46.801 -+	outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
  46.802 - }
  46.803 - 
  46.804 - static u8 tpm_nsc_status(struct tpm_chip *chip)
  46.805 - {
  46.806 --	return inb(chip->vendor->base + NSC_STATUS);
  46.807 -+	return inb(chip->vendor.base + NSC_STATUS);
  46.808 - }
  46.809 - 
  46.810 - static struct file_operations nsc_ops = {
  46.811 -@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] = 
  46.812 - 
  46.813 - static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
  46.814 - 
  46.815 --static struct tpm_vendor_specific tpm_nsc = {
  46.816 -+static const struct tpm_vendor_specific tpm_nsc = {
  46.817 - 	.recv = tpm_nsc_recv,
  46.818 - 	.send = tpm_nsc_send,
  46.819 - 	.cancel = tpm_nsc_cancel,
  46.820 -@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str
  46.821 - {
  46.822 - 	struct tpm_chip *chip = dev_get_drvdata(dev);
  46.823 - 	if ( chip ) {
  46.824 --		release_region(chip->vendor->base, 2);
  46.825 -+		release_region(chip->vendor.base, 2);
  46.826 - 		tpm_remove_hardware(chip->dev);
  46.827 - 	}
  46.828 - }
  46.829 -@@ -286,7 +286,8 @@ static int __init init_nsc(void)
  46.830 - 	int rc = 0;
  46.831 - 	int lo, hi;
  46.832 - 	int nscAddrBase = TPM_ADDR;
  46.833 --
  46.834 -+	struct tpm_chip *chip;
  46.835 -+	unsigned long base;
  46.836 - 
  46.837 - 	/* verify that it is a National part (SID) */
  46.838 - 	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
  46.839 -@@ -300,7 +301,7 @@ static int __init init_nsc(void)
  46.840 - 
  46.841 - 	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
  46.842 - 	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
  46.843 --	tpm_nsc.base = (hi<<8) | lo;
  46.844 -+	base = (hi<<8) | lo;
  46.845 - 
  46.846 - 	/* enable the DPM module */
  46.847 - 	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
  46.848 -@@ -320,13 +321,15 @@ static int __init init_nsc(void)
  46.849 - 	if ((rc = platform_device_register(pdev)) < 0)
  46.850 - 		goto err_free_dev;
  46.851 - 
  46.852 --	if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
  46.853 -+	if (request_region(base, 2, "tpm_nsc0") == NULL ) {
  46.854 - 		rc = -EBUSY;
  46.855 - 		goto err_unreg_dev;
  46.856 - 	}
  46.857 - 
  46.858 --	if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
  46.859 -+	if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
  46.860 -+		rc = -ENODEV;
  46.861 - 		goto err_rel_reg;
  46.862 -+	}
  46.863 - 
  46.864 - 	dev_dbg(&pdev->dev, "NSC TPM detected\n");
  46.865 - 	dev_dbg(&pdev->dev,
  46.866 -@@ -361,10 +364,12 @@ static int __init init_nsc(void)
  46.867 - 		 "NSC TPM revision %d\n",
  46.868 - 		 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
  46.869 - 
  46.870 -+	chip->vendor.base = base;
  46.871 -+
  46.872 - 	return 0;
  46.873 - 
  46.874 - err_rel_reg:
  46.875 --	release_region(tpm_nsc.base, 2);
  46.876 -+	release_region(base, 2);
  46.877 - err_unreg_dev:
  46.878 - 	platform_device_unregister(pdev);
  46.879 - err_free_dev:
  46.880 -diff -pruN ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c ./drivers/char/tpm/tpm_tis.c
  46.881 ---- ../pristine-linux-2.6.16.13/drivers/char/tpm/tpm_tis.c	1969-12-31 19:00:00.000000000 -0500
  46.882 -+++ ./drivers/char/tpm/tpm_tis.c	2006-06-26 18:16:33.000000000 -0400
  46.883 -@@ -0,0 +1,665 @@
  46.884 -+/*
  46.885 -+ * Copyright (C) 2005, 2006 IBM Corporation
  46.886 -+ *
  46.887 -+ * Authors:
  46.888 -+ * Leendert van Doorn <leendert@watson.ibm.com>
  46.889 -+ * Kylene Hall <kjhall@us.ibm.com>
  46.890 -+ *
  46.891 -+ * Device driver for TCG/TCPA TPM (trusted platform module).
  46.892 -+ * Specifications at www.trustedcomputinggroup.org
  46.893 -+ *
  46.894 -+ * This device driver implements the TPM interface as defined in
  46.895 -+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
  46.896 -+ *
  46.897 -+ * This program is free software; you can redistribute it and/or
  46.898 -+ * modify it under the terms of the GNU General Public License as
  46.899 -+ * published by the Free Software Foundation, version 2 of the
  46.900 -+ * License.
  46.901 -+ */
  46.902 -+#include <linux/init.h>
  46.903 -+#include <linux/module.h>
  46.904 -+#include <linux/moduleparam.h>
  46.905 -+#include <linux/pnp.h>
  46.906 -+#include <linux/interrupt.h>
  46.907 -+#include <linux/wait.h>
  46.908 -+#include "tpm.h"
  46.909 -+
  46.910 -+#define TPM_HEADER_SIZE 10
  46.911 -+
  46.912 -+enum tis_access {
  46.913 -+	TPM_ACCESS_VALID = 0x80,
  46.914 -+	TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
  46.915 -+	TPM_ACCESS_REQUEST_PENDING = 0x04,
  46.916 -+	TPM_ACCESS_REQUEST_USE = 0x02,
  46.917 -+};
  46.918 -+
  46.919 -+enum tis_status {
  46.920 -+	TPM_STS_VALID = 0x80,
  46.921 -+	TPM_STS_COMMAND_READY = 0x40,
  46.922 -+	TPM_STS_GO = 0x20,
  46.923 -+	TPM_STS_DATA_AVAIL = 0x10,
  46.924 -+	TPM_STS_DATA_EXPECT = 0x08,
  46.925 -+};
  46.926 -+
  46.927 -+enum tis_int_flags {
  46.928 -+	TPM_GLOBAL_INT_ENABLE = 0x80000000,
  46.929 -+	TPM_INTF_BURST_COUNT_STATIC = 0x100,
  46.930 -+	TPM_INTF_CMD_READY_INT = 0x080,
  46.931 -+	TPM_INTF_INT_EDGE_FALLING = 0x040,
  46.932 -+	TPM_INTF_INT_EDGE_RISING = 0x020,
  46.933 -+	TPM_INTF_INT_LEVEL_LOW = 0x010,
  46.934 -+	TPM_INTF_INT_LEVEL_HIGH = 0x008,
  46.935 -+	TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
  46.936 -+	TPM_INTF_STS_VALID_INT = 0x002,
  46.937 -+	TPM_INTF_DATA_AVAIL_INT = 0x001,
  46.938 -+};
  46.939 -+
  46.940 -+enum tis_defaults {
  46.941 -+	TIS_MEM_BASE = 0xFED40000,
  46.942 -+	TIS_MEM_LEN = 0x5000,
  46.943 -+	TIS_SHORT_TIMEOUT = 750,	/* ms */
  46.944 -+	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
  46.945 -+};
  46.946 -+
  46.947 -+#define	TPM_ACCESS(l)			(0x0000 | ((l) << 12))
  46.948 -+#define	TPM_INT_ENABLE(l)		(0x0008 | ((l) << 12))
  46.949 -+#define	TPM_INT_VECTOR(l)		(0x000C | ((l) << 12))
  46.950 -+#define	TPM_INT_STATUS(l)		(0x0010 | ((l) << 12))
  46.951 -+#define	TPM_INTF_CAPS(l)		(0x0014 | ((l) << 12))
  46.952 -+#define	TPM_STS(l)			(0x0018 | ((l) << 12))
  46.953 -+#define	TPM_DATA_FIFO(l)		(0x0024 | ((l) << 12))
  46.954 -+
  46.955 -+#define	TPM_DID_VID(l)			(0x0F00 | ((l) << 12))
  46.956 -+#define	TPM_RID(l)			(0x0F04 | ((l) << 12))
  46.957 -+
  46.958 -+static LIST_HEAD(tis_chips);
  46.959 -+static DEFINE_SPINLOCK(tis_lock);
  46.960 -+
  46.961 -+static int check_locality(struct tpm_chip *chip, int l)
  46.962 -+{
  46.963 -+	if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
  46.964 -+	     (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
  46.965 -+	    (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
  46.966 -+		return chip->vendor.locality = l;
  46.967 -+
  46.968 -+	return -1;
  46.969 -+}
  46.970 -+
  46.971 -+static void release_locality(struct tpm_chip *chip, int l, int force)
  46.972 -+{
  46.973 -+	if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
  46.974 -+		      (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
  46.975 -+	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
  46.976 -+		iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
  46.977 -+			 chip->vendor.iobase + TPM_ACCESS(l));
  46.978 -+}
  46.979 -+
  46.980 -+static int request_locality(struct tpm_chip *chip, int l)
  46.981 -+{
  46.982 -+	unsigned long stop;
  46.983 -+	long rc;
  46.984 -+
  46.985 -+	if (check_locality(chip, l) >= 0)
  46.986 -+		return l;
  46.987 -+
  46.988 -+	iowrite8(TPM_ACCESS_REQUEST_USE,
  46.989 -+		 chip->vendor.iobase + TPM_ACCESS(l));
  46.990 -+
  46.991 -+	if (chip->vendor.irq) {
  46.992 -+		rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
  46.993 -+						      (check_locality
  46.994 -+						       (chip, l) >= 0),
  46.995 -+						      chip->vendor.timeout_a);
  46.996 -+		if (rc > 0)
  46.997 -+			return l;
  46.998 -+
  46.999 -+	} else {
 46.1000 -+		/* wait for burstcount */
 46.1001 -+		stop = jiffies + chip->vendor.timeout_a;
 46.1002 -+		do {
 46.1003 -+			if (check_locality(chip, l) >= 0)
 46.1004 -+				return l;
 46.1005 -+			msleep(TPM_TIMEOUT);
 46.1006 -+		}
 46.1007 -+		while (time_before(jiffies, stop));
 46.1008 -+	}
 46.1009 -+	return -1;
 46.1010 -+}
 46.1011 -+
 46.1012 -+static u8 tpm_tis_status(struct tpm_chip *chip)
 46.1013 -+{
 46.1014 -+	return ioread8(chip->vendor.iobase +
 46.1015 -+		       TPM_STS(chip->vendor.locality));
 46.1016 -+}
 46.1017 -+
 46.1018 -+static void tpm_tis_ready(struct tpm_chip *chip)
 46.1019 -+{
 46.1020 -+	/* this causes the current command to be aborted */
 46.1021 -+	iowrite8(TPM_STS_COMMAND_READY,
 46.1022 -+		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
 46.1023 -+}
 46.1024 -+
 46.1025 -+static int get_burstcount(struct tpm_chip *chip)
 46.1026 -+{
 46.1027 -+	unsigned long stop;
 46.1028 -+	int burstcnt;
 46.1029 -+
 46.1030 -+	/* wait for burstcount */
 46.1031 -+	/* which timeout value, spec has 2 answers (c & d) */
 46.1032 -+	stop = jiffies + chip->vendor.timeout_d;
 46.1033 -+	do {
 46.1034 -+		burstcnt = ioread8(chip->vendor.iobase +
 46.1035 -+				   TPM_STS(chip->vendor.locality) + 1);
 46.1036 -+		burstcnt += ioread8(chip->vendor.iobase +
 46.1037 -+				    TPM_STS(chip->vendor.locality) +
 46.1038 -+				    2) << 8;
 46.1039 -+		if (burstcnt)
 46.1040 -+			return burstcnt;
 46.1041 -+		msleep(TPM_TIMEOUT);
 46.1042 -+	} while (time_before(jiffies, stop));
 46.1043 -+	return -EBUSY;
 46.1044 -+}
 46.1045 -+
 46.1046 -+static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
 46.1047 -+			 wait_queue_head_t *queue)
 46.1048 -+{
 46.1049 -+	unsigned long stop;
 46.1050 -+	long rc;
 46.1051 -+	u8 status;
 46.1052 -+
 46.1053 -+	/* check current status */
 46.1054 -+	status = tpm_tis_status(chip);
 46.1055 -+	if ((status & mask) == mask)
 46.1056 -+		return 0;
 46.1057 -+
 46.1058 -+	if (chip->vendor.irq) {
 46.1059 -+		rc = wait_event_interruptible_timeout(*queue,
 46.1060 -+						      ((tpm_tis_status
 46.1061 -+							(chip) & mask) ==
 46.1062 -+						       mask), timeout);
 46.1063 -+		if (rc > 0)
 46.1064 -+			return 0;
 46.1065 -+	} else {
 46.1066 -+		stop = jiffies + timeout;
 46.1067 -+		do {
 46.1068 -+			msleep(TPM_TIMEOUT);
 46.1069 -+			status = tpm_tis_status(chip);
 46.1070 -+			if ((status & mask) == mask)
 46.1071 -+				return 0;
 46.1072 -+		} while (time_before(jiffies, stop));
 46.1073 -+	}
 46.1074 -+	return -ETIME;
 46.1075 -+}
 46.1076 -+
 46.1077 -+static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
 46.1078 -+{
 46.1079 -+	int size = 0, burstcnt;
 46.1080 -+	while (size < count &&
 46.1081 -+	       wait_for_stat(chip,
 46.1082 -+			     TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 46.1083 -+			     chip->vendor.timeout_c,
 46.1084 -+			     &chip->vendor.read_queue)
 46.1085 -+	       == 0) {
 46.1086 -+		burstcnt = get_burstcount(chip);
 46.1087 -+		for (; burstcnt > 0 && size < count; burstcnt--)
 46.1088 -+			buf[size++] = ioread8(chip->vendor.iobase +
 46.1089 -+					      TPM_DATA_FIFO(chip->vendor.
 46.1090 -+							    locality));
 46.1091 -+	}
 46.1092 -+	return size;
 46.1093 -+}
 46.1094 -+
 46.1095 -+static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 46.1096 -+{
 46.1097 -+	int size = 0;
 46.1098 -+	int expected, status;
 46.1099 -+
 46.1100 -+	if (count < TPM_HEADER_SIZE) {
 46.1101 -+		size = -EIO;
 46.1102 -+		goto out;
 46.1103 -+	}
 46.1104 -+
 46.1105 -+	/* read first 10 bytes, including tag, paramsize, and result */
 46.1106 -+	if ((size =
 46.1107 -+	     recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
 46.1108 -+		dev_err(chip->dev, "Unable to read header\n");
 46.1109 -+		goto out;
 46.1110 -+	}
 46.1111 -+
 46.1112 -+	expected = be32_to_cpu(*(__be32 *) (buf + 2));
 46.1113 -+	if (expected > count) {
 46.1114 -+		size = -EIO;
 46.1115 -+		goto out;
 46.1116 -+	}
 46.1117 -+
 46.1118 -+	if ((size +=
 46.1119 -+	     recv_data(chip, &buf[TPM_HEADER_SIZE],
 46.1120 -+		       expected - TPM_HEADER_SIZE)) < expected) {
 46.1121 -+		dev_err(chip->dev, "Unable to read remainder of result\n");
 46.1122 -+		size = -ETIME;
 46.1123 -+		goto out;
 46.1124 -+	}
 46.1125 -+
 46.1126 -+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
 46.1127 -+		      &chip->vendor.int_queue);
 46.1128 -+	status = tpm_tis_status(chip);
 46.1129 -+	if (status & TPM_STS_DATA_AVAIL) {	/* retry? */
 46.1130 -+		dev_err(chip->dev, "Error left over data\n");
 46.1131 -+		size = -EIO;
 46.1132 -+		goto out;
 46.1133 -+	}
 46.1134 -+
 46.1135 -+out:
 46.1136 -+	tpm_tis_ready(chip);
 46.1137 -+	release_locality(chip, chip->vendor.locality, 0);
 46.1138 -+	return size;
 46.1139 -+}
 46.1140 -+
 46.1141 -+/*
 46.1142 -+ * If interrupts are used (signaled by an irq set in the vendor structure)
 46.1143 -+ * tpm.c can skip polling for the data to be available as the interrupt is
 46.1144 -+ * waited for here
 46.1145 -+ */
 46.1146 -+static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
 46.1147 -+{
 46.1148 -+	int rc, status, burstcnt;
 46.1149 -+	size_t count = 0;
 46.1150 -+	u32 ordinal;
 46.1151 -+
 46.1152 -+	if (request_locality(chip, 0) < 0)
 46.1153 -+		return -EBUSY;
 46.1154 -+
 46.1155 -+	status = tpm_tis_status(chip);
 46.1156 -+	if ((status & TPM_STS_COMMAND_READY) == 0) {
 46.1157 -+		tpm_tis_ready(chip);
 46.1158 -+		if (wait_for_stat
 46.1159 -+		    (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
 46.1160 -+		     &chip->vendor.int_queue) < 0) {
 46.1161 -+			rc = -ETIME;
 46.1162 -+			goto out_err;
 46.1163 -+		}
 46.1164 -+	}
 46.1165 -+
 46.1166 -+	while (count < len - 1) {
 46.1167 -+		burstcnt = get_burstcount(chip);
 46.1168 -+		for (; burstcnt > 0 && count < len - 1; burstcnt--) {
 46.1169 -+			iowrite8(buf[count], chip->vendor.iobase +
 46.1170 -+				 TPM_DATA_FIFO(chip->vendor.locality));
 46.1171 -+			count++;
 46.1172 -+		}
 46.1173 -+
 46.1174 -+		wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
 46.1175 -+			      &chip->vendor.int_queue);
 46.1176 -+		status = tpm_tis_status(chip);
 46.1177 -+		if ((status & TPM_STS_DATA_EXPECT) == 0) {
 46.1178 -+			rc = -EIO;
 46.1179 -+			goto out_err;
 46.1180 -+		}
 46.1181 -+	}
 46.1182 -+
 46.1183 -+	/* write last byte */
 46.1184 -+	iowrite8(buf[count],
 46.1185 -+		 chip->vendor.iobase +
 46.1186 -+		 TPM_DATA_FIFO(chip->vendor.locality));
 46.1187 -+	wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
 46.1188 -+		      &chip->vendor.int_queue);
 46.1189 -+	status = tpm_tis_status(chip);
 46.1190 -+	if ((status & TPM_STS_DATA_EXPECT) != 0) {
 46.1191 -+		rc = -EIO;
 46.1192 -+		goto out_err;
 46.1193 -+	}
 46.1194 -+
 46.1195 -+	/* go and do it */
 46.1196 -+	iowrite8(TPM_STS_GO,
 46.1197 -+		 chip->vendor.iobase + TPM_STS(chip->vendor.locality));
 46.1198 -+
 46.1199 -+	if (chip->vendor.irq) {
 46.1200 -+		ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
 46.1201 -+		if (wait_for_stat
 46.1202 -+		    (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 46.1203 -+		     tpm_calc_ordinal_duration(chip, ordinal),
 46.1204 -+		     &chip->vendor.read_queue) < 0) {
 46.1205 -+			rc = -ETIME;
 46.1206 -+			goto out_err;
 46.1207 -+		}
 46.1208 -+	}
 46.1209 -+	return len;
 46.1210 -+out_err:
 46.1211 -+	tpm_tis_ready(chip);
 46.1212 -+	release_locality(chip, chip->vendor.locality, 0);
 46.1213 -+	return rc;
 46.1214 -+}
 46.1215 -+
 46.1216 -+static struct file_operations tis_ops = {
 46.1217 -+	.owner = THIS_MODULE,
 46.1218 -+	.llseek = no_llseek,
 46.1219 -+	.open = tpm_open,
 46.1220 -+	.read = tpm_read,
 46.1221 -+	.write = tpm_write,
 46.1222 -+	.release = tpm_release,
 46.1223 -+};
 46.1224 -+
 46.1225 -+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
 46.1226 -+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
 46.1227 -+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
 46.1228 -+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
 46.1229 -+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
 46.1230 -+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
 46.1231 -+		   NULL);
 46.1232 -+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
 46.1233 -+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
 46.1234 -+
 46.1235 -+static struct attribute *tis_attrs[] = {
 46.1236 -+	&dev_attr_pubek.attr,
 46.1237 -+	&dev_attr_pcrs.attr,
 46.1238 -+	&dev_attr_enabled.attr,
 46.1239 -+	&dev_attr_active.attr,
 46.1240 -+	&dev_attr_owned.attr,
 46.1241 -+	&dev_attr_temp_deactivated.attr,
 46.1242 -+	&dev_attr_caps.attr,
 46.1243 -+	&dev_attr_cancel.attr, NULL,
 46.1244 -+};
 46.1245 -+
 46.1246 -+static struct attribute_group tis_attr_grp = {
 46.1247 -+	.attrs = tis_attrs
 46.1248 -+};
 46.1249 -+
 46.1250 -+static struct tpm_vendor_specific tpm_tis = {
 46.1251 -+	.status = tpm_tis_status,
 46.1252 -+	.recv = tpm_tis_recv,
 46.1253 -+	.send = tpm_tis_send,
 46.1254 -+	.cancel = tpm_tis_ready,
 46.1255 -+	.req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 46.1256 -+	.req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
 46.1257 -+	.req_canceled = TPM_STS_COMMAND_READY,
 46.1258 -+	.attr_group = &tis_attr_grp,
 46.1259 -+	.miscdev = {
 46.1260 -+		    .fops = &tis_ops,},
 46.1261 -+};
 46.1262 -+
 46.1263 -+static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
 46.1264 -+{
 46.1265 -+	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
 46.1266 -+	u32 interrupt;
 46.1267 -+
 46.1268 -+	interrupt = ioread32(chip->vendor.iobase +
 46.1269 -+			     TPM_INT_STATUS(chip->vendor.locality));
 46.1270 -+
 46.1271 -+	if (interrupt == 0)
 46.1272 -+		return IRQ_NONE;
 46.1273 -+
 46.1274 -+	chip->vendor.irq = irq;
 46.1275 -+
 46.1276 -+	/* Clear interrupts handled with TPM_EOI */
 46.1277 -+	iowrite32(interrupt,
 46.1278 -+		  chip->vendor.iobase +
 46.1279 -+		  TPM_INT_STATUS(chip->vendor.locality));
 46.1280 -+	return IRQ_HANDLED;
 46.1281 -+}
 46.1282 -+
 46.1283 -+static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs *regs)
 46.1284 -+{
 46.1285 -+	struct tpm_chip *chip = (struct tpm_chip *) dev_id;
 46.1286 -+	u32 interrupt;
 46.1287 -+	int i;
 46.1288 -+
 46.1289 -+	interrupt = ioread32(chip->vendor.iobase +
 46.1290 -+			     TPM_INT_STATUS(chip->vendor.locality));
 46.1291 -+
 46.1292 -+	if (interrupt == 0)
 46.1293 -+		return IRQ_NONE;
 46.1294 -+
 46.1295 -+	if (interrupt & TPM_INTF_DATA_AVAIL_INT)
 46.1296 -+		wake_up_interruptible(&chip->vendor.read_queue);
 46.1297 -+	if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
 46.1298 -+		for (i = 0; i < 5; i++)
 46.1299 -+			if (check_locality(chip, i) >= 0)
 46.1300 -+				break;
 46.1301 -+	if (interrupt &
 46.1302 -+	    (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
 46.1303 -+	     TPM_INTF_CMD_READY_INT))
 46.1304 -+		wake_up_interruptible(&chip->vendor.int_queue);
 46.1305 -+
 46.1306 -+	/* Clear interrupts handled with TPM_EOI */
 46.1307 -+	iowrite32(interrupt,
 46.1308 -+		  chip->vendor.iobase +
 46.1309 -+		  TPM_INT_STATUS(chip->vendor.locality));
 46.1310 -+	return IRQ_HANDLED;
 46.1311 -+}
 46.1312 -+
 46.1313 -+static int interrupts = 1;
 46.1314 -+module_param(interrupts, bool, 0444);
 46.1315 -+MODULE_PARM_DESC(interrupts, "Enable interrupts");
 46.1316 -+
 46.1317 -+static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
 46.1318 -+				      const struct pnp_device_id *pnp_id)
 46.1319 -+{
 46.1320 -+	u32 vendor, intfcaps, intmask;
 46.1321 -+	int rc, i;
 46.1322 -+	unsigned long start, len;
 46.1323 -+	struct tpm_chip *chip;
 46.1324 -+
 46.1325 -+	start = pnp_mem_start(pnp_dev, 0);
 46.1326 -+	len = pnp_mem_len(pnp_dev, 0);
 46.1327 -+
 46.1328 -+	if (!start)
 46.1329 -+		start = TIS_MEM_BASE;
 46.1330 -+	if (!len)
 46.1331 -+		len = TIS_MEM_LEN;
 46.1332 -+
 46.1333 -+	if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
 46.1334 -+		return -ENODEV;
 46.1335 -+
 46.1336 -+	chip->vendor.iobase = ioremap(start, len);
 46.1337 -+	if (!chip->vendor.iobase) {
 46.1338 -+		rc = -EIO;
 46.1339 -+		goto out_err;
 46.1340 -+	}
 46.1341 -+
 46.1342 -+	vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
 46.1343 -+
 46.1344 -+	/* Default timeouts */
 46.1345 -+	chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
 46.1346 -+	chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
 46.1347 -+	chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
 46.1348 -+	chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
 46.1349 -+
 46.1350 -+	dev_info(&pnp_dev->dev,
 46.1351 -+		 "1.2 TPM (device-id 0x%X, rev-id %d)\n",
 46.1352 -+		 vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
 46.1353 -+
 46.1354 -+	/* Figure out the capabilities */
 46.1355 -+	intfcaps =
 46.1356 -+	    ioread32(chip->vendor.iobase +
 46.1357 -+		     TPM_INTF_CAPS(chip->vendor.locality));
 46.1358 -+	dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
 46.1359 -+		intfcaps);
 46.1360 -+	if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
 46.1361 -+		dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
 46.1362 -+	if (intfcaps & TPM_INTF_CMD_READY_INT)
 46.1363 -+		dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
 46.1364 -+	if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
 46.1365 -+		dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
 46.1366 -+	if (intfcaps & TPM_INTF_INT_EDGE_RISING)
 46.1367 -+		dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
 46.1368 -+	if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
 46.1369 -+		dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
 46.1370 -+	if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
 46.1371 -+		dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
 46.1372 -+	if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
 46.1373 -+		dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
 46.1374 -+	if (intfcaps & TPM_INTF_STS_VALID_INT)
 46.1375 -+		dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
 46.1376 -+	if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
 46.1377 -+		dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
 46.1378 -+
 46.1379 -+	if (request_locality(chip, 0) != 0) {
 46.1380 -+		rc = -ENODEV;
 46.1381 -+		goto out_err;
 46.1382 -+	}
 46.1383 -+
 46.1384 -+	/* INTERRUPT Setup */
 46.1385 -+	init_waitqueue_head(&chip->vendor.read_queue);
 46.1386 -+	init_waitqueue_head(&chip->vendor.int_queue);
 46.1387 -+
 46.1388 -+	intmask =
 46.1389 -+	    ioread32(chip->vendor.iobase +
 46.1390 -+		     TPM_INT_ENABLE(chip->vendor.locality));
 46.1391 -+
 46.1392 -+	intmask |= TPM_INTF_CMD_READY_INT
 46.1393 -+	    | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
 46.1394 -+	    | TPM_INTF_STS_VALID_INT;
 46.1395 -+
 46.1396 -+	iowrite32(intmask,
 46.1397 -+		  chip->vendor.iobase +
 46.1398 -+		  TPM_INT_ENABLE(chip->vendor.locality));
 46.1399 -+	if (interrupts) {
 46.1400 -+		chip->vendor.irq =
 46.1401 -+		    ioread8(chip->vendor.iobase +
 46.1402 -+			    TPM_INT_VECTOR(chip->vendor.locality));
 46.1403 -+
 46.1404 -+		for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
 46.1405 -+			iowrite8(i, chip->vendor.iobase +
 46.1406 -+				    TPM_INT_VECTOR(chip->vendor.locality));
 46.1407 -+			if (request_irq
 46.1408 -+			    (i, tis_int_probe, SA_SHIRQ,
 46.1409 -+			     chip->vendor.miscdev.name, chip) != 0) {
 46.1410 -+				dev_info(chip->dev,
 46.1411 -+					 "Unable to request irq: %d for probe\n",
 46.1412 -+					 i);
 46.1413 -+				continue;
 46.1414 -+			}
 46.1415 -+
 46.1416 -+			/* Clear all existing */
 46.1417 -+			iowrite32(ioread32
 46.1418 -+				  (chip->vendor.iobase +
 46.1419 -+				   TPM_INT_STATUS(chip->vendor.locality)),
 46.1420 -+				  chip->vendor.iobase +
 46.1421 -+				  TPM_INT_STATUS(chip->vendor.locality));
 46.1422 -+
 46.1423 -+			/* Turn on */
 46.1424 -+			iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
 46.1425 -+				  chip->vendor.iobase +
 46.1426 -+				  TPM_INT_ENABLE(chip->vendor.locality));
 46.1427 -+
 46.1428 -+			/* Generate Interrupts */
 46.1429 -+			tpm_gen_interrupt(chip);
 46.1430 -+
 46.1431 -+			/* Turn off */
 46.1432 -+			iowrite32(intmask,
 46.1433 -+				  chip->vendor.iobase +
 46.1434 -+				  TPM_INT_ENABLE(chip->vendor.locality));
 46.1435 -+			free_irq(i, chip);
 46.1436 -+		}
 46.1437 -+	}
 46.1438 -+	if (chip->vendor.irq) {
 46.1439 -+		iowrite8(chip->vendor.irq,
 46.1440 -+			 chip->vendor.iobase +
 46.1441 -+			 TPM_INT_VECTOR(chip->vendor.locality));
 46.1442 -+		if (request_irq
 46.1443 -+		    (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
 46.1444 -+		     chip->vendor.miscdev.name, chip) != 0) {
 46.1445 -+			dev_info(chip->dev,
 46.1446 -+				 "Unable to request irq: %d for use\n",
 46.1447 -+				 chip->vendor.irq);
 46.1448 -+			chip->vendor.irq = 0;
 46.1449 -+		} else {
 46.1450 -+			/* Clear all existing */
 46.1451 -+			iowrite32(ioread32
 46.1452 -+				  (chip->vendor.iobase +
 46.1453 -+				   TPM_INT_STATUS(chip->vendor.locality)),
 46.1454 -+				  chip->vendor.iobase +
 46.1455 -+				  TPM_INT_STATUS(chip->vendor.locality));
 46.1456 -+
 46.1457 -+			/* Turn on */
 46.1458 -+			iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
 46.1459 -+				  chip->vendor.iobase +
 46.1460 -+				  TPM_INT_ENABLE(chip->vendor.locality));
 46.1461 -+		}
 46.1462 -+	}
 46.1463 -+
 46.1464 -+	INIT_LIST_HEAD(&chip->vendor.list);
 46.1465 -+	spin_lock(&tis_lock);
 46.1466 -+	list_add(&chip->vendor.list, &tis_chips);
 46.1467 -+	spin_unlock(&tis_lock);
 46.1468 -+
 46.1469 -+	tpm_get_timeouts(chip);
 46.1470 -+	tpm_continue_selftest(chip);
 46.1471 -+
 46.1472 -+	return 0;
 46.1473 -+out_err:
 46.1474 -+	if (chip->vendor.iobase)
 46.1475 -+		iounmap(chip->vendor.iobase);
 46.1476 -+	tpm_remove_hardware(chip->dev);
 46.1477 -+	return rc;
 46.1478 -+}
 46.1479 -+
 46.1480 -+static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
 46.1481 -+{
 46.1482 -+	return tpm_pm_suspend(&dev->dev, msg);
 46.1483 -+}
 46.1484 -+
 46.1485 -+static int tpm_tis_pnp_resume(struct pnp_dev *dev)
 46.1486 -+{
 46.1487 -+	return tpm_pm_resume(&dev->dev);
 46.1488 -+}
 46.1489 -+
 46.1490 -+static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
 46.1491 -+	{"PNP0C31", 0},		/* TPM */
 46.1492 -+	{"ATM1200", 0},		/* Atmel */
 46.1493 -+	{"IFX0102", 0},		/* Infineon */
 46.1494 -+	{"BCM0101", 0},		/* Broadcom */
 46.1495 -+	{"NSC1200", 0},		/* National */
 46.1496 -+	/* Add new here */
 46.1497 -+	{"", 0},		/* User Specified */
 46.1498 -+	{"", 0}			/* Terminator */
 46.1499 -+};
 46.1500 -+
 46.1501 -+static struct pnp_driver tis_pnp_driver = {
 46.1502 -+	.name = "tpm_tis",
 46.1503 -+	.id_table = tpm_pnp_tbl,
 46.1504 -+	.probe = tpm_tis_pnp_init,
 46.1505 -+	.suspend = tpm_tis_pnp_suspend,
 46.1506 -+	.resume = tpm_tis_pnp_resume,
 46.1507 -+};
 46.1508 -+
 46.1509 -+#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
 46.1510 -+module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
 46.1511 -+		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 46.1512 -+MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
 46.1513 -+
 46.1514 -+static int __init init_tis(void)
 46.1515 -+{
 46.1516 -+	return pnp_register_driver(&tis_pnp_driver);
 46.1517 -+}
 46.1518 -+
 46.1519 -+static void __exit cleanup_tis(void)
 46.1520 -+{
 46.1521 -+	struct tpm_vendor_specific *i, *j;
 46.1522 -+	struct tpm_chip *chip;
 46.1523 -+	spin_lock(&tis_lock);
 46.1524 -+	list_for_each_entry_safe(i, j, &tis_chips, list) {
 46.1525 -+		chip = to_tpm_chip(i);
 46.1526 -+		iowrite32(~TPM_GLOBAL_INT_ENABLE &
 46.1527 -+			  ioread32(chip->vendor.iobase +
 46.1528 -+				   TPM_INT_ENABLE(chip->vendor.
 46.1529 -+						  locality)),
 46.1530 -+			  chip->vendor.iobase +
 46.1531 -+			  TPM_INT_ENABLE(chip->vendor.locality));
 46.1532 -+		release_locality(chip, chip->vendor.locality, 1);
 46.1533 -+		if (chip->vendor.irq)
 46.1534 -+			free_irq(chip->vendor.irq, chip);
 46.1535 -+		iounmap(i->iobase);
 46.1536 -+		list_del(&i->list);
 46.1537 -+		tpm_remove_hardware(chip->dev);
 46.1538 -+	}
 46.1539 -+	spin_unlock(&tis_lock);
 46.1540 -+	pnp_unregister_driver(&tis_pnp_driver);
 46.1541 -+}
 46.1542 -+
 46.1543 -+module_init(init_tis);
 46.1544 -+module_exit(cleanup_tis);
 46.1545 -+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
 46.1546 -+MODULE_DESCRIPTION("TPM Driver");
 46.1547 -+MODULE_VERSION("2.0");
 46.1548 -+MODULE_LICENSE("GPL");
 46.1549 -
    47.1 --- a/patches/linux-2.6.16.13/x86-elfnote-as-preprocessor-macro.patch	Thu Sep 21 15:35:45 2006 -0600
    47.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.3 @@ -1,44 +0,0 @@
    47.4 -
    47.5 -diff -r 4b7cd997c08f include/linux/elfnote.h
    47.6 ---- a/include/linux/elfnote.h	Wed Aug 23 11:48:46 2006 +0100
    47.7 -+++ b/include/linux/elfnote.h	Wed Aug 23 12:44:27 2006 +0100
    47.8 -@@ -31,22 +31,24 @@
    47.9 - /*
   47.10 -  * Generate a structure with the same shape as Elf{32,64}_Nhdr (which
   47.11 -  * turn out to be the same size and shape), followed by the name and
   47.12 -- * desc data with appropriate padding.  The 'desc' argument includes
   47.13 -- * the assembler pseudo op defining the type of the data: .asciz
   47.14 -- * "hello, world"
   47.15 -+ * desc data with appropriate padding.  The 'desctype' argument is the
   47.16 -+ * assembler pseudo op defining the type of the data e.g. .asciz while
   47.17 -+ * 'descdata' is the data itself e.g.  "hello, world".
   47.18 -+ *
   47.19 -+ * e.g. ELFNOTE(XYZCo, 42, .asciz, "forty-two")
   47.20 -+ *      ELFNOTE(XYZCo, 12, .long, 0xdeadbeef)
   47.21 -  */
   47.22 --.macro ELFNOTE name type desc:vararg
   47.23 --.pushsection ".note.\name"
   47.24 --  .align 4
   47.25 --  .long 2f - 1f			/* namesz */
   47.26 --  .long 4f - 3f			/* descsz */
   47.27 --  .long \type
   47.28 --1:.asciz "\name"
   47.29 --2:.align 4
   47.30 --3:\desc
   47.31 --4:.align 4
   47.32 --.popsection
   47.33 --.endm
   47.34 -+#define ELFNOTE(name, type, desctype, descdata)	\
   47.35 -+.pushsection .note.name			;	\
   47.36 -+  .align 4				;	\
   47.37 -+  .long 2f - 1f		/* namesz */	;	\
   47.38 -+  .long 4f - 3f		/* descsz */	;	\
   47.39 -+  .long type				;	\
   47.40 -+1:.asciz "name"				;	\
   47.41 -+2:.align 4				;	\
   47.42 -+3:desctype descdata			;	\
   47.43 -+4:.align 4				;	\
   47.44 -+.popsection				;
   47.45 - #else	/* !__ASSEMBLER__ */
   47.46 - #include <linux/elf.h>
   47.47 - /*
    48.1 --- a/patches/linux-2.6.16.13/x86-increase-interrupt-vector-range.patch	Thu Sep 21 15:35:45 2006 -0600
    48.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.3 @@ -1,89 +0,0 @@
    48.4 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/entry.S ./arch/i386/kernel/entry.S
    48.5 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/entry.S	2006-05-02 22:38:44.000000000 +0100
    48.6 -+++ ./arch/i386/kernel/entry.S	2006-05-04 17:41:49.000000000 +0100
    48.7 -@@ -406,7 +406,7 @@ vector=0
    48.8 - ENTRY(irq_entries_start)
    48.9 - .rept NR_IRQS
   48.10 - 	ALIGN
   48.11 --1:	pushl $vector-256
   48.12 -+1:	pushl $~(vector)
   48.13 - 	jmp common_interrupt
   48.14 - .data
   48.15 - 	.long 1b
   48.16 -@@ -423,7 +423,7 @@ common_interrupt:
   48.17 - 
   48.18 - #define BUILD_INTERRUPT(name, nr)	\
   48.19 - ENTRY(name)				\
   48.20 --	pushl $nr-256;			\
   48.21 -+	pushl $~(nr);			\
   48.22 - 	SAVE_ALL			\
   48.23 - 	movl %esp,%eax;			\
   48.24 - 	call smp_/**/name;		\
   48.25 -diff -pruN ../pristine-linux-2.6.16.13/arch/i386/kernel/irq.c ./arch/i386/kernel/irq.c
   48.26 ---- ../pristine-linux-2.6.16.13/arch/i386/kernel/irq.c	2006-05-02 22:38:44.000000000 +0100
   48.27 -+++ ./arch/i386/kernel/irq.c	2006-05-04 17:41:49.000000000 +0100
   48.28 -@@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPU
   48.29 -  */
   48.30 - fastcall unsigned int do_IRQ(struct pt_regs *regs)
   48.31 - {	
   48.32 --	/* high bits used in ret_from_ code */
   48.33 --	int irq = regs->orig_eax & 0xff;
   48.34 -+	/* high bit used in ret_from_ code */
   48.35 -+	int irq = ~regs->orig_eax;
   48.36 - #ifdef CONFIG_4KSTACKS
   48.37 - 	union irq_ctx *curctx, *irqctx;
   48.38 - 	u32 *isp;
   48.39 -diff -pruN ../pristine-linux-2.6.16.13/arch/x86_64/kernel/entry.S ./arch/x86_64/kernel/entry.S
   48.40 ---- ../pristine-linux-2.6.16.13/arch/x86_64/kernel/entry.S	2006-05-02 22:38:44.000000000 +0100
   48.41 -+++ ./arch/x86_64/kernel/entry.S	2006-05-04 17:41:49.000000000 +0100
   48.42 -@@ -601,7 +601,7 @@ retint_kernel:	
   48.43 -  */		
   48.44 - 	.macro apicinterrupt num,func
   48.45 - 	INTR_FRAME
   48.46 --	pushq $\num-256
   48.47 -+	pushq $~(\num)
   48.48 - 	CFI_ADJUST_CFA_OFFSET 8
   48.49 - 	interrupt \func
   48.50 - 	jmp ret_from_intr
   48.51 -diff -pruN ../pristine-linux-2.6.16.13/arch/x86_64/kernel/irq.c ./arch/x86_64/kernel/irq.c
   48.52 ---- ../pristine-linux-2.6.16.13/arch/x86_64/kernel/irq.c	2006-05-02 22:38:44.000000000 +0100
   48.53 -+++ ./arch/x86_64/kernel/irq.c	2006-05-04 17:41:49.000000000 +0100
   48.54 -@@ -96,8 +96,8 @@ skip:
   48.55 -  */
   48.56 - asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
   48.57 - {	
   48.58 --	/* high bits used in ret_from_ code  */
   48.59 --	unsigned irq = regs->orig_rax & 0xff;
   48.60 -+	/* high bit used in ret_from_ code  */
   48.61 -+	unsigned irq = ~regs->orig_rax;
   48.62 - 
   48.63 - 	exit_idle();
   48.64 - 	irq_enter();
   48.65 -diff -pruN ../pristine-linux-2.6.16.13/arch/x86_64/kernel/smp.c ./arch/x86_64/kernel/smp.c
   48.66 ---- ../pristine-linux-2.6.16.13/arch/x86_64/kernel/smp.c	2006-05-02 22:38:44.000000000 +0100
   48.67 -+++ ./arch/x86_64/kernel/smp.c	2006-05-04 17:41:49.000000000 +0100
   48.68 -@@ -135,10 +135,10 @@ asmlinkage void smp_invalidate_interrupt
   48.69 - 
   48.70 - 	cpu = smp_processor_id();
   48.71 - 	/*
   48.72 --	 * orig_rax contains the interrupt vector - 256.
   48.73 -+	 * orig_rax contains the negated interrupt vector.
   48.74 - 	 * Use that to determine where the sender put the data.
   48.75 - 	 */
   48.76 --	sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
   48.77 -+	sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START;
   48.78 - 	f = &per_cpu(flush_state, sender);
   48.79 - 
   48.80 - 	if (!cpu_isset(cpu, f->flush_cpumask))
   48.81 -diff -pruN ../pristine-linux-2.6.16.13/include/asm-x86_64/hw_irq.h ./include/asm-x86_64/hw_irq.h
   48.82 ---- ../pristine-linux-2.6.16.13/include/asm-x86_64/hw_irq.h	2006-05-02 22:38:44.000000000 +0100
   48.83 -+++ ./include/asm-x86_64/hw_irq.h	2006-05-04 17:41:49.000000000 +0100
   48.84 -@@ -127,7 +127,7 @@ asmlinkage void IRQ_NAME(nr); \
   48.85 - __asm__( \
   48.86 - "\n.p2align\n" \
   48.87 - "IRQ" #nr "_interrupt:\n\t" \
   48.88 --	"push $" #nr "-256 ; " \
   48.89 -+	"push $~(" #nr ") ; " \
   48.90 - 	"jmp common_interrupt");
   48.91 - 
   48.92 - #if defined(CONFIG_X86_IO_APIC)
    49.1 --- a/patches/linux-2.6.16.13/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch	Thu Sep 21 15:35:45 2006 -0600
    49.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.3 @@ -1,174 +0,0 @@
    49.4 -Taken from 2.6.18-rc4-mm1.
    49.5 -
    49.6 -From: Jeremy Fitzhardinge <jeremy@xensource.com>
    49.7 -
    49.8 -This patch will pack any .note.* section into a PT_NOTE segment in the output
    49.9 -file.
   49.10 -
   49.11 -To do this, we tell ld that we need a PT_NOTE segment.  This requires us to
   49.12 -start explicitly mapping sections to segments, so we also need to explicitly
   49.13 -create PT_LOAD segments for text and data, and map the sections to them
   49.14 -appropriately.  Fortunately, each section will default to its previous
   49.15 -section's segment, so it doesn't take many changes to vmlinux.lds.S.
   49.16 -
   49.17 -This only changes i386 for now, but I presume the corresponding changes for
   49.18 -other architectures will be as simple.
   49.19 -
   49.20 -This change also adds <linux/elfnote.h>, which defines C and Assembler macros
   49.21 -for actually creating ELF notes.
   49.22 -
   49.23 -Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
   49.24 -Cc: Eric W. Biederman <ebiederm@xmission.com>
   49.25 -Cc: Hollis Blanchard <hollisb@us.ibm.com>
   49.26 -Signed-off-by: Andrew Morton <akpm@osdl.org>
   49.27 ----
   49.28 -
   49.29 - arch/i386/kernel/vmlinux.lds.S    |   12 +++
   49.30 - include/asm-generic/vmlinux.lds.h |    3 
   49.31 - include/linux/elfnote.h           |   88 ++++++++++++++++++++++++++++
   49.32 - 3 files changed, 101 insertions(+), 2 deletions(-)
   49.33 -
   49.34 -diff -puN arch/i386/kernel/vmlinux.lds.S~x86-put-note-sections-into-a-pt_note-segment-in-vmlinux arch/i386/kernel/vmlinux.lds.S
   49.35 ---- a/arch/i386/kernel/vmlinux.lds.S~x86-put-note-sections-into-a-pt_note-segment-in-vmlinux
   49.36 -+++ a/arch/i386/kernel/vmlinux.lds.S
   49.37 -@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386"
   49.38 - OUTPUT_ARCH(i386)
   49.39 - ENTRY(phys_startup_32)
   49.40 - jiffies = jiffies_64;
   49.41 -+
   49.42 -+PHDRS {
   49.43 -+	text PT_LOAD FLAGS(5);	/* R_E */
   49.44 -+	data PT_LOAD FLAGS(7);	/* RWE */
   49.45 -+	note PT_NOTE FLAGS(4);	/* R__ */
   49.46 -+}
   49.47 - SECTIONS
   49.48 - {
   49.49 -   . = __KERNEL_START;
   49.50 -@@ -26,7 +32,7 @@ SECTIONS
   49.51 - 	KPROBES_TEXT
   49.52 - 	*(.fixup)
   49.53 - 	*(.gnu.warning)
   49.54 --	} = 0x9090
   49.55 -+	} :text = 0x9090
   49.56 - 
   49.57 -   _etext = .;			/* End of text section */
   49.58 - 
   49.59 -@@ -50,7 +56,7 @@ SECTIONS
   49.60 -   .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
   49.61 - 	*(.data)
   49.62 - 	CONSTRUCTORS
   49.63 --	}
   49.64 -+	} :data
   49.65 - 
   49.66 -   . = ALIGN(4096);
   49.67 -   __nosave_begin = .;
   49.68 -@@ -186,4 +192,6 @@ SECTIONS
   49.69 -   STABS_DEBUG
   49.70 - 
   49.71 -   DWARF_DEBUG
   49.72 -+
   49.73 -+  NOTES
   49.74 - }
   49.75 -diff -puN include/asm-generic/vmlinux.lds.h~x86-put-note-sections-into-a-pt_note-segment-in-vmlinux include/asm-generic/vmlinux.lds.h
   49.76 ---- a/include/asm-generic/vmlinux.lds.h~x86-put-note-sections-into-a-pt_note-segment-in-vmlinux
   49.77 -+++ a/include/asm-generic/vmlinux.lds.h
   49.78 -@@ -194,3 +194,6 @@
   49.79 - 		.stab.index 0 : { *(.stab.index) }			\
   49.80 - 		.stab.indexstr 0 : { *(.stab.indexstr) }		\
   49.81 - 		.comment 0 : { *(.comment) }
   49.82 -+
   49.83 -+#define NOTES								\
   49.84 -+		.notes : { *(.note.*) } :note
   49.85 -diff -puN /dev/null include/linux/elfnote.h
   49.86 ---- /dev/null
   49.87 -+++ a/include/linux/elfnote.h
   49.88 -@@ -0,0 +1,88 @@
   49.89 -+#ifndef _LINUX_ELFNOTE_H
   49.90 -+#define _LINUX_ELFNOTE_H
   49.91 -+/*
   49.92 -+ * Helper macros to generate ELF Note structures, which are put into a
   49.93 -+ * PT_NOTE segment of the final vmlinux image.  These are useful for
   49.94 -+ * including name-value pairs of metadata into the kernel binary (or
   49.95 -+ * modules?) for use by external programs.
   49.96 -+ *
   49.97 -+ * Each note has three parts: a name, a type and a desc.  The name is
   49.98 -+ * intended to distinguish the note's originator, so it would be a
   49.99 -+ * company, project, subsystem, etc; it must be in a suitable form for
  49.100 -+ * use in a section name.  The type is an integer which is used to tag
  49.101 -+ * the data, and is considered to be within the "name" namespace (so
  49.102 -+ * "FooCo"'s type 42 is distinct from "BarProj"'s type 42).  The
  49.103 -+ * "desc" field is the actual data.  There are no constraints on the
  49.104 -+ * desc field's contents, though typically they're fairly small.
  49.105 -+ *
  49.106 -+ * All notes from a given NAME are put into a section named
  49.107 -+ * .note.NAME.  When the kernel image is finally linked, all the notes
  49.108 -+ * are packed into a single .notes section, which is mapped into the
  49.109 -+ * PT_NOTE segment.  Because notes for a given name are grouped into
  49.110 -+ * the same section, they'll all be adjacent the output file.
  49.111 -+ *
  49.112 -+ * This file defines macros for both C and assembler use.  Their
  49.113 -+ * syntax is slightly different, but they're semantically similar.
  49.114 -+ *
  49.115 -+ * See the ELF specification for more detail about ELF notes.
  49.116 -+ */
  49.117 -+
  49.118 -+#ifdef __ASSEMBLER__
  49.119 -+/*
  49.120 -+ * Generate a structure with the same shape as Elf{32,64}_Nhdr (which
  49.121 -+ * turn out to be the same size and shape), followed by the name and
  49.122 -+ * desc data with appropriate padding.  The 'desc' argument includes
  49.123 -+ * the assembler pseudo op defining the type of the data: .asciz
  49.124 -+ * "hello, world"
  49.125 -+ */
  49.126 -+.macro ELFNOTE name type desc:vararg
  49.127 -+.pushsection ".note.\name"
  49.128 -+  .align 4
  49.129 -+  .long 2f - 1f			/* namesz */
  49.130 -+  .long 4f - 3f			/* descsz */
  49.131 -+  .long \type
  49.132 -+1:.asciz "\name"
  49.133 -+2:.align 4
  49.134 -+3:\desc
  49.135 -+4:.align 4
  49.136 -+.popsection
  49.137 -+.endm
  49.138 -+#else	/* !__ASSEMBLER__ */
  49.139 -+#include <linux/elf.h>
  49.140 -+/*
  49.141 -+ * Use an anonymous structure which matches the shape of
  49.142 -+ * Elf{32,64}_Nhdr, but includes the name and desc data.  The size and
  49.143 -+ * type of name and desc depend on the macro arguments.  "name" must
  49.144 -+ * be a literal string, and "desc" must be passed by value.  You may
  49.145 -+ * only define one note per line, since __LINE__ is used to generate
  49.146 -+ * unique symbols.
  49.147 -+ */
  49.148 -+#define _ELFNOTE_PASTE(a,b)	a##b
  49.149 -+#define _ELFNOTE(size, name, unique, type, desc)			\
  49.150 -+	static const struct {						\
  49.151 -+		struct elf##size##_note _nhdr;				\
  49.152 -+		unsigned char _name[sizeof(name)]			\
  49.153 -+		__attribute__((aligned(sizeof(Elf##size##_Word))));	\
  49.154 -+		typeof(desc) _desc					\
  49.155 -+			     __attribute__((aligned(sizeof(Elf##size##_Word)))); \
  49.156 -+	} _ELFNOTE_PASTE(_note_, unique)				\
  49.157 -+		__attribute_used__					\
  49.158 -+		__attribute__((section(".note." name),			\
  49.159 -+			       aligned(sizeof(Elf##size##_Word)),	\
  49.160 -+			       unused)) = {				\
  49.161 -+		{							\
  49.162 -+			sizeof(name),					\
  49.163 -+			sizeof(desc),					\
  49.164 -+			type,						\
  49.165 -+		},							\
  49.166 -+		name,							\
  49.167 -+		desc							\
  49.168 -+	}
  49.169 -+#define ELFNOTE(size, name, type, desc)		\
  49.170 -+	_ELFNOTE(size, name, __LINE__, type, desc)
  49.171 -+
  49.172 -+#define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc)
  49.173 -+#define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc)
  49.174 -+#endif	/* __ASSEMBLER__ */
  49.175 -+
  49.176 -+#endif /* _LINUX_ELFNOTE_H */
  49.177 -_
    50.1 --- a/patches/linux-2.6.16.13/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch	Thu Sep 21 15:35:45 2006 -0600
    50.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.3 @@ -1,83 +0,0 @@
    50.4 ---- a/arch/x86_64/kernel/vmlinux.lds.S
    50.5 -+++ b/arch/x86_64/kernel/vmlinux.lds.S
    50.6 -@@ -13,6 +13,12 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86
    50.7 - OUTPUT_ARCH(i386:x86-64)
    50.8 - ENTRY(phys_startup_64)
    50.9 - jiffies_64 = jiffies;
   50.10 -+PHDRS {
   50.11 -+	text PT_LOAD FLAGS(5);	/* R_E */
   50.12 -+	data PT_LOAD FLAGS(7);	/* RWE */
   50.13 -+	user PT_LOAD FLAGS(7);	/* RWE */
   50.14 -+	note PT_NOTE FLAGS(4);	/* R__ */
   50.15 -+}
   50.16 - SECTIONS
   50.17 - {
   50.18 -   . = __START_KERNEL;
   50.19 -@@ -31,7 +37,7 @@ SECTIONS
   50.20 - 	KPROBES_TEXT
   50.21 - 	*(.fixup)
   50.22 - 	*(.gnu.warning)
   50.23 --	} = 0x9090
   50.24 -+	} :text = 0x9090
   50.25 -   				/* out-of-line lock text */
   50.26 -   .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET) { *(.text.lock) }
   50.27 - 
   50.28 -@@ -57,17 +63,10 @@ #endif
   50.29 -   .data : AT(ADDR(.data) - LOAD_OFFSET) {
   50.30 - 	*(.data)
   50.31 - 	CONSTRUCTORS
   50.32 --	}
   50.33 -+	} :data
   50.34 - 
   50.35 -   _edata = .;			/* End of data section */
   50.36 - 
   50.37 --  __bss_start = .;		/* BSS */
   50.38 --  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
   50.39 --	*(.bss.page_aligned)	
   50.40 --	*(.bss)
   50.41 --	}
   50.42 --  __bss_stop = .;
   50.43 --
   50.44 -   . = ALIGN(PAGE_SIZE);
   50.45 -   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   50.46 -   .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
   50.47 -@@ -89,7 +88,7 @@ #define VVIRT_OFFSET (VSYSCALL_ADDR - VS
   50.48 - #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
   50.49 - 
   50.50 -   . = VSYSCALL_ADDR;
   50.51 --  .vsyscall_0 :	 AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) }
   50.52 -+  .vsyscall_0 :	 AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
   50.53 -   __vsyscall_0 = VSYSCALL_VIRT_ADDR;
   50.54 - 
   50.55 -   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
   50.56 -@@ -132,7 +131,7 @@ #undef VVIRT
   50.57 -   . = ALIGN(8192);		/* init_task */
   50.58 -   .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
   50.59 - 	*(.data.init_task)
   50.60 --  }
   50.61 -+  } :data
   50.62 - 
   50.63 -   . = ALIGN(4096);
   50.64 -   .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
   50.65 -@@ -222,6 +221,14 @@ SECTIONS
   50.66 -   . = ALIGN(4096);
   50.67 -   __nosave_end = .;
   50.68 - 
   50.69 -+  __bss_start = .;		/* BSS */
   50.70 -+  . = ALIGN(4096);
   50.71 -+  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
   50.72 -+	*(.bss.page_aligned)
   50.73 -+	*(.bss)
   50.74 -+	}
   50.75 -+  __bss_stop = .;
   50.76 -+
   50.77 -   _end = . ;
   50.78 - 
   50.79 -   /* Sections to be discarded */
   50.80 -@@ -235,4 +242,6 @@ #endif
   50.81 -   STABS_DEBUG
   50.82 - 
   50.83 -   DWARF_DEBUG
   50.84 -+
   50.85 -+  NOTES
   50.86 - }
    51.1 --- a/patches/linux-2.6.16.13/xen-hotplug.patch	Thu Sep 21 15:35:45 2006 -0600
    51.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.3 @@ -1,11 +0,0 @@
    51.4 ---- ../pristine-linux-2.6.16.13/fs/proc/proc_misc.c	2006-05-02 22:38:44.000000000 +0100
    51.5 -+++ ./fs/proc/proc_misc.c	2006-05-22 15:29:34.000000000 +0100
    51.6 -@@ -433,7 +433,7 @@ static int show_stat(struct seq_file *p,
    51.7 - 		(unsigned long long)cputime64_to_clock_t(irq),
    51.8 - 		(unsigned long long)cputime64_to_clock_t(softirq),
    51.9 - 		(unsigned long long)cputime64_to_clock_t(steal));
   51.10 --	for_each_online_cpu(i) {
   51.11 -+	for_each_cpu(i) {
   51.12 - 
   51.13 - 		/* Copy values here to work around gcc-2.95.3, gcc-2.96 */
   51.14 - 		user = kstat_cpu(i).cpustat.user;
    52.1 --- a/patches/linux-2.6.16.13/xenoprof-generic.patch	Thu Sep 21 15:35:45 2006 -0600
    52.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.3 @@ -1,615 +0,0 @@
    52.4 -diff -Naur orig/drivers/oprofile/buffer_sync.c new/drivers/oprofile/buffer_sync.c
    52.5 ---- orig/drivers/oprofile/buffer_sync.c	2006-05-02 14:38:44.000000000 -0700
    52.6 -+++ new/drivers/oprofile/buffer_sync.c	2006-07-06 18:19:05.000000000 -0700
    52.7 -@@ -6,6 +6,10 @@
    52.8 -  *
    52.9 -  * @author John Levon <levon@movementarian.org>
   52.10 -  *
   52.11 -+ * Modified by Aravind Menon for Xen
   52.12 -+ * These modifications are:
   52.13 -+ * Copyright (C) 2005 Hewlett-Packard Co.
   52.14 -+ *
   52.15 -  * This is the core of the buffer management. Each
   52.16 -  * CPU buffer is processed and entered into the
   52.17 -  * global event buffer. Such processing is necessary
   52.18 -@@ -275,15 +279,31 @@
   52.19 - 	last_cookie = INVALID_COOKIE;
   52.20 - }
   52.21 - 
   52.22 --static void add_kernel_ctx_switch(unsigned int in_kernel)
   52.23 -+static void add_cpu_mode_switch(unsigned int cpu_mode)
   52.24 - {
   52.25 - 	add_event_entry(ESCAPE_CODE);
   52.26 --	if (in_kernel)
   52.27 --		add_event_entry(KERNEL_ENTER_SWITCH_CODE); 
   52.28 --	else
   52.29 --		add_event_entry(KERNEL_EXIT_SWITCH_CODE); 
   52.30 -+	switch (cpu_mode) {
   52.31 -+	case CPU_MODE_USER:
   52.32 -+		add_event_entry(USER_ENTER_SWITCH_CODE);
   52.33 -+		break;
   52.34 -+	case CPU_MODE_KERNEL:
   52.35 -+		add_event_entry(KERNEL_ENTER_SWITCH_CODE);
   52.36 -+		break;
   52.37 -+	case CPU_MODE_XEN:
   52.38 -+		add_event_entry(XEN_ENTER_SWITCH_CODE);
   52.39 -+	  	break;
   52.40 -+	default:
   52.41 -+		break;
   52.42 -+	}
   52.43 - }
   52.44 -- 
   52.45 -+
   52.46 -+static void add_domain_switch(unsigned long domain_id)
   52.47 -+{
   52.48 -+	add_event_entry(ESCAPE_CODE);
   52.49 -+	add_event_entry(DOMAIN_SWITCH_CODE);
   52.50 -+	add_event_entry(domain_id);
   52.51 -+}
   52.52 -+
   52.53 - static void
   52.54 - add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
   52.55 - {
   52.56 -@@ -348,9 +368,9 @@
   52.57 -  * for later lookup from userspace.
   52.58 -  */
   52.59 - static int
   52.60 --add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
   52.61 -+add_sample(struct mm_struct * mm, struct op_sample * s, int cpu_mode)
   52.62 - {
   52.63 --	if (in_kernel) {
   52.64 -+	if (cpu_mode >= CPU_MODE_KERNEL) {
   52.65 - 		add_sample_entry(s->eip, s->event);
   52.66 - 		return 1;
   52.67 - 	} else if (mm) {
   52.68 -@@ -496,10 +516,11 @@
   52.69 - 	struct mm_struct *mm = NULL;
   52.70 - 	struct task_struct * new;
   52.71 - 	unsigned long cookie = 0;
   52.72 --	int in_kernel = 1;
   52.73 -+	int cpu_mode = 1;
   52.74 - 	unsigned int i;
   52.75 - 	sync_buffer_state state = sb_buffer_start;
   52.76 - 	unsigned long available;
   52.77 -+	int domain_switch = 0;
   52.78 - 
   52.79 - 	down(&buffer_sem);
   52.80 -  
   52.81 -@@ -512,16 +533,18 @@
   52.82 - 	for (i = 0; i < available; ++i) {
   52.83 - 		struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
   52.84 -  
   52.85 --		if (is_code(s->eip)) {
   52.86 --			if (s->event <= CPU_IS_KERNEL) {
   52.87 --				/* kernel/userspace switch */
   52.88 --				in_kernel = s->event;
   52.89 -+		if (is_code(s->eip) && !domain_switch) {
   52.90 -+			if (s->event <= CPU_MODE_XEN) {
   52.91 -+				/* xen/kernel/userspace switch */
   52.92 -+				cpu_mode = s->event;
   52.93 - 				if (state == sb_buffer_start)
   52.94 - 					state = sb_sample_start;
   52.95 --				add_kernel_ctx_switch(s->event);
   52.96 -+				add_cpu_mode_switch(s->event);
   52.97 - 			} else if (s->event == CPU_TRACE_BEGIN) {
   52.98 - 				state = sb_bt_start;
   52.99 - 				add_trace_begin();
  52.100 -+			} else if (s->event == CPU_DOMAIN_SWITCH) {
  52.101 -+					domain_switch = 1;				
  52.102 - 			} else {
  52.103 - 				struct mm_struct * oldmm = mm;
  52.104 - 
  52.105 -@@ -535,11 +558,16 @@
  52.106 - 				add_user_ctx_switch(new, cookie);
  52.107 - 			}
  52.108 - 		} else {
  52.109 --			if (state >= sb_bt_start &&
  52.110 --			    !add_sample(mm, s, in_kernel)) {
  52.111 --				if (state == sb_bt_start) {
  52.112 --					state = sb_bt_ignore;
  52.113 --					atomic_inc(&oprofile_stats.bt_lost_no_mapping);
  52.114 -+			if (domain_switch) {
  52.115 -+				add_domain_switch(s->eip);
  52.116 -+				domain_switch = 0;
  52.117 -+			} else {
  52.118 -+				if (state >= sb_bt_start &&
  52.119 -+				    !add_sample(mm, s, cpu_mode)) {
  52.120 -+					if (state == sb_bt_start) {
  52.121 -+						state = sb_bt_ignore;
  52.122 -+						atomic_inc(&oprofile_stats.bt_lost_no_mapping);
  52.123 -+					}
  52.124 - 				}
  52.125 - 			}
  52.126 - 		}
  52.127 -diff -Naur orig/drivers/oprofile/cpu_buffer.c new/drivers/oprofile/cpu_buffer.c
  52.128 ---- orig/drivers/oprofile/cpu_buffer.c	2006-05-02 14:38:44.000000000 -0700
  52.129 -+++ new/drivers/oprofile/cpu_buffer.c	2006-07-06 18:19:05.000000000 -0700
  52.130 -@@ -6,6 +6,10 @@
  52.131 -  *
  52.132 -  * @author John Levon <levon@movementarian.org>
  52.133 -  *
  52.134 -+ * Modified by Aravind Menon for Xen
  52.135 -+ * These modifications are:
  52.136 -+ * Copyright (C) 2005 Hewlett-Packard Co.
  52.137 -+ *
  52.138 -  * Each CPU has a local buffer that stores PC value/event
  52.139 -  * pairs. We also log context switches when we notice them.
  52.140 -  * Eventually each CPU's buffer is processed into the global
  52.141 -@@ -34,6 +38,8 @@
  52.142 - #define DEFAULT_TIMER_EXPIRE (HZ / 10)
  52.143 - static int work_enabled;
  52.144 - 
  52.145 -+static int32_t current_domain = COORDINATOR_DOMAIN;
  52.146 -+
  52.147 - void free_cpu_buffers(void)
  52.148 - {
  52.149 - 	int i;
  52.150 -@@ -58,7 +64,7 @@
  52.151 - 			goto fail;
  52.152 -  
  52.153 - 		b->last_task = NULL;
  52.154 --		b->last_is_kernel = -1;
  52.155 -+		b->last_cpu_mode = -1;
  52.156 - 		b->tracing = 0;
  52.157 - 		b->buffer_size = buffer_size;
  52.158 - 		b->tail_pos = 0;
  52.159 -@@ -114,7 +120,7 @@
  52.160 - 	 * collected will populate the buffer with proper
  52.161 - 	 * values to initialize the buffer
  52.162 - 	 */
  52.163 --	cpu_buf->last_is_kernel = -1;
  52.164 -+	cpu_buf->last_cpu_mode = -1;
  52.165 - 	cpu_buf->last_task = NULL;
  52.166 - }
  52.167 - 
  52.168 -@@ -164,13 +170,13 @@
  52.169 -  * because of the head/tail separation of the writer and reader
  52.170 -  * of the CPU buffer.
  52.171 -  *
  52.172 -- * is_kernel is needed because on some architectures you cannot
  52.173 -+ * cpu_mode is needed because on some architectures you cannot
  52.174 -  * tell if you are in kernel or user space simply by looking at
  52.175 -- * pc. We tag this in the buffer by generating kernel enter/exit
  52.176 -- * events whenever is_kernel changes
  52.177 -+ * pc. We tag this in the buffer by generating kernel/user (and xen)
  52.178 -+ *  enter events whenever cpu_mode changes
  52.179 -  */
  52.180 - static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
  52.181 --		      int is_kernel, unsigned long event)
  52.182 -+		      int cpu_mode, unsigned long event)
  52.183 - {
  52.184 - 	struct task_struct * task;
  52.185 - 
  52.186 -@@ -181,18 +187,18 @@
  52.187 - 		return 0;
  52.188 - 	}
  52.189 - 
  52.190 --	is_kernel = !!is_kernel;
  52.191 --
  52.192 - 	task = current;
  52.193 - 
  52.194 - 	/* notice a switch from user->kernel or vice versa */
  52.195 --	if (cpu_buf->last_is_kernel != is_kernel) {
  52.196 --		cpu_buf->last_is_kernel = is_kernel;
  52.197 --		add_code(cpu_buf, is_kernel);
  52.198 -+	if (cpu_buf->last_cpu_mode != cpu_mode) {
  52.199 -+		cpu_buf->last_cpu_mode = cpu_mode;
  52.200 -+		add_code(cpu_buf, cpu_mode);
  52.201 - 	}
  52.202 --
  52.203 -+	
  52.204 - 	/* notice a task switch */
  52.205 --	if (cpu_buf->last_task != task) {
  52.206 -+	/* if not processing other domain samples */
  52.207 -+	if ((cpu_buf->last_task != task) &&
  52.208 -+	    (current_domain == COORDINATOR_DOMAIN)) {
  52.209 - 		cpu_buf->last_task = task;
  52.210 - 		add_code(cpu_buf, (unsigned long)task);
  52.211 - 	}
  52.212 -@@ -269,6 +275,25 @@
  52.213 - 	add_sample(cpu_buf, pc, 0);
  52.214 - }
  52.215 - 
  52.216 -+int oprofile_add_domain_switch(int32_t domain_id)
  52.217 -+{
  52.218 -+	struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
  52.219 -+
  52.220 -+	/* should have space for switching into and out of domain 
  52.221 -+	   (2 slots each) plus one sample and one cpu mode switch */
  52.222 -+	if (((nr_available_slots(cpu_buf) < 6) && 
  52.223 -+	     (domain_id != COORDINATOR_DOMAIN)) ||
  52.224 -+	    (nr_available_slots(cpu_buf) < 2))
  52.225 -+		return 0;
  52.226 -+
  52.227 -+	add_code(cpu_buf, CPU_DOMAIN_SWITCH);
  52.228 -+	add_sample(cpu_buf, domain_id, 0);
  52.229 -+
  52.230 -+	current_domain = domain_id;
  52.231 -+
  52.232 -+	return 1;
  52.233 -+}
  52.234 -+
  52.235 - /*
  52.236 -  * This serves to avoid cpu buffer overflow, and makes sure
  52.237 -  * the task mortuary progresses
  52.238 -diff -Naur orig/drivers/oprofile/cpu_buffer.h new/drivers/oprofile/cpu_buffer.h
  52.239 ---- orig/drivers/oprofile/cpu_buffer.h	2006-05-02 14:38:44.000000000 -0700
  52.240 -+++ new/drivers/oprofile/cpu_buffer.h	2006-07-06 18:19:05.000000000 -0700
  52.241 -@@ -36,7 +36,7 @@
  52.242 - 	volatile unsigned long tail_pos;
  52.243 - 	unsigned long buffer_size;
  52.244 - 	struct task_struct * last_task;
  52.245 --	int last_is_kernel;
  52.246 -+	int last_cpu_mode;
  52.247 - 	int tracing;
  52.248 - 	struct op_sample * buffer;
  52.249 - 	unsigned long sample_received;
  52.250 -@@ -51,7 +51,10 @@
  52.251 - void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
  52.252 - 
  52.253 - /* transient events for the CPU buffer -> event buffer */
  52.254 --#define CPU_IS_KERNEL 1
  52.255 --#define CPU_TRACE_BEGIN 2
  52.256 -+#define CPU_MODE_USER           0
  52.257 -+#define CPU_MODE_KERNEL         1
  52.258 -+#define CPU_MODE_XEN            2
  52.259 -+#define CPU_TRACE_BEGIN         3
  52.260 -+#define CPU_DOMAIN_SWITCH       4
  52.261 - 
  52.262 - #endif /* OPROFILE_CPU_BUFFER_H */
  52.263 -diff -Naur orig/drivers/oprofile/event_buffer.h new/drivers/oprofile/event_buffer.h
  52.264 ---- orig/drivers/oprofile/event_buffer.h	2006-05-02 14:38:44.000000000 -0700
  52.265 -+++ new/drivers/oprofile/event_buffer.h	2006-07-06 18:19:05.000000000 -0700
  52.266 -@@ -29,15 +29,20 @@
  52.267 - #define CPU_SWITCH_CODE 		2
  52.268 - #define COOKIE_SWITCH_CODE 		3
  52.269 - #define KERNEL_ENTER_SWITCH_CODE	4
  52.270 --#define KERNEL_EXIT_SWITCH_CODE		5
  52.271 -+#define USER_ENTER_SWITCH_CODE		5
  52.272 - #define MODULE_LOADED_CODE		6
  52.273 - #define CTX_TGID_CODE			7
  52.274 - #define TRACE_BEGIN_CODE		8
  52.275 - #define TRACE_END_CODE			9
  52.276 -+#define XEN_ENTER_SWITCH_CODE		10
  52.277 -+#define DOMAIN_SWITCH_CODE		11
  52.278 -  
  52.279 - #define INVALID_COOKIE ~0UL
  52.280 - #define NO_COOKIE 0UL
  52.281 - 
  52.282 -+/* Constant used to refer to coordinator domain (Xen) */
  52.283 -+#define COORDINATOR_DOMAIN -1
  52.284 -+
  52.285 - /* add data to the event buffer */
  52.286 - void add_event_entry(unsigned long data);
  52.287 -  
  52.288 -diff -Naur orig/drivers/oprofile/oprof.c new/drivers/oprofile/oprof.c
  52.289 ---- orig/drivers/oprofile/oprof.c	2006-05-02 14:38:44.000000000 -0700
  52.290 -+++ new/drivers/oprofile/oprof.c	2006-07-06 18:19:05.000000000 -0700
  52.291 -@@ -5,6 +5,10 @@
  52.292 -  * @remark Read the file COPYING
  52.293 -  *
  52.294 -  * @author John Levon <levon@movementarian.org>
  52.295 -+ *
  52.296 -+ * Modified by Aravind Menon for Xen
  52.297 -+ * These modifications are:
  52.298 -+ * Copyright (C) 2005 Hewlett-Packard Co.
  52.299 -  */
  52.300 - 
  52.301 - #include <linux/kernel.h>
  52.302 -@@ -19,7 +23,7 @@
  52.303 - #include "cpu_buffer.h"
  52.304 - #include "buffer_sync.h"
  52.305 - #include "oprofile_stats.h"
  52.306 -- 
  52.307 -+
  52.308 - struct oprofile_operations oprofile_ops;
  52.309 - 
  52.310 - unsigned long oprofile_started;
  52.311 -@@ -33,6 +37,32 @@
  52.312 -  */
  52.313 - static int timer = 0;
  52.314 - 
  52.315 -+int oprofile_set_active(int active_domains[], unsigned int adomains)
  52.316 -+{
  52.317 -+	int err;
  52.318 -+
  52.319 -+	if (!oprofile_ops.set_active)
  52.320 -+		return -EINVAL;
  52.321 -+
  52.322 -+	down(&start_sem);
  52.323 -+	err = oprofile_ops.set_active(active_domains, adomains);
  52.324 -+	up(&start_sem);
  52.325 -+	return err;
  52.326 -+}
  52.327 -+
  52.328 -+int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
  52.329 -+{
  52.330 -+	int err;
  52.331 -+
  52.332 -+	if (!oprofile_ops.set_passive)
  52.333 -+		return -EINVAL;
  52.334 -+
  52.335 -+	down(&start_sem);
  52.336 -+	err = oprofile_ops.set_passive(passive_domains, pdomains);
  52.337 -+	up(&start_sem);
  52.338 -+	return err;
  52.339 -+}
  52.340 -+
  52.341 - int oprofile_setup(void)
  52.342 - {
  52.343 - 	int err;
  52.344 -diff -Naur orig/drivers/oprofile/oprof.h new/drivers/oprofile/oprof.h
  52.345 ---- orig/drivers/oprofile/oprof.h	2006-05-02 14:38:44.000000000 -0700
  52.346 -+++ new/drivers/oprofile/oprof.h	2006-07-06 18:19:05.000000000 -0700
  52.347 -@@ -35,5 +35,8 @@
  52.348 - void oprofile_timer_init(struct oprofile_operations * ops);
  52.349 - 
  52.350 - int oprofile_set_backtrace(unsigned long depth);
  52.351 -+
  52.352 -+int oprofile_set_active(int active_domains[], unsigned int adomains);
  52.353 -+int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
  52.354 -  
  52.355 - #endif /* OPROF_H */
  52.356 -diff -Naur orig/drivers/oprofile/oprofile_files.c new/drivers/oprofile/oprofile_files.c
  52.357 ---- orig/drivers/oprofile/oprofile_files.c	2006-05-02 14:38:44.000000000 -0700
  52.358 -+++ new/drivers/oprofile/oprofile_files.c	2006-07-06 18:19:05.000000000 -0700
  52.359 -@@ -5,15 +5,21 @@
  52.360 -  * @remark Read the file COPYING
  52.361 -  *
  52.362 -  * @author John Levon <levon@movementarian.org>
  52.363 -+ *
  52.364 -+ * Modified by Aravind Menon for Xen
  52.365 -+ * These modifications are:
  52.366 -+ * Copyright (C) 2005 Hewlett-Packard Co.	
  52.367 -  */
  52.368 - 
  52.369 - #include <linux/fs.h>
  52.370 - #include <linux/oprofile.h>
  52.371 -+#include <asm/uaccess.h>
  52.372 -+#include <linux/ctype.h>
  52.373 - 
  52.374 - #include "event_buffer.h"
  52.375 - #include "oprofile_stats.h"
  52.376 - #include "oprof.h"
  52.377 -- 
  52.378 -+
  52.379 - unsigned long fs_buffer_size = 131072;
  52.380 - unsigned long fs_cpu_buffer_size = 8192;
  52.381 - unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
  52.382 -@@ -117,11 +123,202 @@
  52.383 - static struct file_operations dump_fops = {
  52.384 - 	.write		= dump_write,
  52.385 - };
  52.386 -- 
  52.387 -+
  52.388 -+#define TMPBUFSIZE 512
  52.389 -+
  52.390 -+static unsigned int adomains = 0;
  52.391 -+static int active_domains[MAX_OPROF_DOMAINS + 1];
  52.392 -+static DEFINE_MUTEX(adom_mutex);
  52.393 -+
  52.394 -+static ssize_t adomain_write(struct file * file, char const __user * buf, 
  52.395 -+			     size_t count, loff_t * offset)
  52.396 -+{
  52.397 -+	char *tmpbuf;
  52.398 -+	char *startp, *endp;
  52.399 -+	int i;
  52.400 -+	unsigned long val;
  52.401 -+	ssize_t retval = count;
  52.402 -+	
  52.403 -+	if (*offset)
  52.404 -+		return -EINVAL;	
  52.405 -+	if (count > TMPBUFSIZE - 1)
  52.406 -+		return -EINVAL;
  52.407 -+
  52.408 -+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
  52.409 -+		return -ENOMEM;
  52.410 -+
  52.411 -+	if (copy_from_user(tmpbuf, buf, count)) {
  52.412 -+		kfree(tmpbuf);
  52.413 -+		return -EFAULT;
  52.414 -+	}
  52.415 -+	tmpbuf[count] = 0;
  52.416 -+
  52.417 -+	mutex_lock(&adom_mutex);
  52.418 -+
  52.419 -+	startp = tmpbuf;
  52.420 -+	/* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
  52.421 -+	for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
  52.422 -+		val = simple_strtoul(startp, &endp, 0);
  52.423 -+		if (endp == startp)
  52.424 -+			break;
  52.425 -+		while (ispunct(*endp) || isspace(*endp))
  52.426 -+			endp++;
  52.427 -+		active_domains[i] = val;
  52.428 -+		if (active_domains[i] != val)
  52.429 -+			/* Overflow, force error below */
  52.430 -+			i = MAX_OPROF_DOMAINS + 1;
  52.431 -+		startp = endp;
  52.432 -+	}
  52.433 -+	/* Force error on trailing junk */
  52.434 -+	adomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
  52.435 -+
  52.436 -+	kfree(tmpbuf);
  52.437 -+
  52.438 -+	if (adomains > MAX_OPROF_DOMAINS
  52.439 -+	    || oprofile_set_active(active_domains, adomains)) {
  52.440 -+		adomains = 0;
  52.441 -+		retval = -EINVAL;
  52.442 -+	}
  52.443 -+
  52.444 -+	mutex_unlock(&adom_mutex);
  52.445 -+	return retval;
  52.446 -+}
  52.447 -+
  52.448 -+static ssize_t adomain_read(struct file * file, char __user * buf, 
  52.449 -+			    size_t count, loff_t * offset)
  52.450 -+{
  52.451 -+	char * tmpbuf;
  52.452 -+	size_t len;
  52.453 -+	int i;
  52.454 -+	ssize_t retval;
  52.455 -+
  52.456 -+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
  52.457 -+		return -ENOMEM;
  52.458 -+
  52.459 -+	mutex_lock(&adom_mutex);
  52.460 -+
  52.461 -+	len = 0;
  52.462 -+	for (i = 0; i < adomains; i++)
  52.463 -+		len += snprintf(tmpbuf + len,
  52.464 -+				len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
  52.465 -+				"%u ", active_domains[i]);
  52.466 -+	WARN_ON(len > TMPBUFSIZE);
  52.467 -+	if (len != 0 && len <= TMPBUFSIZE)
  52.468 -+		tmpbuf[len-1] = '\n';
  52.469 -+
  52.470 -+	mutex_unlock(&adom_mutex);
  52.471 -+
  52.472 -+	retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
  52.473 -+
  52.474 -+	kfree(tmpbuf);
  52.475 -+	return retval;
  52.476 -+}
  52.477 -+
  52.478 -+
  52.479 -+static struct file_operations active_domain_ops = {
  52.480 -+	.read		= adomain_read,
  52.481 -+	.write		= adomain_write,
  52.482 -+};
  52.483 -+
  52.484 -+static unsigned int pdomains = 0;
  52.485 -+static int passive_domains[MAX_OPROF_DOMAINS];
  52.486 -+static DEFINE_MUTEX(pdom_mutex);
  52.487 -+
  52.488 -+static ssize_t pdomain_write(struct file * file, char const __user * buf, 
  52.489 -+			     size_t count, loff_t * offset)
  52.490 -+{
  52.491 -+	char *tmpbuf;
  52.492 -+	char *startp, *endp;
  52.493 -+	int i;
  52.494 -+	unsigned long val;
  52.495 -+	ssize_t retval = count;
  52.496 -+	
  52.497 -+	if (*offset)
  52.498 -+		return -EINVAL;	
  52.499 -+	if (count > TMPBUFSIZE - 1)
  52.500 -+		return -EINVAL;
  52.501 -+
  52.502 -+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
  52.503 -+		return -ENOMEM;
  52.504 -+
  52.505 -+	if (copy_from_user(tmpbuf, buf, count)) {
  52.506 -+		kfree(tmpbuf);
  52.507 -+		return -EFAULT;
  52.508 -+	}
  52.509 -+	tmpbuf[count] = 0;
  52.510 -+
  52.511 -+	mutex_lock(&pdom_mutex);
  52.512 -+
  52.513 -+	startp = tmpbuf;
  52.514 -+	/* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
  52.515 -+	for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
  52.516 -+		val = simple_strtoul(startp, &endp, 0);
  52.517 -+		if (endp == startp)
  52.518 -+			break;
  52.519 -+		while (ispunct(*endp) || isspace(*endp))
  52.520 -+			endp++;
  52.521 -+		passive_domains[i] = val;
  52.522 -+		if (passive_domains[i] != val)
  52.523 -+			/* Overflow, force error below */
  52.524 -+			i = MAX_OPROF_DOMAINS + 1;
  52.525 -+		startp = endp;
  52.526 -+	}
  52.527 -+	/* Force error on trailing junk */
  52.528 -+	pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
  52.529 -+
  52.530 -+	kfree(tmpbuf);
  52.531 -+
  52.532 -+	if (pdomains > MAX_OPROF_DOMAINS
  52.533 -+	    || oprofile_set_passive(passive_domains, pdomains)) {
  52.534 -+		pdomains = 0;
  52.535 -+		retval = -EINVAL;
  52.536 -+	}
  52.537 -+
  52.538 -+	mutex_unlock(&pdom_mutex);
  52.539 -+	return retval;
  52.540 -+}
  52.541 -+
  52.542 -+static ssize_t pdomain_read(struct file * file, char __user * buf, 
  52.543 -+			    size_t count, loff_t * offset)
  52.544 -+{
  52.545 -+	char * tmpbuf;
  52.546 -+	size_t len;
  52.547 -+	int i;
  52.548 -+	ssize_t retval;
  52.549 -+
  52.550 -+	if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
  52.551 -+		return -ENOMEM;
  52.552 -+
  52.553 -+	mutex_lock(&pdom_mutex);
  52.554 -+
  52.555 -+	len = 0;
  52.556 -+	for (i = 0; i < pdomains; i++)
  52.557 -+		len += snprintf(tmpbuf + len,
  52.558 -+				len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
  52.559 -+				"%u ", passive_domains[i]);
  52.560 -+	WARN_ON(len > TMPBUFSIZE);
  52.561 -+	if (len != 0 && len <= TMPBUFSIZE)
  52.562 -+		tmpbuf[len-1] = '\n';
  52.563 -+
  52.564 -+	mutex_unlock(&pdom_mutex);
  52.565 -+
  52.566 -+	retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
  52.567 -+
  52.568 -+	kfree(tmpbuf);
  52.569 -+	return retval;
  52.570 -+}
  52.571 -+
  52.572 -+static struct file_operations passive_domain_ops = {
  52.573 -+	.read		= pdomain_read,
  52.574 -+	.write		= pdomain_write,
  52.575 -+};
  52.576 -+
  52.577 - void oprofile_create_files(struct super_block * sb, struct dentry * root)
  52.578 - {
  52.579 - 	oprofilefs_create_file(sb, root, "enable", &enable_fops);
  52.580 - 	oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
  52.581 -+	oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
  52.582 -+	oprofilefs_create_file(sb, root, "passive_domains", &passive_domain_ops);
  52.583 - 	oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
  52.584 - 	oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
  52.585 - 	oprofilefs_create_ulong(sb, root, "buffer_watershed", &fs_buffer_watershed);
  52.586 -diff -Naur orig/include/linux/oprofile.h new/include/linux/oprofile.h
  52.587 ---- orig/include/linux/oprofile.h	2006-05-02 14:38:44.000000000 -0700
  52.588 -+++ new/include/linux/oprofile.h	2006-07-06 18:19:31.000000000 -0700
  52.589 -@@ -16,6 +16,8 @@
  52.590 - #include <linux/types.h>
  52.591 - #include <linux/spinlock.h>
  52.592 - #include <asm/atomic.h>
  52.593 -+
  52.594 -+#include <xen/interface/xenoprof.h>
  52.595 -  
  52.596 - struct super_block;
  52.597 - struct dentry;
  52.598 -@@ -27,6 +29,11 @@
  52.599 - 	/* create any necessary configuration files in the oprofile fs.
  52.600 - 	 * Optional. */
  52.601 - 	int (*create_files)(struct super_block * sb, struct dentry * root);
  52.602 -+	/* setup active domains with Xen */
  52.603 -+	int (*set_active)(int *active_domains, unsigned int adomains);
  52.604 -+        /* setup passive domains with Xen */
  52.605 -+        int (*set_passive)(int *passive_domains, unsigned int pdomains);
  52.606 -+	
  52.607 - 	/* Do any necessary interrupt setup. Optional. */
  52.608 - 	int (*setup)(void);
  52.609 - 	/* Do any necessary interrupt shutdown. Optional. */
  52.610 -@@ -68,6 +75,8 @@
  52.611 - /* add a backtrace entry, to be called from the ->backtrace callback */
  52.612 - void oprofile_add_trace(unsigned long eip);
  52.613 - 
  52.614 -+/* add a domain switch entry */
  52.615 -+int oprofile_add_domain_switch(int32_t domain_id);
  52.616 - 
  52.617 - /**
  52.618 -  * Create a file of the given name as a child of the given root, with
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/patches/linux-2.6.16.29/blktap-aio-16_03_06.patch	Sun Sep 24 13:10:13 2006 -0600
    53.3 @@ -0,0 +1,294 @@
    53.4 +diff -pruN ../orig-linux-2.6.16.29/fs/aio.c ./fs/aio.c
    53.5 +--- ../orig-linux-2.6.16.29/fs/aio.c	2006-09-12 19:02:10.000000000 +0100
    53.6 ++++ ./fs/aio.c	2006-09-19 13:58:49.000000000 +0100
    53.7 +@@ -34,6 +34,11 @@
    53.8 + #include <asm/uaccess.h>
    53.9 + #include <asm/mmu_context.h>
   53.10 + 
   53.11 ++#ifdef CONFIG_EPOLL
   53.12 ++#include <linux/poll.h>
   53.13 ++#include <linux/eventpoll.h>
   53.14 ++#endif
   53.15 ++
   53.16 + #if DEBUG > 1
   53.17 + #define dprintk		printk
   53.18 + #else
   53.19 +@@ -1016,6 +1021,10 @@ put_rq:
   53.20 + 	if (waitqueue_active(&ctx->wait))
   53.21 + 		wake_up(&ctx->wait);
   53.22 + 
   53.23 ++#ifdef CONFIG_EPOLL
   53.24 ++	if (ctx->file && waitqueue_active(&ctx->poll_wait))
   53.25 ++		wake_up(&ctx->poll_wait);
   53.26 ++#endif
   53.27 + 	if (ret)
   53.28 + 		put_ioctx(ctx);
   53.29 + 
   53.30 +@@ -1025,6 +1034,8 @@ put_rq:
   53.31 + /* aio_read_evt
   53.32 +  *	Pull an event off of the ioctx's event ring.  Returns the number of 
   53.33 +  *	events fetched (0 or 1 ;-)
   53.34 ++ *	If ent parameter is 0, just returns the number of events that would
   53.35 ++ *	be fetched.
   53.36 +  *	FIXME: make this use cmpxchg.
   53.37 +  *	TODO: make the ringbuffer user mmap()able (requires FIXME).
   53.38 +  */
   53.39 +@@ -1047,13 +1058,18 @@ static int aio_read_evt(struct kioctx *i
   53.40 + 
   53.41 + 	head = ring->head % info->nr;
   53.42 + 	if (head != ring->tail) {
   53.43 +-		struct io_event *evp = aio_ring_event(info, head, KM_USER1);
   53.44 +-		*ent = *evp;
   53.45 +-		head = (head + 1) % info->nr;
   53.46 +-		smp_mb(); /* finish reading the event before updatng the head */
   53.47 +-		ring->head = head;
   53.48 +-		ret = 1;
   53.49 +-		put_aio_ring_event(evp, KM_USER1);
   53.50 ++		if (ent) { /* event requested */
   53.51 ++			struct io_event *evp =
   53.52 ++				aio_ring_event(info, head, KM_USER1);
   53.53 ++			*ent = *evp;
   53.54 ++			head = (head + 1) % info->nr;
   53.55 ++			/* finish reading the event before updatng the head */
   53.56 ++			smp_mb();
   53.57 ++			ring->head = head;
   53.58 ++			ret = 1;
   53.59 ++			put_aio_ring_event(evp, KM_USER1);
   53.60 ++		} else /* only need to know availability */
   53.61 ++			ret = 1;
   53.62 + 	}
   53.63 + 	spin_unlock(&info->ring_lock);
   53.64 + 
   53.65 +@@ -1236,9 +1252,78 @@ static void io_destroy(struct kioctx *io
   53.66 + 
   53.67 + 	aio_cancel_all(ioctx);
   53.68 + 	wait_for_all_aios(ioctx);
   53.69 ++#ifdef CONFIG_EPOLL
   53.70 ++	/* forget the poll file, but it's up to the user to close it */
   53.71 ++	if (ioctx->file) {
   53.72 ++		ioctx->file->private_data = 0;
   53.73 ++		ioctx->file = 0;
   53.74 ++	}
   53.75 ++#endif
   53.76 + 	put_ioctx(ioctx);	/* once for the lookup */
   53.77 + }
   53.78 + 
   53.79 ++#ifdef CONFIG_EPOLL
   53.80 ++
   53.81 ++static int aio_queue_fd_close(struct inode *inode, struct file *file)
   53.82 ++{
   53.83 ++	struct kioctx *ioctx = file->private_data;
   53.84 ++	if (ioctx) {
   53.85 ++		file->private_data = 0;
   53.86 ++		spin_lock_irq(&ioctx->ctx_lock);
   53.87 ++		ioctx->file = 0;
   53.88 ++		spin_unlock_irq(&ioctx->ctx_lock);
   53.89 ++	}
   53.90 ++	return 0;
   53.91 ++}
   53.92 ++
   53.93 ++static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
   53.94 ++{	unsigned int pollflags = 0;
   53.95 ++	struct kioctx *ioctx = file->private_data;
   53.96 ++
   53.97 ++	if (ioctx) {
   53.98 ++
   53.99 ++		spin_lock_irq(&ioctx->ctx_lock);
  53.100 ++		/* Insert inside our poll wait queue */
  53.101 ++		poll_wait(file, &ioctx->poll_wait, wait);
  53.102 ++
  53.103 ++		/* Check our condition */
  53.104 ++		if (aio_read_evt(ioctx, 0))
  53.105 ++			pollflags = POLLIN | POLLRDNORM;
  53.106 ++		spin_unlock_irq(&ioctx->ctx_lock);
  53.107 ++	}
  53.108 ++
  53.109 ++	return pollflags;
  53.110 ++}
  53.111 ++
  53.112 ++static struct file_operations aioq_fops = {
  53.113 ++	.release	= aio_queue_fd_close,
  53.114 ++	.poll		= aio_queue_fd_poll
  53.115 ++};
  53.116 ++
  53.117 ++/* make_aio_fd:
  53.118 ++ *  Create a file descriptor that can be used to poll the event queue.
  53.119 ++ *  Based and piggybacked on the excellent epoll code.
  53.120 ++ */
  53.121 ++
  53.122 ++static int make_aio_fd(struct kioctx *ioctx)
  53.123 ++{
  53.124 ++	int error, fd;
  53.125 ++	struct inode *inode;
  53.126 ++	struct file *file;
  53.127 ++
  53.128 ++	error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
  53.129 ++	if (error)
  53.130 ++		return error;
  53.131 ++
  53.132 ++	/* associate the file with the IO context */
  53.133 ++	file->private_data = ioctx;
  53.134 ++	ioctx->file = file;
  53.135 ++	init_waitqueue_head(&ioctx->poll_wait);
  53.136 ++	return fd;
  53.137 ++}
  53.138 ++#endif
  53.139 ++
  53.140 ++
  53.141 + /* sys_io_setup:
  53.142 +  *	Create an aio_context capable of receiving at least nr_events.
  53.143 +  *	ctxp must not point to an aio_context that already exists, and
  53.144 +@@ -1251,18 +1336,30 @@ static void io_destroy(struct kioctx *io
  53.145 +  *	resources are available.  May fail with -EFAULT if an invalid
  53.146 +  *	pointer is passed for ctxp.  Will fail with -ENOSYS if not
  53.147 +  *	implemented.
  53.148 ++ *
  53.149 ++ *	To request a selectable fd, the user context has to be initialized
  53.150 ++ *	to 1, instead of 0, and the return value is the fd.
  53.151 ++ *	This keeps the system call compatible, since a non-zero value
  53.152 ++ *	was not allowed so far.
  53.153 +  */
  53.154 + asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
  53.155 + {
  53.156 + 	struct kioctx *ioctx = NULL;
  53.157 + 	unsigned long ctx;
  53.158 + 	long ret;
  53.159 ++	int make_fd = 0;
  53.160 + 
  53.161 + 	ret = get_user(ctx, ctxp);
  53.162 + 	if (unlikely(ret))
  53.163 + 		goto out;
  53.164 + 
  53.165 + 	ret = -EINVAL;
  53.166 ++#ifdef CONFIG_EPOLL
  53.167 ++	if (ctx == 1) {
  53.168 ++		make_fd = 1;
  53.169 ++		ctx = 0;
  53.170 ++	}
  53.171 ++#endif
  53.172 + 	if (unlikely(ctx || nr_events == 0)) {
  53.173 + 		pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
  53.174 + 		         ctx, nr_events);
  53.175 +@@ -1273,8 +1370,12 @@ asmlinkage long sys_io_setup(unsigned nr
  53.176 + 	ret = PTR_ERR(ioctx);
  53.177 + 	if (!IS_ERR(ioctx)) {
  53.178 + 		ret = put_user(ioctx->user_id, ctxp);
  53.179 +-		if (!ret)
  53.180 +-			return 0;
  53.181 ++#ifdef CONFIG_EPOLL
  53.182 ++		if (make_fd && ret >= 0)
  53.183 ++			ret = make_aio_fd(ioctx);
  53.184 ++#endif
  53.185 ++		if (ret >= 0)
  53.186 ++			return ret;
  53.187 + 
  53.188 + 		get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
  53.189 + 		io_destroy(ioctx);
  53.190 +diff -pruN ../orig-linux-2.6.16.29/fs/eventpoll.c ./fs/eventpoll.c
  53.191 +--- ../orig-linux-2.6.16.29/fs/eventpoll.c	2006-09-12 19:02:10.000000000 +0100
  53.192 ++++ ./fs/eventpoll.c	2006-09-19 13:58:49.000000000 +0100
  53.193 +@@ -235,8 +235,6 @@ struct ep_pqueue {
  53.194 + 
  53.195 + static void ep_poll_safewake_init(struct poll_safewake *psw);
  53.196 + static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
  53.197 +-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  53.198 +-		    struct eventpoll *ep);
  53.199 + static int ep_alloc(struct eventpoll **pep);
  53.200 + static void ep_free(struct eventpoll *ep);
  53.201 + static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
  53.202 +@@ -266,7 +264,7 @@ static int ep_events_transfer(struct eve
  53.203 + static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
  53.204 + 		   int maxevents, long timeout);
  53.205 + static int eventpollfs_delete_dentry(struct dentry *dentry);
  53.206 +-static struct inode *ep_eventpoll_inode(void);
  53.207 ++static struct inode *ep_eventpoll_inode(struct file_operations *fops);
  53.208 + static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
  53.209 + 					      int flags, const char *dev_name,
  53.210 + 					      void *data);
  53.211 +@@ -525,7 +523,7 @@ asmlinkage long sys_epoll_create(int siz
  53.212 + 	 * Creates all the items needed to setup an eventpoll file. That is,
  53.213 + 	 * a file structure, and inode and a free file descriptor.
  53.214 + 	 */
  53.215 +-	error = ep_getfd(&fd, &inode, &file, ep);
  53.216 ++	error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
  53.217 + 	if (error)
  53.218 + 		goto eexit_2;
  53.219 + 
  53.220 +@@ -710,8 +708,8 @@ eexit_1:
  53.221 + /*
  53.222 +  * Creates the file descriptor to be used by the epoll interface.
  53.223 +  */
  53.224 +-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  53.225 +-		    struct eventpoll *ep)
  53.226 ++int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  53.227 ++		    struct eventpoll *ep, struct file_operations *fops)
  53.228 + {
  53.229 + 	struct qstr this;
  53.230 + 	char name[32];
  53.231 +@@ -727,7 +725,7 @@ static int ep_getfd(int *efd, struct ino
  53.232 + 		goto eexit_1;
  53.233 + 
  53.234 + 	/* Allocates an inode from the eventpoll file system */
  53.235 +-	inode = ep_eventpoll_inode();
  53.236 ++	inode = ep_eventpoll_inode(fops);
  53.237 + 	error = PTR_ERR(inode);
  53.238 + 	if (IS_ERR(inode))
  53.239 + 		goto eexit_2;
  53.240 +@@ -758,7 +756,7 @@ static int ep_getfd(int *efd, struct ino
  53.241 + 
  53.242 + 	file->f_pos = 0;
  53.243 + 	file->f_flags = O_RDONLY;
  53.244 +-	file->f_op = &eventpoll_fops;
  53.245 ++	file->f_op = fops;
  53.246 + 	file->f_mode = FMODE_READ;
  53.247 + 	file->f_version = 0;
  53.248 + 	file->private_data = ep;
  53.249 +@@ -1574,7 +1572,7 @@ static int eventpollfs_delete_dentry(str
  53.250 + }
  53.251 + 
  53.252 + 
  53.253 +-static struct inode *ep_eventpoll_inode(void)
  53.254 ++static struct inode *ep_eventpoll_inode(struct file_operations *fops)
  53.255 + {
  53.256 + 	int error = -ENOMEM;
  53.257 + 	struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
  53.258 +@@ -1582,7 +1580,7 @@ static struct inode *ep_eventpoll_inode(
  53.259 + 	if (!inode)
  53.260 + 		goto eexit_1;
  53.261 + 
  53.262 +-	inode->i_fop = &eventpoll_fops;
  53.263 ++	inode->i_fop = fops;
  53.264 + 
  53.265 + 	/*
  53.266 + 	 * Mark the inode dirty from the very beginning,
  53.267 +diff -pruN ../orig-linux-2.6.16.29/include/linux/aio.h ./include/linux/aio.h
  53.268 +--- ../orig-linux-2.6.16.29/include/linux/aio.h	2006-09-12 19:02:10.000000000 +0100
  53.269 ++++ ./include/linux/aio.h	2006-09-19 13:58:49.000000000 +0100
  53.270 +@@ -191,6 +191,11 @@ struct kioctx {
  53.271 + 	struct aio_ring_info	ring_info;
  53.272 + 
  53.273 + 	struct work_struct	wq;
  53.274 ++#ifdef CONFIG_EPOLL
  53.275 ++	// poll integration
  53.276 ++	wait_queue_head_t       poll_wait;
  53.277 ++	struct file		*file;
  53.278 ++#endif
  53.279 + };
  53.280 + 
  53.281 + /* prototypes */
  53.282 +diff -pruN ../orig-linux-2.6.16.29/include/linux/eventpoll.h ./include/linux/eventpoll.h
  53.283 +--- ../orig-linux-2.6.16.29/include/linux/eventpoll.h	2006-09-12 19:02:10.000000000 +0100
  53.284 ++++ ./include/linux/eventpoll.h	2006-09-19 13:58:49.000000000 +0100
  53.285 +@@ -86,6 +86,12 @@ static inline void eventpoll_release(str
  53.286 + }
  53.287 + 
  53.288 + 
  53.289 ++/*
  53.290 ++ * called by aio code to create fd that can poll the  aio event queueQ
  53.291 ++ */
  53.292 ++struct eventpoll;
  53.293 ++int ep_getfd(int *efd, struct inode **einode, struct file **efile,
  53.294 ++             struct eventpoll *ep, struct file_operations *fops);
  53.295 + #else
  53.296 + 
  53.297 + static inline void eventpoll_init_file(struct file *file) {}
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/patches/linux-2.6.16.29/device_bind.patch	Sun Sep 24 13:10:13 2006 -0600
    54.3 @@ -0,0 +1,15 @@
    54.4 +diff -pruN ../orig-linux-2.6.16.29/drivers/base/bus.c ./drivers/base/bus.c
    54.5 +--- ../orig-linux-2.6.16.29/drivers/base/bus.c	2006-09-12 19:02:10.000000000 +0100
    54.6 ++++ ./drivers/base/bus.c	2006-09-19 13:58:54.000000000 +0100
    54.7 +@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device
    54.8 + 		up(&dev->sem);
    54.9 + 		if (dev->parent)
   54.10 + 			up(&dev->parent->sem);
   54.11 ++
   54.12 ++		if (err > 0) 		/* success */
   54.13 ++			err = count;
   54.14 ++		else if (err == 0)	/* driver didn't accept device */
   54.15 ++			err = -ENODEV;
   54.16 + 	}
   54.17 + 	put_device(dev);
   54.18 + 	put_bus(bus);
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/patches/linux-2.6.16.29/fix-hz-suspend.patch	Sun Sep 24 13:10:13 2006 -0600
    55.3 @@ -0,0 +1,26 @@
    55.4 +diff -pruN ../orig-linux-2.6.16.29/kernel/timer.c ./kernel/timer.c
    55.5 +--- ../orig-linux-2.6.16.29/kernel/timer.c	2006-09-12 19:02:10.000000000 +0100
    55.6 ++++ ./kernel/timer.c	2006-09-19 13:58:58.000000000 +0100
    55.7 +@@ -555,6 +555,22 @@ found:
    55.8 + 	}
    55.9 + 	spin_unlock(&base->t_base.lock);
   55.10 + 
   55.11 ++	/*
   55.12 ++	 * It can happen that other CPUs service timer IRQs and increment
   55.13 ++	 * jiffies, but we have not yet got a local timer tick to process
   55.14 ++	 * the timer wheels.  In that case, the expiry time can be before
   55.15 ++	 * jiffies, but since the high-resolution timer here is relative to
   55.16 ++	 * jiffies, the default expression when high-resolution timers are
   55.17 ++	 * not active,
   55.18 ++	 *
   55.19 ++	 *   time_before(MAX_JIFFY_OFFSET + jiffies, expires)
   55.20 ++	 *
   55.21 ++	 * would falsely evaluate to true.  If that is the case, just
   55.22 ++	 * return jiffies so that we can immediately fire the local timer
   55.23 ++	 */
   55.24 ++	if (time_before(expires, jiffies))
   55.25 ++		return jiffies;
   55.26 ++
   55.27 + 	if (time_before(hr_expires, expires))
   55.28 + 		return hr_expires;
   55.29 + 
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/patches/linux-2.6.16.29/fix-ide-cd-pio-mode.patch	Sun Sep 24 13:10:13 2006 -0600
    56.3 @@ -0,0 +1,18 @@
    56.4 +diff -pruN ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c ./drivers/ide/ide-lib.c
    56.5 +--- ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c	2006-09-12 19:02:10.000000000 +0100
    56.6 ++++ ./drivers/ide/ide-lib.c	2006-09-19 13:59:03.000000000 +0100
    56.7 +@@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *driv
    56.8 + {
    56.9 + 	u64 addr = BLK_BOUNCE_HIGH;	/* dma64_addr_t */
   56.10 + 
   56.11 +-	if (!PCI_DMA_BUS_IS_PHYS) {
   56.12 +-		addr = BLK_BOUNCE_ANY;
   56.13 +-	} else if (on && drive->media == ide_disk) {
   56.14 +-		if (HWIF(drive)->pci_dev)
   56.15 ++	if (on && drive->media == ide_disk) {
   56.16 ++		if (!PCI_DMA_BUS_IS_PHYS)
   56.17 ++			addr = BLK_BOUNCE_ANY;
   56.18 ++		else if (HWIF(drive)->pci_dev)
   56.19 + 			addr = HWIF(drive)->pci_dev->dma_mask;
   56.20 + 	}
   56.21 + 
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/patches/linux-2.6.16.29/i386-mach-io-check-nmi.patch	Sun Sep 24 13:10:13 2006 -0600
    57.3 @@ -0,0 +1,45 @@
    57.4 +diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c ./arch/i386/kernel/traps.c
    57.5 +--- ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c	2006-09-12 19:02:10.000000000 +0100
    57.6 ++++ ./arch/i386/kernel/traps.c	2006-09-19 13:59:06.000000000 +0100
    57.7 +@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
    57.8 + 
    57.9 + static void io_check_error(unsigned char reason, struct pt_regs * regs)
   57.10 + {
   57.11 +-	unsigned long i;
   57.12 +-
   57.13 + 	printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
   57.14 + 	show_registers(regs);
   57.15 + 
   57.16 + 	/* Re-enable the IOCK line, wait for a few seconds */
   57.17 +-	reason = (reason & 0xf) | 8;
   57.18 +-	outb(reason, 0x61);
   57.19 +-	i = 2000;
   57.20 +-	while (--i) udelay(1000);
   57.21 +-	reason &= ~8;
   57.22 +-	outb(reason, 0x61);
   57.23 ++	clear_io_check_error(reason);
   57.24 + }
   57.25 + 
   57.26 + static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
   57.27 +diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/mach-default/mach_traps.h ./include/asm-i386/mach-default/mach_traps.h
   57.28 +--- ../orig-linux-2.6.16.29/include/asm-i386/mach-default/mach_traps.h	2006-09-12 19:02:10.000000000 +0100
   57.29 ++++ ./include/asm-i386/mach-default/mach_traps.h	2006-09-19 13:59:06.000000000 +0100
   57.30 +@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
   57.31 + 	outb(reason, 0x61);
   57.32 + }
   57.33 + 
   57.34 ++static inline void clear_io_check_error(unsigned char reason)
   57.35 ++{
   57.36 ++	unsigned long i;
   57.37 ++
   57.38 ++	reason = (reason & 0xf) | 8;
   57.39 ++	outb(reason, 0x61);
   57.40 ++	i = 2000;
   57.41 ++	while (--i) udelay(1000);
   57.42 ++	reason &= ~8;
   57.43 ++	outb(reason, 0x61);
   57.44 ++}
   57.45 ++
   57.46 + static inline unsigned char get_nmi_reason(void)
   57.47 + {
   57.48 + 	return inb(0x61);
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/patches/linux-2.6.16.29/ipv6-no-autoconf.patch	Sun Sep 24 13:10:13 2006 -0600
    58.3 @@ -0,0 +1,19 @@
    58.4 +diff -pruN ../orig-linux-2.6.16.29/net/ipv6/addrconf.c ./net/ipv6/addrconf.c
    58.5 +--- ../orig-linux-2.6.16.29/net/ipv6/addrconf.c	2006-09-12 19:02:10.000000000 +0100
    58.6 ++++ ./net/ipv6/addrconf.c	2006-09-19 13:59:11.000000000 +0100
    58.7 +@@ -2471,6 +2471,7 @@ static void addrconf_dad_start(struct in
    58.8 + 	spin_lock_bh(&ifp->lock);
    58.9 + 
   58.10 + 	if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
   58.11 ++	    !(dev->flags&IFF_MULTICAST) ||
   58.12 + 	    !(ifp->flags&IFA_F_TENTATIVE)) {
   58.13 + 		ifp->flags &= ~IFA_F_TENTATIVE;
   58.14 + 		spin_unlock_bh(&ifp->lock);
   58.15 +@@ -2555,6 +2556,7 @@ static void addrconf_dad_completed(struc
   58.16 + 	if (ifp->idev->cnf.forwarding == 0 &&
   58.17 + 	    ifp->idev->cnf.rtr_solicits > 0 &&
   58.18 + 	    (dev->flags&IFF_LOOPBACK) == 0 &&
   58.19 ++	    (dev->flags & IFF_MULTICAST) &&
   58.20 + 	    (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
   58.21 + 		struct in6_addr all_routers;
   58.22 + 
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/patches/linux-2.6.16.29/net-csum.patch	Sun Sep 24 13:10:13 2006 -0600
    59.3 @@ -0,0 +1,63 @@
    59.4 +diff -pruN ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_tcp.c ./net/ipv4/netfilter/ip_nat_proto_tcp.c
    59.5 +--- ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-09-12 19:02:10.000000000 +0100
    59.6 ++++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c	2006-09-19 13:59:15.000000000 +0100
    59.7 +@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb,
    59.8 + 	if (hdrsize < sizeof(*hdr))
    59.9 + 		return 1;
   59.10 + 
   59.11 +-	hdr->check = ip_nat_cheat_check(~oldip, newip,
   59.12 ++#ifdef CONFIG_XEN
   59.13 ++	if ((*pskb)->proto_csum_blank)
   59.14 ++		hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   59.15 ++	else
   59.16 ++#endif
   59.17 ++		hdr->check = ip_nat_cheat_check(~oldip, newip,
   59.18 + 					ip_nat_cheat_check(oldport ^ 0xFFFF,
   59.19 + 							   newport,
   59.20 + 							   hdr->check));
   59.21 +diff -pruN ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_udp.c ./net/ipv4/netfilter/ip_nat_proto_udp.c
   59.22 +--- ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_udp.c	2006-09-12 19:02:10.000000000 +0100
   59.23 ++++ ./net/ipv4/netfilter/ip_nat_proto_udp.c	2006-09-19 13:59:15.000000000 +0100
   59.24 +@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb,
   59.25 + 		newport = tuple->dst.u.udp.port;
   59.26 + 		portptr = &hdr->dest;
   59.27 + 	}
   59.28 +-	if (hdr->check) /* 0 is a special case meaning no checksum */
   59.29 +-		hdr->check = ip_nat_cheat_check(~oldip, newip,
   59.30 ++	if (hdr->check) { /* 0 is a special case meaning no checksum */
   59.31 ++#ifdef CONFIG_XEN
   59.32 ++		if ((*pskb)->proto_csum_blank)
   59.33 ++			hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
   59.34 ++		else
   59.35 ++#endif
   59.36 ++			hdr->check = ip_nat_cheat_check(~oldip, newip,
   59.37 + 					ip_nat_cheat_check(*portptr ^ 0xFFFF,
   59.38 + 							   newport,
   59.39 + 							   hdr->check));
   59.40 ++	}
   59.41 + 	*portptr = newport;
   59.42 + 	return 1;
   59.43 + }
   59.44 +diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c ./net/ipv4/xfrm4_output.c
   59.45 +--- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c	2006-09-12 19:02:10.000000000 +0100
   59.46 ++++ ./net/ipv4/xfrm4_output.c	2006-09-19 13:59:15.000000000 +0100
   59.47 +@@ -17,6 +17,8 @@
   59.48 + #include <net/xfrm.h>
   59.49 + #include <net/icmp.h>
   59.50 + 
   59.51 ++extern int skb_checksum_setup(struct sk_buff *skb);
   59.52 ++
   59.53 + /* Add encapsulation header.
   59.54 +  *
   59.55 +  * In transport mode, the IP header will be moved forward to make space
   59.56 +@@ -103,6 +105,10 @@ static int xfrm4_output_one(struct sk_bu
   59.57 + 	struct xfrm_state *x = dst->xfrm;
   59.58 + 	int err;
   59.59 + 	
   59.60 ++	err = skb_checksum_setup(skb);
   59.61 ++	if (err)
   59.62 ++		goto error_nolock;
   59.63 ++
   59.64 + 	if (skb->ip_summed == CHECKSUM_HW) {
   59.65 + 		err = skb_checksum_help(skb, 0);
   59.66 + 		if (err)
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/patches/linux-2.6.16.29/net-gso-0-base.patch	Sun Sep 24 13:10:13 2006 -0600
    60.3 @@ -0,0 +1,2835 @@
    60.4 +diff -pruN ../orig-linux-2.6.16.29/Documentation/networking/netdevices.txt ./Documentation/networking/netdevices.txt
    60.5 +--- ../orig-linux-2.6.16.29/Documentation/networking/netdevices.txt	2006-09-12 19:02:10.000000000 +0100
    60.6 ++++ ./Documentation/networking/netdevices.txt	2006-09-19 13:59:20.000000000 +0100
    60.7 +@@ -42,9 +42,9 @@ dev->get_stats:
    60.8 + 	Context: nominally process, but don't sleep inside an rwlock
    60.9 + 
   60.10 + dev->hard_start_xmit:
   60.11 +-	Synchronization: dev->xmit_lock spinlock.
   60.12 ++	Synchronization: netif_tx_lock spinlock.
   60.13 + 	When the driver sets NETIF_F_LLTX in dev->features this will be
   60.14 +-	called without holding xmit_lock. In this case the driver 
   60.15 ++	called without holding netif_tx_lock. In this case the driver
   60.16 + 	has to lock by itself when needed. It is recommended to use a try lock
   60.17 + 	for this and return -1 when the spin lock fails. 
   60.18 + 	The locking there should also properly protect against 
   60.19 +@@ -62,12 +62,12 @@ dev->hard_start_xmit:
   60.20 + 	  Only valid when NETIF_F_LLTX is set.
   60.21 + 
   60.22 + dev->tx_timeout:
   60.23 +-	Synchronization: dev->xmit_lock spinlock.
   60.24 ++	Synchronization: netif_tx_lock spinlock.
   60.25 + 	Context: BHs disabled
   60.26 + 	Notes: netif_queue_stopped() is guaranteed true
   60.27 + 
   60.28 + dev->set_multicast_list:
   60.29 +-	Synchronization: dev->xmit_lock spinlock.
   60.30 ++	Synchronization: netif_tx_lock spinlock.
   60.31 + 	Context: BHs disabled
   60.32 + 
   60.33 + dev->poll:
   60.34 +diff -pruN ../orig-linux-2.6.16.29/drivers/block/aoe/aoenet.c ./drivers/block/aoe/aoenet.c
   60.35 +--- ../orig-linux-2.6.16.29/drivers/block/aoe/aoenet.c	2006-09-12 19:02:10.000000000 +0100
   60.36 ++++ ./drivers/block/aoe/aoenet.c	2006-09-19 13:59:20.000000000 +0100
   60.37 +@@ -95,9 +95,8 @@ mac_addr(char addr[6])
   60.38 + static struct sk_buff *
   60.39 + skb_check(struct sk_buff *skb)
   60.40 + {
   60.41 +-	if (skb_is_nonlinear(skb))
   60.42 + 	if ((skb = skb_share_check(skb, GFP_ATOMIC)))
   60.43 +-	if (skb_linearize(skb, GFP_ATOMIC) < 0) {
   60.44 ++	if (skb_linearize(skb)) {
   60.45 + 		dev_kfree_skb(skb);
   60.46 + 		return NULL;
   60.47 + 	}
   60.48 +diff -pruN ../orig-linux-2.6.16.29/drivers/infiniband/ulp/ipoib/ipoib_multicast.c ./drivers/infiniband/ulp/ipoib/ipoib_multicast.c
   60.49 +--- ../orig-linux-2.6.16.29/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2006-09-12 19:02:10.000000000 +0100
   60.50 ++++ ./drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2006-09-19 13:59:20.000000000 +0100
   60.51 +@@ -821,7 +821,8 @@ void ipoib_mcast_restart_task(void *dev_
   60.52 + 
   60.53 + 	ipoib_mcast_stop_thread(dev, 0);
   60.54 + 
   60.55 +-	spin_lock_irqsave(&dev->xmit_lock, flags);
   60.56 ++	local_irq_save(flags);
   60.57 ++	netif_tx_lock(dev);
   60.58 + 	spin_lock(&priv->lock);
   60.59 + 
   60.60 + 	/*
   60.61 +@@ -896,7 +897,8 @@ void ipoib_mcast_restart_task(void *dev_
   60.62 + 	}
   60.63 + 
   60.64 + 	spin_unlock(&priv->lock);
   60.65 +-	spin_unlock_irqrestore(&dev->xmit_lock, flags);
   60.66 ++	netif_tx_unlock(dev);
   60.67 ++	local_irq_restore(flags);
   60.68 + 
   60.69 + 	/* We have to cancel outside of the spinlock */
   60.70 + 	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
   60.71 +diff -pruN ../orig-linux-2.6.16.29/drivers/media/dvb/dvb-core/dvb_net.c ./drivers/media/dvb/dvb-core/dvb_net.c
   60.72 +--- ../orig-linux-2.6.16.29/drivers/media/dvb/dvb-core/dvb_net.c	2006-09-12 19:02:10.000000000 +0100
   60.73 ++++ ./drivers/media/dvb/dvb-core/dvb_net.c	2006-09-19 13:59:20.000000000 +0100
   60.74 +@@ -1052,7 +1052,7 @@ static void wq_set_multicast_list (void 
   60.75 + 
   60.76 + 	dvb_net_feed_stop(dev);
   60.77 + 	priv->rx_mode = RX_MODE_UNI;
   60.78 +-	spin_lock_bh(&dev->xmit_lock);
   60.79 ++	netif_tx_lock_bh(dev);
   60.80 + 
   60.81 + 	if (dev->flags & IFF_PROMISC) {
   60.82 + 		dprintk("%s: promiscuous mode\n", dev->name);
   60.83 +@@ -1077,7 +1077,7 @@ static void wq_set_multicast_list (void 
   60.84 + 		}
   60.85 + 	}
   60.86 + 
   60.87 +-	spin_unlock_bh(&dev->xmit_lock);
   60.88 ++	netif_tx_unlock_bh(dev);
   60.89 + 	dvb_net_feed_start(dev);
   60.90 + }
   60.91 + 
   60.92 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/8139cp.c ./drivers/net/8139cp.c
   60.93 +--- ../orig-linux-2.6.16.29/drivers/net/8139cp.c	2006-09-12 19:02:10.000000000 +0100
   60.94 ++++ ./drivers/net/8139cp.c	2006-09-19 13:59:20.000000000 +0100
   60.95 +@@ -794,7 +794,7 @@ static int cp_start_xmit (struct sk_buff
   60.96 + 	entry = cp->tx_head;
   60.97 + 	eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
   60.98 + 	if (dev->features & NETIF_F_TSO)
   60.99 +-		mss = skb_shinfo(skb)->tso_size;
  60.100 ++		mss = skb_shinfo(skb)->gso_size;
  60.101 + 
  60.102 + 	if (skb_shinfo(skb)->nr_frags == 0) {
  60.103 + 		struct cp_desc *txd = &cp->tx_ring[entry];
  60.104 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/bnx2.c ./drivers/net/bnx2.c
  60.105 +--- ../orig-linux-2.6.16.29/drivers/net/bnx2.c	2006-09-12 19:02:10.000000000 +0100
  60.106 ++++ ./drivers/net/bnx2.c	2006-09-19 13:59:20.000000000 +0100
  60.107 +@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
  60.108 + 		skb = tx_buf->skb;
  60.109 + #ifdef BCM_TSO 
  60.110 + 		/* partial BD completions possible with TSO packets */
  60.111 +-		if (skb_shinfo(skb)->tso_size) {
  60.112 ++		if (skb_shinfo(skb)->gso_size) {
  60.113 + 			u16 last_idx, last_ring_idx;
  60.114 + 
  60.115 + 			last_idx = sw_cons +
  60.116 +@@ -1948,7 +1948,7 @@ bnx2_poll(struct net_device *dev, int *b
  60.117 + 	return 1;
  60.118 + }
  60.119 + 
  60.120 +-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
  60.121 ++/* Called with rtnl_lock from vlan functions and also netif_tx_lock
  60.122 +  * from set_multicast.
  60.123 +  */
  60.124 + static void
  60.125 +@@ -4403,7 +4403,7 @@ bnx2_vlan_rx_kill_vid(struct net_device 
  60.126 + }
  60.127 + #endif
  60.128 + 
  60.129 +-/* Called with dev->xmit_lock.
  60.130 ++/* Called with netif_tx_lock.
  60.131 +  * hard_start_xmit is pseudo-lockless - a lock is only required when
  60.132 +  * the tx queue is full. This way, we get the benefit of lockless
  60.133 +  * operations most of the time without the complexities to handle
  60.134 +@@ -4441,7 +4441,7 @@ bnx2_start_xmit(struct sk_buff *skb, str
  60.135 + 			(TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
  60.136 + 	}
  60.137 + #ifdef BCM_TSO 
  60.138 +-	if ((mss = skb_shinfo(skb)->tso_size) &&
  60.139 ++	if ((mss = skb_shinfo(skb)->gso_size) &&
  60.140 + 		(skb->len > (bp->dev->mtu + ETH_HLEN))) {
  60.141 + 		u32 tcp_opt_len, ip_tcp_len;
  60.142 + 
  60.143 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/bonding/bond_main.c ./drivers/net/bonding/bond_main.c
  60.144 +--- ../orig-linux-2.6.16.29/drivers/net/bonding/bond_main.c	2006-09-12 19:02:10.000000000 +0100
  60.145 ++++ ./drivers/net/bonding/bond_main.c	2006-09-19 13:59:20.000000000 +0100
  60.146 +@@ -1145,8 +1145,7 @@ int bond_sethwaddr(struct net_device *bo
  60.147 + }
  60.148 + 
  60.149 + #define BOND_INTERSECT_FEATURES \
  60.150 +-	(NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
  60.151 +-	NETIF_F_TSO|NETIF_F_UFO)
  60.152 ++	(NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
  60.153 + 
  60.154 + /* 
  60.155 +  * Compute the common dev->feature set available to all slaves.  Some
  60.156 +@@ -1164,9 +1163,7 @@ static int bond_compute_features(struct 
  60.157 + 		features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
  60.158 + 
  60.159 + 	if ((features & NETIF_F_SG) && 
  60.160 +-	    !(features & (NETIF_F_IP_CSUM |
  60.161 +-			  NETIF_F_NO_CSUM |
  60.162 +-			  NETIF_F_HW_CSUM)))
  60.163 ++	    !(features & NETIF_F_ALL_CSUM))
  60.164 + 		features &= ~NETIF_F_SG;
  60.165 + 
  60.166 + 	/* 
  60.167 +@@ -4147,7 +4144,7 @@ static int bond_init(struct net_device *
  60.168 + 	 */
  60.169 + 	bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
  60.170 + 
  60.171 +-	/* don't acquire bond device's xmit_lock when 
  60.172 ++	/* don't acquire bond device's netif_tx_lock when
  60.173 + 	 * transmitting */
  60.174 + 	bond_dev->features |= NETIF_F_LLTX;
  60.175 + 
  60.176 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c ./drivers/net/chelsio/sge.c
  60.177 +--- ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c	2006-09-12 19:02:10.000000000 +0100
  60.178 ++++ ./drivers/net/chelsio/sge.c	2006-09-19 13:59:20.000000000 +0100
  60.179 +@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
  60.180 + 	struct cpl_tx_pkt *cpl;
  60.181 + 
  60.182 + #ifdef NETIF_F_TSO
  60.183 +-	if (skb_shinfo(skb)->tso_size) {
  60.184 ++	if (skb_shinfo(skb)->gso_size) {
  60.185 + 		int eth_type;
  60.186 + 		struct cpl_tx_pkt_lso *hdr;
  60.187 + 
  60.188 +@@ -1434,7 +1434,7 @@ int t1_start_xmit(struct sk_buff *skb, s
  60.189 + 		hdr->ip_hdr_words = skb->nh.iph->ihl;
  60.190 + 		hdr->tcp_hdr_words = skb->h.th->doff;
  60.191 + 		hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
  60.192 +-						skb_shinfo(skb)->tso_size));
  60.193 ++						skb_shinfo(skb)->gso_size));
  60.194 + 		hdr->len = htonl(skb->len - sizeof(*hdr));
  60.195 + 		cpl = (struct cpl_tx_pkt *)hdr;
  60.196 + 		sge->stats.tx_lso_pkts++;
  60.197 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c ./drivers/net/e1000/e1000_main.c
  60.198 +--- ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c	2006-09-12 19:02:10.000000000 +0100
  60.199 ++++ ./drivers/net/e1000/e1000_main.c	2006-09-19 13:59:20.000000000 +0100
  60.200 +@@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
  60.201 + 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
  60.202 + 	int err;
  60.203 + 
  60.204 +-	if (skb_shinfo(skb)->tso_size) {
  60.205 ++	if (skb_shinfo(skb)->gso_size) {
  60.206 + 		if (skb_header_cloned(skb)) {
  60.207 + 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
  60.208 + 			if (err)
  60.209 +@@ -2534,7 +2534,7 @@ e1000_tso(struct e1000_adapter *adapter,
  60.210 + 		}
  60.211 + 
  60.212 + 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
  60.213 +-		mss = skb_shinfo(skb)->tso_size;
  60.214 ++		mss = skb_shinfo(skb)->gso_size;
  60.215 + 		if (skb->protocol == ntohs(ETH_P_IP)) {
  60.216 + 			skb->nh.iph->tot_len = 0;
  60.217 + 			skb->nh.iph->check = 0;
  60.218 +@@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
  60.219 + 		 * tso gets written back prematurely before the data is fully
  60.220 + 		 * DMAd to the controller */
  60.221 + 		if (!skb->data_len && tx_ring->last_tx_tso &&
  60.222 +-				!skb_shinfo(skb)->tso_size) {
  60.223 ++				!skb_shinfo(skb)->gso_size) {
  60.224 + 			tx_ring->last_tx_tso = 0;
  60.225 + 			size -= 4;
  60.226 + 		}
  60.227 +@@ -2893,7 +2893,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
  60.228 + 	}
  60.229 + 
  60.230 + #ifdef NETIF_F_TSO
  60.231 +-	mss = skb_shinfo(skb)->tso_size;
  60.232 ++	mss = skb_shinfo(skb)->gso_size;
  60.233 + 	/* The controller does a simple calculation to 
  60.234 + 	 * make sure there is enough room in the FIFO before
  60.235 + 	 * initiating the DMA for each buffer.  The calc is:
  60.236 +@@ -2935,7 +2935,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
  60.237 + #ifdef NETIF_F_TSO
  60.238 + 	/* Controller Erratum workaround */
  60.239 + 	if (!skb->data_len && tx_ring->last_tx_tso &&
  60.240 +-		!skb_shinfo(skb)->tso_size)
  60.241 ++		!skb_shinfo(skb)->gso_size)
  60.242 + 		count++;
  60.243 + #endif
  60.244 + 
  60.245 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/forcedeth.c ./drivers/net/forcedeth.c
  60.246 +--- ../orig-linux-2.6.16.29/drivers/net/forcedeth.c	2006-09-12 19:02:10.000000000 +0100
  60.247 ++++ ./drivers/net/forcedeth.c	2006-09-19 13:59:20.000000000 +0100
  60.248 +@@ -482,9 +482,9 @@ typedef union _ring_type {
  60.249 +  * critical parts:
  60.250 +  * - rx is (pseudo-) lockless: it relies on the single-threading provided
  60.251 +  *	by the arch code for interrupts.
  60.252 +- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
  60.253 ++ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
  60.254 +  *	needs dev->priv->lock :-(
  60.255 +- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
  60.256 ++ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
  60.257 +  */
  60.258 + 
  60.259 + /* in dev: base, irq */
  60.260 +@@ -1016,7 +1016,7 @@ static void drain_ring(struct net_device
  60.261 + 
  60.262 + /*
  60.263 +  * nv_start_xmit: dev->hard_start_xmit function
  60.264 +- * Called with dev->xmit_lock held.
  60.265 ++ * Called with netif_tx_lock held.
  60.266 +  */
  60.267 + static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
  60.268 + {
  60.269 +@@ -1105,8 +1105,8 @@ static int nv_start_xmit(struct sk_buff 
  60.270 + 	np->tx_skbuff[nr] = skb;
  60.271 + 
  60.272 + #ifdef NETIF_F_TSO
  60.273 +-	if (skb_shinfo(skb)->tso_size)
  60.274 +-		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size << NV_TX2_TSO_SHIFT);
  60.275 ++	if (skb_shinfo(skb)->gso_size)
  60.276 ++		tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size << NV_TX2_TSO_SHIFT);
  60.277 + 	else
  60.278 + #endif
  60.279 + 	tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ? (NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
  60.280 +@@ -1203,7 +1203,7 @@ static void nv_tx_done(struct net_device
  60.281 + 
  60.282 + /*
  60.283 +  * nv_tx_timeout: dev->tx_timeout function
  60.284 +- * Called with dev->xmit_lock held.
  60.285 ++ * Called with netif_tx_lock held.
  60.286 +  */
  60.287 + static void nv_tx_timeout(struct net_device *dev)
  60.288 + {
  60.289 +@@ -1524,7 +1524,7 @@ static int nv_change_mtu(struct net_devi
  60.290 + 		 * Changing the MTU is a rare event, it shouldn't matter.
  60.291 + 		 */
  60.292 + 		disable_irq(dev->irq);
  60.293 +-		spin_lock_bh(&dev->xmit_lock);
  60.294 ++		netif_tx_lock_bh(dev);
  60.295 + 		spin_lock(&np->lock);
  60.296 + 		/* stop engines */
  60.297 + 		nv_stop_rx(dev);
  60.298 +@@ -1559,7 +1559,7 @@ static int nv_change_mtu(struct net_devi
  60.299 + 		nv_start_rx(dev);
  60.300 + 		nv_start_tx(dev);
  60.301 + 		spin_unlock(&np->lock);
  60.302 +-		spin_unlock_bh(&dev->xmit_lock);
  60.303 ++		netif_tx_unlock_bh(dev);
  60.304 + 		enable_irq(dev->irq);
  60.305 + 	}
  60.306 + 	return 0;
  60.307 +@@ -1594,7 +1594,7 @@ static int nv_set_mac_address(struct net
  60.308 + 	memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
  60.309 + 
  60.310 + 	if (netif_running(dev)) {
  60.311 +-		spin_lock_bh(&dev->xmit_lock);
  60.312 ++		netif_tx_lock_bh(dev);
  60.313 + 		spin_lock_irq(&np->lock);
  60.314 + 
  60.315 + 		/* stop rx engine */
  60.316 +@@ -1606,7 +1606,7 @@ static int nv_set_mac_address(struct net
  60.317 + 		/* restart rx engine */
  60.318 + 		nv_start_rx(dev);
  60.319 + 		spin_unlock_irq(&np->lock);
  60.320 +-		spin_unlock_bh(&dev->xmit_lock);
  60.321 ++		netif_tx_unlock_bh(dev);
  60.322 + 	} else {
  60.323 + 		nv_copy_mac_to_hw(dev);
  60.324 + 	}
  60.325 +@@ -1615,7 +1615,7 @@ static int nv_set_mac_address(struct net
  60.326 + 
  60.327 + /*
  60.328 +  * nv_set_multicast: dev->set_multicast function
  60.329 +- * Called with dev->xmit_lock held.
  60.330 ++ * Called with netif_tx_lock held.
  60.331 +  */
  60.332 + static void nv_set_multicast(struct net_device *dev)
  60.333 + {
  60.334 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/hamradio/6pack.c ./drivers/net/hamradio/6pack.c
  60.335 +--- ../orig-linux-2.6.16.29/drivers/net/hamradio/6pack.c	2006-09-12 19:02:10.000000000 +0100
  60.336 ++++ ./drivers/net/hamradio/6pack.c	2006-09-19 13:59:20.000000000 +0100
  60.337 +@@ -308,9 +308,9 @@ static int sp_set_mac_address(struct net
  60.338 + {
  60.339 + 	struct sockaddr_ax25 *sa = addr;
  60.340 + 
  60.341 +-	spin_lock_irq(&dev->xmit_lock);
  60.342 ++	netif_tx_lock_bh(dev);
  60.343 + 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
  60.344 +-	spin_unlock_irq(&dev->xmit_lock);
  60.345 ++	netif_tx_unlock_bh(dev);
  60.346 + 
  60.347 + 	return 0;
  60.348 + }
  60.349 +@@ -767,9 +767,9 @@ static int sixpack_ioctl(struct tty_stru
  60.350 + 			break;
  60.351 + 		}
  60.352 + 
  60.353 +-		spin_lock_irq(&dev->xmit_lock);
  60.354 ++		netif_tx_lock_bh(dev);
  60.355 + 		memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
  60.356 +-		spin_unlock_irq(&dev->xmit_lock);
  60.357 ++		netif_tx_unlock_bh(dev);
  60.358 + 
  60.359 + 		err = 0;
  60.360 + 		break;
  60.361 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/hamradio/mkiss.c ./drivers/net/hamradio/mkiss.c
  60.362 +--- ../orig-linux-2.6.16.29/drivers/net/hamradio/mkiss.c	2006-09-12 19:02:10.000000000 +0100
  60.363 ++++ ./drivers/net/hamradio/mkiss.c	2006-09-19 13:59:20.000000000 +0100
  60.364 +@@ -357,9 +357,9 @@ static int ax_set_mac_address(struct net
  60.365 + {
  60.366 + 	struct sockaddr_ax25 *sa = addr;
  60.367 + 
  60.368 +-	spin_lock_irq(&dev->xmit_lock);
  60.369 ++	netif_tx_lock_bh(dev);
  60.370 + 	memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
  60.371 +-	spin_unlock_irq(&dev->xmit_lock);
  60.372 ++	netif_tx_unlock_bh(dev);
  60.373 + 
  60.374 + 	return 0;
  60.375 + }
  60.376 +@@ -886,9 +886,9 @@ static int mkiss_ioctl(struct tty_struct
  60.377 + 			break;
  60.378 + 		}
  60.379 + 
  60.380 +-		spin_lock_irq(&dev->xmit_lock);
  60.381 ++		netif_tx_lock_bh(dev);
  60.382 + 		memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
  60.383 +-		spin_unlock_irq(&dev->xmit_lock);
  60.384 ++		netif_tx_unlock_bh(dev);
  60.385 + 
  60.386 + 		err = 0;
  60.387 + 		break;
  60.388 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/ifb.c ./drivers/net/ifb.c
  60.389 +--- ../orig-linux-2.6.16.29/drivers/net/ifb.c	2006-09-12 19:02:10.000000000 +0100
  60.390 ++++ ./drivers/net/ifb.c	2006-09-19 13:59:20.000000000 +0100
  60.391 +@@ -76,13 +76,13 @@ static void ri_tasklet(unsigned long dev
  60.392 + 	dp->st_task_enter++;
  60.393 + 	if ((skb = skb_peek(&dp->tq)) == NULL) {
  60.394 + 		dp->st_txq_refl_try++;
  60.395 +-		if (spin_trylock(&_dev->xmit_lock)) {
  60.396 ++		if (netif_tx_trylock(_dev)) {
  60.397 + 			dp->st_rxq_enter++;
  60.398 + 			while ((skb = skb_dequeue(&dp->rq)) != NULL) {
  60.399 + 				skb_queue_tail(&dp->tq, skb);
  60.400 + 				dp->st_rx2tx_tran++;
  60.401 + 			}
  60.402 +-			spin_unlock(&_dev->xmit_lock);
  60.403 ++			netif_tx_unlock(_dev);
  60.404 + 		} else {
  60.405 + 			/* reschedule */
  60.406 + 			dp->st_rxq_notenter++;
  60.407 +@@ -110,7 +110,7 @@ static void ri_tasklet(unsigned long dev
  60.408 + 		}
  60.409 + 	}
  60.410 + 
  60.411 +-	if (spin_trylock(&_dev->xmit_lock)) {
  60.412 ++	if (netif_tx_trylock(_dev)) {
  60.413 + 		dp->st_rxq_check++;
  60.414 + 		if ((skb = skb_peek(&dp->rq)) == NULL) {
  60.415 + 			dp->tasklet_pending = 0;
  60.416 +@@ -118,10 +118,10 @@ static void ri_tasklet(unsigned long dev
  60.417 + 				netif_wake_queue(_dev);
  60.418 + 		} else {
  60.419 + 			dp->st_rxq_rsch++;
  60.420 +-			spin_unlock(&_dev->xmit_lock);
  60.421 ++			netif_tx_unlock(_dev);
  60.422 + 			goto resched;
  60.423 + 		}
  60.424 +-		spin_unlock(&_dev->xmit_lock);
  60.425 ++		netif_tx_unlock(_dev);
  60.426 + 	} else {
  60.427 + resched:
  60.428 + 		dp->tasklet_pending = 1;
  60.429 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/irda/vlsi_ir.c ./drivers/net/irda/vlsi_ir.c
  60.430 +--- ../orig-linux-2.6.16.29/drivers/net/irda/vlsi_ir.c	2006-09-12 19:02:10.000000000 +0100
  60.431 ++++ ./drivers/net/irda/vlsi_ir.c	2006-09-19 13:59:20.000000000 +0100
  60.432 +@@ -959,7 +959,7 @@ static int vlsi_hard_start_xmit(struct s
  60.433 + 			    ||  (now.tv_sec==ready.tv_sec && now.tv_usec>=ready.tv_usec))
  60.434 + 			    	break;
  60.435 + 			udelay(100);
  60.436 +-			/* must not sleep here - we are called under xmit_lock! */
  60.437 ++			/* must not sleep here - called under netif_tx_lock! */
  60.438 + 		}
  60.439 + 	}
  60.440 + 
  60.441 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c ./drivers/net/ixgb/ixgb_main.c
  60.442 +--- ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c	2006-09-12 19:02:10.000000000 +0100
  60.443 ++++ ./drivers/net/ixgb/ixgb_main.c	2006-09-19 13:59:20.000000000 +0100
  60.444 +@@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
  60.445 + 	uint16_t ipcse, tucse, mss;
  60.446 + 	int err;
  60.447 + 
  60.448 +-	if(likely(skb_shinfo(skb)->tso_size)) {
  60.449 ++	if(likely(skb_shinfo(skb)->gso_size)) {
  60.450 + 		if (skb_header_cloned(skb)) {
  60.451 + 			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
  60.452 + 			if (err)
  60.453 +@@ -1171,7 +1171,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
  60.454 + 		}
  60.455 + 
  60.456 + 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
  60.457 +-		mss = skb_shinfo(skb)->tso_size;
  60.458 ++		mss = skb_shinfo(skb)->gso_size;
  60.459 + 		skb->nh.iph->tot_len = 0;
  60.460 + 		skb->nh.iph->check = 0;
  60.461 + 		skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
  60.462 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/loopback.c ./drivers/net/loopback.c
  60.463 +--- ../orig-linux-2.6.16.29/drivers/net/loopback.c	2006-09-12 19:02:10.000000000 +0100
  60.464 ++++ ./drivers/net/loopback.c	2006-09-19 13:59:20.000000000 +0100
  60.465 +@@ -74,7 +74,7 @@ static void emulate_large_send_offload(s
  60.466 + 	struct iphdr *iph = skb->nh.iph;
  60.467 + 	struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4));
  60.468 + 	unsigned int doffset = (iph->ihl + th->doff) * 4;
  60.469 +-	unsigned int mtu = skb_shinfo(skb)->tso_size + doffset;
  60.470 ++	unsigned int mtu = skb_shinfo(skb)->gso_size + doffset;
  60.471 + 	unsigned int offset = 0;
  60.472 + 	u32 seq = ntohl(th->seq);
  60.473 + 	u16 id  = ntohs(iph->id);
  60.474 +@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff 
  60.475 + #endif
  60.476 + 
  60.477 + #ifdef LOOPBACK_TSO
  60.478 +-	if (skb_shinfo(skb)->tso_size) {
  60.479 ++	if (skb_shinfo(skb)->gso_size) {
  60.480 + 		BUG_ON(skb->protocol != htons(ETH_P_IP));
  60.481 + 		BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
  60.482 + 
  60.483 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/mv643xx_eth.c ./drivers/net/mv643xx_eth.c
  60.484 +--- ../orig-linux-2.6.16.29/drivers/net/mv643xx_eth.c	2006-09-12 19:02:10.000000000 +0100
  60.485 ++++ ./drivers/net/mv643xx_eth.c	2006-09-19 13:59:20.000000000 +0100
  60.486 +@@ -1107,7 +1107,7 @@ static int mv643xx_eth_start_xmit(struct
  60.487 + 
  60.488 + #ifdef MV643XX_CHECKSUM_OFFLOAD_TX
  60.489 + 	if (has_tiny_unaligned_frags(skb)) {
  60.490 +-		if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
  60.491 ++		if (__skb_linearize(skb)) {
  60.492 + 			stats->tx_dropped++;
  60.493 + 			printk(KERN_DEBUG "%s: failed to linearize tiny "
  60.494 + 					"unaligned fragment\n", dev->name);
  60.495 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/natsemi.c ./drivers/net/natsemi.c
  60.496 +--- ../orig-linux-2.6.16.29/drivers/net/natsemi.c	2006-09-12 19:02:10.000000000 +0100
  60.497 ++++ ./drivers/net/natsemi.c	2006-09-19 13:59:20.000000000 +0100
  60.498 +@@ -323,12 +323,12 @@ performance critical codepaths:
  60.499 + The rx process only runs in the interrupt handler. Access from outside
  60.500 + the interrupt handler is only permitted after disable_irq().
  60.501 + 
  60.502 +-The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
  60.503 ++The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
  60.504 + is set, then access is permitted under spin_lock_irq(&np->lock).
  60.505 + 
  60.506 + Thus configuration functions that want to access everything must call
  60.507 + 	disable_irq(dev->irq);
  60.508 +-	spin_lock_bh(dev->xmit_lock);
  60.509 ++	netif_tx_lock_bh(dev);
  60.510 + 	spin_lock_irq(&np->lock);
  60.511 + 
  60.512 + IV. Notes
  60.513 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/r8169.c ./drivers/net/r8169.c
  60.514 +--- ../orig-linux-2.6.16.29/drivers/net/r8169.c	2006-09-12 19:02:10.000000000 +0100
  60.515 ++++ ./drivers/net/r8169.c	2006-09-19 13:59:20.000000000 +0100
  60.516 +@@ -2171,7 +2171,7 @@ static int rtl8169_xmit_frags(struct rtl
  60.517 + static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device *dev)
  60.518 + {
  60.519 + 	if (dev->features & NETIF_F_TSO) {
  60.520 +-		u32 mss = skb_shinfo(skb)->tso_size;
  60.521 ++		u32 mss = skb_shinfo(skb)->gso_size;
  60.522 + 
  60.523 + 		if (mss)
  60.524 + 			return LargeSend | ((mss & MSSMask) << MSSShift);
  60.525 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/s2io.c ./drivers/net/s2io.c
  60.526 +--- ../orig-linux-2.6.16.29/drivers/net/s2io.c	2006-09-12 19:02:10.000000000 +0100
  60.527 ++++ ./drivers/net/s2io.c	2006-09-19 13:59:20.000000000 +0100
  60.528 +@@ -3522,8 +3522,8 @@ static int s2io_xmit(struct sk_buff *skb
  60.529 + 	txdp->Control_1 = 0;
  60.530 + 	txdp->Control_2 = 0;
  60.531 + #ifdef NETIF_F_TSO
  60.532 +-	mss = skb_shinfo(skb)->tso_size;
  60.533 +-	if (mss) {
  60.534 ++	mss = skb_shinfo(skb)->gso_size;
  60.535 ++	if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
  60.536 + 		txdp->Control_1 |= TXD_TCP_LSO_EN;
  60.537 + 		txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
  60.538 + 	}
  60.539 +@@ -3543,10 +3543,10 @@ static int s2io_xmit(struct sk_buff *skb
  60.540 + 	}
  60.541 + 
  60.542 + 	frg_len = skb->len - skb->data_len;
  60.543 +-	if (skb_shinfo(skb)->ufo_size) {
  60.544 ++	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
  60.545 + 		int ufo_size;
  60.546 + 
  60.547 +-		ufo_size = skb_shinfo(skb)->ufo_size;
  60.548 ++		ufo_size = skb_shinfo(skb)->gso_size;
  60.549 + 		ufo_size &= ~7;
  60.550 + 		txdp->Control_1 |= TXD_UFO_EN;
  60.551 + 		txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
  60.552 +@@ -3572,7 +3572,7 @@ static int s2io_xmit(struct sk_buff *skb
  60.553 + 	txdp->Host_Control = (unsigned long) skb;
  60.554 + 	txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
  60.555 + 
  60.556 +-	if (skb_shinfo(skb)->ufo_size)
  60.557 ++	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  60.558 + 		txdp->Control_1 |= TXD_UFO_EN;
  60.559 + 
  60.560 + 	frg_cnt = skb_shinfo(skb)->nr_frags;
  60.561 +@@ -3587,12 +3587,12 @@ static int s2io_xmit(struct sk_buff *skb
  60.562 + 		    (sp->pdev, frag->page, frag->page_offset,
  60.563 + 		     frag->size, PCI_DMA_TODEVICE);
  60.564 + 		txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
  60.565 +-		if (skb_shinfo(skb)->ufo_size)
  60.566 ++		if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  60.567 + 			txdp->Control_1 |= TXD_UFO_EN;
  60.568 + 	}
  60.569 + 	txdp->Control_1 |= TXD_GATHER_CODE_LAST;
  60.570 + 
  60.571 +-	if (skb_shinfo(skb)->ufo_size)
  60.572 ++	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  60.573 + 		frg_cnt++; /* as Txd0 was used for inband header */
  60.574 + 
  60.575 + 	tx_fifo = mac_control->tx_FIFO_start[queue];
  60.576 +@@ -3606,7 +3606,7 @@ static int s2io_xmit(struct sk_buff *skb
  60.577 + 	if (mss)
  60.578 + 		val64 |= TX_FIFO_SPECIAL_FUNC;
  60.579 + #endif
  60.580 +-	if (skb_shinfo(skb)->ufo_size)
  60.581 ++	if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
  60.582 + 		val64 |= TX_FIFO_SPECIAL_FUNC;
  60.583 + 	writeq(val64, &tx_fifo->List_Control);
  60.584 + 
  60.585 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/sky2.c ./drivers/net/sky2.c
  60.586 +--- ../orig-linux-2.6.16.29/drivers/net/sky2.c	2006-09-12 19:02:10.000000000 +0100
  60.587 ++++ ./drivers/net/sky2.c	2006-09-19 13:59:20.000000000 +0100
  60.588 +@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
  60.589 + 	count = sizeof(dma_addr_t) / sizeof(u32);
  60.590 + 	count += skb_shinfo(skb)->nr_frags * count;
  60.591 + 
  60.592 +-	if (skb_shinfo(skb)->tso_size)
  60.593 ++	if (skb_shinfo(skb)->gso_size)
  60.594 + 		++count;
  60.595 + 
  60.596 + 	if (skb->ip_summed == CHECKSUM_HW)
  60.597 +@@ -1197,7 +1197,7 @@ static int sky2_xmit_frame(struct sk_buf
  60.598 + 	}
  60.599 + 
  60.600 + 	/* Check for TCP Segmentation Offload */
  60.601 +-	mss = skb_shinfo(skb)->tso_size;
  60.602 ++	mss = skb_shinfo(skb)->gso_size;
  60.603 + 	if (mss != 0) {
  60.604 + 		/* just drop the packet if non-linear expansion fails */
  60.605 + 		if (skb_header_cloned(skb) &&
  60.606 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/tg3.c ./drivers/net/tg3.c
  60.607 +--- ../orig-linux-2.6.16.29/drivers/net/tg3.c	2006-09-12 19:02:10.000000000 +0100
  60.608 ++++ ./drivers/net/tg3.c	2006-09-19 13:59:20.000000000 +0100
  60.609 +@@ -3664,7 +3664,7 @@ static int tg3_start_xmit(struct sk_buff
  60.610 + #if TG3_TSO_SUPPORT != 0
  60.611 + 	mss = 0;
  60.612 + 	if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
  60.613 +-	    (mss = skb_shinfo(skb)->tso_size) != 0) {
  60.614 ++	    (mss = skb_shinfo(skb)->gso_size) != 0) {
  60.615 + 		int tcp_opt_len, ip_tcp_len;
  60.616 + 
  60.617 + 		if (skb_header_cloned(skb) &&
  60.618 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/tulip/winbond-840.c ./drivers/net/tulip/winbond-840.c
  60.619 +--- ../orig-linux-2.6.16.29/drivers/net/tulip/winbond-840.c	2006-09-12 19:02:10.000000000 +0100
  60.620 ++++ ./drivers/net/tulip/winbond-840.c	2006-09-19 13:59:20.000000000 +0100
  60.621 +@@ -1605,11 +1605,11 @@ static void __devexit w840_remove1 (stru
  60.622 +  * - get_stats:
  60.623 +  * 	spin_lock_irq(np->lock), doesn't touch hw if not present
  60.624 +  * - hard_start_xmit:
  60.625 +- * 	netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
  60.626 ++ * 	synchronize_irq + netif_tx_disable;
  60.627 +  * - tx_timeout:
  60.628 +- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  60.629 ++ * 	netif_device_detach + netif_tx_disable;
  60.630 +  * - set_multicast_list
  60.631 +- * 	netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  60.632 ++ * 	netif_device_detach + netif_tx_disable;
  60.633 +  * - interrupt handler
  60.634 +  * 	doesn't touch hw if not present, synchronize_irq waits for
  60.635 +  * 	running instances of the interrupt handler.
  60.636 +@@ -1635,11 +1635,10 @@ static int w840_suspend (struct pci_dev 
  60.637 + 		netif_device_detach(dev);
  60.638 + 		update_csr6(dev, 0);
  60.639 + 		iowrite32(0, ioaddr + IntrEnable);
  60.640 +-		netif_stop_queue(dev);
  60.641 + 		spin_unlock_irq(&np->lock);
  60.642 + 
  60.643 +-		spin_unlock_wait(&dev->xmit_lock);
  60.644 + 		synchronize_irq(dev->irq);
  60.645 ++		netif_tx_disable(dev);
  60.646 + 	
  60.647 + 		np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
  60.648 + 
  60.649 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/typhoon.c ./drivers/net/typhoon.c
  60.650 +--- ../orig-linux-2.6.16.29/drivers/net/typhoon.c	2006-09-12 19:02:10.000000000 +0100
  60.651 ++++ ./drivers/net/typhoon.c	2006-09-19 13:59:20.000000000 +0100
  60.652 +@@ -340,7 +340,7 @@ enum state_values {
  60.653 + #endif
  60.654 + 
  60.655 + #if defined(NETIF_F_TSO)
  60.656 +-#define skb_tso_size(x)		(skb_shinfo(x)->tso_size)
  60.657 ++#define skb_tso_size(x)		(skb_shinfo(x)->gso_size)
  60.658 + #define TSO_NUM_DESCRIPTORS	2
  60.659 + #define TSO_OFFLOAD_ON		TYPHOON_OFFLOAD_TCP_SEGMENT
  60.660 + #else
  60.661 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/via-velocity.c ./drivers/net/via-velocity.c
  60.662 +--- ../orig-linux-2.6.16.29/drivers/net/via-velocity.c	2006-09-12 19:02:10.000000000 +0100
  60.663 ++++ ./drivers/net/via-velocity.c	2006-09-19 13:59:20.000000000 +0100
  60.664 +@@ -1899,6 +1899,13 @@ static int velocity_xmit(struct sk_buff 
  60.665 + 
  60.666 + 	int pktlen = skb->len;
  60.667 + 
  60.668 ++#ifdef VELOCITY_ZERO_COPY_SUPPORT
  60.669 ++	if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
  60.670 ++		kfree_skb(skb);
  60.671 ++		return 0;
  60.672 ++	}
  60.673 ++#endif
  60.674 ++
  60.675 + 	spin_lock_irqsave(&vptr->lock, flags);
  60.676 + 
  60.677 + 	index = vptr->td_curr[qnum];
  60.678 +@@ -1914,8 +1921,6 @@ static int velocity_xmit(struct sk_buff 
  60.679 + 	 */
  60.680 + 	if (pktlen < ETH_ZLEN) {
  60.681 + 		/* Cannot occur until ZC support */
  60.682 +-		if(skb_linearize(skb, GFP_ATOMIC))
  60.683 +-			return 0; 
  60.684 + 		pktlen = ETH_ZLEN;
  60.685 + 		memcpy(tdinfo->buf, skb->data, skb->len);
  60.686 + 		memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
  60.687 +@@ -1933,7 +1938,6 @@ static int velocity_xmit(struct sk_buff 
  60.688 + 		int nfrags = skb_shinfo(skb)->nr_frags;
  60.689 + 		tdinfo->skb = skb;
  60.690 + 		if (nfrags > 6) {
  60.691 +-			skb_linearize(skb, GFP_ATOMIC);
  60.692 + 			memcpy(tdinfo->buf, skb->data, skb->len);
  60.693 + 			tdinfo->skb_dma[0] = tdinfo->buf_dma;
  60.694 + 			td_ptr->tdesc0.pktsize = 
  60.695 +diff -pruN ../orig-linux-2.6.16.29/drivers/net/wireless/orinoco.c ./drivers/net/wireless/orinoco.c
  60.696 +--- ../orig-linux-2.6.16.29/drivers/net/wireless/orinoco.c	2006-09-12 19:02:10.000000000 +0100
  60.697 ++++ ./drivers/net/wireless/orinoco.c	2006-09-19 13:59:20.000000000 +0100
  60.698 +@@ -1835,7 +1835,9 @@ static int __orinoco_program_rids(struct
  60.699 + 	/* Set promiscuity / multicast*/
  60.700 + 	priv->promiscuous = 0;
  60.701 + 	priv->mc_count = 0;
  60.702 +-	__orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
  60.703 ++
  60.704 ++	/* FIXME: what about netif_tx_lock */
  60.705 ++	__orinoco_set_multicast_list(dev);
  60.706 + 
  60.707 + 	return 0;
  60.708 + }
  60.709 +diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_eddp.c ./drivers/s390/net/qeth_eddp.c
  60.710 +--- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_eddp.c	2006-09-12 19:02:10.000000000 +0100
  60.711 ++++ ./drivers/s390/net/qeth_eddp.c	2006-09-19 13:59:20.000000000 +0100
  60.712 +@@ -421,7 +421,7 @@ __qeth_eddp_fill_context_tcp(struct qeth
  60.713 +        }
  60.714 + 	tcph = eddp->skb->h.th;
  60.715 + 	while (eddp->skb_offset < eddp->skb->len) {
  60.716 +-		data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
  60.717 ++		data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
  60.718 + 			       (int)(eddp->skb->len - eddp->skb_offset));
  60.719 + 		/* prepare qdio hdr */
  60.720 + 		if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
  60.721 +@@ -516,20 +516,20 @@ qeth_eddp_calc_num_pages(struct qeth_edd
  60.722 + 	
  60.723 + 	QETH_DBF_TEXT(trace, 5, "eddpcanp");
  60.724 + 	/* can we put multiple skbs in one page? */
  60.725 +-	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
  60.726 ++	skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
  60.727 + 	if (skbs_per_page > 1){
  60.728 +-		ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
  60.729 ++		ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
  60.730 + 				 skbs_per_page + 1;
  60.731 + 		ctx->elements_per_skb = 1;
  60.732 + 	} else {
  60.733 + 		/* no -> how many elements per skb? */
  60.734 +-		ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
  60.735 ++		ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
  60.736 + 				     PAGE_SIZE) >> PAGE_SHIFT;
  60.737 + 		ctx->num_pages = ctx->elements_per_skb *
  60.738 +-				 (skb_shinfo(skb)->tso_segs + 1);
  60.739 ++				 (skb_shinfo(skb)->gso_segs + 1);
  60.740 + 	}
  60.741 + 	ctx->num_elements = ctx->elements_per_skb *
  60.742 +-			    (skb_shinfo(skb)->tso_segs + 1);
  60.743 ++			    (skb_shinfo(skb)->gso_segs + 1);
  60.744 + }
  60.745 + 
  60.746 + static inline struct qeth_eddp_context *
  60.747 +diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c ./drivers/s390/net/qeth_main.c
  60.748 +--- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c	2006-09-12 19:02:10.000000000 +0100
  60.749 ++++ ./drivers/s390/net/qeth_main.c	2006-09-19 13:59:20.000000000 +0100
  60.750 +@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
  60.751 + 	queue = card->qdio.out_qs
  60.752 + 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
  60.753 + 
  60.754 +-	if (skb_shinfo(skb)->tso_size)
  60.755 ++	if (skb_shinfo(skb)->gso_size)
  60.756 + 		large_send = card->options.large_send;
  60.757 + 
  60.758 + 	/*are we able to do TSO ? If so ,prepare and send it from here */
  60.759 +@@ -4501,7 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
  60.760 + 		card->stats.tx_packets++;
  60.761 + 		card->stats.tx_bytes += skb->len;
  60.762 + #ifdef CONFIG_QETH_PERF_STATS
  60.763 +-		if (skb_shinfo(skb)->tso_size &&
  60.764 ++		if (skb_shinfo(skb)->gso_size &&
  60.765 + 		   !(large_send == QETH_LARGE_SEND_NO)) {
  60.766 + 			card->perf_stats.large_send_bytes += skb->len;
  60.767 + 			card->perf_stats.large_send_cnt++;
  60.768 +diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_tso.h ./drivers/s390/net/qeth_tso.h
  60.769 +--- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_tso.h	2006-09-12 19:02:10.000000000 +0100
  60.770 ++++ ./drivers/s390/net/qeth_tso.h	2006-09-19 13:59:20.000000000 +0100
  60.771 +@@ -51,7 +51,7 @@ qeth_tso_fill_header(struct qeth_card *c
  60.772 + 	hdr->ext.hdr_version = 1;
  60.773 + 	hdr->ext.hdr_len     = 28;
  60.774 + 	/*insert non-fix values */
  60.775 +-	hdr->ext.mss = skb_shinfo(skb)->tso_size;
  60.776 ++	hdr->ext.mss = skb_shinfo(skb)->gso_size;
  60.777 + 	hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
  60.778 + 	hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
  60.779 + 				       sizeof(struct qeth_hdr_tso));
  60.780 +diff -pruN ../orig-linux-2.6.16.29/include/linux/ethtool.h ./include/linux/ethtool.h
  60.781 +--- ../orig-linux-2.6.16.29/include/linux/ethtool.h	2006-09-12 19:02:10.00000