[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-3.0.4-testing] [LINUX] Update to 2.6.16.38 point release.
# HG changeset patch # User Ian Campbell <ian.campbell@xxxxxxxxxxxxx> # Date 1170064833 0 # Node ID 4be85bb2f54d62338ddd7b793299ef5381850333 # Parent 18f30d7ef2b87b67e8cd1fd36acaabea39b1bfc3 [LINUX] Update to 2.6.16.38 point release. Only required update was to net-gso-0-base.patch to fixup a call to skb_linearize with the old prototype in net/sctp. Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxxxxx> --- patches/linux-2.6.16.33/blktap-aio-16_03_06.patch | 271 - patches/linux-2.6.16.33/device_bind.patch | 14 patches/linux-2.6.16.33/fix-hz-suspend.patch | 25 patches/linux-2.6.16.33/fix-ide-cd-pio-mode.patch | 13 patches/linux-2.6.16.33/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch | 43 patches/linux-2.6.16.33/git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch | 74 patches/linux-2.6.16.33/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch | 292 - patches/linux-2.6.16.33/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch | 320 - patches/linux-2.6.16.33/git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch | 45 patches/linux-2.6.16.33/i386-mach-io-check-nmi.patch | 35 patches/linux-2.6.16.33/ipv6-no-autoconf.patch | 18 patches/linux-2.6.16.33/kasprintf.patch | 57 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch | 102 patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch | 95 patches/linux-2.6.16.33/net-csum.patch | 57 patches/linux-2.6.16.33/net-gso-0-base.patch | 2501 ---------- patches/linux-2.6.16.33/net-gso-1-check-dodgy.patch | 22 patches/linux-2.6.16.33/net-gso-2-checksum-fix.patch | 400 - 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 | 16 patches/linux-2.6.16.33/net-gso-5-rcv-mss.patch | 11 patches/linux-2.6.16.33/net-gso-6-linear-segmentation.patch | 20 patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch | 252 - patches/linux-2.6.16.33/pmd-shared.patch | 100 patches/linux-2.6.16.33/rcu_needs_cpu.patch | 33 patches/linux-2.6.16.33/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch | 26 patches/linux-2.6.16.33/series | 35 patches/linux-2.6.16.33/smp-alts.patch | 540 -- patches/linux-2.6.16.33/tpm_plugin_2.6.17.patch | 1380 ----- patches/linux-2.6.16.33/vsnprintf.patch | 178 patches/linux-2.6.16.33/x86-elfnote-as-preprocessor-macro.patch | 27 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 | 138 patches/linux-2.6.16.33/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch | 72 patches/linux-2.6.16.33/xen-hotplug.patch | 10 patches/linux-2.6.16.33/xenoprof-generic.patch | 615 -- buildconfigs/linux-defconfig_xen0_x86_32 | 27 buildconfigs/linux-defconfig_xen0_x86_64 | 27 buildconfigs/linux-defconfig_xen_x86_32 | 44 buildconfigs/linux-defconfig_xen_x86_64 | 44 buildconfigs/mk.linux-2.6-xen | 2 linux-2.6-xen-sparse/arch/i386/Kconfig.cpu | 3 linux-2.6-xen-sparse/include/asm-i386/system.h | 8 linux-2.6-xen-sparse/net/core/dev.c | 16 patches/linux-2.6.16.38/blktap-aio-16_03_06.patch | 161 patches/linux-2.6.16.38/device_bind.patch | 9 patches/linux-2.6.16.38/fix-hz-suspend.patch | 9 patches/linux-2.6.16.38/fix-ide-cd-pio-mode.patch | 13 patches/linux-2.6.16.38/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch | 50 patches/linux-2.6.16.38/git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch | 75 patches/linux-2.6.16.38/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch | 197 patches/linux-2.6.16.38/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch | 156 patches/linux-2.6.16.38/git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch | 44 patches/linux-2.6.16.38/i386-mach-io-check-nmi.patch | 30 patches/linux-2.6.16.38/ipv6-no-autoconf.patch | 16 patches/linux-2.6.16.38/kasprintf.patch | 32 patches/linux-2.6.16.38/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch | 114 patches/linux-2.6.16.38/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch | 114 patches/linux-2.6.16.38/net-csum.patch | 40 patches/linux-2.6.16.38/net-gso-0-base.patch | 1970 +++++++ patches/linux-2.6.16.38/net-gso-1-check-dodgy.patch | 16 patches/linux-2.6.16.38/net-gso-2-checksum-fix.patch | 311 + patches/linux-2.6.16.38/net-gso-3-fix-errorcheck.patch | 13 patches/linux-2.6.16.38/net-gso-4-kill-warnon.patch | 26 patches/linux-2.6.16.38/net-gso-5-rcv-mss.patch | 11 patches/linux-2.6.16.38/net-gso-6-linear-segmentation.patch | 21 patches/linux-2.6.16.38/pci-mmconfig-fix-from-2.6.17.patch | 143 patches/linux-2.6.16.38/pmd-shared.patch | 57 patches/linux-2.6.16.38/rcu_needs_cpu.patch | 18 patches/linux-2.6.16.38/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch | 26 patches/linux-2.6.16.38/series | 35 patches/linux-2.6.16.38/smp-alts.patch | 330 + patches/linux-2.6.16.38/tpm_plugin_2.6.17.patch | 703 ++ patches/linux-2.6.16.38/vsnprintf.patch | 177 patches/linux-2.6.16.38/x86-elfnote-as-preprocessor-macro.patch | 25 patches/linux-2.6.16.38/x86-increase-interrupt-vector-range.patch | 73 patches/linux-2.6.16.38/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch | 39 patches/linux-2.6.16.38/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch | 63 patches/linux-2.6.16.38/xen-hotplug.patch | 10 patches/linux-2.6.16.38/xenoprof-generic.patch | 294 + 80 files changed, 5542 insertions(+), 7973 deletions(-) diff -r 18f30d7ef2b8 -r 4be85bb2f54d buildconfigs/linux-defconfig_xen0_x86_32 --- a/buildconfigs/linux-defconfig_xen0_x86_32 Tue Jan 23 19:06:31 2007 -0800 +++ b/buildconfigs/linux-defconfig_xen0_x86_32 Mon Jan 29 10:00:33 2007 +0000 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.13-xen0 -# Thu May 11 17:06:31 2006 +# Linux kernel version: 2.6.16.38 +# Fri Jan 26 15:57:32 2007 # CONFIG_X86_32=y CONFIG_SEMAPHORE_SLEEPERS=y @@ -182,6 +182,7 @@ CONFIG_KEXEC=y CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # # Power management options (ACPI, APM) @@ -542,6 +543,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0 CONFIG_AIC79XX_DEBUG_MASK=0 CONFIG_AIC79XX_REG_PRETTY_PRINT=y # CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set CONFIG_MEGARAID_NEWGEN=y # CONFIG_MEGARAID_MM is not set # CONFIG_MEGARAID_LEGACY is not set @@ -553,6 +555,7 @@ CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_MV is not set # CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_PDC_ADMA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_SATA_QSTOR is not set CONFIG_SCSI_SATA_PROMISE=y CONFIG_SCSI_SATA_SX4=y @@ -1310,24 +1313,26 @@ CONFIG_CRYPTO_CRC32C=m # # CONFIG_CRYPTO_DEV_PADLOCK is not set CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030202 +CONFIG_XEN_INTERFACE_VERSION=0x00030203 # # XEN # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y +CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y # CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set -CONFIG_XEN_BLKDEV_BACKEND=y -CONFIG_XEN_BLKDEV_TAP=y -CONFIG_XEN_NETDEV_BACKEND=y -# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set -CONFIG_XEN_NETDEV_LOOPBACK=y # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y @@ -1339,7 +1344,13 @@ CONFIG_XEN_COMPAT_030002=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y # # Library routines diff -r 18f30d7ef2b8 -r 4be85bb2f54d buildconfigs/linux-defconfig_xen0_x86_64 --- a/buildconfigs/linux-defconfig_xen0_x86_64 Tue Jan 23 19:06:31 2007 -0800 +++ b/buildconfigs/linux-defconfig_xen0_x86_64 Mon Jan 29 10:00:33 2007 +0000 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.13-xen0 -# Thu May 11 17:17:19 2006 +# Linux kernel version: 2.6.16.38 +# Fri Jan 26 15:57:41 2007 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -115,7 +115,6 @@ CONFIG_PREEMPT_NONE=y CONFIG_PREEMPT_NONE=y # CONFIG_PREEMPT_VOLUNTARY is not set # CONFIG_PREEMPT is not set -CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -125,6 +124,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4096 +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_SWIOTLB=y CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set @@ -504,6 +504,7 @@ CONFIG_SCSI_ATA_PIIX=y # CONFIG_SCSI_SATA_MV is not set # CONFIG_SCSI_SATA_NV is not set # CONFIG_SCSI_PDC_ADMA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_SATA_QSTOR is not set CONFIG_SCSI_SATA_PROMISE=y CONFIG_SCSI_SATA_SX4=y @@ -1251,24 +1252,26 @@ CONFIG_CRYPTO_CRC32C=m # Hardware crypto devices # CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030202 +CONFIG_XEN_INTERFACE_VERSION=0x00030203 # # XEN # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y +CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_PCIDEV_BACKEND=y # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y # CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set -CONFIG_XEN_BLKDEV_BACKEND=y -CONFIG_XEN_BLKDEV_TAP=y -CONFIG_XEN_NETDEV_BACKEND=y -# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set -CONFIG_XEN_NETDEV_LOOPBACK=y # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y @@ -1280,7 +1283,13 @@ CONFIG_XEN_COMPAT_030002=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y # # Library routines diff -r 18f30d7ef2b8 -r 4be85bb2f54d buildconfigs/linux-defconfig_xen_x86_32 --- a/buildconfigs/linux-defconfig_xen_x86_32 Tue Jan 23 19:06:31 2007 -0800 +++ b/buildconfigs/linux-defconfig_xen_x86_32 Mon Jan 29 10:00:33 2007 +0000 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.13-xen -# Thu May 11 17:11:00 2006 +# Linux kernel version: 2.6.16.38 +# Fri Jan 26 15:58:01 2007 # CONFIG_X86_32=y CONFIG_SEMAPHORE_SLEEPERS=y @@ -184,13 +184,14 @@ CONFIG_REGPARM=y CONFIG_REGPARM=y CONFIG_SECCOMP=y CONFIG_HZ_100=y -CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 +CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # # Power management options (ACPI, APM) @@ -1102,6 +1103,7 @@ CONFIG_AIC79XX_DEBUG_MASK=0 CONFIG_AIC79XX_DEBUG_MASK=0 CONFIG_AIC79XX_REG_PRETTY_PRINT=y CONFIG_SCSI_DPT_I2O=m +CONFIG_SCSI_ADVANSYS=m CONFIG_MEGARAID_NEWGEN=y CONFIG_MEGARAID_MM=m CONFIG_MEGARAID_MAILBOX=m @@ -1114,6 +1116,7 @@ CONFIG_SCSI_SATA_MV=m CONFIG_SCSI_SATA_MV=m CONFIG_SCSI_SATA_NV=m CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m CONFIG_SCSI_SATA_QSTOR=m CONFIG_SCSI_SATA_PROMISE=m CONFIG_SCSI_SATA_SX4=m @@ -2371,6 +2374,18 @@ CONFIG_SND_CS46XX=m CONFIG_SND_CS46XX=m CONFIG_SND_CS46XX_NEW_DSP=y CONFIG_SND_CS5535AUDIO=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m CONFIG_SND_EMU10K1=m CONFIG_SND_EMU10K1X=m CONFIG_SND_ENS1370=m @@ -2379,7 +2394,6 @@ CONFIG_SND_ES1968=m CONFIG_SND_ES1968=m CONFIG_SND_FM801=m # CONFIG_SND_FM801_TEA575X_BOOL is not set -CONFIG_SND_FM801_TEA575X=m CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDSP=m CONFIG_SND_HDSPM=m @@ -2777,7 +2791,6 @@ CONFIG_NTFS_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -# CONFIG_PROC_VMCORE is not set CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set @@ -3013,24 +3026,26 @@ CONFIG_CRYPTO_TEST=m # # CONFIG_CRYPTO_DEV_PADLOCK is not set CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030202 +CONFIG_XEN_INTERFACE_VERSION=0x00030203 # # XEN # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y +CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_XEN_PCIDEV_BACKEND_VPCI=y # CONFIG_XEN_PCIDEV_BACKEND_PASS is not set # CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set -CONFIG_XEN_BLKDEV_BACKEND=y -CONFIG_XEN_BLKDEV_TAP=y -CONFIG_XEN_NETDEV_BACKEND=y -# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set -CONFIG_XEN_NETDEV_LOOPBACK=y # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y @@ -3044,7 +3059,14 @@ CONFIG_XEN_COMPAT_030002=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y # # Library routines diff -r 18f30d7ef2b8 -r 4be85bb2f54d buildconfigs/linux-defconfig_xen_x86_64 --- a/buildconfigs/linux-defconfig_xen_x86_64 Tue Jan 23 19:06:31 2007 -0800 +++ b/buildconfigs/linux-defconfig_xen_x86_64 Mon Jan 29 10:00:33 2007 +0000 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.13-xen -# Thu May 11 17:18:58 2006 +# Linux kernel version: 2.6.16.38 +# Fri Jan 26 15:58:21 2007 # CONFIG_X86_64=y CONFIG_64BIT=y @@ -122,7 +122,6 @@ CONFIG_PREEMPT_VOLUNTARY=y CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set CONFIG_PREEMPT_BKL=y -CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -134,12 +133,13 @@ CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_SPLIT_PTLOCK_CPUS=4096 CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_SWIOTLB=y +CONFIG_KEXEC=y # CONFIG_CRASH_DUMP is not set CONFIG_PHYSICAL_START=0x100000 CONFIG_SECCOMP=y CONFIG_HZ_100=y -CONFIG_KEXEC=y # CONFIG_HZ_250 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=100 @@ -1062,6 +1062,7 @@ CONFIG_SCSI_SATA_MV=m CONFIG_SCSI_SATA_MV=m CONFIG_SCSI_SATA_NV=m CONFIG_SCSI_PDC_ADMA=m +CONFIG_SCSI_HPTIOP=m CONFIG_SCSI_SATA_QSTOR=m CONFIG_SCSI_SATA_PROMISE=m CONFIG_SCSI_SATA_SX4=m @@ -2231,6 +2232,18 @@ CONFIG_SND_CS4281=m CONFIG_SND_CS4281=m CONFIG_SND_CS46XX=m CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m CONFIG_SND_EMU10K1=m CONFIG_SND_EMU10K1X=m CONFIG_SND_ENS1370=m @@ -2239,7 +2252,6 @@ CONFIG_SND_ES1968=m CONFIG_SND_ES1968=m CONFIG_SND_FM801=m # CONFIG_SND_FM801_TEA575X_BOOL is not set -CONFIG_SND_FM801_TEA575X=m CONFIG_SND_HDA_INTEL=m CONFIG_SND_HDSP=m CONFIG_SND_HDSPM=m @@ -2844,26 +2856,27 @@ CONFIG_CRYPTO_TEST=m # Hardware crypto devices # CONFIG_XEN=y -CONFIG_XEN_INTERFACE_VERSION=0x00030202 +CONFIG_XEN_INTERFACE_VERSION=0x00030203 # # XEN # CONFIG_XEN_PRIVILEGED_GUEST=y # CONFIG_XEN_UNPRIVILEGED_GUEST is not set +CONFIG_XEN_PRIVCMD=y +CONFIG_XEN_XENBUS_DEV=y CONFIG_XEN_BACKEND=y +CONFIG_XEN_BLKDEV_BACKEND=y +CONFIG_XEN_BLKDEV_TAP=y +CONFIG_XEN_NETDEV_BACKEND=y +# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set +CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_PCIDEV_BACKEND=m # CONFIG_XEN_PCIDEV_BACKEND_VPCI is not set CONFIG_XEN_PCIDEV_BACKEND_PASS=y # CONFIG_XEN_PCIDEV_BACKEND_SLOT is not set # CONFIG_XEN_PCIDEV_BE_DEBUG is not set -CONFIG_XEN_BLKDEV_BACKEND=y -CONFIG_XEN_BLKDEV_TAP=y -CONFIG_XEN_NETDEV_BACKEND=y -# CONFIG_XEN_NETDEV_PIPELINED_TRANSMITTER is not set -CONFIG_XEN_NETDEV_LOOPBACK=y CONFIG_XEN_TPMDEV_BACKEND=m -# CONFIG_XEN_TPMDEV_CLOSE_IF_VTPM_FAILS is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_FRAMEBUFFER=y @@ -2876,7 +2889,14 @@ CONFIG_XEN_COMPAT_030002=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y +CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_UTIL=y +CONFIG_XEN_BALLOON=y +CONFIG_XEN_DEVMEM=y +CONFIG_XEN_SKBUFF=y +CONFIG_XEN_REBOOT=y +CONFIG_XEN_SMPBOOT=y # # Library routines diff -r 18f30d7ef2b8 -r 4be85bb2f54d buildconfigs/mk.linux-2.6-xen --- a/buildconfigs/mk.linux-2.6-xen Tue Jan 23 19:06:31 2007 -0800 +++ b/buildconfigs/mk.linux-2.6-xen Mon Jan 29 10:00:33 2007 +0000 @@ -1,5 +1,5 @@ LINUX_SERIES = 2.6 LINUX_SERIES = 2.6 -LINUX_VER = 2.6.16.33 +LINUX_VER = 2.6.16.38 EXTRAVERSION ?= xen diff -r 18f30d7ef2b8 -r 4be85bb2f54d linux-2.6-xen-sparse/arch/i386/Kconfig.cpu --- a/linux-2.6-xen-sparse/arch/i386/Kconfig.cpu Tue Jan 23 19:06:31 2007 -0800 +++ b/linux-2.6-xen-sparse/arch/i386/Kconfig.cpu Mon Jan 29 10:00:33 2007 +0000 @@ -7,6 +7,7 @@ choice config M386 bool "386" + depends on !UML ---help--- This is the processor type of your CPU. This information is used for optimizing purposes. In order to compile a kernel that can run on @@ -301,7 +302,7 @@ config X86_USE_PPRO_CHECKSUM config X86_USE_3DNOW bool - depends on MCYRIXIII || MK7 || MGEODE_LX + depends on (MCYRIXIII || MK7 || MGEODE_LX) && !UML default y config X86_OOSTORE diff -r 18f30d7ef2b8 -r 4be85bb2f54d linux-2.6-xen-sparse/include/asm-i386/system.h --- a/linux-2.6-xen-sparse/include/asm-i386/system.h Tue Jan 23 19:06:31 2007 -0800 +++ b/linux-2.6-xen-sparse/include/asm-i386/system.h Mon Jan 29 10:00:33 2007 +0000 @@ -12,9 +12,14 @@ struct task_struct; /* one of the strang struct task_struct; /* one of the stranger aspects of C forward declarations.. */ extern struct task_struct * FASTCALL(__switch_to(struct task_struct *prev, struct task_struct *next)); +/* + * Saving eflags is important. It switches not only IOPL between tasks, + * it also protects other tasks from NT leaking through sysenter etc. + */ #define switch_to(prev,next,last) do { \ unsigned long esi,edi; \ - asm volatile("pushl %%ebp\n\t" \ + asm volatile("pushfl\n\t" /* Save flags */ \ + "pushl %%ebp\n\t" \ "movl %%esp,%0\n\t" /* save ESP */ \ "movl %5,%%esp\n\t" /* restore ESP */ \ "movl $1f,%1\n\t" /* save EIP */ \ @@ -22,6 +27,7 @@ extern struct task_struct * FASTCALL(__s "jmp __switch_to\n" \ "1:\t" \ "popl %%ebp\n\t" \ + "popfl" \ :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \ "=a" (last),"=S" (esi),"=D" (edi) \ :"m" (next->thread.esp),"m" (next->thread.eip), \ diff -r 18f30d7ef2b8 -r 4be85bb2f54d linux-2.6-xen-sparse/net/core/dev.c --- a/linux-2.6-xen-sparse/net/core/dev.c Tue Jan 23 19:06:31 2007 -0800 +++ b/linux-2.6-xen-sparse/net/core/dev.c Mon Jan 29 10:00:33 2007 +0000 @@ -1441,14 +1441,16 @@ gso: if (q->enqueue) { /* Grab device queue */ spin_lock(&dev->queue_lock); - - rc = q->enqueue(skb, q); - - qdisc_run(dev); - + q = dev->qdisc; + if (q->enqueue) { + rc = q->enqueue(skb, q); + qdisc_run(dev); + spin_unlock(&dev->queue_lock); + + rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; + goto out; + } spin_unlock(&dev->queue_lock); - rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; - goto out; } /* The device has no queue. Common case for software devices: diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/blktap-aio-16_03_06.patch --- a/patches/linux-2.6.16.33/blktap-aio-16_03_06.patch Tue Jan 23 19:06:31 2007 -0800 +++ /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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/device_bind.patch --- a/patches/linux-2.6.16.33/device_bind.patch Tue Jan 23 19:06:31 2007 -0800 +++ /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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/fix-hz-suspend.patch --- a/patches/linux-2.6.16.33/fix-hz-suspend.patch Tue Jan 23 19:06:31 2007 -0800 +++ /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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/fix-ide-cd-pio-mode.patch --- a/patches/linux-2.6.16.33/fix-ide-cd-pio-mode.patch Tue Jan 23 19:06:31 2007 -0800 +++ /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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch --- a/patches/linux-2.6.16.33/git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -From: Eric W. Biederman <ebiederm@xxxxxxxxxxxx> -Date: Sun, 30 Jul 2006 10:03:20 +0000 (-0700) -Subject: [PATCH] machine_kexec.c: Fix the description of segment handling -X-Git-Tag: v2.6.18-rc4 -X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2a8a3d5b65e86ec1dfef7d268c64a909eab94af7 - -[PATCH] machine_kexec.c: Fix the description of segment handling - -One of my original comments in machine_kexec was unclear -and this should fix it. - -Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxx> -Cc: Andi Kleen <ak@xxxxxx> -Acked-by: Horms <horms@xxxxxxxxxxxx> -Signed-off-by: Andrew Morton <akpm@xxxxxxxx> -Signed-off-by: Linus Torvalds <torvalds@xxxxxxxx> ---- - ---- a/arch/i386/kernel/machine_kexec.c -+++ b/arch/i386/kernel/machine_kexec.c -@@ -189,14 +189,11 @@ NORET_TYPE void machine_kexec(struct kim - memcpy((void *)reboot_code_buffer, relocate_new_kernel, - relocate_new_kernel_size); - -- /* The segment registers are funny things, they are -- * automatically loaded from a table, in memory wherever you -- * set them to a specific selector, but this table is never -- * accessed again you set the segment to a different selector. -- * -- * The more common model is are caches where the behide -- * the scenes work is done, but is also dropped at arbitrary -- * times. -+ /* The segment registers are funny things, they have both a -+ * visible and an invisible part. Whenever the visible part is -+ * set to a specific selector, the invisible part is loaded -+ * with from a table in memory. At no other time is the -+ * descriptor table in memory accessed. - * - * I take advantage of this here by force loading the - * segments, before I zap the gdt with an invalid value. ---- a/arch/x86_64/kernel/machine_kexec.c -+++ b/arch/x86_64/kernel/machine_kexec.c -@@ -207,14 +207,11 @@ NORET_TYPE void machine_kexec(struct kim - __flush_tlb(); - - -- /* The segment registers are funny things, they are -- * automatically loaded from a table, in memory wherever you -- * set them to a specific selector, but this table is never -- * accessed again unless you set the segment to a different selector. -- * -- * The more common model are caches where the behide -- * the scenes work is done, but is also dropped at arbitrary -- * times. -+ /* The segment registers are funny things, they have both a -+ * visible and an invisible part. Whenever the visible part is -+ * set to a specific selector, the invisible part is loaded -+ * with from a table in memory. At no other time is the -+ * descriptor table in memory accessed. - * - * I take advantage of this here by force loading the - * segments, before I zap the gdt with an invalid value. diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch --- a/patches/linux-2.6.16.33/git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -From: Tobias Klauser <tklauser@xxxxxxxxxxx> -Date: Mon, 26 Jun 2006 16:57:34 +0000 (+0200) -Subject: Storage class should be first -X-Git-Tag: v2.6.18-rc1 -X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=2efe55a9cec8418f0e0cde3dc3787a42fddc4411 - -Storage class should be first - -Storage class should be before const - -Signed-off-by: Tobias Klauser <tklauser@xxxxxxxxxxx> -Signed-off-by: Adrian Bunk <bunk@xxxxxxxxx> ---- - ---- a/arch/i386/kernel/machine_kexec.c -+++ b/arch/i386/kernel/machine_kexec.c -@@ -133,9 +133,9 @@ typedef asmlinkage NORET_TYPE void (*rel - unsigned long start_address, - unsigned int has_pae) ATTRIB_NORET; - --const extern unsigned char relocate_new_kernel[]; -+extern const unsigned char relocate_new_kernel[]; - extern void relocate_new_kernel_end(void); --const extern unsigned int relocate_new_kernel_size; -+extern const unsigned int relocate_new_kernel_size; - - /* - * A architecture hook called to validate the ---- a/arch/powerpc/kernel/machine_kexec_32.c -+++ b/arch/powerpc/kernel/machine_kexec_32.c -@@ -30,8 +30,8 @@ typedef NORET_TYPE void (*relocate_new_k - */ - void default_machine_kexec(struct kimage *image) - { -- const extern unsigned char relocate_new_kernel[]; -- const extern unsigned int relocate_new_kernel_size; -+ extern const unsigned char relocate_new_kernel[]; -+ extern const unsigned int relocate_new_kernel_size; - unsigned long page_list; - unsigned long reboot_code_buffer, reboot_code_buffer_phys; - relocate_new_kernel_t rnk; ---- a/arch/ppc/kernel/machine_kexec.c -+++ b/arch/ppc/kernel/machine_kexec.c -@@ -25,8 +25,8 @@ typedef NORET_TYPE void (*relocate_new_k - unsigned long reboot_code_buffer, - unsigned long start_address) ATTRIB_NORET; - --const extern unsigned char relocate_new_kernel[]; --const extern unsigned int relocate_new_kernel_size; -+extern const unsigned char relocate_new_kernel[]; -+extern const unsigned int relocate_new_kernel_size; - - void machine_shutdown(void) - { ---- a/arch/s390/kernel/machine_kexec.c -+++ b/arch/s390/kernel/machine_kexec.c -@@ -27,8 +27,8 @@ static void kexec_halt_all_cpus(void *); - - typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long); - --const extern unsigned char relocate_kernel[]; --const extern unsigned long long relocate_kernel_len; -+extern const unsigned char relocate_kernel[]; -+extern const unsigned long long relocate_kernel_len; - - int - machine_kexec_prepare(struct kimage *image) ---- a/arch/sh/kernel/machine_kexec.c -+++ b/arch/sh/kernel/machine_kexec.c -@@ -25,8 +25,8 @@ typedef NORET_TYPE void (*relocate_new_k - unsigned long start_address, - unsigned long vbr_reg) ATTRIB_NORET; - --const extern unsigned char relocate_new_kernel[]; --const extern unsigned int relocate_new_kernel_size; -+extern const unsigned char relocate_new_kernel[]; -+extern const unsigned int relocate_new_kernel_size; - extern void *gdb_vbr_vector; - - /* ---- a/arch/x86_64/kernel/machine_kexec.c -+++ b/arch/x86_64/kernel/machine_kexec.c -@@ -149,8 +149,8 @@ typedef NORET_TYPE void (*relocate_new_k - unsigned long start_address, - unsigned long pgtable) ATTRIB_NORET; - --const extern unsigned char relocate_new_kernel[]; --const extern unsigned long relocate_new_kernel_size; -+extern const unsigned char relocate_new_kernel[]; -+extern const unsigned long relocate_new_kernel_size; - - int machine_kexec_prepare(struct kimage *image) - { diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch --- a/patches/linux-2.6.16.33/git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,401 +0,0 @@ -From: Magnus Damm <magnus@xxxxxxxxxxxxx> -Date: Tue, 26 Sep 2006 08:52:38 +0000 (+0200) -Subject: [PATCH] i386: Avoid overwriting the current pgd (V4, i386) -X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3566561bfadffcb5dbc85d576be80c0dbf2cccc9 - -[PATCH] i386: Avoid overwriting the current pgd (V4, i386) - -kexec: Avoid overwriting the current pgd (V4, i386) - -This patch upgrades the i386-specific kexec code to avoid overwriting the -current pgd. Overwriting the current pgd is bad when CONFIG_CRASH_DUMP is used -to start a secondary kernel that dumps the memory of the previous kernel. - -The code introduces a new set of page tables. These tables are used to provide -an executable identity mapping without overwriting the current pgd. - -Signed-off-by: Magnus Damm <magnus@xxxxxxxxxxxxx> -Signed-off-by: Andi Kleen <ak@xxxxxxx> ---- - ---- a/arch/i386/kernel/machine_kexec.c -+++ b/arch/i386/kernel/machine_kexec.c -@@ -21,70 +21,13 @@ - #include <asm/system.h> - - #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) -- --#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) --#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) --#define L2_ATTR (_PAGE_PRESENT) -- --#define LEVEL0_SIZE (1UL << 12UL) -- --#ifndef CONFIG_X86_PAE --#define LEVEL1_SIZE (1UL << 22UL) --static u32 pgtable_level1[1024] PAGE_ALIGNED; -- --static void identity_map_page(unsigned long address) --{ -- unsigned long level1_index, level2_index; -- u32 *pgtable_level2; -- -- /* Find the current page table */ -- pgtable_level2 = __va(read_cr3()); -- -- /* Find the indexes of the physical address to identity map */ -- level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE; -- level2_index = address / LEVEL1_SIZE; -- -- /* Identity map the page table entry */ -- pgtable_level1[level1_index] = address | L0_ATTR; -- pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR; -- -- /* Flush the tlb so the new mapping takes effect. -- * Global tlb entries are not flushed but that is not an issue. -- */ -- load_cr3(pgtable_level2); --} -- --#else --#define LEVEL1_SIZE (1UL << 21UL) --#define LEVEL2_SIZE (1UL << 30UL) --static u64 pgtable_level1[512] PAGE_ALIGNED; --static u64 pgtable_level2[512] PAGE_ALIGNED; -- --static void identity_map_page(unsigned long address) --{ -- unsigned long level1_index, level2_index, level3_index; -- u64 *pgtable_level3; -- -- /* Find the current page table */ -- pgtable_level3 = __va(read_cr3()); -- -- /* Find the indexes of the physical address to identity map */ -- level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE; -- level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE; -- level3_index = address / LEVEL2_SIZE; -- -- /* Identity map the page table entry */ -- pgtable_level1[level1_index] = address | L0_ATTR; -- pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR; -- set_64bit(&pgtable_level3[level3_index], -- __pa(pgtable_level2) | L2_ATTR); -- -- /* Flush the tlb so the new mapping takes effect. -- * Global tlb entries are not flushed but that is not an issue. -- */ -- load_cr3(pgtable_level3); --} -+static u32 kexec_pgd[1024] PAGE_ALIGNED; -+#ifdef CONFIG_X86_PAE -+static u32 kexec_pmd0[1024] PAGE_ALIGNED; -+static u32 kexec_pmd1[1024] PAGE_ALIGNED; - #endif -+static u32 kexec_pte0[1024] PAGE_ALIGNED; -+static u32 kexec_pte1[1024] PAGE_ALIGNED; - - static void set_idt(void *newidt, __u16 limit) - { -@@ -128,16 +71,6 @@ static void load_segments(void) - #undef __STR - } - --typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)( -- unsigned long indirection_page, -- unsigned long reboot_code_buffer, -- unsigned long start_address, -- unsigned int has_pae) ATTRIB_NORET; -- --extern const unsigned char relocate_new_kernel[]; --extern void relocate_new_kernel_end(void); --extern const unsigned int relocate_new_kernel_size; -- - /* - * A architecture hook called to validate the - * proposed image and prepare the control pages -@@ -170,25 +103,29 @@ void machine_kexec_cleanup(struct kimage - */ - NORET_TYPE void machine_kexec(struct kimage *image) - { -- unsigned long page_list; -- unsigned long reboot_code_buffer; -- -- relocate_new_kernel_t rnk; -+ unsigned long page_list[PAGES_NR]; -+ void *control_page; - - /* Interrupts aren't acceptable while we reboot */ - local_irq_disable(); - -- /* Compute some offsets */ -- reboot_code_buffer = page_to_pfn(image->control_code_page) -- << PAGE_SHIFT; -- page_list = image->head; -- -- /* Set up an identity mapping for the reboot_code_buffer */ -- identity_map_page(reboot_code_buffer); -- -- /* copy it out */ -- memcpy((void *)reboot_code_buffer, relocate_new_kernel, -- relocate_new_kernel_size); -+ control_page = page_address(image->control_code_page); -+ memcpy(control_page, relocate_kernel, PAGE_SIZE); -+ -+ page_list[PA_CONTROL_PAGE] = __pa(control_page); -+ page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; -+ page_list[PA_PGD] = __pa(kexec_pgd); -+ page_list[VA_PGD] = (unsigned long)kexec_pgd; -+#ifdef CONFIG_X86_PAE -+ page_list[PA_PMD_0] = __pa(kexec_pmd0); -+ page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; -+ page_list[PA_PMD_1] = __pa(kexec_pmd1); -+ page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; -+#endif -+ page_list[PA_PTE_0] = __pa(kexec_pte0); -+ page_list[VA_PTE_0] = (unsigned long)kexec_pte0; -+ page_list[PA_PTE_1] = __pa(kexec_pte1); -+ page_list[VA_PTE_1] = (unsigned long)kexec_pte1; - - /* The segment registers are funny things, they have both a - * visible and an invisible part. Whenever the visible part is -@@ -207,8 +144,8 @@ NORET_TYPE void machine_kexec(struct kim - set_idt(phys_to_virt(0),0); - - /* now call it */ -- rnk = (relocate_new_kernel_t) reboot_code_buffer; -- (*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae); -+ relocate_kernel((unsigned long)image->head, (unsigned long)page_list, -+ image->start, cpu_has_pae); - } - - /* crashkernel=size@addr specifies the location to reserve for ---- a/arch/i386/kernel/relocate_kernel.S -+++ b/arch/i386/kernel/relocate_kernel.S -@@ -7,16 +7,138 @@ - */ - - #include <linux/linkage.h> -+#include <asm/page.h> -+#include <asm/kexec.h> -+ -+/* -+ * Must be relocatable PIC code callable as a C function -+ */ -+ -+#define PTR(x) (x << 2) -+#define PAGE_ALIGNED (1 << PAGE_SHIFT) -+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */ -+#define PAE_PGD_ATTR 0x01 /* _PAGE_PRESENT */ -+ -+ .text -+ .align PAGE_ALIGNED -+ .globl relocate_kernel -+relocate_kernel: -+ movl 8(%esp), %ebp /* list of pages */ -+ -+#ifdef CONFIG_X86_PAE -+ /* map the control page at its virtual address */ -+ -+ movl PTR(VA_PGD)(%ebp), %edi -+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax -+ andl $0xc0000000, %eax -+ shrl $27, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_PMD_0)(%ebp), %edx -+ orl $PAE_PGD_ATTR, %edx -+ movl %edx, (%eax) -+ -+ movl PTR(VA_PMD_0)(%ebp), %edi -+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax -+ andl $0x3fe00000, %eax -+ shrl $18, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_PTE_0)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+ -+ movl PTR(VA_PTE_0)(%ebp), %edi -+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax -+ andl $0x001ff000, %eax -+ shrl $9, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+ -+ /* identity map the control page at its physical address */ -+ -+ movl PTR(VA_PGD)(%ebp), %edi -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax -+ andl $0xc0000000, %eax -+ shrl $27, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_PMD_1)(%ebp), %edx -+ orl $PAE_PGD_ATTR, %edx -+ movl %edx, (%eax) -+ -+ movl PTR(VA_PMD_1)(%ebp), %edi -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax -+ andl $0x3fe00000, %eax -+ shrl $18, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_PTE_1)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+ -+ movl PTR(VA_PTE_1)(%ebp), %edi -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax -+ andl $0x001ff000, %eax -+ shrl $9, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+#else -+ /* map the control page at its virtual address */ -+ -+ movl PTR(VA_PGD)(%ebp), %edi -+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax -+ andl $0xffc00000, %eax -+ shrl $20, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_PTE_0)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+ -+ movl PTR(VA_PTE_0)(%ebp), %edi -+ movl PTR(VA_CONTROL_PAGE)(%ebp), %eax -+ andl $0x003ff000, %eax -+ shrl $10, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+ -+ /* identity map the control page at its physical address */ -+ -+ movl PTR(VA_PGD)(%ebp), %edi -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax -+ andl $0xffc00000, %eax -+ shrl $20, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_PTE_1)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+ -+ movl PTR(VA_PTE_1)(%ebp), %edi -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %eax -+ andl $0x003ff000, %eax -+ shrl $10, %eax -+ addl %edi, %eax -+ -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edx -+ orl $PAGE_ATTR, %edx -+ movl %edx, (%eax) -+#endif - -- /* -- * Must be relocatable PIC code callable as a C function, that once -- * it starts can not use the previous processes stack. -- */ -- .globl relocate_new_kernel - relocate_new_kernel: - /* read the arguments and say goodbye to the stack */ - movl 4(%esp), %ebx /* page_list */ -- movl 8(%esp), %ebp /* reboot_code_buffer */ -+ movl 8(%esp), %ebp /* list of pages */ - movl 12(%esp), %edx /* start address */ - movl 16(%esp), %ecx /* cpu_has_pae */ - -@@ -24,11 +146,26 @@ relocate_new_kernel: - pushl $0 - popfl - -- /* set a new stack at the bottom of our page... */ -- lea 4096(%ebp), %esp -+ /* get physical address of control page now */ -+ /* this is impossible after page table switch */ -+ movl PTR(PA_CONTROL_PAGE)(%ebp), %edi -+ -+ /* switch to new set of page tables */ -+ movl PTR(PA_PGD)(%ebp), %eax -+ movl %eax, %cr3 -+ -+ /* setup a new stack at the end of the physical control page */ -+ lea 4096(%edi), %esp - -- /* store the parameters back on the stack */ -- pushl %edx /* store the start address */ -+ /* jump to identity mapped page */ -+ movl %edi, %eax -+ addl $(identity_mapped - relocate_kernel), %eax -+ pushl %eax -+ ret -+ -+identity_mapped: -+ /* store the start address on the stack */ -+ pushl %edx - - /* Set cr0 to a known state: - * 31 0 == Paging disabled -@@ -113,8 +250,3 @@ relocate_new_kernel: - xorl %edi, %edi - xorl %ebp, %ebp - ret --relocate_new_kernel_end: -- -- .globl relocate_new_kernel_size --relocate_new_kernel_size: -- .long relocate_new_kernel_end - relocate_new_kernel ---- a/include/asm-i386/kexec.h -+++ b/include/asm-i386/kexec.h -@@ -1,6 +1,26 @@ - #ifndef _I386_KEXEC_H - #define _I386_KEXEC_H - -+#define PA_CONTROL_PAGE 0 -+#define VA_CONTROL_PAGE 1 -+#define PA_PGD 2 -+#define VA_PGD 3 -+#define PA_PTE_0 4 -+#define VA_PTE_0 5 -+#define PA_PTE_1 6 -+#define VA_PTE_1 7 -+#ifdef CONFIG_X86_PAE -+#define PA_PMD_0 8 -+#define VA_PMD_0 9 -+#define PA_PMD_1 10 -+#define VA_PMD_1 11 -+#define PAGES_NR 12 -+#else -+#define PAGES_NR 8 -+#endif -+ -+#ifndef __ASSEMBLY__ -+ - #include <asm/fixmap.h> - #include <asm/ptrace.h> - #include <asm/string.h> -@@ -72,5 +92,12 @@ static inline void crash_setup_regs(stru - newregs->eip = (unsigned long)current_text_addr(); - } - } -+asmlinkage NORET_TYPE void -+relocate_kernel(unsigned long indirection_page, -+ unsigned long control_page, -+ unsigned long start_address, -+ unsigned int has_pae) ATTRIB_NORET; -+ -+#endif /* __ASSEMBLY__ */ - - #endif /* _I386_KEXEC_H */ diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch --- a/patches/linux-2.6.16.33/git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,375 +0,0 @@ -From: Magnus Damm <magnus@xxxxxxxxxxxxx> -Date: Tue, 26 Sep 2006 08:52:38 +0000 (+0200) -Subject: [PATCH] Avoid overwriting the current pgd (V4, x86_64) -X-Git-Tag: v2.6.19-rc1 -X-Git-Url: http://www.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f - -[PATCH] Avoid overwriting the current pgd (V4, x86_64) - -kexec: Avoid overwriting the current pgd (V4, x86_64) - -This patch upgrades the x86_64-specific kexec code to avoid overwriting the -current pgd. Overwriting the current pgd is bad when CONFIG_CRASH_DUMP is used -to start a secondary kernel that dumps the memory of the previous kernel. - -The code introduces a new set of page tables. These tables are used to provide -an executable identity mapping without overwriting the current pgd. - -Signed-off-by: Magnus Damm <magnus@xxxxxxxxxxxxx> -Signed-off-by: Andi Kleen <ak@xxxxxxx> ---- - ---- a/arch/x86_64/kernel/machine_kexec.c -+++ b/arch/x86_64/kernel/machine_kexec.c -@@ -15,6 +15,15 @@ - #include <asm/mmu_context.h> - #include <asm/io.h> - -+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE))) -+static u64 kexec_pgd[512] PAGE_ALIGNED; -+static u64 kexec_pud0[512] PAGE_ALIGNED; -+static u64 kexec_pmd0[512] PAGE_ALIGNED; -+static u64 kexec_pte0[512] PAGE_ALIGNED; -+static u64 kexec_pud1[512] PAGE_ALIGNED; -+static u64 kexec_pmd1[512] PAGE_ALIGNED; -+static u64 kexec_pte1[512] PAGE_ALIGNED; -+ - static void init_level2_page(pmd_t *level2p, unsigned long addr) - { - unsigned long end_addr; -@@ -144,32 +153,19 @@ static void load_segments(void) - ); - } - --typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page, -- unsigned long control_code_buffer, -- unsigned long start_address, -- unsigned long pgtable) ATTRIB_NORET; -- --extern const unsigned char relocate_new_kernel[]; --extern const unsigned long relocate_new_kernel_size; -- - int machine_kexec_prepare(struct kimage *image) - { -- unsigned long start_pgtable, control_code_buffer; -+ unsigned long start_pgtable; - int result; - - /* Calculate the offsets */ - start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; -- control_code_buffer = start_pgtable + PAGE_SIZE; - - /* Setup the identity mapped 64bit page table */ - result = init_pgtable(image, start_pgtable); - if (result) - return result; - -- /* Place the code in the reboot code buffer */ -- memcpy(__va(control_code_buffer), relocate_new_kernel, -- relocate_new_kernel_size); -- - return 0; - } - -@@ -184,28 +180,34 @@ void machine_kexec_cleanup(struct kimage - */ - NORET_TYPE void machine_kexec(struct kimage *image) - { -- unsigned long page_list; -- unsigned long control_code_buffer; -- unsigned long start_pgtable; -- relocate_new_kernel_t rnk; -+ unsigned long page_list[PAGES_NR]; -+ void *control_page; - - /* Interrupts aren't acceptable while we reboot */ - local_irq_disable(); - -- /* Calculate the offsets */ -- page_list = image->head; -- start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT; -- control_code_buffer = start_pgtable + PAGE_SIZE; -+ control_page = page_address(image->control_code_page) + PAGE_SIZE; -+ memcpy(control_page, relocate_kernel, PAGE_SIZE); - -- /* Set the low half of the page table to my identity mapped -- * page table for kexec. Leave the high half pointing at the -- * kernel pages. Don't bother to flush the global pages -- * as that will happen when I fully switch to my identity mapped -- * page table anyway. -- */ -- memcpy(__va(read_cr3()), __va(start_pgtable), PAGE_SIZE/2); -- __flush_tlb(); -+ page_list[PA_CONTROL_PAGE] = __pa(control_page); -+ page_list[VA_CONTROL_PAGE] = (unsigned long)relocate_kernel; -+ page_list[PA_PGD] = __pa(kexec_pgd); -+ page_list[VA_PGD] = (unsigned long)kexec_pgd; -+ page_list[PA_PUD_0] = __pa(kexec_pud0); -+ page_list[VA_PUD_0] = (unsigned long)kexec_pud0; -+ page_list[PA_PMD_0] = __pa(kexec_pmd0); -+ page_list[VA_PMD_0] = (unsigned long)kexec_pmd0; -+ page_list[PA_PTE_0] = __pa(kexec_pte0); -+ page_list[VA_PTE_0] = (unsigned long)kexec_pte0; -+ page_list[PA_PUD_1] = __pa(kexec_pud1); -+ page_list[VA_PUD_1] = (unsigned long)kexec_pud1; -+ page_list[PA_PMD_1] = __pa(kexec_pmd1); -+ page_list[VA_PMD_1] = (unsigned long)kexec_pmd1; -+ page_list[PA_PTE_1] = __pa(kexec_pte1); -+ page_list[VA_PTE_1] = (unsigned long)kexec_pte1; - -+ page_list[PA_TABLE_PAGE] = -+ (unsigned long)__pa(page_address(image->control_code_page)); - - /* The segment registers are funny things, they have both a - * visible and an invisible part. Whenever the visible part is -@@ -222,9 +224,10 @@ NORET_TYPE void machine_kexec(struct kim - */ - set_gdt(phys_to_virt(0),0); - set_idt(phys_to_virt(0),0); -+ - /* now call it */ -- rnk = (relocate_new_kernel_t) control_code_buffer; -- (*rnk)(page_list, control_code_buffer, image->start, start_pgtable); -+ relocate_kernel((unsigned long)image->head, (unsigned long)page_list, -+ image->start); - } - - /* crashkernel=size@addr specifies the location to reserve for ---- a/arch/x86_64/kernel/relocate_kernel.S -+++ b/arch/x86_64/kernel/relocate_kernel.S -@@ -7,31 +7,169 @@ - */ - - #include <linux/linkage.h> -+#include <asm/page.h> -+#include <asm/kexec.h> - -- /* -- * Must be relocatable PIC code callable as a C function, that once -- * it starts can not use the previous processes stack. -- */ -- .globl relocate_new_kernel -+/* -+ * Must be relocatable PIC code callable as a C function -+ */ -+ -+#define PTR(x) (x << 3) -+#define PAGE_ALIGNED (1 << PAGE_SHIFT) -+#define PAGE_ATTR 0x63 /* _PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY */ -+ -+ .text -+ .align PAGE_ALIGNED - .code64 -+ .globl relocate_kernel -+relocate_kernel: -+ /* %rdi indirection_page -+ * %rsi page_list -+ * %rdx start address -+ */ -+ -+ /* map the control page at its virtual address */ -+ -+ movq $0x0000ff8000000000, %r10 /* mask */ -+ mov $(39 - 3), %cl /* bits to shift */ -+ movq PTR(VA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PGD)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_PUD_0)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ shrq $9, %r10 -+ sub $9, %cl -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PUD_0)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_PMD_0)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ shrq $9, %r10 -+ sub $9, %cl -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PMD_0)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_PTE_0)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ shrq $9, %r10 -+ sub $9, %cl -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PTE_0)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ /* identity map the control page at its physical address */ -+ -+ movq $0x0000ff8000000000, %r10 /* mask */ -+ mov $(39 - 3), %cl /* bits to shift */ -+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r11 /* address to map */ -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PGD)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_PUD_1)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ shrq $9, %r10 -+ sub $9, %cl -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PUD_1)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_PMD_1)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ shrq $9, %r10 -+ sub $9, %cl -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PMD_1)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_PTE_1)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ -+ shrq $9, %r10 -+ sub $9, %cl -+ -+ movq %r11, %r9 -+ andq %r10, %r9 -+ shrq %cl, %r9 -+ -+ movq PTR(VA_PTE_1)(%rsi), %r8 -+ addq %r8, %r9 -+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 -+ orq $PAGE_ATTR, %r8 -+ movq %r8, (%r9) -+ - relocate_new_kernel: -- /* %rdi page_list -- * %rsi reboot_code_buffer -+ /* %rdi indirection_page -+ * %rsi page_list - * %rdx start address -- * %rcx page_table -- * %r8 arg5 -- * %r9 arg6 - */ - - /* zero out flags, and disable interrupts */ - pushq $0 - popfq - -- /* set a new stack at the bottom of our page... */ -- lea 4096(%rsi), %rsp -+ /* get physical address of control page now */ -+ /* this is impossible after page table switch */ -+ movq PTR(PA_CONTROL_PAGE)(%rsi), %r8 -+ -+ /* get physical address of page table now too */ -+ movq PTR(PA_TABLE_PAGE)(%rsi), %rcx -+ -+ /* switch to new set of page tables */ -+ movq PTR(PA_PGD)(%rsi), %r9 -+ movq %r9, %cr3 -+ -+ /* setup a new stack at the end of the physical control page */ -+ lea 4096(%r8), %rsp -+ -+ /* jump to identity mapped page */ -+ addq $(identity_mapped - relocate_kernel), %r8 -+ pushq %r8 -+ ret - -- /* store the parameters back on the stack */ -- pushq %rdx /* store the start address */ -+identity_mapped: -+ /* store the start address on the stack */ -+ pushq %rdx - - /* Set cr0 to a known state: - * 31 1 == Paging enabled -@@ -136,8 +274,3 @@ relocate_new_kernel: - xorq %r15, %r15 - - ret --relocate_new_kernel_end: -- -- .globl relocate_new_kernel_size --relocate_new_kernel_size: -- .quad relocate_new_kernel_end - relocate_new_kernel ---- a/include/asm-x86_64/kexec.h -+++ b/include/asm-x86_64/kexec.h -@@ -1,6 +1,27 @@ - #ifndef _X86_64_KEXEC_H - #define _X86_64_KEXEC_H - -+#define PA_CONTROL_PAGE 0 -+#define VA_CONTROL_PAGE 1 -+#define PA_PGD 2 -+#define VA_PGD 3 -+#define PA_PUD_0 4 -+#define VA_PUD_0 5 -+#define PA_PMD_0 6 -+#define VA_PMD_0 7 -+#define PA_PTE_0 8 -+#define VA_PTE_0 9 -+#define PA_PUD_1 10 -+#define VA_PUD_1 11 -+#define PA_PMD_1 12 -+#define VA_PMD_1 13 -+#define PA_PTE_1 14 -+#define VA_PTE_1 15 -+#define PA_TABLE_PAGE 16 -+#define PAGES_NR 17 -+ -+#ifndef __ASSEMBLY__ -+ - #include <linux/string.h> - - #include <asm/page.h> -@@ -64,4 +85,12 @@ static inline void crash_setup_regs(stru - newregs->rip = (unsigned long)current_text_addr(); - } - } -+ -+NORET_TYPE void -+relocate_kernel(unsigned long indirection_page, -+ unsigned long page_list, -+ unsigned long start_address) ATTRIB_NORET; -+ -+#endif /* __ASSEMBLY__ */ -+ - #endif /* _X86_64_KEXEC_H */ diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch --- a/patches/linux-2.6.16.33/git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -commit dbaab49f92ff6ae6255762a948375e4036cbdbd2 -Author: Vivek Goyal <vgoyal@xxxxxxxxxx> -Date: Sat Oct 21 18:37:03 2006 +0200 - - [PATCH] x86-64: Overlapping program headers in physical addr space fix - - o A recent change to vmlinux.ld.S file broke kexec as now resulting vmlinux - program headers are overlapping in physical address space. - - o Now all the vsyscall related sections are placed after data and after - that mostly init data sections are placed. To avoid physical overlap - among phdrs, there are three possible solutions. - - Place vsyscall sections also in data phdrs instead of user - - move vsyscal sections after init data in bss. - - create another phdrs say data.init and move all the sections - after vsyscall into this new phdr. - - o This patch implements the third solution. - - Signed-off-by: Vivek Goyal <vgoyal@xxxxxxxxxx> - Signed-off-by: Andi Kleen <ak@xxxxxxx> - Cc: Magnus Damm <magnus@xxxxxxxxxxxxx> - Cc: Andi Kleen <ak@xxxxxxx> - Cc: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> - Signed-off-by: Andrew Morton <akpm@xxxxxxxx> - -diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S -index b9df2ab..1283614 100644 ---- a/arch/x86_64/kernel/vmlinux.lds.S -+++ b/arch/x86_64/kernel/vmlinux.lds.S -@@ -17,6 +17,7 @@ PHDRS { - text PT_LOAD FLAGS(5); /* R_E */ - data PT_LOAD FLAGS(7); /* RWE */ - user PT_LOAD FLAGS(7); /* RWE */ -+ data.init PT_LOAD FLAGS(7); /* RWE */ - note PT_NOTE FLAGS(4); /* R__ */ - } - SECTIONS -@@ -131,7 +132,7 @@ SECTIONS - . = ALIGN(8192); /* init_task */ - .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { - *(.data.init_task) -- } :data -+ }:data.init - - . = ALIGN(4096); - .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/i386-mach-io-check-nmi.patch --- a/patches/linux-2.6.16.33/i386-mach-io-check-nmi.patch Tue Jan 23 19:06:31 2007 -0800 +++ /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); -+ 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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/ipv6-no-autoconf.patch --- a/patches/linux-2.6.16.33/ipv6-no-autoconf.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/kasprintf.patch --- a/patches/linux-2.6.16.33/kasprintf.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch --- a/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-i386.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -kexec: Move asm segment handling code to the assembly file (i386) - -This patch moves the idt, gdt, and segment handling code from machine_kexec.c -to relocate_kernel.S. The main reason behind this move is to avoid code -duplication in the Xen hypervisor. With this patch all code required to kexec -is put on the control page. - -On top of that this patch also counts as a cleanup - I think it is much -nicer to write assembly directly in assembly files than wrap inline assembly -in C functions for no apparent reason. - -Signed-off-by: Magnus Damm <magnus@xxxxxxxxxxxxx> ---- - - Applies to 2.6.19-rc1. - - machine_kexec.c | 59 ----------------------------------------------------- - relocate_kernel.S | 58 +++++++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 53 insertions(+), 64 deletions(-) - ---- 0002/arch/i386/kernel/machine_kexec.c -+++ work/arch/i386/kernel/machine_kexec.c 2006-10-05 15:49:08.000000000 +0900 -@@ -29,48 +29,6 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED - static u32 kexec_pte0[1024] PAGE_ALIGNED; - static u32 kexec_pte1[1024] PAGE_ALIGNED; - --static void set_idt(void *newidt, __u16 limit) --{ -- struct Xgt_desc_struct curidt; -- -- /* ia32 supports unaliged loads & stores */ -- curidt.size = limit; -- curidt.address = (unsigned long)newidt; -- -- load_idt(&curidt); --}; -- -- --static void set_gdt(void *newgdt, __u16 limit) --{ -- struct Xgt_desc_struct curgdt; -- -- /* ia32 supports unaligned loads & stores */ -- curgdt.size = limit; -- curgdt.address = (unsigned long)newgdt; -- -- load_gdt(&curgdt); --}; -- --static void load_segments(void) --{ --#define __STR(X) #X --#define STR(X) __STR(X) -- -- __asm__ __volatile__ ( -- "\tljmp $"STR(__KERNEL_CS)",$1f\n" -- "\t1:\n" -- "\tmovl $"STR(__KERNEL_DS)",%%eax\n" -- "\tmovl %%eax,%%ds\n" -- "\tmovl %%eax,%%es\n" -- "\tmovl %%eax,%%fs\n" -- "\tmovl %%eax,%%gs\n" -- "\tmovl %%eax,%%ss\n" -- ::: "eax", "memory"); --#undef STR --#undef __STR --} -- - /* - * A architecture hook called to validate the - * proposed image and prepare the control pages -@@ -127,23 +85,6 @@ NORET_TYPE void machine_kexec(struct kim - page_list[PA_PTE_1] = __pa(kexec_pte1); - page_list[VA_PTE_1] = (unsigned long)kexec_pte1; - -- /* The segment registers are funny things, they have both a -- * visible and an invisible part. Whenever the visible part is -- * set to a specific selector, the invisible part is loaded -- * with from a table in memory. At no other time is the -- * descriptor table in memory accessed. -- * -- * I take advantage of this here by force loading the -- * segments, before I zap the gdt with an invalid value. -- */ -- load_segments(); -- /* The gdt & idt are now invalid. -- * If you want to load them you must set up your own idt & gdt. -- */ -- set_gdt(phys_to_virt(0),0); -- set_idt(phys_to_virt(0),0); -- -- /* now call it */ - relocate_kernel((unsigned long)image->head, (unsigned long)page_list, - image->start, cpu_has_pae); - } ---- 0002/arch/i386/kernel/relocate_kernel.S -+++ work/arch/i386/kernel/relocate_kernel.S 2006-10-05 16:03:21.000000000 +0900 -@@ -154,14 +154,45 @@ relocate_new_kernel: - movl PTR(PA_PGD)(%ebp), %eax - movl %eax, %cr3 - -+ /* setup idt */ -+ movl %edi, %eax -+ addl $(idt_48 - relocate_kernel), %eax -+ lidtl (%eax) -+ -+ /* setup gdt */ -+ movl %edi, %eax -+ addl $(gdt - relocate_kernel), %eax -+ movl %edi, %esi -+ addl $((gdt_48 - relocate_kernel) + 2), %esi -+ movl %eax, (%esi) -+ -+ movl %edi, %eax -+ addl $(gdt_48 - relocate_kernel), %eax -+ lgdtl (%eax) -+ -+ /* setup data segment registers */ -+ mov $(gdt_ds - gdt), %eax -+ mov %eax, %ds -+ mov %eax, %es -+ mov %eax, %fs -+ mov %eax, %gs -+ mov %eax, %ss -+ - /* setup a new stack at the end of the physical control page */ - lea 4096(%edi), %esp - -- /* jump to identity mapped page */ -- movl %edi, %eax -- addl $(identity_mapped - relocate_kernel), %eax -- pushl %eax -- ret -+ /* load new code segment and jump to identity mapped page */ -+ movl %edi, %esi -+ xorl %eax, %eax -+ pushl %eax -+ pushl %esi -+ pushl %eax -+ movl $(gdt_cs - gdt), %eax -+ pushl %eax -+ movl %edi, %eax -+ addl $(identity_mapped - relocate_kernel),%eax -+ pushl %eax -+ iretl - - identity_mapped: - /* store the start address on the stack */ -@@ -250,3 +281,20 @@ identity_mapped: - xorl %edi, %edi - xorl %ebp, %ebp - ret -+ -+ .align 16 -+gdt: -+ .quad 0x0000000000000000 /* NULL descriptor */ -+gdt_cs: -+ .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ -+gdt_ds: -+ .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ -+gdt_end: -+ -+gdt_48: -+ .word gdt_end - gdt - 1 /* limit */ -+ .long 0 /* base - filled in by code above */ -+ -+idt_48: -+ .word 0 /* limit */ -+ .long 0 /* base */ diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch --- a/patches/linux-2.6.16.33/linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -kexec: Move asm segment handling code to the assembly file (x86_64) - -This patch moves the idt, gdt, and segment handling code from machine_kexec.c -to relocate_kernel.S. The main reason behind this move is to avoid code -duplication in the Xen hypervisor. With this patch all code required to kexec -is put on the control page. - -On top of that this patch also counts as a cleanup - I think it is much -nicer to write assembly directly in assembly files than wrap inline assembly -in C functions for no apparent reason. - -Signed-off-by: Magnus Damm <magnus@xxxxxxxxxxxxx> ---- - - Applies to 2.6.19-rc1. - - machine_kexec.c | 58 ----------------------------------------------------- - relocate_kernel.S | 50 +++++++++++++++++++++++++++++++++++++++++---- - 2 files changed, 45 insertions(+), 63 deletions(-) - ---- 0002/arch/x86_64/kernel/machine_kexec.c -+++ work/arch/x86_64/kernel/machine_kexec.c 2006-10-05 16:15:49.000000000 +0900 -@@ -112,47 +112,6 @@ static int init_pgtable(struct kimage *i - return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT); - } - --static void set_idt(void *newidt, u16 limit) --{ -- struct desc_ptr curidt; -- -- /* x86-64 supports unaliged loads & stores */ -- curidt.size = limit; -- curidt.address = (unsigned long)newidt; -- -- __asm__ __volatile__ ( -- "lidtq %0\n" -- : : "m" (curidt) -- ); --}; -- -- --static void set_gdt(void *newgdt, u16 limit) --{ -- struct desc_ptr curgdt; -- -- /* x86-64 supports unaligned loads & stores */ -- curgdt.size = limit; -- curgdt.address = (unsigned long)newgdt; -- -- __asm__ __volatile__ ( -- "lgdtq %0\n" -- : : "m" (curgdt) -- ); --}; -- --static void load_segments(void) --{ -- __asm__ __volatile__ ( -- "\tmovl %0,%%ds\n" -- "\tmovl %0,%%es\n" -- "\tmovl %0,%%ss\n" -- "\tmovl %0,%%fs\n" -- "\tmovl %0,%%gs\n" -- : : "a" (__KERNEL_DS) : "memory" -- ); --} -- - int machine_kexec_prepare(struct kimage *image) - { - unsigned long start_pgtable; -@@ -209,23 +168,6 @@ NORET_TYPE void machine_kexec(struct kim - page_list[PA_TABLE_PAGE] = - (unsigned long)__pa(page_address(image->control_code_page)); - -- /* The segment registers are funny things, they have both a -- * visible and an invisible part. Whenever the visible part is -- * set to a specific selector, the invisible part is loaded -- * with from a table in memory. At no other time is the -- * descriptor table in memory accessed. -- * -- * I take advantage of this here by force loading the -- * segments, before I zap the gdt with an invalid value. -- */ -- load_segments(); -- /* The gdt & idt are now invalid. -- * If you want to load them you must set up your own idt & gdt. -- */ -- set_gdt(phys_to_virt(0),0); -- set_idt(phys_to_virt(0),0); -- -- /* now call it */ - relocate_kernel((unsigned long)image->head, (unsigned long)page_list, - image->start); - } ---- 0002/arch/x86_64/kernel/relocate_kernel.S -+++ work/arch/x86_64/kernel/relocate_kernel.S 2006-10-05 16:18:07.000000000 +0900 -@@ -159,13 +159,39 @@ relocate_new_kernel: - movq PTR(PA_PGD)(%rsi), %r9 - movq %r9, %cr3 - -+ /* setup idt */ -+ movq %r8, %rax -+ addq $(idt_80 - relocate_kernel), %rax -+ lidtq (%rax) -+ -+ /* setup gdt */ -+ movq %r8, %rax -+ addq $(gdt - relocate_kernel), %rax -+ movq %r8, %r9 -+ addq $((gdt_80 - relocate_kernel) + 2), %r9 -+ movq %rax, (%r9) -+ -+ movq %r8, %rax -+ addq $(gdt_80 - relocate_kernel), %rax -+ lgdtq (%rax) -+ -+ /* setup data segment registers */ -+ xorl %eax, %eax -+ movl %eax, %ds -+ movl %eax, %es -+ movl %eax, %fs -+ movl %eax, %gs -+ movl %eax, %ss -+ - /* setup a new stack at the end of the physical control page */ - lea 4096(%r8), %rsp - -- /* jump to identity mapped page */ -- addq $(identity_mapped - relocate_kernel), %r8 -- pushq %r8 -- ret -+ /* load new code segment and jump to identity mapped page */ -+ movq %r8, %rax -+ addq $(identity_mapped - relocate_kernel), %rax -+ pushq $(gdt_cs - gdt) -+ pushq %rax -+ lretq - - identity_mapped: - /* store the start address on the stack */ -@@ -272,5 +298,19 @@ identity_mapped: - xorq %r13, %r13 - xorq %r14, %r14 - xorq %r15, %r15 -- - ret -+ -+ .align 16 -+gdt: -+ .quad 0x0000000000000000 /* NULL descriptor */ -+gdt_cs: -+ .quad 0x00af9a000000ffff -+gdt_end: -+ -+gdt_80: -+ .word gdt_end - gdt - 1 /* limit */ -+ .quad 0 /* base - filled in by code above */ -+ -+idt_80: -+ .word 0 /* limit */ -+ .quad 0 /* base */ diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-csum.patch --- a/patches/linux-2.6.16.33/net-csum.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-0-base.patch --- a/patches/linux-2.6.16.33/net-gso-0-base.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2898 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-1-check-dodgy.patch --- a/patches/linux-2.6.16.33/net-gso-1-check-dodgy.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-2-checksum-fix.patch --- a/patches/linux-2.6.16.33/net-gso-2-checksum-fix.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,451 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-3-fix-errorcheck.patch --- a/patches/linux-2.6.16.33/net-gso-3-fix-errorcheck.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-4-kill-warnon.patch --- a/patches/linux-2.6.16.33/net-gso-4-kill-warnon.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-5-rcv-mss.patch --- a/patches/linux-2.6.16.33/net-gso-5-rcv-mss.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/net-gso-6-linear-segmentation.patch --- a/patches/linux-2.6.16.33/net-gso-6-linear-segmentation.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ -diff -Naru a/net/core/skbuff.c b/net/core/skbuff.c ---- a/net/core/skbuff.c 2006-12-14 09:32:04 -08:00 -+++ b/net/core/skbuff.c 2006-12-14 09:32:04 -08:00 -@@ -1946,7 +1946,7 @@ - do { - struct sk_buff *nskb; - skb_frag_t *frag; -- int hsize, nsize; -+ int hsize; - int k; - int size; - -@@ -1957,11 +1957,10 @@ - hsize = skb_headlen(skb) - offset; - if (hsize < 0) - hsize = 0; -- nsize = hsize + doffset; -- if (nsize > len + doffset || !sg) -- nsize = len + doffset; -+ if (hsize > len || !sg) -+ hsize = len; - -- nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); -+ nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC); - if (unlikely(!nskb)) - goto err; diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch --- a/patches/linux-2.6.16.33/pci-mmconfig-fix-from-2.6.17.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,292 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/pmd-shared.patch --- a/patches/linux-2.6.16.33/pmd-shared.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/rcu_needs_cpu.patch --- a/patches/linux-2.6.16.33/rcu_needs_cpu.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch --- a/patches/linux-2.6.16.33/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/series --- a/patches/linux-2.6.16.33/series Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +0,0 @@ -git-2efe55a9cec8418f0e0cde3dc3787a42fddc4411.patch -git-2a8a3d5b65e86ec1dfef7d268c64a909eab94af7.patch -git-3566561bfadffcb5dbc85d576be80c0dbf2cccc9.patch -linux-2.6.19-rc1-kexec-move_segment_code-i386.patch -git-4bfaaef01a1badb9e8ffb0c0a37cd2379008d21f.patch -linux-2.6.19-rc1-kexec-move_segment_code-x86_64.patch -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 -net-gso-6-linear-segmentation.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 -git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch -x86-elfnote-as-preprocessor-macro.patch -vsnprintf.patch -kasprintf.patch diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/smp-alts.patch --- a/patches/linux-2.6.16.33/smp-alts.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,591 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/tpm_plugin_2.6.17.patch --- a/patches/linux-2.6.16.33/tpm_plugin_2.6.17.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1545 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/vsnprintf.patch --- a/patches/linux-2.6.16.33/vsnprintf.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,211 +0,0 @@ -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[-1] = '\0'; -+ } -+ /* the trailing null byte doesn't count towards the total */ - return str-buf; - } - diff -r 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/x86-elfnote-as-preprocessor-macro.patch --- a/patches/linux-2.6.16.33/x86-elfnote-as-preprocessor-macro.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/x86-increase-interrupt-vector-range.patch --- a/patches/linux-2.6.16.33/x86-increase-interrupt-vector-range.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch --- a/patches/linux-2.6.16.33/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch --- a/patches/linux-2.6.16.33/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/xen-hotplug.patch --- a/patches/linux-2.6.16.33/xen-hotplug.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.33/xenoprof-generic.patch --- a/patches/linux-2.6.16.33/xenoprof-generic.patch Tue Jan 23 19:06:31 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,662 +0,0 @@ -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 18f30d7ef2b8 -r 4be85bb2f54d patches/linux-2.6.16.38/blktap-aio-16_03_06.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/linux-2.6.16.38/blktap-aio-16_03_06.patch Mon Jan 29 10:00:33 2007 +0000 @@ -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 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |