# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID d8c32fa3e3a98fc900c86a563652d6b83a6e5ef1
# Parent d54bcabd0624ceb692d40ed19586c7cedfa283d4
# Parent 463bda1677151dd4b588c838a2cd2f5ad2669c82
merge with xen-unstable.hg
---
patches/linux-2.6.16.32/blktap-aio-16_03_06.patch
| 271 -
patches/linux-2.6.16.32/device_bind.patch
| 14
patches/linux-2.6.16.32/fix-hz-suspend.patch
| 25
patches/linux-2.6.16.32/fix-ide-cd-pio-mode.patch
| 13
patches/linux-2.6.16.32/i386-mach-io-check-nmi.patch
| 35
patches/linux-2.6.16.32/ipv6-no-autoconf.patch
| 18
patches/linux-2.6.16.32/kasprintf.patch
| 57
patches/linux-2.6.16.32/net-csum.patch
| 57
patches/linux-2.6.16.32/net-gso-0-base.patch
| 2501 ----------
patches/linux-2.6.16.32/net-gso-1-check-dodgy.patch
| 22
patches/linux-2.6.16.32/net-gso-2-checksum-fix.patch
| 400 -
patches/linux-2.6.16.32/net-gso-3-fix-errorcheck.patch
| 13
patches/linux-2.6.16.32/net-gso-4-kill-warnon.patch
| 16
patches/linux-2.6.16.32/net-gso-5-rcv-mss.patch
| 11
patches/linux-2.6.16.32/pci-mmconfig-fix-from-2.6.17.patch
| 252 -
patches/linux-2.6.16.32/pmd-shared.patch
| 100
patches/linux-2.6.16.32/rcu_needs_cpu.patch
| 33
patches/linux-2.6.16.32/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
| 26
patches/linux-2.6.16.32/series
| 27
patches/linux-2.6.16.32/smp-alts.patch
| 540 --
patches/linux-2.6.16.32/tpm_plugin_2.6.17.patch
| 1380 -----
patches/linux-2.6.16.32/vsnprintf.patch
| 178
patches/linux-2.6.16.32/x86-elfnote-as-preprocessor-macro.patch
| 27
patches/linux-2.6.16.32/x86-increase-interrupt-vector-range.patch
| 73
patches/linux-2.6.16.32/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
| 138
patches/linux-2.6.16.32/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
| 72
patches/linux-2.6.16.32/xen-hotplug.patch
| 10
patches/linux-2.6.16.32/xenoprof-generic.patch
| 615 --
tools/firmware/hvmloader/acpi_ssdt_tpm.asl
| 29
tools/firmware/hvmloader/acpi_ssdt_tpm.h
| 25
tools/firmware/hvmloader/acpi_utils.c
| 318 -
tools/firmware/hvmloader/acpi_utils.h
| 36
Config.mk
| 1
buildconfigs/mk.linux-2.6-xen
| 2
docs/src/user.tex
| 5
linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
| 23
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
| 4
linux-2.6-xen-sparse/drivers/xen/console/console.c
| 68
patches/linux-2.6.16.33/blktap-aio-16_03_06.patch
| 161
patches/linux-2.6.16.33/device_bind.patch
| 9
patches/linux-2.6.16.33/fix-hz-suspend.patch
| 9
patches/linux-2.6.16.33/fix-ide-cd-pio-mode.patch
| 13
patches/linux-2.6.16.33/i386-mach-io-check-nmi.patch
| 30
patches/linux-2.6.16.33/ipv6-no-autoconf.patch
| 16
patches/linux-2.6.16.33/kasprintf.patch
| 32
patches/linux-2.6.16.33/net-csum.patch
| 40
patches/linux-2.6.16.33/net-gso-0-base.patch
| 1970 +++++++
patches/linux-2.6.16.33/net-gso-1-check-dodgy.patch
| 16
patches/linux-2.6.16.33/net-gso-2-checksum-fix.patch
| 311 +
patches/linux-2.6.16.33/net-gso-3-fix-errorcheck.patch
| 13
patches/linux-2.6.16.33/net-gso-4-kill-warnon.patch
| 26
patches/linux-2.6.16.33/net-gso-5-rcv-mss.patch
| 11
patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch
| 143
patches/linux-2.6.16.33/pmd-shared.patch
| 57
patches/linux-2.6.16.33/rcu_needs_cpu.patch
| 18
patches/linux-2.6.16.33/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
| 26
patches/linux-2.6.16.33/series
| 27
patches/linux-2.6.16.33/smp-alts.patch
| 330 +
patches/linux-2.6.16.33/tpm_plugin_2.6.17.patch
| 703 ++
patches/linux-2.6.16.33/vsnprintf.patch
| 177
patches/linux-2.6.16.33/x86-elfnote-as-preprocessor-macro.patch
| 25
patches/linux-2.6.16.33/x86-increase-interrupt-vector-range.patch
| 73
patches/linux-2.6.16.33/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
| 39
patches/linux-2.6.16.33/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
| 63
patches/linux-2.6.16.33/xen-hotplug.patch
| 10
patches/linux-2.6.16.33/xenoprof-generic.patch
| 294 +
tools/Makefile
| 1
tools/examples/network-route
| 8
tools/firmware/hvmloader/Makefile
| 15
tools/firmware/hvmloader/acpi/Makefile
| 15
tools/firmware/hvmloader/acpi/acpi2_0.h
| 17
tools/firmware/hvmloader/acpi/build.c
| 121
tools/firmware/hvmloader/acpi/ssdt_tpm.asl
| 29
tools/firmware/hvmloader/acpi/ssdt_tpm.h
| 25
tools/firmware/hvmloader/hvmloader.c
| 9
tools/firmware/hvmloader/mp_tables.c
| 1
tools/firmware/hvmloader/util.h
| 3
tools/libxen/Makefile
| 43
tools/libxen/src/xen_common.c
| 10
tools/python/xen/xend/XendAPI.py
| 68
tools/python/xen/xend/XendAuthSessions.py
| 2
tools/python/xen/xend/XendDomain.py
| 16
tools/python/xen/xend/XendDomainInfo.py
| 3
tools/python/xen/xend/server/SrvDaemon.py
| 23
tools/python/xen/xend/xenstore/xstransact.py
| 3
tools/python/xen/xend/xenstore/xswatch.py
| 11
tools/python/xen/xm/main.py
| 54
tools/python/xen/xm/new.py
| 6
xen/arch/x86/hvm/vmx/vmx.c
| 10
xen/arch/x86/x86_emulate.c
| 16
xen/common/memory.c
| 4
xen/common/page_alloc.c
| 49
xen/include/asm-ia64/config.h
| 2
xen/include/asm-powerpc/config.h
| 2
xen/include/asm-x86/config.h
| 2
xen/include/public/xenoprof.h
| 2
xen/include/xen/mm.h
| 4
97 files changed, 5131 insertions(+), 7520 deletions(-)
diff -r d54bcabd0624 -r d8c32fa3e3a9 Config.mk
--- a/Config.mk Wed Nov 29 11:05:02 2006 -0700
+++ b/Config.mk Wed Nov 29 11:07:28 2006 -0700
@@ -71,5 +71,6 @@ XENSTAT_XENTOP ?= y
XENSTAT_XENTOP ?= y
VTPM_TOOLS ?= n
+LIBXENAPI_BINDINGS ?= n
-include $(XEN_ROOT)/.config
diff -r d54bcabd0624 -r d8c32fa3e3a9 buildconfigs/mk.linux-2.6-xen
--- a/buildconfigs/mk.linux-2.6-xen Wed Nov 29 11:05:02 2006 -0700
+++ b/buildconfigs/mk.linux-2.6-xen Wed Nov 29 11:07:28 2006 -0700
@@ -1,5 +1,5 @@ LINUX_SERIES = 2.6
LINUX_SERIES = 2.6
-LINUX_VER = 2.6.16.32
+LINUX_VER = 2.6.16.33
EXTRAVERSION ?= xen
diff -r d54bcabd0624 -r d8c32fa3e3a9 docs/src/user.tex
--- a/docs/src/user.tex Wed Nov 29 11:05:02 2006 -0700
+++ b/docs/src/user.tex Wed Nov 29 11:07:28 2006 -0700
@@ -3240,6 +3240,11 @@ editing \path{grub.conf}.
enabled by the BIOS.
\item [ apic=bigsmp,default,es7000,summit ] Specify NUMA platform.
This can usually be probed automatically.
+\item [ dma\_bits=xxx ] Specify width of DMA
+ addresses in bits. Default is 30 bits (addresses up to 1GB are DMAable).
+\item [ dma\_emergency\_pool=xxx ] Specify lower bound on size of DMA
+ pool below which ordinary allocations will fail rather than fall
+ back to allocating from the DMA pool.
\end{description}
In addition, the following options may be specified on the Xen command
diff -r d54bcabd0624 -r d8c32fa3e3a9
linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c Wed Nov 29 11:05:02
2006 -0700
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c Wed Nov 29 11:07:28
2006 -0700
@@ -47,8 +47,8 @@ EXPORT_SYMBOL(swiotlb);
*/
#define IO_TLB_SHIFT 11
-/* Width of DMA addresses in the IO TLB. 31 bits is an aacraid limitation. */
-#define IO_TLB_DMA_BITS 31
+/* Width of DMA addresses in the IO TLB. 30 bits is a b44 limitation. */
+#define DEFAULT_IO_TLB_DMA_BITS 30
static int swiotlb_force;
static char *iotlb_virt_start;
@@ -97,6 +97,15 @@ static struct phys_addr {
* Protect the above data structures in the map and unmap calls
*/
static DEFINE_SPINLOCK(io_tlb_lock);
+
+static unsigned int io_tlb_dma_bits = DEFAULT_IO_TLB_DMA_BITS;
+static int __init
+setup_io_tlb_bits(char *str)
+{
+ io_tlb_dma_bits = simple_strtoul(str, NULL, 0);
+ return 0;
+}
+__setup("swiotlb_bits=", setup_io_tlb_bits);
static int __init
setup_io_tlb_npages(char *str)
@@ -158,7 +167,7 @@ swiotlb_init_with_default_size (size_t d
int rc = xen_create_contiguous_region(
(unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
- IO_TLB_DMA_BITS);
+ io_tlb_dma_bits);
BUG_ON(rc);
}
@@ -183,10 +192,12 @@ swiotlb_init_with_default_size (size_t d
printk(KERN_INFO "Software IO TLB enabled: \n"
" Aperture: %lu megabytes\n"
- " Kernel range: 0x%016lx - 0x%016lx\n",
+ " Kernel range: 0x%016lx - 0x%016lx\n"
+ " Address size: %u bits\n",
bytes >> 20,
(unsigned long)iotlb_virt_start,
- (unsigned long)iotlb_virt_start + bytes);
+ (unsigned long)iotlb_virt_start + bytes,
+ io_tlb_dma_bits);
}
void
@@ -654,7 +665,7 @@ int
int
swiotlb_dma_supported (struct device *hwdev, u64 mask)
{
- return (mask >= ((1UL << IO_TLB_DMA_BITS) - 1));
+ return (mask >= ((1UL << io_tlb_dma_bits) - 1));
}
EXPORT_SYMBOL(swiotlb_init);
diff -r d54bcabd0624 -r d8c32fa3e3a9
linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Wed Nov 29 11:05:02
2006 -0700
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Wed Nov 29 11:07:28
2006 -0700
@@ -709,6 +709,10 @@ irqreturn_t timer_interrupt(int irq, voi
account_system_time(current, HARDIRQ_OFFSET,
(cputime_t)delta_cpu);
}
+
+ /* Offlined for more than a few seconds? Avoid lockup warnings. */
+ if (stolen > 5*HZ)
+ touch_softlockup_watchdog();
/* Local timer processing (see update_process_times()). */
run_local_timers();
diff -r d54bcabd0624 -r d8c32fa3e3a9
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Nov 29
11:05:02 2006 -0700
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Wed Nov 29
11:07:28 2006 -0700
@@ -64,13 +64,20 @@
* 'xencons=off' [XC_OFF]: Console is disabled.
* 'xencons=tty' [XC_TTY]: Console attached to '/dev/tty[0-9]+'.
* 'xencons=ttyS' [XC_SERIAL]: Console attached to '/dev/ttyS[0-9]+'.
+ * 'xencons=xvc' [XC_XVC]: Console attached to '/dev/xvc0'.
* [XC_DEFAULT]: DOM0 -> XC_SERIAL ; all others -> XC_TTY.
*
* NB. In mode XC_TTY, we create dummy consoles for tty2-63. This suppresses
* warnings from standard distro startup scripts.
*/
-static enum { XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL } xc_mode = XC_DEFAULT;
+static enum {
+ XC_OFF, XC_DEFAULT, XC_TTY, XC_SERIAL, XC_XVC
+} xc_mode = XC_DEFAULT;
static int xc_num = -1;
+
+/* /dev/xvc0 device number allocated by lanana.org. */
+#define XEN_XVC_MAJOR 204
+#define XEN_XVC_MINOR 191
#ifdef CONFIG_MAGIC_SYSRQ
static unsigned long sysrq_requested;
@@ -82,27 +89,23 @@ static int __init xencons_setup(char *st
char *q;
int n;
- if (!strncmp(str, "ttyS", 4))
+ if (!strncmp(str, "ttyS", 4)) {
xc_mode = XC_SERIAL;
- else if (!strncmp(str, "tty", 3))
+ str += 4;
+ } else if (!strncmp(str, "tty", 3)) {
xc_mode = XC_TTY;
- else if (!strncmp(str, "off", 3))
+ str += 3;
+ } else if (!strncmp(str, "xvc", 3)) {
+ xc_mode = XC_XVC;
+ str += 3;
+ } else if (!strncmp(str, "off", 3)) {
xc_mode = XC_OFF;
-
- switch (xc_mode) {
- case XC_SERIAL:
- n = simple_strtol(str+4, &q, 10);
- if (q > (str + 4))
- xc_num = n;
- break;
- case XC_TTY:
- n = simple_strtol(str+3, &q, 10);
- if (q > (str + 3))
- xc_num = n;
- break;
- default:
- break;
- }
+ str += 3;
+ }
+
+ n = simple_strtol(str, &q, 10);
+ if (q != str)
+ xc_num = n;
return 1;
}
@@ -201,6 +204,12 @@ static int __init xen_console_init(void)
}
switch (xc_mode) {
+ case XC_XVC:
+ strcpy(kcons_info.name, "xvc");
+ if (xc_num == -1)
+ xc_num = 0;
+ break;
+
case XC_SERIAL:
strcpy(kcons_info.name, "ttyS");
if (xc_num == -1)
@@ -305,7 +314,7 @@ void dom0_init_screen_info(const struct
/******************** User-space console driver (/dev/console) ************/
#define DRV(_d) (_d)
-#define DUMMY_TTY(_tty) ((xc_mode != XC_SERIAL) && \
+#define DUMMY_TTY(_tty) ((xc_mode == XC_TTY) && \
((_tty)->index != (xc_num - 1)))
static struct termios *xencons_termios[MAX_NR_CONSOLES];
@@ -628,8 +637,8 @@ static int __init xencons_init(void)
return rc;
}
- xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
- 1 : MAX_NR_CONSOLES);
+ xencons_driver = alloc_tty_driver((xc_mode == XC_TTY) ?
+ MAX_NR_CONSOLES : 1);
if (xencons_driver == NULL)
return -ENOMEM;
@@ -644,14 +653,23 @@ static int __init xencons_init(void)
DRV(xencons_driver)->termios = xencons_termios;
DRV(xencons_driver)->termios_locked = xencons_termios_locked;
- if (xc_mode == XC_SERIAL) {
+ switch (xc_mode) {
+ case XC_XVC:
+ DRV(xencons_driver)->name = "xvc";
+ DRV(xencons_driver)->major = XEN_XVC_MAJOR;
+ DRV(xencons_driver)->minor_start = XEN_XVC_MINOR;
+ DRV(xencons_driver)->name_base = xc_num;
+ break;
+ case XC_SERIAL:
DRV(xencons_driver)->name = "ttyS";
DRV(xencons_driver)->minor_start = 64 + xc_num;
- DRV(xencons_driver)->name_base = 0 + xc_num;
- } else {
+ DRV(xencons_driver)->name_base = xc_num;
+ break;
+ default:
DRV(xencons_driver)->name = "tty";
DRV(xencons_driver)->minor_start = 1;
DRV(xencons_driver)->name_base = 1;
+ break;
}
tty_set_operations(xencons_driver, &xencons_ops);
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/Makefile
--- a/tools/Makefile Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/Makefile Wed Nov 29 11:07:28 2006 -0700
@@ -19,6 +19,7 @@ SUBDIRS-y += libaio
SUBDIRS-y += libaio
SUBDIRS-y += blktap
SUBDIRS-y += libfsimage
+SUBDIRS-$(LIBXENAPI_BINDINGS) += libxen
# These don't cross-compile
ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/examples/network-route
--- a/tools/examples/network-route Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/examples/network-route Wed Nov 29 11:07:28 2006 -0700
@@ -16,4 +16,12 @@
#
#============================================================================
+dir=$(dirname "$0")
+. "$dir/xen-script-common.sh"
+
+evalVariables "$@"
+
+netdev=${netdev:-eth${vifnum}}
+
echo 1 >/proc/sys/net/ipv4/ip_forward
+echo 1 >/proc/sys/net/ipv4/conf/${netdev}/proxy_arp
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/Makefile
--- a/tools/firmware/hvmloader/Makefile Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/Makefile Wed Nov 29 11:07:28 2006 -0700
@@ -18,18 +18,13 @@
# Place - Suite 330, Boston, MA 02111-1307 USA.
#
-# External CFLAGS can do more harm than good.
-CFLAGS :=
-
override XEN_TARGET_ARCH = x86_32
XEN_ROOT = ../../..
-include $(XEN_ROOT)/Config.mk
+CFLAGS := -I$(XEN_ROOT)/tools/libxc -I.
+include $(XEN_ROOT)/tools/Rules.mk
# The HVM loader is started in 32-bit mode at the address below:
LOADADDR = 0x100000
-
-DEFINES =-DDEBUG
-XENINC =-I$(XEN_ROOT)/tools/libxc
# Disable PIE/SSP if GCC supports them. They can break us.
CFLAGS += $(call cc-option,$(CC),-nopie,)
@@ -37,10 +32,10 @@ CFLAGS += $(call cc-option,$(CC),-fno-s
CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
OBJCOPY = objcopy
-CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
+CFLAGS += -fno-builtin -O2 -msoft-float
LDFLAGS = -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
-SRCS = hvmloader.c mp_tables.c util.c smbios.c acpi_utils.c
+SRCS = hvmloader.c mp_tables.c util.c smbios.c
OBJS = $(patsubst %.c,%.o,$(SRCS))
.PHONY: all
@@ -65,5 +60,5 @@ roms.h: ../rombios/BIOS-bochs-latest ../
.PHONY: clean
clean:
rm -f roms.h acpi.h
- rm -f hvmloader hvmloader.tmp hvmloader.o $(OBJS)
+ rm -f hvmloader hvmloader.tmp *.o
$(MAKE) -C acpi clean
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/acpi/Makefile
--- a/tools/firmware/hvmloader/acpi/Makefile Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/acpi/Makefile Wed Nov 29 11:07:28 2006 -0700
@@ -27,15 +27,28 @@ IASL_VER = acpica-unix-20050513
IASL_VER = acpica-unix-20050513
IASL_URL =
http://developer.intel.com/technology/iapc/acpi/downloads/$(IASL_VER).tar.gz
+# Disable PIE/SSP if GCC supports them. They can break us.
+CFLAGS += $(call cc-option,$(CC),-nopie,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
+CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
+
+CFLAGS += -fno-builtin -O2 -msoft-float
+
vpath iasl $(PATH)
all: acpi.a
+
+ssdt_tpm.h: ssdt_tpm.asl
+ $(MAKE) iasl
+ iasl -tc ssdt_tpm.asl
+ mv ssdt_tpm.hex ssdt_tpm.h
+ rm -f *.aml
dsdt.c: dsdt.asl
$(MAKE) iasl
iasl -tc dsdt.asl
mv dsdt.hex dsdt.c
echo "int DsdtLen=sizeof(AmlCode);" >> dsdt.c
- rm *.aml
+ rm -f *.aml
iasl:
@echo
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/acpi/acpi2_0.h
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h Wed Nov 29 11:07:28 2006 -0700
@@ -119,7 +119,7 @@ struct acpi_20_rsdp {
*/
struct acpi_20_rsdt {
struct acpi_header header;
- uint32_t entry[ACPI_MAX_NUM_TABLES];
+ uint32_t entry[1];
};
#define ACPI_2_0_RSDT_REVISION 0x01
@@ -128,20 +128,19 @@ struct acpi_20_rsdt {
*/
struct acpi_20_xsdt {
struct acpi_header header;
- uint64_t entry[ACPI_MAX_NUM_TABLES];
+ uint64_t entry[1];
};
#define ACPI_2_0_XSDT_REVISION 0x01
/*
* TCG Hardware Interface Table (TCPA)
*/
-
-typedef struct _ACPI_2_0_TCPA_CLIENT {
- struct acpi_header header;
- uint16_t PlatformClass;
- uint32_t LAML;
- uint64_t LASA;
-} ACPI_2_0_TCPA_CLIENT;
+struct acpi_20_tcpa {
+ struct acpi_header header;
+ uint16_t platform_class;
+ uint32_t laml;
+ uint64_t lasa;
+};
#define ACPI_2_0_TCPA_REVISION 0x02
#define ACPI_2_0_TCPA_LAML_SIZE (64*1024)
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/acpi/build.c
--- a/tools/firmware/hvmloader/acpi/build.c Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/acpi/build.c Wed Nov 29 11:07:28 2006 -0700
@@ -17,8 +17,12 @@
*/
#include "acpi2_0.h"
+#include "ssdt_tpm.h"
#include "../config.h"
#include "../util.h"
+#include <xen/hvm/e820.h>
+
+#define align16(sz) (((sz) + 15) & ~15)
extern struct acpi_20_rsdp Rsdp;
extern struct acpi_20_rsdt Rsdt;
@@ -103,39 +107,88 @@ int construct_madt(struct acpi_20_madt *
madt->header.length = offset;
set_checksum(madt, offsetof(struct acpi_header, checksum), offset);
- return offset;
-}
-
-/*
- * Copy all the ACPI table to buffer.
- * Buffer layout: FACS, DSDT, FADT, MADT, XSDT, RSDT, RSDP.
- */
+ return align16(offset);
+}
+
+int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs)
+{
+ int offset = 0, nr_tables = 0;
+ struct acpi_20_madt *madt;
+ struct acpi_20_tcpa *tcpa;
+ static const uint16_t tis_signature[] = {0x0001, 0x0001, 0x0001};
+ uint16_t *tis_hdr;
+
+ /* MADT. */
+ if ( (get_vcpu_nr() > 1) || get_apic_mode() )
+ {
+ madt = (struct acpi_20_madt *)&buf[offset];
+ offset += construct_madt(madt);
+ table_ptrs[nr_tables++] = (unsigned long)madt;
+ }
+
+ /* TPM TCPA and SSDT. */
+ tis_hdr = (uint16_t *)0xFED40F00;
+ if ( (tis_hdr[0] == tis_signature[0]) &&
+ (tis_hdr[1] == tis_signature[1]) &&
+ (tis_hdr[2] == tis_signature[2]) )
+ {
+ memcpy(&buf[offset], AmlCode_TPM, sizeof(AmlCode_TPM));
+ table_ptrs[nr_tables++] = (unsigned long)&buf[offset];
+ offset += align16(sizeof(AmlCode_TPM));
+
+ tcpa = (struct acpi_20_tcpa *)&buf[offset];
+ memset(tcpa, 0, sizeof(*tcpa));
+ offset += align16(sizeof(*tcpa));
+ table_ptrs[nr_tables++] = (unsigned long)tcpa;
+
+ tcpa->header.signature = ACPI_2_0_TCPA_SIGNATURE;
+ tcpa->header.length = sizeof(*tcpa);
+ tcpa->header.revision = ACPI_2_0_TCPA_REVISION;
+ strncpy(tcpa->header.oem_id, "IBM ", 6);
+ tcpa->header.oem_table_id = ASCII64(' ', ' ', ' ', ' ',
+ ' ', 'x', 'e', 'n');
+ tcpa->header.oem_revision = 1;
+ tcpa->header.creator_id = ASCII32('I', 'B', 'M', ' ');
+ tcpa->header.creator_revision = 1;
+ tcpa->lasa = e820_malloc(
+ ACPI_2_0_TCPA_LAML_SIZE, E820_RESERVED, (uint32_t)~0);
+ if ( tcpa->lasa )
+ {
+ tcpa->laml = ACPI_2_0_TCPA_LAML_SIZE;
+ memset((char *)(unsigned long)tcpa->lasa, 0, tcpa->laml);
+ set_checksum(tcpa,
+ offsetof(struct acpi_header, checksum),
+ tcpa->header.length);
+ }
+ }
+
+ table_ptrs[nr_tables] = 0;
+ return align16(offset);
+}
+
+/* Copy all the ACPI table to buffer. */
int acpi_build_tables(uint8_t *buf)
{
struct acpi_20_rsdp *rsdp;
struct acpi_20_rsdt *rsdt;
struct acpi_20_xsdt *xsdt;
struct acpi_20_fadt *fadt;
- struct acpi_20_madt *madt = 0;
struct acpi_20_facs *facs;
unsigned char *dsdt;
- int offset = 0, requires_madt;
-
- requires_madt = ((get_vcpu_nr() > 1) || get_apic_mode());
-
-#define inc_offset(sz) (offset = (offset + (sz) + 15) & ~15)
+ unsigned long secondary_tables[16];
+ int offset = 0, i;
facs = (struct acpi_20_facs *)&buf[offset];
memcpy(facs, &Facs, sizeof(struct acpi_20_facs));
- inc_offset(sizeof(struct acpi_20_facs));
+ offset += align16(sizeof(struct acpi_20_facs));
dsdt = (unsigned char *)&buf[offset];
memcpy(dsdt, &AmlCode, DsdtLen);
- inc_offset(DsdtLen);
+ offset += align16(DsdtLen);
fadt = (struct acpi_20_fadt *)&buf[offset];
memcpy(fadt, &Fadt, sizeof(struct acpi_20_fadt));
- inc_offset(sizeof(struct acpi_20_fadt));
+ offset += align16(sizeof(struct acpi_20_fadt));
fadt->dsdt = (unsigned long)dsdt;
fadt->x_dsdt = (unsigned long)dsdt;
fadt->firmware_ctrl = (unsigned long)facs;
@@ -144,43 +197,33 @@ int acpi_build_tables(uint8_t *buf)
offsetof(struct acpi_header, checksum),
sizeof(struct acpi_20_fadt));
- if ( requires_madt )
- {
- madt = (struct acpi_20_madt *)&buf[offset];
- inc_offset(construct_madt(madt));
- }
+ offset += construct_secondary_tables(&buf[offset], secondary_tables);
xsdt = (struct acpi_20_xsdt *)&buf[offset];
- memcpy(xsdt, &Xsdt, sizeof(struct acpi_20_xsdt));
- inc_offset(sizeof(struct acpi_20_xsdt));
+ memcpy(xsdt, &Xsdt, sizeof(struct acpi_header));
xsdt->entry[0] = (unsigned long)fadt;
- xsdt->header.length = sizeof(struct acpi_header) + sizeof(uint64_t);
- if ( requires_madt )
- {
- xsdt->entry[1] = (unsigned long)madt;
- xsdt->header.length += sizeof(uint64_t);
- }
+ for ( i = 0; secondary_tables[i]; i++ )
+ xsdt->entry[i+1] = secondary_tables[i];
+ xsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint64_t);
+ offset += align16(xsdt->header.length);
set_checksum(xsdt,
offsetof(struct acpi_header, checksum),
xsdt->header.length);
rsdt = (struct acpi_20_rsdt *)&buf[offset];
- memcpy(rsdt, &Rsdt, sizeof(struct acpi_20_rsdt));
- inc_offset(sizeof(struct acpi_20_rsdt));
+ memcpy(rsdt, &Rsdt, sizeof(struct acpi_header));
rsdt->entry[0] = (unsigned long)fadt;
- rsdt->header.length = sizeof(struct acpi_header) + sizeof(uint32_t);
- if ( requires_madt )
- {
- rsdt->entry[1] = (unsigned long)madt;
- rsdt->header.length += sizeof(uint32_t);
- }
+ for ( i = 0; secondary_tables[i]; i++ )
+ rsdt->entry[i+1] = secondary_tables[i];
+ rsdt->header.length = sizeof(struct acpi_header) + (i+1)*sizeof(uint32_t);
+ offset += align16(rsdt->header.length);
set_checksum(rsdt,
offsetof(struct acpi_header, checksum),
rsdt->header.length);
rsdp = (struct acpi_20_rsdp *)&buf[offset];
memcpy(rsdp, &Rsdp, sizeof(struct acpi_20_rsdp));
- inc_offset(sizeof(struct acpi_20_rsdp));
+ offset += align16(sizeof(struct acpi_20_rsdp));
rsdp->rsdt_address = (unsigned long)rsdt;
rsdp->xsdt_address = (unsigned long)xsdt;
set_checksum(rsdp,
@@ -189,8 +232,6 @@ int acpi_build_tables(uint8_t *buf)
set_checksum(rsdp,
offsetof(struct acpi_20_rsdp, extended_checksum),
sizeof(struct acpi_20_rsdp));
-
-#undef inc_offset
return offset;
}
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/hvmloader.c Wed Nov 29 11:07:28 2006 -0700
@@ -23,7 +23,6 @@
#include "acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
#include "hypercall.h"
#include "util.h"
-#include "acpi_utils.h"
#include "smbios.h"
#include "config.h"
#include "apic_regs.h"
@@ -283,7 +282,6 @@ int main(void)
int main(void)
{
int acpi_sz;
- uint8_t *freemem;
printf("HVM Loader\n");
@@ -318,12 +316,7 @@ int main(void)
{
printf("Loading ACPI ...\n");
acpi_sz = acpi_build_tables((uint8_t *)ACPI_PHYSICAL_ADDRESS);
- freemem = (uint8_t *)ACPI_PHYSICAL_ADDRESS + acpi_sz;
- ASSERT(freemem <= (uint8_t *)0xF0000);
- acpi_update((unsigned char *)ACPI_PHYSICAL_ADDRESS,
- freemem - (uint8_t *)ACPI_PHYSICAL_ADDRESS,
- (unsigned char *)0xF0000,
- &freemem);
+ ASSERT((ACPI_PHYSICAL_ADDRESS + acpi_sz) <= 0xF0000);
}
if ( check_amd() )
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/mp_tables.c
--- a/tools/firmware/hvmloader/mp_tables.c Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/mp_tables.c Wed Nov 29 11:07:28 2006 -0700
@@ -28,7 +28,6 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
-#include <acpi_utils.h>
#include "config.h"
/* FIXME find a header that already has types defined!!! */
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/util.h
--- a/tools/firmware/hvmloader/util.h Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/firmware/hvmloader/util.h Wed Nov 29 11:07:28 2006 -0700
@@ -5,6 +5,9 @@
#undef offsetof
#define offsetof(t, m) ((unsigned long)&((t *)0)->m)
+
+#undef NULL
+#define NULL ((void*)0)
extern void __assert_failed(char *assertion, char *file, int line)
__attribute__((noreturn));
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/libxen/Makefile
--- a/tools/libxen/Makefile Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/libxen/Makefile Wed Nov 29 11:07:28 2006 -0700
@@ -15,23 +15,58 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+MAJOR = 0.1
+MINOR = 0
CFLAGS = -Iinclude \
- $(shell xml2-config --cflags) \
+ $(shell xml2-config --cflags) \
$(shell curl-config --cflags) \
-W -Wall -Wmissing-prototypes -Werror -std=c99 -O2 -fPIC
LDFLAGS = $(shell xml2-config --libs) \
$(shell curl-config --libs)
+LIBXENAPI_HDRS = $(wildcard include/*.h)
+LIBXENAPI_OBJS = $(patsubst %.c, %.o, $(wildcard src/*.c))
+
+
+.PHONY: all
+all: libxenapi.so libxenapi.a
+
+libxenapi.so: libxenapi.so.$(MAJOR)
+ ln -sf $< $@
+
+libxenapi.so.$(MAJOR): libxenapi.so.$(MAJOR).$(MINOR)
+ ln -sf $< $@
+
+libxenapi.so.$(MAJOR).$(MINOR): $(LIBXENAPI_OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG)
-Wl,libxenapi.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^
+
+libxenapi.a: $(LIBXENAPI_OBJS)
+ $(AR) rcs libxenapi.a $^
+
test/test_bindings: test/test_bindings.o src/libxen.so
$(CC) $(LDFLAGS) -o $@ $< -L src -lxen
-src/libxen.so: $(patsubst %.c, %.o, $(wildcard src/*.c))
- $(CC) -shared -o $@ $^
+
+.PHONY: install
+install: all
+ $(INSTALL_DIR) -p $(DESTDIR)/usr/include/xen/api
+ $(INSTALL_DIR) -p $(DESTDIR)/usr/$(LIBDIR)
+ $(INSTALL_PROG) libxenapi.so.$(MAJOR).$(MINOR) $(DESTDIR)/usr/$(LIBDIR)
+ ln -sf libxenapi.so.$(MAJOR).$(MINOR)
$(DESTDIR)/usr/$(LIBDIR)/libxenapi.so.$(MAJOR)
+ ln -sf libxenapi.so.$(MAJOR) $(DESTDIR)/usr/$(LIBDIR)/libxenapi.so
+ $(INSTALL_DATA) libxenapi.a $(DESTDIR)/usr/$(LIBDIR)
+ for i in $(LIBXENAPI_HDRS); do \
+ $(INSTALL_DATA) $$i $(DESTDIR)/usr/include/xen/api; \
+ done
.PHONY: clean
clean:
rm -f `find -name *.o`
- rm -f src/libxen.so
+ rm -f libxenapi.so*
+ rm -f libxenapi.a
rm -f test/test_bindings
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/libxen/src/xen_common.c
--- a/tools/libxen/src/xen_common.c Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/libxen/src/xen_common.c Wed Nov 29 11:07:28 2006 -0700
@@ -35,6 +35,14 @@
#include "xen_string_string_map.h"
+/*
+ * Whether to ignore missing structure entries. This is not something we
+ * want to do, once the API has stabilised, as it indicates that the server is
+ * broken, but at the moment, complaining is just slowing development down.
+ */
+#define PERMISSIVE 1
+
+
static xmlXPathCompExprPtr responsePath = NULL;
static xmlXPathCompExprPtr faultPath = NULL;
@@ -756,6 +764,7 @@ static void parse_into(xen_session *s, x
cur = cur->next;
}
+#if !PERMISSIVE
/* Check that we've filled all fields. */
for (size_t i = 0; i < member_count; i++)
{
@@ -780,6 +789,7 @@ static void parse_into(xen_session *s, x
return;
}
}
+#endif
free(checklist);
((void **)value)[slot] = result;
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xend/XendAPI.py
--- a/tools/python/xen/xend/XendAPI.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xend/XendAPI.py Wed Nov 29 11:07:28 2006 -0700
@@ -248,8 +248,8 @@ def valid_sr(func):
# Bridge to Legacy XM API calls
# -----------------------------
-def do_vm_func(fn_name, vm_ref, *args):
- """Helper wrapper func to abstract away from repeative code.
+def do_vm_func(fn_name, vm_ref, *args, **kwargs):
+ """Helper wrapper func to abstract away from repetitive code.
@param fn_name: function name for XendDomain instance
@type fn_name: string
@@ -260,7 +260,7 @@ def do_vm_func(fn_name, vm_ref, *args):
"""
xendom = XendDomain.instance()
fn = getattr(xendom, fn_name)
- xendom.do_legacy_api_with_uuid(fn, vm_ref, *args)
+ xendom.do_legacy_api_with_uuid(fn, vm_ref, *args, **kwargs)
return xen_api_success_void()
@@ -327,7 +327,7 @@ class XendAPI:
# wrap validators around readable class attributes
for attr_name in ro_attrs + rw_attrs + self.Base_attr_ro:
- getter_name = '%s_get_%s' % (cls.lower(), attr_name.lower())
+ getter_name = '%s_get_%s' % (cls.lower(), attr_name)
try:
getter = getattr(XendAPI, getter_name)
for validator in validators:
@@ -340,7 +340,7 @@ class XendAPI:
# wrap validators around writable class attrributes
for attr_name in rw_attrs + self.Base_attr_rw:
- setter_name = '%s_set_%s' % (cls.lower(), attr_name.lower())
+ setter_name = '%s_set_%s' % (cls.lower(), attr_name)
try:
setter = getattr(XendAPI, setter_name)
for validator in validators:
@@ -353,7 +353,7 @@ class XendAPI:
# wrap validators around methods
for method_name in methods + self.Base_methods:
- method_full_name = '%s_%s' % (cls.lower(),method_name.lower())
+ method_full_name = '%s_%s' % (cls.lower(), method_name)
try:
method = getattr(XendAPI, method_full_name)
for validator in validators:
@@ -366,7 +366,7 @@ class XendAPI:
# wrap validators around class functions
for func_name in funcs + self.Base_funcs:
- func_full_name = '%s_%s' % (cls.lower(), func_name.lower())
+ func_full_name = '%s_%s' % (cls.lower(), func_name)
try:
method = getattr(XendAPI, func_full_name)
method = session_required(method)
@@ -411,7 +411,7 @@ class XendAPI:
record = {'this_host': XendNode.instance().uuid,
'this_user': auth_manager().get_user(session)}
return xen_api_success(record)
- def session_to_xml(self, session):
+ def session_to_XML(self, session):
return xen_api_todo()
# attributes (ro)
@@ -536,7 +536,7 @@ class XendAPI:
'features': node.get_host_cpu_features(host_cpu_ref),
'utilisation': node.get_host_cpu_load(host_cpu_ref)}
return xen_api_success(record)
- def host_cpu_to_xml(self, session, host_cpu_ref):
+ def host_cpu_to_XML(self, session, host_cpu_ref):
return xen_api_todo()
# class methods
@@ -586,7 +586,7 @@ class XendAPI:
'VCPUs_policy',
'VCPUs_params',
'VCPUs_features_force_on',
- 'VCPUS_features_force_off',
+ 'VCPUs_features_force_off',
'actions_after_shutdown',
'actions_after_reboot',
'actions_after_suspend',
@@ -848,19 +848,19 @@ class XendAPI:
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_success_void()
- def vm_set_vcpus_policy(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success_void()
-
- def vm_set_vcpus_params(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success_void()
-
- def vm_set_vcpus_features_force_on(self, session, vm_ref):
- dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
- return xen_api_success_void()
-
- def vm_set_vcpus_features_force_off(self, session, vm_ref):
+ def vm_set_VCPUs_policy(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ return xen_api_success_void()
+
+ def vm_set_VCPUs_params(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ return xen_api_success_void()
+
+ def vm_set_VCPUs_features_force_on(self, session, vm_ref):
+ dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
+ return xen_api_success_void()
+
+ def vm_set_VCPUs_features_force_off(self, session, vm_ref):
dom = XendDomain.instance().get_vm_by_uuid(vm_ref)
return xen_api_success_void()
@@ -950,7 +950,7 @@ class XendAPI:
return xen_api_success(domuuid)
# object methods
- def vm_to_xml(self, session, vm_ref):
+ def vm_to_XML(self, session, vm_ref):
return xen_api_todo()
def vm_get_record(self, session, vm_ref):
@@ -1027,9 +1027,9 @@ class XendAPI:
def vm_pause(self, session, vm_ref):
return do_vm_func("domain_pause", vm_ref)
def vm_resume(self, session, vm_ref, start_paused):
- return do_vm_func("domain_resume", vm_ref)
- def vm_start(self, session, vm_ref):
- return do_vm_func("domain_start", vm_ref)
+ return do_vm_func("domain_resume", vm_ref, start_paused =
start_paused)
+ def vm_start(self, session, vm_ref, start_paused):
+ return do_vm_func("domain_start", vm_ref, start_paused = start_paused)
def vm_suspend(self, session, vm_ref):
return do_vm_func("domain_suspend", vm_ref)
def vm_unpause(self, session, vm_ref):
@@ -1092,11 +1092,11 @@ class XendAPI:
return xen_api_success(vbd_ref)
# attributes (rw)
- def vbd_get_vm(self, session, vbd_ref):
+ def vbd_get_VM(self, session, vbd_ref):
xendom = XendDomain.instance()
return xen_api_success(xendom.get_dev_property('vbd', vbd_ref, 'VM'))
- def vbd_get_vdi(self, session, vbd_ref):
+ def vbd_get_VDI(self, session, vbd_ref):
return xen_api_todo()
def vbd_get_device(self, session, vbd_ref):
@@ -1218,7 +1218,7 @@ class XendAPI:
image = sr.xen_api_get_by_uuid(vdi_ref)
return xen_api_success(image.name_description)
- def vdi_get_sr(self, session, vdi_ref):
+ def vdi_get_SR(self, session, vdi_ref):
sr = XendNode.instance().get_sr()
return xen_api_success(sr.uuid)
@@ -1249,7 +1249,7 @@ class XendAPI:
image.name_description = value
return xen_api_success_void()
- def vdi_set_sr(self, session, vdi_ref, value):
+ def vdi_set_SR(self, session, vdi_ref, value):
return xen_api_error(XEND_ERROR_UNSUPPORTED)
def vdi_set_virtual_size(self, session, vdi_ref, value):
@@ -1269,7 +1269,7 @@ class XendAPI:
sr.destroy_image(vdi_ref)
return xen_api_success_void()
- def vdi_to_xml(self, session, vdi_ref):
+ def vdi_to_XML(self, session, vdi_ref):
return xen_api_todo()
def vdi_get_record(self, session, vdi_ref):
@@ -1451,7 +1451,7 @@ class XendAPI:
def sr_destroy(self, session, sr_ref):
return xen_api_error(XEND_ERROR_UNSUPPORTED)
- def sr_to_xml(self, session, sr_ref):
+ def sr_to_XML(self, session, sr_ref):
return xen_api_todo()
def sr_get_record(self, session, sr_ref):
@@ -1469,7 +1469,7 @@ class XendAPI:
})
# Attribute acceess
- def sr_get_vdis(self, session, sr_ref):
+ def sr_get_VDIs(self, session, sr_ref):
sr = XendNode.instance().get_sr()
return xen_api_success(sr.list_images())
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xend/XendAuthSessions.py
--- a/tools/python/xen/xend/XendAuthSessions.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xend/XendAuthSessions.py Wed Nov 29 11:07:28 2006 -0700
@@ -55,7 +55,7 @@ class XendAuthSessions:
@return: Session UUID
"""
if self.is_authorized(username, password):
- return login_unconditionally(username)
+ return self.login_unconditionally(username)
raise XendError("Login failed")
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xend/XendDomain.py Wed Nov 29 11:07:28 2006 -0700
@@ -647,18 +647,18 @@ class XendDomain:
def is_valid_dev(self, klass, dev_uuid):
return (self.get_vm_with_dev_uuid(klass, dev_uuid) != None)
- def do_legacy_api_with_uuid(self, fn, vm_uuid, *args):
+ def do_legacy_api_with_uuid(self, fn, vm_uuid, *args, **kwargs):
self.domains_lock.acquire()
try:
for domid, dom in self.domains.items():
if dom.get_uuid == vm_uuid:
- return fn(domid, *args)
+ return fn(domid, *args, **kwargs)
if vm_uuid in self.managed_domains:
domid = self.managed_domains[vm_uuid].getDomid()
if domid == None:
domid = self.managed_domains[vm_uuid].getName()
- return fn(domid, *args)
+ return fn(domid, *args, **kwargs)
raise XendInvalidDomain("Domain does not exist")
finally:
@@ -795,7 +795,7 @@ class XendDomain:
raise XendError("can't write guest state file %s: %s" %
(path, ex[1]))
- def domain_resume(self, domname):
+ def domain_resume(self, domname, start_paused = False):
"""Resumes a domain that is persistently managed by Xend.
@param domname: Domain Name
@@ -827,7 +827,8 @@ class XendDomain:
log.debug('Current DomainInfo state: %d' % dominfo.state)
XendCheckpoint.restore(self,
os.open(chkpath, os.O_RDONLY),
- dominfo)
+ dominfo,
+ paused = start_paused)
self._add_domain(dominfo)
os.unlink(chkpath)
except OSError, ex:
@@ -886,7 +887,7 @@ class XendDomain:
finally:
self.domains_lock.release()
- def domain_start(self, domid):
+ def domain_start(self, domid, start_paused = True):
"""Start a managed domain
@require: Domain must not be running.
@@ -911,6 +912,9 @@ class XendDomain:
self._add_domain(dominfo)
finally:
self.domains_lock.release()
+ dominfo.waitForDevices()
+ if not start_paused:
+ dominfo.unpause()
def domain_delete(self, domid):
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xend/XendDomainInfo.py Wed Nov 29 11:07:28 2006 -0700
@@ -439,7 +439,6 @@ class XendDomainInfo:
self._storeDomDetails()
self._registerWatches()
self.refreshShutdown()
- self.unpause()
# save running configuration if XendDomains believe domain is
# persistent
@@ -1715,6 +1714,8 @@ class XendDomainInfo:
return '' # TODO
def get_platform_std_vga(self):
return False
+ def get_platform_keymap(self):
+ return ''
def get_platform_serial(self):
return '' # TODO
def get_platform_localtime(self):
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xend/server/SrvDaemon.py
--- a/tools/python/xen/xend/server/SrvDaemon.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xend/server/SrvDaemon.py Wed Nov 29 11:07:28 2006 -0700
@@ -6,7 +6,9 @@
###########################################################
import os
+import os.path
import signal
+import stat
import sys
import threading
import time
@@ -102,17 +104,32 @@ class Daemon:
# Detach from standard file descriptors, and redirect them to
# /dev/null or the log as appropriate.
+ # We open the log file first, so that we can diagnose a failure to do
+ # so _before_ we close stderr.
+ try:
+ parent = os.path.dirname(XEND_DEBUG_LOG)
+ if not os.path.exists(parent):
+ os.makedirs(parent, stat.S_IRWXU)
+ fd = os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND)
+ except Exception, exn:
+ print >>sys.stderr, exn
+ print >>sys.stderr, ("Xend failed to open %s. Exiting!" %
+ XEND_DEBUG_LOG)
+ sys.exit(1)
+
os.close(0)
os.close(1)
os.close(2)
if XEND_DEBUG:
os.open('/dev/null', os.O_RDONLY)
- os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND)
- os.dup(1)
+ os.dup(fd)
+ os.dup(fd)
else:
os.open('/dev/null', os.O_RDWR)
os.dup(0)
- os.open(XEND_DEBUG_LOG, os.O_WRONLY|os.O_CREAT|os.O_APPEND)
+ os.dup(fd)
+ os.close(fd)
+
print >>sys.stderr, ("Xend started at %s." %
time.asctime(time.localtime()))
diff -r d54bcabd0624 -r d8c32fa3e3a9
tools/python/xen/xend/xenstore/xstransact.py
--- a/tools/python/xen/xend/xenstore/xstransact.py Wed Nov 29 11:05:02
2006 -0700
+++ b/tools/python/xen/xend/xenstore/xstransact.py Wed Nov 29 11:07:28
2006 -0700
@@ -11,11 +11,12 @@ class xstransact:
class xstransact:
def __init__(self, path = ""):
- assert path is not None
self.in_transaction = False # Set this temporarily -- if this
# constructor fails, then we need to
# protect __del__.
+
+ assert path is not None
self.path = path.rstrip("/")
self.transaction = xshandle().transaction_start()
self.in_transaction = True
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xend/xenstore/xswatch.py
--- a/tools/python/xen/xend/xenstore/xswatch.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xend/xenstore/xswatch.py Wed Nov 29 11:07:28 2006 -0700
@@ -5,6 +5,7 @@
# Public License. See the file "COPYING" in the main directory of
# this archive for more details.
+import errno
import threading
from xen.xend.xenstore.xsutil import xshandle
@@ -65,7 +66,15 @@ def watchMain():
watch = we[1]
res = watch.fn(we[0], *watch.args, **watch.kwargs)
if not res:
- watch.unwatch()
+ try:
+ watch.unwatch()
+ except RuntimeError, exn:
+ if exn.args[0] == errno.ENOENT:
+ # The watch has already been unregistered -- that's
+ # fine.
+ pass
+ else:
+ raise
except:
log.exception("read_watch failed")
# Ignore this exception -- there's no point throwing it
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xm/main.py
--- a/tools/python/xen/xm/main.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xm/main.py Wed Nov 29 11:07:28 2006 -0700
@@ -207,7 +207,13 @@ SUBCOMMAND_OPTIONS = {
('-L', '--live', 'Dump core without pausing the domain'),
('-C', '--crash', 'Crash domain after dumping core'),
),
- 'restore': (
+ 'start': (
+ ('-p', '--paused', 'Do not unpause domain after starting it'),
+ ),
+ 'resume': (
+ ('-p', '--paused', 'Do not unpause domain after resuming it'),
+ ),
+ 'restore': (
('-p', '--paused', 'Do not unpause domain after restoring it'),
),
}
@@ -742,9 +748,26 @@ def xm_vcpu_list(args):
print format % locals()
def xm_start(args):
- arg_check(args, "start", 1)
- dom = args[0]
- server.xend.domain.start(dom)
+ arg_check(args, "start", 1, 2)
+
+ try:
+ (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
+ except getopt.GetoptError, opterr:
+ err(opterr)
+ sys.exit(1)
+
+ paused = False
+ for (k, v) in options:
+ if k in ['-p', '--paused']:
+ paused = True
+
+ if len(params) != 1:
+ err("Wrong number of parameters")
+ usage('start')
+ sys.exit(1)
+
+ dom = params[0]
+ server.xend.domain.start(dom, paused)
def xm_delete(args):
arg_check(args, "delete", 1)
@@ -757,9 +780,26 @@ def xm_suspend(args):
server.xend.domain.suspend(dom)
def xm_resume(args):
- arg_check(args, "resume", 1)
- dom = args[0]
- server.xend.domain.resume(dom)
+ arg_check(args, "resume", 1, 2)
+
+ try:
+ (options, params) = getopt.gnu_getopt(args, 'p', ['paused'])
+ except getopt.GetoptError, opterr:
+ err(opterr)
+ sys.exit(1)
+
+ paused = False
+ for (k, v) in options:
+ if k in ['-p', '--paused']:
+ paused = True
+
+ if len(params) != 1:
+ err("Wrong number of parameters")
+ usage('resume')
+ sys.exit(1)
+
+ dom = params[0]
+ server.xend.domain.resume(dom, paused)
def xm_reboot(args):
arg_check(args, "reboot", 1, 3)
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/python/xen/xm/new.py
--- a/tools/python/xen/xm/new.py Wed Nov 29 11:05:02 2006 -0700
+++ b/tools/python/xen/xm/new.py Wed Nov 29 11:07:28 2006 -0700
@@ -58,6 +58,12 @@ def main(argv):
if not opts:
return
+ if type(config) == str:
+ try:
+ config = sxp.parse(file(config))[0]
+ except IOError, exn:
+ raise OptionError("Cannot read file %s: %s" % (config, exn[1]))
+
if opts.vals.dryrun:
PrettyPrint.prettyprint(config)
else:
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Nov 29 11:07:28 2006 -0700
@@ -878,15 +878,19 @@ static void vmx_do_cpuid(struct cpu_user
{
eax = ebx = ecx = edx = 0x0;
}
+ else if ( input == CPUID_LEAF_0x80000001 )
+ {
+#if CONFIG_PAGING_LEVELS >= 3
+ if ( !v->domain->arch.hvm_domain.params[HVM_PARAM_PAE_ENABLED] )
+#endif
+ clear_bit(X86_FEATURE_NX & 31, &edx);
#ifdef __i386__
- else if ( input == CPUID_LEAF_0x80000001 )
- {
clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
clear_bit(X86_FEATURE_LM & 31, &edx);
clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
- }
#endif
+ }
}
regs->eax = (unsigned long) eax;
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/arch/x86/x86_emulate.c Wed Nov 29 11:07:28 2006 -0700
@@ -615,9 +615,9 @@ x86_emulate_memop(
}
switch ( modrm_mod )
{
- case 0: if ( modrm_rm == 6 ) ea = insn_fetch(uint16_t); break;
- case 1: ea += insn_fetch(uint8_t); break;
- case 2: ea += insn_fetch(uint16_t); break;
+ case 0: if ( modrm_rm == 6 ) ea = insn_fetch(int16_t); break;
+ case 1: ea += insn_fetch(int8_t); break;
+ case 2: ea += insn_fetch(int16_t); break;
}
}
else
@@ -632,7 +632,7 @@ x86_emulate_memop(
ea = *(long *)decode_register(sib_index, &_regs, 0);
ea <<= (sib >> 6) & 3;
if ( (modrm_mod == 0) && ((sib_base & 7) == 5) )
- ea += insn_fetch(uint32_t);
+ ea += insn_fetch(int32_t);
else
ea += *(long *)decode_register(sib_base, &_regs, 0);
}
@@ -646,13 +646,13 @@ x86_emulate_memop(
case 0:
if ( (modrm_rm & 7) != 5 )
break;
- ea = insn_fetch(uint32_t);
+ ea = insn_fetch(int32_t);
if ( mode != X86EMUL_MODE_PROT64 )
break;
/* Relative to RIP of next instruction. Argh! */
ea += _regs.eip;
if ( (d & SrcMask) == SrcImm )
- ea += (d & ByteOp) ? 1 : op_bytes;
+ ea += (d & ByteOp) ? 1 : ((op_bytes == 8) ? 4 : op_bytes);
else if ( (d & SrcMask) == SrcImmByte )
ea += 1;
else if ( ((b == 0xf6) || (b == 0xf7)) &&
@@ -661,8 +661,8 @@ x86_emulate_memop(
ea += (d & ByteOp) ? 1
: ((op_bytes == 8) ? 4 : op_bytes);
break;
- case 1: ea += insn_fetch(uint8_t); break;
- case 2: ea += insn_fetch(uint32_t); break;
+ case 1: ea += insn_fetch(int8_t); break;
+ case 2: ea += insn_fetch(int32_t); break;
}
}
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/common/memory.c
--- a/xen/common/memory.c Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/common/memory.c Wed Nov 29 11:07:28 2006 -0700
@@ -328,7 +328,7 @@ static long memory_exchange(XEN_GUEST_HA
(exch.out.address_bits <
(get_order_from_pages(max_page) + PAGE_SHIFT)) )
{
- if ( exch.out.address_bits < 31 )
+ if ( exch.out.address_bits < dma_bitsize )
{
rc = -ENOMEM;
goto fail_early;
@@ -541,7 +541,7 @@ long do_memory_op(unsigned long cmd, XEN
(reservation.address_bits <
(get_order_from_pages(max_page) + PAGE_SHIFT)) )
{
- if ( reservation.address_bits < 31 )
+ if ( reservation.address_bits < dma_bitsize )
return start_extent;
args.memflags = MEMF_dma;
}
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/common/page_alloc.c
--- a/xen/common/page_alloc.c Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/common/page_alloc.c Wed Nov 29 11:07:28 2006 -0700
@@ -46,18 +46,39 @@ string_param("badpage", opt_badpage);
string_param("badpage", opt_badpage);
/*
+ * Bit width of the DMA heap.
+ */
+unsigned int dma_bitsize = CONFIG_DMA_BITSIZE;
+unsigned long max_dma_mfn = (1UL << (CONFIG_DMA_BITSIZE - PAGE_SHIFT)) - 1;
+static void parse_dma_bits(char *s)
+{
+ unsigned int v = simple_strtol(s, NULL, 0);
+ if ( v >= (sizeof(long)*8 + PAGE_SHIFT) )
+ {
+ dma_bitsize = sizeof(long)*8 + PAGE_SHIFT;
+ max_dma_mfn = ~0UL;
+ }
+ else
+ {
+ dma_bitsize = v;
+ max_dma_mfn = (1UL << (dma_bitsize - PAGE_SHIFT)) - 1;
+ }
+}
+custom_param("dma_bits", parse_dma_bits);
+
+/*
* Amount of memory to reserve in a low-memory (<4GB) pool for specific
* allocation requests. Ordinary requests will not fall back to the
* lowmem emergency pool.
*/
-static unsigned long lowmem_emergency_pool_pages;
-static void parse_lowmem_emergency_pool(char *s)
+static unsigned long dma_emergency_pool_pages;
+static void parse_dma_emergency_pool(char *s)
{
unsigned long long bytes;
bytes = parse_size_and_unit(s, NULL);
- lowmem_emergency_pool_pages = bytes >> PAGE_SHIFT;
-}
-custom_param("lowmem_emergency_pool", parse_lowmem_emergency_pool);
+ dma_emergency_pool_pages = bytes >> PAGE_SHIFT;
+}
+custom_param("dma_emergency_pool", parse_dma_emergency_pool);
#define round_pgdown(_p) ((_p)&PAGE_MASK)
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
@@ -248,7 +269,7 @@ unsigned long alloc_boot_pages(unsigned
#define NR_ZONES 3
#define pfn_dom_zone_type(_pfn) \
- (((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM)
+ (((_pfn) <= max_dma_mfn) ? MEMZONE_DMADOM : MEMZONE_DOM)
static struct list_head heap[NR_ZONES][MAX_NUMNODES][MAX_ORDER+1];
@@ -278,6 +299,8 @@ void end_boot_allocator(void)
if ( curr_free )
init_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 1);
}
+
+ printk("Domain heap initialised: DMA width %u bits\n", dma_bitsize);
}
/*
@@ -575,13 +598,13 @@ void init_domheap_pages(paddr_t ps, padd
s_tot = round_pgup(ps) >> PAGE_SHIFT;
e_tot = round_pgdown(pe) >> PAGE_SHIFT;
- s_dma = min(s_tot, MAX_DMADOM_PFN + 1);
- e_dma = min(e_tot, MAX_DMADOM_PFN + 1);
+ s_dma = min(s_tot, max_dma_mfn + 1);
+ e_dma = min(e_tot, max_dma_mfn + 1);
if ( s_dma < e_dma )
init_heap_pages(MEMZONE_DMADOM, mfn_to_page(s_dma), e_dma - s_dma);
- s_nrm = max(s_tot, MAX_DMADOM_PFN + 1);
- e_nrm = max(e_tot, MAX_DMADOM_PFN + 1);
+ s_nrm = max(s_tot, max_dma_mfn + 1);
+ e_nrm = max(e_tot, max_dma_mfn + 1);
if ( s_nrm < e_nrm )
init_heap_pages(MEMZONE_DOM, mfn_to_page(s_nrm), e_nrm - s_nrm);
}
@@ -655,7 +678,7 @@ struct page_info *__alloc_domheap_pages(
if ( unlikely(pg == NULL) &&
((order > MAX_ORDER) ||
(avail_heap_pages(MEMZONE_DMADOM,-1) <
- (lowmem_emergency_pool_pages + (1UL << order)))) )
+ (dma_emergency_pool_pages + (1UL << order)))) )
return NULL;
}
@@ -799,8 +822,8 @@ unsigned long avail_domheap_pages(void)
avail_nrm = avail_heap_pages(MEMZONE_DOM,-1);
avail_dma = avail_heap_pages(MEMZONE_DMADOM,-1);
- if ( avail_dma > lowmem_emergency_pool_pages )
- avail_dma -= lowmem_emergency_pool_pages;
+ if ( avail_dma > dma_emergency_pool_pages )
+ avail_dma -= dma_emergency_pool_pages;
else
avail_dma = 0;
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/include/asm-ia64/config.h
--- a/xen/include/asm-ia64/config.h Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/include/asm-ia64/config.h Wed Nov 29 11:07:28 2006 -0700
@@ -41,7 +41,7 @@
#define CONFIG_IOSAPIC
#define supervisor_mode_kernel (0)
-#define MAX_DMADOM_PFN (0x7FFFFFFFUL >> PAGE_SHIFT) /* 31 addressable bits */
+#define CONFIG_DMA_BITSIZE 30
/* If PERFC is used, include privop maps. */
#ifdef PERF_COUNTERS
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/include/asm-powerpc/config.h
--- a/xen/include/asm-powerpc/config.h Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/include/asm-powerpc/config.h Wed Nov 29 11:07:28 2006 -0700
@@ -70,7 +70,7 @@ extern char __bss_start[];
#define supervisor_mode_kernel (0)
-#define MAX_DMADOM_PFN (~0UL)
+#define CONFIG_DMA_BITSIZE 64
#include <asm/powerpc64/config.h>
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/include/asm-x86/config.h
--- a/xen/include/asm-x86/config.h Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/include/asm-x86/config.h Wed Nov 29 11:07:28 2006 -0700
@@ -82,7 +82,7 @@
/* Debug stack is restricted to 8kB by guard pages. */
#define DEBUG_STACK_SIZE 8192
-#define MAX_DMADOM_PFN 0x7FFFFUL /* 31 addressable bits */
+#define CONFIG_DMA_BITSIZE 30
#ifndef __ASSEMBLY__
extern unsigned long _end; /* standard ELF symbol */
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/include/public/xenoprof.h
--- a/xen/include/public/xenoprof.h Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/include/public/xenoprof.h Wed Nov 29 11:07:28 2006 -0700
@@ -28,6 +28,8 @@
#ifndef __XEN_PUBLIC_XENOPROF_H__
#define __XEN_PUBLIC_XENOPROF_H__
+
+#include "xen.h"
/*
* Commands to HYPERVISOR_xenoprof_op().
diff -r d54bcabd0624 -r d8c32fa3e3a9 xen/include/xen/mm.h
--- a/xen/include/xen/mm.h Wed Nov 29 11:05:02 2006 -0700
+++ b/xen/include/xen/mm.h Wed Nov 29 11:07:28 2006 -0700
@@ -89,6 +89,10 @@ int assign_pages(
#define MAX_ORDER 20 /* 2^20 contiguous pages */
#endif
+/* DMA heap parameters. */
+extern unsigned int dma_bitsize;
+extern unsigned long max_dma_mfn;
+
/* Automatic page scrubbing for dead domains. */
extern struct list_head page_scrub_list;
#define page_scrub_schedule_work() \
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/blktap-aio-16_03_06.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/blktap-aio-16_03_06.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,294 @@
+diff -pruN ../orig-linux-2.6.16.29/fs/aio.c ./fs/aio.c
+--- ../orig-linux-2.6.16.29/fs/aio.c 2006-09-12 19:02:10.000000000 +0100
++++ ./fs/aio.c 2006-09-19 13:58:49.000000000 +0100
+@@ -34,6 +34,11 @@
+ #include <asm/uaccess.h>
+ #include <asm/mmu_context.h>
+
++#ifdef CONFIG_EPOLL
++#include <linux/poll.h>
++#include <linux/eventpoll.h>
++#endif
++
+ #if DEBUG > 1
+ #define dprintk printk
+ #else
+@@ -1016,6 +1021,10 @@ put_rq:
+ if (waitqueue_active(&ctx->wait))
+ wake_up(&ctx->wait);
+
++#ifdef CONFIG_EPOLL
++ if (ctx->file && waitqueue_active(&ctx->poll_wait))
++ wake_up(&ctx->poll_wait);
++#endif
+ if (ret)
+ put_ioctx(ctx);
+
+@@ -1025,6 +1034,8 @@ put_rq:
+ /* aio_read_evt
+ * Pull an event off of the ioctx's event ring. Returns the number of
+ * events fetched (0 or 1 ;-)
++ * If ent parameter is 0, just returns the number of events that would
++ * be fetched.
+ * FIXME: make this use cmpxchg.
+ * TODO: make the ringbuffer user mmap()able (requires FIXME).
+ */
+@@ -1047,13 +1058,18 @@ static int aio_read_evt(struct kioctx *i
+
+ head = ring->head % info->nr;
+ if (head != ring->tail) {
+- struct io_event *evp = aio_ring_event(info, head, KM_USER1);
+- *ent = *evp;
+- head = (head + 1) % info->nr;
+- smp_mb(); /* finish reading the event before updatng the head */
+- ring->head = head;
+- ret = 1;
+- put_aio_ring_event(evp, KM_USER1);
++ if (ent) { /* event requested */
++ struct io_event *evp =
++ aio_ring_event(info, head, KM_USER1);
++ *ent = *evp;
++ head = (head + 1) % info->nr;
++ /* finish reading the event before updatng the head */
++ smp_mb();
++ ring->head = head;
++ ret = 1;
++ put_aio_ring_event(evp, KM_USER1);
++ } else /* only need to know availability */
++ ret = 1;
+ }
+ spin_unlock(&info->ring_lock);
+
+@@ -1236,9 +1252,78 @@ static void io_destroy(struct kioctx *io
+
+ aio_cancel_all(ioctx);
+ wait_for_all_aios(ioctx);
++#ifdef CONFIG_EPOLL
++ /* forget the poll file, but it's up to the user to close it */
++ if (ioctx->file) {
++ ioctx->file->private_data = 0;
++ ioctx->file = 0;
++ }
++#endif
+ put_ioctx(ioctx); /* once for the lookup */
+ }
+
++#ifdef CONFIG_EPOLL
++
++static int aio_queue_fd_close(struct inode *inode, struct file *file)
++{
++ struct kioctx *ioctx = file->private_data;
++ if (ioctx) {
++ file->private_data = 0;
++ spin_lock_irq(&ioctx->ctx_lock);
++ ioctx->file = 0;
++ spin_unlock_irq(&ioctx->ctx_lock);
++ }
++ return 0;
++}
++
++static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
++{ unsigned int pollflags = 0;
++ struct kioctx *ioctx = file->private_data;
++
++ if (ioctx) {
++
++ spin_lock_irq(&ioctx->ctx_lock);
++ /* Insert inside our poll wait queue */
++ poll_wait(file, &ioctx->poll_wait, wait);
++
++ /* Check our condition */
++ if (aio_read_evt(ioctx, 0))
++ pollflags = POLLIN | POLLRDNORM;
++ spin_unlock_irq(&ioctx->ctx_lock);
++ }
++
++ return pollflags;
++}
++
++static struct file_operations aioq_fops = {
++ .release = aio_queue_fd_close,
++ .poll = aio_queue_fd_poll
++};
++
++/* make_aio_fd:
++ * Create a file descriptor that can be used to poll the event queue.
++ * Based and piggybacked on the excellent epoll code.
++ */
++
++static int make_aio_fd(struct kioctx *ioctx)
++{
++ int error, fd;
++ struct inode *inode;
++ struct file *file;
++
++ error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
++ if (error)
++ return error;
++
++ /* associate the file with the IO context */
++ file->private_data = ioctx;
++ ioctx->file = file;
++ init_waitqueue_head(&ioctx->poll_wait);
++ return fd;
++}
++#endif
++
++
+ /* sys_io_setup:
+ * Create an aio_context capable of receiving at least nr_events.
+ * ctxp must not point to an aio_context that already exists, and
+@@ -1251,18 +1336,30 @@ static void io_destroy(struct kioctx *io
+ * resources are available. May fail with -EFAULT if an invalid
+ * pointer is passed for ctxp. Will fail with -ENOSYS if not
+ * implemented.
++ *
++ * To request a selectable fd, the user context has to be initialized
++ * to 1, instead of 0, and the return value is the fd.
++ * This keeps the system call compatible, since a non-zero value
++ * was not allowed so far.
+ */
+ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
+ {
+ struct kioctx *ioctx = NULL;
+ unsigned long ctx;
+ long ret;
++ int make_fd = 0;
+
+ ret = get_user(ctx, ctxp);
+ if (unlikely(ret))
+ goto out;
+
+ ret = -EINVAL;
++#ifdef CONFIG_EPOLL
++ if (ctx == 1) {
++ make_fd = 1;
++ ctx = 0;
++ }
++#endif
+ if (unlikely(ctx || nr_events == 0)) {
+ pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
+ ctx, nr_events);
+@@ -1273,8 +1370,12 @@ asmlinkage long sys_io_setup(unsigned nr
+ ret = PTR_ERR(ioctx);
+ if (!IS_ERR(ioctx)) {
+ ret = put_user(ioctx->user_id, ctxp);
+- if (!ret)
+- return 0;
++#ifdef CONFIG_EPOLL
++ if (make_fd && ret >= 0)
++ ret = make_aio_fd(ioctx);
++#endif
++ if (ret >= 0)
++ return ret;
+
+ get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
+ io_destroy(ioctx);
+diff -pruN ../orig-linux-2.6.16.29/fs/eventpoll.c ./fs/eventpoll.c
+--- ../orig-linux-2.6.16.29/fs/eventpoll.c 2006-09-12 19:02:10.000000000
+0100
++++ ./fs/eventpoll.c 2006-09-19 13:58:49.000000000 +0100
+@@ -235,8 +235,6 @@ struct ep_pqueue {
+
+ static void ep_poll_safewake_init(struct poll_safewake *psw);
+ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t
*wq);
+-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+- struct eventpoll *ep);
+ static int ep_alloc(struct eventpoll **pep);
+ static void ep_free(struct eventpoll *ep);
+ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int
fd);
+@@ -266,7 +264,7 @@ static int ep_events_transfer(struct eve
+ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
+ int maxevents, long timeout);
+ static int eventpollfs_delete_dentry(struct dentry *dentry);
+-static struct inode *ep_eventpoll_inode(void);
++static struct inode *ep_eventpoll_inode(struct file_operations *fops);
+ static struct super_block *eventpollfs_get_sb(struct file_system_type
*fs_type,
+ int flags, const char *dev_name,
+ void *data);
+@@ -525,7 +523,7 @@ asmlinkage long sys_epoll_create(int siz
+ * Creates all the items needed to setup an eventpoll file. That is,
+ * a file structure, and inode and a free file descriptor.
+ */
+- error = ep_getfd(&fd, &inode, &file, ep);
++ error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
+ if (error)
+ goto eexit_2;
+
+@@ -710,8 +708,8 @@ eexit_1:
+ /*
+ * Creates the file descriptor to be used by the epoll interface.
+ */
+-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
+- struct eventpoll *ep)
++int ep_getfd(int *efd, struct inode **einode, struct file **efile,
++ struct eventpoll *ep, struct file_operations *fops)
+ {
+ struct qstr this;
+ char name[32];
+@@ -727,7 +725,7 @@ static int ep_getfd(int *efd, struct ino
+ goto eexit_1;
+
+ /* Allocates an inode from the eventpoll file system */
+- inode = ep_eventpoll_inode();
++ inode = ep_eventpoll_inode(fops);
+ error = PTR_ERR(inode);
+ if (IS_ERR(inode))
+ goto eexit_2;
+@@ -758,7 +756,7 @@ static int ep_getfd(int *efd, struct ino
+
+ file->f_pos = 0;
+ file->f_flags = O_RDONLY;
+- file->f_op = &eventpoll_fops;
++ file->f_op = fops;
+ file->f_mode = FMODE_READ;
+ file->f_version = 0;
+ file->private_data = ep;
+@@ -1574,7 +1572,7 @@ static int eventpollfs_delete_dentry(str
+ }
+
+
+-static struct inode *ep_eventpoll_inode(void)
++static struct inode *ep_eventpoll_inode(struct file_operations *fops)
+ {
+ int error = -ENOMEM;
+ struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
+@@ -1582,7 +1580,7 @@ static struct inode *ep_eventpoll_inode(
+ if (!inode)
+ goto eexit_1;
+
+- inode->i_fop = &eventpoll_fops;
++ inode->i_fop = fops;
+
+ /*
+ * Mark the inode dirty from the very beginning,
+diff -pruN ../orig-linux-2.6.16.29/include/linux/aio.h ./include/linux/aio.h
+--- ../orig-linux-2.6.16.29/include/linux/aio.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/linux/aio.h 2006-09-19 13:58:49.000000000 +0100
+@@ -191,6 +191,11 @@ struct kioctx {
+ struct aio_ring_info ring_info;
+
+ struct work_struct wq;
++#ifdef CONFIG_EPOLL
++ // poll integration
++ wait_queue_head_t poll_wait;
++ struct file *file;
++#endif
+ };
+
+ /* prototypes */
+diff -pruN ../orig-linux-2.6.16.29/include/linux/eventpoll.h
./include/linux/eventpoll.h
+--- ../orig-linux-2.6.16.29/include/linux/eventpoll.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/linux/eventpoll.h 2006-09-19 13:58:49.000000000 +0100
+@@ -86,6 +86,12 @@ static inline void eventpoll_release(str
+ }
+
+
++/*
++ * called by aio code to create fd that can poll the aio event queueQ
++ */
++struct eventpoll;
++int ep_getfd(int *efd, struct inode **einode, struct file **efile,
++ struct eventpoll *ep, struct file_operations *fops);
+ #else
+
+ static inline void eventpoll_init_file(struct file *file) {}
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/device_bind.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/device_bind.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,15 @@
+diff -pruN ../orig-linux-2.6.16.29/drivers/base/bus.c ./drivers/base/bus.c
+--- ../orig-linux-2.6.16.29/drivers/base/bus.c 2006-09-12 19:02:10.000000000
+0100
++++ ./drivers/base/bus.c 2006-09-19 13:58:54.000000000 +0100
+@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device
+ up(&dev->sem);
+ if (dev->parent)
+ up(&dev->parent->sem);
++
++ if (err > 0) /* success */
++ err = count;
++ else if (err == 0) /* driver didn't accept device */
++ err = -ENODEV;
+ }
+ put_device(dev);
+ put_bus(bus);
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/fix-hz-suspend.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/fix-hz-suspend.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,26 @@
+diff -pruN ../orig-linux-2.6.16.29/kernel/timer.c ./kernel/timer.c
+--- ../orig-linux-2.6.16.29/kernel/timer.c 2006-09-12 19:02:10.000000000
+0100
++++ ./kernel/timer.c 2006-09-19 13:58:58.000000000 +0100
+@@ -555,6 +555,22 @@ found:
+ }
+ spin_unlock(&base->t_base.lock);
+
++ /*
++ * It can happen that other CPUs service timer IRQs and increment
++ * jiffies, but we have not yet got a local timer tick to process
++ * the timer wheels. In that case, the expiry time can be before
++ * jiffies, but since the high-resolution timer here is relative to
++ * jiffies, the default expression when high-resolution timers are
++ * not active,
++ *
++ * time_before(MAX_JIFFY_OFFSET + jiffies, expires)
++ *
++ * would falsely evaluate to true. If that is the case, just
++ * return jiffies so that we can immediately fire the local timer
++ */
++ if (time_before(expires, jiffies))
++ return jiffies;
++
+ if (time_before(hr_expires, expires))
+ return hr_expires;
+
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/fix-ide-cd-pio-mode.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/fix-ide-cd-pio-mode.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,18 @@
+diff -pruN ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c
./drivers/ide/ide-lib.c
+--- ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c 2006-09-12
19:02:10.000000000 +0100
++++ ./drivers/ide/ide-lib.c 2006-09-19 13:59:03.000000000 +0100
+@@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *driv
+ {
+ u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
+
+- if (!PCI_DMA_BUS_IS_PHYS) {
+- addr = BLK_BOUNCE_ANY;
+- } else if (on && drive->media == ide_disk) {
+- if (HWIF(drive)->pci_dev)
++ if (on && drive->media == ide_disk) {
++ if (!PCI_DMA_BUS_IS_PHYS)
++ addr = BLK_BOUNCE_ANY;
++ else if (HWIF(drive)->pci_dev)
+ addr = HWIF(drive)->pci_dev->dma_mask;
+ }
+
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/i386-mach-io-check-nmi.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/i386-mach-io-check-nmi.patch Wed Nov 29
11:07:28 2006 -0700
@@ -0,0 +1,45 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c
./arch/i386/kernel/traps.c
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/kernel/traps.c 2006-09-19 13:59:06.000000000 +0100
+@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
+
+ static void io_check_error(unsigned char reason, struct pt_regs * regs)
+ {
+- unsigned long i;
+-
+ printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
+ show_registers(regs);
+
+ /* Re-enable the IOCK line, wait for a few seconds */
+- reason = (reason & 0xf) | 8;
+- outb(reason, 0x61);
+- i = 2000;
+- while (--i) udelay(1000);
+- reason &= ~8;
+- outb(reason, 0x61);
++ clear_io_check_error(reason);
+ }
+
+ static void unknown_nmi_error(unsigned char reason, struct pt_regs * regs)
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/mach-default/mach_traps.h
./include/asm-i386/mach-default/mach_traps.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/mach-default/mach_traps.h
2006-09-12 19:02:10.000000000 +0100
++++ ./include/asm-i386/mach-default/mach_traps.h 2006-09-19
13:59:06.000000000 +0100
+@@ -15,6 +15,18 @@ static inline void clear_mem_error(unsig
+ outb(reason, 0x61);
+ }
+
++static inline void clear_io_check_error(unsigned char reason)
++{
++ unsigned long i;
++
++ reason = (reason & 0xf) | 8;
++ outb(reason, 0x61);
++ i = 2000;
++ while (--i) udelay(1000);
++ reason &= ~8;
++ outb(reason, 0x61);
++}
++
+ static inline unsigned char get_nmi_reason(void)
+ {
+ return inb(0x61);
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/ipv6-no-autoconf.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/ipv6-no-autoconf.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,19 @@
+diff -pruN ../orig-linux-2.6.16.29/net/ipv6/addrconf.c ./net/ipv6/addrconf.c
+--- ../orig-linux-2.6.16.29/net/ipv6/addrconf.c 2006-09-12
19:02:10.000000000 +0100
++++ ./net/ipv6/addrconf.c 2006-09-19 13:59:11.000000000 +0100
+@@ -2471,6 +2471,7 @@ static void addrconf_dad_start(struct in
+ spin_lock_bh(&ifp->lock);
+
+ if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) ||
++ !(dev->flags&IFF_MULTICAST) ||
+ !(ifp->flags&IFA_F_TENTATIVE)) {
+ ifp->flags &= ~IFA_F_TENTATIVE;
+ spin_unlock_bh(&ifp->lock);
+@@ -2555,6 +2556,7 @@ static void addrconf_dad_completed(struc
+ if (ifp->idev->cnf.forwarding == 0 &&
+ ifp->idev->cnf.rtr_solicits > 0 &&
+ (dev->flags&IFF_LOOPBACK) == 0 &&
++ (dev->flags & IFF_MULTICAST) &&
+ (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
+ struct in6_addr all_routers;
+
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/kasprintf.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/kasprintf.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,59 @@
+commit e905914f96e11862b130dd229f73045dad9a34e8
+Author: Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
+Date: Sun Jun 25 05:49:17 2006 -0700
+
+ [PATCH] Implement kasprintf
+
+ Implement kasprintf, a kernel version of asprintf. This allocates the
+ memory required for the formatted string, including the trailing '\0'.
+ Returns NULL on allocation failure.
+
+ Signed-off-by: Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
+ Signed-off-by: Chris Wright <chrisw@xxxxxxxxxxxx>
+ Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
+ Signed-off-by: Linus Torvalds <torvalds@xxxxxxxx>
+
+diff --git a/include/linux/kernel.h b/include/linux/kernel.h
+index 8c21aaa..3c5e4c2 100644
+--- a/include/linux/kernel.h
++++ b/include/linux/kernel.h
+@@ -117,6 +117,8 @@ extern int scnprintf(char * buf, size_t
+ __attribute__ ((format (printf, 3, 4)));
+ extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+ __attribute__ ((format (printf, 3, 0)));
++extern char *kasprintf(gfp_t gfp, const char *fmt, ...)
++ __attribute__ ((format (printf, 2, 3)));
+
+ extern int sscanf(const char *, const char *, ...)
+ __attribute__ ((format (scanf, 2, 3)));
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c
+index f595947..797428a 100644
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -849,3 +849,26 @@ int sscanf(const char * buf, const char
+ }
+
+ EXPORT_SYMBOL(sscanf);
++
++
++/* Simplified asprintf. */
++char *kasprintf(gfp_t gfp, const char *fmt, ...)
++{
++ va_list ap;
++ unsigned int len;
++ char *p;
++
++ va_start(ap, fmt);
++ len = vsnprintf(NULL, 0, fmt, ap);
++ va_end(ap);
++
++ p = kmalloc(len+1, gfp);
++ if (!p)
++ return NULL;
++ va_start(ap, fmt);
++ vsnprintf(p, len+1, fmt, ap);
++ va_end(ap);
++ return p;
++}
++
++EXPORT_SYMBOL(kasprintf);
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/net-csum.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-csum.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,63 @@
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_tcp.c
./net/ipv4/netfilter/ip_nat_proto_tcp.c
+--- ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_tcp.c
2006-09-12 19:02:10.000000000 +0100
++++ ./net/ipv4/netfilter/ip_nat_proto_tcp.c 2006-09-19 13:59:15.000000000
+0100
+@@ -129,7 +129,12 @@ tcp_manip_pkt(struct sk_buff **pskb,
+ if (hdrsize < sizeof(*hdr))
+ return 1;
+
+- hdr->check = ip_nat_cheat_check(~oldip, newip,
++#ifdef CONFIG_XEN
++ if ((*pskb)->proto_csum_blank)
++ hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
++ else
++#endif
++ hdr->check = ip_nat_cheat_check(~oldip, newip,
+ ip_nat_cheat_check(oldport ^ 0xFFFF,
+ newport,
+ hdr->check));
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_udp.c
./net/ipv4/netfilter/ip_nat_proto_udp.c
+--- ../orig-linux-2.6.16.29/net/ipv4/netfilter/ip_nat_proto_udp.c
2006-09-12 19:02:10.000000000 +0100
++++ ./net/ipv4/netfilter/ip_nat_proto_udp.c 2006-09-19 13:59:15.000000000
+0100
+@@ -113,11 +113,17 @@ udp_manip_pkt(struct sk_buff **pskb,
+ newport = tuple->dst.u.udp.port;
+ portptr = &hdr->dest;
+ }
+- if (hdr->check) /* 0 is a special case meaning no checksum */
+- hdr->check = ip_nat_cheat_check(~oldip, newip,
++ if (hdr->check) { /* 0 is a special case meaning no checksum */
++#ifdef CONFIG_XEN
++ if ((*pskb)->proto_csum_blank)
++ hdr->check = ip_nat_cheat_check(oldip, ~newip,
hdr->check);
++ else
++#endif
++ hdr->check = ip_nat_cheat_check(~oldip, newip,
+ ip_nat_cheat_check(*portptr ^ 0xFFFF,
+ newport,
+ hdr->check));
++ }
+ *portptr = newport;
+ return 1;
+ }
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c
./net/ipv4/xfrm4_output.c
+--- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c 2006-09-12
19:02:10.000000000 +0100
++++ ./net/ipv4/xfrm4_output.c 2006-09-19 13:59:15.000000000 +0100
+@@ -17,6 +17,8 @@
+ #include <net/xfrm.h>
+ #include <net/icmp.h>
+
++extern int skb_checksum_setup(struct sk_buff *skb);
++
+ /* Add encapsulation header.
+ *
+ * In transport mode, the IP header will be moved forward to make space
+@@ -103,6 +105,10 @@ static int xfrm4_output_one(struct sk_bu
+ struct xfrm_state *x = dst->xfrm;
+ int err;
+
++ err = skb_checksum_setup(skb);
++ if (err)
++ goto error_nolock;
++
+ if (skb->ip_summed == CHECKSUM_HW) {
+ err = skb_checksum_help(skb, 0);
+ if (err)
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/net-gso-0-base.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-gso-0-base.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,2898 @@
+Index: tmp-xxx/Documentation/networking/netdevices.txt
+===================================================================
+--- tmp-xxx.orig/Documentation/networking/netdevices.txt 2006-11-15
10:38:39.000000000 +0000
++++ tmp-xxx/Documentation/networking/netdevices.txt 2006-11-27
10:52:42.000000000 +0000
+@@ -42,9 +42,9 @@
+ Context: nominally process, but don't sleep inside an rwlock
+
+ dev->hard_start_xmit:
+- Synchronization: dev->xmit_lock spinlock.
++ Synchronization: netif_tx_lock spinlock.
+ When the driver sets NETIF_F_LLTX in dev->features this will be
+- called without holding xmit_lock. In this case the driver
++ called without holding netif_tx_lock. In this case the driver
+ has to lock by itself when needed. It is recommended to use a try lock
+ for this and return -1 when the spin lock fails.
+ The locking there should also properly protect against
+@@ -62,12 +62,12 @@
+ Only valid when NETIF_F_LLTX is set.
+
+ dev->tx_timeout:
+- Synchronization: dev->xmit_lock spinlock.
++ Synchronization: netif_tx_lock spinlock.
+ Context: BHs disabled
+ Notes: netif_queue_stopped() is guaranteed true
+
+ dev->set_multicast_list:
+- Synchronization: dev->xmit_lock spinlock.
++ Synchronization: netif_tx_lock spinlock.
+ Context: BHs disabled
+
+ dev->poll:
+Index: tmp-xxx/drivers/block/aoe/aoenet.c
+===================================================================
+--- tmp-xxx.orig/drivers/block/aoe/aoenet.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/block/aoe/aoenet.c 2006-11-27 10:52:42.000000000 +0000
+@@ -95,9 +95,8 @@
+ static struct sk_buff *
+ skb_check(struct sk_buff *skb)
+ {
+- if (skb_is_nonlinear(skb))
+ if ((skb = skb_share_check(skb, GFP_ATOMIC)))
+- if (skb_linearize(skb, GFP_ATOMIC) < 0) {
++ if (skb_linearize(skb)) {
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+Index: tmp-xxx/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+===================================================================
+--- tmp-xxx.orig/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/infiniband/ulp/ipoib/ipoib_multicast.c 2006-11-27
10:52:42.000000000 +0000
+@@ -821,7 +821,8 @@
+
+ ipoib_mcast_stop_thread(dev, 0);
+
+- spin_lock_irqsave(&dev->xmit_lock, flags);
++ local_irq_save(flags);
++ netif_tx_lock(dev);
+ spin_lock(&priv->lock);
+
+ /*
+@@ -896,7 +897,8 @@
+ }
+
+ spin_unlock(&priv->lock);
+- spin_unlock_irqrestore(&dev->xmit_lock, flags);
++ netif_tx_unlock(dev);
++ local_irq_restore(flags);
+
+ /* We have to cancel outside of the spinlock */
+ list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
+Index: tmp-xxx/drivers/media/dvb/dvb-core/dvb_net.c
+===================================================================
+--- tmp-xxx.orig/drivers/media/dvb/dvb-core/dvb_net.c 2006-11-15
10:38:39.000000000 +0000
++++ tmp-xxx/drivers/media/dvb/dvb-core/dvb_net.c 2006-11-27
10:52:42.000000000 +0000
+@@ -1053,7 +1053,7 @@
+
+ dvb_net_feed_stop(dev);
+ priv->rx_mode = RX_MODE_UNI;
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+
+ if (dev->flags & IFF_PROMISC) {
+ dprintk("%s: promiscuous mode\n", dev->name);
+@@ -1078,7 +1078,7 @@
+ }
+ }
+
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ dvb_net_feed_start(dev);
+ }
+
+Index: tmp-xxx/drivers/net/8139cp.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/8139cp.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/8139cp.c 2006-11-27 10:52:42.000000000 +0000
+@@ -794,7 +794,7 @@
+ entry = cp->tx_head;
+ eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
+ if (dev->features & NETIF_F_TSO)
+- mss = skb_shinfo(skb)->tso_size;
++ mss = skb_shinfo(skb)->gso_size;
+
+ if (skb_shinfo(skb)->nr_frags == 0) {
+ struct cp_desc *txd = &cp->tx_ring[entry];
+Index: tmp-xxx/drivers/net/bnx2.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/bnx2.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/bnx2.c 2006-11-27 10:52:42.000000000 +0000
+@@ -1593,7 +1593,7 @@
+ skb = tx_buf->skb;
+ #ifdef BCM_TSO
+ /* partial BD completions possible with TSO packets */
+- if (skb_shinfo(skb)->tso_size) {
++ if (skb_shinfo(skb)->gso_size) {
+ u16 last_idx, last_ring_idx;
+
+ last_idx = sw_cons +
+@@ -1948,7 +1948,7 @@
+ return 1;
+ }
+
+-/* Called with rtnl_lock from vlan functions and also dev->xmit_lock
++/* Called with rtnl_lock from vlan functions and also netif_tx_lock
+ * from set_multicast.
+ */
+ static void
+@@ -4403,7 +4403,7 @@
+ }
+ #endif
+
+-/* Called with dev->xmit_lock.
++/* Called with netif_tx_lock.
+ * hard_start_xmit is pseudo-lockless - a lock is only required when
+ * the tx queue is full. This way, we get the benefit of lockless
+ * operations most of the time without the complexities to handle
+@@ -4441,7 +4441,7 @@
+ (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16));
+ }
+ #ifdef BCM_TSO
+- if ((mss = skb_shinfo(skb)->tso_size) &&
++ if ((mss = skb_shinfo(skb)->gso_size) &&
+ (skb->len > (bp->dev->mtu + ETH_HLEN))) {
+ u32 tcp_opt_len, ip_tcp_len;
+
+Index: tmp-xxx/drivers/net/bonding/bond_main.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/bonding/bond_main.c 2006-11-15
10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/bonding/bond_main.c 2006-11-27 10:52:42.000000000
+0000
+@@ -1145,8 +1145,7 @@
+ }
+
+ #define BOND_INTERSECT_FEATURES \
+- (NETIF_F_SG|NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM|\
+- NETIF_F_TSO|NETIF_F_UFO)
++ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_TSO | NETIF_F_UFO)
+
+ /*
+ * Compute the common dev->feature set available to all slaves. Some
+@@ -1164,9 +1163,7 @@
+ features &= (slave->dev->features & BOND_INTERSECT_FEATURES);
+
+ if ((features & NETIF_F_SG) &&
+- !(features & (NETIF_F_IP_CSUM |
+- NETIF_F_NO_CSUM |
+- NETIF_F_HW_CSUM)))
++ !(features & NETIF_F_ALL_CSUM))
+ features &= ~NETIF_F_SG;
+
+ /*
+@@ -4147,7 +4144,7 @@
+ */
+ bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
+
+- /* don't acquire bond device's xmit_lock when
++ /* don't acquire bond device's netif_tx_lock when
+ * transmitting */
+ bond_dev->features |= NETIF_F_LLTX;
+
+Index: tmp-xxx/drivers/net/chelsio/sge.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/chelsio/sge.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/chelsio/sge.c 2006-11-27 10:52:42.000000000 +0000
+@@ -1419,7 +1419,7 @@
+ struct cpl_tx_pkt *cpl;
+
+ #ifdef NETIF_F_TSO
+- if (skb_shinfo(skb)->tso_size) {
++ if (skb_shinfo(skb)->gso_size) {
+ int eth_type;
+ struct cpl_tx_pkt_lso *hdr;
+
+@@ -1434,7 +1434,7 @@
+ hdr->ip_hdr_words = skb->nh.iph->ihl;
+ hdr->tcp_hdr_words = skb->h.th->doff;
+ hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
+- skb_shinfo(skb)->tso_size));
++ skb_shinfo(skb)->gso_size));
+ hdr->len = htonl(skb->len - sizeof(*hdr));
+ cpl = (struct cpl_tx_pkt *)hdr;
+ sge->stats.tx_lso_pkts++;
+Index: tmp-xxx/drivers/net/e1000/e1000_main.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/e1000/e1000_main.c 2006-11-15
10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/e1000/e1000_main.c 2006-11-27 10:52:42.000000000
+0000
+@@ -2526,7 +2526,7 @@
+ uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+ int err;
+
+- if (skb_shinfo(skb)->tso_size) {
++ if (skb_shinfo(skb)->gso_size) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+@@ -2534,7 +2534,7 @@
+ }
+
+ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+- mss = skb_shinfo(skb)->tso_size;
++ mss = skb_shinfo(skb)->gso_size;
+ if (skb->protocol == ntohs(ETH_P_IP)) {
+ skb->nh.iph->tot_len = 0;
+ skb->nh.iph->check = 0;
+@@ -2651,7 +2651,7 @@
+ * tso gets written back prematurely before the data is fully
+ * DMAd to the controller */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+- !skb_shinfo(skb)->tso_size) {
++ !skb_shinfo(skb)->gso_size) {
+ tx_ring->last_tx_tso = 0;
+ size -= 4;
+ }
+@@ -2893,7 +2893,7 @@
+ }
+
+ #ifdef NETIF_F_TSO
+- mss = skb_shinfo(skb)->tso_size;
++ mss = skb_shinfo(skb)->gso_size;
+ /* The controller does a simple calculation to
+ * make sure there is enough room in the FIFO before
+ * initiating the DMA for each buffer. The calc is:
+@@ -2935,7 +2935,7 @@
+ #ifdef NETIF_F_TSO
+ /* Controller Erratum workaround */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+- !skb_shinfo(skb)->tso_size)
++ !skb_shinfo(skb)->gso_size)
+ count++;
+ #endif
+
+Index: tmp-xxx/drivers/net/forcedeth.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/forcedeth.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/forcedeth.c 2006-11-27 10:52:42.000000000 +0000
+@@ -482,9 +482,9 @@
+ * critical parts:
+ * - rx is (pseudo-) lockless: it relies on the single-threading provided
+ * by the arch code for interrupts.
+- * - tx setup is lockless: it relies on dev->xmit_lock. Actual submission
++ * - tx setup is lockless: it relies on netif_tx_lock. Actual submission
+ * needs dev->priv->lock :-(
+- * - set_multicast_list: preparation lockless, relies on dev->xmit_lock.
++ * - set_multicast_list: preparation lockless, relies on netif_tx_lock.
+ */
+
+ /* in dev: base, irq */
+@@ -1016,7 +1016,7 @@
+
+ /*
+ * nv_start_xmit: dev->hard_start_xmit function
+- * Called with dev->xmit_lock held.
++ * Called with netif_tx_lock held.
+ */
+ static int nv_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+@@ -1105,8 +1105,8 @@
+ np->tx_skbuff[nr] = skb;
+
+ #ifdef NETIF_F_TSO
+- if (skb_shinfo(skb)->tso_size)
+- tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->tso_size <<
NV_TX2_TSO_SHIFT);
++ if (skb_shinfo(skb)->gso_size)
++ tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size <<
NV_TX2_TSO_SHIFT);
+ else
+ #endif
+ tx_flags_extra = (skb->ip_summed == CHECKSUM_HW ?
(NV_TX2_CHECKSUM_L3|NV_TX2_CHECKSUM_L4) : 0);
+@@ -1203,7 +1203,7 @@
+
+ /*
+ * nv_tx_timeout: dev->tx_timeout function
+- * Called with dev->xmit_lock held.
++ * Called with netif_tx_lock held.
+ */
+ static void nv_tx_timeout(struct net_device *dev)
+ {
+@@ -1524,7 +1524,7 @@
+ * Changing the MTU is a rare event, it shouldn't matter.
+ */
+ disable_irq(dev->irq);
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ spin_lock(&np->lock);
+ /* stop engines */
+ nv_stop_rx(dev);
+@@ -1559,7 +1559,7 @@
+ nv_start_rx(dev);
+ nv_start_tx(dev);
+ spin_unlock(&np->lock);
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ enable_irq(dev->irq);
+ }
+ return 0;
+@@ -1594,7 +1594,7 @@
+ memcpy(dev->dev_addr, macaddr->sa_data, ETH_ALEN);
+
+ if (netif_running(dev)) {
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ spin_lock_irq(&np->lock);
+
+ /* stop rx engine */
+@@ -1606,7 +1606,7 @@
+ /* restart rx engine */
+ nv_start_rx(dev);
+ spin_unlock_irq(&np->lock);
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ } else {
+ nv_copy_mac_to_hw(dev);
+ }
+@@ -1615,7 +1615,7 @@
+
+ /*
+ * nv_set_multicast: dev->set_multicast function
+- * Called with dev->xmit_lock held.
++ * Called with netif_tx_lock held.
+ */
+ static void nv_set_multicast(struct net_device *dev)
+ {
+Index: tmp-xxx/drivers/net/hamradio/6pack.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/hamradio/6pack.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/hamradio/6pack.c 2006-11-27 10:52:42.000000000
+0000
+@@ -308,9 +308,9 @@
+ {
+ struct sockaddr_ax25 *sa = addr;
+
+- spin_lock_irq(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
+- spin_unlock_irq(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+
+ return 0;
+ }
+@@ -767,9 +767,9 @@
+ break;
+ }
+
+- spin_lock_irq(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ memcpy(dev->dev_addr, &addr, AX25_ADDR_LEN);
+- spin_unlock_irq(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+
+ err = 0;
+ break;
+Index: tmp-xxx/drivers/net/hamradio/mkiss.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/hamradio/mkiss.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/hamradio/mkiss.c 2006-11-27 10:52:42.000000000
+0000
+@@ -357,9 +357,9 @@
+ {
+ struct sockaddr_ax25 *sa = addr;
+
+- spin_lock_irq(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ memcpy(dev->dev_addr, &sa->sax25_call, AX25_ADDR_LEN);
+- spin_unlock_irq(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+
+ return 0;
+ }
+@@ -886,9 +886,9 @@
+ break;
+ }
+
+- spin_lock_irq(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ memcpy(dev->dev_addr, addr, AX25_ADDR_LEN);
+- spin_unlock_irq(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+
+ err = 0;
+ break;
+Index: tmp-xxx/drivers/net/ifb.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/ifb.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/ifb.c 2006-11-27 10:52:42.000000000 +0000
+@@ -76,13 +76,13 @@
+ dp->st_task_enter++;
+ if ((skb = skb_peek(&dp->tq)) == NULL) {
+ dp->st_txq_refl_try++;
+- if (spin_trylock(&_dev->xmit_lock)) {
++ if (netif_tx_trylock(_dev)) {
+ dp->st_rxq_enter++;
+ while ((skb = skb_dequeue(&dp->rq)) != NULL) {
+ skb_queue_tail(&dp->tq, skb);
+ dp->st_rx2tx_tran++;
+ }
+- spin_unlock(&_dev->xmit_lock);
++ netif_tx_unlock(_dev);
+ } else {
+ /* reschedule */
+ dp->st_rxq_notenter++;
+@@ -110,7 +110,7 @@
+ }
+ }
+
+- if (spin_trylock(&_dev->xmit_lock)) {
++ if (netif_tx_trylock(_dev)) {
+ dp->st_rxq_check++;
+ if ((skb = skb_peek(&dp->rq)) == NULL) {
+ dp->tasklet_pending = 0;
+@@ -118,10 +118,10 @@
+ netif_wake_queue(_dev);
+ } else {
+ dp->st_rxq_rsch++;
+- spin_unlock(&_dev->xmit_lock);
++ netif_tx_unlock(_dev);
+ goto resched;
+ }
+- spin_unlock(&_dev->xmit_lock);
++ netif_tx_unlock(_dev);
+ } else {
+ resched:
+ dp->tasklet_pending = 1;
+Index: tmp-xxx/drivers/net/irda/vlsi_ir.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/irda/vlsi_ir.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/irda/vlsi_ir.c 2006-11-27 10:52:42.000000000 +0000
+@@ -959,7 +959,7 @@
+ || (now.tv_sec==ready.tv_sec &&
now.tv_usec>=ready.tv_usec))
+ break;
+ udelay(100);
+- /* must not sleep here - we are called under xmit_lock!
*/
++ /* must not sleep here - called under netif_tx_lock! */
+ }
+ }
+
+Index: tmp-xxx/drivers/net/ixgb/ixgb_main.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/ixgb/ixgb_main.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/ixgb/ixgb_main.c 2006-11-27 10:52:42.000000000
+0000
+@@ -1163,7 +1163,7 @@
+ uint16_t ipcse, tucse, mss;
+ int err;
+
+- if(likely(skb_shinfo(skb)->tso_size)) {
++ if(likely(skb_shinfo(skb)->gso_size)) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+@@ -1171,7 +1171,7 @@
+ }
+
+ hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
+- mss = skb_shinfo(skb)->tso_size;
++ mss = skb_shinfo(skb)->gso_size;
+ skb->nh.iph->tot_len = 0;
+ skb->nh.iph->check = 0;
+ skb->h.th->check = ~csum_tcpudp_magic(skb->nh.iph->saddr,
+Index: tmp-xxx/drivers/net/loopback.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/loopback.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/loopback.c 2006-11-27 10:52:42.000000000 +0000
+@@ -74,7 +74,7 @@
+ struct iphdr *iph = skb->nh.iph;
+ struct tcphdr *th = (struct tcphdr*)(skb->nh.raw + (iph->ihl * 4));
+ unsigned int doffset = (iph->ihl + th->doff) * 4;
+- unsigned int mtu = skb_shinfo(skb)->tso_size + doffset;
++ unsigned int mtu = skb_shinfo(skb)->gso_size + doffset;
+ unsigned int offset = 0;
+ u32 seq = ntohl(th->seq);
+ u16 id = ntohs(iph->id);
+@@ -139,7 +139,7 @@
+ #endif
+
+ #ifdef LOOPBACK_TSO
+- if (skb_shinfo(skb)->tso_size) {
++ if (skb_shinfo(skb)->gso_size) {
+ BUG_ON(skb->protocol != htons(ETH_P_IP));
+ BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
+
+Index: tmp-xxx/drivers/net/mv643xx_eth.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/mv643xx_eth.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/mv643xx_eth.c 2006-11-27 10:52:42.000000000 +0000
+@@ -1107,7 +1107,7 @@
+
+ #ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+ if (has_tiny_unaligned_frags(skb)) {
+- if ((skb_linearize(skb, GFP_ATOMIC) != 0)) {
++ if (__skb_linearize(skb)) {
+ stats->tx_dropped++;
+ printk(KERN_DEBUG "%s: failed to linearize tiny "
+ "unaligned fragment\n", dev->name);
+Index: tmp-xxx/drivers/net/natsemi.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/natsemi.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/natsemi.c 2006-11-27 10:52:42.000000000 +0000
+@@ -323,12 +323,12 @@
+ The rx process only runs in the interrupt handler. Access from outside
+ the interrupt handler is only permitted after disable_irq().
+
+-The rx process usually runs under the dev->xmit_lock. If np->intr_tx_reap
++The rx process usually runs under the netif_tx_lock. If np->intr_tx_reap
+ is set, then access is permitted under spin_lock_irq(&np->lock).
+
+ Thus configuration functions that want to access everything must call
+ disable_irq(dev->irq);
+- spin_lock_bh(dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ spin_lock_irq(&np->lock);
+
+ IV. Notes
+Index: tmp-xxx/drivers/net/r8169.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/r8169.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/r8169.c 2006-11-27 10:52:42.000000000 +0000
+@@ -2171,7 +2171,7 @@
+ static inline u32 rtl8169_tso_csum(struct sk_buff *skb, struct net_device
*dev)
+ {
+ if (dev->features & NETIF_F_TSO) {
+- u32 mss = skb_shinfo(skb)->tso_size;
++ u32 mss = skb_shinfo(skb)->gso_size;
+
+ if (mss)
+ return LargeSend | ((mss & MSSMask) << MSSShift);
+Index: tmp-xxx/drivers/net/s2io.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/s2io.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/s2io.c 2006-11-27 10:52:42.000000000 +0000
+@@ -3522,8 +3522,8 @@
+ txdp->Control_1 = 0;
+ txdp->Control_2 = 0;
+ #ifdef NETIF_F_TSO
+- mss = skb_shinfo(skb)->tso_size;
+- if (mss) {
++ mss = skb_shinfo(skb)->gso_size;
++ if (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV4) {
+ txdp->Control_1 |= TXD_TCP_LSO_EN;
+ txdp->Control_1 |= TXD_TCP_LSO_MSS(mss);
+ }
+@@ -3543,10 +3543,10 @@
+ }
+
+ frg_len = skb->len - skb->data_len;
+- if (skb_shinfo(skb)->ufo_size) {
++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4) {
+ int ufo_size;
+
+- ufo_size = skb_shinfo(skb)->ufo_size;
++ ufo_size = skb_shinfo(skb)->gso_size;
+ ufo_size &= ~7;
+ txdp->Control_1 |= TXD_UFO_EN;
+ txdp->Control_1 |= TXD_UFO_MSS(ufo_size);
+@@ -3572,7 +3572,7 @@
+ txdp->Host_Control = (unsigned long) skb;
+ txdp->Control_1 |= TXD_BUFFER0_SIZE(frg_len);
+
+- if (skb_shinfo(skb)->ufo_size)
++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+ txdp->Control_1 |= TXD_UFO_EN;
+
+ frg_cnt = skb_shinfo(skb)->nr_frags;
+@@ -3587,12 +3587,12 @@
+ (sp->pdev, frag->page, frag->page_offset,
+ frag->size, PCI_DMA_TODEVICE);
+ txdp->Control_1 = TXD_BUFFER0_SIZE(frag->size);
+- if (skb_shinfo(skb)->ufo_size)
++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+ txdp->Control_1 |= TXD_UFO_EN;
+ }
+ txdp->Control_1 |= TXD_GATHER_CODE_LAST;
+
+- if (skb_shinfo(skb)->ufo_size)
++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+ frg_cnt++; /* as Txd0 was used for inband header */
+
+ tx_fifo = mac_control->tx_FIFO_start[queue];
+@@ -3606,7 +3606,7 @@
+ if (mss)
+ val64 |= TX_FIFO_SPECIAL_FUNC;
+ #endif
+- if (skb_shinfo(skb)->ufo_size)
++ if (skb_shinfo(skb)->gso_type == SKB_GSO_UDPV4)
+ val64 |= TX_FIFO_SPECIAL_FUNC;
+ writeq(val64, &tx_fifo->List_Control);
+
+Index: tmp-xxx/drivers/net/sky2.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/sky2.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/sky2.c 2006-11-27 10:52:42.000000000 +0000
+@@ -1141,7 +1141,7 @@
+ count = sizeof(dma_addr_t) / sizeof(u32);
+ count += skb_shinfo(skb)->nr_frags * count;
+
+- if (skb_shinfo(skb)->tso_size)
++ if (skb_shinfo(skb)->gso_size)
+ ++count;
+
+ if (skb->ip_summed == CHECKSUM_HW)
+@@ -1213,7 +1213,7 @@
+ }
+
+ /* Check for TCP Segmentation Offload */
+- mss = skb_shinfo(skb)->tso_size;
++ mss = skb_shinfo(skb)->gso_size;
+ if (mss != 0) {
+ /* just drop the packet if non-linear expansion fails */
+ if (skb_header_cloned(skb) &&
+Index: tmp-xxx/drivers/net/tg3.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/tg3.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/tg3.c 2006-11-27 10:52:42.000000000 +0000
+@@ -3664,7 +3664,7 @@
+ #if TG3_TSO_SUPPORT != 0
+ mss = 0;
+ if (skb->len > (tp->dev->mtu + ETH_HLEN) &&
+- (mss = skb_shinfo(skb)->tso_size) != 0) {
++ (mss = skb_shinfo(skb)->gso_size) != 0) {
+ int tcp_opt_len, ip_tcp_len;
+
+ if (skb_header_cloned(skb) &&
+Index: tmp-xxx/drivers/net/tulip/winbond-840.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/tulip/winbond-840.c 2006-11-15
10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/tulip/winbond-840.c 2006-11-27 10:52:42.000000000
+0000
+@@ -1605,11 +1605,11 @@
+ * - get_stats:
+ * spin_lock_irq(np->lock), doesn't touch hw if not present
+ * - hard_start_xmit:
+- * netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
++ * synchronize_irq + netif_tx_disable;
+ * - tx_timeout:
+- * netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
++ * netif_device_detach + netif_tx_disable;
+ * - set_multicast_list
+- * netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
++ * netif_device_detach + netif_tx_disable;
+ * - interrupt handler
+ * doesn't touch hw if not present, synchronize_irq waits for
+ * running instances of the interrupt handler.
+@@ -1635,11 +1635,10 @@
+ netif_device_detach(dev);
+ update_csr6(dev, 0);
+ iowrite32(0, ioaddr + IntrEnable);
+- netif_stop_queue(dev);
+ spin_unlock_irq(&np->lock);
+
+- spin_unlock_wait(&dev->xmit_lock);
+ synchronize_irq(dev->irq);
++ netif_tx_disable(dev);
+
+ np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) &
0xffff;
+
+Index: tmp-xxx/drivers/net/typhoon.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/typhoon.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/typhoon.c 2006-11-27 10:52:42.000000000 +0000
+@@ -340,7 +340,7 @@
+ #endif
+
+ #if defined(NETIF_F_TSO)
+-#define skb_tso_size(x) (skb_shinfo(x)->tso_size)
++#define skb_tso_size(x) (skb_shinfo(x)->gso_size)
+ #define TSO_NUM_DESCRIPTORS 2
+ #define TSO_OFFLOAD_ON TYPHOON_OFFLOAD_TCP_SEGMENT
+ #else
+Index: tmp-xxx/drivers/net/via-velocity.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/via-velocity.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/net/via-velocity.c 2006-11-27 10:52:42.000000000 +0000
+@@ -1905,6 +1905,13 @@
+
+ int pktlen = skb->len;
+
++#ifdef VELOCITY_ZERO_COPY_SUPPORT
++ if (skb_shinfo(skb)->nr_frags > 6 && __skb_linearize(skb)) {
++ kfree_skb(skb);
++ return 0;
++ }
++#endif
++
+ spin_lock_irqsave(&vptr->lock, flags);
+
+ index = vptr->td_curr[qnum];
+@@ -1920,8 +1927,6 @@
+ */
+ if (pktlen < ETH_ZLEN) {
+ /* Cannot occur until ZC support */
+- if(skb_linearize(skb, GFP_ATOMIC))
+- return 0;
+ pktlen = ETH_ZLEN;
+ memcpy(tdinfo->buf, skb->data, skb->len);
+ memset(tdinfo->buf + skb->len, 0, ETH_ZLEN - skb->len);
+@@ -1939,7 +1944,6 @@
+ int nfrags = skb_shinfo(skb)->nr_frags;
+ tdinfo->skb = skb;
+ if (nfrags > 6) {
+- skb_linearize(skb, GFP_ATOMIC);
+ memcpy(tdinfo->buf, skb->data, skb->len);
+ tdinfo->skb_dma[0] = tdinfo->buf_dma;
+ td_ptr->tdesc0.pktsize =
+Index: tmp-xxx/drivers/net/wireless/orinoco.c
+===================================================================
+--- tmp-xxx.orig/drivers/net/wireless/orinoco.c 2006-11-15
10:38:39.000000000 +0000
++++ tmp-xxx/drivers/net/wireless/orinoco.c 2006-11-27 10:52:42.000000000
+0000
+@@ -1835,7 +1835,9 @@
+ /* Set promiscuity / multicast*/
+ priv->promiscuous = 0;
+ priv->mc_count = 0;
+- __orinoco_set_multicast_list(dev); /* FIXME: what about the xmit_lock */
++
++ /* FIXME: what about netif_tx_lock */
++ __orinoco_set_multicast_list(dev);
+
+ return 0;
+ }
+Index: tmp-xxx/drivers/s390/net/qeth_eddp.c
+===================================================================
+--- tmp-xxx.orig/drivers/s390/net/qeth_eddp.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/s390/net/qeth_eddp.c 2006-11-27 10:52:42.000000000
+0000
+@@ -421,7 +421,7 @@
+ }
+ tcph = eddp->skb->h.th;
+ while (eddp->skb_offset < eddp->skb->len) {
+- data_len = min((int)skb_shinfo(eddp->skb)->tso_size,
++ data_len = min((int)skb_shinfo(eddp->skb)->gso_size,
+ (int)(eddp->skb->len - eddp->skb_offset));
+ /* prepare qdio hdr */
+ if (eddp->qh.hdr.l2.id == QETH_HEADER_TYPE_LAYER2){
+@@ -516,20 +516,20 @@
+
+ QETH_DBF_TEXT(trace, 5, "eddpcanp");
+ /* can we put multiple skbs in one page? */
+- skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->tso_size + hdr_len);
++ skbs_per_page = PAGE_SIZE / (skb_shinfo(skb)->gso_size + hdr_len);
+ if (skbs_per_page > 1){
+- ctx->num_pages = (skb_shinfo(skb)->tso_segs + 1) /
++ ctx->num_pages = (skb_shinfo(skb)->gso_segs + 1) /
+ skbs_per_page + 1;
+ ctx->elements_per_skb = 1;
+ } else {
+ /* no -> how many elements per skb? */
+- ctx->elements_per_skb = (skb_shinfo(skb)->tso_size + hdr_len +
++ ctx->elements_per_skb = (skb_shinfo(skb)->gso_size + hdr_len +
+ PAGE_SIZE) >> PAGE_SHIFT;
+ ctx->num_pages = ctx->elements_per_skb *
+- (skb_shinfo(skb)->tso_segs + 1);
++ (skb_shinfo(skb)->gso_segs + 1);
+ }
+ ctx->num_elements = ctx->elements_per_skb *
+- (skb_shinfo(skb)->tso_segs + 1);
++ (skb_shinfo(skb)->gso_segs + 1);
+ }
+
+ static inline struct qeth_eddp_context *
+Index: tmp-xxx/drivers/s390/net/qeth_main.c
+===================================================================
+--- tmp-xxx.orig/drivers/s390/net/qeth_main.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/s390/net/qeth_main.c 2006-11-27 10:52:42.000000000
+0000
+@@ -4454,7 +4454,7 @@
+ queue = card->qdio.out_qs
+ [qeth_get_priority_queue(card, skb, ipv, cast_type)];
+
+- if (skb_shinfo(skb)->tso_size)
++ if (skb_shinfo(skb)->gso_size)
+ large_send = card->options.large_send;
+
+ /*are we able to do TSO ? If so ,prepare and send it from here */
+@@ -4501,7 +4501,7 @@
+ card->stats.tx_packets++;
+ card->stats.tx_bytes += skb->len;
+ #ifdef CONFIG_QETH_PERF_STATS
+- if (skb_shinfo(skb)->tso_size &&
++ if (skb_shinfo(skb)->gso_size &&
+ !(large_send == QETH_LARGE_SEND_NO)) {
+ card->perf_stats.large_send_bytes += skb->len;
+ card->perf_stats.large_send_cnt++;
+Index: tmp-xxx/drivers/s390/net/qeth_tso.h
+===================================================================
+--- tmp-xxx.orig/drivers/s390/net/qeth_tso.h 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/drivers/s390/net/qeth_tso.h 2006-11-27 10:52:42.000000000
+0000
+@@ -51,7 +51,7 @@
+ hdr->ext.hdr_version = 1;
+ hdr->ext.hdr_len = 28;
+ /*insert non-fix values */
+- hdr->ext.mss = skb_shinfo(skb)->tso_size;
++ hdr->ext.mss = skb_shinfo(skb)->gso_size;
+ hdr->ext.dg_hdr_len = (__u16)(iph->ihl*4 + tcph->doff*4);
+ hdr->ext.payload_len = (__u16)(skb->len - hdr->ext.dg_hdr_len -
+ sizeof(struct qeth_hdr_tso));
+Index: tmp-xxx/include/linux/ethtool.h
+===================================================================
+--- tmp-xxx.orig/include/linux/ethtool.h 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/include/linux/ethtool.h 2006-11-27 10:52:42.000000000 +0000
+@@ -408,6 +408,8 @@
+ #define ETHTOOL_GPERMADDR 0x00000020 /* Get permanent hardware address */
+ #define ETHTOOL_GUFO 0x00000021 /* Get UFO enable (ethtool_value) */
+ #define ETHTOOL_SUFO 0x00000022 /* Set UFO enable (ethtool_value) */
++#define ETHTOOL_GGSO 0x00000023 /* Get GSO enable (ethtool_value) */
++#define ETHTOOL_SGSO 0x00000024 /* Set GSO enable (ethtool_value) */
+
+ /* compatibility with older code */
+ #define SPARC_ETH_GSET ETHTOOL_GSET
+Index: tmp-xxx/include/linux/netdevice.h
+===================================================================
+--- tmp-xxx.orig/include/linux/netdevice.h 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/include/linux/netdevice.h 2006-11-27 10:52:42.000000000 +0000
+@@ -230,7 +230,8 @@
+ __LINK_STATE_SCHED,
+ __LINK_STATE_NOCARRIER,
+ __LINK_STATE_RX_SCHED,
+- __LINK_STATE_LINKWATCH_PENDING
++ __LINK_STATE_LINKWATCH_PENDING,
++ __LINK_STATE_QDISC_RUNNING,
+ };
+
+
+@@ -306,9 +307,17 @@
+ #define NETIF_F_HW_VLAN_RX 256 /* Receive VLAN hw acceleration */
+ #define NETIF_F_HW_VLAN_FILTER 512 /* Receive filtering on VLAN */
+ #define NETIF_F_VLAN_CHALLENGED 1024 /* Device cannot handle VLAN
packets */
+-#define NETIF_F_TSO 2048 /* Can offload TCP/IP segmentation */
++#define NETIF_F_GSO 2048 /* Enable software GSO. */
+ #define NETIF_F_LLTX 4096 /* LockLess TX */
+-#define NETIF_F_UFO 8192 /* Can offload UDP Large Send*/
++
++ /* Segmentation offload features */
++#define NETIF_F_GSO_SHIFT 16
++#define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT)
++#define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT)
++#define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT)
++
++#define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)
++#define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM)
+
+ struct net_device *next_sched;
+
+@@ -394,6 +403,9 @@
+ struct list_head qdisc_list;
+ unsigned long tx_queue_len; /* Max frames per queue allowed
*/
+
++ /* Partially transmitted GSO packet. */
++ struct sk_buff *gso_skb;
++
+ /* ingress path synchronizer */
+ spinlock_t ingress_lock;
+ struct Qdisc *qdisc_ingress;
+@@ -402,7 +414,7 @@
+ * One part is mostly used on xmit path (device)
+ */
+ /* hard_start_xmit synchronizer */
+- spinlock_t xmit_lock ____cacheline_aligned_in_smp;
++ spinlock_t _xmit_lock ____cacheline_aligned_in_smp;
+ /* cpu id of processor entered to hard_start_xmit or -1,
+ if nobody entered there.
+ */
+@@ -527,6 +539,8 @@
+ struct net_device *,
+ struct packet_type *,
+ struct net_device *);
++ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
++ int features);
+ void *af_packet_priv;
+ struct list_head list;
+ };
+@@ -693,7 +707,8 @@
+ extern int dev_set_mtu(struct net_device *, int);
+ extern int dev_set_mac_address(struct net_device *,
+ struct sockaddr *);
+-extern void dev_queue_xmit_nit(struct sk_buff *skb, struct
net_device *dev);
++extern int dev_hard_start_xmit(struct sk_buff *skb,
++ struct net_device *dev);
+
+ extern void dev_init(void);
+
+@@ -900,11 +915,43 @@
+ clear_bit(__LINK_STATE_RX_SCHED, &dev->state);
+ }
+
++static inline void netif_tx_lock(struct net_device *dev)
++{
++ spin_lock(&dev->_xmit_lock);
++ dev->xmit_lock_owner = smp_processor_id();
++}
++
++static inline void netif_tx_lock_bh(struct net_device *dev)
++{
++ spin_lock_bh(&dev->_xmit_lock);
++ dev->xmit_lock_owner = smp_processor_id();
++}
++
++static inline int netif_tx_trylock(struct net_device *dev)
++{
++ int err = spin_trylock(&dev->_xmit_lock);
++ if (!err)
++ dev->xmit_lock_owner = smp_processor_id();
++ return err;
++}
++
++static inline void netif_tx_unlock(struct net_device *dev)
++{
++ dev->xmit_lock_owner = -1;
++ spin_unlock(&dev->_xmit_lock);
++}
++
++static inline void netif_tx_unlock_bh(struct net_device *dev)
++{
++ dev->xmit_lock_owner = -1;
++ spin_unlock_bh(&dev->_xmit_lock);
++}
++
+ static inline void netif_tx_disable(struct net_device *dev)
+ {
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ netif_stop_queue(dev);
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ }
+
+ /* These functions live elsewhere (drivers/net/net_init.c, but related) */
+@@ -932,6 +979,7 @@
+ extern int weight_p;
+ extern int netdev_set_master(struct net_device *dev, struct
net_device *master);
+ extern int skb_checksum_help(struct sk_buff *skb, int inward);
++extern struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features);
+ #ifdef CONFIG_BUG
+ extern void netdev_rx_csum_fault(struct net_device *dev);
+ #else
+@@ -951,6 +999,18 @@
+
+ extern void linkwatch_run_queue(void);
+
++static inline int skb_gso_ok(struct sk_buff *skb, int features)
++{
++ int feature = skb_shinfo(skb)->gso_size ?
++ skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
++ return (features & feature) == feature;
++}
++
++static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
++{
++ return !skb_gso_ok(skb, dev->features);
++}
++
+ #endif /* __KERNEL__ */
+
+ #endif /* _LINUX_DEV_H */
+Index: tmp-xxx/include/linux/skbuff.h
+===================================================================
+--- tmp-xxx.orig/include/linux/skbuff.h 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/include/linux/skbuff.h 2006-11-27 10:52:42.000000000 +0000
+@@ -134,9 +134,10 @@
+ struct skb_shared_info {
+ atomic_t dataref;
+ unsigned short nr_frags;
+- unsigned short tso_size;
+- unsigned short tso_segs;
+- unsigned short ufo_size;
++ unsigned short gso_size;
++ /* Warning: this field is not always filled in (UFO)! */
++ unsigned short gso_segs;
++ unsigned short gso_type;
+ unsigned int ip6_frag_id;
+ struct sk_buff *frag_list;
+ skb_frag_t frags[MAX_SKB_FRAGS];
+@@ -168,6 +169,14 @@
+ SKB_FCLONE_CLONE,
+ };
+
++enum {
++ SKB_GSO_TCPV4 = 1 << 0,
++ SKB_GSO_UDPV4 = 1 << 1,
++
++ /* This indicates the skb is from an untrusted source. */
++ SKB_GSO_DODGY = 1 << 2,
++};
++
+ /**
+ * struct sk_buff - socket buffer
+ * @next: Next buffer in list
+@@ -1148,18 +1157,34 @@
+ return 0;
+ }
+
++static inline int __skb_linearize(struct sk_buff *skb)
++{
++ return __pskb_pull_tail(skb, skb->data_len) ? 0 : -ENOMEM;
++}
++
+ /**
+ * skb_linearize - convert paged skb to linear one
+ * @skb: buffer to linarize
+- * @gfp: allocation mode
+ *
+ * If there is no free memory -ENOMEM is returned, otherwise zero
+ * is returned and the old skb data released.
+ */
+-extern int __skb_linearize(struct sk_buff *skb, gfp_t gfp);
+-static inline int skb_linearize(struct sk_buff *skb, gfp_t gfp)
++static inline int skb_linearize(struct sk_buff *skb)
++{
++ return skb_is_nonlinear(skb) ? __skb_linearize(skb) : 0;
++}
++
++/**
++ * skb_linearize_cow - make sure skb is linear and writable
++ * @skb: buffer to process
++ *
++ * If there is no free memory -ENOMEM is returned, otherwise zero
++ * is returned and the old skb data released.
++ */
++static inline int skb_linearize_cow(struct sk_buff *skb)
+ {
+- return __skb_linearize(skb, gfp);
++ return skb_is_nonlinear(skb) || skb_cloned(skb) ?
++ __skb_linearize(skb) : 0;
+ }
+
+ /**
+@@ -1254,6 +1279,7 @@
+ struct sk_buff *skb1, const u32 len);
+
+ extern void skb_release_data(struct sk_buff *skb);
++extern struct sk_buff *skb_segment(struct sk_buff *skb, int features);
+
+ static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
+ int len, void *buffer)
+Index: tmp-xxx/include/net/pkt_sched.h
+===================================================================
+--- tmp-xxx.orig/include/net/pkt_sched.h 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/include/net/pkt_sched.h 2006-11-27 10:52:42.000000000 +0000
+@@ -218,12 +218,13 @@
+ struct rtattr *tab);
+ extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
+
+-extern int qdisc_restart(struct net_device *dev);
++extern void __qdisc_run(struct net_device *dev);
+
+ static inline void qdisc_run(struct net_device *dev)
+ {
+- while (!netif_queue_stopped(dev) && qdisc_restart(dev) < 0)
+- /* NOTHING */;
++ if (!netif_queue_stopped(dev) &&
++ !test_and_set_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
++ __qdisc_run(dev);
+ }
+
+ extern int tc_classify(struct sk_buff *skb, struct tcf_proto *tp,
+Index: tmp-xxx/include/net/protocol.h
+===================================================================
+--- tmp-xxx.orig/include/net/protocol.h 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/include/net/protocol.h 2006-11-27 10:52:42.000000000 +0000
+@@ -37,6 +37,8 @@
+ struct net_protocol {
+ int (*handler)(struct sk_buff *skb);
+ void (*err_handler)(struct sk_buff *skb, u32 info);
++ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
++ int features);
+ int no_policy;
+ };
+
+Index: tmp-xxx/include/net/sock.h
+===================================================================
+--- tmp-xxx.orig/include/net/sock.h 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/include/net/sock.h 2006-11-27 10:52:42.000000000 +0000
+@@ -1064,9 +1064,13 @@
+ {
+ __sk_dst_set(sk, dst);
+ sk->sk_route_caps = dst->dev->features;
++ if (sk->sk_route_caps & NETIF_F_GSO)
++ sk->sk_route_caps |= NETIF_F_TSO;
+ if (sk->sk_route_caps & NETIF_F_TSO) {
+ if (sock_flag(sk, SOCK_NO_LARGESEND) || dst->header_len)
+ sk->sk_route_caps &= ~NETIF_F_TSO;
++ else
++ sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
+ }
+ }
+
+Index: tmp-xxx/include/net/tcp.h
+===================================================================
+--- tmp-xxx.orig/include/net/tcp.h 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/include/net/tcp.h 2006-11-27 10:52:42.000000000 +0000
+@@ -552,13 +552,13 @@
+ */
+ static inline int tcp_skb_pcount(const struct sk_buff *skb)
+ {
+- return skb_shinfo(skb)->tso_segs;
++ return skb_shinfo(skb)->gso_segs;
+ }
+
+ /* This is valid iff tcp_skb_pcount() > 1. */
+ static inline int tcp_skb_mss(const struct sk_buff *skb)
+ {
+- return skb_shinfo(skb)->tso_size;
++ return skb_shinfo(skb)->gso_size;
+ }
+
+ static inline void tcp_dec_pcount_approx(__u32 *count,
+@@ -1063,6 +1063,8 @@
+
+ extern int tcp_v4_destroy_sock(struct sock *sk);
+
++extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
++
+ #ifdef CONFIG_PROC_FS
+ extern int tcp4_proc_init(void);
+ extern void tcp4_proc_exit(void);
+Index: tmp-xxx/net/atm/clip.c
+===================================================================
+--- tmp-xxx.orig/net/atm/clip.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/atm/clip.c 2006-11-27 10:52:42.000000000 +0000
+@@ -101,7 +101,7 @@
+ printk(KERN_CRIT "!clip_vcc->entry (clip_vcc %p)\n",clip_vcc);
+ return;
+ }
+- spin_lock_bh(&entry->neigh->dev->xmit_lock); /* block
clip_start_xmit() */
++ netif_tx_lock_bh(entry->neigh->dev); /* block clip_start_xmit() */
+ entry->neigh->used = jiffies;
+ for (walk = &entry->vccs; *walk; walk = &(*walk)->next)
+ if (*walk == clip_vcc) {
+@@ -125,7 +125,7 @@
+ printk(KERN_CRIT "ATMARP: unlink_clip_vcc failed (entry %p, vcc "
+ "0x%p)\n",entry,clip_vcc);
+ out:
+- spin_unlock_bh(&entry->neigh->dev->xmit_lock);
++ netif_tx_unlock_bh(entry->neigh->dev);
+ }
+
+ /* The neighbour entry n->lock is held. */
+Index: tmp-xxx/net/bridge/br_device.c
+===================================================================
+--- tmp-xxx.orig/net/bridge/br_device.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/net/bridge/br_device.c 2006-11-27 10:52:42.000000000 +0000
+@@ -146,9 +146,9 @@
+ struct net_bridge *br = netdev_priv(dev);
+
+ if (data)
+- br->feature_mask |= NETIF_F_IP_CSUM;
++ br->feature_mask |= NETIF_F_NO_CSUM;
+ else
+- br->feature_mask &= ~NETIF_F_IP_CSUM;
++ br->feature_mask &= ~NETIF_F_ALL_CSUM;
+
+ br_features_recompute(br);
+ return 0;
+@@ -185,6 +185,6 @@
+ dev->set_mac_address = br_set_mac_address;
+ dev->priv_flags = IFF_EBRIDGE;
+
+- dev->features = NETIF_F_SG | NETIF_F_FRAGLIST
+- | NETIF_F_HIGHDMA | NETIF_F_TSO | NETIF_F_IP_CSUM;
++ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA |
++ NETIF_F_TSO | NETIF_F_NO_CSUM | NETIF_F_GSO_ROBUST;
+ }
+Index: tmp-xxx/net/bridge/br_forward.c
+===================================================================
+--- tmp-xxx.orig/net/bridge/br_forward.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/net/bridge/br_forward.c 2006-11-27 10:52:42.000000000 +0000
+@@ -32,7 +32,7 @@
+ int br_dev_queue_push_xmit(struct sk_buff *skb)
+ {
+ /* drop mtu oversized packets except tso */
+- if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size)
++ if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
+ kfree_skb(skb);
+ else {
+ #ifdef CONFIG_BRIDGE_NETFILTER
+Index: tmp-xxx/net/bridge/br_if.c
+===================================================================
+--- tmp-xxx.orig/net/bridge/br_if.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/bridge/br_if.c 2006-11-27 10:52:42.000000000 +0000
+@@ -385,17 +385,28 @@
+ struct net_bridge_port *p;
+ unsigned long features, checksum;
+
+- features = br->feature_mask &~ NETIF_F_IP_CSUM;
+- checksum = br->feature_mask & NETIF_F_IP_CSUM;
++ checksum = br->feature_mask & NETIF_F_ALL_CSUM ? NETIF_F_NO_CSUM : 0;
++ features = br->feature_mask & ~NETIF_F_ALL_CSUM;
+
+ list_for_each_entry(p, &br->port_list, list) {
+- if (!(p->dev->features
+- & (NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM)))
++ unsigned long feature = p->dev->features;
++
++ if (checksum & NETIF_F_NO_CSUM && !(feature & NETIF_F_NO_CSUM))
++ checksum ^= NETIF_F_NO_CSUM | NETIF_F_HW_CSUM;
++ if (checksum & NETIF_F_HW_CSUM && !(feature & NETIF_F_HW_CSUM))
++ checksum ^= NETIF_F_HW_CSUM | NETIF_F_IP_CSUM;
++ if (!(feature & NETIF_F_IP_CSUM))
+ checksum = 0;
+- features &= p->dev->features;
++
++ if (feature & NETIF_F_GSO)
++ feature |= NETIF_F_TSO;
++ feature |= NETIF_F_GSO;
++
++ features &= feature;
+ }
+
+- br->dev->features = features | checksum | NETIF_F_LLTX;
++ br->dev->features = features | checksum | NETIF_F_LLTX |
++ NETIF_F_GSO_ROBUST;
+ }
+
+ /* called with RTNL */
+Index: tmp-xxx/net/bridge/br_netfilter.c
+===================================================================
+--- tmp-xxx.orig/net/bridge/br_netfilter.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/net/bridge/br_netfilter.c 2006-11-27 10:52:42.000000000 +0000
+@@ -743,7 +743,7 @@
+ {
+ if (skb->protocol == htons(ETH_P_IP) &&
+ skb->len > skb->dev->mtu &&
+- !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
++ !skb_shinfo(skb)->gso_size)
+ return ip_fragment(skb, br_dev_queue_push_xmit);
+ else
+ return br_dev_queue_push_xmit(skb);
+Index: tmp-xxx/net/core/dev.c
+===================================================================
+--- tmp-xxx.orig/net/core/dev.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/core/dev.c 2006-11-27 10:57:31.000000000 +0000
+@@ -115,6 +115,7 @@
+ #include <net/iw_handler.h>
+ #endif /* CONFIG_NET_RADIO */
+ #include <asm/current.h>
++#include <linux/err.h>
+
+ /*
+ * The list of packet types we will receive (as opposed to discard)
+@@ -1032,7 +1033,7 @@
+ * taps currently in use.
+ */
+
+-void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
++static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
+ {
+ struct packet_type *ptype;
+
+@@ -1106,6 +1107,45 @@
+ return ret;
+ }
+
++/**
++ * skb_gso_segment - Perform segmentation on skb.
++ * @skb: buffer to segment
++ * @features: features for the output path (see dev->features)
++ *
++ * This function segments the given skb and returns a list of segments.
++ *
++ * It may return NULL if the skb requires no segmentation. This is
++ * only possible when GSO is used for verifying header integrity.
++ */
++struct sk_buff *skb_gso_segment(struct sk_buff *skb, int features)
++{
++ struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
++ struct packet_type *ptype;
++ int type = skb->protocol;
++
++ BUG_ON(skb_shinfo(skb)->frag_list);
++ BUG_ON(skb->ip_summed != CHECKSUM_HW);
++
++ skb->mac.raw = skb->data;
++ skb->mac_len = skb->nh.raw - skb->data;
++ __skb_pull(skb, skb->mac_len);
++
++ rcu_read_lock();
++ list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
++ if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
++ segs = ptype->gso_segment(skb, features);
++ break;
++ }
++ }
++ rcu_read_unlock();
++
++ __skb_push(skb, skb->data - skb->mac.raw);
++
++ return segs;
++}
++
++EXPORT_SYMBOL(skb_gso_segment);
++
+ /* Take action when hardware reception checksum errors are detected. */
+ #ifdef CONFIG_BUG
+ void netdev_rx_csum_fault(struct net_device *dev)
+@@ -1142,76 +1182,107 @@
+ #define illegal_highdma(dev, skb) (0)
+ #endif
+
+-/* Keep head the same: replace data */
+-int __skb_linearize(struct sk_buff *skb, gfp_t gfp_mask)
++struct dev_gso_cb {
++ void (*destructor)(struct sk_buff *skb);
++};
++
++#define DEV_GSO_CB(skb) ((struct dev_gso_cb *)(skb)->cb)
++
++static void dev_gso_skb_destructor(struct sk_buff *skb)
+ {
+- unsigned int size;
+- u8 *data;
+- long offset;
+- struct skb_shared_info *ninfo;
+- int headerlen = skb->data - skb->head;
+- int expand = (skb->tail + skb->data_len) - skb->end;
+-
+- if (skb_shared(skb))
+- BUG();
+-
+- if (expand <= 0)
+- expand = 0;
+-
+- size = skb->end - skb->head + expand;
+- size = SKB_DATA_ALIGN(size);
+- data = kmalloc(size + sizeof(struct skb_shared_info), gfp_mask);
+- if (!data)
+- return -ENOMEM;
+-
+- /* Copy entire thing */
+- if (skb_copy_bits(skb, -headerlen, data, headerlen + skb->len))
+- BUG();
+-
+- /* Set up shinfo */
+- ninfo = (struct skb_shared_info*)(data + size);
+- atomic_set(&ninfo->dataref, 1);
+- ninfo->tso_size = skb_shinfo(skb)->tso_size;
+- ninfo->tso_segs = skb_shinfo(skb)->tso_segs;
+- ninfo->ufo_size = skb_shinfo(skb)->ufo_size;
+- ninfo->nr_frags = 0;
+- ninfo->frag_list = NULL;
+-
+- /* Offset between the two in bytes */
+- offset = data - skb->head;
+-
+- /* Free old data. */
+- skb_release_data(skb);
+-
+- skb->head = data;
+- skb->end = data + size;
+-
+- /* Set up new pointers */
+- skb->h.raw += offset;
+- skb->nh.raw += offset;
+- skb->mac.raw += offset;
+- skb->tail += offset;
+- skb->data += offset;
++ struct dev_gso_cb *cb;
+
+- /* We are no longer a clone, even if we were. */
+- skb->cloned = 0;
++ do {
++ struct sk_buff *nskb = skb->next;
+
+- skb->tail += skb->data_len;
+- skb->data_len = 0;
++ skb->next = nskb->next;
++ nskb->next = NULL;
++ kfree_skb(nskb);
++ } while (skb->next);
++
++ cb = DEV_GSO_CB(skb);
++ if (cb->destructor)
++ cb->destructor(skb);
++}
++
++/**
++ * dev_gso_segment - Perform emulated hardware segmentation on skb.
++ * @skb: buffer to segment
++ *
++ * This function segments the given skb and stores the list of segments
++ * in skb->next.
++ */
++static int dev_gso_segment(struct sk_buff *skb)
++{
++ struct net_device *dev = skb->dev;
++ struct sk_buff *segs;
++ int features = dev->features & ~(illegal_highdma(dev, skb) ?
++ NETIF_F_SG : 0);
++
++ segs = skb_gso_segment(skb, features);
++
++ /* Verifying header integrity only. */
++ if (!segs)
++ return 0;
++
++ if (unlikely(IS_ERR(segs)))
++ return PTR_ERR(segs);
++
++ skb->next = segs;
++ DEV_GSO_CB(skb)->destructor = skb->destructor;
++ skb->destructor = dev_gso_skb_destructor;
++ return 0;
++}
++
++int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++ if (likely(!skb->next)) {
++ if (netdev_nit)
++ dev_queue_xmit_nit(skb, dev);
++
++ if (netif_needs_gso(dev, skb)) {
++ if (unlikely(dev_gso_segment(skb)))
++ goto out_kfree_skb;
++ if (skb->next)
++ goto gso;
++ }
++
++ return dev->hard_start_xmit(skb, dev);
++ }
++
++gso:
++ do {
++ struct sk_buff *nskb = skb->next;
++ int rc;
++
++ skb->next = nskb->next;
++ nskb->next = NULL;
++ rc = dev->hard_start_xmit(nskb, dev);
++ if (unlikely(rc)) {
++ nskb->next = skb->next;
++ skb->next = nskb;
++ return rc;
++ }
++ if (unlikely(netif_queue_stopped(dev) && skb->next))
++ return NETDEV_TX_BUSY;
++ } while (skb->next);
++
++ skb->destructor = DEV_GSO_CB(skb)->destructor;
++
++out_kfree_skb:
++ kfree_skb(skb);
+ return 0;
+ }
+
+ #define HARD_TX_LOCK(dev, cpu) { \
+ if ((dev->features & NETIF_F_LLTX) == 0) { \
+- spin_lock(&dev->xmit_lock); \
+- dev->xmit_lock_owner = cpu; \
++ netif_tx_lock(dev); \
+ } \
+ }
+
+ #define HARD_TX_UNLOCK(dev) { \
+ if ((dev->features & NETIF_F_LLTX) == 0) { \
+- dev->xmit_lock_owner = -1; \
+- spin_unlock(&dev->xmit_lock); \
++ netif_tx_unlock(dev); \
+ } \
+ }
+
+@@ -1247,9 +1318,13 @@
+ struct Qdisc *q;
+ int rc = -ENOMEM;
+
++ /* GSO will handle the following emulations directly. */
++ if (netif_needs_gso(dev, skb))
++ goto gso;
++
+ if (skb_shinfo(skb)->frag_list &&
+ !(dev->features & NETIF_F_FRAGLIST) &&
+- __skb_linearize(skb, GFP_ATOMIC))
++ __skb_linearize(skb))
+ goto out_kfree_skb;
+
+ /* Fragmented skb is linearized if device does not support SG,
+@@ -1258,25 +1333,26 @@
+ */
+ if (skb_shinfo(skb)->nr_frags &&
+ (!(dev->features & NETIF_F_SG) || illegal_highdma(dev, skb)) &&
+- __skb_linearize(skb, GFP_ATOMIC))
++ __skb_linearize(skb))
+ goto out_kfree_skb;
+
+ /* If packet is not checksummed and device does not support
+ * checksumming for this protocol, complete checksumming here.
+ */
+ if (skb->ip_summed == CHECKSUM_HW &&
+- (!(dev->features & (NETIF_F_HW_CSUM | NETIF_F_NO_CSUM)) &&
++ (!(dev->features & NETIF_F_GEN_CSUM) &&
+ (!(dev->features & NETIF_F_IP_CSUM) ||
+ skb->protocol != htons(ETH_P_IP))))
+ if (skb_checksum_help(skb, 0))
+ goto out_kfree_skb;
+
++gso:
+ spin_lock_prefetch(&dev->queue_lock);
+
+ /* Disable soft irqs for various locks below. Also
+ * stops preemption for RCU.
+ */
+- local_bh_disable();
++ rcu_read_lock_bh();
+
+ /* Updates of qdisc are serialized by queue_lock.
+ * The struct Qdisc which is pointed to by qdisc is now a
+@@ -1310,8 +1386,8 @@
+ /* The device has no queue. Common case for software devices:
+ loopback, all the sorts of tunnels...
+
+- Really, it is unlikely that xmit_lock protection is necessary here.
+- (f.e. loopback and IP tunnels are clean ignoring statistics
++ Really, it is unlikely that netif_tx_lock protection is necessary
++ here. (f.e. loopback and IP tunnels are clean ignoring statistics
+ counters.)
+ However, it is possible, that they rely on protection
+ made by us here.
+@@ -1327,11 +1403,8 @@
+ HARD_TX_LOCK(dev, cpu);
+
+ if (!netif_queue_stopped(dev)) {
+- if (netdev_nit)
+- dev_queue_xmit_nit(skb, dev);
+-
+ rc = 0;
+- if (!dev->hard_start_xmit(skb, dev)) {
++ if (!dev_hard_start_xmit(skb, dev)) {
+ HARD_TX_UNLOCK(dev);
+ goto out;
+ }
+@@ -1350,13 +1423,13 @@
+ }
+
+ rc = -ENETDOWN;
+- local_bh_enable();
++ rcu_read_unlock_bh();
+
+ out_kfree_skb:
+ kfree_skb(skb);
+ return rc;
+ out:
+- local_bh_enable();
++ rcu_read_unlock_bh();
+ return rc;
+ }
+
+@@ -2671,7 +2744,7 @@
+ BUG_ON(dev->reg_state != NETREG_UNINITIALIZED);
+
+ spin_lock_init(&dev->queue_lock);
+- spin_lock_init(&dev->xmit_lock);
++ spin_lock_init(&dev->_xmit_lock);
+ dev->xmit_lock_owner = -1;
+ #ifdef CONFIG_NET_CLS_ACT
+ spin_lock_init(&dev->ingress_lock);
+@@ -2715,9 +2788,7 @@
+
+ /* Fix illegal SG+CSUM combinations. */
+ if ((dev->features & NETIF_F_SG) &&
+- !(dev->features & (NETIF_F_IP_CSUM |
+- NETIF_F_NO_CSUM |
+- NETIF_F_HW_CSUM))) {
++ !(dev->features & NETIF_F_ALL_CSUM)) {
+ printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
+ dev->name);
+ dev->features &= ~NETIF_F_SG;
+@@ -3269,7 +3340,6 @@
+ EXPORT_SYMBOL(__dev_get_by_index);
+ EXPORT_SYMBOL(__dev_get_by_name);
+ EXPORT_SYMBOL(__dev_remove_pack);
+-EXPORT_SYMBOL(__skb_linearize);
+ EXPORT_SYMBOL(dev_valid_name);
+ EXPORT_SYMBOL(dev_add_pack);
+ EXPORT_SYMBOL(dev_alloc_name);
+Index: tmp-xxx/net/core/dev_mcast.c
+===================================================================
+--- tmp-xxx.orig/net/core/dev_mcast.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/core/dev_mcast.c 2006-11-27 10:52:42.000000000 +0000
+@@ -62,7 +62,7 @@
+ * Device mc lists are changed by bh at least if IPv6 is enabled,
+ * so that it must be bh protected.
+ *
+- * We block accesses to device mc filters with dev->xmit_lock.
++ * We block accesses to device mc filters with netif_tx_lock.
+ */
+
+ /*
+@@ -93,9 +93,9 @@
+
+ void dev_mc_upload(struct net_device *dev)
+ {
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ __dev_mc_upload(dev);
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ }
+
+ /*
+@@ -107,7 +107,7 @@
+ int err = 0;
+ struct dev_mc_list *dmi, **dmip;
+
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+
+ for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; dmip = &dmi->next) {
+ /*
+@@ -139,13 +139,13 @@
+ */
+ __dev_mc_upload(dev);
+
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ return 0;
+ }
+ }
+ err = -ENOENT;
+ done:
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ return err;
+ }
+
+@@ -160,7 +160,7 @@
+
+ dmi1 = kmalloc(sizeof(*dmi), GFP_ATOMIC);
+
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ for (dmi = dev->mc_list; dmi != NULL; dmi = dmi->next) {
+ if (memcmp(dmi->dmi_addr, addr, dmi->dmi_addrlen) == 0 &&
+ dmi->dmi_addrlen == alen) {
+@@ -176,7 +176,7 @@
+ }
+
+ if ((dmi = dmi1) == NULL) {
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ return -ENOMEM;
+ }
+ memcpy(dmi->dmi_addr, addr, alen);
+@@ -189,11 +189,11 @@
+
+ __dev_mc_upload(dev);
+
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ return 0;
+
+ done:
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ kfree(dmi1);
+ return err;
+ }
+@@ -204,7 +204,7 @@
+
+ void dev_mc_discard(struct net_device *dev)
+ {
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+
+ while (dev->mc_list != NULL) {
+ struct dev_mc_list *tmp = dev->mc_list;
+@@ -215,7 +215,7 @@
+ }
+ dev->mc_count = 0;
+
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ }
+
+ #ifdef CONFIG_PROC_FS
+@@ -250,7 +250,7 @@
+ struct dev_mc_list *m;
+ struct net_device *dev = v;
+
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ for (m = dev->mc_list; m; m = m->next) {
+ int i;
+
+@@ -262,7 +262,7 @@
+
+ seq_putc(seq, '\n');
+ }
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ return 0;
+ }
+
+Index: tmp-xxx/net/core/ethtool.c
+===================================================================
+--- tmp-xxx.orig/net/core/ethtool.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/core/ethtool.c 2006-11-27 10:52:42.000000000 +0000
+@@ -30,7 +30,7 @@
+
+ u32 ethtool_op_get_tx_csum(struct net_device *dev)
+ {
+- return (dev->features & (NETIF_F_IP_CSUM | NETIF_F_HW_CSUM)) != 0;
++ return (dev->features & NETIF_F_ALL_CSUM) != 0;
+ }
+
+ int ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+@@ -551,9 +551,7 @@
+ return -EFAULT;
+
+ if (edata.data &&
+- !(dev->features & (NETIF_F_IP_CSUM |
+- NETIF_F_NO_CSUM |
+- NETIF_F_HW_CSUM)))
++ !(dev->features & NETIF_F_ALL_CSUM))
+ return -EINVAL;
+
+ return __ethtool_set_sg(dev, edata.data);
+@@ -561,7 +559,7 @@
+
+ static int ethtool_get_tso(struct net_device *dev, char __user *useraddr)
+ {
+- struct ethtool_value edata = { ETHTOOL_GTSO };
++ struct ethtool_value edata = { ETHTOOL_GUFO };
+
+ if (!dev->ethtool_ops->get_tso)
+ return -EOPNOTSUPP;
+@@ -616,6 +614,29 @@
+ return dev->ethtool_ops->set_ufo(dev, edata.data);
+ }
+
++static int ethtool_get_gso(struct net_device *dev, char __user *useraddr)
++{
++ struct ethtool_value edata = { ETHTOOL_GGSO };
++
++ edata.data = dev->features & NETIF_F_GSO;
++ if (copy_to_user(useraddr, &edata, sizeof(edata)))
++ return -EFAULT;
++ return 0;
++}
++
++static int ethtool_set_gso(struct net_device *dev, char __user *useraddr)
++{
++ struct ethtool_value edata;
++
++ if (copy_from_user(&edata, useraddr, sizeof(edata)))
++ return -EFAULT;
++ if (edata.data)
++ dev->features |= NETIF_F_GSO;
++ else
++ dev->features &= ~NETIF_F_GSO;
++ return 0;
++}
++
+ static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
+ {
+ struct ethtool_test test;
+@@ -907,6 +928,12 @@
+ case ETHTOOL_SUFO:
+ rc = ethtool_set_ufo(dev, useraddr);
+ break;
++ case ETHTOOL_GGSO:
++ rc = ethtool_get_gso(dev, useraddr);
++ break;
++ case ETHTOOL_SGSO:
++ rc = ethtool_set_gso(dev, useraddr);
++ break;
+ default:
+ rc = -EOPNOTSUPP;
+ }
+Index: tmp-xxx/net/core/netpoll.c
+===================================================================
+--- tmp-xxx.orig/net/core/netpoll.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/core/netpoll.c 2006-11-27 10:52:42.000000000 +0000
+@@ -273,24 +273,21 @@
+
+ do {
+ npinfo->tries--;
+- spin_lock(&np->dev->xmit_lock);
+- np->dev->xmit_lock_owner = smp_processor_id();
++ netif_tx_lock(np->dev);
+
+ /*
+ * network drivers do not expect to be called if the queue is
+ * stopped.
+ */
+ if (netif_queue_stopped(np->dev)) {
+- np->dev->xmit_lock_owner = -1;
+- spin_unlock(&np->dev->xmit_lock);
++ netif_tx_unlock(np->dev);
+ netpoll_poll(np);
+ udelay(50);
+ continue;
+ }
+
+ status = np->dev->hard_start_xmit(skb, np->dev);
+- np->dev->xmit_lock_owner = -1;
+- spin_unlock(&np->dev->xmit_lock);
++ netif_tx_unlock(np->dev);
+
+ /* success */
+ if(!status) {
+Index: tmp-xxx/net/core/pktgen.c
+===================================================================
+--- tmp-xxx.orig/net/core/pktgen.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/core/pktgen.c 2006-11-27 10:52:42.000000000 +0000
+@@ -2586,7 +2586,7 @@
+ }
+ }
+
+- spin_lock_bh(&odev->xmit_lock);
++ netif_tx_lock_bh(odev);
+ if (!netif_queue_stopped(odev)) {
+
+ atomic_inc(&(pkt_dev->skb->users));
+@@ -2631,7 +2631,7 @@
+ pkt_dev->next_tx_ns = 0;
+ }
+
+- spin_unlock_bh(&odev->xmit_lock);
++ netif_tx_unlock_bh(odev);
+
+ /* If pkt_dev->count is zero, then run forever */
+ if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) {
+Index: tmp-xxx/net/core/skbuff.c
+===================================================================
+--- tmp-xxx.orig/net/core/skbuff.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/core/skbuff.c 2006-11-27 10:58:31.000000000 +0000
+@@ -164,9 +164,9 @@
+ shinfo = skb_shinfo(skb);
+ atomic_set(&shinfo->dataref, 1);
+ shinfo->nr_frags = 0;
+- shinfo->tso_size = 0;
+- shinfo->tso_segs = 0;
+- shinfo->ufo_size = 0;
++ shinfo->gso_size = 0;
++ shinfo->gso_segs = 0;
++ shinfo->gso_type = 0;
+ shinfo->ip6_frag_id = 0;
+ shinfo->frag_list = NULL;
+
+@@ -230,9 +230,9 @@
+
+ atomic_set(&(skb_shinfo(skb)->dataref), 1);
+ skb_shinfo(skb)->nr_frags = 0;
+- skb_shinfo(skb)->tso_size = 0;
+- skb_shinfo(skb)->tso_segs = 0;
+- skb_shinfo(skb)->ufo_size = 0;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_segs = 0;
++ skb_shinfo(skb)->gso_type = 0;
+ skb_shinfo(skb)->frag_list = NULL;
+ out:
+ return skb;
+@@ -507,9 +507,9 @@
+ new->tc_index = old->tc_index;
+ #endif
+ atomic_set(&new->users, 1);
+- skb_shinfo(new)->tso_size = skb_shinfo(old)->tso_size;
+- skb_shinfo(new)->tso_segs = skb_shinfo(old)->tso_segs;
+- skb_shinfo(new)->ufo_size = skb_shinfo(old)->ufo_size;
++ skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
++ skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
++ skb_shinfo(new)->gso_type = skb_shinfo(old)->gso_type;
+ }
+
+ /**
+@@ -1822,6 +1822,133 @@
+ return 0;
+ }
+
++/**
++ * skb_segment - Perform protocol segmentation on skb.
++ * @skb: buffer to segment
++ * @features: features for the output path (see dev->features)
++ *
++ * This function performs segmentation on the given skb. It returns
++ * the segment at the given position. It returns NULL if there are
++ * no more segments to generate, or when an error is encountered.
++ */
++struct sk_buff *skb_segment(struct sk_buff *skb, int features)
++{
++ struct sk_buff *segs = NULL;
++ struct sk_buff *tail = NULL;
++ unsigned int mss = skb_shinfo(skb)->gso_size;
++ unsigned int doffset = skb->data - skb->mac.raw;
++ unsigned int offset = doffset;
++ unsigned int headroom;
++ unsigned int len;
++ int sg = features & NETIF_F_SG;
++ int nfrags = skb_shinfo(skb)->nr_frags;
++ int err = -ENOMEM;
++ int i = 0;
++ int pos;
++
++ __skb_push(skb, doffset);
++ headroom = skb_headroom(skb);
++ pos = skb_headlen(skb);
++
++ do {
++ struct sk_buff *nskb;
++ skb_frag_t *frag;
++ int hsize, nsize;
++ int k;
++ int size;
++
++ len = skb->len - offset;
++ if (len > mss)
++ len = mss;
++
++ hsize = skb_headlen(skb) - offset;
++ if (hsize < 0)
++ hsize = 0;
++ nsize = hsize + doffset;
++ if (nsize > len + doffset || !sg)
++ nsize = len + doffset;
++
++ nskb = alloc_skb(nsize + headroom, GFP_ATOMIC);
++ if (unlikely(!nskb))
++ goto err;
++
++ if (segs)
++ tail->next = nskb;
++ else
++ segs = nskb;
++ tail = nskb;
++
++ nskb->dev = skb->dev;
++ nskb->priority = skb->priority;
++ nskb->protocol = skb->protocol;
++ nskb->dst = dst_clone(skb->dst);
++ memcpy(nskb->cb, skb->cb, sizeof(skb->cb));
++ nskb->pkt_type = skb->pkt_type;
++ nskb->mac_len = skb->mac_len;
++
++ skb_reserve(nskb, headroom);
++ nskb->mac.raw = nskb->data;
++ nskb->nh.raw = nskb->data + skb->mac_len;
++ nskb->h.raw = nskb->nh.raw + (skb->h.raw - skb->nh.raw);
++ memcpy(skb_put(nskb, doffset), skb->data, doffset);
++
++ if (!sg) {
++ nskb->csum = skb_copy_and_csum_bits(skb, offset,
++ skb_put(nskb, len),
++ len, 0);
++ continue;
++ }
++
++ frag = skb_shinfo(nskb)->frags;
++ k = 0;
++
++ nskb->ip_summed = CHECKSUM_HW;
++ nskb->csum = skb->csum;
++ memcpy(skb_put(nskb, hsize), skb->data + offset, hsize);
++
++ while (pos < offset + len) {
++ BUG_ON(i >= nfrags);
++
++ *frag = skb_shinfo(skb)->frags[i];
++ get_page(frag->page);
++ size = frag->size;
++
++ if (pos < offset) {
++ frag->page_offset += offset - pos;
++ frag->size -= offset - pos;
++ }
++
++ k++;
++
++ if (pos + size <= offset + len) {
++ i++;
++ pos += size;
++ } else {
++ frag->size -= pos + size - (offset + len);
++ break;
++ }
++
++ frag++;
++ }
++
++ skb_shinfo(nskb)->nr_frags = k;
++ nskb->data_len = len - hsize;
++ nskb->len += nskb->data_len;
++ nskb->truesize += nskb->data_len;
++ } while ((offset += len) < skb->len);
++
++ return segs;
++
++err:
++ while ((skb = segs)) {
++ segs = skb->next;
++ kfree(skb);
++ }
++ return ERR_PTR(err);
++}
++
++EXPORT_SYMBOL_GPL(skb_segment);
++
+ void __init skb_init(void)
+ {
+ skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
+Index: tmp-xxx/net/decnet/dn_nsp_in.c
+===================================================================
+--- tmp-xxx.orig/net/decnet/dn_nsp_in.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/net/decnet/dn_nsp_in.c 2006-11-27 10:52:42.000000000 +0000
+@@ -801,8 +801,7 @@
+ * We linearize everything except data segments here.
+ */
+ if (cb->nsp_flags & ~0x60) {
+- if (unlikely(skb_is_nonlinear(skb)) &&
+- skb_linearize(skb, GFP_ATOMIC) != 0)
++ if (unlikely(skb_linearize(skb)))
+ goto free_out;
+ }
+
+Index: tmp-xxx/net/decnet/dn_route.c
+===================================================================
+--- tmp-xxx.orig/net/decnet/dn_route.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/decnet/dn_route.c 2006-11-27 10:52:42.000000000 +0000
+@@ -629,8 +629,7 @@
+ padlen);
+
+ if (flags & DN_RT_PKT_CNTL) {
+- if (unlikely(skb_is_nonlinear(skb)) &&
+- skb_linearize(skb, GFP_ATOMIC) != 0)
++ if (unlikely(skb_linearize(skb)))
+ goto dump_it;
+
+ switch(flags & DN_RT_CNTL_MSK) {
+Index: tmp-xxx/net/ipv4/af_inet.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/af_inet.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv4/af_inet.c 2006-11-27 10:52:42.000000000 +0000
+@@ -68,6 +68,7 @@
+ */
+
+ #include <linux/config.h>
++#include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/types.h>
+ #include <linux/socket.h>
+@@ -1084,6 +1085,54 @@
+
+ EXPORT_SYMBOL(inet_sk_rebuild_header);
+
++static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
++{
++ struct sk_buff *segs = ERR_PTR(-EINVAL);
++ struct iphdr *iph;
++ struct net_protocol *ops;
++ int proto;
++ int ihl;
++ int id;
++
++ if (!pskb_may_pull(skb, sizeof(*iph)))
++ goto out;
++
++ iph = skb->nh.iph;
++ ihl = iph->ihl * 4;
++ if (ihl < sizeof(*iph))
++ goto out;
++
++ if (!pskb_may_pull(skb, ihl))
++ goto out;
++
++ skb->h.raw = __skb_pull(skb, ihl);
++ iph = skb->nh.iph;
++ id = ntohs(iph->id);
++ proto = iph->protocol & (MAX_INET_PROTOS - 1);
++ segs = ERR_PTR(-EPROTONOSUPPORT);
++
++ rcu_read_lock();
++ ops = rcu_dereference(inet_protos[proto]);
++ if (ops && ops->gso_segment)
++ segs = ops->gso_segment(skb, features);
++ rcu_read_unlock();
++
++ if (!segs || unlikely(IS_ERR(segs)))
++ goto out;
++
++ skb = segs;
++ do {
++ iph = skb->nh.iph;
++ iph->id = htons(id++);
++ iph->tot_len = htons(skb->len - skb->mac_len);
++ iph->check = 0;
++ iph->check = ip_fast_csum(skb->nh.raw, iph->ihl);
++ } while ((skb = skb->next));
++
++out:
++ return segs;
++}
++
+ #ifdef CONFIG_IP_MULTICAST
+ static struct net_protocol igmp_protocol = {
+ .handler = igmp_rcv,
+@@ -1093,6 +1142,7 @@
+ static struct net_protocol tcp_protocol = {
+ .handler = tcp_v4_rcv,
+ .err_handler = tcp_v4_err,
++ .gso_segment = tcp_tso_segment,
+ .no_policy = 1,
+ };
+
+@@ -1138,6 +1188,7 @@
+ static struct packet_type ip_packet_type = {
+ .type = __constant_htons(ETH_P_IP),
+ .func = ip_rcv,
++ .gso_segment = inet_gso_segment,
+ };
+
+ static int __init inet_init(void)
+Index: tmp-xxx/net/ipv4/ip_output.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/ip_output.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv4/ip_output.c 2006-11-27 10:52:42.000000000 +0000
+@@ -210,8 +210,7 @@
+ return dst_output(skb);
+ }
+ #endif
+- if (skb->len > dst_mtu(skb->dst) &&
+- !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))
++ if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
+ return ip_fragment(skb, ip_finish_output2);
+ else
+ return ip_finish_output2(skb);
+@@ -362,7 +361,7 @@
+ }
+
+ ip_select_ident_more(iph, &rt->u.dst, sk,
+- (skb_shinfo(skb)->tso_segs ?: 1) - 1);
++ (skb_shinfo(skb)->gso_segs ?: 1) - 1);
+
+ /* Add an IP checksum. */
+ ip_send_check(iph);
+@@ -743,7 +742,8 @@
+ (length - transhdrlen));
+ if (!err) {
+ /* specify the length of each IP datagram fragment*/
+- skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
++ skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
++ skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+
+ return 0;
+@@ -839,7 +839,7 @@
+ */
+ if (transhdrlen &&
+ length + fragheaderlen <= mtu &&
+-
rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
++ rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
+ !exthdrlen)
+ csummode = CHECKSUM_HW;
+
+@@ -1086,14 +1086,16 @@
+
+ inet->cork.length += size;
+ if ((sk->sk_protocol == IPPROTO_UDP) &&
+- (rt->u.dst.dev->features & NETIF_F_UFO))
+- skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen);
++ (rt->u.dst.dev->features & NETIF_F_UFO)) {
++ skb_shinfo(skb)->gso_size = mtu - fragheaderlen;
++ skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
++ }
+
+
+ while (size > 0) {
+ int i;
+
+- if (skb_shinfo(skb)->ufo_size)
++ if (skb_shinfo(skb)->gso_size)
+ len = size;
+ else {
+
+Index: tmp-xxx/net/ipv4/ipcomp.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/ipcomp.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv4/ipcomp.c 2006-11-27 10:52:42.000000000 +0000
+@@ -84,7 +84,7 @@
+ struct xfrm_decap_state *decap, struct sk_buff *skb)
+ {
+ u8 nexthdr;
+- int err = 0;
++ int err = -ENOMEM;
+ struct iphdr *iph;
+ union {
+ struct iphdr iph;
+@@ -92,11 +92,8 @@
+ } tmp_iph;
+
+
+- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+- skb_linearize(skb, GFP_ATOMIC) != 0) {
+- err = -ENOMEM;
++ if (skb_linearize_cow(skb))
+ goto out;
+- }
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+@@ -171,10 +168,8 @@
+ goto out_ok;
+ }
+
+- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+- skb_linearize(skb, GFP_ATOMIC) != 0) {
++ if (skb_linearize_cow(skb))
+ goto out_ok;
+- }
+
+ err = ipcomp_compress(x, skb);
+ iph = skb->nh.iph;
+Index: tmp-xxx/net/ipv4/tcp.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/tcp.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv4/tcp.c 2006-11-27 10:52:42.000000000 +0000
+@@ -257,6 +257,7 @@
+ #include <linux/fs.h>
+ #include <linux/random.h>
+ #include <linux/bootmem.h>
++#include <linux/err.h>
+
+ #include <net/icmp.h>
+ #include <net/tcp.h>
+@@ -570,7 +571,7 @@
+ skb->ip_summed = CHECKSUM_HW;
+ tp->write_seq += copy;
+ TCP_SKB_CB(skb)->end_seq += copy;
+- skb_shinfo(skb)->tso_segs = 0;
++ skb_shinfo(skb)->gso_segs = 0;
+
+ if (!copied)
+ TCP_SKB_CB(skb)->flags &= ~TCPCB_FLAG_PSH;
+@@ -621,14 +622,10 @@
+ ssize_t res;
+ struct sock *sk = sock->sk;
+
+-#define TCP_ZC_CSUM_FLAGS (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |
NETIF_F_HW_CSUM)
+-
+ if (!(sk->sk_route_caps & NETIF_F_SG) ||
+- !(sk->sk_route_caps & TCP_ZC_CSUM_FLAGS))
++ !(sk->sk_route_caps & NETIF_F_ALL_CSUM))
+ return sock_no_sendpage(sock, page, offset, size, flags);
+
+-#undef TCP_ZC_CSUM_FLAGS
+-
+ lock_sock(sk);
+ TCP_CHECK_TIMER(sk);
+ res = do_tcp_sendpages(sk, &page, offset, size, flags);
+@@ -725,9 +722,7 @@
+ /*
+ * Check whether we can use HW checksum.
+ */
+- if (sk->sk_route_caps &
+- (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM |
+- NETIF_F_HW_CSUM))
++ if (sk->sk_route_caps & NETIF_F_ALL_CSUM)
+ skb->ip_summed = CHECKSUM_HW;
+
+ skb_entail(sk, tp, skb);
+@@ -823,7 +818,7 @@
+
+ tp->write_seq += copy;
+ TCP_SKB_CB(skb)->end_seq += copy;
+- skb_shinfo(skb)->tso_segs = 0;
++ skb_shinfo(skb)->gso_segs = 0;
+
+ from += copy;
+ copied += copy;
+@@ -2026,6 +2021,71 @@
+ }
+
+
++struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
++{
++ struct sk_buff *segs = ERR_PTR(-EINVAL);
++ struct tcphdr *th;
++ unsigned thlen;
++ unsigned int seq;
++ unsigned int delta;
++ unsigned int oldlen;
++ unsigned int len;
++
++ if (!pskb_may_pull(skb, sizeof(*th)))
++ goto out;
++
++ th = skb->h.th;
++ thlen = th->doff * 4;
++ if (thlen < sizeof(*th))
++ goto out;
++
++ if (!pskb_may_pull(skb, thlen))
++ goto out;
++
++ segs = NULL;
++ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
++ goto out;
++
++ oldlen = (u16)~skb->len;
++ __skb_pull(skb, thlen);
++
++ segs = skb_segment(skb, features);
++ if (IS_ERR(segs))
++ goto out;
++
++ len = skb_shinfo(skb)->gso_size;
++ delta = htonl(oldlen + (thlen + len));
++
++ skb = segs;
++ th = skb->h.th;
++ seq = ntohl(th->seq);
++
++ do {
++ th->fin = th->psh = 0;
++
++ th->check = ~csum_fold(th->check + delta);
++ if (skb->ip_summed != CHECKSUM_HW)
++ th->check = csum_fold(csum_partial(skb->h.raw, thlen,
++ skb->csum));
++
++ seq += len;
++ skb = skb->next;
++ th = skb->h.th;
++
++ th->seq = htonl(seq);
++ th->cwr = 0;
++ } while (skb->next);
++
++ delta = htonl(oldlen + (skb->tail - skb->h.raw) + skb->data_len);
++ th->check = ~csum_fold(th->check + delta);
++ if (skb->ip_summed != CHECKSUM_HW)
++ th->check = csum_fold(csum_partial(skb->h.raw, thlen,
++ skb->csum));
++
++out:
++ return segs;
++}
++
+ extern void __skb_cb_too_small_for_tcp(int, int);
+ extern struct tcp_congestion_ops tcp_reno;
+
+Index: tmp-xxx/net/ipv4/tcp_input.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/tcp_input.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv4/tcp_input.c 2006-11-27 10:52:42.000000000 +0000
+@@ -1072,7 +1072,7 @@
+ else
+ pkt_len = (end_seq -
+ TCP_SKB_CB(skb)->seq);
+- if (tcp_fragment(sk, skb, pkt_len,
skb_shinfo(skb)->tso_size))
++ if (tcp_fragment(sk, skb, pkt_len,
skb_shinfo(skb)->gso_size))
+ break;
+ pcount = tcp_skb_pcount(skb);
+ }
+Index: tmp-xxx/net/ipv4/tcp_output.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/tcp_output.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv4/tcp_output.c 2006-11-27 10:52:42.000000000 +0000
+@@ -497,15 +497,17 @@
+ /* Avoid the costly divide in the normal
+ * non-TSO case.
+ */
+- skb_shinfo(skb)->tso_segs = 1;
+- skb_shinfo(skb)->tso_size = 0;
++ skb_shinfo(skb)->gso_segs = 1;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_type = 0;
+ } else {
+ unsigned int factor;
+
+ factor = skb->len + (mss_now - 1);
+ factor /= mss_now;
+- skb_shinfo(skb)->tso_segs = factor;
+- skb_shinfo(skb)->tso_size = mss_now;
++ skb_shinfo(skb)->gso_segs = factor;
++ skb_shinfo(skb)->gso_size = mss_now;
++ skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+ }
+ }
+
+@@ -850,7 +852,7 @@
+
+ if (!tso_segs ||
+ (tso_segs > 1 &&
+- skb_shinfo(skb)->tso_size != mss_now)) {
++ tcp_skb_mss(skb) != mss_now)) {
+ tcp_set_skb_tso_segs(sk, skb, mss_now);
+ tso_segs = tcp_skb_pcount(skb);
+ }
+@@ -1510,8 +1512,9 @@
+ tp->snd_una == (TCP_SKB_CB(skb)->end_seq - 1)) {
+ if (!pskb_trim(skb, 0)) {
+ TCP_SKB_CB(skb)->seq = TCP_SKB_CB(skb)->end_seq - 1;
+- skb_shinfo(skb)->tso_segs = 1;
+- skb_shinfo(skb)->tso_size = 0;
++ skb_shinfo(skb)->gso_segs = 1;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_type = 0;
+ skb->ip_summed = CHECKSUM_NONE;
+ skb->csum = 0;
+ }
+@@ -1716,8 +1719,9 @@
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_FIN);
+ TCP_SKB_CB(skb)->sacked = 0;
+- skb_shinfo(skb)->tso_segs = 1;
+- skb_shinfo(skb)->tso_size = 0;
++ skb_shinfo(skb)->gso_segs = 1;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_type = 0;
+
+ /* FIN eats a sequence byte, write_seq advanced by
tcp_queue_skb(). */
+ TCP_SKB_CB(skb)->seq = tp->write_seq;
+@@ -1749,8 +1753,9 @@
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = (TCPCB_FLAG_ACK | TCPCB_FLAG_RST);
+ TCP_SKB_CB(skb)->sacked = 0;
+- skb_shinfo(skb)->tso_segs = 1;
+- skb_shinfo(skb)->tso_size = 0;
++ skb_shinfo(skb)->gso_segs = 1;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_type = 0;
+
+ /* Send it off. */
+ TCP_SKB_CB(skb)->seq = tcp_acceptable_seq(sk, tp);
+@@ -1833,8 +1838,9 @@
+ TCP_SKB_CB(skb)->seq = tcp_rsk(req)->snt_isn;
+ TCP_SKB_CB(skb)->end_seq = TCP_SKB_CB(skb)->seq + 1;
+ TCP_SKB_CB(skb)->sacked = 0;
+- skb_shinfo(skb)->tso_segs = 1;
+- skb_shinfo(skb)->tso_size = 0;
++ skb_shinfo(skb)->gso_segs = 1;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_type = 0;
+ th->seq = htonl(TCP_SKB_CB(skb)->seq);
+ th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
+ if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
+@@ -1937,8 +1943,9 @@
+ TCP_SKB_CB(buff)->flags = TCPCB_FLAG_SYN;
+ TCP_ECN_send_syn(sk, tp, buff);
+ TCP_SKB_CB(buff)->sacked = 0;
+- skb_shinfo(buff)->tso_segs = 1;
+- skb_shinfo(buff)->tso_size = 0;
++ skb_shinfo(buff)->gso_segs = 1;
++ skb_shinfo(buff)->gso_size = 0;
++ skb_shinfo(buff)->gso_type = 0;
+ buff->csum = 0;
+ TCP_SKB_CB(buff)->seq = tp->write_seq++;
+ TCP_SKB_CB(buff)->end_seq = tp->write_seq;
+@@ -2042,8 +2049,9 @@
+ buff->csum = 0;
+ TCP_SKB_CB(buff)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(buff)->sacked = 0;
+- skb_shinfo(buff)->tso_segs = 1;
+- skb_shinfo(buff)->tso_size = 0;
++ skb_shinfo(buff)->gso_segs = 1;
++ skb_shinfo(buff)->gso_size = 0;
++ skb_shinfo(buff)->gso_type = 0;
+
+ /* Send it off, this clears delayed acks for us. */
+ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(buff)->end_seq =
tcp_acceptable_seq(sk, tp);
+@@ -2078,8 +2086,9 @@
+ skb->csum = 0;
+ TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
+ TCP_SKB_CB(skb)->sacked = urgent;
+- skb_shinfo(skb)->tso_segs = 1;
+- skb_shinfo(skb)->tso_size = 0;
++ skb_shinfo(skb)->gso_segs = 1;
++ skb_shinfo(skb)->gso_size = 0;
++ skb_shinfo(skb)->gso_type = 0;
+
+ /* Use a previous sequence. This should cause the other
+ * end to send an ack. Don't queue or clone SKB, just
+Index: tmp-xxx/net/ipv4/xfrm4_output.c
+===================================================================
+--- tmp-xxx.orig/net/ipv4/xfrm4_output.c 2006-11-27 10:52:32.000000000
+0000
++++ tmp-xxx/net/ipv4/xfrm4_output.c 2006-11-27 10:52:42.000000000 +0000
+@@ -9,6 +9,8 @@
+ */
+
+ #include <linux/compiler.h>
++#include <linux/if_ether.h>
++#include <linux/kernel.h>
+ #include <linux/skbuff.h>
+ #include <linux/spinlock.h>
+ #include <linux/netfilter_ipv4.h>
+@@ -158,16 +160,10 @@
+ goto out_exit;
+ }
+
+-static int xfrm4_output_finish(struct sk_buff *skb)
++static int xfrm4_output_finish2(struct sk_buff *skb)
+ {
+ int err;
+
+-#ifdef CONFIG_NETFILTER
+- if (!skb->dst->xfrm) {
+- IPCB(skb)->flags |= IPSKB_REROUTED;
+- return dst_output(skb);
+- }
+-#endif
+ while (likely((err = xfrm4_output_one(skb)) == 0)) {
+ nf_reset(skb);
+
+@@ -180,7 +176,7 @@
+ return dst_output(skb);
+
+ err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
+- skb->dst->dev, xfrm4_output_finish);
++ skb->dst->dev, xfrm4_output_finish2);
+ if (unlikely(err != 1))
+ break;
+ }
+@@ -188,6 +184,48 @@
+ return err;
+ }
+
++static int xfrm4_output_finish(struct sk_buff *skb)
++{
++ struct sk_buff *segs;
++
++#ifdef CONFIG_NETFILTER
++ if (!skb->dst->xfrm) {
++ IPCB(skb)->flags |= IPSKB_REROUTED;
++ return dst_output(skb);
++ }
++#endif
++
++ if (!skb_shinfo(skb)->gso_size)
++ return xfrm4_output_finish2(skb);
++
++ skb->protocol = htons(ETH_P_IP);
++ segs = skb_gso_segment(skb, 0);
++ kfree_skb(skb);
++ if (unlikely(IS_ERR(segs)))
++ return PTR_ERR(segs);
++
++ do {
++ struct sk_buff *nskb = segs->next;
++ int err;
++
++ segs->next = NULL;
++ err = xfrm4_output_finish2(segs);
++
++ if (unlikely(err)) {
++ while ((segs = nskb)) {
++ nskb = segs->next;
++ segs->next = NULL;
++ kfree_skb(segs);
++ }
++ return err;
++ }
++
++ segs = nskb;
++ } while (segs);
++
++ return 0;
++}
++
+ int xfrm4_output(struct sk_buff *skb)
+ {
+ return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
skb->dst->dev,
+Index: tmp-xxx/net/ipv6/ip6_output.c
+===================================================================
+--- tmp-xxx.orig/net/ipv6/ip6_output.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv6/ip6_output.c 2006-11-27 10:52:42.000000000 +0000
+@@ -147,7 +147,7 @@
+
+ int ip6_output(struct sk_buff *skb)
+ {
+- if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->ufo_size) ||
++ if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
+ dst_allfrag(skb->dst))
+ return ip6_fragment(skb, ip6_output2);
+ else
+@@ -829,8 +829,9 @@
+ struct frag_hdr fhdr;
+
+ /* specify the length of each IP datagram fragment*/
+- skb_shinfo(skb)->ufo_size = (mtu - fragheaderlen) -
+- sizeof(struct frag_hdr);
++ skb_shinfo(skb)->gso_size = mtu - fragheaderlen -
++ sizeof(struct frag_hdr);
++ skb_shinfo(skb)->gso_type = SKB_GSO_UDPV4;
+ ipv6_select_ident(skb, &fhdr);
+ skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
+ __skb_queue_tail(&sk->sk_write_queue, skb);
+Index: tmp-xxx/net/ipv6/ipcomp6.c
+===================================================================
+--- tmp-xxx.orig/net/ipv6/ipcomp6.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/ipv6/ipcomp6.c 2006-11-27 10:52:42.000000000 +0000
+@@ -64,7 +64,7 @@
+
+ static int ipcomp6_input(struct xfrm_state *x, struct xfrm_decap_state
*decap, struct sk_buff *skb)
+ {
+- int err = 0;
++ int err = -ENOMEM;
+ u8 nexthdr = 0;
+ int hdr_len = skb->h.raw - skb->nh.raw;
+ unsigned char *tmp_hdr = NULL;
+@@ -75,11 +75,8 @@
+ struct crypto_tfm *tfm;
+ int cpu;
+
+- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+- skb_linearize(skb, GFP_ATOMIC) != 0) {
+- err = -ENOMEM;
++ if (skb_linearize_cow(skb))
+ goto out;
+- }
+
+ skb->ip_summed = CHECKSUM_NONE;
+
+@@ -158,10 +155,8 @@
+ goto out_ok;
+ }
+
+- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
+- skb_linearize(skb, GFP_ATOMIC) != 0) {
++ if (skb_linearize_cow(skb))
+ goto out_ok;
+- }
+
+ /* compression */
+ plen = skb->len - hdr_len;
+Index: tmp-xxx/net/ipv6/xfrm6_output.c
+===================================================================
+--- tmp-xxx.orig/net/ipv6/xfrm6_output.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/net/ipv6/xfrm6_output.c 2006-11-27 10:52:42.000000000 +0000
+@@ -151,7 +151,7 @@
+ goto out_exit;
+ }
+
+-static int xfrm6_output_finish(struct sk_buff *skb)
++static int xfrm6_output_finish2(struct sk_buff *skb)
+ {
+ int err;
+
+@@ -167,7 +167,7 @@
+ return dst_output(skb);
+
+ err = nf_hook(PF_INET6, NF_IP6_POST_ROUTING, &skb, NULL,
+- skb->dst->dev, xfrm6_output_finish);
++ skb->dst->dev, xfrm6_output_finish2);
+ if (unlikely(err != 1))
+ break;
+ }
+@@ -175,6 +175,41 @@
+ return err;
+ }
+
++static int xfrm6_output_finish(struct sk_buff *skb)
++{
++ struct sk_buff *segs;
++
++ if (!skb_shinfo(skb)->gso_size)
++ return xfrm6_output_finish2(skb);
++
++ skb->protocol = htons(ETH_P_IP);
++ segs = skb_gso_segment(skb, 0);
++ kfree_skb(skb);
++ if (unlikely(IS_ERR(segs)))
++ return PTR_ERR(segs);
++
++ do {
++ struct sk_buff *nskb = segs->next;
++ int err;
++
++ segs->next = NULL;
++ err = xfrm6_output_finish2(segs);
++
++ if (unlikely(err)) {
++ while ((segs = nskb)) {
++ nskb = segs->next;
++ segs->next = NULL;
++ kfree_skb(segs);
++ }
++ return err;
++ }
++
++ segs = nskb;
++ } while (segs);
++
++ return 0;
++}
++
+ int xfrm6_output(struct sk_buff *skb)
+ {
+ return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dst->dev,
+Index: tmp-xxx/net/sched/sch_generic.c
+===================================================================
+--- tmp-xxx.orig/net/sched/sch_generic.c 2006-11-15 10:38:39.000000000
+0000
++++ tmp-xxx/net/sched/sch_generic.c 2006-11-27 10:52:42.000000000 +0000
+@@ -72,9 +72,9 @@
+ dev->queue_lock serializes queue accesses for this device
+ AND dev->qdisc pointer itself.
+
+- dev->xmit_lock serializes accesses to device driver.
++ netif_tx_lock serializes accesses to device driver.
+
+- dev->queue_lock and dev->xmit_lock are mutually exclusive,
++ dev->queue_lock and netif_tx_lock are mutually exclusive,
+ if one is grabbed, another must be free.
+ */
+
+@@ -90,14 +90,17 @@
+ NOTE: Called under dev->queue_lock with locally disabled BH.
+ */
+
+-int qdisc_restart(struct net_device *dev)
++static inline int qdisc_restart(struct net_device *dev)
+ {
+ struct Qdisc *q = dev->qdisc;
+ struct sk_buff *skb;
+
+ /* Dequeue packet */
+- if ((skb = q->dequeue(q)) != NULL) {
++ if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
+ unsigned nolock = (dev->features & NETIF_F_LLTX);
++
++ dev->gso_skb = NULL;
++
+ /*
+ * When the driver has LLTX set it does its own locking
+ * in start_xmit. No need to add additional overhead by
+@@ -108,7 +111,7 @@
+ * will be requeued.
+ */
+ if (!nolock) {
+- if (!spin_trylock(&dev->xmit_lock)) {
++ if (!netif_tx_trylock(dev)) {
+ collision:
+ /* So, someone grabbed the driver. */
+
+@@ -126,8 +129,6 @@
+ __get_cpu_var(netdev_rx_stat).cpu_collision++;
+ goto requeue;
+ }
+- /* Remember that the driver is grabbed by us. */
+- dev->xmit_lock_owner = smp_processor_id();
+ }
+
+ {
+@@ -136,14 +137,11 @@
+
+ if (!netif_queue_stopped(dev)) {
+ int ret;
+- if (netdev_nit)
+- dev_queue_xmit_nit(skb, dev);
+
+- ret = dev->hard_start_xmit(skb, dev);
++ ret = dev_hard_start_xmit(skb, dev);
+ if (ret == NETDEV_TX_OK) {
+ if (!nolock) {
+- dev->xmit_lock_owner = -1;
+- spin_unlock(&dev->xmit_lock);
++ netif_tx_unlock(dev);
+ }
+ spin_lock(&dev->queue_lock);
+ return -1;
+@@ -157,8 +155,7 @@
+ /* NETDEV_TX_BUSY - we need to requeue */
+ /* Release the driver */
+ if (!nolock) {
+- dev->xmit_lock_owner = -1;
+- spin_unlock(&dev->xmit_lock);
++ netif_tx_unlock(dev);
+ }
+ spin_lock(&dev->queue_lock);
+ q = dev->qdisc;
+@@ -175,7 +172,10 @@
+ */
+
+ requeue:
+- q->ops->requeue(skb, q);
++ if (skb->next)
++ dev->gso_skb = skb;
++ else
++ q->ops->requeue(skb, q);
+ netif_schedule(dev);
+ return 1;
+ }
+@@ -183,11 +183,23 @@
+ return q->q.qlen;
+ }
+
++void __qdisc_run(struct net_device *dev)
++{
++ if (unlikely(dev->qdisc == &noop_qdisc))
++ goto out;
++
++ while (qdisc_restart(dev) < 0 && !netif_queue_stopped(dev))
++ /* NOTHING */;
++
++out:
++ clear_bit(__LINK_STATE_QDISC_RUNNING, &dev->state);
++}
++
+ static void dev_watchdog(unsigned long arg)
+ {
+ struct net_device *dev = (struct net_device *)arg;
+
+- spin_lock(&dev->xmit_lock);
++ netif_tx_lock(dev);
+ if (dev->qdisc != &noop_qdisc) {
+ if (netif_device_present(dev) &&
+ netif_running(dev) &&
+@@ -201,7 +213,7 @@
+ dev_hold(dev);
+ }
+ }
+- spin_unlock(&dev->xmit_lock);
++ netif_tx_unlock(dev);
+
+ dev_put(dev);
+ }
+@@ -225,17 +237,17 @@
+
+ static void dev_watchdog_up(struct net_device *dev)
+ {
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ __netdev_watchdog_up(dev);
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ }
+
+ static void dev_watchdog_down(struct net_device *dev)
+ {
+- spin_lock_bh(&dev->xmit_lock);
++ netif_tx_lock_bh(dev);
+ if (del_timer(&dev->watchdog_timer))
+ __dev_put(dev);
+- spin_unlock_bh(&dev->xmit_lock);
++ netif_tx_unlock_bh(dev);
+ }
+
+ void netif_carrier_on(struct net_device *dev)
+@@ -577,10 +589,17 @@
+
+ dev_watchdog_down(dev);
+
+- while (test_bit(__LINK_STATE_SCHED, &dev->state))
++ /* Wait for outstanding dev_queue_xmit calls. */
++ synchronize_rcu();
++
++ /* Wait for outstanding qdisc_run calls. */
++ while (test_bit(__LINK_STATE_QDISC_RUNNING, &dev->state))
+ yield();
+
+- spin_unlock_wait(&dev->xmit_lock);
++ if (dev->gso_skb) {
++ kfree_skb(dev->gso_skb);
++ dev->gso_skb = NULL;
++ }
+ }
+
+ void dev_init_scheduler(struct net_device *dev)
+@@ -622,6 +641,5 @@
+ EXPORT_SYMBOL(qdisc_alloc);
+ EXPORT_SYMBOL(qdisc_destroy);
+ EXPORT_SYMBOL(qdisc_reset);
+-EXPORT_SYMBOL(qdisc_restart);
+ EXPORT_SYMBOL(qdisc_lock_tree);
+ EXPORT_SYMBOL(qdisc_unlock_tree);
+Index: tmp-xxx/net/sched/sch_teql.c
+===================================================================
+--- tmp-xxx.orig/net/sched/sch_teql.c 2006-11-15 10:38:39.000000000 +0000
++++ tmp-xxx/net/sched/sch_teql.c 2006-11-27 10:52:42.000000000 +0000
+@@ -302,20 +302,17 @@
+
+ switch (teql_resolve(skb, skb_res, slave)) {
+ case 0:
+- if (spin_trylock(&slave->xmit_lock)) {
+- slave->xmit_lock_owner = smp_processor_id();
++ if (netif_tx_trylock(slave)) {
+ if (!netif_queue_stopped(slave) &&
+ slave->hard_start_xmit(skb, slave) == 0) {
+- slave->xmit_lock_owner = -1;
+- spin_unlock(&slave->xmit_lock);
++ netif_tx_unlock(slave);
+ master->slaves = NEXT_SLAVE(q);
+ netif_wake_queue(dev);
+ master->stats.tx_packets++;
+ master->stats.tx_bytes += len;
+ return 0;
+ }
+- slave->xmit_lock_owner = -1;
+- spin_unlock(&slave->xmit_lock);
++ netif_tx_unlock(slave);
+ }
+ if (netif_queue_stopped(dev))
+ busy = 1;
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/net-gso-1-check-dodgy.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-gso-1-check-dodgy.patch Wed Nov 29
11:07:28 2006 -0700
@@ -0,0 +1,27 @@
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp.c ./net/ipv4/tcp.c
+--- ../orig-linux-2.6.16.29/net/ipv4/tcp.c 2006-09-19 13:59:20.000000000
+0100
++++ ./net/ipv4/tcp.c 2006-09-19 13:59:42.000000000 +0100
+@@ -2042,13 +2042,19 @@ struct sk_buff *tcp_tso_segment(struct s
+ if (!pskb_may_pull(skb, thlen))
+ goto out;
+
+- segs = NULL;
+- if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+- goto out;
+-
+ oldlen = (u16)~skb->len;
+ __skb_pull(skb, thlen);
+
++ if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
++ /* Packet is from an untrusted source, reset gso_segs. */
++ int mss = skb_shinfo(skb)->gso_size;
++
++ skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
++
++ segs = NULL;
++ goto out;
++ }
++
+ segs = skb_segment(skb, features);
+ if (IS_ERR(segs))
+ goto out;
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/net-gso-2-checksum-fix.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-gso-2-checksum-fix.patch Wed Nov 29
11:07:28 2006 -0700
@@ -0,0 +1,451 @@
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/bnx2.c ./drivers/net/bnx2.c
+--- ../orig-linux-2.6.16.29/drivers/net/bnx2.c 2006-09-19 13:59:20.000000000
+0100
++++ ./drivers/net/bnx2.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1593,7 +1593,7 @@ bnx2_tx_int(struct bnx2 *bp)
+ skb = tx_buf->skb;
+ #ifdef BCM_TSO
+ /* partial BD completions possible with TSO packets */
+- if (skb_shinfo(skb)->gso_size) {
++ if (skb_is_gso(skb)) {
+ u16 last_idx, last_ring_idx;
+
+ last_idx = sw_cons +
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c
./drivers/net/chelsio/sge.c
+--- ../orig-linux-2.6.16.29/drivers/net/chelsio/sge.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/net/chelsio/sge.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1419,7 +1419,7 @@ int t1_start_xmit(struct sk_buff *skb, s
+ struct cpl_tx_pkt *cpl;
+
+ #ifdef NETIF_F_TSO
+- if (skb_shinfo(skb)->gso_size) {
++ if (skb_is_gso(skb)) {
+ int eth_type;
+ struct cpl_tx_pkt_lso *hdr;
+
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c
./drivers/net/e1000/e1000_main.c
+--- ../orig-linux-2.6.16.29/drivers/net/e1000/e1000_main.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/net/e1000/e1000_main.c 2006-09-19 13:59:46.000000000 +0100
+@@ -2526,7 +2526,7 @@ e1000_tso(struct e1000_adapter *adapter,
+ uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+ int err;
+
+- if (skb_shinfo(skb)->gso_size) {
++ if (skb_is_gso(skb)) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+@@ -2651,7 +2651,7 @@ e1000_tx_map(struct e1000_adapter *adapt
+ * tso gets written back prematurely before the data is fully
+ * DMAd to the controller */
+ if (!skb->data_len && tx_ring->last_tx_tso &&
+- !skb_shinfo(skb)->gso_size) {
++ !skb_is_gso(skb)) {
+ tx_ring->last_tx_tso = 0;
+ size -= 4;
+ }
+@@ -2934,8 +2934,7 @@ e1000_xmit_frame(struct sk_buff *skb, st
+
+ #ifdef NETIF_F_TSO
+ /* Controller Erratum workaround */
+- if (!skb->data_len && tx_ring->last_tx_tso &&
+- !skb_shinfo(skb)->gso_size)
++ if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb))
+ count++;
+ #endif
+
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/forcedeth.c
./drivers/net/forcedeth.c
+--- ../orig-linux-2.6.16.29/drivers/net/forcedeth.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/net/forcedeth.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1105,7 +1105,7 @@ static int nv_start_xmit(struct sk_buff
+ np->tx_skbuff[nr] = skb;
+
+ #ifdef NETIF_F_TSO
+- if (skb_shinfo(skb)->gso_size)
++ if (skb_is_gso(skb))
+ tx_flags_extra = NV_TX2_TSO | (skb_shinfo(skb)->gso_size <<
NV_TX2_TSO_SHIFT);
+ else
+ #endif
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c
./drivers/net/ixgb/ixgb_main.c
+--- ../orig-linux-2.6.16.29/drivers/net/ixgb/ixgb_main.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/net/ixgb/ixgb_main.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1163,7 +1163,7 @@ ixgb_tso(struct ixgb_adapter *adapter, s
+ uint16_t ipcse, tucse, mss;
+ int err;
+
+- if(likely(skb_shinfo(skb)->gso_size)) {
++ if (likely(skb_is_gso(skb))) {
+ if (skb_header_cloned(skb)) {
+ err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+ if (err)
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/loopback.c
./drivers/net/loopback.c
+--- ../orig-linux-2.6.16.29/drivers/net/loopback.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/net/loopback.c 2006-09-19 13:59:46.000000000 +0100
+@@ -139,7 +139,7 @@ static int loopback_xmit(struct sk_buff
+ #endif
+
+ #ifdef LOOPBACK_TSO
+- if (skb_shinfo(skb)->gso_size) {
++ if (skb_is_gso(skb)) {
+ BUG_ON(skb->protocol != htons(ETH_P_IP));
+ BUG_ON(skb->nh.iph->protocol != IPPROTO_TCP);
+
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/sky2.c ./drivers/net/sky2.c
+--- ../orig-linux-2.6.16.29/drivers/net/sky2.c 2006-09-19 13:59:20.000000000
+0100
++++ ./drivers/net/sky2.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1125,7 +1125,7 @@ static unsigned tx_le_req(const struct s
+ count = sizeof(dma_addr_t) / sizeof(u32);
+ count += skb_shinfo(skb)->nr_frags * count;
+
+- if (skb_shinfo(skb)->gso_size)
++ if (skb_is_gso(skb))
+ ++count;
+
+ if (skb->ip_summed == CHECKSUM_HW)
+diff -pruN ../orig-linux-2.6.16.29/drivers/net/typhoon.c
./drivers/net/typhoon.c
+--- ../orig-linux-2.6.16.29/drivers/net/typhoon.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/net/typhoon.c 2006-09-19 13:59:46.000000000 +0100
+@@ -805,7 +805,7 @@ typhoon_start_tx(struct sk_buff *skb, st
+ * If problems develop with TSO, check this first.
+ */
+ numDesc = skb_shinfo(skb)->nr_frags + 1;
+- if(skb_tso_size(skb))
++ if (skb_is_gso(skb))
+ numDesc++;
+
+ /* When checking for free space in the ring, we need to also
+@@ -845,7 +845,7 @@ typhoon_start_tx(struct sk_buff *skb, st
+ TYPHOON_TX_PF_VLAN_TAG_SHIFT);
+ }
+
+- if(skb_tso_size(skb)) {
++ if (skb_is_gso(skb)) {
+ first_txd->processFlags |= TYPHOON_TX_PF_TCP_SEGMENT;
+ first_txd->numDesc++;
+
+diff -pruN ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c
./drivers/s390/net/qeth_main.c
+--- ../orig-linux-2.6.16.29/drivers/s390/net/qeth_main.c 2006-09-19
13:59:20.000000000 +0100
++++ ./drivers/s390/net/qeth_main.c 2006-09-19 13:59:46.000000000 +0100
+@@ -4454,7 +4454,7 @@ qeth_send_packet(struct qeth_card *card,
+ queue = card->qdio.out_qs
+ [qeth_get_priority_queue(card, skb, ipv, cast_type)];
+
+- if (skb_shinfo(skb)->gso_size)
++ if (skb_is_gso(skb))
+ large_send = card->options.large_send;
+
+ /*are we able to do TSO ? If so ,prepare and send it from here */
+@@ -4501,8 +4501,7 @@ qeth_send_packet(struct qeth_card *card,
+ card->stats.tx_packets++;
+ card->stats.tx_bytes += skb->len;
+ #ifdef CONFIG_QETH_PERF_STATS
+- if (skb_shinfo(skb)->gso_size &&
+- !(large_send == QETH_LARGE_SEND_NO)) {
++ if (skb_is_gso(skb) && !(large_send == QETH_LARGE_SEND_NO)) {
+ card->perf_stats.large_send_bytes += skb->len;
+ card->perf_stats.large_send_cnt++;
+ }
+diff -pruN ../orig-linux-2.6.16.29/include/linux/netdevice.h
./include/linux/netdevice.h
+--- ../orig-linux-2.6.16.29/include/linux/netdevice.h 2006-09-19
13:59:20.000000000 +0100
++++ ./include/linux/netdevice.h 2006-09-19 13:59:46.000000000 +0100
+@@ -541,6 +541,7 @@ struct packet_type {
+ struct net_device *);
+ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
+ int features);
++ int (*gso_send_check)(struct sk_buff *skb);
+ void *af_packet_priv;
+ struct list_head list;
+ };
+@@ -1001,14 +1002,15 @@ extern void linkwatch_run_queue(void);
+
+ static inline int skb_gso_ok(struct sk_buff *skb, int features)
+ {
+- int feature = skb_shinfo(skb)->gso_size ?
+- skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0;
++ int feature = skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT;
+ return (features & feature) == feature;
+ }
+
+ static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb)
+ {
+- return !skb_gso_ok(skb, dev->features);
++ return skb_is_gso(skb) &&
++ (!skb_gso_ok(skb, dev->features) ||
++ unlikely(skb->ip_summed != CHECKSUM_HW));
+ }
+
+ #endif /* __KERNEL__ */
+diff -pruN ../orig-linux-2.6.16.29/include/linux/skbuff.h
./include/linux/skbuff.h
+--- ../orig-linux-2.6.16.29/include/linux/skbuff.h 2006-09-19
13:59:20.000000000 +0100
++++ ./include/linux/skbuff.h 2006-09-19 13:59:46.000000000 +0100
+@@ -1403,5 +1403,10 @@ static inline void nf_bridge_get(struct
+ static inline void nf_reset(struct sk_buff *skb) {}
+ #endif /* CONFIG_NETFILTER */
+
++static inline int skb_is_gso(const struct sk_buff *skb)
++{
++ return skb_shinfo(skb)->gso_size;
++}
++
+ #endif /* __KERNEL__ */
+ #endif /* _LINUX_SKBUFF_H */
+diff -pruN ../orig-linux-2.6.16.29/include/net/protocol.h
./include/net/protocol.h
+--- ../orig-linux-2.6.16.29/include/net/protocol.h 2006-09-19
13:59:20.000000000 +0100
++++ ./include/net/protocol.h 2006-09-19 13:59:46.000000000 +0100
+@@ -37,6 +37,7 @@
+ struct net_protocol {
+ int (*handler)(struct sk_buff *skb);
+ void (*err_handler)(struct sk_buff *skb, u32 info);
++ int (*gso_send_check)(struct sk_buff *skb);
+ struct sk_buff *(*gso_segment)(struct sk_buff *skb,
+ int features);
+ int no_policy;
+diff -pruN ../orig-linux-2.6.16.29/include/net/tcp.h ./include/net/tcp.h
+--- ../orig-linux-2.6.16.29/include/net/tcp.h 2006-09-19 13:59:20.000000000
+0100
++++ ./include/net/tcp.h 2006-09-19 13:59:46.000000000 +0100
+@@ -1063,6 +1063,7 @@ extern struct request_sock_ops tcp_reque
+
+ extern int tcp_v4_destroy_sock(struct sock *sk);
+
++extern int tcp_v4_gso_send_check(struct sk_buff *skb);
+ extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features);
+
+ #ifdef CONFIG_PROC_FS
+diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_forward.c
./net/bridge/br_forward.c
+--- ../orig-linux-2.6.16.29/net/bridge/br_forward.c 2006-09-19
13:59:20.000000000 +0100
++++ ./net/bridge/br_forward.c 2006-09-19 13:59:46.000000000 +0100
+@@ -32,7 +32,7 @@ static inline int should_deliver(const s
+ int br_dev_queue_push_xmit(struct sk_buff *skb)
+ {
+ /* drop mtu oversized packets except tso */
+- if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->gso_size)
++ if (skb->len > skb->dev->mtu && !skb_is_gso(skb))
+ kfree_skb(skb);
+ else {
+ #ifdef CONFIG_BRIDGE_NETFILTER
+diff -pruN ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c
./net/bridge/br_netfilter.c
+--- ../orig-linux-2.6.16.29/net/bridge/br_netfilter.c 2006-09-19
13:59:20.000000000 +0100
++++ ./net/bridge/br_netfilter.c 2006-09-19 13:59:46.000000000 +0100
+@@ -743,7 +743,7 @@ static int br_nf_dev_queue_xmit(struct s
+ {
+ if (skb->protocol == htons(ETH_P_IP) &&
+ skb->len > skb->dev->mtu &&
+- !skb_shinfo(skb)->gso_size)
++ !skb_is_gso(skb))
+ return ip_fragment(skb, br_dev_queue_push_xmit);
+ else
+ return br_dev_queue_push_xmit(skb);
+diff -pruN ../orig-linux-2.6.16.29/net/core/dev.c ./net/core/dev.c
+--- ../orig-linux-2.6.16.29/net/core/dev.c 2006-09-19 13:59:20.000000000
+0100
++++ ./net/core/dev.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1083,9 +1083,17 @@ int skb_checksum_help(struct sk_buff *sk
+ unsigned int csum;
+ int ret = 0, offset = skb->h.raw - skb->data;
+
+- if (inward) {
+- skb->ip_summed = CHECKSUM_NONE;
+- goto out;
++ if (inward)
++ goto out_set_summed;
++
++ if (unlikely(skb_shinfo(skb)->gso_size)) {
++ static int warned;
++
++ WARN_ON(!warned);
++ warned = 1;
++
++ /* Let GSO fix up the checksum. */
++ goto out_set_summed;
+ }
+
+ if (skb_cloned(skb)) {
+@@ -1102,6 +1110,8 @@ int skb_checksum_help(struct sk_buff *sk
+ BUG_ON(skb->csum + 2 > offset);
+
+ *(u16*)(skb->h.raw + skb->csum) = csum_fold(csum);
++
++out_set_summed:
+ skb->ip_summed = CHECKSUM_NONE;
+ out:
+ return ret;
+@@ -1122,17 +1132,35 @@ struct sk_buff *skb_gso_segment(struct s
+ struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
+ struct packet_type *ptype;
+ int type = skb->protocol;
++ int err;
+
+ BUG_ON(skb_shinfo(skb)->frag_list);
+- BUG_ON(skb->ip_summed != CHECKSUM_HW);
+
+ skb->mac.raw = skb->data;
+ skb->mac_len = skb->nh.raw - skb->data;
+ __skb_pull(skb, skb->mac_len);
+
++ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
++ static int warned;
++
++ WARN_ON(!warned);
++ warned = 1;
++
++ if (skb_header_cloned(skb) &&
++ (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
++ return ERR_PTR(err);
++ }
++
+ rcu_read_lock();
+ list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type) & 15], list) {
+ if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
++ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
++ err = ptype->gso_send_check(skb);
++ segs = ERR_PTR(err);
++ if (err || skb_gso_ok(skb, features))
++ break;
++ __skb_push(skb, skb->data - skb->nh.raw);
++ }
+ segs = ptype->gso_segment(skb, features);
+ break;
+ }
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/af_inet.c ./net/ipv4/af_inet.c
+--- ../orig-linux-2.6.16.29/net/ipv4/af_inet.c 2006-09-19 13:59:20.000000000
+0100
++++ ./net/ipv4/af_inet.c 2006-09-19 13:59:46.000000000 +0100
+@@ -1085,6 +1085,40 @@ int inet_sk_rebuild_header(struct sock *
+
+ EXPORT_SYMBOL(inet_sk_rebuild_header);
+
++static int inet_gso_send_check(struct sk_buff *skb)
++{
++ struct iphdr *iph;
++ struct net_protocol *ops;
++ int proto;
++ int ihl;
++ int err = -EINVAL;
++
++ if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
++ goto out;
++
++ iph = skb->nh.iph;
++ ihl = iph->ihl * 4;
++ if (ihl < sizeof(*iph))
++ goto out;
++
++ if (unlikely(!pskb_may_pull(skb, ihl)))
++ goto out;
++
++ skb->h.raw = __skb_pull(skb, ihl);
++ iph = skb->nh.iph;
++ proto = iph->protocol & (MAX_INET_PROTOS - 1);
++ err = -EPROTONOSUPPORT;
++
++ rcu_read_lock();
++ ops = rcu_dereference(inet_protos[proto]);
++ if (likely(ops && ops->gso_send_check))
++ err = ops->gso_send_check(skb);
++ rcu_read_unlock();
++
++out:
++ return err;
++}
++
+ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
+ {
+ struct sk_buff *segs = ERR_PTR(-EINVAL);
+@@ -1142,6 +1176,7 @@ static struct net_protocol igmp_protocol
+ static struct net_protocol tcp_protocol = {
+ .handler = tcp_v4_rcv,
+ .err_handler = tcp_v4_err,
++ .gso_send_check = tcp_v4_gso_send_check,
+ .gso_segment = tcp_tso_segment,
+ .no_policy = 1,
+ };
+@@ -1188,6 +1223,7 @@ static int ipv4_proc_init(void);
+ static struct packet_type ip_packet_type = {
+ .type = __constant_htons(ETH_P_IP),
+ .func = ip_rcv,
++ .gso_send_check = inet_gso_send_check,
+ .gso_segment = inet_gso_segment,
+ };
+
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/ip_output.c ./net/ipv4/ip_output.c
+--- ../orig-linux-2.6.16.29/net/ipv4/ip_output.c 2006-09-19
13:59:20.000000000 +0100
++++ ./net/ipv4/ip_output.c 2006-09-19 13:59:46.000000000 +0100
+@@ -210,7 +210,7 @@ static inline int ip_finish_output(struc
+ return dst_output(skb);
+ }
+ #endif
+- if (skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size)
++ if (skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb))
+ return ip_fragment(skb, ip_finish_output2);
+ else
+ return ip_finish_output2(skb);
+@@ -1095,7 +1095,7 @@ ssize_t ip_append_page(struct sock *sk,
+ while (size > 0) {
+ int i;
+
+- if (skb_shinfo(skb)->gso_size)
++ if (skb_is_gso(skb))
+ len = size;
+ else {
+
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/tcp_ipv4.c ./net/ipv4/tcp_ipv4.c
+--- ../orig-linux-2.6.16.29/net/ipv4/tcp_ipv4.c 2006-09-12
19:02:10.000000000 +0100
++++ ./net/ipv4/tcp_ipv4.c 2006-09-19 13:59:46.000000000 +0100
+@@ -495,6 +495,24 @@ void tcp_v4_send_check(struct sock *sk,
+ }
+ }
+
++int tcp_v4_gso_send_check(struct sk_buff *skb)
++{
++ struct iphdr *iph;
++ struct tcphdr *th;
++
++ if (!pskb_may_pull(skb, sizeof(*th)))
++ return -EINVAL;
++
++ iph = skb->nh.iph;
++ th = skb->h.th;
++
++ th->check = 0;
++ th->check = ~tcp_v4_check(th, skb->len, iph->saddr, iph->daddr, 0);
++ skb->csum = offsetof(struct tcphdr, check);
++ skb->ip_summed = CHECKSUM_HW;
++ return 0;
++}
++
+ /*
+ * This routine will send an RST to the other tcp.
+ *
+diff -pruN ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c
./net/ipv4/xfrm4_output.c
+--- ../orig-linux-2.6.16.29/net/ipv4/xfrm4_output.c 2006-09-19
13:59:20.000000000 +0100
++++ ./net/ipv4/xfrm4_output.c 2006-09-19 13:59:46.000000000 +0100
+@@ -195,7 +195,7 @@ static int xfrm4_output_finish(struct sk
+ }
+ #endif
+
+- if (!skb_shinfo(skb)->gso_size)
++ if (!skb_is_gso(skb))
+ return xfrm4_output_finish2(skb);
+
+ skb->protocol = htons(ETH_P_IP);
+diff -pruN ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c
./net/ipv6/ip6_output.c
+--- ../orig-linux-2.6.16.29/net/ipv6/ip6_output.c 2006-09-19
13:59:20.000000000 +0100
++++ ./net/ipv6/ip6_output.c 2006-09-19 13:59:46.000000000 +0100
+@@ -147,7 +147,7 @@ static int ip6_output2(struct sk_buff *s
+
+ int ip6_output(struct sk_buff *skb)
+ {
+- if ((skb->len > dst_mtu(skb->dst) && !skb_shinfo(skb)->gso_size) ||
++ if ((skb->len > dst_mtu(skb->dst) && !skb_is_gso(skb)) ||
+ dst_allfrag(skb->dst))
+ return ip6_fragment(skb, ip6_output2);
+ else
+diff -pruN ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c
./net/ipv6/xfrm6_output.c
+--- ../orig-linux-2.6.16.29/net/ipv6/xfrm6_output.c 2006-09-19
13:59:20.000000000 +0100
++++ ./net/ipv6/xfrm6_output.c 2006-09-19 13:59:46.000000000 +0100
+@@ -179,7 +179,7 @@ static int xfrm6_output_finish(struct sk
+ {
+ struct sk_buff *segs;
+
+- if (!skb_shinfo(skb)->gso_size)
++ if (!skb_is_gso(skb))
+ return xfrm6_output_finish2(skb);
+
+ skb->protocol = htons(ETH_P_IP);
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/net-gso-3-fix-errorcheck.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-gso-3-fix-errorcheck.patch Wed Nov 29
11:07:28 2006 -0700
@@ -0,0 +1,17 @@
+diff -pruN ../orig-linux-2.6.16.29/include/linux/netdevice.h
./include/linux/netdevice.h
+--- ../orig-linux-2.6.16.29/include/linux/netdevice.h 2006-09-19
13:59:46.000000000 +0100
++++ ./include/linux/netdevice.h 2006-09-19 14:05:28.000000000 +0100
+@@ -930,10 +930,10 @@ static inline void netif_tx_lock_bh(stru
+
+ static inline int netif_tx_trylock(struct net_device *dev)
+ {
+- int err = spin_trylock(&dev->_xmit_lock);
+- if (!err)
++ int ok = spin_trylock(&dev->_xmit_lock);
++ if (likely(ok))
+ dev->xmit_lock_owner = smp_processor_id();
+- return err;
++ return ok;
+ }
+
+ static inline void netif_tx_unlock(struct net_device *dev)
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/net-gso-4-kill-warnon.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-gso-4-kill-warnon.patch Wed Nov 29
11:07:28 2006 -0700
@@ -0,0 +1,27 @@
+diff -pruN ../orig-linux-2.6.16.29/net/core/dev.c ./net/core/dev.c
+--- ../orig-linux-2.6.16.29/net/core/dev.c 2006-09-19 13:59:46.000000000
+0100
++++ ./net/core/dev.c 2006-09-19 14:05:32.000000000 +0100
+@@ -1087,11 +1087,6 @@ int skb_checksum_help(struct sk_buff *sk
+ goto out_set_summed;
+
+ if (unlikely(skb_shinfo(skb)->gso_size)) {
+- static int warned;
+-
+- WARN_ON(!warned);
+- warned = 1;
+-
+ /* Let GSO fix up the checksum. */
+ goto out_set_summed;
+ }
+@@ -1141,11 +1136,6 @@ struct sk_buff *skb_gso_segment(struct s
+ __skb_pull(skb, skb->mac_len);
+
+ if (unlikely(skb->ip_summed != CHECKSUM_HW)) {
+- static int warned;
+-
+- WARN_ON(!warned);
+- warned = 1;
+-
+ if (skb_header_cloned(skb) &&
+ (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ return ERR_PTR(err);
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/net-gso-5-rcv-mss.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/net-gso-5-rcv-mss.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,13 @@
+diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
+index 104af5d..1fa1536 100644
+--- a/net/ipv4/tcp_input.c
++++ b/net/ipv4/tcp_input.c
+@@ -127,7 +127,7 @@ static void tcp_measure_rcv_mss(struct s
+ /* skb->len may jitter because of SACKs, even if peer
+ * sends good full-sized frames.
+ */
+- len = skb->len;
++ len = skb_shinfo(skb)->gso_size ?: skb->len;
+ if (len >= icsk->icsk_ack.rcv_mss) {
+ icsk->icsk_ack.rcv_mss = len;
+ } else {
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch Wed Nov
29 11:07:28 2006 -0700
@@ -0,0 +1,292 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c
./arch/i386/pci/mmconfig.c
+--- ../orig-linux-2.6.16.29/arch/i386/pci/mmconfig.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/pci/mmconfig.c 2006-09-21 09:35:27.000000000 +0100
+@@ -12,14 +12,22 @@
+ #include <linux/pci.h>
+ #include <linux/init.h>
+ #include <linux/acpi.h>
++#include <asm/e820.h>
+ #include "pci.h"
+
++/* aperture is up to 256MB but BIOS may reserve less */
++#define MMCONFIG_APER_MIN (2 * 1024*1024)
++#define MMCONFIG_APER_MAX (256 * 1024*1024)
++
++/* Assume systems with more busses have correct MCFG */
++#define MAX_CHECK_BUS 16
++
+ #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))
+
+ /* The base address of the last MMCONFIG device accessed */
+ static u32 mmcfg_last_accessed_device;
+
+-static DECLARE_BITMAP(fallback_slots, 32);
++static DECLARE_BITMAP(fallback_slots, MAX_CHECK_BUS*32);
+
+ /*
+ * Functions for accessing PCI configuration space with MMCONFIG accesses
+@@ -29,8 +37,8 @@ static u32 get_base_addr(unsigned int se
+ int cfg_num = -1;
+ struct acpi_table_mcfg_config *cfg;
+
+- if (seg == 0 && bus == 0 &&
+- test_bit(PCI_SLOT(devfn), fallback_slots))
++ if (seg == 0 && bus < MAX_CHECK_BUS &&
++ test_bit(PCI_SLOT(devfn) + 32*bus, fallback_slots))
+ return 0;
+
+ while (1) {
+@@ -74,8 +82,10 @@ static int pci_mmcfg_read(unsigned int s
+ unsigned long flags;
+ u32 base;
+
+- if (!value || (bus > 255) || (devfn > 255) || (reg > 4095))
++ if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
++ *value = -1;
+ return -EINVAL;
++ }
+
+ base = get_base_addr(seg, bus, devfn);
+ if (!base)
+@@ -146,30 +156,66 @@ static struct pci_raw_ops pci_mmcfg = {
+ Normally this can be expressed in the MCFG by not listing them
+ and assigning suitable _SEGs, but this isn't implemented in some BIOS.
+ Instead try to discover all devices on bus 0 that are unreachable using MM
+- and fallback for them.
+- We only do this for bus 0/seg 0 */
++ and fallback for them. */
+ static __init void unreachable_devices(void)
+ {
+- int i;
++ int i, k;
+ unsigned long flags;
+
+- for (i = 0; i < 32; i++) {
+- u32 val1;
+- u32 addr;
++ for (k = 0; k < MAX_CHECK_BUS; k++) {
++ for (i = 0; i < 32; i++) {
++ u32 val1;
++ u32 addr;
++
++ pci_conf1_read(0, k, PCI_DEVFN(i, 0), 0, 4, &val1);
++ if (val1 == 0xffffffff)
++ continue;
++
++ /* Locking probably not needed, but safer */
++ spin_lock_irqsave(&pci_config_lock, flags);
++ addr = get_base_addr(0, k, PCI_DEVFN(i, 0));
++ if (addr != 0)
++ pci_exp_set_dev_base(addr, k, PCI_DEVFN(i, 0));
++ if (addr == 0 ||
++ readl((u32 __iomem *)mmcfg_virt_addr) != val1) {
++ set_bit(i, fallback_slots);
++ printk(KERN_NOTICE
++ "PCI: No mmconfig possible on %x:%x\n", k, i);
++ }
++ spin_unlock_irqrestore(&pci_config_lock, flags);
++ }
++ }
++}
+
+- pci_conf1_read(0, 0, PCI_DEVFN(i, 0), 0, 4, &val1);
+- if (val1 == 0xffffffff)
++/* NB. Ripped from arch/i386/kernel/setup.c for this Xen bugfix patch. */
++#ifdef CONFIG_XEN
++extern struct e820map machine_e820;
++#define e820 machine_e820
++#endif
++static int __init
++e820_all_mapped(unsigned long s, unsigned long e, unsigned type)
++{
++ u64 start = s;
++ u64 end = e;
++ int i;
++ for (i = 0; i < e820.nr_map; i++) {
++ struct e820entry *ei = &e820.map[i];
++ if (type && ei->type != type)
+ continue;
+-
+- /* Locking probably not needed, but safer */
+- spin_lock_irqsave(&pci_config_lock, flags);
+- addr = get_base_addr(0, 0, PCI_DEVFN(i, 0));
+- if (addr != 0)
+- pci_exp_set_dev_base(addr, 0, PCI_DEVFN(i, 0));
+- if (addr == 0 || readl((u32 __iomem *)mmcfg_virt_addr) != val1)
+- set_bit(i, fallback_slots);
+- spin_unlock_irqrestore(&pci_config_lock, flags);
++ /* is the region (part) in overlap with the current region ?*/
++ if (ei->addr >= end || ei->addr + ei->size <= start)
++ continue;
++ /* if the region is at the beginning of <start,end> we move
++ * start to the end of the region since it's ok until there
++ */
++ if (ei->addr <= start)
++ start = ei->addr + ei->size;
++ /* if start is now at or beyond end, we're done, full
++ * coverage */
++ if (start >= end)
++ return 1; /* we're done */
+ }
++ return 0;
+ }
+
+ static int __init pci_mmcfg_init(void)
+@@ -183,6 +229,15 @@ static int __init pci_mmcfg_init(void)
+ (pci_mmcfg_config[0].base_address == 0))
+ goto out;
+
++ if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
++ pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
++ E820_RESERVED)) {
++ printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not
E820-reserved\n",
++ pci_mmcfg_config[0].base_address);
++ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
++ goto out;
++ }
++
+ printk(KERN_INFO "PCI: Using MMCONFIG\n");
+ raw_pci_ops = &pci_mmcfg;
+ pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
+diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c
./arch/x86_64/pci/mmconfig.c
+--- ../orig-linux-2.6.16.29/arch/x86_64/pci/mmconfig.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/x86_64/pci/mmconfig.c 2006-09-21 09:35:40.000000000 +0100
+@@ -9,11 +9,19 @@
+ #include <linux/init.h>
+ #include <linux/acpi.h>
+ #include <linux/bitmap.h>
++#include <asm/e820.h>
++
+ #include "pci.h"
+
+-#define MMCONFIG_APER_SIZE (256*1024*1024)
++/* aperture is up to 256MB but BIOS may reserve less */
++#define MMCONFIG_APER_MIN (2 * 1024*1024)
++#define MMCONFIG_APER_MAX (256 * 1024*1024)
++
++/* Verify the first 16 busses. We assume that systems with more busses
++ get MCFG right. */
++#define MAX_CHECK_BUS 16
+
+-static DECLARE_BITMAP(fallback_slots, 32);
++static DECLARE_BITMAP(fallback_slots, 32*MAX_CHECK_BUS);
+
+ /* Static virtual mapping of the MMCONFIG aperture */
+ struct mmcfg_virt {
+@@ -55,7 +63,8 @@ static char __iomem *get_virt(unsigned i
+ static char __iomem *pci_dev_base(unsigned int seg, unsigned int bus,
unsigned int devfn)
+ {
+ char __iomem *addr;
+- if (seg == 0 && bus == 0 && test_bit(PCI_SLOT(devfn), &fallback_slots))
++ if (seg == 0 && bus < MAX_CHECK_BUS &&
++ test_bit(32*bus + PCI_SLOT(devfn), fallback_slots))
+ return NULL;
+ addr = get_virt(seg, bus);
+ if (!addr)
+@@ -69,8 +78,10 @@ static int pci_mmcfg_read(unsigned int s
+ char __iomem *addr;
+
+ /* Why do we have this when nobody checks it. How about a BUG()!? -AK */
+- if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
++ if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095))) {
++ *value = -1;
+ return -EINVAL;
++ }
+
+ addr = pci_dev_base(seg, bus, devfn);
+ if (!addr)
+@@ -129,23 +140,56 @@ static struct pci_raw_ops pci_mmcfg = {
+ Normally this can be expressed in the MCFG by not listing them
+ and assigning suitable _SEGs, but this isn't implemented in some BIOS.
+ Instead try to discover all devices on bus 0 that are unreachable using MM
+- and fallback for them.
+- We only do this for bus 0/seg 0 */
++ and fallback for them. */
+ static __init void unreachable_devices(void)
+ {
+- int i;
+- for (i = 0; i < 32; i++) {
+- u32 val1;
+- char __iomem *addr;
++ int i, k;
++ /* Use the max bus number from ACPI here? */
++ for (k = 0; k < MAX_CHECK_BUS; k++) {
++ for (i = 0; i < 32; i++) {
++ u32 val1;
++ char __iomem *addr;
++
++ pci_conf1_read(0, k, PCI_DEVFN(i,0), 0, 4, &val1);
++ if (val1 == 0xffffffff)
++ continue;
++ addr = pci_dev_base(0, k, PCI_DEVFN(i, 0));
++ if (addr == NULL|| readl(addr) != val1) {
++ set_bit(i + 32*k, fallback_slots);
++ printk(KERN_NOTICE
++ "PCI: No mmconfig possible on device %x:%x\n",
++ k, i);
++ }
++ }
++ }
++}
+
+- pci_conf1_read(0, 0, PCI_DEVFN(i,0), 0, 4, &val1);
+- if (val1 == 0xffffffff)
++/* NB. Ripped from arch/x86_64/kernel/e820.c for this Xen bugfix patch. */
++#ifdef CONFIG_XEN
++extern struct e820map machine_e820;
++#define e820 machine_e820
++#endif
++static int __init e820_all_mapped(unsigned long start, unsigned long end,
unsigned type)
++{
++ int i;
++ for (i = 0; i < e820.nr_map; i++) {
++ struct e820entry *ei = &e820.map[i];
++ if (type && ei->type != type)
+ continue;
+- addr = pci_dev_base(0, 0, PCI_DEVFN(i, 0));
+- if (addr == NULL|| readl(addr) != val1) {
+- set_bit(i, &fallback_slots);
+- }
++ /* is the region (part) in overlap with the current region ?*/
++ if (ei->addr >= end || ei->addr + ei->size <= start)
++ continue;
++
++ /* if the region is at the beginning of <start,end> we move
++ * start to the end of the region since it's ok until there
++ */
++ if (ei->addr <= start)
++ start = ei->addr + ei->size;
++ /* if start is now at or beyond end, we're done, full coverage
*/
++ if (start >= end)
++ return 1; /* we're done */
+ }
++ return 0;
+ }
+
+ static int __init pci_mmcfg_init(void)
+@@ -161,6 +205,15 @@ static int __init pci_mmcfg_init(void)
+ (pci_mmcfg_config[0].base_address == 0))
+ return 0;
+
++ if (!e820_all_mapped(pci_mmcfg_config[0].base_address,
++ pci_mmcfg_config[0].base_address + MMCONFIG_APER_MIN,
++ E820_RESERVED)) {
++ printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %x is not
E820-reserved\n",
++ pci_mmcfg_config[0].base_address);
++ printk(KERN_ERR "PCI: Not using MMCONFIG.\n");
++ return 0;
++ }
++
+ /* RED-PEN i386 doesn't do _nocache right now */
+ pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) *
pci_mmcfg_config_num, GFP_KERNEL);
+ if (pci_mmcfg_virt == NULL) {
+@@ -169,7 +222,8 @@ static int __init pci_mmcfg_init(void)
+ }
+ for (i = 0; i < pci_mmcfg_config_num; ++i) {
+ pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
+- pci_mmcfg_virt[i].virt =
ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
++ pci_mmcfg_virt[i].virt =
ioremap_nocache(pci_mmcfg_config[i].base_address,
++ MMCONFIG_APER_MAX);
+ if (!pci_mmcfg_virt[i].virt) {
+ printk("PCI: Cannot map mmconfig aperture for segment
%d\n",
+ pci_mmcfg_config[i].pci_segment_group_number);
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/pmd-shared.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/pmd-shared.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,111 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/mm/pageattr.c
./arch/i386/mm/pageattr.c
+--- ../orig-linux-2.6.16.29/arch/i386/mm/pageattr.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/mm/pageattr.c 2006-09-19 14:05:35.000000000 +0100
+@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
+ unsigned long flags;
+
+ set_pte_atomic(kpte, pte); /* change init_mm */
+- if (PTRS_PER_PMD > 1)
++ if (HAVE_SHARED_KERNEL_PMD)
+ return;
+
+ spin_lock_irqsave(&pgd_lock, flags);
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/mm/pgtable.c
./arch/i386/mm/pgtable.c
+--- ../orig-linux-2.6.16.29/arch/i386/mm/pgtable.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/mm/pgtable.c 2006-09-19 14:05:35.000000000 +0100
+@@ -215,9 +215,10 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
+ spin_lock_irqsave(&pgd_lock, flags);
+ }
+
+- clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+- swapper_pg_dir + USER_PTRS_PER_PGD,
+- KERNEL_PGD_PTRS);
++ if (PTRS_PER_PMD == 1 || HAVE_SHARED_KERNEL_PMD)
++ clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
++ swapper_pg_dir + USER_PTRS_PER_PGD,
++ KERNEL_PGD_PTRS);
+ if (PTRS_PER_PMD > 1)
+ return;
+
+@@ -249,6 +250,30 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
+ goto out_oom;
+ set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
+ }
++
++ if (!HAVE_SHARED_KERNEL_PMD) {
++ unsigned long flags;
++
++ for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
++ pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
++ if (!pmd)
++ goto out_oom;
++ set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
++ }
++
++ spin_lock_irqsave(&pgd_lock, flags);
++ for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
++ unsigned long v = (unsigned long)i << PGDIR_SHIFT;
++ pgd_t *kpgd = pgd_offset_k(v);
++ pud_t *kpud = pud_offset(kpgd, v);
++ pmd_t *kpmd = pmd_offset(kpud, v);
++ pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
++ memcpy(pmd, kpmd, PAGE_SIZE);
++ }
++ pgd_list_add(pgd);
++ spin_unlock_irqrestore(&pgd_lock, flags);
++ }
++
+ return pgd;
+
+ out_oom:
+@@ -263,9 +288,23 @@ void pgd_free(pgd_t *pgd)
+ int i;
+
+ /* in the PAE case user pgd entries are overwritten before usage */
+- if (PTRS_PER_PMD > 1)
+- for (i = 0; i < USER_PTRS_PER_PGD; ++i)
+- kmem_cache_free(pmd_cache, (void
*)__va(pgd_val(pgd[i])-1));
++ if (PTRS_PER_PMD > 1) {
++ for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
++ pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
++ kmem_cache_free(pmd_cache, pmd);
++ }
++ if (!HAVE_SHARED_KERNEL_PMD) {
++ unsigned long flags;
++ spin_lock_irqsave(&pgd_lock, flags);
++ pgd_list_del(pgd);
++ spin_unlock_irqrestore(&pgd_lock, flags);
++ for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
++ pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
++ memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
++ kmem_cache_free(pmd_cache, pmd);
++ }
++ }
++ }
+ /* in the non-PAE case, free_pgtables() clears user pgd entries */
+ kmem_cache_free(pgd_cache, pgd);
+ }
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/pgtable-2level-defs.h
./include/asm-i386/pgtable-2level-defs.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/pgtable-2level-defs.h
2006-09-12 19:02:10.000000000 +0100
++++ ./include/asm-i386/pgtable-2level-defs.h 2006-09-19 14:05:35.000000000
+0100
+@@ -1,6 +1,8 @@
+ #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
+ #define _I386_PGTABLE_2LEVEL_DEFS_H
+
++#define HAVE_SHARED_KERNEL_PMD 0
++
+ /*
+ * traditional i386 two-level paging structure:
+ */
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/pgtable-3level-defs.h
./include/asm-i386/pgtable-3level-defs.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/pgtable-3level-defs.h
2006-09-12 19:02:10.000000000 +0100
++++ ./include/asm-i386/pgtable-3level-defs.h 2006-09-19 14:05:35.000000000
+0100
+@@ -1,6 +1,8 @@
+ #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
+ #define _I386_PGTABLE_3LEVEL_DEFS_H
+
++#define HAVE_SHARED_KERNEL_PMD 1
++
+ /*
+ * PGDIR_SHIFT determines what a top-level page table entry can map
+ */
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/rcu_needs_cpu.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/rcu_needs_cpu.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,35 @@
+diff -pruN ../orig-linux-2.6.16.29/include/linux/rcupdate.h
./include/linux/rcupdate.h
+--- ../orig-linux-2.6.16.29/include/linux/rcupdate.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/linux/rcupdate.h 2006-09-19 14:05:39.000000000 +0100
+@@ -134,6 +134,7 @@ static inline void rcu_bh_qsctr_inc(int
+ }
+
+ extern int rcu_pending(int cpu);
++extern int rcu_needs_cpu(int cpu);
+
+ /**
+ * rcu_read_lock - mark the beginning of an RCU read-side critical section.
+diff -pruN ../orig-linux-2.6.16.29/kernel/rcupdate.c ./kernel/rcupdate.c
+--- ../orig-linux-2.6.16.29/kernel/rcupdate.c 2006-09-12 19:02:10.000000000
+0100
++++ ./kernel/rcupdate.c 2006-09-19 14:05:39.000000000 +0100
+@@ -485,6 +485,20 @@ int rcu_pending(int cpu)
+ __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
+ }
+
++/*
++ * Check to see if any future RCU-related work will need to be done
++ * by the current CPU, even if none need be done immediately, returning
++ * 1 if so. This function is part of the RCU implementation; it is -not-
++ * an exported member of the RCU API.
++ */
++int rcu_needs_cpu(int cpu)
++{
++ struct rcu_data *rdp = &per_cpu(rcu_data, cpu);
++ struct rcu_data *rdp_bh = &per_cpu(rcu_bh_data, cpu);
++
++ return (!!rdp->curlist || !!rdp_bh->curlist || rcu_pending(cpu));
++}
++
+ void rcu_check_callbacks(int cpu, int user)
+ {
+ if (user ||
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++
b/patches/linux-2.6.16.33/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,30 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/entry.S
./arch/i386/kernel/entry.S
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/entry.S 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/kernel/entry.S 2006-09-19 14:05:44.000000000 +0100
+@@ -177,7 +177,7 @@ need_resched:
+
+ # sysenter call handler stub
+ ENTRY(sysenter_entry)
+- movl TSS_sysenter_esp0(%esp),%esp
++ movl SYSENTER_stack_esp0(%esp),%esp
+ sysenter_past_esp:
+ sti
+ pushl $(__USER_DS)
+@@ -492,7 +492,7 @@ device_not_available_emulate:
+ * that sets up the real kernel stack. Check here, since we can't
+ * allow the wrong stack to be used.
+ *
+- * "TSS_sysenter_esp0+12" is because the NMI/debug handler will have
++ * "SYSENTER_stack_esp0+12" is because the NMI/debug handler will have
+ * already pushed 3 words if it hits on the sysenter instruction:
+ * eflags, cs and eip.
+ *
+@@ -504,7 +504,7 @@ device_not_available_emulate:
+ cmpw $__KERNEL_CS,4(%esp); \
+ jne ok; \
+ label: \
+- movl TSS_sysenter_esp0+offset(%esp),%esp; \
++ movl SYSENTER_stack_esp0+offset(%esp),%esp; \
+ pushfl; \
+ pushl $__KERNEL_CS; \
+ pushl $sysenter_past_esp
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/series
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/series Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,27 @@
+blktap-aio-16_03_06.patch
+device_bind.patch
+fix-hz-suspend.patch
+fix-ide-cd-pio-mode.patch
+i386-mach-io-check-nmi.patch
+ipv6-no-autoconf.patch
+net-csum.patch
+net-gso-0-base.patch
+net-gso-1-check-dodgy.patch
+net-gso-2-checksum-fix.patch
+net-gso-3-fix-errorcheck.patch
+net-gso-4-kill-warnon.patch
+net-gso-5-rcv-mss.patch
+pci-mmconfig-fix-from-2.6.17.patch
+pmd-shared.patch
+rcu_needs_cpu.patch
+rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch
+smp-alts.patch
+tpm_plugin_2.6.17.patch
+x86-increase-interrupt-vector-range.patch
+xen-hotplug.patch
+xenoprof-generic.patch
+x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
+x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
+x86-elfnote-as-preprocessor-macro.patch
+vsnprintf.patch
+kasprintf.patch
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/smp-alts.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/smp-alts.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,591 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/Kconfig ./arch/i386/Kconfig
+--- ../orig-linux-2.6.16.29/arch/i386/Kconfig 2006-09-12 19:02:10.000000000
+0100
++++ ./arch/i386/Kconfig 2006-09-19 14:05:48.000000000 +0100
+@@ -202,6 +202,19 @@ config SMP
+
+ If you don't know what to do here, say N.
+
++config SMP_ALTERNATIVES
++ bool "SMP alternatives support (EXPERIMENTAL)"
++ depends on SMP && EXPERIMENTAL
++ help
++ Try to reduce the overhead of running an SMP kernel on a uniprocessor
++ host slightly by replacing certain key instruction sequences
++ according to whether we currently have more than one CPU available.
++ This should provide a noticeable boost to performance when
++ running SMP kernels on UP machines, and have negligible impact
++ when running on an true SMP host.
++
++ If unsure, say N.
++
+ config NR_CPUS
+ int "Maximum number of CPUs (2-255)"
+ range 2 255
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/Makefile
./arch/i386/kernel/Makefile
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/Makefile 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/kernel/Makefile 2006-09-19 14:05:48.000000000 +0100
+@@ -37,6 +37,7 @@ obj-$(CONFIG_EFI) += efi.o efi_stub.o
+ obj-$(CONFIG_DOUBLEFAULT) += doublefault.o
+ obj-$(CONFIG_VM86) += vm86.o
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
++obj-$(CONFIG_SMP_ALTERNATIVES) += smpalts.o
+
+ EXTRA_AFLAGS := -traditional
+
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/smpalts.c
./arch/i386/kernel/smpalts.c
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/smpalts.c 1970-01-01
01:00:00.000000000 +0100
++++ ./arch/i386/kernel/smpalts.c 2006-09-19 14:05:48.000000000 +0100
+@@ -0,0 +1,85 @@
++#include <linux/kernel.h>
++#include <asm/system.h>
++#include <asm/smp_alt.h>
++#include <asm/processor.h>
++#include <asm/string.h>
++
++struct smp_replacement_record {
++ unsigned char targ_size;
++ unsigned char smp1_size;
++ unsigned char smp2_size;
++ unsigned char up_size;
++ unsigned char feature;
++ unsigned char data[0];
++};
++
++struct smp_alternative_record {
++ void *targ_start;
++ struct smp_replacement_record *repl;
++};
++
++extern struct smp_alternative_record __start_smp_alternatives_table,
++ __stop_smp_alternatives_table;
++extern unsigned long __init_begin, __init_end;
++
++void prepare_for_smp(void)
++{
++ struct smp_alternative_record *r;
++ printk(KERN_INFO "Enabling SMP...\n");
++ for (r = &__start_smp_alternatives_table;
++ r != &__stop_smp_alternatives_table;
++ r++) {
++ BUG_ON(r->repl->targ_size < r->repl->smp1_size);
++ BUG_ON(r->repl->targ_size < r->repl->smp2_size);
++ BUG_ON(r->repl->targ_size < r->repl->up_size);
++ if (system_state == SYSTEM_RUNNING &&
++ r->targ_start >= (void *)&__init_begin &&
++ r->targ_start < (void *)&__init_end)
++ continue;
++ if (r->repl->feature != (unsigned char)-1 &&
++ boot_cpu_has(r->repl->feature)) {
++ memcpy(r->targ_start,
++ r->repl->data + r->repl->smp1_size,
++ r->repl->smp2_size);
++ memset(r->targ_start + r->repl->smp2_size,
++ 0x90,
++ r->repl->targ_size - r->repl->smp2_size);
++ } else {
++ memcpy(r->targ_start,
++ r->repl->data,
++ r->repl->smp1_size);
++ memset(r->targ_start + r->repl->smp1_size,
++ 0x90,
++ r->repl->targ_size - r->repl->smp1_size);
++ }
++ }
++ /* Paranoia */
++ asm volatile ("jmp 1f\n1:");
++ mb();
++}
++
++void unprepare_for_smp(void)
++{
++ struct smp_alternative_record *r;
++ printk(KERN_INFO "Disabling SMP...\n");
++ for (r = &__start_smp_alternatives_table;
++ r != &__stop_smp_alternatives_table;
++ r++) {
++ BUG_ON(r->repl->targ_size < r->repl->smp1_size);
++ BUG_ON(r->repl->targ_size < r->repl->smp2_size);
++ BUG_ON(r->repl->targ_size < r->repl->up_size);
++ if (system_state == SYSTEM_RUNNING &&
++ r->targ_start >= (void *)&__init_begin &&
++ r->targ_start < (void *)&__init_end)
++ continue;
++ memcpy(r->targ_start,
++ r->repl->data + r->repl->smp1_size + r->repl->smp2_size,
++ r->repl->up_size);
++ memset(r->targ_start + r->repl->up_size,
++ 0x90,
++ r->repl->targ_size - r->repl->up_size);
++ }
++ /* Paranoia */
++ asm volatile ("jmp 1f\n1:");
++ mb();
++}
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/smpboot.c
./arch/i386/kernel/smpboot.c
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/smpboot.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/kernel/smpboot.c 2006-09-19 14:05:48.000000000 +0100
+@@ -1218,6 +1218,11 @@ static void __init smp_boot_cpus(unsigne
+ if (max_cpus <= cpucount+1)
+ continue;
+
++#ifdef CONFIG_SMP_ALTERNATIVES
++ if (kicked == 1)
++ prepare_for_smp();
++#endif
++
+ if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
+ printk("CPU #%d not responding - cannot use it.\n",
+ apicid);
+@@ -1396,6 +1401,11 @@ int __devinit __cpu_up(unsigned int cpu)
+ return -EIO;
+ }
+
++#ifdef CONFIG_SMP_ALTERNATIVES
++ if (num_online_cpus() == 1)
++ prepare_for_smp();
++#endif
++
+ local_irq_enable();
+ per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+ /* Unleash the CPU! */
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/vmlinux.lds.S
./arch/i386/kernel/vmlinux.lds.S
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/vmlinux.lds.S 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/kernel/vmlinux.lds.S 2006-09-19 14:05:48.000000000 +0100
+@@ -34,6 +34,13 @@ SECTIONS
+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
+ __stop___ex_table = .;
+
++ . = ALIGN(16);
++ __start_smp_alternatives_table = .;
++ __smp_alternatives : { *(__smp_alternatives) }
++ __stop_smp_alternatives_table = .;
++
++ __smp_replacements : { *(__smp_replacements) }
++
+ RODATA
+
+ /* writeable */
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/atomic.h
./include/asm-i386/atomic.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/atomic.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-i386/atomic.h 2006-09-19 14:05:48.000000000 +0100
+@@ -4,18 +4,13 @@
+ #include <linux/config.h>
+ #include <linux/compiler.h>
+ #include <asm/processor.h>
++#include <asm/smp_alt.h>
+
+ /*
+ * Atomic operations that C can't guarantee us. Useful for
+ * resource counting etc..
+ */
+
+-#ifdef CONFIG_SMP
+-#define LOCK "lock ; "
+-#else
+-#define LOCK ""
+-#endif
+-
+ /*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/bitops.h
./include/asm-i386/bitops.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/bitops.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-i386/bitops.h 2006-09-19 14:05:48.000000000 +0100
+@@ -7,6 +7,7 @@
+
+ #include <linux/config.h>
+ #include <linux/compiler.h>
++#include <asm/smp_alt.h>
+
+ /*
+ * These have to be done with inline assembly: that way the bit-setting
+@@ -16,12 +17,6 @@
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+-#ifdef CONFIG_SMP
+-#define LOCK_PREFIX "lock ; "
+-#else
+-#define LOCK_PREFIX ""
+-#endif
+-
+ #define ADDR (*(volatile long *) addr)
+
+ /**
+@@ -41,7 +36,7 @@
+ */
+ static inline void set_bit(int nr, volatile unsigned long * addr)
+ {
+- __asm__ __volatile__( LOCK_PREFIX
++ __asm__ __volatile__( LOCK
+ "btsl %1,%0"
+ :"+m" (ADDR)
+ :"Ir" (nr));
+@@ -76,7 +71,7 @@ static inline void __set_bit(int nr, vol
+ */
+ static inline void clear_bit(int nr, volatile unsigned long * addr)
+ {
+- __asm__ __volatile__( LOCK_PREFIX
++ __asm__ __volatile__( LOCK
+ "btrl %1,%0"
+ :"+m" (ADDR)
+ :"Ir" (nr));
+@@ -121,7 +116,7 @@ static inline void __change_bit(int nr,
+ */
+ static inline void change_bit(int nr, volatile unsigned long * addr)
+ {
+- __asm__ __volatile__( LOCK_PREFIX
++ __asm__ __volatile__( LOCK
+ "btcl %1,%0"
+ :"+m" (ADDR)
+ :"Ir" (nr));
+@@ -140,7 +135,7 @@ static inline int test_and_set_bit(int n
+ {
+ int oldbit;
+
+- __asm__ __volatile__( LOCK_PREFIX
++ __asm__ __volatile__( LOCK
+ "btsl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"+m" (ADDR)
+ :"Ir" (nr) : "memory");
+@@ -180,7 +175,7 @@ static inline int test_and_clear_bit(int
+ {
+ int oldbit;
+
+- __asm__ __volatile__( LOCK_PREFIX
++ __asm__ __volatile__( LOCK
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"+m" (ADDR)
+ :"Ir" (nr) : "memory");
+@@ -231,7 +226,7 @@ static inline int test_and_change_bit(in
+ {
+ int oldbit;
+
+- __asm__ __volatile__( LOCK_PREFIX
++ __asm__ __volatile__( LOCK
+ "btcl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"+m" (ADDR)
+ :"Ir" (nr) : "memory");
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/futex.h
./include/asm-i386/futex.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/futex.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-i386/futex.h 2006-09-19 14:05:48.000000000 +0100
+@@ -28,7 +28,7 @@
+ "1: movl %2, %0\n\
+ movl %0, %3\n" \
+ insn "\n" \
+-"2: " LOCK_PREFIX "cmpxchgl %3, %2\n\
++"2: " LOCK "cmpxchgl %3, %2\n\
+ jnz 1b\n\
+ 3: .section .fixup,\"ax\"\n\
+ 4: mov %5, %1\n\
+@@ -68,7 +68,7 @@ futex_atomic_op_inuser (int encoded_op,
+ #endif
+ switch (op) {
+ case FUTEX_OP_ADD:
+- __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret,
++ __futex_atomic_op1(LOCK "xaddl %0, %2", ret,
+ oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/rwsem.h
./include/asm-i386/rwsem.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/rwsem.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-i386/rwsem.h 2006-09-19 14:05:48.000000000 +0100
+@@ -40,6 +40,7 @@
+
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
++#include <asm/smp_alt.h>
+
+ struct rwsem_waiter;
+
+@@ -99,7 +100,7 @@ static inline void __down_read(struct rw
+ {
+ __asm__ __volatile__(
+ "# beginning down_read\n\t"
+-LOCK_PREFIX " incl (%%eax)\n\t" /* adds 0x00000001, returns the old
value */
++LOCK " incl (%%eax)\n\t" /* adds 0x00000001, returns the old
value */
+ " js 2f\n\t" /* jump if we weren't granted the lock */
+ "1:\n\t"
+ LOCK_SECTION_START("")
+@@ -130,7 +131,7 @@ static inline int __down_read_trylock(st
+ " movl %1,%2\n\t"
+ " addl %3,%2\n\t"
+ " jle 2f\n\t"
+-LOCK_PREFIX " cmpxchgl %2,%0\n\t"
++LOCK " cmpxchgl %2,%0\n\t"
+ " jnz 1b\n\t"
+ "2:\n\t"
+ "# ending __down_read_trylock\n\t"
+@@ -150,7 +151,7 @@ static inline void __down_write(struct r
+ tmp = RWSEM_ACTIVE_WRITE_BIAS;
+ __asm__ __volatile__(
+ "# beginning down_write\n\t"
+-LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns
the old value */
++LOCK " xadd %%edx,(%%eax)\n\t" /* subtract 0x0000ffff, returns
the old value */
+ " testl %%edx,%%edx\n\t" /* was the count 0 before? */
+ " jnz 2f\n\t" /* jump if we weren't granted the lock */
+ "1:\n\t"
+@@ -188,7 +189,7 @@ static inline void __up_read(struct rw_s
+ __s32 tmp = -RWSEM_ACTIVE_READ_BIAS;
+ __asm__ __volatile__(
+ "# beginning __up_read\n\t"
+-LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" /* subtracts 1, returns the old
value */
++LOCK " xadd %%edx,(%%eax)\n\t" /* subtracts 1, returns the old
value */
+ " js 2f\n\t" /* jump if the lock is being waited upon */
+ "1:\n\t"
+ LOCK_SECTION_START("")
+@@ -214,7 +215,7 @@ static inline void __up_write(struct rw_
+ __asm__ __volatile__(
+ "# beginning __up_write\n\t"
+ " movl %2,%%edx\n\t"
+-LOCK_PREFIX " xaddl %%edx,(%%eax)\n\t" /* tries to transition
0xffff0001 -> 0x00000000 */
++LOCK " xaddl %%edx,(%%eax)\n\t" /* tries to transition
0xffff0001 -> 0x00000000 */
+ " jnz 2f\n\t" /* jump if the lock is being waited upon */
+ "1:\n\t"
+ LOCK_SECTION_START("")
+@@ -239,7 +240,7 @@ static inline void __downgrade_write(str
+ {
+ __asm__ __volatile__(
+ "# beginning __downgrade_write\n\t"
+-LOCK_PREFIX " addl %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 ->
0xYYYY0001 */
++LOCK " addl %2,(%%eax)\n\t" /* transitions 0xZZZZ0001 ->
0xYYYY0001 */
+ " js 2f\n\t" /* jump if the lock is being waited upon */
+ "1:\n\t"
+ LOCK_SECTION_START("")
+@@ -263,7 +264,7 @@ LOCK_PREFIX " addl %2,(%%eax)\n\t"
+ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+ {
+ __asm__ __volatile__(
+-LOCK_PREFIX "addl %1,%0"
++LOCK "addl %1,%0"
+ : "=m"(sem->count)
+ : "ir"(delta), "m"(sem->count));
+ }
+@@ -276,7 +277,7 @@ static inline int rwsem_atomic_update(in
+ int tmp = delta;
+
+ __asm__ __volatile__(
+-LOCK_PREFIX "xadd %0,(%2)"
++LOCK "xadd %0,(%2)"
+ : "+r"(tmp), "=m"(sem->count)
+ : "r"(sem), "m"(sem->count)
+ : "memory");
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/smp_alt.h
./include/asm-i386/smp_alt.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/smp_alt.h 1970-01-01
01:00:00.000000000 +0100
++++ ./include/asm-i386/smp_alt.h 2006-09-19 14:05:48.000000000 +0100
+@@ -0,0 +1,32 @@
++#ifndef __ASM_SMP_ALT_H__
++#define __ASM_SMP_ALT_H__
++
++#include <linux/config.h>
++
++#ifdef CONFIG_SMP
++#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
++#define LOCK \
++ "6677: nop\n" \
++ ".section __smp_alternatives,\"a\"\n" \
++ ".long 6677b\n" \
++ ".long 6678f\n" \
++ ".previous\n" \
++ ".section __smp_replacements,\"a\"\n" \
++ "6678: .byte 1\n" \
++ ".byte 1\n" \
++ ".byte 0\n" \
++ ".byte 1\n" \
++ ".byte -1\n" \
++ "lock\n" \
++ "nop\n" \
++ ".previous\n"
++void prepare_for_smp(void);
++void unprepare_for_smp(void);
++#else
++#define LOCK "lock ; "
++#endif
++#else
++#define LOCK ""
++#endif
++
++#endif /* __ASM_SMP_ALT_H__ */
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/spinlock.h
./include/asm-i386/spinlock.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/spinlock.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-i386/spinlock.h 2006-09-19 14:05:48.000000000 +0100
+@@ -6,6 +6,7 @@
+ #include <asm/page.h>
+ #include <linux/config.h>
+ #include <linux/compiler.h>
++#include <asm/smp_alt.h>
+
+ /*
+ * Your basic SMP spinlocks, allowing only a single CPU anywhere
+@@ -23,7 +24,8 @@
+
+ #define __raw_spin_lock_string \
+ "\n1:\t" \
+- "lock ; decb %0\n\t" \
++ LOCK \
++ "decb %0\n\t" \
+ "jns 3f\n" \
+ "2:\t" \
+ "rep;nop\n\t" \
+@@ -34,7 +36,8 @@
+
+ #define __raw_spin_lock_string_flags \
+ "\n1:\t" \
+- "lock ; decb %0\n\t" \
++ LOCK \
++ "decb %0\n\t" \
+ "jns 4f\n\t" \
+ "2:\t" \
+ "testl $0x200, %1\n\t" \
+@@ -65,10 +68,34 @@ static inline void __raw_spin_lock_flags
+ static inline int __raw_spin_trylock(raw_spinlock_t *lock)
+ {
+ char oldval;
++#ifdef CONFIG_SMP_ALTERNATIVES
+ __asm__ __volatile__(
+- "xchgb %b0,%1"
++ "1:movb %1,%b0\n"
++ "movb $0,%1\n"
++ "2:"
++ ".section __smp_alternatives,\"a\"\n"
++ ".long 1b\n"
++ ".long 3f\n"
++ ".previous\n"
++ ".section __smp_replacements,\"a\"\n"
++ "3: .byte 2b - 1b\n"
++ ".byte 5f-4f\n"
++ ".byte 0\n"
++ ".byte 6f-5f\n"
++ ".byte -1\n"
++ "4: xchgb %b0,%1\n"
++ "5: movb %1,%b0\n"
++ "movb $0,%1\n"
++ "6:\n"
++ ".previous\n"
+ :"=q" (oldval), "=m" (lock->slock)
+ :"0" (0) : "memory");
++#else
++ __asm__ __volatile__(
++ "xchgb %b0,%1\n"
++ :"=q" (oldval), "=m" (lock->slock)
++ :"0" (0) : "memory");
++#endif
+ return oldval > 0;
+ }
+
+@@ -178,12 +205,12 @@ static inline int __raw_write_trylock(ra
+
+ static inline void __raw_read_unlock(raw_rwlock_t *rw)
+ {
+- asm volatile("lock ; incl %0" :"=m" (rw->lock) : : "memory");
++ asm volatile(LOCK "incl %0" :"=m" (rw->lock) : : "memory");
+ }
+
+ static inline void __raw_write_unlock(raw_rwlock_t *rw)
+ {
+- asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ", %0"
++ asm volatile(LOCK "addl $" RW_LOCK_BIAS_STR ", %0"
+ : "=m" (rw->lock) : : "memory");
+ }
+
+diff -pruN ../orig-linux-2.6.16.29/include/asm-i386/system.h
./include/asm-i386/system.h
+--- ../orig-linux-2.6.16.29/include/asm-i386/system.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-i386/system.h 2006-09-19 14:05:48.000000000 +0100
+@@ -5,7 +5,7 @@
+ #include <linux/kernel.h>
+ #include <asm/segment.h>
+ #include <asm/cpufeature.h>
+-#include <linux/bitops.h> /* for LOCK_PREFIX */
++#include <asm/smp_alt.h>
+
+ #ifdef __KERNEL__
+
+@@ -271,19 +271,19 @@ static inline unsigned long __cmpxchg(vo
+ unsigned long prev;
+ switch (size) {
+ case 1:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
++ __asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ case 2:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
++ __asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
+ : "=a"(prev)
+ : "r"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ case 4:
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
++ __asm__ __volatile__(LOCK "cmpxchgl %1,%2"
+ : "=a"(prev)
+ : "r"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+@@ -336,7 +336,7 @@ static inline unsigned long long __cmpxc
+ unsigned long long new)
+ {
+ unsigned long long prev;
+- __asm__ __volatile__(LOCK_PREFIX "cmpxchg8b %3"
++ __asm__ __volatile__(LOCK "cmpxchg8b %3"
+ : "=A"(prev)
+ : "b"((unsigned long)new),
+ "c"((unsigned long)(new >> 32)),
+@@ -503,11 +503,55 @@ struct alt_instr {
+ #endif
+
+ #ifdef CONFIG_SMP
++#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
++#define smp_alt_mb(instr) \
++__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
++ ".section __smp_alternatives,\"a\"\n" \
++ ".long 6667b\n" \
++ ".long 6673f\n" \
++ ".previous\n" \
++ ".section __smp_replacements,\"a\"\n" \
++ "6673:.byte 6668b-6667b\n" \
++ ".byte 6670f-6669f\n" \
++ ".byte 6671f-6670f\n" \
++ ".byte 0\n" \
++ ".byte %c0\n" \
++ "6669:lock;addl $0,0(%%esp)\n" \
++ "6670:" instr "\n" \
++ "6671:\n" \
++ ".previous\n" \
++ : \
++ : "i" (X86_FEATURE_XMM2) \
++ : "memory")
++#define smp_rmb() smp_alt_mb("lfence")
++#define smp_mb() smp_alt_mb("mfence")
++#define set_mb(var, value) do { \
++unsigned long __set_mb_temp; \
++__asm__ __volatile__("6667:movl %1, %0\n6668:\n" \
++ ".section __smp_alternatives,\"a\"\n" \
++ ".long 6667b\n" \
++ ".long 6673f\n" \
++ ".previous\n" \
++ ".section __smp_replacements,\"a\"\n" \
++ "6673: .byte 6668b-6667b\n" \
++ ".byte 6670f-6669f\n" \
++ ".byte 0\n" \
++ ".byte 6671f-6670f\n" \
++ ".byte -1\n" \
++ "6669: xchg %1, %0\n" \
++ "6670:movl %1, %0\n" \
++ "6671:\n" \
++ ".previous\n" \
++ : "=m" (var), "=r" (__set_mb_temp) \
++ : "1" (value) \
++ : "memory"); } while (0)
++#else
+ #define smp_mb() mb()
+ #define smp_rmb() rmb()
++#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
++#endif
+ #define smp_wmb() wmb()
+ #define smp_read_barrier_depends() read_barrier_depends()
+-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
+ #else
+ #define smp_mb() barrier()
+ #define smp_rmb() barrier()
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/tpm_plugin_2.6.17.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/tpm_plugin_2.6.17.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,1545 @@
+diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.c
./drivers/char/tpm/tpm_atmel.c
+--- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.c 2006-09-12
19:02:10.000000000 +0100
++++ ./drivers/char/tpm/tpm_atmel.c 2006-09-19 14:05:52.000000000 +0100
+@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip
+ return -EIO;
+
+ for (i = 0; i < 6; i++) {
+- status = ioread8(chip->vendor->iobase + 1);
++ status = ioread8(chip->vendor.iobase + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(chip->dev, "error reading header\n");
+ return -EIO;
+ }
+- *buf++ = ioread8(chip->vendor->iobase);
++ *buf++ = ioread8(chip->vendor.iobase);
+ }
+
+ /* size of the data received */
+@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip
+ dev_err(chip->dev,
+ "Recv size(%d) less than available space\n", size);
+ for (; i < size; i++) { /* clear the waiting data anyway */
+- status = ioread8(chip->vendor->iobase + 1);
++ status = ioread8(chip->vendor.iobase + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(chip->dev, "error reading data\n");
+ return -EIO;
+@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip
+
+ /* read all the data available */
+ for (; i < size; i++) {
+- status = ioread8(chip->vendor->iobase + 1);
++ status = ioread8(chip->vendor.iobase + 1);
+ if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+ dev_err(chip->dev, "error reading data\n");
+ return -EIO;
+ }
+- *buf++ = ioread8(chip->vendor->iobase);
++ *buf++ = ioread8(chip->vendor.iobase);
+ }
+
+ /* make sure data available is gone */
+- status = ioread8(chip->vendor->iobase + 1);
++ status = ioread8(chip->vendor.iobase + 1);
+
+ if (status & ATML_STATUS_DATA_AVAIL) {
+ dev_err(chip->dev, "data available is stuck\n");
+@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip
+ dev_dbg(chip->dev, "tpm_atml_send:\n");
+ for (i = 0; i < count; i++) {
+ dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
+- iowrite8(buf[i], chip->vendor->iobase);
++ iowrite8(buf[i], chip->vendor.iobase);
+ }
+
+ return count;
+@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip
+
+ static void tpm_atml_cancel(struct tpm_chip *chip)
+ {
+- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
++ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
+ }
+
+ static u8 tpm_atml_status(struct tpm_chip *chip)
+ {
+- return ioread8(chip->vendor->iobase + 1);
++ return ioread8(chip->vendor.iobase + 1);
+ }
+
+ static struct file_operations atmel_ops = {
+@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] =
+
+ static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
+
+-static struct tpm_vendor_specific tpm_atmel = {
++static const struct tpm_vendor_specific tpm_atmel = {
+ .recv = tpm_atml_recv,
+ .send = tpm_atml_send,
+ .cancel = tpm_atml_cancel,
+@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
+ struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
+
+ if (chip) {
+- if (chip->vendor->have_region)
+- atmel_release_region(chip->vendor->base,
+- chip->vendor->region_size);
+- atmel_put_base_addr(chip->vendor);
++ if (chip->vendor.have_region)
++ atmel_release_region(chip->vendor.base,
++ chip->vendor.region_size);
++ atmel_put_base_addr(chip->vendor.iobase);
+ tpm_remove_hardware(chip->dev);
+ platform_device_unregister(pdev);
+ }
+@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
+ static int __init init_atmel(void)
+ {
+ int rc = 0;
++ void __iomem *iobase = NULL;
++ int have_region, region_size;
++ unsigned long base;
++ struct tpm_chip *chip;
+
+ driver_register(&atml_drv);
+
+- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
++ if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) {
+ rc = -ENODEV;
+ goto err_unreg_drv;
+ }
+
+- tpm_atmel.have_region =
++ have_region =
+ (atmel_request_region
+- (tpm_atmel.base, tpm_atmel.region_size,
+- "tpm_atmel0") == NULL) ? 0 : 1;
++ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
++
+
+ if (IS_ERR
+ (pdev =
+@@ -199,17 +203,25 @@ static int __init init_atmel(void)
+ goto err_rel_reg;
+ }
+
+- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
++ rc = -ENODEV;
+ goto err_unreg_dev;
++ }
++
++ chip->vendor.iobase = iobase;
++ chip->vendor.base = base;
++ chip->vendor.have_region = have_region;
++ chip->vendor.region_size = region_size;
++
+ return 0;
+
+ err_unreg_dev:
+ platform_device_unregister(pdev);
+ err_rel_reg:
+- atmel_put_base_addr(&tpm_atmel);
+- if (tpm_atmel.have_region)
+- atmel_release_region(tpm_atmel.base,
+- tpm_atmel.region_size);
++ atmel_put_base_addr(iobase);
++ if (have_region)
++ atmel_release_region(base,
++ region_size);
+ err_unreg_drv:
+ driver_unregister(&atml_drv);
+ return rc;
+diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.h
./drivers/char/tpm/tpm_atmel.h
+--- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_atmel.h 2006-09-12
19:02:10.000000000 +0100
++++ ./drivers/char/tpm/tpm_atmel.h 2006-09-19 14:05:52.000000000 +0100
+@@ -28,13 +28,12 @@
+ #define atmel_request_region request_mem_region
+ #define atmel_release_region release_mem_region
+
+-static inline void atmel_put_base_addr(struct tpm_vendor_specific
+- *vendor)
++static inline void atmel_put_base_addr(void __iomem *iobase)
+ {
+- iounmap(vendor->iobase);
++ iounmap(iobase);
+ }
+
+-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
++static void __iomem * atmel_get_base_addr(unsigned long *base, int
*region_size)
+ {
+ struct device_node *dn;
+ unsigned long address, size;
+@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add
+ else
+ size = reg[naddrc];
+
+- vendor->base = address;
+- vendor->region_size = size;
+- return ioremap(vendor->base, vendor->region_size);
++ *base = address;
++ *region_size = size;
++ return ioremap(*base, *region_size);
+ }
+ #else
+ #define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
+@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
+ return 0;
+ }
+
+-static inline void atmel_put_base_addr(struct tpm_vendor_specific
+- *vendor)
++static inline void atmel_put_base_addr(void __iomem *iobase)
+ {
+ }
+
+ /* Determine where to talk to device */
+-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
+- *vendor)
++static void __iomem * atmel_get_base_addr(unsigned long *base, int
*region_size)
+ {
+ int lo, hi;
+
+@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add
+ lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+ hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+
+- vendor->base = (hi << 8) | lo;
+- vendor->region_size = 2;
++ *base = (hi << 8) | lo;
++ *region_size = 2;
+
+- return ioport_map(vendor->base, vendor->region_size);
++ return ioport_map(*base, *region_size);
+ }
+ #endif
+diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_bios.c
./drivers/char/tpm/tpm_bios.c
+--- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_bios.c 2006-09-12
19:02:10.000000000 +0100
++++ ./drivers/char/tpm/tpm_bios.c 2006-09-19 14:05:52.000000000 +0100
+@@ -29,6 +29,11 @@
+ #define MAX_TEXT_EVENT 1000 /* Max event string length */
+ #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
+
++enum bios_platform_class {
++ BIOS_CLIENT = 0x00,
++ BIOS_SERVER = 0x01,
++};
++
+ struct tpm_bios_log {
+ void *bios_event_log;
+ void *bios_event_log_end;
+@@ -36,9 +41,18 @@ struct tpm_bios_log {
+
+ struct acpi_tcpa {
+ struct acpi_table_header hdr;
+- u16 reserved;
+- u32 log_max_len __attribute__ ((packed));
+- u32 log_start_addr __attribute__ ((packed));
++ u16 platform_class;
++ union {
++ struct client_hdr {
++ u32 log_max_len __attribute__ ((packed));
++ u64 log_start_addr __attribute__ ((packed));
++ } client;
++ struct server_hdr {
++ u16 reserved;
++ u64 log_max_len __attribute__ ((packed));
++ u64 log_start_addr __attribute__ ((packed));
++ } server;
++ };
+ };
+
+ struct tcpa_event {
+@@ -91,6 +105,12 @@ static const char* tcpa_event_type_strin
+ "Non-Host Info"
+ };
+
++struct tcpa_pc_event {
++ u32 event_id;
++ u32 event_size;
++ u8 event_data[0];
++};
++
+ enum tcpa_pc_event_ids {
+ SMBIOS = 1,
+ BIS_CERT,
+@@ -100,14 +120,15 @@ enum tcpa_pc_event_ids {
+ NVRAM,
+ OPTION_ROM_EXEC,
+ OPTION_ROM_CONFIG,
+- OPTION_ROM_MICROCODE,
++ OPTION_ROM_MICROCODE = 10,
+ S_CRTM_VERSION,
+ S_CRTM_CONTENTS,
+ POST_CONTENTS,
++ HOST_TABLE_OF_DEVICES,
+ };
+
+ static const char* tcpa_pc_event_id_strings[] = {
+- ""
++ "",
+ "SMBIOS",
+ "BIS Certificate",
+ "POST BIOS ",
+@@ -116,10 +137,12 @@ static const char* tcpa_pc_event_id_stri
+ "NVRAM",
+ "Option ROM",
+ "Option ROM config",
+- "Option ROM microcode",
++ "",
++ "Option ROM microcode ",
+ "S-CRTM Version",
+- "S-CRTM Contents",
+- "S-CRTM POST Contents",
++ "S-CRTM Contents ",
++ "POST Contents ",
++ "Table of Devices",
+ };
+
+ /* returns pointer to start of pos. entry of tcg log */
+@@ -191,7 +214,7 @@ static int get_event_name(char *dest, st
+ const char *name = "";
+ char data[40] = "";
+ int i, n_len = 0, d_len = 0;
+- u32 event_id;
++ struct tcpa_pc_event *pc_event;
+
+ switch(event->event_type) {
+ case PREBOOT:
+@@ -220,31 +243,32 @@ static int get_event_name(char *dest, st
+ }
+ break;
+ case EVENT_TAG:
+- event_id = be32_to_cpu(*((u32 *)event_entry));
++ pc_event = (struct tcpa_pc_event *)event_entry;
+
+ /* ToDo Row data -> Base64 */
+
+- switch (event_id) {
++ switch (pc_event->event_id) {
+ case SMBIOS:
+ case BIS_CERT:
+ case CMOS:
+ case NVRAM:
+ case OPTION_ROM_EXEC:
+ case OPTION_ROM_CONFIG:
+- case OPTION_ROM_MICROCODE:
+ case S_CRTM_VERSION:
+- case S_CRTM_CONTENTS:
+- case POST_CONTENTS:
+- name = tcpa_pc_event_id_strings[event_id];
++ name = tcpa_pc_event_id_strings[pc_event->event_id];
+ n_len = strlen(name);
+ break;
++ /* hash data */
+ case POST_BIOS_ROM:
+ case ESCD:
+- name = tcpa_pc_event_id_strings[event_id];
++ case OPTION_ROM_MICROCODE:
++ case S_CRTM_CONTENTS:
++ case POST_CONTENTS:
++ name = tcpa_pc_event_id_strings[pc_event->event_id];
+ n_len = strlen(name);
+ for (i = 0; i < 20; i++)
+- d_len += sprintf(data, "%02x",
+- event_entry[8 + i]);
++ d_len += sprintf(&data[2*i], "%02x",
++ pc_event->event_data[i]);
+ break;
+ default:
+ break;
+@@ -260,52 +284,13 @@ static int get_event_name(char *dest, st
+
+ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
+ {
++ struct tcpa_event *event = v;
++ char *data = v;
++ int i;
+
+- char *eventname;
+- char data[4];
+- u32 help;
+- int i, len;
+- struct tcpa_event *event = (struct tcpa_event *) v;
+- unsigned char *event_entry =
+- (unsigned char *) (v + sizeof(struct tcpa_event));
+-
+- eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL);
+- if (!eventname) {
+- printk(KERN_ERR "%s: ERROR - No Memory for event name\n ",
+- __func__);
+- return -ENOMEM;
+- }
+-
+- /* 1st: PCR used is in little-endian format (4 bytes) */
+- help = le32_to_cpu(event->pcr_index);
+- memcpy(data, &help, 4);
+- for (i = 0; i < 4; i++)
+- seq_putc(m, data[i]);
+-
+- /* 2nd: SHA1 (20 bytes) */
+- for (i = 0; i < 20; i++)
+- seq_putc(m, event->pcr_value[i]);
+-
+- /* 3rd: event type identifier (4 bytes) */
+- help = le32_to_cpu(event->event_type);
+- memcpy(data, &help, 4);
+- for (i = 0; i < 4; i++)
++ for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++)
+ seq_putc(m, data[i]);
+
+- len = 0;
+-
+- len += get_event_name(eventname, event, event_entry);
+-
+- /* 4th: filename <= 255 + \'0' delimiter */
+- if (len > TCG_EVENT_NAME_LEN_MAX)
+- len = TCG_EVENT_NAME_LEN_MAX;
+-
+- for (i = 0; i < len; i++)
+- seq_putc(m, eventname[i]);
+-
+- /* 5th: delimiter */
+- seq_putc(m, '\0');
+-
+ return 0;
+ }
+
+@@ -353,6 +338,7 @@ static int tpm_ascii_bios_measurements_s
+ /* 4th: eventname <= max + \'0' delimiter */
+ seq_printf(m, " %s\n", eventname);
+
++ kfree(eventname);
+ return 0;
+ }
+
+@@ -376,6 +362,7 @@ static int read_log(struct tpm_bios_log
+ struct acpi_tcpa *buff;
+ acpi_status status;
+ struct acpi_table_header *virt;
++ u64 len, start;
+
+ if (log->bios_event_log != NULL) {
+ printk(KERN_ERR
+@@ -396,27 +383,37 @@ static int read_log(struct tpm_bios_log
+ return -EIO;
+ }
+
+- if (buff->log_max_len == 0) {
++ switch(buff->platform_class) {
++ case BIOS_SERVER:
++ len = buff->server.log_max_len;
++ start = buff->server.log_start_addr;
++ break;
++ case BIOS_CLIENT:
++ default:
++ len = buff->client.log_max_len;
++ start = buff->client.log_start_addr;
++ break;
++ }
++ if (!len) {
+ printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
+ return -EIO;
+ }
+
+ /* malloc EventLog space */
+- log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
++ log->bios_event_log = kmalloc(len, GFP_KERNEL);
+ if (!log->bios_event_log) {
+- printk
+- ("%s: ERROR - Not enough Memory for BIOS measurements\n",
+- __func__);
++ printk("%s: ERROR - Not enough Memory for BIOS measurements\n",
++ __func__);
+ return -ENOMEM;
+ }
+
+- log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
++ log->bios_event_log_end = log->bios_event_log + len;
+
+- acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, (void *)
&virt);
++ acpi_os_map_memory(start, len, (void *) &virt);
+
+- memcpy(log->bios_event_log, virt, buff->log_max_len);
++ memcpy(log->bios_event_log, virt, len);
+
+- acpi_os_unmap_memory(virt, buff->log_max_len);
++ acpi_os_unmap_memory(virt, len);
+ return 0;
+ }
+
+diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_infineon.c
./drivers/char/tpm/tpm_infineon.c
+--- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_infineon.c 2006-09-12
19:02:10.000000000 +0100
++++ ./drivers/char/tpm/tpm_infineon.c 2006-09-19 14:05:52.000000000 +0100
+@@ -15,6 +15,7 @@
+ * License.
+ */
+
++#include <linux/init.h>
+ #include <linux/pnp.h>
+ #include "tpm.h"
+
+@@ -104,7 +105,7 @@ static int empty_fifo(struct tpm_chip *c
+
+ if (clear_wrfifo) {
+ for (i = 0; i < 4096; i++) {
+- status = inb(chip->vendor->base + WRFIFO);
++ status = inb(chip->vendor.base + WRFIFO);
+ if (status == 0xff) {
+ if (check == 5)
+ break;
+@@ -124,8 +125,8 @@ static int empty_fifo(struct tpm_chip *c
+ */
+ i = 0;
+ do {
+- status = inb(chip->vendor->base + RDFIFO);
+- status = inb(chip->vendor->base + STAT);
++ status = inb(chip->vendor.base + RDFIFO);
++ status = inb(chip->vendor.base + STAT);
+ i++;
+ if (i == TPM_MAX_TRIES)
+ return -EIO;
+@@ -138,7 +139,7 @@ static int wait(struct tpm_chip *chip, i
+ int status;
+ int i;
+ for (i = 0; i < TPM_MAX_TRIES; i++) {
+- status = inb(chip->vendor->base + STAT);
++ status = inb(chip->vendor.base + STAT);
+ /* check the status-register if wait_for_bit is set */
+ if (status & 1 << wait_for_bit)
+ break;
+@@ -157,7 +158,7 @@ static int wait(struct tpm_chip *chip, i
+ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
+ {
+ wait(chip, STAT_XFE);
+- outb(sendbyte, chip->vendor->base + WRFIFO);
++ outb(sendbyte, chip->vendor.base + WRFIFO);
+ }
+
+ /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
+@@ -204,7 +205,7 @@ recv_begin:
+ ret = wait(chip, STAT_RDA);
+ if (ret)
+ return -EIO;
+- buf[i] = inb(chip->vendor->base + RDFIFO);
++ buf[i] = inb(chip->vendor.base + RDFIFO);
+ }
+
+ if (buf[0] != TPM_VL_VER) {
+@@ -219,7 +220,7 @@ recv_begin:
+
+ for (i = 0; i < size; i++) {
+ wait(chip, STAT_RDA);
+- buf[i] = inb(chip->vendor->base + RDFIFO);
++ buf[i] = inb(chip->vendor.base + RDFIFO);
+ }
+
+ if ((size == 0x6D00) && (buf[1] == 0x80)) {
+@@ -268,7 +269,7 @@ static int tpm_inf_send(struct tpm_chip
+ u8 count_high, count_low, count_4, count_3, count_2, count_1;
+
+ /* Disabling Reset, LP and IRQC */
+- outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
++ outb(RESET_LP_IRQC_DISABLE, chip->vendor.base + CMD);
+
+ ret = empty_fifo(chip, 1);
+ if (ret) {
+@@ -319,7 +320,7 @@ static void tpm_inf_cancel(struct tpm_ch
+
+ static u8 tpm_inf_status(struct tpm_chip *chip)
+ {
+- return inb(chip->vendor->base + STAT);
++ return inb(chip->vendor.base + STAT);
+ }
+
+ static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+@@ -346,7 +347,7 @@ static struct file_operations inf_ops =
+ .release = tpm_release,
+ };
+
+-static struct tpm_vendor_specific tpm_inf = {
++static const struct tpm_vendor_specific tpm_inf = {
+ .recv = tpm_inf_recv,
+ .send = tpm_inf_send,
+ .cancel = tpm_inf_cancel,
+@@ -375,6 +376,7 @@ static int __devinit tpm_inf_pnp_probe(s
+ int version[2];
+ int productid[2];
+ char chipname[20];
++ struct tpm_chip *chip;
+
+ /* read IO-ports through PnP */
+ if (pnp_port_valid(dev, 0) && pnp_port_valid(dev, 1) &&
+@@ -395,14 +397,13 @@ static int __devinit tpm_inf_pnp_probe(s
+ goto err_last;
+ }
+ /* publish my base address and request region */
+- tpm_inf.base = TPM_INF_BASE;
+ if (request_region
+- (tpm_inf.base, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
++ (TPM_INF_BASE, TPM_INF_PORT_LEN, "tpm_infineon0") == NULL) {
+ rc = -EINVAL;
+ goto err_last;
+ }
+- if (request_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN,
+- "tpm_infineon0") == NULL) {
++ if (request_region
++ (TPM_INF_ADDR, TPM_INF_ADDR_LEN, "tpm_infineon0") == NULL) {
+ rc = -EINVAL;
+ goto err_last;
+ }
+@@ -442,9 +443,9 @@ static int __devinit tpm_inf_pnp_probe(s
+
+ /* configure TPM with IO-ports */
+ outb(IOLIMH, TPM_INF_ADDR);
+- outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
++ outb(((TPM_INF_BASE >> 8) & 0xff), TPM_INF_DATA);
+ outb(IOLIML, TPM_INF_ADDR);
+- outb((tpm_inf.base & 0xff), TPM_INF_DATA);
++ outb((TPM_INF_BASE & 0xff), TPM_INF_DATA);
+
+ /* control if IO-ports are set correctly */
+ outb(IOLIMH, TPM_INF_ADDR);
+@@ -452,10 +453,10 @@ static int __devinit tpm_inf_pnp_probe(s
+ outb(IOLIML, TPM_INF_ADDR);
+ iol = inb(TPM_INF_DATA);
+
+- if ((ioh << 8 | iol) != tpm_inf.base) {
++ if ((ioh << 8 | iol) != TPM_INF_BASE) {
+ dev_err(&dev->dev,
+- "Could not set IO-ports to 0x%lx\n",
+- tpm_inf.base);
++ "Could not set IO-ports to 0x%x\n",
++ TPM_INF_BASE);
+ rc = -EIO;
+ goto err_release_region;
+ }
+@@ -466,15 +467,15 @@ static int __devinit tpm_inf_pnp_probe(s
+ outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
+
+ /* disable RESET, LP and IRQC */
+- outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
++ outb(RESET_LP_IRQC_DISABLE, TPM_INF_BASE + CMD);
+
+ /* Finally, we're done, print some infos */
+ dev_info(&dev->dev, "TPM found: "
+ "config base 0x%x, "
+ "io base 0x%x, "
+- "chip version %02x%02x, "
+- "vendor id %x%x (Infineon), "
+- "product id %02x%02x"
++ "chip version 0x%02x%02x, "
++ "vendor id 0x%x%x (Infineon), "
++ "product id 0x%02x%02x"
+ "%s\n",
+ TPM_INF_ADDR,
+ TPM_INF_BASE,
+@@ -482,11 +483,10 @@ static int __devinit tpm_inf_pnp_probe(s
+ vendorid[0], vendorid[1],
+ productid[0], productid[1], chipname);
+
+- rc = tpm_register_hardware(&dev->dev, &tpm_inf);
+- if (rc < 0) {
+- rc = -ENODEV;
++ if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) {
+ goto err_release_region;
+ }
++ chip->vendor.base = TPM_INF_BASE;
+ return 0;
+ } else {
+ rc = -ENODEV;
+@@ -494,7 +494,7 @@ static int __devinit tpm_inf_pnp_probe(s
+ }
+
+ err_release_region:
+- release_region(tpm_inf.base, TPM_INF_PORT_LEN);
++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
+ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+
+ err_last:
+@@ -506,7 +506,8 @@ static __devexit void tpm_inf_pnp_remove
+ struct tpm_chip *chip = pnp_get_drvdata(dev);
+
+ if (chip) {
+- release_region(chip->vendor->base, TPM_INF_PORT_LEN);
++ release_region(TPM_INF_BASE, TPM_INF_PORT_LEN);
++ release_region(TPM_INF_ADDR, TPM_INF_ADDR_LEN);
+ tpm_remove_hardware(chip->dev);
+ }
+ }
+@@ -520,7 +521,7 @@ static struct pnp_driver tpm_inf_pnp = {
+ },
+ .id_table = tpm_pnp_tbl,
+ .probe = tpm_inf_pnp_probe,
+- .remove = tpm_inf_pnp_remove,
++ .remove = __devexit_p(tpm_inf_pnp_remove),
+ };
+
+ static int __init init_inf(void)
+@@ -538,5 +539,5 @@ module_exit(cleanup_inf);
+
+ MODULE_AUTHOR("Marcel Selhorst <selhorst@xxxxxxxxxxxxx>");
+ MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT
1.2");
+-MODULE_VERSION("1.7");
++MODULE_VERSION("1.8");
+ MODULE_LICENSE("GPL");
+diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_nsc.c
./drivers/char/tpm/tpm_nsc.c
+--- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_nsc.c 2006-09-12
19:02:10.000000000 +0100
++++ ./drivers/char/tpm/tpm_nsc.c 2006-09-19 14:05:52.000000000 +0100
+@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip
+ unsigned long stop;
+
+ /* status immediately available check */
+- *data = inb(chip->vendor->base + NSC_STATUS);
++ *data = inb(chip->vendor.base + NSC_STATUS);
+ if ((*data & mask) == val)
+ return 0;
+
+@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip
+ stop = jiffies + 10 * HZ;
+ do {
+ msleep(TPM_TIMEOUT);
+- *data = inb(chip->vendor->base + 1);
++ *data = inb(chip->vendor.base + 1);
+ if ((*data & mask) == val)
+ return 0;
+ }
+@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm
+ unsigned long stop;
+
+ /* status immediately available check */
+- status = inb(chip->vendor->base + NSC_STATUS);
++ status = inb(chip->vendor.base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+- status = inb(chip->vendor->base + NSC_DATA);
++ status = inb(chip->vendor.base + NSC_DATA);
+ if (status & NSC_STATUS_RDY)
+ return 0;
+
+@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm
+ stop = jiffies + 100;
+ do {
+ msleep(TPM_TIMEOUT);
+- status = inb(chip->vendor->base + NSC_STATUS);
++ status = inb(chip->vendor.base + NSC_STATUS);
+ if (status & NSC_STATUS_OBF)
+- status = inb(chip->vendor->base + NSC_DATA);
++ status = inb(chip->vendor.base + NSC_DATA);
+ if (status & NSC_STATUS_RDY)
+ return 0;
+ }
+@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip
+ return -EIO;
+ }
+ if ((data =
+- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
++ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ dev_err(chip->dev, "not in normal mode (0x%x)\n",
+ data);
+ return -EIO;
+@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip
+ }
+ if (data & NSC_STATUS_F0)
+ break;
+- *p = inb(chip->vendor->base + NSC_DATA);
++ *p = inb(chip->vendor.base + NSC_DATA);
+ }
+
+ if ((data & NSC_STATUS_F0) == 0 &&
+@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip
+ dev_err(chip->dev, "F0 not set\n");
+ return -EIO;
+ }
+- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
++ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ dev_err(chip->dev,
+ "expected end of command(0x%x)\n", data);
+ return -EIO;
+@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip
+ * fix it. Not sure why this is needed, we followed the flow
+ * chart in the manual to the letter.
+ */
+- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
+
+ if (nsc_wait_for_ready(chip) != 0)
+ return -EIO;
+@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip
+ return -EIO;
+ }
+
+- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
++ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
+ if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+ dev_err(chip->dev, "IBR timeout\n");
+ return -EIO;
+@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip
+ "IBF timeout (while writing data)\n");
+ return -EIO;
+ }
+- outb(buf[i], chip->vendor->base + NSC_DATA);
++ outb(buf[i], chip->vendor.base + NSC_DATA);
+ }
+
+ if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+ dev_err(chip->dev, "IBF timeout\n");
+ return -EIO;
+ }
+- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
++ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
+
+ return count;
+ }
+
+ static void tpm_nsc_cancel(struct tpm_chip *chip)
+ {
+- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
++ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
+ }
+
+ static u8 tpm_nsc_status(struct tpm_chip *chip)
+ {
+- return inb(chip->vendor->base + NSC_STATUS);
++ return inb(chip->vendor.base + NSC_STATUS);
+ }
+
+ static struct file_operations nsc_ops = {
+@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] =
+
+ static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
+
+-static struct tpm_vendor_specific tpm_nsc = {
++static const struct tpm_vendor_specific tpm_nsc = {
+ .recv = tpm_nsc_recv,
+ .send = tpm_nsc_send,
+ .cancel = tpm_nsc_cancel,
+@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str
+ {
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if ( chip ) {
+- release_region(chip->vendor->base, 2);
++ release_region(chip->vendor.base, 2);
+ tpm_remove_hardware(chip->dev);
+ }
+ }
+@@ -286,7 +286,8 @@ static int __init init_nsc(void)
+ int rc = 0;
+ int lo, hi;
+ int nscAddrBase = TPM_ADDR;
+-
++ struct tpm_chip *chip;
++ unsigned long base;
+
+ /* verify that it is a National part (SID) */
+ if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
+@@ -300,7 +301,7 @@ static int __init init_nsc(void)
+
+ hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
+ lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
+- tpm_nsc.base = (hi<<8) | lo;
++ base = (hi<<8) | lo;
+
+ /* enable the DPM module */
+ tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
+@@ -320,13 +321,15 @@ static int __init init_nsc(void)
+ if ((rc = platform_device_register(pdev)) < 0)
+ goto err_free_dev;
+
+- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
++ if (request_region(base, 2, "tpm_nsc0") == NULL ) {
+ rc = -EBUSY;
+ goto err_unreg_dev;
+ }
+
+- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
++ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
++ rc = -ENODEV;
+ goto err_rel_reg;
++ }
+
+ dev_dbg(&pdev->dev, "NSC TPM detected\n");
+ dev_dbg(&pdev->dev,
+@@ -361,10 +364,12 @@ static int __init init_nsc(void)
+ "NSC TPM revision %d\n",
+ tpm_read_index(nscAddrBase, 0x27) & 0x1F);
+
++ chip->vendor.base = base;
++
+ return 0;
+
+ err_rel_reg:
+- release_region(tpm_nsc.base, 2);
++ release_region(base, 2);
+ err_unreg_dev:
+ platform_device_unregister(pdev);
+ err_free_dev:
+diff -pruN ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_tis.c
./drivers/char/tpm/tpm_tis.c
+--- ../orig-linux-2.6.16.29/drivers/char/tpm/tpm_tis.c 1970-01-01
01:00:00.000000000 +0100
++++ ./drivers/char/tpm/tpm_tis.c 2006-09-19 14:05:52.000000000 +0100
+@@ -0,0 +1,665 @@
++/*
++ * Copyright (C) 2005, 2006 IBM Corporation
++ *
++ * Authors:
++ * Leendert van Doorn <leendert@xxxxxxxxxxxxxx>
++ * Kylene Hall <kjhall@xxxxxxxxxx>
++ *
++ * Device driver for TCG/TCPA TPM (trusted platform module).
++ * Specifications at www.trustedcomputinggroup.org
++ *
++ * This device driver implements the TPM interface as defined in
++ * the TCG TPM Interface Spec version 1.2, revision 1.0.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation, version 2 of the
++ * License.
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/pnp.h>
++#include <linux/interrupt.h>
++#include <linux/wait.h>
++#include "tpm.h"
++
++#define TPM_HEADER_SIZE 10
++
++enum tis_access {
++ TPM_ACCESS_VALID = 0x80,
++ TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
++ TPM_ACCESS_REQUEST_PENDING = 0x04,
++ TPM_ACCESS_REQUEST_USE = 0x02,
++};
++
++enum tis_status {
++ TPM_STS_VALID = 0x80,
++ TPM_STS_COMMAND_READY = 0x40,
++ TPM_STS_GO = 0x20,
++ TPM_STS_DATA_AVAIL = 0x10,
++ TPM_STS_DATA_EXPECT = 0x08,
++};
++
++enum tis_int_flags {
++ TPM_GLOBAL_INT_ENABLE = 0x80000000,
++ TPM_INTF_BURST_COUNT_STATIC = 0x100,
++ TPM_INTF_CMD_READY_INT = 0x080,
++ TPM_INTF_INT_EDGE_FALLING = 0x040,
++ TPM_INTF_INT_EDGE_RISING = 0x020,
++ TPM_INTF_INT_LEVEL_LOW = 0x010,
++ TPM_INTF_INT_LEVEL_HIGH = 0x008,
++ TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
++ TPM_INTF_STS_VALID_INT = 0x002,
++ TPM_INTF_DATA_AVAIL_INT = 0x001,
++};
++
++enum tis_defaults {
++ TIS_MEM_BASE = 0xFED40000,
++ TIS_MEM_LEN = 0x5000,
++ TIS_SHORT_TIMEOUT = 750, /* ms */
++ TIS_LONG_TIMEOUT = 2000, /* 2 sec */
++};
++
++#define TPM_ACCESS(l) (0x0000 | ((l) << 12))
++#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12))
++#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12))
++#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12))
++#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12))
++#define TPM_STS(l) (0x0018 | ((l) << 12))
++#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12))
++
++#define TPM_DID_VID(l) (0x0F00 | ((l) << 12))
++#define TPM_RID(l) (0x0F04 | ((l) << 12))
++
++static LIST_HEAD(tis_chips);
++static DEFINE_SPINLOCK(tis_lock);
++
++static int check_locality(struct tpm_chip *chip, int l)
++{
++ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
++ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
++ return chip->vendor.locality = l;
++
++ return -1;
++}
++
++static void release_locality(struct tpm_chip *chip, int l, int force)
++{
++ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
++ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
++ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
++ chip->vendor.iobase + TPM_ACCESS(l));
++}
++
++static int request_locality(struct tpm_chip *chip, int l)
++{
++ unsigned long stop;
++ long rc;
++
++ if (check_locality(chip, l) >= 0)
++ return l;
++
++ iowrite8(TPM_ACCESS_REQUEST_USE,
++ chip->vendor.iobase + TPM_ACCESS(l));
++
++ if (chip->vendor.irq) {
++ rc = wait_event_interruptible_timeout(chip->vendor.int_queue,
++ (check_locality
++ (chip, l) >= 0),
++ chip->vendor.timeout_a);
++ if (rc > 0)
++ return l;
++
++ } else {
++ /* wait for burstcount */
++ stop = jiffies + chip->vendor.timeout_a;
++ do {
++ if (check_locality(chip, l) >= 0)
++ return l;
++ msleep(TPM_TIMEOUT);
++ }
++ while (time_before(jiffies, stop));
++ }
++ return -1;
++}
++
++static u8 tpm_tis_status(struct tpm_chip *chip)
++{
++ return ioread8(chip->vendor.iobase +
++ TPM_STS(chip->vendor.locality));
++}
++
++static void tpm_tis_ready(struct tpm_chip *chip)
++{
++ /* this causes the current command to be aborted */
++ iowrite8(TPM_STS_COMMAND_READY,
++ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
++}
++
++static int get_burstcount(struct tpm_chip *chip)
++{
++ unsigned long stop;
++ int burstcnt;
++
++ /* wait for burstcount */
++ /* which timeout value, spec has 2 answers (c & d) */
++ stop = jiffies + chip->vendor.timeout_d;
++ do {
++ burstcnt = ioread8(chip->vendor.iobase +
++ TPM_STS(chip->vendor.locality) + 1);
++ burstcnt += ioread8(chip->vendor.iobase +
++ TPM_STS(chip->vendor.locality) +
++ 2) << 8;
++ if (burstcnt)
++ return burstcnt;
++ msleep(TPM_TIMEOUT);
++ } while (time_before(jiffies, stop));
++ return -EBUSY;
++}
++
++static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long
timeout,
++ wait_queue_head_t *queue)
++{
++ unsigned long stop;
++ long rc;
++ u8 status;
++
++ /* check current status */
++ status = tpm_tis_status(chip);
++ if ((status & mask) == mask)
++ return 0;
++
++ if (chip->vendor.irq) {
++ rc = wait_event_interruptible_timeout(*queue,
++ ((tpm_tis_status
++ (chip) & mask) ==
++ mask), timeout);
++ if (rc > 0)
++ return 0;
++ } else {
++ stop = jiffies + timeout;
++ do {
++ msleep(TPM_TIMEOUT);
++ status = tpm_tis_status(chip);
++ if ((status & mask) == mask)
++ return 0;
++ } while (time_before(jiffies, stop));
++ }
++ return -ETIME;
++}
++
++static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
++{
++ int size = 0, burstcnt;
++ while (size < count &&
++ wait_for_stat(chip,
++ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++ chip->vendor.timeout_c,
++ &chip->vendor.read_queue)
++ == 0) {
++ burstcnt = get_burstcount(chip);
++ for (; burstcnt > 0 && size < count; burstcnt--)
++ buf[size++] = ioread8(chip->vendor.iobase +
++ TPM_DATA_FIFO(chip->vendor.
++ locality));
++ }
++ return size;
++}
++
++static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
++{
++ int size = 0;
++ int expected, status;
++
++ if (count < TPM_HEADER_SIZE) {
++ size = -EIO;
++ goto out;
++ }
++
++ /* read first 10 bytes, including tag, paramsize, and result */
++ if ((size =
++ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
++ dev_err(chip->dev, "Unable to read header\n");
++ goto out;
++ }
++
++ expected = be32_to_cpu(*(__be32 *) (buf + 2));
++ if (expected > count) {
++ size = -EIO;
++ goto out;
++ }
++
++ if ((size +=
++ recv_data(chip, &buf[TPM_HEADER_SIZE],
++ expected - TPM_HEADER_SIZE)) < expected) {
++ dev_err(chip->dev, "Unable to read remainder of result\n");
++ size = -ETIME;
++ goto out;
++ }
++
++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
++ &chip->vendor.int_queue);
++ status = tpm_tis_status(chip);
++ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
++ dev_err(chip->dev, "Error left over data\n");
++ size = -EIO;
++ goto out;
++ }
++
++out:
++ tpm_tis_ready(chip);
++ release_locality(chip, chip->vendor.locality, 0);
++ return size;
++}
++
++/*
++ * If interrupts are used (signaled by an irq set in the vendor structure)
++ * tpm.c can skip polling for the data to be available as the interrupt is
++ * waited for here
++ */
++static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
++{
++ int rc, status, burstcnt;
++ size_t count = 0;
++ u32 ordinal;
++
++ if (request_locality(chip, 0) < 0)
++ return -EBUSY;
++
++ status = tpm_tis_status(chip);
++ if ((status & TPM_STS_COMMAND_READY) == 0) {
++ tpm_tis_ready(chip);
++ if (wait_for_stat
++ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
++ &chip->vendor.int_queue) < 0) {
++ rc = -ETIME;
++ goto out_err;
++ }
++ }
++
++ while (count < len - 1) {
++ burstcnt = get_burstcount(chip);
++ for (; burstcnt > 0 && count < len - 1; burstcnt--) {
++ iowrite8(buf[count], chip->vendor.iobase +
++ TPM_DATA_FIFO(chip->vendor.locality));
++ count++;
++ }
++
++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
++ &chip->vendor.int_queue);
++ status = tpm_tis_status(chip);
++ if ((status & TPM_STS_DATA_EXPECT) == 0) {
++ rc = -EIO;
++ goto out_err;
++ }
++ }
++
++ /* write last byte */
++ iowrite8(buf[count],
++ chip->vendor.iobase +
++ TPM_DATA_FIFO(chip->vendor.locality));
++ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
++ &chip->vendor.int_queue);
++ status = tpm_tis_status(chip);
++ if ((status & TPM_STS_DATA_EXPECT) != 0) {
++ rc = -EIO;
++ goto out_err;
++ }
++
++ /* go and do it */
++ iowrite8(TPM_STS_GO,
++ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
++
++ if (chip->vendor.irq) {
++ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
++ if (wait_for_stat
++ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++ tpm_calc_ordinal_duration(chip, ordinal),
++ &chip->vendor.read_queue) < 0) {
++ rc = -ETIME;
++ goto out_err;
++ }
++ }
++ return len;
++out_err:
++ tpm_tis_ready(chip);
++ release_locality(chip, chip->vendor.locality, 0);
++ return rc;
++}
++
++static struct file_operations tis_ops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .open = tpm_open,
++ .read = tpm_read,
++ .write = tpm_write,
++ .release = tpm_release,
++};
++
++static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
++static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
++static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
++static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
++static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
++static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
++ NULL);
++static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
++static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
++
++static struct attribute *tis_attrs[] = {
++ &dev_attr_pubek.attr,
++ &dev_attr_pcrs.attr,
++ &dev_attr_enabled.attr,
++ &dev_attr_active.attr,
++ &dev_attr_owned.attr,
++ &dev_attr_temp_deactivated.attr,
++ &dev_attr_caps.attr,
++ &dev_attr_cancel.attr, NULL,
++};
++
++static struct attribute_group tis_attr_grp = {
++ .attrs = tis_attrs
++};
++
++static struct tpm_vendor_specific tpm_tis = {
++ .status = tpm_tis_status,
++ .recv = tpm_tis_recv,
++ .send = tpm_tis_send,
++ .cancel = tpm_tis_ready,
++ .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++ .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
++ .req_canceled = TPM_STS_COMMAND_READY,
++ .attr_group = &tis_attr_grp,
++ .miscdev = {
++ .fops = &tis_ops,},
++};
++
++static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
++ u32 interrupt;
++
++ interrupt = ioread32(chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality));
++
++ if (interrupt == 0)
++ return IRQ_NONE;
++
++ chip->vendor.irq = irq;
++
++ /* Clear interrupts handled with TPM_EOI */
++ iowrite32(interrupt,
++ chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality));
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs
*regs)
++{
++ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
++ u32 interrupt;
++ int i;
++
++ interrupt = ioread32(chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality));
++
++ if (interrupt == 0)
++ return IRQ_NONE;
++
++ if (interrupt & TPM_INTF_DATA_AVAIL_INT)
++ wake_up_interruptible(&chip->vendor.read_queue);
++ if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
++ for (i = 0; i < 5; i++)
++ if (check_locality(chip, i) >= 0)
++ break;
++ if (interrupt &
++ (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
++ TPM_INTF_CMD_READY_INT))
++ wake_up_interruptible(&chip->vendor.int_queue);
++
++ /* Clear interrupts handled with TPM_EOI */
++ iowrite32(interrupt,
++ chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality));
++ return IRQ_HANDLED;
++}
++
++static int interrupts = 1;
++module_param(interrupts, bool, 0444);
++MODULE_PARM_DESC(interrupts, "Enable interrupts");
++
++static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
++ const struct pnp_device_id *pnp_id)
++{
++ u32 vendor, intfcaps, intmask;
++ int rc, i;
++ unsigned long start, len;
++ struct tpm_chip *chip;
++
++ start = pnp_mem_start(pnp_dev, 0);
++ len = pnp_mem_len(pnp_dev, 0);
++
++ if (!start)
++ start = TIS_MEM_BASE;
++ if (!len)
++ len = TIS_MEM_LEN;
++
++ if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
++ return -ENODEV;
++
++ chip->vendor.iobase = ioremap(start, len);
++ if (!chip->vendor.iobase) {
++ rc = -EIO;
++ goto out_err;
++ }
++
++ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
++
++ /* Default timeouts */
++ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
++ chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
++ chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
++ chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
++
++ dev_info(&pnp_dev->dev,
++ "1.2 TPM (device-id 0x%X, rev-id %d)\n",
++ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
++
++ /* Figure out the capabilities */
++ intfcaps =
++ ioread32(chip->vendor.iobase +
++ TPM_INTF_CAPS(chip->vendor.locality));
++ dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
++ intfcaps);
++ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
++ dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
++ if (intfcaps & TPM_INTF_CMD_READY_INT)
++ dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
++ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
++ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
++ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
++ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
++ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
++ dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
++ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
++ dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
++ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
++ dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
++ if (intfcaps & TPM_INTF_STS_VALID_INT)
++ dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
++ if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
++ dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
++
++ if (request_locality(chip, 0) != 0) {
++ rc = -ENODEV;
++ goto out_err;
++ }
++
++ /* INTERRUPT Setup */
++ init_waitqueue_head(&chip->vendor.read_queue);
++ init_waitqueue_head(&chip->vendor.int_queue);
++
++ intmask =
++ ioread32(chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.locality));
++
++ intmask |= TPM_INTF_CMD_READY_INT
++ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
++ | TPM_INTF_STS_VALID_INT;
++
++ iowrite32(intmask,
++ chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.locality));
++ if (interrupts) {
++ chip->vendor.irq =
++ ioread8(chip->vendor.iobase +
++ TPM_INT_VECTOR(chip->vendor.locality));
++
++ for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
++ iowrite8(i, chip->vendor.iobase +
++ TPM_INT_VECTOR(chip->vendor.locality));
++ if (request_irq
++ (i, tis_int_probe, SA_SHIRQ,
++ chip->vendor.miscdev.name, chip) != 0) {
++ dev_info(chip->dev,
++ "Unable to request irq: %d for
probe\n",
++ i);
++ continue;
++ }
++
++ /* Clear all existing */
++ iowrite32(ioread32
++ (chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality)),
++ chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality));
++
++ /* Turn on */
++ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
++ chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.locality));
++
++ /* Generate Interrupts */
++ tpm_gen_interrupt(chip);
++
++ /* Turn off */
++ iowrite32(intmask,
++ chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.locality));
++ free_irq(i, chip);
++ }
++ }
++ if (chip->vendor.irq) {
++ iowrite8(chip->vendor.irq,
++ chip->vendor.iobase +
++ TPM_INT_VECTOR(chip->vendor.locality));
++ if (request_irq
++ (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
++ chip->vendor.miscdev.name, chip) != 0) {
++ dev_info(chip->dev,
++ "Unable to request irq: %d for use\n",
++ chip->vendor.irq);
++ chip->vendor.irq = 0;
++ } else {
++ /* Clear all existing */
++ iowrite32(ioread32
++ (chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality)),
++ chip->vendor.iobase +
++ TPM_INT_STATUS(chip->vendor.locality));
++
++ /* Turn on */
++ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
++ chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.locality));
++ }
++ }
++
++ INIT_LIST_HEAD(&chip->vendor.list);
++ spin_lock(&tis_lock);
++ list_add(&chip->vendor.list, &tis_chips);
++ spin_unlock(&tis_lock);
++
++ tpm_get_timeouts(chip);
++ tpm_continue_selftest(chip);
++
++ return 0;
++out_err:
++ if (chip->vendor.iobase)
++ iounmap(chip->vendor.iobase);
++ tpm_remove_hardware(chip->dev);
++ return rc;
++}
++
++static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
++{
++ return tpm_pm_suspend(&dev->dev, msg);
++}
++
++static int tpm_tis_pnp_resume(struct pnp_dev *dev)
++{
++ return tpm_pm_resume(&dev->dev);
++}
++
++static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
++ {"PNP0C31", 0}, /* TPM */
++ {"ATM1200", 0}, /* Atmel */
++ {"IFX0102", 0}, /* Infineon */
++ {"BCM0101", 0}, /* Broadcom */
++ {"NSC1200", 0}, /* National */
++ /* Add new here */
++ {"", 0}, /* User Specified */
++ {"", 0} /* Terminator */
++};
++
++static struct pnp_driver tis_pnp_driver = {
++ .name = "tpm_tis",
++ .id_table = tpm_pnp_tbl,
++ .probe = tpm_tis_pnp_init,
++ .suspend = tpm_tis_pnp_suspend,
++ .resume = tpm_tis_pnp_resume,
++};
++
++#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
++module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
++ sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
++MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
++
++static int __init init_tis(void)
++{
++ return pnp_register_driver(&tis_pnp_driver);
++}
++
++static void __exit cleanup_tis(void)
++{
++ struct tpm_vendor_specific *i, *j;
++ struct tpm_chip *chip;
++ spin_lock(&tis_lock);
++ list_for_each_entry_safe(i, j, &tis_chips, list) {
++ chip = to_tpm_chip(i);
++ iowrite32(~TPM_GLOBAL_INT_ENABLE &
++ ioread32(chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.
++ locality)),
++ chip->vendor.iobase +
++ TPM_INT_ENABLE(chip->vendor.locality));
++ release_locality(chip, chip->vendor.locality, 1);
++ if (chip->vendor.irq)
++ free_irq(chip->vendor.irq, chip);
++ iounmap(i->iobase);
++ list_del(&i->list);
++ tpm_remove_hardware(chip->dev);
++ }
++ spin_unlock(&tis_lock);
++ pnp_unregister_driver(&tis_pnp_driver);
++}
++
++module_init(init_tis);
++module_exit(cleanup_tis);
++MODULE_AUTHOR("Leendert van Doorn (leendert@xxxxxxxxxxxxxx)");
++MODULE_DESCRIPTION("TPM Driver");
++MODULE_VERSION("2.0");
++MODULE_LICENSE("GPL");
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/vsnprintf.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/vsnprintf.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,211 @@
+commit f796937a062c7aeb44cd0e75e1586c8543634a7d
+Author: Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
+Date: Sun Jun 25 05:49:17 2006 -0700
+
+ [PATCH] Fix bounds check in vsnprintf, to allow for a 0 size and NULL
buffer
+
+ This change allows callers to use a 0-byte buffer and a NULL buffer pointer
+ with vsnprintf, so it can be used to determine how large the resulting
+ formatted string will be.
+
+ Previously the code effectively treated a size of 0 as a size of 4G (on
+ 32-bit systems), with other checks preventing it from actually trying to
+ emit the string - but the terminal \0 would still be written, which would
+ crash if the buffer is NULL.
+
+ This change changes the boundary check so that 'end' points to the putative
+ location of the terminal '\0', which is only written if size > 0.
+
+ vsnprintf still allows the buffer size to be set very large, to allow
+ unbounded buffer sizes (to implement sprintf, etc).
+
+ [akpm@xxxxxxxx: fix long-vs-longlong confusion]
+ Signed-off-by: Jeremy Fitzhardinge <jeremy@xxxxxxxxxxxxx>
+ Signed-off-by: Chris Wright <chrisw@xxxxxxxxxxxx>
+ Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
+ Signed-off-by: Linus Torvalds <torvalds@xxxxxxxx>
+
+diff --git a/lib/vsprintf.c b/lib/vsprintf.c
+index b07db5c..f595947 100644
+--- a/lib/vsprintf.c
++++ b/lib/vsprintf.c
+@@ -187,49 +187,49 @@ static char * number(char * buf, char *
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT))) {
+ while(size-->0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+ }
+ if (sign) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = sign;
+ ++buf;
+ }
+ if (type & SPECIAL) {
+ if (base==8) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = '0';
+ ++buf;
+ } else if (base==16) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = '0';
+ ++buf;
+- if (buf <= end)
++ if (buf < end)
+ *buf = digits[33];
+ ++buf;
+ }
+ }
+ if (!(type & LEFT)) {
+ while (size-- > 0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = c;
+ ++buf;
+ }
+ }
+ while (i < precision--) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = '0';
+ ++buf;
+ }
+ while (i-- > 0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = tmp[i];
+ ++buf;
+ }
+ while (size-- > 0) {
+- if (buf <= end)
++ if (buf < end)
+ *buf = ' ';
+ ++buf;
+ }
+@@ -272,7 +272,8 @@ int vsnprintf(char *buf, size_t size, co
+ /* 'z' changed to 'Z' --davidm 1/25/99 */
+ /* 't' added for ptrdiff_t */
+
+- /* Reject out-of-range values early */
++ /* Reject out-of-range values early. Large positive sizes are
++ used for unknown buffer sizes. */
+ if (unlikely((int) size < 0)) {
+ /* There can be only one.. */
+ static int warn = 1;
+@@ -282,16 +283,17 @@ int vsnprintf(char *buf, size_t size, co
+ }
+
+ str = buf;
+- end = buf + size - 1;
++ end = buf + size;
+
+- if (end < buf - 1) {
+- end = ((void *) -1);
+- size = end - buf + 1;
++ /* Make sure end is always >= buf */
++ if (end < buf) {
++ end = ((void *)-1);
++ size = end - buf;
+ }
+
+ for (; *fmt ; ++fmt) {
+ if (*fmt != '%') {
+- if (str <= end)
++ if (str < end)
+ *str = *fmt;
+ ++str;
+ continue;
+@@ -357,17 +359,17 @@ int vsnprintf(char *buf, size_t size, co
+ case 'c':
+ if (!(flags & LEFT)) {
+ while (--field_width > 0) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ c = (unsigned char) va_arg(args, int);
+- if (str <= end)
++ if (str < end)
+ *str = c;
+ ++str;
+ while (--field_width > 0) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+@@ -382,18 +384,18 @@ int vsnprintf(char *buf, size_t size, co
+
+ if (!(flags & LEFT)) {
+ while (len < field_width--) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+ }
+ for (i = 0; i < len; ++i) {
+- if (str <= end)
++ if (str < end)
+ *str = *s;
+ ++str; ++s;
+ }
+ while (len < field_width--) {
+- if (str <= end)
++ if (str < end)
+ *str = ' ';
+ ++str;
+ }
+@@ -426,7 +428,7 @@ int vsnprintf(char *buf, size_t size, co
+ continue;
+
+ case '%':
+- if (str <= end)
++ if (str < end)
+ *str = '%';
+ ++str;
+ continue;
+@@ -449,11 +451,11 @@ int vsnprintf(char *buf, size_t size, co
+ break;
+
+ default:
+- if (str <= end)
++ if (str < end)
+ *str = '%';
+ ++str;
+ if (*fmt) {
+- if (str <= end)
++ if (str < end)
+ *str = *fmt;
+ ++str;
+ } else {
+@@ -483,14 +485,13 @@ int vsnprintf(char *buf, size_t size, co
+ str = number(str, end, num, base,
+ field_width, precision, flags);
+ }
+- if (str <= end)
+- *str = '\0';
+- else if (size > 0)
+- /* don't write out a null byte if the buf size is zero */
+- *end = '\0';
+- /* the trailing null byte doesn't count towards the total
+- * ++str;
+- */
++ if (size > 0) {
++ if (str < end)
++ *str = '\0';
++ else
++ *end = '\0';
++ }
++ /* the trailing null byte doesn't count towards the total */
+ return str-buf;
+ }
+
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/x86-elfnote-as-preprocessor-macro.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/x86-elfnote-as-preprocessor-macro.patch Wed Nov
29 11:07:28 2006 -0700
@@ -0,0 +1,43 @@
+diff -pruN ../orig-linux-2.6.16.29/include/linux/elfnote.h
./include/linux/elfnote.h
+--- ../orig-linux-2.6.16.29/include/linux/elfnote.h 2006-09-19
14:06:10.000000000 +0100
++++ ./include/linux/elfnote.h 2006-09-19 14:06:20.000000000 +0100
+@@ -31,22 +31,24 @@
+ /*
+ * Generate a structure with the same shape as Elf{32,64}_Nhdr (which
+ * turn out to be the same size and shape), followed by the name and
+- * desc data with appropriate padding. The 'desc' argument includes
+- * the assembler pseudo op defining the type of the data: .asciz
+- * "hello, world"
++ * desc data with appropriate padding. The 'desctype' argument is the
++ * assembler pseudo op defining the type of the data e.g. .asciz while
++ * 'descdata' is the data itself e.g. "hello, world".
++ *
++ * e.g. ELFNOTE(XYZCo, 42, .asciz, "forty-two")
++ * ELFNOTE(XYZCo, 12, .long, 0xdeadbeef)
+ */
+-.macro ELFNOTE name type desc:vararg
+-.pushsection ".note.\name"
+- .align 4
+- .long 2f - 1f /* namesz */
+- .long 4f - 3f /* descsz */
+- .long \type
+-1:.asciz "\name"
+-2:.align 4
+-3:\desc
+-4:.align 4
+-.popsection
+-.endm
++#define ELFNOTE(name, type, desctype, descdata) \
++.pushsection .note.name ; \
++ .align 4 ; \
++ .long 2f - 1f /* namesz */ ; \
++ .long 4f - 3f /* descsz */ ; \
++ .long type ; \
++1:.asciz "name" ; \
++2:.align 4 ; \
++3:desctype descdata ; \
++4:.align 4 ; \
++.popsection ;
+ #else /* !__ASSEMBLER__ */
+ #include <linux/elf.h>
+ /*
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/x86-increase-interrupt-vector-range.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/x86-increase-interrupt-vector-range.patch Wed Nov
29 11:07:28 2006 -0700
@@ -0,0 +1,89 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/entry.S
./arch/i386/kernel/entry.S
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/entry.S 2006-09-19
14:05:44.000000000 +0100
++++ ./arch/i386/kernel/entry.S 2006-09-19 14:05:56.000000000 +0100
+@@ -406,7 +406,7 @@ vector=0
+ ENTRY(irq_entries_start)
+ .rept NR_IRQS
+ ALIGN
+-1: pushl $vector-256
++1: pushl $~(vector)
+ jmp common_interrupt
+ .data
+ .long 1b
+@@ -423,7 +423,7 @@ common_interrupt:
+
+ #define BUILD_INTERRUPT(name, nr) \
+ ENTRY(name) \
+- pushl $nr-256; \
++ pushl $~(nr); \
+ SAVE_ALL \
+ movl %esp,%eax; \
+ call smp_/**/name; \
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/irq.c
./arch/i386/kernel/irq.c
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/irq.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/i386/kernel/irq.c 2006-09-19 14:05:56.000000000 +0100
+@@ -53,8 +53,8 @@ static union irq_ctx *softirq_ctx[NR_CPU
+ */
+ fastcall unsigned int do_IRQ(struct pt_regs *regs)
+ {
+- /* high bits used in ret_from_ code */
+- int irq = regs->orig_eax & 0xff;
++ /* high bit used in ret_from_ code */
++ int irq = ~regs->orig_eax;
+ #ifdef CONFIG_4KSTACKS
+ union irq_ctx *curctx, *irqctx;
+ u32 *isp;
+diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/kernel/entry.S
./arch/x86_64/kernel/entry.S
+--- ../orig-linux-2.6.16.29/arch/x86_64/kernel/entry.S 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/x86_64/kernel/entry.S 2006-09-19 14:05:56.000000000 +0100
+@@ -596,7 +596,7 @@ retint_kernel:
+ */
+ .macro apicinterrupt num,func
+ INTR_FRAME
+- pushq $\num-256
++ pushq $~(\num)
+ CFI_ADJUST_CFA_OFFSET 8
+ interrupt \func
+ jmp ret_from_intr
+diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/kernel/irq.c
./arch/x86_64/kernel/irq.c
+--- ../orig-linux-2.6.16.29/arch/x86_64/kernel/irq.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/x86_64/kernel/irq.c 2006-09-19 14:05:56.000000000 +0100
+@@ -96,8 +96,8 @@ skip:
+ */
+ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
+ {
+- /* high bits used in ret_from_ code */
+- unsigned irq = regs->orig_rax & 0xff;
++ /* high bit used in ret_from_ code */
++ unsigned irq = ~regs->orig_rax;
+
+ exit_idle();
+ irq_enter();
+diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/kernel/smp.c
./arch/x86_64/kernel/smp.c
+--- ../orig-linux-2.6.16.29/arch/x86_64/kernel/smp.c 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/x86_64/kernel/smp.c 2006-09-19 14:05:56.000000000 +0100
+@@ -135,10 +135,10 @@ asmlinkage void smp_invalidate_interrupt
+
+ cpu = smp_processor_id();
+ /*
+- * orig_rax contains the interrupt vector - 256.
++ * orig_rax contains the negated interrupt vector.
+ * Use that to determine where the sender put the data.
+ */
+- sender = regs->orig_rax + 256 - INVALIDATE_TLB_VECTOR_START;
++ sender = ~regs->orig_rax - INVALIDATE_TLB_VECTOR_START;
+ f = &per_cpu(flush_state, sender);
+
+ if (!cpu_isset(cpu, f->flush_cpumask))
+diff -pruN ../orig-linux-2.6.16.29/include/asm-x86_64/hw_irq.h
./include/asm-x86_64/hw_irq.h
+--- ../orig-linux-2.6.16.29/include/asm-x86_64/hw_irq.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-x86_64/hw_irq.h 2006-09-19 14:05:56.000000000 +0100
+@@ -127,7 +127,7 @@ asmlinkage void IRQ_NAME(nr); \
+ __asm__( \
+ "\n.p2align\n" \
+ "IRQ" #nr "_interrupt:\n\t" \
+- "push $" #nr "-256 ; " \
++ "push $~(" #nr ") ; " \
+ "jmp common_interrupt");
+
+ #if defined(CONFIG_X86_IO_APIC)
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++
b/patches/linux-2.6.16.33/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,143 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/vmlinux.lds.S
./arch/i386/kernel/vmlinux.lds.S
+--- ../orig-linux-2.6.16.29/arch/i386/kernel/vmlinux.lds.S 2006-09-19
14:05:48.000000000 +0100
++++ ./arch/i386/kernel/vmlinux.lds.S 2006-09-19 14:06:10.000000000 +0100
+@@ -12,6 +12,12 @@ OUTPUT_FORMAT("elf32-i386", "elf32-i386"
+ OUTPUT_ARCH(i386)
+ ENTRY(phys_startup_32)
+ jiffies = jiffies_64;
++
++PHDRS {
++ text PT_LOAD FLAGS(5); /* R_E */
++ data PT_LOAD FLAGS(7); /* RWE */
++ note PT_NOTE FLAGS(4); /* R__ */
++}
+ SECTIONS
+ {
+ . = __KERNEL_START;
+@@ -25,7 +31,7 @@ SECTIONS
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+- } = 0x9090
++ } :text = 0x9090
+
+ _etext = .; /* End of text section */
+
+@@ -47,7 +53,7 @@ SECTIONS
+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
+ *(.data)
+ CONSTRUCTORS
+- }
++ } :data
+
+ . = ALIGN(4096);
+ __nosave_begin = .;
+@@ -154,4 +160,6 @@ SECTIONS
+ STABS_DEBUG
+
+ DWARF_DEBUG
++
++ NOTES
+ }
+diff -pruN ../orig-linux-2.6.16.29/include/asm-generic/vmlinux.lds.h
./include/asm-generic/vmlinux.lds.h
+--- ../orig-linux-2.6.16.29/include/asm-generic/vmlinux.lds.h 2006-09-12
19:02:10.000000000 +0100
++++ ./include/asm-generic/vmlinux.lds.h 2006-09-19 14:06:10.000000000
+0100
+@@ -152,3 +152,6 @@
+ .stab.index 0 : { *(.stab.index) } \
+ .stab.indexstr 0 : { *(.stab.indexstr) } \
+ .comment 0 : { *(.comment) }
++
++#define NOTES \
++ .notes : { *(.note.*) } :note
+diff -pruN ../orig-linux-2.6.16.29/include/linux/elfnote.h
./include/linux/elfnote.h
+--- ../orig-linux-2.6.16.29/include/linux/elfnote.h 1970-01-01
01:00:00.000000000 +0100
++++ ./include/linux/elfnote.h 2006-09-19 14:06:10.000000000 +0100
+@@ -0,0 +1,88 @@
++#ifndef _LINUX_ELFNOTE_H
++#define _LINUX_ELFNOTE_H
++/*
++ * Helper macros to generate ELF Note structures, which are put into a
++ * PT_NOTE segment of the final vmlinux image. These are useful for
++ * including name-value pairs of metadata into the kernel binary (or
++ * modules?) for use by external programs.
++ *
++ * Each note has three parts: a name, a type and a desc. The name is
++ * intended to distinguish the note's originator, so it would be a
++ * company, project, subsystem, etc; it must be in a suitable form for
++ * use in a section name. The type is an integer which is used to tag
++ * the data, and is considered to be within the "name" namespace (so
++ * "FooCo"'s type 42 is distinct from "BarProj"'s type 42). The
++ * "desc" field is the actual data. There are no constraints on the
++ * desc field's contents, though typically they're fairly small.
++ *
++ * All notes from a given NAME are put into a section named
++ * .note.NAME. When the kernel image is finally linked, all the notes
++ * are packed into a single .notes section, which is mapped into the
++ * PT_NOTE segment. Because notes for a given name are grouped into
++ * the same section, they'll all be adjacent the output file.
++ *
++ * This file defines macros for both C and assembler use. Their
++ * syntax is slightly different, but they're semantically similar.
++ *
++ * See the ELF specification for more detail about ELF notes.
++ */
++
++#ifdef __ASSEMBLER__
++/*
++ * Generate a structure with the same shape as Elf{32,64}_Nhdr (which
++ * turn out to be the same size and shape), followed by the name and
++ * desc data with appropriate padding. The 'desc' argument includes
++ * the assembler pseudo op defining the type of the data: .asciz
++ * "hello, world"
++ */
++.macro ELFNOTE name type desc:vararg
++.pushsection ".note.\name"
++ .align 4
++ .long 2f - 1f /* namesz */
++ .long 4f - 3f /* descsz */
++ .long \type
++1:.asciz "\name"
++2:.align 4
++3:\desc
++4:.align 4
++.popsection
++.endm
++#else /* !__ASSEMBLER__ */
++#include <linux/elf.h>
++/*
++ * Use an anonymous structure which matches the shape of
++ * Elf{32,64}_Nhdr, but includes the name and desc data. The size and
++ * type of name and desc depend on the macro arguments. "name" must
++ * be a literal string, and "desc" must be passed by value. You may
++ * only define one note per line, since __LINE__ is used to generate
++ * unique symbols.
++ */
++#define _ELFNOTE_PASTE(a,b) a##b
++#define _ELFNOTE(size, name, unique, type, desc) \
++ static const struct { \
++ struct elf##size##_note _nhdr; \
++ unsigned char _name[sizeof(name)] \
++ __attribute__((aligned(sizeof(Elf##size##_Word)))); \
++ typeof(desc) _desc \
++
__attribute__((aligned(sizeof(Elf##size##_Word)))); \
++ } _ELFNOTE_PASTE(_note_, unique) \
++ __attribute_used__ \
++ __attribute__((section(".note." name), \
++ aligned(sizeof(Elf##size##_Word)), \
++ unused)) = { \
++ { \
++ sizeof(name), \
++ sizeof(desc), \
++ type, \
++ }, \
++ name, \
++ desc \
++ }
++#define ELFNOTE(size, name, type, desc) \
++ _ELFNOTE(size, name, __LINE__, type, desc)
++
++#define ELFNOTE32(name, type, desc) ELFNOTE(32, name, type, desc)
++#define ELFNOTE64(name, type, desc) ELFNOTE(64, name, type, desc)
++#endif /* __ASSEMBLER__ */
++
++#endif /* _LINUX_ELFNOTE_H */
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++
b/patches/linux-2.6.16.33/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch
Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,84 @@
+diff -pruN ../orig-linux-2.6.16.29/arch/x86_64/kernel/vmlinux.lds.S
./arch/x86_64/kernel/vmlinux.lds.S
+--- ../orig-linux-2.6.16.29/arch/x86_64/kernel/vmlinux.lds.S 2006-09-12
19:02:10.000000000 +0100
++++ ./arch/x86_64/kernel/vmlinux.lds.S 2006-09-19 14:06:15.000000000 +0100
+@@ -14,6 +14,12 @@ OUTPUT_FORMAT("elf64-x86-64", "elf64-x86
+ OUTPUT_ARCH(i386:x86-64)
+ ENTRY(phys_startup_64)
+ jiffies_64 = jiffies;
++PHDRS {
++ text PT_LOAD FLAGS(5); /* R_E */
++ data PT_LOAD FLAGS(7); /* RWE */
++ user PT_LOAD FLAGS(7); /* RWE */
++ note PT_NOTE FLAGS(4); /* R__ */
++}
+ SECTIONS
+ {
+ . = __START_KERNEL;
+@@ -26,7 +32,7 @@ SECTIONS
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
+- } = 0x9090
++ } :text = 0x9090
+ /* out-of-line lock text */
+ .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET) { *(.text.lock) }
+
+@@ -43,17 +49,10 @@ SECTIONS
+ .data : AT(ADDR(.data) - LOAD_OFFSET) {
+ *(.data)
+ CONSTRUCTORS
+- }
++ } :data
+
+ _edata = .; /* End of data section */
+
+- __bss_start = .; /* BSS */
+- .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
+- *(.bss.page_aligned)
+- *(.bss)
+- }
+- __bss_stop = .;
+-
+ . = ALIGN(PAGE_SIZE);
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+@@ -75,7 +74,7 @@ SECTIONS
+ #define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
+
+ . = VSYSCALL_ADDR;
+- .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) }
++ .vsyscall_0 : AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) } :user
+ __vsyscall_0 = VSYSCALL_VIRT_ADDR;
+
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
+@@ -118,7 +117,7 @@ SECTIONS
+ . = ALIGN(8192); /* init_task */
+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+ *(.data.init_task)
+- }
++ } :data
+
+ . = ALIGN(4096);
+ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+@@ -188,6 +187,14 @@ SECTIONS
+ . = ALIGN(4096);
+ __nosave_end = .;
+
++ __bss_start = .; /* BSS */
++ . = ALIGN(4096);
++ .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
++ *(.bss.page_aligned)
++ *(.bss)
++ }
++ __bss_stop = .;
++
+ _end = . ;
+
+ /* Sections to be discarded */
+@@ -201,4 +208,6 @@ SECTIONS
+ STABS_DEBUG
+
+ DWARF_DEBUG
++
++ NOTES
+ }
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.33/xen-hotplug.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/xen-hotplug.patch Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,12 @@
+diff -pruN ../orig-linux-2.6.16.29/fs/proc/proc_misc.c ./fs/proc/proc_misc.c
+--- ../orig-linux-2.6.16.29/fs/proc/proc_misc.c 2006-09-12
19:02:10.000000000 +0100
++++ ./fs/proc/proc_misc.c 2006-09-19 14:06:00.000000000 +0100
+@@ -433,7 +433,7 @@ static int show_stat(struct seq_file *p,
+ (unsigned long long)cputime64_to_clock_t(irq),
+ (unsigned long long)cputime64_to_clock_t(softirq),
+ (unsigned long long)cputime64_to_clock_t(steal));
+- for_each_online_cpu(i) {
++ for_each_cpu(i) {
+
+ /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
+ user = kstat_cpu(i).cpustat.user;
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.33/xenoprof-generic.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/patches/linux-2.6.16.33/xenoprof-generic.patch Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,662 @@
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/buffer_sync.c
./drivers/oprofile/buffer_sync.c
+--- ../orig-linux-2.6.16.29/drivers/oprofile/buffer_sync.c 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/buffer_sync.c 2006-11-06 15:16:52.000000000 -0800
+@@ -6,6 +6,10 @@
+ *
+ * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
+ *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
++ *
+ * This is the core of the buffer management. Each
+ * CPU buffer is processed and entered into the
+ * global event buffer. Such processing is necessary
+@@ -38,6 +42,7 @@ static cpumask_t marked_cpus = CPU_MASK_
+ static DEFINE_SPINLOCK(task_mortuary);
+ static void process_task_mortuary(void);
+
++static int cpu_current_domain[NR_CPUS];
+
+ /* Take ownership of the task struct and place it on the
+ * list for processing. Only after two full buffer syncs
+@@ -146,6 +151,11 @@ static void end_sync(void)
+ int sync_start(void)
+ {
+ int err;
++ int i;
++
++ for (i = 0; i < NR_CPUS; i++) {
++ cpu_current_domain[i] = COORDINATOR_DOMAIN;
++ }
+
+ start_cpu_work();
+
+@@ -275,15 +285,31 @@ static void add_cpu_switch(int i)
+ last_cookie = INVALID_COOKIE;
+ }
+
+-static void add_kernel_ctx_switch(unsigned int in_kernel)
++static void add_cpu_mode_switch(unsigned int cpu_mode)
+ {
+ add_event_entry(ESCAPE_CODE);
+- if (in_kernel)
+- add_event_entry(KERNEL_ENTER_SWITCH_CODE);
+- else
+- add_event_entry(KERNEL_EXIT_SWITCH_CODE);
++ switch (cpu_mode) {
++ case CPU_MODE_USER:
++ add_event_entry(USER_ENTER_SWITCH_CODE);
++ break;
++ case CPU_MODE_KERNEL:
++ add_event_entry(KERNEL_ENTER_SWITCH_CODE);
++ break;
++ case CPU_MODE_XEN:
++ add_event_entry(XEN_ENTER_SWITCH_CODE);
++ break;
++ default:
++ break;
++ }
+ }
+-
++
++static void add_domain_switch(unsigned long domain_id)
++{
++ add_event_entry(ESCAPE_CODE);
++ add_event_entry(DOMAIN_SWITCH_CODE);
++ add_event_entry(domain_id);
++}
++
+ static void
+ add_user_ctx_switch(struct task_struct const * task, unsigned long cookie)
+ {
+@@ -348,9 +374,9 @@ static int add_us_sample(struct mm_struc
+ * for later lookup from userspace.
+ */
+ static int
+-add_sample(struct mm_struct * mm, struct op_sample * s, int in_kernel)
++add_sample(struct mm_struct * mm, struct op_sample * s, int cpu_mode)
+ {
+- if (in_kernel) {
++ if (cpu_mode >= CPU_MODE_KERNEL) {
+ add_sample_entry(s->eip, s->event);
+ return 1;
+ } else if (mm) {
+@@ -496,15 +522,21 @@ void sync_buffer(int cpu)
+ struct mm_struct *mm = NULL;
+ struct task_struct * new;
+ unsigned long cookie = 0;
+- int in_kernel = 1;
++ int cpu_mode = 1;
+ unsigned int i;
+ sync_buffer_state state = sb_buffer_start;
+ unsigned long available;
++ int domain_switch = 0;
+
+ down(&buffer_sem);
+
+ add_cpu_switch(cpu);
+
++ /* We need to assign the first samples in this CPU buffer to the
++ same domain that we were processing at the last sync_buffer */
++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) {
++ add_domain_switch(cpu_current_domain[cpu]);
++ }
+ /* Remember, only we can modify tail_pos */
+
+ available = get_slots(cpu_buf);
+@@ -512,16 +544,18 @@ void sync_buffer(int cpu)
+ for (i = 0; i < available; ++i) {
+ struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos];
+
+- if (is_code(s->eip)) {
+- if (s->event <= CPU_IS_KERNEL) {
+- /* kernel/userspace switch */
+- in_kernel = s->event;
++ if (is_code(s->eip) && !domain_switch) {
++ if (s->event <= CPU_MODE_XEN) {
++ /* xen/kernel/userspace switch */
++ cpu_mode = s->event;
+ if (state == sb_buffer_start)
+ state = sb_sample_start;
+- add_kernel_ctx_switch(s->event);
++ add_cpu_mode_switch(s->event);
+ } else if (s->event == CPU_TRACE_BEGIN) {
+ state = sb_bt_start;
+ add_trace_begin();
++ } else if (s->event == CPU_DOMAIN_SWITCH) {
++ domain_switch = 1;
+ } else {
+ struct mm_struct * oldmm = mm;
+
+@@ -535,11 +569,21 @@ void sync_buffer(int cpu)
+ add_user_ctx_switch(new, cookie);
+ }
+ } else {
+- if (state >= sb_bt_start &&
+- !add_sample(mm, s, in_kernel)) {
+- if (state == sb_bt_start) {
+- state = sb_bt_ignore;
+-
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++ if (domain_switch) {
++ cpu_current_domain[cpu] = s->eip;
++ add_domain_switch(s->eip);
++ domain_switch = 0;
++ } else {
++ if (cpu_current_domain[cpu] !=
++ COORDINATOR_DOMAIN) {
++ add_sample_entry(s->eip, s->event);
++ }
++ else if (state >= sb_bt_start &&
++ !add_sample(mm, s, cpu_mode)) {
++ if (state == sb_bt_start) {
++ state = sb_bt_ignore;
++
atomic_inc(&oprofile_stats.bt_lost_no_mapping);
++ }
+ }
+ }
+ }
+@@ -548,6 +592,11 @@ void sync_buffer(int cpu)
+ }
+ release_mm(mm);
+
++ /* We reset domain to COORDINATOR at each CPU switch */
++ if (cpu_current_domain[cpu] != COORDINATOR_DOMAIN) {
++ add_domain_switch(COORDINATOR_DOMAIN);
++ }
++
+ mark_done(cpu);
+
+ up(&buffer_sem);
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.c
./drivers/oprofile/cpu_buffer.c
+--- ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.c 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/cpu_buffer.c 2006-11-06 14:47:55.000000000 -0800
+@@ -6,6 +6,10 @@
+ *
+ * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
+ *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
++ *
+ * Each CPU has a local buffer that stores PC value/event
+ * pairs. We also log context switches when we notice them.
+ * Eventually each CPU's buffer is processed into the global
+@@ -34,6 +38,8 @@ static void wq_sync_buffer(void *);
+ #define DEFAULT_TIMER_EXPIRE (HZ / 10)
+ static int work_enabled;
+
++static int32_t current_domain = COORDINATOR_DOMAIN;
++
+ void free_cpu_buffers(void)
+ {
+ int i;
+@@ -58,7 +64,7 @@ int alloc_cpu_buffers(void)
+ goto fail;
+
+ b->last_task = NULL;
+- b->last_is_kernel = -1;
++ b->last_cpu_mode = -1;
+ b->tracing = 0;
+ b->buffer_size = buffer_size;
+ b->tail_pos = 0;
+@@ -114,7 +120,7 @@ void cpu_buffer_reset(struct oprofile_cp
+ * collected will populate the buffer with proper
+ * values to initialize the buffer
+ */
+- cpu_buf->last_is_kernel = -1;
++ cpu_buf->last_cpu_mode = -1;
+ cpu_buf->last_task = NULL;
+ }
+
+@@ -164,13 +170,13 @@ add_code(struct oprofile_cpu_buffer * bu
+ * because of the head/tail separation of the writer and reader
+ * of the CPU buffer.
+ *
+- * is_kernel is needed because on some architectures you cannot
++ * cpu_mode is needed because on some architectures you cannot
+ * tell if you are in kernel or user space simply by looking at
+- * pc. We tag this in the buffer by generating kernel enter/exit
+- * events whenever is_kernel changes
++ * pc. We tag this in the buffer by generating kernel/user (and xen)
++ * enter events whenever cpu_mode changes
+ */
+ static int log_sample(struct oprofile_cpu_buffer * cpu_buf, unsigned long pc,
+- int is_kernel, unsigned long event)
++ int cpu_mode, unsigned long event)
+ {
+ struct task_struct * task;
+
+@@ -181,18 +187,18 @@ static int log_sample(struct oprofile_cp
+ return 0;
+ }
+
+- is_kernel = !!is_kernel;
+-
+ task = current;
+
+ /* notice a switch from user->kernel or vice versa */
+- if (cpu_buf->last_is_kernel != is_kernel) {
+- cpu_buf->last_is_kernel = is_kernel;
+- add_code(cpu_buf, is_kernel);
++ if (cpu_buf->last_cpu_mode != cpu_mode) {
++ cpu_buf->last_cpu_mode = cpu_mode;
++ add_code(cpu_buf, cpu_mode);
+ }
+-
++
+ /* notice a task switch */
+- if (cpu_buf->last_task != task) {
++ /* if not processing other domain samples */
++ if ((cpu_buf->last_task != task) &&
++ (current_domain == COORDINATOR_DOMAIN)) {
+ cpu_buf->last_task = task;
+ add_code(cpu_buf, (unsigned long)task);
+ }
+@@ -269,6 +275,25 @@ void oprofile_add_trace(unsigned long pc
+ add_sample(cpu_buf, pc, 0);
+ }
+
++int oprofile_add_domain_switch(int32_t domain_id)
++{
++ struct oprofile_cpu_buffer * cpu_buf = &cpu_buffer[smp_processor_id()];
++
++ /* should have space for switching into and out of domain
++ (2 slots each) plus one sample and one cpu mode switch */
++ if (((nr_available_slots(cpu_buf) < 6) &&
++ (domain_id != COORDINATOR_DOMAIN)) ||
++ (nr_available_slots(cpu_buf) < 2))
++ return 0;
++
++ add_code(cpu_buf, CPU_DOMAIN_SWITCH);
++ add_sample(cpu_buf, domain_id, 0);
++
++ current_domain = domain_id;
++
++ return 1;
++}
++
+ /*
+ * This serves to avoid cpu buffer overflow, and makes sure
+ * the task mortuary progresses
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.h
./drivers/oprofile/cpu_buffer.h
+--- ../orig-linux-2.6.16.29/drivers/oprofile/cpu_buffer.h 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/cpu_buffer.h 2006-11-06 14:47:55.000000000 -0800
+@@ -36,7 +36,7 @@ struct oprofile_cpu_buffer {
+ volatile unsigned long tail_pos;
+ unsigned long buffer_size;
+ struct task_struct * last_task;
+- int last_is_kernel;
++ int last_cpu_mode;
+ int tracing;
+ struct op_sample * buffer;
+ unsigned long sample_received;
+@@ -51,7 +51,10 @@ extern struct oprofile_cpu_buffer cpu_bu
+ void cpu_buffer_reset(struct oprofile_cpu_buffer * cpu_buf);
+
+ /* transient events for the CPU buffer -> event buffer */
+-#define CPU_IS_KERNEL 1
+-#define CPU_TRACE_BEGIN 2
++#define CPU_MODE_USER 0
++#define CPU_MODE_KERNEL 1
++#define CPU_MODE_XEN 2
++#define CPU_TRACE_BEGIN 3
++#define CPU_DOMAIN_SWITCH 4
+
+ #endif /* OPROFILE_CPU_BUFFER_H */
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/event_buffer.h
./drivers/oprofile/event_buffer.h
+--- ../orig-linux-2.6.16.29/drivers/oprofile/event_buffer.h 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/event_buffer.h 2006-11-06 14:47:55.000000000 -0800
+@@ -29,15 +29,20 @@ void wake_up_buffer_waiter(void);
+ #define CPU_SWITCH_CODE 2
+ #define COOKIE_SWITCH_CODE 3
+ #define KERNEL_ENTER_SWITCH_CODE 4
+-#define KERNEL_EXIT_SWITCH_CODE 5
++#define USER_ENTER_SWITCH_CODE 5
+ #define MODULE_LOADED_CODE 6
+ #define CTX_TGID_CODE 7
+ #define TRACE_BEGIN_CODE 8
+ #define TRACE_END_CODE 9
++#define XEN_ENTER_SWITCH_CODE 10
++#define DOMAIN_SWITCH_CODE 11
+
+ #define INVALID_COOKIE ~0UL
+ #define NO_COOKIE 0UL
+
++/* Constant used to refer to coordinator domain (Xen) */
++#define COORDINATOR_DOMAIN -1
++
+ /* add data to the event buffer */
+ void add_event_entry(unsigned long data);
+
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/oprof.c
./drivers/oprofile/oprof.c
+--- ../orig-linux-2.6.16.29/drivers/oprofile/oprof.c 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/oprof.c 2006-11-06 14:47:55.000000000 -0800
+@@ -5,6 +5,10 @@
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
++ *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+ #include <linux/kernel.h>
+@@ -19,7 +23,7 @@
+ #include "cpu_buffer.h"
+ #include "buffer_sync.h"
+ #include "oprofile_stats.h"
+-
++
+ struct oprofile_operations oprofile_ops;
+
+ unsigned long oprofile_started;
+@@ -33,6 +37,32 @@ static DECLARE_MUTEX(start_sem);
+ */
+ static int timer = 0;
+
++int oprofile_set_active(int active_domains[], unsigned int adomains)
++{
++ int err;
++
++ if (!oprofile_ops.set_active)
++ return -EINVAL;
++
++ down(&start_sem);
++ err = oprofile_ops.set_active(active_domains, adomains);
++ up(&start_sem);
++ return err;
++}
++
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains)
++{
++ int err;
++
++ if (!oprofile_ops.set_passive)
++ return -EINVAL;
++
++ down(&start_sem);
++ err = oprofile_ops.set_passive(passive_domains, pdomains);
++ up(&start_sem);
++ return err;
++}
++
+ int oprofile_setup(void)
+ {
+ int err;
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/oprof.h
./drivers/oprofile/oprof.h
+--- ../orig-linux-2.6.16.29/drivers/oprofile/oprof.h 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/oprof.h 2006-11-06 14:47:55.000000000 -0800
+@@ -35,5 +35,8 @@ void oprofile_create_files(struct super_
+ void oprofile_timer_init(struct oprofile_operations * ops);
+
+ int oprofile_set_backtrace(unsigned long depth);
++
++int oprofile_set_active(int active_domains[], unsigned int adomains);
++int oprofile_set_passive(int passive_domains[], unsigned int pdomains);
+
+ #endif /* OPROF_H */
+diff -pruN ../orig-linux-2.6.16.29/drivers/oprofile/oprofile_files.c
./drivers/oprofile/oprofile_files.c
+--- ../orig-linux-2.6.16.29/drivers/oprofile/oprofile_files.c 2006-11-06
14:46:52.000000000 -0800
++++ ./drivers/oprofile/oprofile_files.c 2006-11-06 14:47:55.000000000
-0800
+@@ -5,15 +5,21 @@
+ * @remark Read the file COPYING
+ *
+ * @author John Levon <levon@xxxxxxxxxxxxxxxxx>
++ *
++ * Modified by Aravind Menon for Xen
++ * These modifications are:
++ * Copyright (C) 2005 Hewlett-Packard Co.
+ */
+
+ #include <linux/fs.h>
+ #include <linux/oprofile.h>
++#include <asm/uaccess.h>
++#include <linux/ctype.h>
+
+ #include "event_buffer.h"
+ #include "oprofile_stats.h"
+ #include "oprof.h"
+-
++
+ unsigned long fs_buffer_size = 131072;
+ unsigned long fs_cpu_buffer_size = 8192;
+ unsigned long fs_buffer_watershed = 32768; /* FIXME: tune */
+@@ -117,11 +123,202 @@ static ssize_t dump_write(struct file *
+ static struct file_operations dump_fops = {
+ .write = dump_write,
+ };
+-
++
++#define TMPBUFSIZE 512
++
++static unsigned int adomains = 0;
++static int active_domains[MAX_OPROF_DOMAINS + 1];
++static DEFINE_MUTEX(adom_mutex);
++
++static ssize_t adomain_write(struct file * file, char const __user * buf,
++ size_t count, loff_t * offset)
++{
++ char *tmpbuf;
++ char *startp, *endp;
++ int i;
++ unsigned long val;
++ ssize_t retval = count;
++
++ if (*offset)
++ return -EINVAL;
++ if (count > TMPBUFSIZE - 1)
++ return -EINVAL;
++
++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++ return -ENOMEM;
++
++ if (copy_from_user(tmpbuf, buf, count)) {
++ kfree(tmpbuf);
++ return -EFAULT;
++ }
++ tmpbuf[count] = 0;
++
++ mutex_lock(&adom_mutex);
++
++ startp = tmpbuf;
++ /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
++ for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
++ val = simple_strtoul(startp, &endp, 0);
++ if (endp == startp)
++ break;
++ while (ispunct(*endp) || isspace(*endp))
++ endp++;
++ active_domains[i] = val;
++ if (active_domains[i] != val)
++ /* Overflow, force error below */
++ i = MAX_OPROF_DOMAINS + 1;
++ startp = endp;
++ }
++ /* Force error on trailing junk */
++ adomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
++
++ kfree(tmpbuf);
++
++ if (adomains > MAX_OPROF_DOMAINS
++ || oprofile_set_active(active_domains, adomains)) {
++ adomains = 0;
++ retval = -EINVAL;
++ }
++
++ mutex_unlock(&adom_mutex);
++ return retval;
++}
++
++static ssize_t adomain_read(struct file * file, char __user * buf,
++ size_t count, loff_t * offset)
++{
++ char * tmpbuf;
++ size_t len;
++ int i;
++ ssize_t retval;
++
++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++ return -ENOMEM;
++
++ mutex_lock(&adom_mutex);
++
++ len = 0;
++ for (i = 0; i < adomains; i++)
++ len += snprintf(tmpbuf + len,
++ len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
++ "%u ", active_domains[i]);
++ WARN_ON(len > TMPBUFSIZE);
++ if (len != 0 && len <= TMPBUFSIZE)
++ tmpbuf[len-1] = '\n';
++
++ mutex_unlock(&adom_mutex);
++
++ retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
++
++ kfree(tmpbuf);
++ return retval;
++}
++
++
++static struct file_operations active_domain_ops = {
++ .read = adomain_read,
++ .write = adomain_write,
++};
++
++static unsigned int pdomains = 0;
++static int passive_domains[MAX_OPROF_DOMAINS];
++static DEFINE_MUTEX(pdom_mutex);
++
++static ssize_t pdomain_write(struct file * file, char const __user * buf,
++ size_t count, loff_t * offset)
++{
++ char *tmpbuf;
++ char *startp, *endp;
++ int i;
++ unsigned long val;
++ ssize_t retval = count;
++
++ if (*offset)
++ return -EINVAL;
++ if (count > TMPBUFSIZE - 1)
++ return -EINVAL;
++
++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++ return -ENOMEM;
++
++ if (copy_from_user(tmpbuf, buf, count)) {
++ kfree(tmpbuf);
++ return -EFAULT;
++ }
++ tmpbuf[count] = 0;
++
++ mutex_lock(&pdom_mutex);
++
++ startp = tmpbuf;
++ /* Parse one more than MAX_OPROF_DOMAINS, for easy error checking */
++ for (i = 0; i <= MAX_OPROF_DOMAINS; i++) {
++ val = simple_strtoul(startp, &endp, 0);
++ if (endp == startp)
++ break;
++ while (ispunct(*endp) || isspace(*endp))
++ endp++;
++ passive_domains[i] = val;
++ if (passive_domains[i] != val)
++ /* Overflow, force error below */
++ i = MAX_OPROF_DOMAINS + 1;
++ startp = endp;
++ }
++ /* Force error on trailing junk */
++ pdomains = *startp ? MAX_OPROF_DOMAINS + 1 : i;
++
++ kfree(tmpbuf);
++
++ if (pdomains > MAX_OPROF_DOMAINS
++ || oprofile_set_passive(passive_domains, pdomains)) {
++ pdomains = 0;
++ retval = -EINVAL;
++ }
++
++ mutex_unlock(&pdom_mutex);
++ return retval;
++}
++
++static ssize_t pdomain_read(struct file * file, char __user * buf,
++ size_t count, loff_t * offset)
++{
++ char * tmpbuf;
++ size_t len;
++ int i;
++ ssize_t retval;
++
++ if (!(tmpbuf = kmalloc(TMPBUFSIZE, GFP_KERNEL)))
++ return -ENOMEM;
++
++ mutex_lock(&pdom_mutex);
++
++ len = 0;
++ for (i = 0; i < pdomains; i++)
++ len += snprintf(tmpbuf + len,
++ len < TMPBUFSIZE ? TMPBUFSIZE - len : 0,
++ "%u ", passive_domains[i]);
++ WARN_ON(len > TMPBUFSIZE);
++ if (len != 0 && len <= TMPBUFSIZE)
++ tmpbuf[len-1] = '\n';
++
++ mutex_unlock(&pdom_mutex);
++
++ retval = simple_read_from_buffer(buf, count, offset, tmpbuf, len);
++
++ kfree(tmpbuf);
++ return retval;
++}
++
++static struct file_operations passive_domain_ops = {
++ .read = pdomain_read,
++ .write = pdomain_write,
++};
++
+ void oprofile_create_files(struct super_block * sb, struct dentry * root)
+ {
+ oprofilefs_create_file(sb, root, "enable", &enable_fops);
+ oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666);
++ oprofilefs_create_file(sb, root, "active_domains", &active_domain_ops);
++ oprofilefs_create_file(sb, root, "passive_domains",
&passive_domain_ops);
+ oprofilefs_create_file(sb, root, "buffer", &event_buffer_fops);
+ oprofilefs_create_ulong(sb, root, "buffer_size", &fs_buffer_size);
+ oprofilefs_create_ulong(sb, root, "buffer_watershed",
&fs_buffer_watershed);
+diff -pruN ../orig-linux-2.6.16.29/include/linux/oprofile.h
./include/linux/oprofile.h
+--- ../orig-linux-2.6.16.29/include/linux/oprofile.h 2006-11-06
14:46:42.000000000 -0800
++++ ./include/linux/oprofile.h 2006-11-06 14:47:55.000000000 -0800
+@@ -16,6 +16,8 @@
+ #include <linux/types.h>
+ #include <linux/spinlock.h>
+ #include <asm/atomic.h>
++
++#include <xen/interface/xenoprof.h>
+
+ struct super_block;
+ struct dentry;
+@@ -27,6 +29,11 @@ struct oprofile_operations {
+ /* create any necessary configuration files in the oprofile fs.
+ * Optional. */
+ int (*create_files)(struct super_block * sb, struct dentry * root);
++ /* setup active domains with Xen */
++ int (*set_active)(int *active_domains, unsigned int adomains);
++ /* setup passive domains with Xen */
++ int (*set_passive)(int *passive_domains, unsigned int pdomains);
++
+ /* Do any necessary interrupt setup. Optional. */
+ int (*setup)(void);
+ /* Do any necessary interrupt shutdown. Optional. */
+@@ -68,6 +75,8 @@ void oprofile_add_pc(unsigned long pc, i
+ /* add a backtrace entry, to be called from the ->backtrace callback */
+ void oprofile_add_trace(unsigned long eip);
+
++/* add a domain switch entry */
++int oprofile_add_domain_switch(int32_t domain_id);
+
+ /**
+ * Create a file of the given name as a child of the given root, with
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/acpi/ssdt_tpm.asl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/hvmloader/acpi/ssdt_tpm.asl Wed Nov 29 11:07:28
2006 -0700
@@ -0,0 +1,29 @@
+//**********************************************************************//
+//*
+//* Copyright (c) 2006, IBM Corporation.
+//*
+//* This program is free software; you can redistribute it and/or modify it
+//* under the terms and conditions of the GNU General Public License,
+//* version 2, as published by the Free Software Foundation.
+//*
+//* This program is distributed in the hope it will be useful, but WITHOUT
+//* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+//* more details.
+//*
+//* You should have received a copy of the GNU General Public License along
with
+//* this program; if not, write to the Free Software Foundation, Inc., 59
Temple
+//* Place - Suite 330, Boston, MA 02111-1307 USA.
+
+//* SSDT for TPM TIS Interface for Xen with Qemu device model
+
+DefinitionBlock ("SSDT_TPM.aml", "SSDT", 1, "IBM","xen", 2006)
+{
+ Device (TPM) {
+ Name (_HID, EisaId ("PNP0C31"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ Memory32Fixed (ReadWrite, 0xFED40000, 0x5000,)
+ })
+ }
+}
\ No newline at end of file
diff -r d54bcabd0624 -r d8c32fa3e3a9 tools/firmware/hvmloader/acpi/ssdt_tpm.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/hvmloader/acpi/ssdt_tpm.h Wed Nov 29 11:07:28 2006 -0700
@@ -0,0 +1,25 @@
+/*
+ *
+ * Intel ACPI Component Architecture
+ * ASL Optimizing Compiler version 20060707 [Sep 11 2006]
+ * Copyright (C) 2000 - 2006 Intel Corporation
+ * Supports ACPI Specification Revision 3.0a
+ *
+ * Compilation of "acpi_ssdt_tpm.asl" - Mon Oct 30 11:28:27 2006
+ *
+ * C source code output
+ *
+ */
+unsigned char AmlCode_TPM[] =
+{
+ 0x53,0x53,0x44,0x54,0x4C,0x00,0x00,0x00, /* 00000000 "SSDTL..." */
+ 0x01,0x6D,0x49,0x42,0x4D,0x00,0x00,0x00, /* 00000008 ".mIBM..." */
+ 0x78,0x65,0x6E,0x00,0x00,0x00,0x00,0x00, /* 00000010 "xen....." */
+ 0xD6,0x07,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
+ 0x07,0x07,0x06,0x20,0x5B,0x82,0x26,0x54, /* 00000020 "... [.&T" */
+ 0x50,0x4D,0x5F,0x08,0x5F,0x48,0x49,0x44, /* 00000028 "PM_._HID" */
+ 0x0C,0x41,0xD0,0x0C,0x31,0x08,0x5F,0x43, /* 00000030 ".A..1._C" */
+ 0x52,0x53,0x11,0x11,0x0A,0x0E,0x86,0x09, /* 00000038 "RS......" */
+ 0x00,0x01,0x00,0x00,0xD4,0xFE,0x00,0x50, /* 00000040 ".......P" */
+ 0x00,0x00,0x79,0x00,
+};
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.32/blktap-aio-16_03_06.patch
--- a/patches/linux-2.6.16.32/blktap-aio-16_03_06.patch Wed Nov 29 11:05:02
2006 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,294 +0,0 @@
-diff -pruN ../orig-linux-2.6.16.29/fs/aio.c ./fs/aio.c
---- ../orig-linux-2.6.16.29/fs/aio.c 2006-09-12 19:02:10.000000000 +0100
-+++ ./fs/aio.c 2006-09-19 13:58:49.000000000 +0100
-@@ -34,6 +34,11 @@
- #include <asm/uaccess.h>
- #include <asm/mmu_context.h>
-
-+#ifdef CONFIG_EPOLL
-+#include <linux/poll.h>
-+#include <linux/eventpoll.h>
-+#endif
-+
- #if DEBUG > 1
- #define dprintk printk
- #else
-@@ -1016,6 +1021,10 @@ put_rq:
- if (waitqueue_active(&ctx->wait))
- wake_up(&ctx->wait);
-
-+#ifdef CONFIG_EPOLL
-+ if (ctx->file && waitqueue_active(&ctx->poll_wait))
-+ wake_up(&ctx->poll_wait);
-+#endif
- if (ret)
- put_ioctx(ctx);
-
-@@ -1025,6 +1034,8 @@ put_rq:
- /* aio_read_evt
- * Pull an event off of the ioctx's event ring. Returns the number of
- * events fetched (0 or 1 ;-)
-+ * If ent parameter is 0, just returns the number of events that would
-+ * be fetched.
- * FIXME: make this use cmpxchg.
- * TODO: make the ringbuffer user mmap()able (requires FIXME).
- */
-@@ -1047,13 +1058,18 @@ static int aio_read_evt(struct kioctx *i
-
- head = ring->head % info->nr;
- if (head != ring->tail) {
-- struct io_event *evp = aio_ring_event(info, head, KM_USER1);
-- *ent = *evp;
-- head = (head + 1) % info->nr;
-- smp_mb(); /* finish reading the event before updatng the head */
-- ring->head = head;
-- ret = 1;
-- put_aio_ring_event(evp, KM_USER1);
-+ if (ent) { /* event requested */
-+ struct io_event *evp =
-+ aio_ring_event(info, head, KM_USER1);
-+ *ent = *evp;
-+ head = (head + 1) % info->nr;
-+ /* finish reading the event before updatng the head */
-+ smp_mb();
-+ ring->head = head;
-+ ret = 1;
-+ put_aio_ring_event(evp, KM_USER1);
-+ } else /* only need to know availability */
-+ ret = 1;
- }
- spin_unlock(&info->ring_lock);
-
-@@ -1236,9 +1252,78 @@ static void io_destroy(struct kioctx *io
-
- aio_cancel_all(ioctx);
- wait_for_all_aios(ioctx);
-+#ifdef CONFIG_EPOLL
-+ /* forget the poll file, but it's up to the user to close it */
-+ if (ioctx->file) {
-+ ioctx->file->private_data = 0;
-+ ioctx->file = 0;
-+ }
-+#endif
- put_ioctx(ioctx); /* once for the lookup */
- }
-
-+#ifdef CONFIG_EPOLL
-+
-+static int aio_queue_fd_close(struct inode *inode, struct file *file)
-+{
-+ struct kioctx *ioctx = file->private_data;
-+ if (ioctx) {
-+ file->private_data = 0;
-+ spin_lock_irq(&ioctx->ctx_lock);
-+ ioctx->file = 0;
-+ spin_unlock_irq(&ioctx->ctx_lock);
-+ }
-+ return 0;
-+}
-+
-+static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
-+{ unsigned int pollflags = 0;
-+ struct kioctx *ioctx = file->private_data;
-+
-+ if (ioctx) {
-+
-+ spin_lock_irq(&ioctx->ctx_lock);
-+ /* Insert inside our poll wait queue */
-+ poll_wait(file, &ioctx->poll_wait, wait);
-+
-+ /* Check our condition */
-+ if (aio_read_evt(ioctx, 0))
-+ pollflags = POLLIN | POLLRDNORM;
-+ spin_unlock_irq(&ioctx->ctx_lock);
-+ }
-+
-+ return pollflags;
-+}
-+
-+static struct file_operations aioq_fops = {
-+ .release = aio_queue_fd_close,
-+ .poll = aio_queue_fd_poll
-+};
-+
-+/* make_aio_fd:
-+ * Create a file descriptor that can be used to poll the event queue.
-+ * Based and piggybacked on the excellent epoll code.
-+ */
-+
-+static int make_aio_fd(struct kioctx *ioctx)
-+{
-+ int error, fd;
-+ struct inode *inode;
-+ struct file *file;
-+
-+ error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
-+ if (error)
-+ return error;
-+
-+ /* associate the file with the IO context */
-+ file->private_data = ioctx;
-+ ioctx->file = file;
-+ init_waitqueue_head(&ioctx->poll_wait);
-+ return fd;
-+}
-+#endif
-+
-+
- /* sys_io_setup:
- * Create an aio_context capable of receiving at least nr_events.
- * ctxp must not point to an aio_context that already exists, and
-@@ -1251,18 +1336,30 @@ static void io_destroy(struct kioctx *io
- * resources are available. May fail with -EFAULT if an invalid
- * pointer is passed for ctxp. Will fail with -ENOSYS if not
- * implemented.
-+ *
-+ * To request a selectable fd, the user context has to be initialized
-+ * to 1, instead of 0, and the return value is the fd.
-+ * This keeps the system call compatible, since a non-zero value
-+ * was not allowed so far.
- */
- asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
- {
- struct kioctx *ioctx = NULL;
- unsigned long ctx;
- long ret;
-+ int make_fd = 0;
-
- ret = get_user(ctx, ctxp);
- if (unlikely(ret))
- goto out;
-
- ret = -EINVAL;
-+#ifdef CONFIG_EPOLL
-+ if (ctx == 1) {
-+ make_fd = 1;
-+ ctx = 0;
-+ }
-+#endif
- if (unlikely(ctx || nr_events == 0)) {
- pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
- ctx, nr_events);
-@@ -1273,8 +1370,12 @@ asmlinkage long sys_io_setup(unsigned nr
- ret = PTR_ERR(ioctx);
- if (!IS_ERR(ioctx)) {
- ret = put_user(ioctx->user_id, ctxp);
-- if (!ret)
-- return 0;
-+#ifdef CONFIG_EPOLL
-+ if (make_fd && ret >= 0)
-+ ret = make_aio_fd(ioctx);
-+#endif
-+ if (ret >= 0)
-+ return ret;
-
- get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
- io_destroy(ioctx);
-diff -pruN ../orig-linux-2.6.16.29/fs/eventpoll.c ./fs/eventpoll.c
---- ../orig-linux-2.6.16.29/fs/eventpoll.c 2006-09-12 19:02:10.000000000
+0100
-+++ ./fs/eventpoll.c 2006-09-19 13:58:49.000000000 +0100
-@@ -235,8 +235,6 @@ struct ep_pqueue {
-
- static void ep_poll_safewake_init(struct poll_safewake *psw);
- static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t
*wq);
--static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
-- struct eventpoll *ep);
- static int ep_alloc(struct eventpoll **pep);
- static void ep_free(struct eventpoll *ep);
- static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int
fd);
-@@ -266,7 +264,7 @@ static int ep_events_transfer(struct eve
- static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
- int maxevents, long timeout);
- static int eventpollfs_delete_dentry(struct dentry *dentry);
--static struct inode *ep_eventpoll_inode(void);
-+static struct inode *ep_eventpoll_inode(struct file_operations *fops);
- static struct super_block *eventpollfs_get_sb(struct file_system_type
*fs_type,
- int flags, const char *dev_name,
- void *data);
-@@ -525,7 +523,7 @@ asmlinkage long sys_epoll_create(int siz
- * Creates all the items needed to setup an eventpoll file. That is,
- * a file structure, and inode and a free file descriptor.
- */
-- error = ep_getfd(&fd, &inode, &file, ep);
-+ error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
- if (error)
- goto eexit_2;
-
-@@ -710,8 +708,8 @@ eexit_1:
- /*
- * Creates the file descriptor to be used by the epoll interface.
- */
--static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
-- struct eventpoll *ep)
-+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
-+ struct eventpoll *ep, struct file_operations *fops)
- {
- struct qstr this;
- char name[32];
-@@ -727,7 +725,7 @@ static int ep_getfd(int *efd, struct ino
- goto eexit_1;
-
- /* Allocates an inode from the eventpoll file system */
-- inode = ep_eventpoll_inode();
-+ inode = ep_eventpoll_inode(fops);
- error = PTR_ERR(inode);
- if (IS_ERR(inode))
- goto eexit_2;
-@@ -758,7 +756,7 @@ static int ep_getfd(int *efd, struct ino
-
- file->f_pos = 0;
- file->f_flags = O_RDONLY;
-- file->f_op = &eventpoll_fops;
-+ file->f_op = fops;
- file->f_mode = FMODE_READ;
- file->f_version = 0;
- file->private_data = ep;
-@@ -1574,7 +1572,7 @@ static int eventpollfs_delete_dentry(str
- }
-
-
--static struct inode *ep_eventpoll_inode(void)
-+static struct inode *ep_eventpoll_inode(struct file_operations *fops)
- {
- int error = -ENOMEM;
- struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
-@@ -1582,7 +1580,7 @@ static struct inode *ep_eventpoll_inode(
- if (!inode)
- goto eexit_1;
-
-- inode->i_fop = &eventpoll_fops;
-+ inode->i_fop = fops;
-
- /*
- * Mark the inode dirty from the very beginning,
-diff -pruN ../orig-linux-2.6.16.29/include/linux/aio.h ./include/linux/aio.h
---- ../orig-linux-2.6.16.29/include/linux/aio.h 2006-09-12
19:02:10.000000000 +0100
-+++ ./include/linux/aio.h 2006-09-19 13:58:49.000000000 +0100
-@@ -191,6 +191,11 @@ struct kioctx {
- struct aio_ring_info ring_info;
-
- struct work_struct wq;
-+#ifdef CONFIG_EPOLL
-+ // poll integration
-+ wait_queue_head_t poll_wait;
-+ struct file *file;
-+#endif
- };
-
- /* prototypes */
-diff -pruN ../orig-linux-2.6.16.29/include/linux/eventpoll.h
./include/linux/eventpoll.h
---- ../orig-linux-2.6.16.29/include/linux/eventpoll.h 2006-09-12
19:02:10.000000000 +0100
-+++ ./include/linux/eventpoll.h 2006-09-19 13:58:49.000000000 +0100
-@@ -86,6 +86,12 @@ static inline void eventpoll_release(str
- }
-
-
-+/*
-+ * called by aio code to create fd that can poll the aio event queueQ
-+ */
-+struct eventpoll;
-+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
-+ struct eventpoll *ep, struct file_operations *fops);
- #else
-
- static inline void eventpoll_init_file(struct file *file) {}
diff -r d54bcabd0624 -r d8c32fa3e3a9 patches/linux-2.6.16.32/device_bind.patch
--- a/patches/linux-2.6.16.32/device_bind.patch Wed Nov 29 11:05:02 2006 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-diff -pruN ../orig-linux-2.6.16.29/drivers/base/bus.c ./drivers/base/bus.c
---- ../orig-linux-2.6.16.29/drivers/base/bus.c 2006-09-12 19:02:10.000000000
+0100
-+++ ./drivers/base/bus.c 2006-09-19 13:58:54.000000000 +0100
-@@ -188,6 +188,11 @@ static ssize_t driver_bind(struct device
- up(&dev->sem);
- if (dev->parent)
- up(&dev->parent->sem);
-+
-+ if (err > 0) /* success */
-+ err = count;
-+ else if (err == 0) /* driver didn't accept device */
-+ err = -ENODEV;
- }
- put_device(dev);
- put_bus(bus);
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.32/fix-hz-suspend.patch
--- a/patches/linux-2.6.16.32/fix-hz-suspend.patch Wed Nov 29 11:05:02
2006 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-diff -pruN ../orig-linux-2.6.16.29/kernel/timer.c ./kernel/timer.c
---- ../orig-linux-2.6.16.29/kernel/timer.c 2006-09-12 19:02:10.000000000
+0100
-+++ ./kernel/timer.c 2006-09-19 13:58:58.000000000 +0100
-@@ -555,6 +555,22 @@ found:
- }
- spin_unlock(&base->t_base.lock);
-
-+ /*
-+ * It can happen that other CPUs service timer IRQs and increment
-+ * jiffies, but we have not yet got a local timer tick to process
-+ * the timer wheels. In that case, the expiry time can be before
-+ * jiffies, but since the high-resolution timer here is relative to
-+ * jiffies, the default expression when high-resolution timers are
-+ * not active,
-+ *
-+ * time_before(MAX_JIFFY_OFFSET + jiffies, expires)
-+ *
-+ * would falsely evaluate to true. If that is the case, just
-+ * return jiffies so that we can immediately fire the local timer
-+ */
-+ if (time_before(expires, jiffies))
-+ return jiffies;
-+
- if (time_before(hr_expires, expires))
- return hr_expires;
-
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.32/fix-ide-cd-pio-mode.patch
--- a/patches/linux-2.6.16.32/fix-ide-cd-pio-mode.patch Wed Nov 29 11:05:02
2006 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-diff -pruN ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c
./drivers/ide/ide-lib.c
---- ../orig-linux-2.6.16.29/drivers/ide/ide-lib.c 2006-09-12
19:02:10.000000000 +0100
-+++ ./drivers/ide/ide-lib.c 2006-09-19 13:59:03.000000000 +0100
-@@ -410,10 +410,10 @@ void ide_toggle_bounce(ide_drive_t *driv
- {
- u64 addr = BLK_BOUNCE_HIGH; /* dma64_addr_t */
-
-- if (!PCI_DMA_BUS_IS_PHYS) {
-- addr = BLK_BOUNCE_ANY;
-- } else if (on && drive->media == ide_disk) {
-- if (HWIF(drive)->pci_dev)
-+ if (on && drive->media == ide_disk) {
-+ if (!PCI_DMA_BUS_IS_PHYS)
-+ addr = BLK_BOUNCE_ANY;
-+ else if (HWIF(drive)->pci_dev)
- addr = HWIF(drive)->pci_dev->dma_mask;
- }
-
diff -r d54bcabd0624 -r d8c32fa3e3a9
patches/linux-2.6.16.32/i386-mach-io-check-nmi.patch
--- a/patches/linux-2.6.16.32/i386-mach-io-check-nmi.patch Wed Nov 29
11:05:02 2006 -0700
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-diff -pruN ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c
./arch/i386/kernel/traps.c
---- ../orig-linux-2.6.16.29/arch/i386/kernel/traps.c 2006-09-12
19:02:10.000000000 +0100
-+++ ./arch/i386/kernel/traps.c 2006-09-19 13:59:06.000000000 +0100
-@@ -567,18 +567,11 @@ static void mem_parity_error(unsigned ch
-
- static void io_check_error(unsigned char reason, struct pt_regs * regs)
- {
-- unsigned long i;
--
- printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n");
- show_registers(regs);
-
- /* Re-enable the IOCK line, wait for a few seconds */
-- reason = (reason & 0xf) | 8;
-- outb(reason, 0x61);
-- i = 2000;
-- while (--i) udelay(1000);
-- reason &= ~8;
-- outb(reason, 0x61);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|